]> Pileus Git - wmpus/commitdiff
Add WM_CLOSE client message
authorAndy Spencer <andy753421@gmail.com>
Sun, 19 Apr 2015 00:33:16 +0000 (00:33 +0000)
committerAndy Spencer <andy753421@gmail.com>
Sun, 19 Apr 2015 00:33:16 +0000 (00:33 +0000)
makefile
sys-xcb.c

index 400ce7a50c8dc4fe309edca2aadfab2e7d77fb38..a00980e7d19e792fd2d7f0079b358ea354f85322 100644 (file)
--- a/makefile
+++ b/makefile
@@ -13,7 +13,7 @@ MANPREFIX ?= ${PREFIX}/share/man
 ifeq ($(SYS),xcb)
 GCC       ?= gcc
 PROG      ?= wmpus
-LDFLAGS   += -lxcb -lxcb-keysyms -lxcb-util -lxcb-ewmh -lxcb-xinerama
+LDFLAGS   += -lxcb -lxcb-keysyms -lxcb-util -lxcb-icccm -lxcb-ewmh -lxcb-xinerama
 endif
 
 ifeq ($(SYS),xlib)
index dc8088a9f5fd6332c0fcdc98a14767eacd743406..c9259c3ef3cfe0366ca838714d74f7db2e28b755 100644 (file)
--- a/sys-xcb.c
+++ b/sys-xcb.c
@@ -22,6 +22,7 @@
 #include <xcb/xcb.h>
 #include <xcb/xcb_event.h>
 #include <xcb/xcb_keysyms.h>
+#include <xcb/xcb_icccm.h>
 #include <xcb/xcb_ewmh.h>
 #include <xcb/xinerama.h>
 
@@ -69,6 +70,8 @@ static list_t                *screens;
 static void                  *cache;
 static xcb_pixmap_t           colors[NCOLORS];
 static unsigned int           grabbed;
+static xcb_atom_t             wm_protos;
+static xcb_atom_t             wm_delete;
 
 /************************
  * Conversion functions *
@@ -330,6 +333,21 @@ static int do_get_input_focus(void)
        return reply->focus;
 }
 
+static xcb_atom_t do_intern_atom(const char *name)
+{
+       xcb_intern_atom_cookie_t cookie =
+               xcb_intern_atom(conn, 0, strlen(name), name);
+       if (!cookie.sequence)
+               return warn("do_intern_atom: bad cookie");
+
+       xcb_intern_atom_reply_t *reply =
+               xcb_intern_atom_reply(conn, cookie, NULL);
+       if (!reply)
+               return warn("do_intern_atom: no reply");
+
+       return reply->atom;
+}
+
 static int do_ewmh_init_atoms(void)
 {
        xcb_intern_atom_cookie_t *cookies =
@@ -427,6 +445,40 @@ static void do_configure_window(xcb_window_t win,
        xcb_configure_window(conn, win, mask, list);
 }
 
+static int do_client_message(xcb_window_t win, xcb_atom_t atom)
+{
+       /* Get protocols */
+       xcb_get_property_cookie_t cookie =
+               xcb_icccm_get_wm_protocols(conn, win, wm_protos);
+       if (!cookie.sequence)
+               return warn("do_client_message: %d - bad cookie", win);
+
+       xcb_icccm_get_wm_protocols_reply_t protos = {};
+       if (!xcb_icccm_get_wm_protocols_reply(conn, cookie, &protos, NULL))
+               return warn("do_client_message: %d - no reply", win);
+
+       /* Search for the atom */
+       int found = 0;
+       for (int i = 0; i < protos.atoms_len; i++)
+               if (protos.atoms[i] == atom)
+                       found = 1;
+       if (!found)
+               return warn("do_client_message: %d - no atom", win);
+
+       /* Send the message */
+       xcb_client_message_event_t msg = {
+               .response_type  = XCB_CLIENT_MESSAGE,
+               .format         = 32,
+               .window         = win,
+               .type           = wm_protos,
+               .data.data32[0] = atom,
+               .data.data32[1] = XCB_CURRENT_TIME,
+       };
+       xcb_send_event(conn, 0, win, XCB_EVENT_MASK_NO_EVENT,
+                       (const char *)&msg);
+       return 1;
+}
+
 /**************************
  * Window Manager Helpers *
  **************************/
@@ -839,7 +891,8 @@ void sys_show(win_t *win, state_t state)
                        break;
 
                case ST_CLOSE:
-                       xcb_kill_client(conn, xcb);
+                       if (!do_client_message(xcb, wm_delete))
+                               xcb_kill_client(conn, xcb);
                        break;
        }
 
@@ -965,6 +1018,12 @@ void sys_init(void)
        root     = iter.data->root;
        colormap = iter.data->default_colormap;
 
+       /* Setup X Atoms */
+       wm_protos = do_intern_atom("WM_PROTOCOLS");
+       wm_delete = do_intern_atom("WM_DELETE_WINDOW");
+       if (!wm_protos || !wm_delete)
+               error("unable to setup atoms");
+
        /* Setup EWMH connection */
        if (!do_ewmh_init_atoms())
                error("ewmh setup failed");