aboutsummaryrefslogtreecommitdiff
path: root/src-qt5
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5')
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.cpp267
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.h164
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri6
3 files changed, 435 insertions, 2 deletions
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.cpp
new file mode 100644
index 00000000..a1b8dbbb
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.cpp
@@ -0,0 +1,267 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2017-2018, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "NativeWindowObject.h"
+#include <QQmlEngine>
+#include <QDebug>
+
+// == QML Type Registration ==
+void NativeWindowObject::RegisterType(){
+ static bool done = false;
+ if(done){ return; }
+ done=true;
+ qmlRegisterType<NativeWindowObject>("Lumina.Backend.NativeWindowObject",2,0, "NativeWindowObject");
+}
+
+// === PUBLIC ===
+NativeWindowObject::NativeWindowObject(WId id) : QObject(){
+ winid = id;
+ frameid = 0;
+ dmgID = 0;
+}
+
+NativeWindowObject::~NativeWindowObject(){
+ hash.clear();
+}
+
+void NativeWindowObject::addFrameWinID(WId fid){
+ frameid = fid;
+}
+
+void NativeWindowObject::addDamageID(unsigned int dmg){
+ dmgID = dmg;
+}
+
+bool NativeWindowObject::isRelatedTo(WId tmp){
+ return (relatedTo.contains(tmp) || winid == tmp || frameid == tmp);
+}
+
+WId NativeWindowObject::id(){
+ return winid;
+}
+
+WId NativeWindowObject::frameId(){
+ return frameid;
+}
+
+unsigned int NativeWindowObject::damageId(){
+ return dmgID;
+}
+
+QVariant NativeWindowObject::property(NativeWindowObject::Property prop){
+ if(hash.contains(prop)){ return hash.value(prop); }
+ else if(prop == NativeWindowObject::RelatedWindows){ return QVariant::fromValue(relatedTo); }
+ return QVariant(); //null variant
+}
+
+void NativeWindowObject::setProperty(NativeWindowObject::Property prop, QVariant val, bool force){
+ if(prop == NativeWindowObject::RelatedWindows){ relatedTo = val.value< QList<WId> >(); }
+ else if(prop == NativeWindowObject::None || (!force && hash.value(prop)==val)){ return; }
+ else{ hash.insert(prop, val); }
+ emitSinglePropChanged(prop);
+ emit PropertiesChanged(QList<NativeWindowObject::Property>() << prop, QList<QVariant>() << val);
+}
+
+void NativeWindowObject::setProperties(QList<NativeWindowObject::Property> props, QList<QVariant> vals, bool force){
+ for(int i=0; i<props.length(); i++){
+ if(i>=vals.length()){ props.removeAt(i); i--; continue; } //no corresponding value for this property
+ if(props[i] == NativeWindowObject::None || (!force && (hash.value(props[i]) == vals[i])) ){ props.removeAt(i); vals.removeAt(i); i--; continue; } //Invalid property or identical value
+ hash.insert(props[i], vals[i]);
+ emitSinglePropChanged(props[i]);
+ }
+ emit PropertiesChanged(props, vals);
+}
+
+void NativeWindowObject::requestProperty(NativeWindowObject::Property prop, QVariant val, bool force){
+ if(prop == NativeWindowObject::None || prop == NativeWindowObject::RelatedWindows || (!force && hash.value(prop)==val) ){ return; }
+ emit RequestPropertiesChange(winid, QList<NativeWindowObject::Property>() << prop, QList<QVariant>() << val);
+}
+
+void NativeWindowObject::requestProperties(QList<NativeWindowObject::Property> props, QList<QVariant> vals, bool force){
+ //Verify/adjust inputs as needed
+ for(int i=0; i<props.length(); i++){
+ if(i>=vals.length()){ props.removeAt(i); i--; continue; } //no corresponding value for this property
+ if(props[i] == NativeWindowObject::None || props[i] == NativeWindowObject::RelatedWindows || (!force && hash.value(props[i])==vals[i]) ){ props.removeAt(i); vals.removeAt(i); i--; continue; } //Invalid property or identical value
+ /*if( (props[i] == NativeWindowObject::Visible || props[i] == NativeWindowObject::Active) && frameid !=0){
+ //These particular properties needs to change the frame - not the window itself
+ emit RequestPropertiesChange(frameid, QList<NativeWindowObject::Property>() << props[i], QList<QVariant>() << vals[i]);
+ props.removeAt(i); vals.removeAt(i); i--;
+ }*/
+ }
+ emit RequestPropertiesChange(winid, props, vals);
+}
+
+QRect NativeWindowObject::geometry(){
+ //Calculate the "full" geometry of the window + frame (if any)
+ //Check that the size is between the min/max limitations
+ QSize size = hash.value(NativeWindowObject::Size).toSize();
+ QSize min = hash.value(NativeWindowObject::MinSize).toSize();
+ QSize max = hash.value(NativeWindowObject::MaxSize).toSize();
+ if(min.isValid() && min.width() > size.width() ){ size.setWidth(min.width()); }
+ if(min.isValid() && min.height() > size.height()){ size.setHeight(min.height()); }
+ if(max.isValid() && max.width() < size.width() && max.width()>min.width()){ size.setWidth(max.width()); }
+ if(max.isValid() && max.height() < size.height() && max.height()>min.height()){ size.setHeight(max.height()); }
+ //Assemble the full geometry
+ QRect geom( hash.value(NativeWindowObject::GlobalPos).toPoint(), size );
+ //Now adjust the window geom by the frame margins
+ QList<int> frame = hash.value(NativeWindowObject::FrameExtents).value< QList<int> >(); //Left,Right,Top,Bottom
+ //qDebug() << "Calculate Geometry:" << geom << frame;
+ if(frame.length()==4){
+ geom = geom.adjusted( -frame[0], -frame[2], frame[1], frame[3] );
+ }
+ //qDebug() << " - Total:" << geom;
+ return geom;
+}
+
+// QML ACCESS FUNCTIONS (shortcuts for particular properties in a format QML can use)
+QImage NativeWindowObject::winImage(){
+ return this->property(NativeWindowObject::WinImage).value<QImage>();
+}
+
+QString NativeWindowObject::name(){
+ return this->property(NativeWindowObject::Name).toString();
+}
+
+QString NativeWindowObject::title(){
+ return this->property(NativeWindowObject::Title).toString();
+}
+
+QString NativeWindowObject::shortTitle(){
+ return this->property(NativeWindowObject::ShortTitle).toString();
+}
+
+QIcon NativeWindowObject::icon(){
+ return this->property(NativeWindowObject::Name).value<QIcon>();
+}
+
+//QML Button states
+bool NativeWindowObject::showCloseButton(){
+ QList<NativeWindowObject::Type> types = this->property(NativeWindowObject::WinTypes).value<QList < NativeWindowObject::Type> >();
+ QList<NativeWindowObject::Type> badtypes;
+ badtypes << NativeWindowObject::T_DESKTOP << NativeWindowObject::T_TOOLBAR << NativeWindowObject::T_MENU \
+ << NativeWindowObject::T_SPLASH << NativeWindowObject::T_DROPDOWN_MENU << NativeWindowObject::T_POPUP_MENU \
+ << NativeWindowObject::T_NOTIFICATION << NativeWindowObject::T_COMBO << NativeWindowObject::T_DND;
+ for(int i=0; i<types.length(); i++){
+ if(badtypes.contains(types[i])){ return false; }
+ }
+ return true;
+}
+
+bool NativeWindowObject::showMaxButton(){
+ QList<NativeWindowObject::Type> types = this->property(NativeWindowObject::WinTypes).value<QList < NativeWindowObject::Type> >();
+ QList<NativeWindowObject::Type> badtypes;
+ badtypes << NativeWindowObject::T_DESKTOP << NativeWindowObject::T_TOOLBAR << NativeWindowObject::T_MENU \
+ << NativeWindowObject::T_SPLASH << NativeWindowObject::T_DROPDOWN_MENU << NativeWindowObject::T_POPUP_MENU \
+ << NativeWindowObject::T_NOTIFICATION << NativeWindowObject::T_COMBO << NativeWindowObject::T_DND;
+ for(int i=0; i<types.length(); i++){
+ if(badtypes.contains(types[i])){ return false; }
+ }
+ return true;
+}
+
+bool NativeWindowObject::showMinButton(){
+ QList<NativeWindowObject::Type> types = this->property(NativeWindowObject::WinTypes).value<QList < NativeWindowObject::Type> >();
+ QList<NativeWindowObject::Type> badtypes;
+ badtypes << NativeWindowObject::T_DESKTOP << NativeWindowObject::T_TOOLBAR << NativeWindowObject::T_MENU \
+ << NativeWindowObject::T_SPLASH << NativeWindowObject::T_DROPDOWN_MENU << NativeWindowObject::T_POPUP_MENU \
+ << NativeWindowObject::T_NOTIFICATION << NativeWindowObject::T_COMBO << NativeWindowObject::T_DND << NativeWindowObject::T_DIALOG;
+ for(int i=0; i<types.length(); i++){
+ if(badtypes.contains(types[i])){ return false; }
+ }
+ return true;
+}
+
+bool NativeWindowObject::showTitlebar(){
+ QList<NativeWindowObject::Type> types = this->property(NativeWindowObject::WinTypes).value<QList < NativeWindowObject::Type> >();
+ QList<NativeWindowObject::Type> badtypes;
+ badtypes << NativeWindowObject::T_DESKTOP << NativeWindowObject::T_TOOLBAR << NativeWindowObject::T_MENU \
+ << NativeWindowObject::T_SPLASH << NativeWindowObject::T_DROPDOWN_MENU << NativeWindowObject::T_POPUP_MENU \
+ << NativeWindowObject::T_NOTIFICATION << NativeWindowObject::T_COMBO << NativeWindowObject::T_DND;
+ for(int i=0; i<types.length(); i++){
+ if(badtypes.contains(types[i])){ return false; }
+ }
+ return true;
+}
+
+bool NativeWindowObject::showGenericButton(){
+ QList<NativeWindowObject::Type> types = this->property(NativeWindowObject::WinTypes).value<QList < NativeWindowObject::Type> >();
+ QList<NativeWindowObject::Type> badtypes;
+ badtypes << NativeWindowObject::T_DESKTOP << NativeWindowObject::T_TOOLBAR << NativeWindowObject::T_MENU \
+ << NativeWindowObject::T_SPLASH << NativeWindowObject::T_DROPDOWN_MENU << NativeWindowObject::T_POPUP_MENU \
+ << NativeWindowObject::T_NOTIFICATION << NativeWindowObject::T_COMBO << NativeWindowObject::T_DND;
+ for(int i=0; i<types.length(); i++){
+ if(badtypes.contains(types[i])){ return false; }
+ }
+ return true;
+}
+
+bool NativeWindowObject::showWindowFrame(){
+ QList<NativeWindowObject::Type> types = this->property(NativeWindowObject::WinTypes).value<QList < NativeWindowObject::Type> >();
+ QList<NativeWindowObject::Type> badtypes;
+ badtypes << NativeWindowObject::T_DESKTOP << NativeWindowObject::T_TOOLBAR << NativeWindowObject::T_MENU \
+ << NativeWindowObject::T_SPLASH << NativeWindowObject::T_DROPDOWN_MENU << NativeWindowObject::T_POPUP_MENU \
+ << NativeWindowObject::T_NOTIFICATION << NativeWindowObject::T_COMBO << NativeWindowObject::T_DND;
+ for(int i=0; i<types.length(); i++){
+ if(badtypes.contains(types[i])){ return false; }
+ }
+ return true;
+}
+
+//QML Window States
+bool NativeWindowObject::isSticky(){
+ return (this->property(NativeWindowObject::Workspace).toInt()<0 || this->property(NativeWindowObject::States).value<QList<NativeWindowObject::State> >().contains(NativeWindowObject::S_STICKY) );
+}
+
+//QML Geometry reporting
+QRect NativeWindowObject::frameGeometry(){
+ return geometry();
+}
+
+QRect NativeWindowObject::imageGeometry(){
+ QRect geom( this->property(NativeWindowObject::GlobalPos).toPoint(), this->property(NativeWindowObject::Size).toSize() );
+ return geom;
+}
+
+// ==== PUBLIC SLOTS ===
+void NativeWindowObject::toggleVisibility(){
+ setProperty(NativeWindowObject::Visible, !property(NativeWindowObject::Visible).toBool() );
+}
+
+void NativeWindowObject::requestClose(){
+ emit RequestClose(winid);
+}
+
+void NativeWindowObject::requestKill(){
+ emit RequestKill(winid);
+}
+
+void NativeWindowObject::requestPing(){
+ emit RequestPing(winid);
+}
+
+// ==== PRIVATE ====
+void NativeWindowObject::emitSinglePropChanged(NativeWindowObject::Property prop){
+ //Simple switch to emit the QML-usable signals as properties are changed
+ switch(prop){
+ case NativeWindowObject::Name:
+ emit nameChanged(); break;
+ case NativeWindowObject::Title:
+ emit titleChanged(); break;
+ case NativeWindowObject::ShortTitle:
+ emit shortTitleChanged(); break;
+ case NativeWindowObject::Icon:
+ emit iconChanged(); break;
+ case NativeWindowObject::Workspace:
+ case NativeWindowObject::States:
+ emit stickyChanged(); break;
+ case NativeWindowObject::WinImage:
+ emit winImageChanged(); break;
+ case NativeWindowObject::WinTypes:
+ emit winTypeChanged(); break;
+ default:
+ break; //do nothing otherwise
+ }
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.h
new file mode 100644
index 00000000..8a8504aa
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.h
@@ -0,0 +1,164 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2017-2018, 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_SOURCES_NATIVE_WINDOW_OBJECT_H
+#define _LUMINA_SOURCES_NATIVE_WINDOW_OBJECT_H
+#include "global-includes.h"
+
+class NativeWindowObject : public QObject{
+ Q_OBJECT
+ // QML-ACCESSIBLE PROPERTIES
+ Q_PROPERTY( QImage winImage READ winImage NOTIFY winImageChanged)
+ Q_PROPERTY( QString name READ name NOTIFY nameChanged)
+ Q_PROPERTY( QString title READ title NOTIFY titleChanged)
+ Q_PROPERTY( QString shortTitle READ shortTitle NOTIFY shortTitleChanged)
+ Q_PROPERTY( QIcon icon READ icon NOTIFY iconChanged)
+ Q_PROPERTY( bool sticky READ isSticky NOTIFY stickyChanged)
+ //Button/Titlebar visibility
+ Q_PROPERTY( bool showCloseButton READ showCloseButton NOTIFY winTypeChanged)
+ Q_PROPERTY( bool showMinButton READ showMinButton NOTIFY winTypeChanged)
+ Q_PROPERTY( bool showMaxButton READ showMaxButton NOTIFY winTypeChanged)
+ Q_PROPERTY( bool showTitlebar READ showTitlebar NOTIFY winTypeChanged)
+ Q_PROPERTY( bool showGenericButton READ showGenericButton NOTIFY winTypeChanged)
+ Q_PROPERTY( bool showWindowFrame READ showWindowFrame NOTIFY winTypeChanged)
+ //Geometry information
+ Q_PROPERTY( QRect frameGeometry READ frameGeometry NOTIFY geomChanged)
+ Q_PROPERTY( QRect imageGeometry READ imageGeometry NOTIFY geomChanged)
+
+public:
+ enum State{ S_MODAL, S_STICKY, S_MAX_VERT, S_MAX_HORZ, S_SHADED, S_SKIP_TASKBAR, S_SKIP_PAGER, S_HIDDEN, S_FULLSCREEN, S_ABOVE, S_BELOW, S_ATTENTION };
+ enum Type{T_DESKTOP, T_DOCK, T_TOOLBAR, T_MENU, T_UTILITY, T_SPLASH, T_DIALOG, T_DROPDOWN_MENU, T_POPUP_MENU, T_TOOLTIP, T_NOTIFICATION, T_COMBO, T_DND, T_NORMAL };
+ enum Action {A_MOVE, A_RESIZE, A_MINIMIZE, A_SHADE, A_STICK, A_MAX_VERT, A_MAX_HORZ, A_FULLSCREEN, A_CHANGE_DESKTOP, A_CLOSE, A_ABOVE, A_BELOW};
+
+ enum Property{ /*QVariant Type*/
+ None=0, /*null*/
+ MinSize=1, /*QSize*/
+ MaxSize=2, /*QSize*/
+ Size=3, /*QSize*/
+ GlobalPos=4, /*QPoint*/
+ Title=5, /*QString*/
+ ShortTitle=6, /*QString*/
+ Icon=7, /*QIcon*/
+ Name=8, /*QString*/
+ Workspace=9, /*int*/
+ States=10, /*QList<NativeWindowObject::State> : Current state of the window */
+ WinTypes=11, /*QList<NativeWindowObject::Type> : Current type of window (typically does not change)*/
+ WinActions=12, /*QList<NativeWindowObject::Action> : Current actions that the window allows (Managed/set by the WM)*/
+ FrameExtents=13, /*QList<int> : [Left, Right, Top, Bottom] in pixels */
+ RelatedWindows=14, /* QList<WId> - better to use the "isRelatedTo(WId)" function instead of reading this directly*/
+ Active=15, /*bool*/
+ Visible=16, /*bool*/
+ WinImage=17 /*QImage*/
+ };
+
+ static QList<NativeWindowObject::Property> allProperties(){
+ //Return all the available properties (excluding "None" and "FrameExtents" (WM control only) )
+ QList<NativeWindowObject::Property> props;
+ props << MinSize << MaxSize << Size << GlobalPos << Title << ShortTitle << Icon << Name << Workspace \
+ << States << WinTypes << WinActions << RelatedWindows << Active << Visible;
+ return props;
+ };
+
+ static void RegisterType();
+
+ NativeWindowObject(WId id = 0);
+ ~NativeWindowObject();
+
+ void addFrameWinID(WId);
+ void addDamageID(unsigned int);
+ bool isRelatedTo(WId);
+
+ WId id();
+ WId frameId();
+ unsigned int damageId();
+
+ //QWindow* window();
+
+ QVariant property(NativeWindowObject::Property);
+ void setProperty(NativeWindowObject::Property, QVariant, bool force = false);
+ void setProperties(QList<NativeWindowObject::Property>, QList<QVariant>, bool force = false);
+ void requestProperty(NativeWindowObject::Property, QVariant, bool force = false);
+ void requestProperties(QList<NativeWindowObject::Property>, QList<QVariant>, bool force = false);
+
+ Q_INVOKABLE QRect geometry(); //this returns the "full" geometry of the window (window + frame)
+
+ // QML ACCESS FUNCTIONS (shortcuts for particular properties in a format QML can use)
+ Q_INVOKABLE QImage winImage();
+ Q_INVOKABLE QString name();
+ Q_INVOKABLE QString title();
+ Q_INVOKABLE QString shortTitle();
+ Q_INVOKABLE QIcon icon();
+ //QML Button states
+ Q_INVOKABLE bool showCloseButton();
+ Q_INVOKABLE bool showMaxButton();
+ Q_INVOKABLE bool showMinButton();
+ Q_INVOKABLE bool showTitlebar();
+ Q_INVOKABLE bool showGenericButton();
+ Q_INVOKABLE bool showWindowFrame();
+ //QML Window States
+ Q_INVOKABLE bool isSticky();
+
+ //QML Geometry reporting
+ Q_INVOKABLE QRect frameGeometry();
+ Q_INVOKABLE QRect imageGeometry();
+
+public slots:
+ Q_INVOKABLE void toggleVisibility();
+ Q_INVOKABLE void requestClose(); //ask the app to close the window (may/not depending on activity)
+ Q_INVOKABLE void requestKill(); //ask the WM to kill the app associated with this window (harsh - only use if not responding)
+ Q_INVOKABLE void requestPing(); //ask the app if it is still active (a WindowNotResponding signal will get sent out if there is no reply);
+
+private:
+ QHash <NativeWindowObject::Property, QVariant> hash;
+ //QWindow *WIN;
+ WId winid, frameid;
+ QList<WId> relatedTo;
+ unsigned int dmgID;
+
+ void emitSinglePropChanged(NativeWindowObject::Property);
+
+signals:
+ //General Notifications
+ void PropertiesChanged(QList<NativeWindowObject::Property>, QList<QVariant>);
+ void RequestPropertiesChange(WId, QList<NativeWindowObject::Property>, QList<QVariant>);
+ void WindowClosed(WId);
+ void WindowNotResponding(WId); //will be sent out if a window does not respond to a ping request
+ void VisualChanged();
+
+ //Action Requests (not automatically emitted - typically used to ask the WM to do something)
+ //Note: "WId" should be the NativeWindowObject id()
+ void RequestClose(WId); //Close the window
+ void RequestKill(WId); //Kill the window/app (usually from being unresponsive)
+ void RequestPing(WId); //Verify that the window is still active (such as not closing after a request
+ void RequestReparent(WId, WId, QPoint); //client window, frame window, relative origin point in frame
+ // System Tray Icon Embed/Unembed Requests
+ //void RequestEmbed(WId, QWidget*);
+ //void RequestUnEmbed(WId, QWidget*);
+
+ // QML update signals
+ void winImageChanged();
+ void nameChanged();
+ void titleChanged();
+ void shortTitleChanged();
+ void iconChanged();
+ void stickyChanged();
+ void winTypeChanged();
+ void geomChanged();
+};
+
+// Declare the enumerations as Qt MetaTypes
+Q_DECLARE_METATYPE(NativeWindowObject::Type);
+Q_DECLARE_METATYPE(NativeWindowObject::Action);
+Q_DECLARE_METATYPE(NativeWindowObject::State);
+Q_DECLARE_METATYPE(NativeWindowObject::Property);
+
+#endif
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri
index 899f4968..25bdc019 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri
@@ -1,9 +1,11 @@
SOURCES *= $${PWD}/RootDesktopObject.cpp \
$${PWD}/ScreenObject.cpp \
- $${PWD}/PanelObject.cpp
+ $${PWD}/PanelObject.cpp \
+ $${PWD}/NativeWindowObject.cpp
HEADERS *= $${PWD}/RootDesktopObject.h \
$${PWD}/ScreenObject.h \
- $${PWD}/PanelObject.h
+ $${PWD}/PanelObject.h \
+ $${PWD}/NativeWindowObject.h
INCLUDEPATH *= $${PWD}
bgstack15