diff options
Diffstat (limited to 'src-qt5/core')
24 files changed, 410 insertions, 108 deletions
diff --git a/src-qt5/core/libLumina/LFileInfo.cpp b/src-qt5/core/libLumina/LFileInfo.cpp index e7d2b71a..3b659c75 100644 --- a/src-qt5/core/libLumina/LFileInfo.cpp +++ b/src-qt5/core/libLumina/LFileInfo.cpp @@ -35,29 +35,37 @@ void LFileInfo::loadExtraInfo(){ mime = "inode/directory"; //Special directory icons QString name = this->fileName().toLower(); - if(name=="desktop"){ icon = "user-desktop"; } - else if(name=="tmp"){ icon = "folder-temp"; } - else if(name=="video" || name=="videos"){ icon = "folder-video"; } - else if(name=="music" || name=="audio"){ icon = "folder-sound"; } - else if(name=="projects" || name=="devel"){ icon = "folder-development"; } - else if(name=="notes"){ icon = "folder-txt"; } - else if(name=="downloads"){ icon = "folder-downloads"; } - else if(name=="documents"){ icon = "folder-documents"; } - else if(name=="images" || name=="pictures"){ icon = "folder-image"; } - else if(this->absoluteFilePath().startsWith("/net/")){ icon = "folder-remote"; } - else if( !this->isReadable() ){ icon = "folder-locked"; } + if(name=="desktop"){ iconList << "user-desktop"; } + else if(name=="tmp"){ iconList << "folder-temp"; } + else if(name=="video" || name=="videos"){ iconList << "folder-video" << "camera-photo-film" ; } + else if(name=="music" || name=="audio"){ iconList << "folder-sound" << "media-playlist-audio"; } + else if(name=="projects" || name=="devel"){ iconList << "folder-development"; } + else if(name=="notes"){ iconList << "folder-txt" << "note-multiple-outline" << "note-multiple"; } + else if(name=="downloads"){ iconList << "folder-downloads" << "folder-download"; } + else if(name=="documents"){ iconList << "folder-documents"; } + else if(name=="images" || name=="pictures"){ iconList << "folder-image"; } + else if(this->absoluteFilePath().startsWith("/net/")){ iconList << "folder-remote"; } + else if( !this->isReadable() ){ iconList << "folder-locked"<< "folder-lock"; } + iconList << "folder"; }else if( this->suffix()=="desktop"){ mime = "application/x-desktop"; - icon = "application-x-desktop"; //default value + iconList << "application-x-desktop"; //default value desk = new XDGDesktop(this->absoluteFilePath(), 0); if(desk->type!=XDGDesktop::BAD){ //use the specific desktop file info (if possible) - if(!desk->icon.isEmpty()){ icon = desk->icon; } + if(!desk->icon.isEmpty()){ iconList << desk->icon; } } }else{ //Generic file, just determine the mimetype mime = LXDG::findAppMimeForFile(this->fileName()); } + //check the mimetype for an icon as needed + QString tmp = mime; + tmp.replace("/","-"); + iconList << tmp; + if(this->isExecutable()){ + iconList << "application-x-executable"; + } } bool LFileInfo::zfsAvailable(){ @@ -94,14 +102,9 @@ QString LFileInfo::mimetype(){ // -- Return the icon to use for this file QString LFileInfo::iconfile(){ - if(!icon.isEmpty()){ - return icon; - }else if(!mime.isEmpty()){ - QString tmp = mime; - tmp.replace("/","-"); - return tmp; - }else if(this->isExecutable()){ - return "application-x-executable"; + //Go through the icon list and find the first one that exists in the current theme + for(int i=0; i<iconList.length(); i++){ + if( QIcon::hasThemeIcon(iconList[i])){ return iconList[i]; } } return ""; //Fall back to nothing } diff --git a/src-qt5/core/libLumina/LFileInfo.h b/src-qt5/core/libLumina/LFileInfo.h index df1abb65..f72c8649 100644 --- a/src-qt5/core/libLumina/LFileInfo.h +++ b/src-qt5/core/libLumina/LFileInfo.h @@ -17,7 +17,8 @@ class LFileInfo : public QFileInfo{ private: - QString mime, icon, zfs_ds; + QString mime, zfs_ds; + QStringList iconList; XDGDesktop *desk; void loadExtraInfo(); 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 edde5ed7..32f84f93 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp @@ -129,6 +129,8 @@ void DesktopManager::NewWindowAvailable(NativeWindowObject* win){ #ifdef USE_WIDGETS qDebug() << "Got New Widget Window:" << win->name(); NativeWindow *tmp = new NativeWindow(win); + //Lumina::NWS->RequestReparent(win->id(), win->frameId(), tmp->relativeOrigin()); + QTimer::singleShot(10, tmp, SLOT(initProperties()) ); #endif syncWindowList(); } diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h index 945deec0..5ae75ea4 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h @@ -41,6 +41,7 @@ public: Q_INVOKABLE int height(); Q_INVOKABLE bool isVertical(); Q_INVOKABLE QStringList plugins(); + Q_INVOKABLE QRect geometry(){ return geom; } public slots: void setBackground(QString fileOrColor); diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.cpp index 44b2d715..86dd8482 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.cpp @@ -6,11 +6,34 @@ //=========================================== #include "NativeWindow.h" +#include <QWidget> +#include <QWindow> + // === PUBLIC === NativeWindow::NativeWindow( NativeWindowObject *obj ) : QFrame(0, Qt::Window | Qt::FramelessWindowHint){ WIN = obj; createFrame(); - WIN->addFrameWinID(this->winId()); + WIN->addFrameWinID(container->winId()); +} + +NativeWindow::~NativeWindow(){ + vlayout->deleteLater(); + toolbarL->deleteLater(); +} + +QPoint NativeWindow::relativeOrigin(){ + //Update all the margins for the frame + /*QList<int> frame = WIN->property(NativeWindowObject::FrameExtents).value<QList<int> >(); + //QList<int> : [Left, Right, Top, Bottom] in pixels + int topM = frame[2] - titleLabel->fontMetrics().height(); //figure out how much extra we have to work with + if(topM<0){ topM = 0; } + int botM = topM/2.0; + QPoint containerCorner(frame[0], topM-botM); + return containerCorner;*/ + return QPoint(0,0); +} + +void NativeWindow::initProperties(){ //Setup all the property connections connect(WIN, SIGNAL(winImageChanged()), this, SLOT(syncWinImage()) ); connect(WIN, SIGNAL(nameChanged()), this, SLOT(syncName()) ); @@ -21,28 +44,24 @@ NativeWindow::NativeWindow( NativeWindowObject *obj ) : QFrame(0, Qt::Window | Q connect(WIN, SIGNAL(winTypeChanged()), this, SLOT(syncWinType()) ); connect(WIN, SIGNAL(geomChanged()), this, SLOT(syncGeom()) ); connect(WIN, SIGNAL(WindowClosed(WId)), this, SLOT(deleteLater()) ); + + //Setup all the button connections + connect(minB, SIGNAL(clicked()), WIN, SLOT(toggleVisibility()) ); + connect(maxB, SIGNAL(clicked()), WIN, SLOT(toggleMaximize()) ); + connect(closeB, SIGNAL(clicked()), WIN, SLOT(requestClose()) ); + //Now Perform the initial property loads syncWinImage(); syncName(); syncTitle(); syncIcon(); syncSticky(); - syncVisibility(); syncWinType(); syncGeom(); - //Setup all the button connections - connect(minB, SIGNAL(clicked()), WIN, SLOT(toggleVisibility()) ); - connect(maxB, SIGNAL(clicked()), WIN, SLOT(toggleMaximize()) ); - connect(closeB, SIGNAL(clicked()), WIN, SLOT(requestClose()) ); - + syncVisibility(true); //init visibility - force it visible to start with } -NativeWindow::~NativeWindow(){ - vlayout->deleteLater(); - toolbarL->deleteLater(); -} - // === PRIVATE === void NativeWindow::createFrame(){ //Initialize the widgets @@ -62,7 +81,8 @@ void NativeWindow::createFrame(){ vlayout->setSpacing(0); toolbarL = new QHBoxLayout(); toolbarL->setSpacing(0); - + container = QWidget::createWindowContainer(QWindow::fromWinId(WIN->id()), this); + container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); //vlayout.align titleLabel = new QLabel(this); titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); @@ -75,7 +95,7 @@ void NativeWindow::createFrame(){ toolbarL->addWidget(maxB); toolbarL->addWidget(closeB); vlayout->addLayout(toolbarL); - vlayout->addStretch(); + vlayout->addWidget(container); this->setLayout(vlayout); // Load the icons for the buttons loadIcons(); @@ -112,9 +132,13 @@ void NativeWindow::syncSticky(){ qDebug() << "Got Sticky Change:" << WIN->isSticky(); } -void NativeWindow::syncVisibility(){ - qDebug() << "Sync Visibility:" << WIN->isVisible(); - this->setVisible(WIN->isVisible()); +void NativeWindow::syncVisibility(bool init){ + if(init){ + WIN->setProperty(NativeWindowObject::Visible, true, true); //force it + }else{ + qDebug() << "Sync Visibility:" << WIN->isVisible(); + this->setVisible(WIN->isVisible()); + } } void NativeWindow::syncWinType(){ diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.h index 1d87ed71..f2fd822c 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.h +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/NativeWindow.h @@ -16,6 +16,11 @@ public: NativeWindow(NativeWindowObject *obj); ~NativeWindow(); + QPoint relativeOrigin(); //origin of the embedded window relative to the frame + +public slots: + void initProperties(); + private: //Core object NativeWindowObject *WIN; @@ -27,6 +32,7 @@ private: QHBoxLayout *toolbarL; QVBoxLayout *vlayout; QLabel *titleLabel; + QWidget *container; // Info cache variables QRect oldgeom; @@ -38,7 +44,7 @@ private slots: void syncTitle(); void syncIcon(); void syncSticky(); - void syncVisibility(); + void syncVisibility(bool init = false); void syncWinType(); void syncGeom(); }; diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/Panel.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/Panel.cpp new file mode 100644 index 00000000..3f75e8c8 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/Panel.cpp @@ -0,0 +1,87 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2018, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "Panel.h" + +// PUBLIC +Panel::Panel(PanelObject *pobj) : QWidget(0, Qt::Window | Qt::FramelessWindowHint){ + this->setObjectName("LuminaPanelBackgroundWidget"); + obj = pobj; + layout = new QBoxLayout(QBoxLayout::LeftToRight, this); + this->setBackgroundRole(QPalette::AlternateBase); + connect(obj, SIGNAL(backgroundChanged()), this, SLOT(updateBackground()) ); + connect(obj, SIGNAL(geomChanged()), this, SLOT(updateGeom()) ); + connect(obj, SIGNAL(pluginsChanged()), this, SLOT(updatePlugins()) ); + connect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)) ); + updateGeom(); + updateBackground(); + updatePlugins(); + this->showNormal(); +} + +Panel::~Panel(){ + +} + +// PRIVATE +Plugin* Panel::findPlugin(QString id){ + for(int i=0; i<PLUGINS.count(); i++){ + if(PLUGINS[i]->id()==id){ return PLUGINS[i]; } + } + return 0; +} + +Plugin* Panel::createPlugin(QString id){ + + return 0; +} + +// PRIVATE SLOTS +void Panel::objectDestroyed(QObject *dobj){ + if(dobj == Q_NULLPTR || dobj == obj){ + //Make sure this widget is also cleaned up when the base object is deleted + this->deleteLater(); + } +} + +void Panel::updateGeom(){ + this->setGeometry(obj->geometry()); + this->setFixedSize(obj->geometry().size()); + layout->setDirection( obj->isVertical() ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight ); + for(int i=0; i<PLUGINS.length(); i++){ + PLUGINS[i]->setVertical( obj->isVertical() ); + } +} + +void Panel::updateBackground(){ + static QString PANELTEMPLATE = "QToolButton::menu-indicator{ image: none; } QWidget#LuminaPanelBackgroundWidget{ background: %1; }"; + QString bg = obj->background(); + //qDebug() << "Got panel BG:" << obj->name() << bg; + this->setStyleSheet(PANELTEMPLATE.arg(bg)); +} + +void Panel::updatePlugins(){ + QStringList plugs = obj->plugins(); + qDebug() << "Got panel plugins:" << obj->name() << plugs; + for(int i=0; i<plugs.length(); i++){ + lastplugins.removeAll(plugs[i]); //remove this from the last list (handled) + Plugin *plug = findPlugin(plugs[i]); + if(plug==0){ plug = createPlugin(plugs[i]); } + if(plug==0){ continue; } //not a valid plugin - just skip it + //Now setup the order of the plugins properly + if( layout->indexOf(plug) >=0 ){ + layout->removeWidget(plug); //remove from the layout for a moment + } + layout->insertWidget(i, plug); + } + //Now remove any plugins which were deleted from config + for(int i=0; i<lastplugins.length(); i++){ + Plugin *plug = findPlugin(lastplugins[i]); + if(plug==0){ continue; } + plug->deleteLater(); + } + lastplugins = plugs; +} diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/Panel.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/Panel.h new file mode 100644 index 00000000..64b0e239 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/Panel.h @@ -0,0 +1,38 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2018, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is the Widgets version of a floating, top-level panel +//=========================================== +#ifndef _DESKTOP_WIDGETS_PANEL_H +#define _DESKTOP_WIDGETS_PANEL_H + +#include <global-includes.h> +#include <QBoxLayout> +#include "Plugin.h" + +class Panel : public QWidget { + Q_OBJECT +private: + PanelObject *obj; + QBoxLayout *layout; + QStringList lastplugins; + //Stuff for managing the plugins + QList<Plugin*> PLUGINS; + Plugin* findPlugin(QString id); + Plugin* createPlugin(QString id); + +public: + Panel(PanelObject *pobj); + ~Panel(); + +private slots: + void objectDestroyed(QObject*); + void updateGeom(); + void updateBackground(); + void updatePlugins(); + +}; +#endif diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/Plugin.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/Plugin.h new file mode 100644 index 00000000..0934374f --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/Plugin.h @@ -0,0 +1,58 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2018, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is the Widgets version of a generic plugin +//=========================================== +#ifndef _DESKTOP_WIDGETS_GENERIC_PLUGIN_H +#define _DESKTOP_WIDGETS_GENERIC_PLUGIN_H + +#include <global-includes.h> + +//Base plugin type for a canvas/widget +class Plugin : public QWidget{ + Q_OBJECT +private: + bool isPanelPlugin; + bool isVertical; //only used for panel plugins + QString _id; + +signals: + void orientationChanged(); + +public: + Plugin(QWidget *parent, QString id, bool panelplug = false) : QWidget(parent){ + isPanelPlugin = panelplug; + isVertical = false; + _id = id; + } + + void setVertical(bool set){ + if(set!=isVertical){ isVertical = set; emit orientationChanged(); } + } + + QString id(){ return _id; } + +private slots: + +}; + +//Special subclass for a button-based plugin +class PluginButton : public Plugin{ + Q_OBJECT +private: + QToolButton *button; + +public: + PluginButton(QWidget *parent, QString id, bool panelplug=false) : Plugin(parent, id, panelplug) { + button = new QToolButton(this); + this->setLayout( new QBoxLayout(QBoxLayout::LeftToRight) ); + this->layout()->setContentsMargins(0,0,0,0); + this->layout()->addWidget(button); + } + + ~PluginButton(){} +}; +#endif 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 index 9e22a143..3c034dc6 100644 --- 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 @@ -6,6 +6,7 @@ //=========================================== #include <global-objects.h> #include "RootDesktop.h" +#include "Panel.h" // === PUBLIC === RootDesktop::RootDesktop(QWindow *) : QWidget(0, Qt::Widget | Qt::FramelessWindowHint | Qt::WindowStaysOnBottomHint){ @@ -66,7 +67,14 @@ void RootDesktop::on_screensChanged(){ } void RootDesktop::on_panelsChanged(){ - + QStringList pans = RootDesktopObject::instance()->panels(); + //Now find any new panels and create them as needed + for(int i=0; i<pans.length(); i++){ + if(lastpanels.contains(pans[i])){ continue; } //already created + //Need to create a new panel widget (self-maintained) + new Panel( RootDesktopObject::instance()->panel(pans[i]) ); + } + lastpanels = pans; //save this for the next time around } void RootDesktop::on_windowsChanged(){ 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 index 16ce0e47..ff717074 100644 --- 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 @@ -20,7 +20,7 @@ public: private: QImage bgimage; - QStringList lastscreens; + QStringList lastscreens, lastpanels; QTimer *bgTimer; DesktopContextMenu *cmenu; 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 index f1e200fd..7ed228f7 100644 --- 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 @@ -3,8 +3,11 @@ INCLUDEPATH *= $${PWD} SOURCES *= $${PWD}/RootDesktop.cpp \ $${PWD}/ContextMenu.cpp \ - $${PWD}/NativeWindow.cpp + $${PWD}/NativeWindow.cpp \ + $${PWD}/Panel.cpp HEADERS *= $${PWD}/RootDesktop.h \ $${PWD}/ContextMenu.h \ - $${PWD}/NativeWindow.h + $${PWD}/NativeWindow.h \ + $${PWD}/Panel.h \ + $${PWD}/Plugin.h diff --git a/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp b/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp index 65fa98a7..0d1e9c10 100644 --- a/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp @@ -631,6 +631,7 @@ void NativeWindowSystem::SetupNewWindow(NativeWindowObject *win){ win->addDamageID( (uint) dmgID); //save this for later }else{ + /* //xcb_reparent_window(QX11Info::connection(), win->id(), this->winId(), 0, 0); //Also use a partial-composite here - make sure the window pixmap is available even when the window is obscured xcb_composite_redirect_window(QX11Info::connection(), win->id(), XCB_COMPOSITE_REDIRECT_AUTOMATIC); @@ -639,6 +640,7 @@ void NativeWindowSystem::SetupNewWindow(NativeWindowObject *win){ Damage dmgID = XDamageCreate(QX11Info::display(), win->id(), XDamageReportRawRectangles); win->addDamageID( (uint) dmgID); //save this for later + */ } //win->addFrameWinID(this->winId()); registerClientEvents(win->id()); @@ -795,7 +797,7 @@ void NativeWindowSystem::NewWindowDetected(WId id){ if(attr == 0){ return; } //could not get attributes of window if(attr->override_redirect){ free(attr); return; } //window has override redirect set (do not manage) free(attr); - xcb_reparent_window(QX11Info::connection(), id, QX11Info::appRootWindow(), 0, 0); + //xcb_reparent_window(QX11Info::connection(), id, QX11Info::appRootWindow(), 0, 0); //Now go ahead and create/populate the container for this window NativeWindowObject *win = new NativeWindowObject(id); diff --git a/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.h b/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.h index 0b6cd67e..f6033674 100644 --- a/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.h +++ b/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.h @@ -127,12 +127,14 @@ public slots: void NewMouseRelease(int buttoncode, WId win = 0); void CheckDamageID(WId); + void RequestReparent(WId, WId, QPoint); //client, parent, relative origin point in parent + + private slots: //These are the slots which are built-in and automatically connected when a new NativeWindow is created void RequestClose(WId); void RequestKill(WId); void RequestPing(WId); - void RequestReparent(WId, WId, QPoint); //client, parent, relative origin point in parent //Window-mgmt functions (see Window-mgmt.cpp for details) void ArrangeWindows(WId primary, QString type); diff --git a/src-qt5/core/lumina-desktop/LDesktopBackground.cpp b/src-qt5/core/lumina-desktop/LDesktopBackground.cpp index 6b458c24..22ee6dc4 100644 --- a/src-qt5/core/lumina-desktop/LDesktopBackground.cpp +++ b/src-qt5/core/lumina-desktop/LDesktopBackground.cpp @@ -46,7 +46,7 @@ QPixmap LDesktopBackground::setBackground(const QString& bgFile, const QString& } else { mode = Qt::KeepAspectRatio; } - if(bgImage.height() != geom.height() && bgImage.width() != geom.width() ){ bgImage = bgImage.scaled(geom.size(), mode); } + if(bgImage.height() != geom.height() && bgImage.width() != geom.width() ){ bgImage = bgImage.scaled(geom.size(), mode, Qt::SmoothTransformation); } //bgImage = bgImage.scaled(size(), mode); } diff --git a/src-qt5/core/lumina-desktop/LSession.cpp b/src-qt5/core/lumina-desktop/LSession.cpp index c1f49fc3..fe399e40 100644 --- a/src-qt5/core/lumina-desktop/LSession.cpp +++ b/src-qt5/core/lumina-desktop/LSession.cpp @@ -10,6 +10,7 @@ #include <QTime> #include <QScreen> #include <QtConcurrent> +#include <QMimeData> #include "LXcbEventFilter.h" #include "BootSplash.h" @@ -72,6 +73,11 @@ LSession::LSession(int &argc, char ** argv) : LSingleApplication(argc, argv, "lu connect(this, SIGNAL(screenAdded(QScreen*)), this, SLOT(screensChanged()) ); connect(this, SIGNAL(screenRemoved(QScreen*)), this, SLOT(screensChanged()) ); connect(this, SIGNAL(primaryScreenChanged(QScreen*)), this, SLOT(screensChanged()) ); + + // Clipboard + ignoreClipboard = false; + qRegisterMetaType<QClipboard::Mode>("QClipboard::Mode"); + connect(QApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)), this, SLOT(handleClipboard(QClipboard::Mode))); } //end check for primary process } @@ -587,6 +593,31 @@ void LSession::SessionEnding(){ stopSystemTray(); //just in case it was not stopped properly earlier } +void LSession::handleClipboard(QClipboard::Mode mode){ + if ( !ignoreClipboard && mode == QClipboard::Clipboard ){ //only support Clipboard + const QMimeData *mime = QApplication::clipboard()->mimeData(mode); + if (mime==NULL) { return; } + if (mime->hasText() && !QApplication::clipboard()->ownsClipboard()) { + //preserve the entire mimeData set, not just the text + //Note that even when we want to "save" the test, we should keep the whole thing + // this preserves formatting codes and more that apps might need + QMimeData *copy = new QMimeData(); + QStringList fmts = mime->formats(); + for(int i=0; i<fmts.length(); i++){ copy->setData(fmts[i], mime->data(fmts[i])); } + ignoreClipboard = true; + QApplication::clipboard()->setMimeData(copy, mode); + ignoreClipboard = false; + //QMetaObject::invokeMethod(this, "storeClipboard", Qt::QueuedConnection, Q_ARG(QString, mime->text()), Q_ARG(QClipboard::Mode, mode)); + } + } +} + +void LSession::storeClipboard(QString text, QClipboard::Mode mode){ + ignoreClipboard = true; + QApplication::clipboard()->setText(text, mode); + ignoreClipboard = false; +} + //=============== // SYSTEM ACCESS //=============== diff --git a/src-qt5/core/lumina-desktop/LSession.h b/src-qt5/core/lumina-desktop/LSession.h index a25f3c15..824eede7 100644 --- a/src-qt5/core/lumina-desktop/LSession.h +++ b/src-qt5/core/lumina-desktop/LSession.h @@ -21,6 +21,7 @@ #include <QMediaPlayer> #include <QThread> #include <QUrl> +#include <QClipboard> #include "Globals.h" #include "AppMenu.h" @@ -141,6 +142,8 @@ private: int VersionStringToNumber(QString version); + bool ignoreClipboard; // flag for (handle/store)Clipboard + public slots: void StartLogout(); void StartShutdown(bool skipupdates = false); @@ -170,6 +173,10 @@ private slots: void SessionEnding(); + // Clipboard + void handleClipboard(QClipboard::Mode mode); + void storeClipboard(QString text, QClipboard::Mode mode); + signals: //System Tray Signals void VisualTrayAvailable(); //new Visual Tray Plugin can be registered diff --git a/src-qt5/core/lumina-desktop/fluxboxconf/fluxbox-keys b/src-qt5/core/lumina-desktop/fluxboxconf/fluxbox-keys index d3ee64ef..82d31e9c 100644 --- a/src-qt5/core/lumina-desktop/fluxboxconf/fluxbox-keys +++ b/src-qt5/core/lumina-desktop/fluxboxconf/fluxbox-keys @@ -49,16 +49,10 @@ OnTitlebar Mouse3 :WindowMenu # alt-tab Mod1 Tab :NextWindow (workspace=[current]) (workspace=[current]) !! FBCV13 !! Mod1 Shift Tab :PrevWindow (workspace=[current]) (workspace=[current]) !! FBCV13 !! -Control Tab :NextGroup (workspace=[current]) (workspace=[current]) -Control Shift Tab :PrevGroup (workspace=[current]) (workspace=[current]) - -# cycle through tabs in the current window -Mod4 Tab :NextTab -Mod4 Shift Tab :PrevTab # Arrange/Tile Current windows -Mod1 Left :ArrangeWindowsStackRight (Layer=Normal) -Mod1 Right :ArrangeWindowsStackLeft (Layer=Normal) +Mod1 Control Left :ArrangeWindowsStackRight (Layer=Normal) +Mod1 Control Right :ArrangeWindowsStackLeft (Layer=Normal) # go to a specific tab in the current window Mod4 1 :Tab 1 @@ -84,14 +78,6 @@ Mod1 F9 :If {Matches (Layer=Normal)} {Minimize} Mod1 F10 :If {Matches (Layer=Normal)} {Maximize} Mod1 F11 :If {Matches (Layer=Normal)} {Fullscreen} -# send the current window to previous/next workspace -Mod4 Left :If {Matches (Layer=Normal)} {SendToPrevWorkspace} -Mod4 Right :If {Matches (Layer=Normal)} {SendToNextWorkspace} - -# send the current window and follow it to previous/next workspace -Control Mod4 Left :If {Matches (Layer=Normal)} {TakeToPrevWorkspace} -Control Mod4 Right :If {Matches (Layer=Normal)} {TakeToNextWorkspace} - # change to a specific workspace Control F1 :Workspace 1 Control F2 :Workspace 2 @@ -109,9 +95,9 @@ Control F12 :Workspace 12 Control Mod1 Left :PrevWorkspace Control Mod1 Right :NextWorkspace -# Control + MouseWheel to change workspaces -Control Mouse4 :PrevWorkspace -Control Mouse5 :NextWorkspace +# Control+Alt + MouseWheel to change workspaces +Control Mod1 Mouse4 :PrevWorkspace +Control Mod1 Mouse5 :NextWorkspace # send the current window to a specific workspace Mod4 F1 :SendToWorkspace 1 @@ -152,3 +138,4 @@ Mod1 Home :Exec lumina-open -brightnessup Mod1 End :Exec lumina-open -brightnessdown F12 :Exec lumina-terminal -toggle 115 :Exec lumina-desktop --show-start +Mod4 space :Exec lumina-desktop --show-start diff --git a/src-qt5/core/lumina-desktop/lumina-desktop.pro b/src-qt5/core/lumina-desktop/lumina-desktop.pro index e36d11a2..cc4b63ae 100644 --- a/src-qt5/core/lumina-desktop/lumina-desktop.pro +++ b/src-qt5/core/lumina-desktop/lumina-desktop.pro @@ -69,9 +69,7 @@ RESOURCES+= Lumina-DE.qrc desktop.path = $${L_SESSDIR} desktop.files = Lumina-DE.desktop -icons.files = Lumina-DE.png \ - Insight-FileManager.png -icons.path = $${L_SHAREDIR}/pixmaps +icons.files = Lumina-DE.png fluxconf.files = fluxboxconf/fluxbox-init-rc \ fluxboxconf/fluxbox-keys diff --git a/src-qt5/core/lumina-session/session.cpp b/src-qt5/core/lumina-session/session.cpp index 743fc396..0f0a99eb 100644 --- a/src-qt5/core/lumina-session/session.cpp +++ b/src-qt5/core/lumina-session/session.cpp @@ -42,7 +42,7 @@ void LSession::procFinished(){ if(PROCS[i]->objectName()=="runtime"){ qDebug() << "Got Desktop Process Finished:" << PROCS[i]->exitCode(); //if(PROCS[i]->exitCode()==787){ PROCS[i]->start(QIODevice::ReadOnly); } //special internal restart code - //else{ + //else{ stopall(); //} }else if(PROCS[i]->objectName()=="wm" && wmfails<2){ wmfails++; PROCS[i]->start(QIODevice::ReadOnly); wmTimer->start(); } //restart the WM //if(PROCS[i]->program().section("/",-1) == "lumina-desktop"){ stopall(); } //start closing down everything @@ -53,14 +53,29 @@ void LSession::procFinished(){ } //qDebug() << " - Final Count:" << stopped << stopping; if(stopping || stopped==PROCS.length()){ + //Note about compton: It does not like running multiple sessions under the *same user* + // (even on different displays). Run a blanket killall on it when closing down so that + // any other Lumina sessions will automatically restart compton on that specific display + QProcess::execute("killall compton"); QCoreApplication::exit(0); + }else{ + //Make sure we restart the process as needed + for(int i=0; i<PROCS.length(); i++){ + if(PROCS[i]->state()==QProcess::NotRunning){ + //runtime/wm processes have special restart rules above + if(PROCS[i]->objectName()!="runtime" && PROCS[i]->objectName()!="wm"){ + PROCS[i]->start(QIODevice::ReadOnly); + } + } + } } } void LSession::startProcess(QString ID, QString command, QStringList watchfiles){ QString dir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/logs"; + QString display = QString(getenv("DISPLAY")).section(":",1,1); if(!QFile::exists(dir)){ QDir tmp(dir); tmp.mkpath(dir); } - QString logfile = dir+"/"+ID+".log"; + QString logfile = dir+"/"+ID+"_"+display+".log"; if(QFile::exists(logfile+".old")){ QFile::remove(logfile+".old"); } if(QFile::exists(logfile)){ QFile::rename(logfile,logfile+".old"); } @@ -86,6 +101,37 @@ void LSession::startProcess(QString ID, QString command, QStringList watchfiles) PROCS << proc; } +void LSession::setupCompositor(){ + //Compositing manager + QSettings settings("lumina-desktop","sessionsettings"); + if(settings.value("enableCompositing",false).toBool()){ + if(LUtils::isValidBinary("compton")){ + //Compton available - check the config file + QString set = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/compton.conf"; + if(!QFile::exists(set)){ + if(QFile::exists(LOS::LuminaShare()+"/compton.conf")){ + QFile::copy(LOS::LuminaShare()+"/compton.conf", set); + } + } + //Auto-detect if GLX is available on the system and turn it on/off as needed + bool startcompton = true; + if(LUtils::isValidBinary("glxinfo")){ + bool hasAccel =! LUtils::getCmdOutput("glxinfo -B").filter("direct rendering:").filter("Yes").isEmpty(); + qDebug() << "Detected GPU Acceleration:" << hasAccel; + QStringList info = LUtils::readFile(set); + for(int i=0; i<info.length(); i++){ + if(info[i].section("=",0,0).simplified()=="backend"){ info[i] = QString("backend = \"")+ (hasAccel ? "glx" : "xrender")+"\""; break; } //replace this line + } + LUtils::writeFile(set, info, true); + if( !hasAccel && settings.value("compositingWithGpuAccelOnly",true).toBool() ){ startcompton = false; } + } + QString disp = getenv("DISPLAY"); + if(startcompton && QFile::exists(set)){ startProcess("compositing","compton -d "+disp+" --config \""+set+"\"", QStringList() << set); } + else if(startcompton){ startProcess("compositing","compton -d "+disp); } + }else if(LUtils::isValidBinary("xcompmgr") && !settings.value("compositingWithGpuAccelOnly",true).toBool() ){ startProcess("compositing","xcompmgr"); } + } +} + void LSession::start(bool unified){ //First check for a valid installation if(!LUtils::isValidBinary("lumina-desktop") ){ @@ -128,32 +174,7 @@ void LSession::start(bool unified){ startProcess("wm", cmd, QStringList() << confDir+"/fluxbox-init" << confDir+"/fluxbox-keys"); } //Compositing manager - QSettings settings("lumina-desktop","sessionsettings"); - if(settings.value("enableCompositing",false).toBool()){ - if(LUtils::isValidBinary("compton")){ - //Compton available - check the config file - QString set = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/compton.conf"; - if(!QFile::exists(set)){ - if(QFile::exists(LOS::LuminaShare()+"/compton.conf")){ - QFile::copy(LOS::LuminaShare()+"/compton.conf", set); - } - } - //Auto-detect if GLX is available on the system and turn it on/off as needed - bool startcompton = true; - if(LUtils::isValidBinary("glxinfo")){ - bool hasAccel =! LUtils::getCmdOutput("glxinfo -B").filter("direct rendering:").filter("Yes").isEmpty(); - qDebug() << "Detected GPU Acceleration:" << hasAccel; - QStringList info = LUtils::readFile(set); - for(int i=0; i<info.length(); i++){ - if(info[i].section("=",0,0).simplified()=="backend"){ info[i] = QString("backend = \"")+ (hasAccel ? "glx" : "xrender")+"\""; break; } //replace this line - } - LUtils::writeFile(set, info, true); - if( !hasAccel && settings.value("compositingWithGpuAccelOnly",true).toBool() ){ startcompton = false; } - } - if(startcompton && QFile::exists(set)){ startProcess("compositing","compton --config \""+set+"\"", QStringList() << set); } - else if(startcompton){ startProcess("compositing","compton"); } - }else if(LUtils::isValidBinary("xcompmgr") && !settings.value("compositingWithGpuAccelOnly",true).toBool() ){ startProcess("compositing","xcompmgr"); } - } + setupCompositor(); } else { if(!LUtils::isValidBinary(WM)){ exit(1); @@ -166,6 +187,7 @@ void LSession::start(bool unified){ if(LUtils::isValidBinary("xscreensaver")){ startProcess("screensaver","xscreensaver -no-splash"); } }else{ //unified process + setupCompositor(); startProcess("runtime","lumina-desktop-unified"); } } diff --git a/src-qt5/core/lumina-session/session.h b/src-qt5/core/lumina-session/session.h index 3bbcbb8e..6f7f8e36 100644 --- a/src-qt5/core/lumina-session/session.h +++ b/src-qt5/core/lumina-session/session.h @@ -63,6 +63,8 @@ private: int wmfails; QTimer *wmTimer; + void setupCompositor(); + private slots: void stopall(); diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp index 789b3990..a6e05000 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp @@ -7,6 +7,7 @@ #include <QTimer> #include <QIcon> #include <QRegExp> +#include <QWindow> #ifdef QT_WIDGETS_LIB #include <QStyle> diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.cpp index cb491aa6..9ffe39f8 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.cpp @@ -61,7 +61,10 @@ QStringList lthemeengine::sharedStyleSheetPath(){ dirs << QString(getenv("XDG_CONFIG_HOME")); dirs << QString(getenv("XDG_CONFIG_DIRS")).split(":"); dirs << QString(getenv("XDG_DATA_DIRS")).split(":"); - for(int i=0; i<dirs.length(); i++){ dirs[i].append("/lthemeengine/qss/"); } + for(int i=0; i<dirs.length(); i++){ + if (!dirs[i].endsWith("/")){ dirs[i].append("/"); } + dirs[i].append("lthemeengine/qss/"); + } if(dirs.isEmpty()){ dirs << LTHEMEENGINE_DATADIR"/lthemeengine/qss/"; } //no XDG settings - use the hardcoded path return dirs; } @@ -75,7 +78,10 @@ QStringList lthemeengine::sharedDesktopStyleSheetPath(){ dirs << QString(getenv("XDG_CONFIG_HOME")); dirs << QString(getenv("XDG_CONFIG_DIRS")).split(":"); dirs << QString(getenv("XDG_DATA_DIRS")).split(":"); - for(int i=0; i<dirs.length(); i++){ dirs[i].append("/lthemeengine/desktop_qss/"); } + for(int i=0; i<dirs.length(); i++){ + if (!dirs[i].endsWith("/")){ dirs[i].append("/"); } + dirs[i].append("lthemeengine/desktop_qss/"); + } if(dirs.isEmpty()){ dirs << LTHEMEENGINE_DATADIR"/lthemeengine/desktop_qss/"; } //no XDG settings - use the hardcoded path return dirs; } @@ -89,7 +95,10 @@ QStringList lthemeengine::sharedColorSchemePath(){ dirs << QString(getenv("XDG_CONFIG_HOME")); dirs << QString(getenv("XDG_CONFIG_DIRS")).split(":"); dirs << QString(getenv("XDG_DATA_DIRS")).split(":"); - for(int i=0; i<dirs.length(); i++){ dirs[i].append("/lthemeengine/colors/"); } + for(int i=0; i<dirs.length(); i++){ + if (!dirs[i].endsWith("/")){ dirs[i].append("/"); } + dirs[i].append("lthemeengine/colors/"); + } if(dirs.isEmpty()){ dirs << LTHEMEENGINE_DATADIR"/lthemeengine/colors/"; } //no XDG settings - use the hardcoded path qDebug() << "Got Color Dirs:" << dirs; return dirs; diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp index 3140c553..72cde6b3 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp @@ -239,26 +239,36 @@ void QSSPage::readSettings(){ void QSSPage::findStyleSheets(QStringList paths, QStringList enabled){ paths.removeDuplicates(); + std::reverse(enabled.begin(), enabled.end()); // reverse for proper order + QMap<int, QString> sortedStylesSheets; for(int i=0; i<paths.length(); i++){ if(!QFile::exists(paths[i])){ continue; } QDir dir(paths[i]); dir.setFilter(QDir::Files); dir.setNameFilters(QStringList() << "*.qss"); foreach (QFileInfo info, dir.entryInfoList()){ + if(enabled.contains(info.filePath())){ sortedStylesSheets[enabled.indexOf(info.filePath())] = info.filePath(); } + else{ + QListWidgetItem *item = new QListWidgetItem(info.fileName()); + item->setToolTip(info.filePath()); + item->setData(QSS_FULL_PATH_ROLE, info.filePath()); + item->setData(QSS_WRITABLE_ROLE, info.isWritable()); + m_ui->list_disabled->addItem(item); + } + } + } + QMapIterator<int, QString> i(sortedStylesSheets); + while (i.hasNext()) { + i.next(); + QFileInfo info(i.value()); + if (info.isFile()) { QListWidgetItem *item = new QListWidgetItem(info.fileName()); item->setToolTip(info.filePath()); item->setData(QSS_FULL_PATH_ROLE, info.filePath()); item->setData(QSS_WRITABLE_ROLE, info.isWritable()); - if( enabled.contains(info.filePath()) ){ m_ui->qssListWidget->addItem(item); } - else{ m_ui->list_disabled->addItem(item); } + m_ui->qssListWidget->addItem(item); } } - //Now ensure the priority of the items in the active list is correct - for(int i = 0; i < m_ui->qssListWidget->count(); ++i){ - QListWidgetItem *item = m_ui->qssListWidget->item(i); - int index = enabled.indexOf( item->data(QSS_FULL_PATH_ROLE).toString() ); - if(index>=0){ m_ui->qssListWidget->insertItem(index, item); }// item->move(m_ui->qssListWidget->count() - 1 - index); } - } m_ui->list_disabled->sortItems(Qt::AscendingOrder); } |