aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/src-cpp/NativeEventFilter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/src-cpp/NativeEventFilter.cpp')
-rw-r--r--src-qt5/src-cpp/NativeEventFilter.cpp300
1 files changed, 300 insertions, 0 deletions
diff --git a/src-qt5/src-cpp/NativeEventFilter.cpp b/src-qt5/src-cpp/NativeEventFilter.cpp
new file mode 100644
index 00000000..c13c1fc8
--- /dev/null
+++ b/src-qt5/src-cpp/NativeEventFilter.cpp
@@ -0,0 +1,300 @@
+//===========================================
+// Lumina-desktop source code
+// Copyright (c) 2015-2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "NativeEventFilter.h"
+#include <QCoreApplication>
+#include <QDebug>
+
+//#include <xcb/xcb_aux.h>
+//#include <xcb/damage.h>
+
+//==================================================
+// NOTE: All the XCB interactions and atoms are accessed via:
+// obj->XCB->EWMH.(atom name)
+// obj->XCB->(do something)
+//==================================================
+
+/*
+List of XCB response types (since almost impossible to find good docs on XCB)
+switch (xcb_generic_event_t*->response_type & ~0x80)
+case values:
+XCB_KEY_[PRESS | RELEASE]
+XCB_BUTTON_[PRESS | RELEASE]
+XCB_MOTION_NOTIFY
+XCB_ENTER_NOTIFY
+XCB_LEAVE_NOTIFY
+XCB_FOCUS_[IN | OUT]
+XCB_KEYMAP_NOTIFY
+XCB_EXPOSE
+XCB_GRAPHICS_EXPOSURE
+XCB_VISIBILITY_NOTIFY
+XCB_CREATE_NOTIFY
+XCB_DESTROY_NOTIFY
+XCB_UNMAP_NOTIFY
+XCB_MAP_[NOTIFY | REQUEST]
+XCB_REPARENT_NOTIFY
+XCB_CONFIGURE_[NOTIFY | REQUEST]
+XCB_GRAVITY_NOTIFY
+XCB_RESIZE_REQUEST
+XCB_CIRCULATE_[NOTIFY | REQUEST]
+XCB_PROPERTY_NOTIFY
+XCB_SELECTION_[CLEAR | REQUEST | NOTIFY]
+XCB_COLORMAP_NOTIFY
+XCB_CLIENT_MESSAGE
+*/
+
+//SYSTEM TRAY STANDARD DEFINITIONS
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+#define SYSTEM_TRAY_BEGIN_MESSAGE 1
+#define SYSTEM_TRAY_CANCEL_MESSAGE 2
+
+//#include <LuminaX11.h>
+#include <QX11Info>
+#include <xcb/xcb_ewmh.h>
+#include <xcb/xcb_keysyms.h>
+#include <xcb/damage.h>
+
+#define DEBUG 0
+
+//Special objects/variables for XCB parsing
+static xcb_ewmh_connection_t EWMH;
+//static LXCB *XCB = 0;
+static xcb_atom_t _NET_SYSTEM_TRAY_OPCODE = 0;
+
+inline void ParsePropertyEvent(xcb_property_notify_event_t *ev, NativeEventFilter *obj){
+ //qDebug() << "Got Property Event:" << ev->window << ev->atom;
+ NativeWindow::Property prop = NativeWindow::None;
+ //Now determine which properties are getting changed, and update the native window as appropriate
+ if(ev->atom == EWMH._NET_WM_NAME){ prop = NativeWindow::Title; }
+ else if(ev->atom == EWMH._NET_WM_ICON){ prop = NativeWindow::Icon; }
+ else if(ev->atom == EWMH._NET_WM_ICON_NAME){ prop = NativeWindow::ShortTitle; }
+ else if(ev->atom == EWMH._NET_WM_DESKTOP){ prop = NativeWindow::Workspace; }
+ else if(ev->atom == EWMH._NET_WM_WINDOW_TYPE ){ prop = NativeWindow::WinTypes; }
+ else if( ev->atom == EWMH._NET_WM_STATE){ prop = NativeWindow::States; }
+ //Send out the signal if necessary
+ if(prop!=NativeWindow::None){
+ //if(DEBUG){
+ //qDebug() << "Detected Property Change:" << ev->window << prop;
+ //}
+ obj->emit WindowPropertyChanged(ev->window, prop);
+ }else{
+ //Quick re-check of the simple properties (nothing like the icon or other graphics)
+ obj->emit WindowPropertiesChanged(ev->window, QList<NativeWindow::Property>() << NativeWindow::Title
+ << NativeWindow::ShortTitle << NativeWindow::Workspace );
+ //qDebug() << "Unknown Property Change:" << ev->window << ev->atom;
+ }
+}
+
+inline void ParseClientMessageEvent(xcb_client_message_event_t *ev, NativeEventFilter *obj){
+ NativeWindow::Property prop = NativeWindow::None;
+ QVariant val;
+ if(ev->type==EWMH._NET_WM_NAME){ prop = NativeWindow::Title; }
+ else if(ev->type==EWMH._NET_WM_ICON){ prop = NativeWindow::Icon; }
+ else if(ev->type==EWMH._NET_WM_ICON_NAME){ prop = NativeWindow::ShortTitle; }
+ else if(ev->type==EWMH._NET_WM_DESKTOP){
+ prop = NativeWindow::Workspace;
+ val = QVariant( (int) ev->data.data32[0] );
+ }else if(ev->type==EWMH._NET_WM_WINDOW_TYPE){ prop = NativeWindow::WinTypes; }
+ else if(ev->type==EWMH._NET_WM_STATE){ prop = NativeWindow::States; }
+
+ if(prop!=NativeWindow::None){
+ //if(DEBUG){
+ qDebug() << "Detected Property Change Request:" << ev->window << prop; //}
+ if(val.isNull()){ obj->emit WindowPropertyChanged(ev->window, prop); }
+ else{ obj->emit RequestWindowPropertyChange(ev->window, prop, val); }
+ }
+
+}
+
+
+//Constructor for the Event Filter wrapper
+NativeEventFilter::NativeEventFilter() : QObject(){
+ EF = new EventFilter(this);
+ if(EWMH.nb_screens <=0){
+ xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &EWMH);
+ if(!xcb_ewmh_init_atoms_replies(&EWMH, cookie, NULL) ){
+ qDebug() << "Error with XCB atom initializations";
+ }
+ }
+ if(_NET_SYSTEM_TRAY_OPCODE==0){
+ //_NET_SYSTEM_TRAY_OPCODE
+ xcb_intern_atom_cookie_t cookie = xcb_intern_atom(QX11Info::connection(), 0, 23,"_NET_SYSTEM_TRAY_OPCODE");
+ xcb_intern_atom_reply_t *r = xcb_intern_atom_reply(QX11Info::connection(), cookie, NULL);
+ if(r){
+ _NET_SYSTEM_TRAY_OPCODE = r->atom;
+ free(r);
+ }
+ }
+}
+
+void NativeEventFilter::start(){
+ if(DEBUG){ qDebug() << " - Install event filter..."; }
+ QCoreApplication::instance()->installNativeEventFilter(EF);
+ if(DEBUG){ qDebug() << " - Run request check..."; }
+
+}
+
+void NativeEventFilter::stop(){
+ QCoreApplication::instance()->installNativeEventFilter(0);
+}
+
+//=============================
+// EventFilter Class
+//=============================
+
+//Constructor for the XCB event filter
+EventFilter::EventFilter(NativeEventFilter *parent) : QAbstractNativeEventFilter(){
+ obj = parent;
+}
+
+//This function format taken directly from the Qt5.3 documentation
+bool EventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *){
+ //qDebug() << "New Event";
+ if(eventType=="xcb_generic_event_t"){
+ //Convert to known event type (for X11 systems)
+ xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message);
+ //Now parse the event and emit signals as necessary
+ switch( ev->response_type & ~0x80){
+//==============================
+// INTERACTIVITY EVENTS
+//==============================
+ case XCB_KEY_PRESS:
+ //This is a keyboard key press
+ //qDebug() << "Key Press Event"
+ obj->emit KeyPressed( ((xcb_key_press_event_t *) ev)->detail, ((xcb_key_press_event_t *) ev)->root );
+ break;
+ case XCB_KEY_RELEASE:
+ //This is a keyboard key release
+ //qDebug() << "Key Release Event";
+ obj->emit KeyReleased( ((xcb_key_release_event_t *) ev)->detail, ((xcb_key_release_event_t *) ev)->root );
+ break;
+ case XCB_BUTTON_PRESS:
+ //This is a mouse button press
+ //qDebug() << "Button Press Event";
+ obj->emit MousePressed( ((xcb_button_press_event_t *) ev)->detail, ((xcb_button_press_event_t *) ev)->root );
+ break;
+ case XCB_BUTTON_RELEASE:
+ //This is a mouse button release
+ //qDebug() << "Button Release Event";
+ obj->emit MouseReleased( ((xcb_button_release_event_t *) ev)->detail, ((xcb_button_release_event_t *) ev)->root );
+ break;
+ case XCB_MOTION_NOTIFY:
+ //This is a mouse movement event
+ if(DEBUG){ qDebug() << "Motion Notify Event"; }
+ obj->emit MouseMovement();
+ break;
+ case XCB_ENTER_NOTIFY:
+ //This is a mouse movement event when mouse goes over a new window
+ //qDebug() << "Enter Notify Event";
+ obj->emit MouseEnterWindow( ((xcb_enter_notify_event_t *) ev)->root );
+ break;
+ case XCB_LEAVE_NOTIFY:
+ //This is a mouse movement event when mouse goes leaves a window
+ //qDebug() << "Leave Notify Event";
+ obj->emit MouseLeaveWindow( ((xcb_leave_notify_event_t *) ev)->root );
+ break;
+//==============================
+ case XCB_EXPOSE:
+ //qDebug() << "Expose Notify Event:";
+ //qDebug() << " - Given Window:" << ((xcb_property_notify_event_t*)ev)->window;
+ break;
+//==============================
+ case XCB_MAP_NOTIFY:
+ //qDebug() << "Window Map Event:" << ((xcb_map_notify_event_t *)ev)->window;
+ obj->emit WindowPropertyChanged( ((xcb_map_notify_event_t *)ev)->window, NativeWindow::Visible, true);
+ break; //This is just a notification that a window was mapped - nothing needs to change here
+ case XCB_MAP_REQUEST:
+ //qDebug() << "Window Map Request Event";
+ obj->emit WindowCreated( ((xcb_map_request_event_t *) ev)->window );
+ break;
+//==============================
+ case XCB_CREATE_NOTIFY:
+ //qDebug() << "Window Create Event";
+ break;
+//==============================
+ case XCB_UNMAP_NOTIFY:
+ //qDebug() << "Window Unmap Event:" << ((xcb_unmap_notify_event_t *)ev)->window;
+ obj->emit WindowPropertyChanged( ((xcb_map_notify_event_t *)ev)->window, NativeWindow::Visible, false);
+ break;
+//==============================
+ case XCB_DESTROY_NOTIFY:
+ //qDebug() << "Window Closed Event:" << ((xcb_destroy_notify_event_t *)ev)->window;
+ obj->emit WindowDestroyed( ((xcb_destroy_notify_event_t *) ev)->window );
+ break;
+//==============================
+ case XCB_FOCUS_IN:
+ //qDebug() << "Focus In Event:";
+ break;
+//==============================
+ case XCB_FOCUS_OUT:
+ //qDebug() << "Focus Out Event:";
+ break;
+//==============================
+ case XCB_PROPERTY_NOTIFY:
+ //qDebug() << "Property Notify Event:";
+ ParsePropertyEvent((xcb_property_notify_event_t*)ev, obj);
+ break;
+//==============================
+ case XCB_CLIENT_MESSAGE:
+ //qDebug() << "Client Message Event";
+ //qDebug() << " - Given Window:" << ((xcb_client_message_event_t*)ev)->window;
+ if( ((xcb_client_message_event_t*)ev)->type == _NET_SYSTEM_TRAY_OPCODE && ((xcb_client_message_event_t*)ev)->format == 32){
+ //data32[0] is timestamp, [1] is opcode, [2] is window handle
+ if(SYSTEM_TRAY_REQUEST_DOCK == ((xcb_client_message_event_t*)ev)->data.data32[1]){
+ obj->emit TrayWindowCreated( ((xcb_client_message_event_t*)ev)->data.data32[2] );
+ //addTrayApp( ((xcb_client_message_event_t*)ev)->data.data32[2] );
+ }
+ //Ignore the System Tray messages at the moment
+ }else if(((xcb_client_message_event_t*)ev)->window != QX11Info::appRootWindow()){
+ ParseClientMessageEvent((xcb_client_message_event_t*)ev, obj);
+ }
+ break;
+//==============================
+ case XCB_CONFIGURE_NOTIFY:
+ //qDebug() << "Configure Notify Event";
+ /*obj->emit WindowPropertiesChanged( ((xcb_configure_notify_event_t*)ev)->window,
+ QList<NativeWindow::Property>() << NativeWindow::GlobalPos << NativeWindow::Size,
+ QList<QVariant>() << QPoint(((xcb_configure_notify_event_t*)ev)->x, ((xcb_configure_notify_event_t*)ev)->y) <<
+ QSize(((xcb_configure_notify_event_t*)ev)->width, ((xcb_configure_notify_event_t*)ev)->height) );*/
+ obj->emit WindowPropertyChanged( ((xcb_configure_notify_event_t*)ev)->window, NativeWindow::Size,
+ QSize(((xcb_configure_notify_event_t*)ev)->width, ((xcb_configure_notify_event_t*)ev)->height) );
+ break;
+//==============================
+ case XCB_CONFIGURE_REQUEST:
+ //qDebug() << "Configure Request Event";
+ obj->emit RequestWindowPropertiesChange( ((xcb_configure_request_event_t*)ev)->window,
+ QList<NativeWindow::Property>() << NativeWindow::GlobalPos << NativeWindow::Size,
+ QList<QVariant>() << QPoint(((xcb_configure_request_event_t*)ev)->x, ((xcb_configure_request_event_t*)ev)->y) <<
+ QSize(((xcb_configure_request_event_t*)ev)->width, ((xcb_configure_request_event_t*)ev)->height) );
+ break;
+//==============================
+ case XCB_RESIZE_REQUEST:
+ //qDebug() << "Resize Request Event";
+ obj->emit RequestWindowPropertyChange( ((xcb_resize_request_event_t*)ev)->window,
+ NativeWindow::Size, QSize(((xcb_resize_request_event_t*)ev)->width, ((xcb_resize_request_event_t*)ev)->height) );
+ break;
+//==============================
+ case XCB_SELECTION_CLEAR:
+ //qDebug() << "Selection Clear Event";
+ break;
+//==============================
+ case 85: //not sure what event this is - but it seems to come up very often (just hide the notice)
+ case 0:
+ case XCB_GE_GENERIC:
+ break; //generic event - don't do anything special
+ default:
+ //if( (ev->response_type & ~0x80)==TrayDmgID){
+ obj->emit PossibleDamageEvent( ((xcb_damage_notify_event_t*)ev)->drawable );
+ //checkDamageID( ((xcb_damage_notify_event_t*)ev)->drawable );
+ //}else{
+ //qDebug() << "Default Event:" << (ev->response_type & ~0x80);
+ //}
+//==============================
+ }
+ }
+ return false;
+ //never stop event handling (this will not impact the X events themselves - just the internal Qt application)
+}
bgstack15