From 11918f54e194807c8ed6988c70306d883c8e9054 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 1 Feb 2017 11:52:09 -0500 Subject: Add a new "NativeWindow" class to the library. This is a pure Qt container class for setting/announcing changes to native windows on the system. This allows the WM class (XCB/Wayland-specific) to simply adjust each window object as needed, and the interface (pure Qt) will automatically adjust as needed. NOTE: Still need to adjust the LXCBEventFilter to use this new class, but the root window and rootsubwindow classes are all setup to use it. --- src-qt5/core/libLumina/NativeWindow.cpp | 37 +++++++++++++++ src-qt5/core/libLumina/NativeWindow.h | 69 ++++++++++++++++++++++++++++ src-qt5/core/libLumina/NativeWindow.pri | 8 ++++ src-qt5/core/libLumina/RootSubWindow.cpp | 77 ++++++++++++++++++++------------ src-qt5/core/libLumina/RootSubWindow.h | 21 ++++----- src-qt5/core/libLumina/RootWindow.cpp | 21 +++------ src-qt5/core/libLumina/RootWindow.h | 7 ++- src-qt5/core/libLumina/RootWindow.pri | 3 +- 8 files changed, 183 insertions(+), 60 deletions(-) create mode 100644 src-qt5/core/libLumina/NativeWindow.cpp create mode 100644 src-qt5/core/libLumina/NativeWindow.h create mode 100644 src-qt5/core/libLumina/NativeWindow.pri (limited to 'src-qt5/core/libLumina') diff --git a/src-qt5/core/libLumina/NativeWindow.cpp b/src-qt5/core/libLumina/NativeWindow.cpp new file mode 100644 index 00000000..eb85e394 --- /dev/null +++ b/src-qt5/core/libLumina/NativeWindow.cpp @@ -0,0 +1,37 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "NativeWindow.h" + +// === PUBLIC === +NativeWindow::NativeWindow(WId id) : QObject(){ + winid = id; + WIN = QWindow::fromWinId(winid); +} + +NativeWindow::~NativeWindow(){ + hash.clear(); + WIN->deleteLater(); +} + +WId NativeWindow::id(){ + return winid; +} + +QWindow* NativeWindow::window(){ + return WIN; +} + +QVariant NativeWindow::property(NativeWindow::Property prop){ + if(hash.contains(prop)){ return hash.value(prop); } + return QVariant(); //null variant +} + +void NativeWindow::setProperty(NativeWindow::Property prop, QVariant val){ + if(prop == NativeWindow::None){ return; } + hash.insert(prop, val); + emit PropertyChanged(prop, val); +} diff --git a/src-qt5/core/libLumina/NativeWindow.h b/src-qt5/core/libLumina/NativeWindow.h new file mode 100644 index 00000000..bcbe8b6c --- /dev/null +++ b/src-qt5/core/libLumina/NativeWindow.h @@ -0,0 +1,69 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is a container object for setting/announcing changes +// in a native window's properties. +// The WM will usually run the "setProperty" function on this object, +// and any other classes/widgets which watch this window can act appropriatly after-the-fact +// Non-WM classes should use the "Request" signals to ask the WM to do something, and listen for changes later +//=========================================== +#ifndef _LUMINA_DESKTOP_NATIVE_WINDOW_H +#define _LUMINA_DESKTOP_NATIVE_WINDOW_H + +#include +#include +#include +#include +#include +#include +#include + +class NativeWindow : public QObject{ + Q_OBJECT +public: + enum Property{ /*QVariant Type*/ + None, /*null*/ + MinSize, /*QSize*/ + MaxSize, /*QSize*/ + Size, /*int*/ + Title, /*QString*/ + Icon, /*QIcon*/ + Name, /*QString*/ + Workspace, /*int*/ + WindowFlags, /*Qt::WindowFlags*/ + Active, /*bool*/ + Visible /*bool*/ + }; + + NativeWindow(WId id); + ~NativeWindow(); + + WId id(); + QWindow* window(); + + QVariant property(NativeWindow::Property); + void setProperty(NativeWindow::Property, QVariant); + +private: + QHash hash; + QWindow *WIN; + WId winid; + +signals: + //General Notifications + void PropertyChanged(NativeWindow::Property, QVariant); + void WindowClosed(WId); + + //Action Requests (not automatically emitted) + //Note: "WId" should be the NativeWindow id() + void RequestActivate(WId); + void RequestClose(WId); + + // System Tray Icon Embed/Unembed Requests + //void RequestEmbed(WId, QWidget*); + //void RequestUnEmbed(WId, QWidget*); +}; +#endif diff --git a/src-qt5/core/libLumina/NativeWindow.pri b/src-qt5/core/libLumina/NativeWindow.pri new file mode 100644 index 00000000..4a585a06 --- /dev/null +++ b/src-qt5/core/libLumina/NativeWindow.pri @@ -0,0 +1,8 @@ + +# Files +SOURCES *= $${PWD}/NativeWindow.cpp + +HEADERS *= $${PWD}/NativeWindow.h + +INCLUDEPATH *= ${PWD} + diff --git a/src-qt5/core/libLumina/RootSubWindow.cpp b/src-qt5/core/libLumina/RootSubWindow.cpp index f1d5fe61..93a49e6b 100644 --- a/src-qt5/core/libLumina/RootSubWindow.cpp +++ b/src-qt5/core/libLumina/RootSubWindow.cpp @@ -8,30 +8,22 @@ #include // === PUBLIC === -RootSubWindow::RootSubWindow(QMdiArea *root, WId window, Qt::WindowFlags flags) : \ - QMdiSubWindow(0, flags){ +RootSubWindow::RootSubWindow(QMdiArea *root, NativeWindow *win) : QMdiSubWindow(0){ this->setAttribute(Qt::WA_DeleteOnClose); //Create the QWindow and QWidget containers for the window + WIN = win; closing = false; - CID = window; - WIN = QWindow::fromWinId(CID); - WinWidget = QWidget::createWindowContainer( WIN, this); + WinWidget = QWidget::createWindowContainer( WIN->window(), this); this->setWidget(WinWidget); + LoadProperties( QList< NativeWindow::Property>() << NativeWindow::WindowFlags << NativeWindow::Title << NativeWindow::Icon \ + << NativeWindow::MinSize << NativeWindow::MaxSize << NativeWindow::Size ); //Hookup the signals/slots connect(this, SIGNAL(aboutToActivate()), this, SLOT(aboutToActivate()) ); - connect(WIN, SIGNAL(windowTitleChanged(const QString&)), this, SLOT(setWindowTitle(const QString&)) ); - connect(WIN, SIGNAL(heightChanged(int)), this, SLOT(adjustHeight(int) )); - connect(WIN, SIGNAL(widthChanged(int)), this, SLOT(adjustWidth(int) )); - - qDebug() << "Initial Window Geometry:" << WIN->geometry(); - qDebug() << "Initial Widget Geometry:" << WinWidget->geometry(); - qDebug() << "Minimums:"; - qDebug() << " - Height:" << WIN->minimumHeight(); - qDebug() << " - Width:" << WIN->minimumWidth(); - - //this->resize(WinWidget->size()); + connect(WIN, SIGNAL(PropertyChanged(NativeWindow::Property, QVariant)), this, SLOT(propertyChanged(NativeWindow::Property, QVariant))); //Now add this window to the root QMdiArea root->addSubWindow(this); + //Make sure the visibily property only gets loaded after it is added to the root area + propertyChanged(NativeWindow::Visible, WIN->property(NativeWindow::Visible)); } RootSubWindow::~RootSubWindow(){ @@ -39,10 +31,15 @@ RootSubWindow::~RootSubWindow(){ } WId RootSubWindow::id(){ - return CID; + return WIN->id(); } // === PRIVATE === +void RootSubWindow::LoadProperties( QList< NativeWindow::Property> list){ + for(int i=0; iproperty(list[i]) ); + } +} // === PUBLIC SLOTS === void RootSubWindow::clientClosed(){ @@ -63,26 +60,48 @@ void RootSubWindow::clientShown(){ // === PRIVATE SLOTS === void RootSubWindow::aboutToActivate(){ - emit Activated(CID); //need to activate the subwindow - not the frame - WIN->requestActivate(); + WIN->emit RequestActivate(WIN->id()); } -void RootSubWindow::adjustHeight(int val){ - qDebug() << "Adjust height:" << val; - WinWidget->resize(WinWidget->width(), val); -} - -void RootSubWindow::adjustWidth(int val){ - qDebug() << "Adjust Width:" << val; - WinWidget->resize(val, WinWidget->height()); +void RootSubWindow::propertyChanged(NativeWindow::Property prop, QVariant val){ + if(val.isNull()){ return; } //not the same as a default/empty value - the property has just not been set yet + switch(prop){ + case NativeWindow::Visible: + if(val.toBool()){ clientShown(); } + else{ clientHidden(); } + break; + case NativeWindow::Title: + this->setWindowTitle(val.toString()); + break; + case NativeWindow::Icon: + this->setWindowIcon(val.value< QIcon>()); + break; + case NativeWindow::Size: + this->resize(val.toSize()); + break; + case NativeWindow::MinSize: + this->setMinimumSize(val.toSize()); + break; + case NativeWindow::MaxSize: + this->setMaximumSize(val.toSize()); + break; + case NativeWindow::Active: + if(val.toBool()){ this->mdiArea()->setActiveSubWindow(this); } + break; + case NativeWindow::WindowFlags: + this->setWindowFlags( val.value< Qt::WindowFlags >() ); + break; + default: + qDebug() << "Window Property Unused:" << prop << val; + } } // === PROTECTED === void RootSubWindow::closeEvent(QCloseEvent *ev){ if(!closing){ - qDebug() << "Close Window By Button:" << CID; + //qDebug() << "Close Window By Button:" << WIN->id(); ev->ignore(); - WIN->destroy(); + WIN->emit RequestClose(WIN->id()); }else{ QMdiSubWindow::closeEvent(ev); } diff --git a/src-qt5/core/libLumina/RootSubWindow.h b/src-qt5/core/libLumina/RootSubWindow.h index d4119ccc..c56f3c96 100644 --- a/src-qt5/core/libLumina/RootSubWindow.h +++ b/src-qt5/core/libLumina/RootSubWindow.h @@ -16,35 +16,36 @@ #include #include +#include + class RootSubWindow : public QMdiSubWindow{ Q_OBJECT public: - RootSubWindow(QMdiArea *root, WId window, Qt::WindowFlags flags = Qt::WindowFlags()); + RootSubWindow(QMdiArea *root, NativeWindow *win); ~RootSubWindow(); WId id(); private: - WId CID; //client window ID - QWindow *WIN; //Embedded window container + NativeWindow *WIN; QWidget *WinWidget; bool closing; + + void LoadProperties( QList< NativeWindow::Property> list); + public slots: void clientClosed(); - void clientHidden(); - void clientShown(); private slots: + void clientHidden(); + void clientShown(); void aboutToActivate(); - void adjustHeight(int); - void adjustWidth(int); + void propertyChanged(NativeWindow::Property, QVariant); + protected: void closeEvent(QCloseEvent*); -signals: - void Activated(WId); - }; #endif diff --git a/src-qt5/core/libLumina/RootWindow.cpp b/src-qt5/core/libLumina/RootWindow.cpp index 57950a48..0758653b 100644 --- a/src-qt5/core/libLumina/RootWindow.cpp +++ b/src-qt5/core/libLumina/RootWindow.cpp @@ -166,28 +166,17 @@ void RootWindow::ChangeWallpaper(QString id, RootWindow::ScaleType scale, QStrin } -void RootWindow::NewWindow(WId win, Qt::WindowFlags flags){ +void RootWindow::NewWindow(NativeWindow *win){ RootSubWindow *subwin = 0; for(int i=0; iid() == win){ subwin = WINDOWS[i]; } + if(WINDOWS[i]->id() == win->id()){ subwin = WINDOWS[i]; } } if(subwin==0){ - subwin = new RootSubWindow(this, win, flags); + subwin = new RootSubWindow(this, win); + connect(win, SIGNAL(WindowClosed(WId)), this, SLOT(CloseWindow(WId)) ); WINDOWS << subwin; } - subwin->show(); -} - -void RootWindow::ShowWindow(WId win){ - for(int i=0; iid() == win){ WINDOWS[i]->clientShown(); break; } - } -} - -void RootWindow::HideWindow(WId win){ - for(int i=0; iid() == win){ WINDOWS[i]->clientHidden(); break; } - } + //subwin->show(); } void RootWindow::CloseWindow(WId win){ diff --git a/src-qt5/core/libLumina/RootWindow.h b/src-qt5/core/libLumina/RootWindow.h index a653d82a..5d3bc963 100644 --- a/src-qt5/core/libLumina/RootWindow.h +++ b/src-qt5/core/libLumina/RootWindow.h @@ -21,6 +21,7 @@ #include #include "RootSubWindow.h" +#include "NativeWindow.h" class RootWindow : public QMdiArea{ Q_OBJECT @@ -54,10 +55,8 @@ public slots: void ChangeWallpaper(QString id, RootWindow::ScaleType scale, QString file); //Note: for "SingleColor" scaling the "file" variable should be "rgb(R,G,B)" or "#hexcode" - void NewWindow(WId win, Qt::WindowFlags flags = Qt::WindowFlags()); - void ShowWindow(WId win); - void HideWindow(WId win); - void CloseWindow(WId win); + void NewWindow(NativeWindow*); + void CloseWindow(WId); //automatically connected for any new native window private slots: diff --git a/src-qt5/core/libLumina/RootWindow.pri b/src-qt5/core/libLumina/RootWindow.pri index fac1992d..35e0e770 100644 --- a/src-qt5/core/libLumina/RootWindow.pri +++ b/src-qt5/core/libLumina/RootWindow.pri @@ -8,5 +8,6 @@ HEADERS *= $${PWD}/RootWindow.h \ INCLUDEPATH *= ${PWD} -# include LUtils and LuminaX11 +# include other library dependencies include(LUtils.pri) +include(NativeWindow.pri); -- cgit