aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/libLumina/NativeWindowSystem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/core/libLumina/NativeWindowSystem.cpp')
-rw-r--r--src-qt5/core/libLumina/NativeWindowSystem.cpp221
1 files changed, 221 insertions, 0 deletions
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
+
+}
bgstack15