aboutsummaryrefslogtreecommitdiff
path: root/src-qt5
diff options
context:
space:
mode:
authorKen Moore <ken@ixsystems.com>2017-02-03 13:40:36 -0500
committerKen Moore <ken@ixsystems.com>2017-02-03 13:40:36 -0500
commit5597b2a289a8bea9ddae94b699afa370f3b0300c (patch)
tree5de649cdf01579bd4b9b7a43c2c9b4b01f72c543 /src-qt5
parentTry to fix the tiling high-DPI wallpaper issue. (diff)
downloadlumina-5597b2a289a8bea9ddae94b699afa370f3b0300c.tar.gz
lumina-5597b2a289a8bea9ddae94b699afa370f3b0300c.tar.bz2
lumina-5597b2a289a8bea9ddae94b699afa370f3b0300c.zip
Commit my work-in-progress on a new NativeWindowSystem class.
This will be a replacement for the current LuminaX11 class usage in the desktop, with a generic Qt5 API that talks to the X11/Wayland subsystems in the background.
Diffstat (limited to 'src-qt5')
-rw-r--r--src-qt5/core/libLumina/LuminaX11.cpp12
-rw-r--r--src-qt5/core/libLumina/LuminaX11.h1
-rw-r--r--src-qt5/core/libLumina/NativeWindow.h23
-rw-r--r--src-qt5/core/libLumina/NativeWindowSystem.cpp221
-rw-r--r--src-qt5/core/libLumina/NativeWindowSystem.h92
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.cpp13
6 files changed, 354 insertions, 8 deletions
diff --git a/src-qt5/core/libLumina/LuminaX11.cpp b/src-qt5/core/libLumina/LuminaX11.cpp
index ee882f7f..e9eb4b7c 100644
--- a/src-qt5/core/libLumina/LuminaX11.cpp
+++ b/src-qt5/core/libLumina/LuminaX11.cpp
@@ -1470,7 +1470,17 @@ void LXCB::WM_ICCCM_SetProtocols(WId win, LXCB::ICCCM_PROTOCOLS flags){
// _NET_SUPPORTED (Root)
void LXCB::WM_Set_Root_Supported(){
//NET_WM standards (ICCCM implied - no standard way to list those)
- xcb_atom_t list[] = {};
+ xcb_atom_t list[] = {EWMH._NET_WM_NAME,
+ EWMH._NET_WM_ICON,
+ EWMH._NET_WM_ICON_NAME,
+ EWMH._NET_WM_DESKTOP,
+ /*_NET_WINDOW_TYPE (and all the various types)*/
+ EWMH._NET_WM_WINDOW_TYPE, EWMH._NET_WM_WINDOW_TYPE_DESKTOP, EWMH._NET_WM_WINDOW_TYPE_DOCK,
+ EWMH._NET_WM_WINDOW_TYPE_TOOLBAR, EWMH._NET_WM_WINDOW_TYPE_MENU, EWMH._NET_WM_WINDOW_TYPE_UTILITY,
+ EWMH._NET_WM_WINDOW_TYPE_SPLASH, EWMH._NET_WM_WINDOW_TYPE_DIALOG, EWMH._NET_WM_WINDOW_TYPE_NORMAL,
+ EWMH._NET_WM_WINDOW_TYPE_DROPDOWN_MENU, EWMH._NET_WM_WINDOW_TYPE_POPUP_MENU, EWMH._NET_WM_WINDOW_TYPE_TOOLTIP,
+ EWMH._NET_WM_WINDOW_TYPE_NOTIFICATION, EWMH._NET_WM_WINDOW_TYPE_COMBO, EWMH._NET_WM_WINDOW_TYPE_DND,
+ };
xcb_ewmh_set_supported(&EWMH, QX11Info::appScreen(), 0,list);
}
diff --git a/src-qt5/core/libLumina/LuminaX11.h b/src-qt5/core/libLumina/LuminaX11.h
index dd9f8213..2f66ce06 100644
--- a/src-qt5/core/libLumina/LuminaX11.h
+++ b/src-qt5/core/libLumina/LuminaX11.h
@@ -23,7 +23,6 @@
#include <QObject>
#include <QFlags>
-
#include <xcb/xcb_ewmh.h>
//SYSTEM TRAY STANDARD DEFINITIONS
diff --git a/src-qt5/core/libLumina/NativeWindow.h b/src-qt5/core/libLumina/NativeWindow.h
index c4fdbb47..59b955c3 100644
--- a/src-qt5/core/libLumina/NativeWindow.h
+++ b/src-qt5/core/libLumina/NativeWindow.h
@@ -24,21 +24,29 @@
class NativeWindow : public QObject{
Q_OBJECT
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, /*null*/
MinSize, /*QSize*/
MaxSize, /*QSize*/
- Size, /*int*/
+ Size, /*QSize*/
+ GlobalPos, /*QPoint*/
Title, /*QString*/
ShortTitle, /*QString*/
Icon, /*QIcon*/
Name, /*QString*/
Workspace, /*int*/
- WindowFlags, /*Qt::WindowFlags*/
+ States, /*QList<NativeWindow::State> : Current state of the window */
+ WinTypes, /*QList<NativeWindow::Type> : Current type of window (typically does not change)*/
+ WinActions, /*QList<NativeWindow::Action> : Current actions that the window allows (Managed/set by the WM)*/
Active, /*bool*/
Visible /*bool*/
};
+
NativeWindow(WId id);
~NativeWindow();
@@ -58,11 +66,14 @@ signals:
void PropertyChanged(NativeWindow::Property, QVariant);
void WindowClosed(WId);
- //Action Requests (not automatically emitted)
+ //Action Requests (not automatically emitted - typically used to ask the WM to do something)
//Note: "WId" should be the NativeWindow id()
- void RequestActivate(WId);
- void RequestClose(WId);
-
+ void RequestActivate(WId); //Activate the window
+ void RequestClose(WId); //Close the window
+ void RequestSetVisible(WId, bool); //Minimize/restore visiblility
+ void RequestSetGeometry(WId, QRect); //Register the location/size of the window
+ void RequestSetFrameExtents(WId, QList<int>); //Register the size of the frame around the window [Left,Right, Top,Bottom] in pixels
+
// System Tray Icon Embed/Unembed Requests
//void RequestEmbed(WId, QWidget*);
//void RequestUnEmbed(WId, QWidget*);
diff --git a/src-qt5/core/libLumina/NativeWindowSystem.cpp b/src-qt5/core/libLumina/NativeWindowSystem.cpp
new file mode 100644
index 00000000..c8e6d483
--- /dev/null
+++ b/src-qt5/core/libLumina/NativeWindowSystem.cpp
@@ -0,0 +1,221 @@
+//===========================================
+// 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 the XCB version of the NativeWindowSystem class,
+// used for interacting with the X11 display system on BSD/Linux/Unix systems
+//===========================================
+#include "NativeWindowSystem.h"
+
+//Additional Qt includes
+#include <QX11Info>
+#include <QDebug>
+
+//XCB Library functions
+#include <xcb/xcb_ewmh.h>
+
+//XCB Library includes
+#include <xcb/xcb.h>
+#include <xcb/xcb_atom.h>
+#include <xcb/xproto.h>
+#include <xcb/xcb_ewmh.h>
+#include <xcb/xcb_icccm.h>
+#include <xcb/xcb_image.h>
+#include <xcb/xcb_aux.h>
+#include <xcb/composite.h>
+#include <xcb/damage.h>
+
+//XLib includes (XCB Damage lib does not appear to register for damage events properly)
+#include <X11/extensions/Xdamage.h>
+
+//SYSTEM TRAY STANDARD DEFINITIONS
+#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
+#define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+#define SYSTEM_TRAY_BEGIN_MESSAGE 1
+#define SYSTEM_TRAY_CANCEL_MESSAGE 2
+
+#define URGENCYHINT (1L << 8) //For window urgency detection
+
+#define ROOT_WIN_EVENT_MASK (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \
+ XCB_EVENT_MASK_BUTTON_PRESS | \
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY | \
+ XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \
+ XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \
+ XCB_EVENT_MASK_POINTER_MOTION | \
+ XCB_EVENT_MASK_PROPERTY_CHANGE | \
+ XCB_EVENT_MASK_FOCUS_CHANGE | \
+ XCB_EVENT_MASK_ENTER_WINDOW)
+
+//Internal XCB private objects class
+class NativeWindowSystem::p_objects{
+public:
+ xcb_ewmh_connection_t EWMH; //This is where all the screen info and atoms are located
+ QHash<QString, xcb_atom_t> ATOMS;
+ xcb_screen_t *root_screen;
+ xcb_window_t root_window, wm_window, tray_window;
+
+ //Functions for setting up these objects as needed
+ bool init_ATOMS(){
+ QStringList atoms;
+ atoms << "WM_TAKE_FOCUS" << "WM_DELETE_WINDOW" << "WM_PROTOCOLS" << "WM_CHANGE_STATE" << "_NET_SYSTEM_TRAY_OPCODE" << "_NET_SYSTEM_TRAY_ORIENTATION" << "_NET_SYSTEM_TRAY_VISUAL" << QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(QX11Info::appScreen()));
+ //Create all the requests for the atoms
+ QList<xcb_intern_atom_reply_t*> reply;
+ for(int i=0; i<atoms.length(); i++){
+ reply << xcb_intern_atom_reply(QX11Info::connection(), \
+ xcb_intern_atom(QX11Info::connection(), 0, atoms[i].length(), atoms[i].toLocal8Bit()), NULL);
+ }
+ //Now evaluate all the requests and save the atoms
+ for(int i=0; i<reply.length(); i++){ //NOTE: this will always be the same length as the "atoms" list
+ if(reply[i]!=0){
+ obj->ATOMS.insert(atoms[i], reply[i]->atom);
+ free(reply[i]); //done with this reply
+ }else{
+ //Invalid atom - could not be created
+ qDebug() << "Could not initialize XCB atom:" << atoms[i];
+ }
+ } //loop over reply
+ return (obj->ATOMS.keys.length() == atoms.length());
+ }
+
+ bool register_wm(){
+ uint32_t value_list[1] = {ROOT_WIN_EVENT_MASK};
+ xcb_generic_error_t *status = xcb_request_check( QX11Info::connection(), xcb_change_window_attributes_checked(QX11Info::connection(), root_window, XCB_CW_EVENT_MASK, value_list));
+ if(status!=0){ return false; }
+ uint32_t params[] = {1};
+ wm_window = xcb_generate_id(QX11Info::connection()); //need a new ID
+ xcb_create_window(QX11Info::connection(), root_screen->root_depth, \
+ win, root_window, -1, -1, 1, 1, 0, \
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, root_screen->root_visual, \
+ XCB_CW_OVERRIDE_REDIRECT, params);
+ if(wm_window==0){ return false; }
+ //Set the _NET_SUPPORTING_WM property on the root window first
+ xcb_ewmh_set_supporting_wm_check(&EWMH, root_window, wm_window);
+ //Also set this property on the child window (pointing to itself)
+ xcb_ewmh_set_supporting_wm_check(&EWMH, wm_window, wm_window);
+ //Now also setup the root event mask on the wm_window
+ status = xcb_request_check( QX11Info::connection(), xcb_change_window_attributes_checked(QX11Info::connection(), wm_window, XCB_CW_EVENT_MASK, value_list));
+ if(status!=0){ return false; }
+ return true;
+ }
+
+ bool startSystemTray{
+ xcb_atom_t _NET_SYSTEM_TRAY_S = ATOMS.value(QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(QX11Info::appScreen())) );
+ //Make sure that there is no other system tray running
+ xcb_get_selection_owner_reply_t *ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \
+ xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL);
+ if(ownreply==0){
+ qWarning() << " - Could not get owner selection reply";
+ return false;
+ }else if(ownreply->owner != 0){
+ free(ownreply);
+ qWarning() << " - An alternate system tray is currently in use";
+ return false;
+ }
+ free(ownreply);
+ //Now create the window to use (just offscreen)
+ //TODO
+ }
+
+}; //end private objects class
+
+
+//inline functions for setting up the internal objects
+
+
+// === PUBLIC ===
+NativeWindowSystem::NativeWindowSystem() : QObject(){
+ obj = 0;
+}
+
+NativeWindowSystem::~NativeWindowSystem(){
+ xcb_ewmh_connection_wipe(obj->EWMH);
+ free(obj);
+}
+
+//Overarching start/stop functions
+bool NativeWindowSystem::start(){
+ //Initialize the XCB/EWMH objects
+ if(obj==0){
+ obj = new p_objects(); } //instantiate the private objects
+ obj->wm_window = 0;
+ obj->tray_window = 0;
+ xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &obj->EWMH);
+ if(!xcb_ewmh_init_atoms_replies(&obj->EWMH, cookie, NULL) ){
+ qDebug() << "Error with XCB atom initializations";
+ return false;
+ }
+ obj->root_screen = xcb_aux_get_screen(QX11Info::connection(), QX11Info::appScreen());
+ obj->root_window = obj->root_screen->root; //simplification for later - minor duplication of memory (unsigned int)
+ //Initialize all the extra atoms that the EWMH object does not have
+ if( !obj->init_ATOMS() ){ return false; }
+ } //Done with private object init
+
+ return true;
+}
+
+void NativeWindowSystem::stop(){
+
+}
+
+// === PRIVATE ===
+void NativeWindowSystem::UpdateWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props){
+
+}
+
+// === PUBLIC SLOTS ===
+//These are the slots which are only used by the desktop system itself or the NativeWindowEventFilter
+void NativeWindowSystem::RegisterVirtualRoot(WId){
+
+}
+
+//NativeWindowEventFilter interactions
+void NativeWindowSystem::NewWindowDetected(WId){
+
+}
+
+void NativeWindowSystem::WindowCloseDetected(WId){
+
+}
+
+void NativeWindowSystem::WindowPropertyChanged(WId, NativeWindow::Property){
+
+}
+
+void NativeWindowSystem::NewKeyPress(int keycode){
+
+}
+
+void NativeWindowSystem::NewKeyRelease(int keycode){
+
+}
+
+void NativeWindowSystem::NewMousePress(int buttoncode){
+
+}
+
+void NativeWindowSystem::NewMouseRelease(int buttoncode){
+
+}
+
+// === PRIVATE SLOTS ===
+//These are the slots which are built-in and automatically connected when a new NativeWindow is created
+void NativeWindowSystem::RequestActivate(WId){
+
+}
+void NativeWindowSystem::RequestClose(WId){
+
+}
+
+void NativeWindowSystem::RequestSetVisible(WId, bool){
+
+}
+void NativeWindowSystem::RequestSetGeometry(WId, QRect){
+
+}
+void NativeWindowSystem::RequestSetFrameExtents(WId, QList<int>){
+ //[Left,Top,Right,Bottom] in pixels
+
+}
diff --git a/src-qt5/core/libLumina/NativeWindowSystem.h b/src-qt5/core/libLumina/NativeWindowSystem.h
new file mode 100644
index 00000000..ef169059
--- /dev/null
+++ b/src-qt5/core/libLumina/NativeWindowSystem.h
@@ -0,0 +1,92 @@
+//===========================================
+// 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 Qt5/Lumina wrapper around native graphics system calls
+// It is primarily designed around the creation/modification of instances of
+// the "NativeWindow" class for passing information around
+//===========================================
+#ifndef _LUMINA_NATIVE_WINDOW_SYSTEM_H
+#define _LUMINA_NATIVE_WINDOW_SYSTEM_H
+
+#include "NativeWindow.h"
+
+class NativeWindowSystem : public QObject{
+ Q_OBJECT
+private:
+ QList<NativeWindow*> NWindows;
+ QList<NativeWindow*> TWindows;
+
+ //Simplifications to find an already-created window object
+ NativeWindow* findWindow(WId id){
+ for(int i=0; i<NWindows.length(); i++){
+ if(id==NWindows[i]->id()){ return NWindows[i]; }
+ }
+ }
+
+ NativeWindow* findTrayWindow(WId id){
+ for(int i=0; i<TWindows.length(); i++){
+ if(id==TWindows[i]->id()){ return TWindows[i]; }
+ }
+ }
+
+ //Now define a simple private_objects class so that each implementation
+ // has a storage container for placing private objects as needed
+ class p_objects;
+ p_objects* obj;
+
+ // Since some properties may be easier to update in bulk
+ // let the native system interaction do them in whatever logical groups are best
+ void UpdateWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props);
+
+public:
+ NativeWindowSystem();
+ ~NativeWindowSystem();
+
+ //Overarching start/stop functions
+ bool start();
+ void stop();
+
+ //General-purpose listing functions
+ QList<NativeWindow*> currentWindows(){ return NWindows; }
+
+public slots:
+ //These are the slots which are typically only used by the desktop system itself or the NativeWindowEventFilter
+
+ //RootWindow interactions
+ void RegisterVirtualRoot(WId);
+ //void GoToWorkspace(int);
+ //void RegisterWorkspaces(QStringList); //Names of workspaces, in ascending order
+ //void RegisterKnownInteractions();
+
+
+ //NativeWindowEventFilter interactions
+ void NewWindowDetected(WId); //will automatically create the new NativeWindow object
+ void WindowCloseDetected(WId); //will update the lists and make changes if needed
+ void WindowPropertyChanged(WId, NativeWindow::Property); //will rescan the window and update the object as needed
+ void NewKeyPress(int keycode);
+ void NewKeyRelease(int keycode);
+ void NewMousePress(int buttoncode);
+ void NewMouseRelease(int buttoncode);
+ void CheckDamageID(WId);
+
+private slots:
+ //These are the slots which are built-in and automatically connected when a new NativeWindow is created
+ void RequestActivate(WId);
+ void RequestClose(WId);
+ void RequestSetVisible(WId, bool);
+ void RequestSetGeometry(WId, QRect);
+ void RequestSetFrameExtents(WId, QList<int>); //[Left,Right,Top,Bottom] in pixels
+
+signals:
+ void NewWindowAvailable(NativeWindow*);
+ void NewInputEvent(); //a mouse or keypress was detected (lock-state independent);
+ void NewKeyPress(int); //only emitted if lockstate = false
+ void NewKeyRelease(int); //only emitted if lockstate = false
+ void NewMousePress(Qt::MouseButton); //only emitted if lockstate = false
+
+};
+
+#endif
diff --git a/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.cpp b/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.cpp
index 27e94737..7031f3df 100644
--- a/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.cpp
+++ b/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.cpp
@@ -53,6 +53,7 @@ void EventFilter::start(){
XCB->setupEventsForRoot(WMFlag);
XCB->WM_Set_Supporting_WM(WMFlag);
+ XCB->WM_Set_Root_Supported(); //announce all the various options that the WM supports
static_cast<XCBEventFilter*>(EF)->startSystemTray();
QCoreApplication::instance()->flush();
@@ -482,6 +483,18 @@ void XCBEventFilter::ParsePropertyEvent(xcb_property_notify_event_t *ev){
}else if(ev->atom == obj->XCB->EWMH._NET_WM_ICON){
qDebug() << " - Found _NET_WM_ICON atom";
nwin->setProperty(NativeWindow::Icon, obj->XCB->WM_Get_Icon(nwin->id()));
+ }else if(ev->atom == obj->XCB->EWMH._NET_WM_ICON_NAME){
+ qDebug() << " - Found _NET_WM_ICON_NAME atom";
+ nwin->setProperty(NativeWindow::ShortTitle, obj->XCB->WM_Get_Icon_Name(nwin->id()));
+ }else if(ev->atom == obj->XCB->EWMH._NET_WM_DESKTOP){
+ qDebug() << " - Found _NET_WM_DESKTOP atom";
+ nwin->setProperty(NativeWindow::Workspace, obj->XCB->WM_Get_Desktop(nwin->id()));
+ }else if(ev->atom == obj->XCB->EWMH._NET_WM_WINDOW_TYPE ){
+ qDebug() << " - Found _NET_WM_WINDOW_TYPE atom";
+
+ }else if( ev->atom == obj->XCB->EWMH._NET_WM_STATE){
+ qDebug() << " - Found _NET_WM_STATE atom";
+
}
}
bgstack15