aboutsummaryrefslogtreecommitdiff
path: root/libLumina
diff options
context:
space:
mode:
authorKen Moore <moorekou@gmail.com>2015-11-20 08:59:06 -0500
committerKen Moore <moorekou@gmail.com>2015-11-20 08:59:06 -0500
commitd0def86a98fdcc6d231d07f571a4555195d6760c (patch)
tree2c844b067aab9b894a45c6c279a104247a08e44d /libLumina
parentAdd the final pieces of the EWMH support functions to the Lumina library. (diff)
downloadlumina-d0def86a98fdcc6d231d07f571a4555195d6760c.tar.gz
lumina-d0def86a98fdcc6d231d07f571a4555195d6760c.tar.bz2
lumina-d0def86a98fdcc6d231d07f571a4555195d6760c.zip
Quick checkpoint for the window manager: NOT STABLE - crashes on window close right now.
Diffstat (limited to 'libLumina')
-rw-r--r--libLumina/LuminaX11.cpp133
-rw-r--r--libLumina/LuminaX11.h41
2 files changed, 164 insertions, 10 deletions
diff --git a/libLumina/LuminaX11.cpp b/libLumina/LuminaX11.cpp
index 0bdea55e..6cbc670d 100644
--- a/libLumina/LuminaX11.cpp
+++ b/libLumina/LuminaX11.cpp
@@ -55,7 +55,7 @@ void LXCB::createWMAtoms(){
ATOMS.clear();
atoms.clear();
//List the atoms needed by some WM functions
- atoms << "WM_TAKE_FOCUS" << "WM_DELETE_WINDOW"; //WM_PROTOCOLS
+ atoms << "WM_TAKE_FOCUS" << "WM_DELETE_WINDOW" << "WM_PROTOCOLS"; //WM_PROTOCOLS
//Create all the requests for the atoms
QList<xcb_intern_atom_reply_t*> reply;
@@ -1107,10 +1107,133 @@ void LXCB::closeSystemTray(WId trayID){
// WM Functions (directly changing properties/settings)
// - Using these directly may prevent the WM from seeing the change
//============
-void LXCB::WM_CloseWindow(WId win){
- xcb_destroy_window(QX11Info::connection(), win);
+void LXCB::WM_CloseWindow(WId win, bool force){
+
+ if(!force){ // && WM_ICCCM_GetProtocols(win).testFlag(LXCB::DELETE_WINDOW)){
+ //Send the window a WM_DELETE_WINDOW message
+ if(atoms.isEmpty()){ createWMAtoms(); } //need these atoms
+ xcb_client_message_event_t event;
+ event.response_type = XCB_CLIENT_MESSAGE;
+ event.format = 32;
+ event.window = win;
+ event.type = ATOMS[atoms.indexOf("WM_PROTOCOLS")];
+ event.data.data32[0] = ATOMS[atoms.indexOf("WM_DELETE_WINDOW")];
+ event.data.data32[1] = XCB_TIME_CURRENT_TIME; //CurrentTime;
+ event.data.data32[2] = 0;
+ event.data.data32[3] = 0;
+ event.data.data32[4] = 0;
+
+ xcb_send_event(QX11Info::connection(), 0, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
+ xcb_flush(QX11Info::connection());
+ }else{ xcb_destroy_window(QX11Info::connection(), win); }
+
+}
+
+void LXCB::WM_ShowWindow(WId win){
+ xcb_map_window(QX11Info::connection(), win);
+}
+
+void LXCB::WM_HideWindow(WId win){
+ xcb_unmap_window(QX11Info::connection(), win);
+}
+
+QList<WId> LXCB::WM_RootWindows(){
+ xcb_query_tree_cookie_t cookie = xcb_query_tree(QX11Info::connection(), QX11Info::appRootWindow());
+ xcb_query_tree_reply_t *reply = 0;
+ QList<WId> out;
+ reply=xcb_query_tree_reply(QX11Info::connection(), cookie, NULL);
+ if(reply!=0){
+ int num = xcb_query_tree_children_length(reply);
+ xcb_window_t *children = xcb_query_tree_children(reply);
+ for(int i=0; i<num; i++){
+ if(!out.contains(children[i])){ out << children[i]; }
+ }
+ free(reply);
+ }
+ return out;
+}
+
+WId LXCB::WM_CreateWindow(WId parent){
+ if(parent ==0){ parent = QX11Info::appRootWindow(); }
+ xcb_screen_t *root_screen = xcb_aux_get_screen(QX11Info::connection(), QX11Info::appScreen());
+ uint32_t params[] = {1};
+ WId win = xcb_generate_id(QX11Info::connection()); //need a new ID
+ xcb_create_window(QX11Info::connection(), root_screen->root_depth, \
+ win, parent, -1, -1, 1, 1, 0, \
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, root_screen->root_visual, \
+ XCB_CW_OVERRIDE_REDIRECT, params);
+ return win;
+}
+
+bool LXCB::WM_ManageWindow(WId win, bool needsmap){
+#define CLIENT_WIN_EVENT_MASK (XCB_EVENT_MASK_PROPERTY_CHANGE | \
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY | \
+ XCB_EVENT_MASK_FOCUS_CHANGE)
+ //return whether the window is/should be managed
+ xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(QX11Info::connection(), win);
+ xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), cookie, NULL);
+ if(attr == 0){ return false; } //could not get attributes of window
+ if(attr->override_redirect){ free(attr); return false; } //window has override redirect set (do not manage)
+ if(!needsmap && attr->map_state != XCB_MAP_STATE_VIEWABLE){
+ //window is never supposed to be visible (lots of these)
+ //if( !WM_ICCCM_GetClass(win).contains("xterm") ){ //Some windows mis-set this flag
+ qDebug() << " - Not Viewable.." << WM_ICCCM_GetClass(win);
+ free(attr); return false;
+ //}
+ }
+ //Setup event handling on the window
+ if( xcb_request_check(QX11Info::connection(), \
+ xcb_change_window_attributes_checked(QX11Info::connection(), win, XCB_CW_EVENT_MASK, (uint32_t[]){CLIENT_WIN_EVENT_MASK } ) ) ){
+ //Could not change event mask - did the window get deleted already?
+ free(attr);
+ qDebug() << " - Could not change event mask";
+ return false;
+ }
+
+ return true;
+}
+
+QRect LXCB::WM_Window_Geom(WId win){
+ xcb_get_geometry_cookie_t cookie = xcb_get_geometry_unchecked(QX11Info::connection(), win);
+ xcb_get_geometry_reply_t *reply = 0;
+ QRect geom;
+ reply = xcb_get_geometry_reply(QX11Info::connection(), cookie, NULL);
+ if(reply!=0){
+ geom = QRect(reply->x, reply->y, reply->width, reply->height);
+ free(reply);
+ }
+ return geom;
}
+void LXCB::setupEventsForFrame(WId frame){
+ #define FRAME_WIN_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \
+ XCB_EVENT_MASK_BUTTON_RELEASE | \
+ XCB_EVENT_MASK_POINTER_MOTION | \
+ XCB_EVENT_MASK_BUTTON_MOTION | \
+ XCB_EVENT_MASK_EXPOSURE | \
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY | \
+ XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \
+ XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \
+ XCB_EVENT_MASK_ENTER_WINDOW)
+
+ xcb_change_window_attributes(QX11Info::connection(), frame, XCB_CW_EVENT_MASK, (uint32_t[]){FRAME_WIN_EVENT_MASK } );
+}
+
+bool LXCB::setupEventsForRoot(WId root){
+ #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)
+
+ if(root==0){ root = QX11Info::appRootWindow(); }
+ xcb_generic_error_t *status = xcb_request_check( QX11Info::connection(), xcb_change_window_attributes_checked(QX11Info::connection(), root, XCB_CW_EVENT_MASK, (uint32_t[]){ROOT_WIN_EVENT_MASK} ) );
+ return (status==0);
+}
// --------------------------------------------------
// ICCCM Standards (older standards)
// --------------------------------------------------
@@ -1176,7 +1299,7 @@ void LXCB::WM_ICCCM_SetClass(WId win, QString name){
}
// -- WM_TRANSIENT_FOR
-WId WM_ICCCM_GetTransientFor(WId win){
+WId LXCB::WM_ICCCM_GetTransientFor(WId win){
xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_transient_for_unchecked(QX11Info::connection(), win);
xcb_window_t trans;
if(1!= xcb_icccm_get_wm_transient_for_reply(QX11Info::connection(), cookie, &trans, NULL) ){
@@ -1186,7 +1309,7 @@ WId WM_ICCCM_GetTransientFor(WId win){
}
}
-void WM_ICCCM_SetTransientFor(WId win, WId transient){
+void LXCB::WM_ICCCM_SetTransientFor(WId win, WId transient){
xcb_icccm_set_wm_transient_for(QX11Info::connection(), win, transient);
}
diff --git a/libLumina/LuminaX11.h b/libLumina/LuminaX11.h
index 0106515d..c799f485 100644
--- a/libLumina/LuminaX11.h
+++ b/libLumina/LuminaX11.h
@@ -35,6 +35,8 @@
#define URGENCYHINT (1L << 8) //For window urgency detection
+//Simple data container for the ICCCM hints (_size, _normal, _hints)
+
//Simple data container for doing STRUT_PARTIAL input/output calculations
class strut_geom{
public:
@@ -45,6 +47,22 @@ public:
~strut_geom(){}
};
+/*class icccm_hints{
+public:
+ int x, y, width, height, min_width, min_height, max_width, max_height;
+ int width_inc, height_inc, min_aspect_num, min_aspect_den, max_aspect_num, max_aspect_den;
+ int base_width, base_height;
+ unsigned int flags; //QFlags(LXCB::SIZE_HINT) combination
+ unsigned int win_gravity; //LXCB::GRAVITY value
+
+ icccm_hints(){
+ x=y=width=height=min_width=max_width=min_height=max_height = 0;
+ width_inc=height_inc=min_aspect_num=min_aspect_den=max_aspect_num=max_aspect_den = 0;
+ flags = win_gravity = 0;
+ }
+ ~icccm_hinits(){}
+};*/
+
//XCB Library replacement for LX11 (Qt5 uses XCB instead of XLib)
class LXCB{
@@ -59,9 +77,10 @@ public:
//Now enums which can have multiple values at once (Use the plural form for the QFlags)
enum ICCCM_PROTOCOL {TAKE_FOCUS = 0x0, DELETE_WINDOW = 0x1}; //any combination
Q_DECLARE_FLAGS(ICCCM_PROTOCOLS, ICCCM_PROTOCOL);
+ enum SIZE_HINT { US_POSITION=1<<0, US_SIZE=1<<1, P_POSITION=1<<2, P_SIZE=1<<3, P_MIN_SIZE=1<<4, P_MAX_SIZE=1<<5, P_RESIZE_INC=1<<6, P_ASPECT=1<<7, BASE_SIZE=1<<8, P_WIN_GRAVITY=1<<9 };
+ Q_DECLARE_FLAGS(SIZE_HINTS, SIZE_HINT);
enum MOVERESIZE_WINDOW_FLAG { X=0x0, Y=0x1, WIDTH=0x2, HEIGHT=0x3};
Q_DECLARE_FLAGS(MOVERESIZE_WINDOW_FLAGS, MOVERESIZE_WINDOW_FLAG);
-
xcb_ewmh_connection_t EWMH; //This is where all the screen info and atoms are located
@@ -129,10 +148,21 @@ public:
//============
- // WM Functions (directly changing properties/settings)
+ // WM Functions (directly changing/reading properties)
// - Using these directly may prevent the WM from seeing the change
//============
- void WM_CloseWindow(WId win);
+ void WM_CloseWindow(WId win, bool force = false);
+ void WM_ShowWindow(WId win);
+ void WM_HideWindow(WId win);
+
+ WId WM_CreateWindow(WId parent = 0);
+
+ // WM Utility Functions
+ QList<WId> WM_RootWindows(); //return all windows which have root as the parent
+ bool WM_ManageWindow(WId win, bool needsmap = true); //return whether the window is/should be managed
+ QRect WM_Window_Geom(WId win); //Return the current window geometry
+ void setupEventsForFrame(WId frame);
+ bool setupEventsForRoot(WId root = 0);
// ICCCM Standards (older standards)
// -- WM_NAME
@@ -154,7 +184,7 @@ public:
// -- WM_NORMAL_HINTS
- // -- WM_HINTS
+ // -- WM_HINTS (contains WM_STATE)
// -- WM_PROTOCOLS
ICCCM_PROTOCOLS WM_ICCCM_GetProtocols(WId win);
@@ -364,5 +394,6 @@ private:
//Now also declare the flags for Qt to be able to use normal operations on them
Q_DECLARE_OPERATORS_FOR_FLAGS(LXCB::ICCCM_PROTOCOLS);
Q_DECLARE_OPERATORS_FOR_FLAGS(LXCB::MOVERESIZE_WINDOW_FLAGS);
+Q_DECLARE_OPERATORS_FOR_FLAGS(LXCB::SIZE_HINTS);
-#endif \ No newline at end of file
+#endif
bgstack15