aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Moore <ken@ixsystems.com>2018-03-07 15:10:49 -0500
committerKen Moore <ken@ixsystems.com>2018-03-07 15:10:49 -0500
commit78fa2f5368ce789f8f1fe63d3de5f43bbb4a9308 (patch)
tree7e93b470d3a489b7e22abd994c07cb7e8cdf4c18
parentFix a missing library dependency for libXCursor (diff)
downloadlumina-78fa2f5368ce789f8f1fe63d3de5f43bbb4a9308.tar.gz
lumina-78fa2f5368ce789f8f1fe63d3de5f43bbb4a9308.tar.bz2
lumina-78fa2f5368ce789f8f1fe63d3de5f43bbb4a9308.zip
Split the Lumina 2 backend:
Based on a qmake flag, have it use QtWidgets or QML for the front-end renderer. This will allow us to import/use all the Lumina 1.x interface elements (in Widget form) for now, but switch over to QML interface later without losing all the improvements to the underling events/communication systems.
-rw-r--r--src-qt5/core/libLumina/LIconCache.h5
-rw-r--r--src-qt5/core/libLumina/LUtils.cpp6
-rw-r--r--src-qt5/core/lumina-desktop-unified/global-includes.h1
-rw-r--r--src-qt5/core/lumina-desktop-unified/lumina-desktop.pro4
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp10
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow-QML.cpp (renamed from src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp)9
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow-Widgets.cpp53
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.h8
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri35
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp5
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h3
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/ContextMenu.cpp (renamed from src-qt5/core/lumina-desktop-unified/src-desktop/OldContextMenu.cpp)19
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/ContextMenu.h (renamed from src-qt5/core/lumina-desktop-unified/src-desktop/OldContextMenu.h)2
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/RootDesktop.cpp120
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/RootDesktop.h44
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/src-widgets.pri8
16 files changed, 299 insertions, 33 deletions
diff --git a/src-qt5/core/libLumina/LIconCache.h b/src-qt5/core/libLumina/LIconCache.h
index 691d328c..6fc693d6 100644
--- a/src-qt5/core/libLumina/LIconCache.h
+++ b/src-qt5/core/libLumina/LIconCache.h
@@ -7,6 +7,9 @@
// This is a simple class for loading/serving icon files
// from the icon theme or local filesystem
//===========================================
+#ifndef _LUMINA_LIBRARY_ICON_CACHE_H
+#define _LUMINA_LIBRARY_ICON_CACHE_H
+
#include <QHash>
#include <QIcon>
#include <QPixmap>
@@ -79,3 +82,5 @@ signals:
void InternalIconLoaded(QString, QDateTime, QByteArray*); //INTERNAL SIGNAL - DO NOT USE in other classes/objects
void IconAvailable(QString); //way for classes to listen/reload icons as they change
};
+
+#endif
diff --git a/src-qt5/core/libLumina/LUtils.cpp b/src-qt5/core/libLumina/LUtils.cpp
index 3d3c878a..6ca8b679 100644
--- a/src-qt5/core/libLumina/LUtils.cpp
+++ b/src-qt5/core/libLumina/LUtils.cpp
@@ -273,13 +273,15 @@ QStringList LUtils::videoExtensions() {
QStringList LUtils::imageExtensions(bool wildcards){
//Note that all the image extensions are lowercase!!
static QStringList imgExtensions;
+ static QStringList imgExtensionsWC;
if(imgExtensions.isEmpty()){
QList<QByteArray> fmt = QImageReader::supportedImageFormats();
for(int i=0; i<fmt.length(); i++){
- if(wildcards){ imgExtensions << "*."+QString::fromLocal8Bit(fmt[i]); }
- else{ imgExtensions << QString::fromLocal8Bit(fmt[i]); }
+ imgExtensionsWC << "*."+QString::fromLocal8Bit(fmt[i]);
+ imgExtensions << QString::fromLocal8Bit(fmt[i]);
}
}
+ if(wildcards){ return imgExtensionsWC; }
return imgExtensions;
}
diff --git a/src-qt5/core/lumina-desktop-unified/global-includes.h b/src-qt5/core/lumina-desktop-unified/global-includes.h
index 6a82775b..69f1a3b0 100644
--- a/src-qt5/core/lumina-desktop-unified/global-includes.h
+++ b/src-qt5/core/lumina-desktop-unified/global-includes.h
@@ -58,6 +58,7 @@
#include <QQmlContext>
#include <QQmlEngine>
#include <QQuickImageProvider>
+#include <QtConcurrent>
// libLumina includes
#include <LuminaX11.h>
diff --git a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro
index a929f844..e601bb09 100644
--- a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro
+++ b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro
@@ -22,6 +22,7 @@ include(../libLumina/LuminaSingleApplication.pri)
include(../libLumina/DesktopSettings.pri)
include(../libLumina/ExternalProcess.pri)
include(../libLumina/XDGMime.pri)
+include(../libLumina/LIconCache.pri)
include(../../src-cpp/plugins-base.pri)
include(../../src-cpp/framework-OSInterface.pri)
@@ -40,7 +41,8 @@ SOURCES += main.cpp \
HEADERS += global-includes.h \
global-objects.h \
LSession.h \
- BootSplash.h
+ BootSplash.h \
+ JsonMenu.h
FORMS += BootSplash.ui
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp
index 73cd6645..b94a241d 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp
@@ -41,16 +41,20 @@ void DesktopManager::updateWallpaper(QString screen_id, int wkspace){
QStringList wpaperList = DesktopSettings::instance()->value(DesktopSettings::Desktop, "wallpapers/"+screen_id+"_wk_"+QString::number(wkspace), QStringList()).toStringList();
//Next look for a list that matches this exact workspace
if(wpaperList.isEmpty()){ wpaperList= DesktopSettings::instance()->value(DesktopSettings::Desktop, "wallpapers/default_wk_"+QString::number(wkspace), QStringList()).toStringList(); }
+ wpaperList.removeAll("");
//Next look for a list that matches this exact screen
if(wpaperList.isEmpty()){ wpaperList= DesktopSettings::instance()->value(DesktopSettings::Desktop, "wallpapers/"+screen_id, QStringList()).toStringList(); }
+ wpaperList.removeAll("");
//Now look for a list that matches any screen/workspace
if(wpaperList.isEmpty()){ wpaperList= DesktopSettings::instance()->value(DesktopSettings::Desktop, "wallpapers/default", QStringList()).toStringList(); }
+ wpaperList.removeAll("");
//Now use the failover wallpaper directory
if(wpaperList.isEmpty()){
QString def = LOS::LuminaShare().section("/",0,-3)+"/wallpapers/lumina-nature"; //Note: LuminaShare() ends with an extra "/"
//qDebug() << "Default Wallpaper:" << def;
if(QFile::exists(def)){ wpaperList << def; }
}
+ //qDebug() << "Got wallpaper list:" << screen_id << wkspace << wpaperList;
//Wallpaper selection/randomization
if(wpaperList.count()==1 && wpaperList.first()==current){ return; } //nothing to do - just the same image
QString wpaper;
@@ -60,6 +64,7 @@ void DesktopManager::updateWallpaper(QString screen_id, int wkspace){
if(!wpaper.isEmpty()){
//Got a directory - update the list of files and re-randomize the selection
QStringList imgs = LUtils::imageExtensions(true);
+ //qDebug() << " - Got Dir: " << imgs;
QDir tdir(wpaper);
prefix=wpaper+"/";
bgL = tdir.entryList(imgs, QDir::Files | QDir::NoDotAndDotDot, QDir::Name);
@@ -91,7 +96,7 @@ void DesktopManager::updatePlugins(QString plugin_id){
// === PUBLIC SLOTS ===
void DesktopManager::workspaceChanged(int wknum){
- qDebug() << "Got Workspace Changed:" << wknum;
+ //qDebug() << "Got Workspace Changed:" << wknum;
syncWindowList();
}
@@ -117,6 +122,9 @@ void DesktopManager::settingsChanged(DesktopSettings::File type){
void DesktopManager::NewWindowAvailable(NativeWindowObject* win){
//connect(win, SIGNAL(WindowClosed(WId)), this, SLOT(syncWindowList()) );
+#ifdef USE_WIDGETS
+ qDebug() << "Got New Widget Window:" << win->name();
+#endif
syncWindowList();
}
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow-QML.cpp
index 9664e506..8619544b 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow-QML.cpp
@@ -1,6 +1,6 @@
//===========================================
// Lumina-desktop source code
-// Copyright (c) 2017, Ken Moore
+// Copyright (c) 2017-2018, Ken Moore
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
@@ -8,6 +8,8 @@
#include "QMLImageProvider.h"
#include <QQmlImageProviderBase>
+QQuickView *root_view;
+
RootWindow::RootWindow() : QObject(){
root_win = QWindow::fromWinId( QX11Info::appRootWindow() );
root_view = new QQuickView(); //make it a child of the root window
@@ -35,6 +37,11 @@ void RootWindow::start(){
root_view->show();
}
+WId RootWindow::viewID(){
+ if(root_view->parent()!=0){ return root_view->parent()->winId(); }
+ return root_view->winId();
+}
+
void RootWindow::syncRootSize(){
//qDebug() << "Sync Root Size:" << root_win->width() << root_win->height() << root_view->geometry();
QList<QScreen*> screens = QApplication::screens();
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow-Widgets.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow-Widgets.cpp
new file mode 100644
index 00000000..6a4c4cb0
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow-Widgets.cpp
@@ -0,0 +1,53 @@
+//===========================================
+// Lumina-desktop source code
+// Copyright (c) 2017-2018, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "RootWindow.h"
+
+//include the Widgets-based classes we need
+#include "RootDesktop.h"
+
+RootDesktop *root_view;
+
+RootWindow::RootWindow() : QObject(){
+ root_win = QWindow::fromWinId( QX11Info::appRootWindow() );
+ root_view = new RootDesktop(root_win); //make it a child of the root window
+ root_obj = RootDesktopObject::instance();
+ syncRootSize();
+ connect(root_win, SIGNAL(widthChanged(int)), this, SLOT(syncRootSize()) );
+ connect(root_win, SIGNAL(heightChanged(int)),this, SLOT(syncRootSize()) );
+}
+
+RootWindow::~RootWindow(){
+ root_view->deleteLater();
+ root_obj->deleteLater();
+}
+
+void RootWindow::start(){
+ root_win->show();
+ //if(root_view->parent()!=0){ root_view->parent()->show(); }
+ root_view->show();
+ root_view->start();
+ QTimer::singleShot(1000, this, SLOT(syncRootSize()) ); //just in case something changed during init routines
+}
+
+WId RootWindow::viewID(){
+ //if(root_view->parent()!=0){ return root_view->parent()->winId(); }
+ return root_view->winId();
+}
+
+void RootWindow::syncRootSize(){
+ //qDebug() << "Sync Root Size:" << root_win->width() << root_win->height() << root_view->geometry();
+ QList<QScreen*> screens = QApplication::screens();
+ QRect unif;
+ for(int i=0; i<screens.length(); i++){ unif = unif.united(screens[i]->geometry()); }
+ if(unif.width() != root_view->width() || unif.height() != root_view->height()){
+ //if(root_view->parent()!=0){ root_view->parent()->setGeometry(0,0,unif.width(), unif.height()); }
+ root_view->setGeometry(0, 0, unif.width(), unif.height() );
+ emit RootResized(root_view->geometry());
+ }
+ root_obj->updateScreens();
+ //qDebug() << " - after:" << root_view->geometry();
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.h b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.h
index 41c75a46..3c7414f2 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.h
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.h
@@ -1,6 +1,6 @@
//===========================================
// Lumina-desktop source code
-// Copyright (c) 2017, Ken Moore
+// Copyright (c) 2017-2018, Ken Moore
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
@@ -13,7 +13,6 @@ class RootWindow : public QObject{
Q_OBJECT
private:
QWindow *root_win;
- QQuickView *root_view;
RootDesktopObject *root_obj;
public:
@@ -22,10 +21,7 @@ public:
void start();
- WId viewID(){
- if(root_view->parent()!=0){ return root_view->parent()->winId(); }
- return root_view->winId();
- }
+ WId viewID();
public slots:
void syncRootSize();
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri b/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri
index ee5ada62..89542e23 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri
@@ -1,15 +1,32 @@
-QT *= gui widgets qml quick
+QT *= gui widgets
-SOURCES *= $${PWD}/RootWindow.cpp \
- $${PWD}/Desktopmanager.cpp \
+#update the includepath so we can just #include as needed without paths
+INCLUDEPATH *= $${PWD}
+
+SOURCES *= $${PWD}/Desktopmanager.cpp \
$${PWD}/QMLImageProvider.cpp
HEADERS *= $${PWD}/RootWindow.h \
- $${PWD}/DesktopManager.h \
- $${PWD}/QMLImageProvider.h
-
-#update the includepath so we can just #include as needed without paths
-INCLUDEPATH *= $${PWD}
+ $${PWD}/DesktopManager.h
+#include the base objects
include($${PWD}/src-cpp/src-cpp.pri)
-include($${PWD}/src-qml/src-qml.pri)
+
+#Now do the QML/Widgets interface switch
+isEmpty(USE_QML){
+ #Widgets-based interface
+ DEFINES += USE_WIDGETS="true"
+
+ SOURCES *= $${PWD}/RootWindow-Widgets.cpp
+
+ include($${PWD}/src-widgets/src-widgets.pri)
+
+}else{
+ #QML-based interface
+ QT *= qml quick
+ DEFINES += USE_QML="true"
+ SOURCES *= $${PWD}/RootWindow-QML.cpp
+ HEADERS *= $${PWD}/QMLImageProvider.h
+
+ include($${PWD}/src-qml/src-qml.pri)
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp
index 5891028c..d9a81f54 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp
@@ -237,6 +237,11 @@ void RootDesktopObject::launchApp(QString appOrPath){
emit launchApplication(appOrPath);
}
+//C++ Access Functions (simplifications for the QML ones)
+QList<NativeWindowObject*> RootDesktopObject::windowObjects(){
+ return window_objects;
+}
+
// === PUBLIC SLOTS ===
void RootDesktopObject::updateScreens(){
QList<QScreen*> scrns = QApplication::screens();
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h
index a6a4a236..3c525848 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h
@@ -55,6 +55,9 @@ public:
Q_INVOKABLE void mousePositionChanged(bool lowerall = false);
Q_INVOKABLE void launchApp(QString appOrPath);
+ //C++ Access Functions (simplifications for the QML ones)
+ QList<NativeWindowObject*> windowObjects();
+
private:
QList<ScreenObject*> s_objects;
QList<PanelObject*> panel_objects;
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/OldContextMenu.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/ContextMenu.cpp
index 47f0e3d7..139eee89 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/OldContextMenu.cpp
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/ContextMenu.cpp
@@ -7,6 +7,7 @@
#include "ContextMenu.h"
#include <global-objects.h>
#include <JsonMenu.h>
+#include <LIconCache.h>
void DesktopContextMenu::SettingsChanged(DesktopSettings::File file){
if(file == DesktopSettings::ContextMenu){ UpdateMenu(false); }
@@ -78,11 +79,11 @@ void DesktopContextMenu::UpdateMenu(bool fast){
}
// === PRIVATE ===
-void DesktopContextMenu::AddWindowToMenu(NativeWindow *win){
- QString label = win->property(NativeWindow::ShortTitle).toString();
- if(label.isEmpty()){ label = win->property(NativeWindow::Title).toString(); }
- if(label.isEmpty()){ label = win->property(NativeWindow::Name).toString(); }
- QAction *tmp = winMenu->addAction( win->property(NativeWindow::Icon).value<QIcon>(), label, win, SLOT(toggleVisibility()) );
+void DesktopContextMenu::AddWindowToMenu(NativeWindowObject *win){
+ QString label = win->property(NativeWindowObject::ShortTitle).toString();
+ if(label.isEmpty()){ label = win->property(NativeWindowObject::Title).toString(); }
+ if(label.isEmpty()){ label = win->property(NativeWindowObject::Name).toString(); }
+ QAction *tmp = winMenu->addAction( win->property(NativeWindowObject::Icon).value<QIcon>(), label, win, SLOT(toggleVisibility()) );
//Need to change the visual somehow to indicate whether it is visible or not
//bool visible = win->property(NativeWindow::Visible).toBool();
// TODO
@@ -176,14 +177,8 @@ void DesktopContextMenu::updateWinMenu(){
LIconCache::instance()->loadIcon( winMenu, "preferences-system-windows");
}
winMenu->clear();
- QList<NativeWindow*> wins = Lumina::NWS->currentWindows();
- unsigned int wkspace = Lumina::NWS->currentWorkspace();
+ QList<NativeWindowObject*> wins = RootDesktopObject::instance()->windowObjects();
for(int i=0; i<wins.length(); i++){
- //First check if this window is in the current workspace (or is "sticky")
- if(wins.at(i)->property(NativeWindow::Workspace).toUInt() != wkspace
- && wins.at(i)->property(NativeWindow::States).value< QList<NativeWindow::State> >().contains(NativeWindow::S_STICKY) ){
- continue;
- }
AddWindowToMenu(wins.at(i));
}
}
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/OldContextMenu.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/ContextMenu.h
index 78756e8c..b20087ef 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/OldContextMenu.h
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/ContextMenu.h
@@ -21,7 +21,7 @@ private:
QMenu *appMenu, *winMenu;
bool usewinmenu;
- void AddWindowToMenu(NativeWindow*);
+ void AddWindowToMenu(NativeWindowObject*);
public:
DesktopContextMenu(QWidget *parent = 0);
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/RootDesktop.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/RootDesktop.cpp
new file mode 100644
index 00000000..9e22a143
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/RootDesktop.cpp
@@ -0,0 +1,120 @@
+//===========================================
+// Lumina-desktop source code
+// Copyright (c) 2018, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include <global-objects.h>
+#include "RootDesktop.h"
+
+// === PUBLIC ===
+RootDesktop::RootDesktop(QWindow *) : QWidget(0, Qt::Widget | Qt::FramelessWindowHint | Qt::WindowStaysOnBottomHint){
+
+}
+
+RootDesktop::~RootDesktop(){
+
+}
+
+void RootDesktop::start(){
+ //qDebug() << "Starting RootDesktop" << this->geometry() << this->isVisible();
+ bgTimer = new QTimer(this);
+ bgTimer->setInterval(50);
+ bgTimer->setSingleShot(true);
+ connect(bgTimer, SIGNAL(timeout()), this, SLOT(bgTimerUpdate()) );
+
+ cmenu = new DesktopContextMenu(this);
+
+ //Setup the connections to the main objects
+ connect(RootDesktopObject::instance(), SIGNAL(screensChanged()), this, SLOT(on_screensChanged()) );
+ connect(RootDesktopObject::instance(), SIGNAL(panelsChanged()), this, SLOT(on_panelsChanged()) );
+ connect(RootDesktopObject::instance(), SIGNAL(windowsChanged()), this, SLOT(on_windowsChanged()) );
+ connect(RootDesktopObject::instance(), SIGNAL(trayWindowsChanged()), this, SLOT(on_trayWindowsChanged()) );
+
+ connect(cmenu, SIGNAL(LockSession()), RootDesktopObject::instance(), SIGNAL(lockScreen()) );
+ connect(cmenu, SIGNAL(showLeaveDialog()), RootDesktopObject::instance(), SIGNAL(startLogout()) );
+ connect(cmenu, SIGNAL(LaunchStandardApplication(QString)), RootDesktopObject::instance(), SIGNAL(launchApplication(QString)) );
+ connect(cmenu, SIGNAL(LaunchApplication(QString)), RootDesktopObject::instance(), SIGNAL(launchApplication(QString)) );
+
+ on_screensChanged(); //make sure this is setup right away (sets up connections
+ QTimer::singleShot(0, this, SLOT(on_panelsChanged()) );
+ QTimer::singleShot(2, this, SLOT(on_windowsChanged()) );
+ QTimer::singleShot(4, this, SLOT(on_trayWindowsChanged()) );
+
+ //Now start the first-run of the background change system
+ cmenu->start();
+ bgTimer->start();
+ this->show();
+}
+
+// === PRIVATE ===
+//QImage bgimage;
+
+
+// === PRIVATE SLOTS ===
+//RootDesktopObject connections
+void RootDesktop::on_screensChanged(){
+ QStringList screens = RootDesktopObject::instance()->screens();
+ //qDebug() << "Screens Changed:" << lastscreens << screens;
+ for(int i=0; i<screens.length(); i++){
+ if(!lastscreens.contains(screens[i])){
+ connect(RootDesktopObject::instance()->screen(screens[i]), SIGNAL(backgroundChanged()), this, SLOT(on_screen_bg_changed()) );
+ }
+ }
+ on_screen_bg_changed(); //start the timer to update the backgrounds now
+ lastscreens = screens; //save this for later
+}
+
+void RootDesktop::on_panelsChanged(){
+
+}
+
+void RootDesktop::on_windowsChanged(){
+
+}
+
+void RootDesktop::on_trayWindowsChanged(){
+
+}
+
+void RootDesktop::on_screen_bg_changed(){
+ if(!bgTimer->isActive()){ bgTimer->start(); }
+}
+
+//Internal use
+void RootDesktop::bgTimerUpdate(){
+ //qDebug() << "bgTimerUpdate";
+ //QtConcurrent::run(this, &RootDesktop::updateBG, this);
+ updateBG(this);
+}
+
+void RootDesktop::updateBG(RootDesktop* obj){
+
+ QImage tmp(obj->size(), QImage::Format_ARGB32_Premultiplied);
+ QStringList scr = RootDesktopObject::instance()->screens();
+ //qDebug() << "updateBG" << scr << tmp.size() << obj->geometry();
+ QPainter imgpaint(&tmp);
+ for(int i=0; i<scr.length(); i++){
+ ScreenObject * screen = RootDesktopObject::instance()->screen(scr[i]);
+ QString file = screen->background(); //in URL format
+ //qDebug() << "Got BG File:" << file << QUrl(file).toLocalFile();
+ QImage img(QUrl(file).toLocalFile());
+ //qDebug() << " - BG File is null:" << img.isNull();
+ imgpaint.drawImage(screen->geometry(), img, QRect(0,0,img.width(), img.height()) );
+ }
+ bgimage = tmp;
+ //QTimer::singleShot(0, obj, SLOT(update()) );
+ obj->update();
+}
+
+// === PROTECTED ===
+void RootDesktop::paintEvent(QPaintEvent *ev){
+ //qDebug() << "Paint Event:" << bgimage.isNull();
+ if (!bgimage.isNull()) {
+ //qDebug() << "Wallpaper paint Event:" << ev->rect();
+ QPainter painter(this);
+ painter.drawImage(ev->rect(), bgimage, ev->rect());
+ }else{
+ QWidget::paintEvent(ev);
+ }
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/RootDesktop.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/RootDesktop.h
new file mode 100644
index 00000000..16ce0e47
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/RootDesktop.h
@@ -0,0 +1,44 @@
+//===========================================
+// Lumina-desktop source code
+// Copyright (c) 2018, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#ifndef _LUMINA_DESKTOP_WIDGETS_ROOT_DESKTOP_H
+#define _LUMINA_DESKTOP_WIDGETS_ROOT_DESKTOP_H
+
+#include <global-includes.h>
+#include "ContextMenu.h"
+
+class RootDesktop : public QWidget{
+ Q_OBJECT
+public:
+ RootDesktop(QWindow *root);
+ ~RootDesktop();
+
+ void start();
+
+private:
+ QImage bgimage;
+ QStringList lastscreens;
+ QTimer *bgTimer;
+ DesktopContextMenu *cmenu;
+
+private slots:
+ //RootDesktopObject connections
+ void on_screensChanged();
+ void on_panelsChanged();
+ void on_windowsChanged();
+ void on_trayWindowsChanged();
+ void on_screen_bg_changed();
+
+ //Internal use
+ void bgTimerUpdate();
+ void updateBG(RootDesktop* obj); //designed to be run in a background thread
+
+protected:
+ virtual void paintEvent(QPaintEvent *ev);
+
+};
+
+#endif
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/src-widgets.pri b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/src-widgets.pri
new file mode 100644
index 00000000..7994bb93
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/src-widgets.pri
@@ -0,0 +1,8 @@
+#update the includepath so we can just #include as needed without paths
+INCLUDEPATH *= $${PWD}
+
+SOURCES *= $${PWD}/RootDesktop.cpp \
+ $${PWD}/ContextMenu.cpp
+
+HEADERS *= $${PWD}/RootDesktop.h \
+ $${PWD}/ContextMenu.h
bgstack15