1 //===========================================
2 //  Lumina-DE source code
3 //  Copyright (c) 2012, Ken Moore
4 //  Available under the 3-clause BSD license
5 //  See the LICENSE file for full details
6 //===========================================
7 #include "LXcbEventFilter.h"
8 
9 //For all the XCB interactions and atoms
10 // is accessed via
11 //    session->XCB->EWMH.(atom name)
12 //    session->XCB->(do something)
13 #include <LuminaX11.h>
14 #include <QDebug>
15 
XCBEventFilter(LSession * sessionhandle)16 XCBEventFilter::XCBEventFilter(LSession *sessionhandle) : QAbstractNativeEventFilter(){
17   session = sessionhandle; //save this for interaction with the session later
18   TrayDmgFlag = 0;
19   stopping = false;
20   session->XCB->SelectInput(QX11Info::appRootWindow()); //make sure we get root window events
21   InitAtoms();
22 }
23 
setTrayDamageFlag(int flag)24 void XCBEventFilter::setTrayDamageFlag(int flag){
25   //Special flag for system tray damage events
26   TrayDmgFlag = flag + XCB_DAMAGE_NOTIFY; //save the whole flag (no calculations later)
27 }
28 
29 //This function format taken directly from the Qt5.3 documentation
nativeEventFilter(const QByteArray & eventType,void * message,long *)30 bool XCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *){
31 	if(stopping){ return false; } //don't do any parsing
32 	//qDebug() << "New Event";
33 	if(eventType=="xcb_generic_event_t"){
34 	  //qDebug() << " - XCB event";
35 	  //Convert to known event type (for X11 systems)
36 	   xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message);
37 	  //Now parse the event and emit signals as necessary
38 	  switch( ev->response_type & ~0x80){
39 //==============================
40 	    case XCB_PROPERTY_NOTIFY:
41 		//qDebug() << "Property Notify Event:";
42 	        //qDebug() << " - Root Window:" << QX11Info::appRootWindow();
43 		//qDebug() << " - Given Window:" << ((xcb_property_notify_event_t*)ev)->window;
44 		//System-specific property change
45 		if( ((xcb_property_notify_event_t*)ev)->window == QX11Info::appRootWindow() \
46 			&& ( ( ((xcb_property_notify_event_t*)ev)->atom == session->XCB->EWMH._NET_DESKTOP_GEOMETRY) \
47 			  ||  (((xcb_property_notify_event_t*)ev)->atom == session->XCB->EWMH._NET_WORKAREA) )){
48 		  session->RootSizeChange();
49 		}else if( ((xcb_property_notify_event_t*)ev)->window == QX11Info::appRootWindow() \
50 			&& ( ( ((xcb_property_notify_event_t*)ev)->atom == session->XCB->EWMH._NET_CURRENT_DESKTOP) )){
51  		  //qDebug() << "Got Workspace Change";
52 		  session->emit WorkspaceChanged();
53 		  session->WindowPropertyEvent(); //make sure we update the lists again - some windows are now hidden
54 		}else if( SysNotifyAtoms.contains( ((xcb_property_notify_event_t*)ev)->atom ) ){
55 		  //Update the status/list of all running windows
56 		  session->WindowPropertyEvent();
57 
58 		//window-specific property change
59 		}else if( WinNotifyAtoms.contains( ((xcb_property_notify_event_t*)ev)->atom ) ){
60 		  //Ping only that window
61 		  //session->WindowPropertyEvent( ((xcb_property_notify_event_t*)ev)->window );
62 		  session->WindowPropertyEvent();
63 	        }
64 		break;
65 //==============================
66 	    case XCB_CLIENT_MESSAGE:
67 		//qDebug() << "Client Message Event";
68 		//qDebug() << " - Root Window:" << QX11Info::appRootWindow();
69 		//qDebug() << " - Given Window:" << ((xcb_client_message_event_t*)ev)->window;
70 		if( TrayDmgFlag!=0 &&  ((xcb_client_message_event_t*)ev)->type == _NET_SYSTEM_TRAY_OPCODE && ((xcb_client_message_event_t*)ev)->format == 32){
71 		  //data32[0] is timestamp, [1] is opcode, [2] is  window handle
72 		  if(SYSTEM_TRAY_REQUEST_DOCK == ((xcb_client_message_event_t*)ev)->data.data32[1]){
73 		      session->SysTrayDockRequest( ((xcb_client_message_event_t*)ev)->data.data32[2] );
74 		  }
75 		  //Ignore the System Tray messages at the moment (let the WM handle it)
76 
77 		//window-specific property changes
78 		/*}else if( ((xcb_client_message_event_t*)ev)->type == session->XCB->EWMH._NET_WM_STATE ){
79 		  if( session->XCB->WindowIsMaximized( ((xcb_client_message_event_t*)ev)->window ) ){
80 		    //Quick fix for maximized windows (since Fluxbox is not doing the STRUT detection properly)
81 		    session->adjustWindowGeom( ((xcb_client_message_event_t*)ev)->window );
82 		  }
83 		  session->WindowPropertyEvent( ((xcb_client_message_event_t*)ev)->window );*/
84 		}else if( WinNotifyAtoms.contains( ((xcb_client_message_event_t*)ev)->type ) ){
85 		  //Ping only that window
86 		  //session->WindowPropertyEvent( ((xcb_client_message_event_t*)ev)->window );
87 		  session->WindowPropertyEvent();
88 	        }
89 	        break;
90 //==============================
91 	    case XCB_DESTROY_NOTIFY:
92 		//qDebug() << "Window Closed Event";
93 		session->WindowClosedEvent( ( (xcb_destroy_notify_event_t*)ev )->window );
94 	        break;
95 //==============================
96 	    case XCB_CONFIGURE_NOTIFY:
97 		//qDebug() << "Configure Notify Event";
98 		session->WindowConfigureEvent( ((xcb_configure_notify_event_t*)ev)->window );
99 	        break;
100 //==============================
101 	    case XCB_SELECTION_CLEAR:
102 		//qDebug() << "Selection Clear Event";
103 		session->WindowSelectionClearEvent( ((xcb_selection_clear_event_t*)ev)->owner );
104 	        break;
105 //==============================
106 	    default:
107 		if(TrayDmgFlag!=0){
108 		  //if( (ev->response_type & ~0x80)==TrayDmgFlag){
109 		    session->WindowDamageEvent( ((xcb_damage_notify_event_t*)ev)->drawable );
110 		  //}
111 		}/*else{
112 	          qDebug() << "Default Event:" << (ev->response_type & ~0x80);
113 	        }*/
114 //==============================
115 	  }
116 	}
117 	//qDebug() << " - finished event";
118 	return false; //make sure the handling keeps going (transparent watching of events)
119 }
120