]> git.sur5r.net Git - i3/i3/commitdiff
Make i3 compatible with the very latest xcb
authorMichael Stapelberg <michael@stapelberg.de>
Fri, 18 Mar 2011 15:07:02 +0000 (16:07 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Fri, 18 Mar 2011 15:36:50 +0000 (16:36 +0100)
This involves:
 • Compiling with xcb-util instead of xcb-{atom,aux} (they merged the libraries)
 • Not using xcb-{event,property} anymore (code removed upstream)
 • Not using the predefined WINDOW, CARDINEL, … atoms (removed upstream)
 • Using the new xcb_icccm_* data types/functions instead of just xcb_*
   (for example xcb_icccm_get_wm_hints instead of xcb_get_wm_hints)

Also I refactored the atoms to use x-macros.

19 files changed:
common.mk
i3-input/main.c
include/atoms.xmacro [new file with mode: 0644]
include/handlers.h
include/i3.h
include/manage.h
include/xcb.h
include/xcb_compat.h [new file with mode: 0644]
src/click.c
src/client.c
src/debug.c
src/ewmh.c
src/floating.c
src/handlers.c
src/mainx.c
src/manage.c
src/resize.c
src/sighandler.c
src/util.c

index 0334ac61bd7720ec4eb292d71d4b751f8cdbcfbe..bcb771428e23cfcd9162d708a8de9f5d47332ae7 100644 (file)
--- a/common.mk
+++ b/common.mk
@@ -40,8 +40,13 @@ LDFLAGS += -lm
 LDFLAGS += -lxcb-event
 LDFLAGS += -lxcb-property
 LDFLAGS += -lxcb-keysyms
+ifeq ($(shell pkg-config --exists xcb-util || echo 1),1)
+CFLAGS += -DXCB_COMPAT
 LDFLAGS += -lxcb-atom
 LDFLAGS += -lxcb-aux
+else
+LDFLAGS += -lxcb-util
+endif
 LDFLAGS += -lxcb-icccm
 LDFLAGS += -lxcb-xinerama
 LDFLAGS += -lxcb-randr
index 2a3f02fdd6ac902eff4fc3ee594a9e1c1052e679..fc9afd30baf0f3c566e82d82800bf34db0316cd7 100644 (file)
@@ -308,13 +308,6 @@ int main(int argc, char *argv[]) {
                 die("Cannot open display\n");
 
         /* Set up event handlers for key press and key release */
-        xcb_event_handlers_t evenths;
-        memset(&evenths, 0, sizeof(xcb_event_handlers_t));
-        xcb_event_handlers_init(conn, &evenths);
-        xcb_event_set_key_press_handler(&evenths, handle_key_press, NULL);
-        xcb_event_set_key_release_handler(&evenths, handle_key_release, NULL);
-        xcb_event_set_expose_handler(&evenths, handle_expose, NULL);
-
         modeswitchmask = get_mod_mask(conn, XK_Mode_switch);
         numlockmask = get_mod_mask(conn, XK_Num_Lock);
        symbols = xcb_key_symbols_alloc(conn);
@@ -362,7 +355,33 @@ int main(int argc, char *argv[]) {
 
         xcb_flush(conn);
 
-        xcb_event_wait_for_event_loop(&evenths);
+        xcb_generic_event_t *event;
+        while ((event = xcb_wait_for_event(conn)) != NULL) {
+                if (event->response_type == 0) {
+                        fprintf(stderr, "X11 Error received! sequence %x\n", event->sequence);
+                        continue;
+                }
+
+                /* Strip off the highest bit (set if the event is generated) */
+                int type = (event->response_type & 0x7F);
+
+                switch (type) {
+                        case XCB_KEY_PRESS:
+                                handle_key_press(NULL, conn, (xcb_key_press_event_t*)event);
+                                break;
+
+                        case XCB_KEY_RELEASE:
+                                handle_key_release(NULL, conn, (xcb_key_release_event_t*)event);
+                                break;
+
+                        case XCB_EXPOSE:
+                                handle_expose(NULL, conn, (xcb_expose_event_t*)event);
+                                break;
+                }
+
+                free(event);
+        }
+
 
         return 0;
 }
diff --git a/include/atoms.xmacro b/include/atoms.xmacro
new file mode 100644 (file)
index 0000000..2543ffd
--- /dev/null
@@ -0,0 +1,31 @@
+xmacro(_NET_SUPPORTED)
+xmacro(_NET_SUPPORTING_WM_CHECK)
+xmacro(_NET_WM_NAME)
+xmacro(_NET_WM_STATE_FULLSCREEN)
+xmacro(_NET_WM_STATE)
+xmacro(_NET_WM_WINDOW_TYPE)
+xmacro(_NET_WM_WINDOW_TYPE_DOCK)
+xmacro(_NET_WM_WINDOW_TYPE_DIALOG)
+xmacro(_NET_WM_WINDOW_TYPE_UTILITY)
+xmacro(_NET_WM_WINDOW_TYPE_TOOLBAR)
+xmacro(_NET_WM_WINDOW_TYPE_SPLASH)
+xmacro(_NET_WM_DESKTOP)
+xmacro(_NET_WM_STRUT_PARTIAL)
+xmacro(WM_PROTOCOLS)
+xmacro(WM_DELETE_WINDOW)
+xmacro(UTF8_STRING)
+xmacro(WM_STATE)
+xmacro(WM_CLIENT_LEADER)
+xmacro(_NET_CURRENT_DESKTOP)
+xmacro(_NET_ACTIVE_WINDOW)
+xmacro(_NET_WORKAREA)
+xmacro(WM_TAKE_FOCUS)
+xmacro(WM_HINTS)
+xmacro(WM_NORMAL_HINTS)
+xmacro(WM_TRANSIENT_FOR)
+xmacro(ATOM)
+xmacro(WINDOW)
+xmacro(WM_NAME)
+xmacro(WM_CLASS)
+xmacro(STRING)
+xmacro(CARDINAL)
index c7cbb3226a44b960c0caf5e9022db34dfc7df99b..6a4d0a4b31e98bb11045b736ce34d26e2f3e3b32 100644 (file)
 
 #include <xcb/randr.h>
 
+extern int randr_base;
+
+/**
+ * Takes an xcb_generic_event_t and calls the appropriate handler, based on the
+ * event type.
+ *
+ */
+void handle_event(int type, xcb_generic_event_t *event);
+
+/**
+ * Requests the property and invokes the appropriate callback.
+ *
+ */
+int property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom);
+
+/**
+ * Sets the appropriate atoms for the property handlers after the atoms were
+ * received from X11
+ *
+ */
+void property_handlers_init();
+
 /**
  * There was a key press. We compare this key code with our bindings table and
  * pass the bound action to parse_command().
index 9b20e2a9812437bfab16e98c95fc8c1945aa1882..f081a1295b9f093165e40c9f670c42730063c093 100644 (file)
@@ -10,7 +10,6 @@
  */
 #include <xcb/xcb.h>
 #include <xcb/xcb_property.h>
-#include <xcb/xcb_event.h>
 #include <xcb/xcb_keysyms.h>
 
 #include <X11/XKBlib.h>
@@ -21,8 +20,6 @@
 #ifndef _I3_H
 #define _I3_H
 
-#define NUM_ATOMS 22
-
 extern xcb_connection_t *global_conn;
 extern xcb_key_symbols_t *keysyms;
 extern char **start_argv;
@@ -32,10 +29,8 @@ extern TAILQ_HEAD(bindings_head, Binding) *bindings;
 extern TAILQ_HEAD(autostarts_head, Autostart) autostarts;
 extern TAILQ_HEAD(assignments_head, Assignment) assignments;
 extern SLIST_HEAD(stack_wins_head, Stack_Window) stack_wins;
-extern xcb_event_handlers_t evenths;
 extern uint8_t root_depth;
 extern bool xkb_supported;
-extern xcb_atom_t atoms[NUM_ATOMS];
 extern xcb_window_t root;
 
 #endif
index 9c87a08ef64fda93ce66d46668026f6dda4d4023..02410f8773065f994d4c1f242bd5707fddb5872c 100644 (file)
@@ -20,8 +20,7 @@
  * manage them
  *
  */
-void manage_existing_windows(xcb_connection_t *conn, xcb_property_handlers_t
-                             *prophs, xcb_window_t root);
+void manage_existing_windows(xcb_connection_t *conn, xcb_window_t root);
 
 /**
  * Restores the geometry of each window by reparenting it to the root window
@@ -37,7 +36,7 @@ void restore_geometry(xcb_connection_t *conn);
  * Do some sanity checks and then reparent the window.
  *
  */
-void manage_window(xcb_property_handlers_t *prophs, xcb_connection_t *conn,
+void manage_window(xcb_connection_t *conn,
                    xcb_window_t window,
                    xcb_get_window_attributes_cookie_t cookie,
                    bool needs_to_be_mapped);
index 8d8675537fed52480ea017cef7672298c73b4a3d..22d0bcda11a33905574bec78b398d64f2ac7d3e7 100644 (file)
                           XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |   /* …subwindows get notifies */ \
                           XCB_EVENT_MASK_ENTER_WINDOW)           /* …user moves cursor inside our window */
 
-
-enum { _NET_SUPPORTED = 0,
-        _NET_SUPPORTING_WM_CHECK,
-        _NET_WM_NAME,
-        _NET_WM_STATE_FULLSCREEN,
-        _NET_WM_STATE,
-        _NET_WM_WINDOW_TYPE,
-        _NET_WM_WINDOW_TYPE_DOCK,
-        _NET_WM_WINDOW_TYPE_DIALOG,
-        _NET_WM_WINDOW_TYPE_UTILITY,
-        _NET_WM_WINDOW_TYPE_TOOLBAR,
-        _NET_WM_WINDOW_TYPE_SPLASH,
-        _NET_WM_DESKTOP,
-        _NET_WM_STRUT_PARTIAL,
-        WM_PROTOCOLS,
-        WM_DELETE_WINDOW,
-        UTF8_STRING,
-        WM_STATE,
-        WM_CLIENT_LEADER,
-        _NET_CURRENT_DESKTOP,
-        _NET_ACTIVE_WINDOW,
-        _NET_WORKAREA,
-        WM_TAKE_FOCUS
-};
+#define xmacro(atom) xcb_atom_t A_ ## atom;
+#include "atoms.xmacro"
+#undef xmacro
 
 extern unsigned int xcb_numlock_mask;
 
diff --git a/include/xcb_compat.h b/include/xcb_compat.h
new file mode 100644 (file)
index 0000000..1282f6c
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _XCB_COMPAT_H
+#define _XCB_COMPAT_H
+
+#define xcb_icccm_get_wm_protocols_reply_t xcb_get_wm_protocols_reply_t
+#define xcb_icccm_get_wm_protocols_unchecked xcb_get_wm_protocols_unchecked
+#define xcb_icccm_get_wm_protocols_reply xcb_get_wm_protocols_reply
+#define xcb_icccm_get_wm_protocols_reply_wipe xcb_get_wm_protocols_reply_wipe
+#define XCB_ICCCM_WM_STATE_NORMAL XCB_WM_STATE_NORMAL
+#define XCB_ICCCM_WM_STATE_WITHDRAWN XCB_WM_STATE_WITHDRAWN
+#define xcb_icccm_get_wm_size_hints_from_reply xcb_get_wm_size_hints_from_reply
+#define xcb_icccm_get_wm_normal_hints_reply xcb_get_wm_normal_hints_reply
+#define xcb_icccm_get_wm_normal_hints_unchecked xcb_get_wm_normal_hints_unchecked
+#define XCB_ICCCM_SIZE_HINT_P_MIN_SIZE XCB_SIZE_HINT_P_MIN_SIZE
+#define XCB_ICCCM_SIZE_HINT_P_RESIZE_INC XCB_SIZE_HINT_P_RESIZE_INC
+#define XCB_ICCCM_SIZE_HINT_BASE_SIZE XCB_SIZE_HINT_BASE_SIZE
+#define XCB_ICCCM_SIZE_HINT_P_ASPECT XCB_SIZE_HINT_P_ASPECT
+#define xcb_icccm_wm_hints_t xcb_wm_hints_t
+#define xcb_icccm_get_wm_hints_from_reply xcb_get_wm_hints_from_reply
+#define xcb_icccm_get_wm_hints_reply xcb_get_wm_hints_reply
+#define xcb_icccm_get_wm_hints_unchecked xcb_get_wm_hints_unchecked
+#define xcb_icccm_wm_hints_get_urgency xcb_wm_hints_get_urgency
+#define xcb_icccm_get_wm_transient_for_from_reply xcb_get_wm_transient_for_from_reply
+#define xcb_icccm_get_wm_transient_for_reply xcb_get_wm_transient_for_reply
+#define xcb_icccm_get_wm_transient_for_unchecked xcb_get_wm_transient_for_unchecked
+
+#endif
index d8183269f87e0949d979d58201f3b2a9689ef317..164912deb447b9372a97a35c8d2a0e6e0f775a76 100644 (file)
 #include <stdbool.h>
 #include <math.h>
 
+/* Contains compatibility definitions for old libxcb versions */
+#ifdef XCB_COMPAT
+#include "xcb_compat.h"
+#endif
+
 #include <xcb/xcb.h>
 #include <xcb/xcb_atom.h>
 #include <xcb/xcb_icccm.h>
index e2868faf3b21feaabb61ebd6d187fc65a9d10b2b..fc0d46ac084b4e1c12d0b0649e7dd2dbfe06ad02 100644 (file)
 #include <assert.h>
 #include <limits.h>
 
+/* Contains compatibility definitions for old libxcb versions */
+#ifdef XCB_COMPAT
+#include "xcb_compat.h"
+#endif
+
 #include <xcb/xcb.h>
 #include <xcb/xcb_icccm.h>
 
@@ -71,11 +76,11 @@ void client_warp_pointer_into(xcb_connection_t *conn, Client *client) {
  */
 static bool client_supports_protocol(xcb_connection_t *conn, Client *client, xcb_atom_t atom) {
         xcb_get_property_cookie_t cookie;
-        xcb_get_wm_protocols_reply_t protocols;
+        xcb_icccm_get_wm_protocols_reply_t protocols;
         bool result = false;
 
-        cookie = xcb_get_wm_protocols_unchecked(conn, client->child, atoms[WM_PROTOCOLS]);
-        if (xcb_get_wm_protocols_reply(conn, cookie, &protocols, NULL) != 1)
+        cookie = xcb_icccm_get_wm_protocols_unchecked(conn, client->child, A_WM_PROTOCOLS);
+        if (xcb_icccm_get_wm_protocols_reply(conn, cookie, &protocols, NULL) != 1)
                 return false;
 
         /* Check if the client’s protocols have the requested atom set */
@@ -83,7 +88,7 @@ static bool client_supports_protocol(xcb_connection_t *conn, Client *client, xcb
                 if (protocols.atoms[i] == atom)
                         result = true;
 
-        xcb_get_wm_protocols_reply_wipe(&protocols);
+        xcb_icccm_get_wm_protocols_reply_wipe(&protocols);
 
         return result;
 }
@@ -94,7 +99,7 @@ static bool client_supports_protocol(xcb_connection_t *conn, Client *client, xcb
  */
 void client_kill(xcb_connection_t *conn, Client *window) {
         /* If the client does not support WM_DELETE_WINDOW, we kill it the hard way */
-        if (!client_supports_protocol(conn, window, atoms[WM_DELETE_WINDOW])) {
+        if (!client_supports_protocol(conn, window, A_WM_DELETE_WINDOW)) {
                 LOG("Killing window the hard way\n");
                 xcb_kill_client(conn, window->child);
                 return;
@@ -106,9 +111,9 @@ void client_kill(xcb_connection_t *conn, Client *window) {
 
         ev.response_type = XCB_CLIENT_MESSAGE;
         ev.window = window->child;
-        ev.type = atoms[WM_PROTOCOLS];
+        ev.type = A_WM_PROTOCOLS;
         ev.format = 32;
-        ev.data.data32[0] = atoms[WM_DELETE_WINDOW];
+        ev.data.data32[0] = A_WM_DELETE_WINDOW;
         ev.data.data32[1] = XCB_CURRENT_TIME;
 
         LOG("Sending WM_DELETE to the client\n");
@@ -229,8 +234,8 @@ void client_enter_fullscreen(xcb_connection_t *conn, Client *client, bool global
         xcb_configure_window(conn, client->frame, XCB_CONFIG_WINDOW_STACK_MODE, values);
 
         /* Update _NET_WM_STATE */
-        values[0] = atoms[_NET_WM_STATE_FULLSCREEN];
-        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, client->child, atoms[_NET_WM_STATE], ATOM, 32, 1, values);
+        values[0] = A__NET_WM_STATE_FULLSCREEN;
+        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, client->child, A__NET_WM_STATE, A_ATOM, 32, 1, values);
 
         fake_configure_notify(conn, r, client->child);
 
@@ -267,7 +272,7 @@ void client_leave_fullscreen(xcb_connection_t *conn, Client *client) {
         }
 
         /* Update _NET_WM_STATE */
-        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, client->child, atoms[_NET_WM_STATE], ATOM, 32, 0, NULL);
+        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, client->child, A__NET_WM_STATE, A_ATOM, 32, 0, NULL);
 
         xcb_flush(conn);
 }
@@ -401,8 +406,8 @@ void client_change_border(xcb_connection_t *conn, Client *client, char border_ty
  */
 void client_unmap(xcb_connection_t *conn, Client *client) {
         /* Set WM_STATE_WITHDRAWN, it seems like Java apps need it */
-        long data[] = { XCB_WM_STATE_WITHDRAWN, XCB_NONE };
-        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, client->child, atoms[WM_STATE], atoms[WM_STATE], 32, 2, data);
+        long data[] = { XCB_ICCCM_WM_STATE_WITHDRAWN, XCB_NONE };
+        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, client->child, A_WM_STATE, A_WM_STATE, 32, 2, data);
 
         xcb_unmap_window(conn, client->frame);
 }
@@ -414,8 +419,8 @@ void client_unmap(xcb_connection_t *conn, Client *client) {
 void client_map(xcb_connection_t *conn, Client *client) {
         /* Set WM_STATE_NORMAL because GTK applications don’t want to drag & drop if we don’t.
          * Also, xprop(1) needs that to work. */
-        long data[] = { XCB_WM_STATE_NORMAL, XCB_NONE };
-        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, client->child, atoms[WM_STATE], atoms[WM_STATE], 32, 2, data);
+        long data[] = { XCB_ICCCM_WM_STATE_NORMAL, XCB_NONE };
+        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, client->child, A_WM_STATE, A_WM_STATE, 32, 2, data);
 
         xcb_map_window(conn, client->frame);
 }
index de47fca257299b32cfe95e00be7e148a4c7e209d..d2bd62b9e95ae5552513631a8285ef1cc8930c81 100644 (file)
@@ -245,6 +245,6 @@ int format_event(xcb_generic_event_t *e) {
     return 1;
 }
 
-int handle_event(void *ignored, xcb_connection_t *c, xcb_generic_event_t *e) {
+int dbg_handle_event(void *ignored, xcb_connection_t *c, xcb_generic_event_t *e) {
         return format_event(e);
 }
index 6bfa3096ef25c777bf5f8b6d22961d8768022037..2c1c157ae59085199d619c4a26ed8d8aca39734a 100644 (file)
@@ -31,7 +31,7 @@
 void ewmh_update_current_desktop() {
         uint32_t current_desktop = c_ws->num;
         xcb_change_property(global_conn, XCB_PROP_MODE_REPLACE, root,
-                            atoms[_NET_CURRENT_DESKTOP], CARDINAL, 32, 1,
+                            A__NET_CURRENT_DESKTOP, A_CARDINAL, 32, 1,
                             &current_desktop);
 }
 
@@ -44,7 +44,7 @@ void ewmh_update_current_desktop() {
  */
 void ewmh_update_active_window(xcb_window_t window) {
         xcb_change_property(global_conn, XCB_PROP_MODE_REPLACE, root,
-                            atoms[_NET_ACTIVE_WINDOW], WINDOW, 32, 1, &window);
+                            A__NET_ACTIVE_WINDOW, A_WINDOW, 32, 1, &window);
 }
 
 /*
@@ -95,7 +95,7 @@ void ewmh_update_workarea() {
                 memcpy(&last_rect, &(ws->rect), sizeof(Rect));
         }
         xcb_change_property(global_conn, XCB_PROP_MODE_REPLACE, root,
-                            atoms[_NET_WORKAREA], CARDINAL, 32,
+                            A__NET_WORKAREA, A_CARDINAL, 32,
                             num_workspaces * (sizeof(Rect) / sizeof(uint32_t)),
                             workarea);
         free(workarea);
index 93a5b11c47ab5dbf58e46b2012d3872befcb32cb..7b9d3ffeb6eecbdb0867f9842a4772cdc98b9aa1 100644 (file)
 #include <assert.h>
 
 #include <xcb/xcb.h>
-#include <xcb/xcb_event.h>
 
 #include "i3.h"
 #include "config.h"
 #include "data.h"
 #include "util.h"
 #include "xcb.h"
-#include "debug.h"
 #include "layout.h"
 #include "client.h"
 #include "floating.h"
 #include "workspace.h"
 #include "log.h"
+#include "handlers.h"
 
 /*
  * Toggles floating mode for the given client.
@@ -404,19 +403,15 @@ void drag_pointer(xcb_connection_t *conn, Client *client, xcb_button_press_event
         while ((inside_event = xcb_wait_for_event(conn))) {
                 /* We now handle all events we can get using xcb_poll_for_event */
                 do {
-                        /* Same as get_event_handler in xcb */
-                        int nr = inside_event->response_type;
-                        if (nr == 0) {
-                                /* An error occured */
-                                handle_event(NULL, conn, inside_event);
+                        /* skip x11 errors */
+                        if (inside_event->response_type == 0) {
                                 free(inside_event);
                                 continue;
                         }
-                        assert(nr < 256);
-                        nr &= XCB_EVENT_RESPONSE_TYPE_MASK;
-                        assert(nr >= 2);
+                        /* Strip off the highest bit (set if the event is generated) */
+                        int type = (inside_event->response_type & 0x7F);
 
-                        switch (nr) {
+                        switch (type) {
                                 case XCB_BUTTON_RELEASE:
                                         goto done;
 
@@ -428,13 +423,13 @@ void drag_pointer(xcb_connection_t *conn, Client *client, xcb_button_press_event
 
                                 case XCB_UNMAP_NOTIFY:
                                         DLOG("Unmap-notify, aborting\n");
-                                        xcb_event_handle(&evenths, inside_event);
+                                        handle_event(type, inside_event);
                                         goto done;
 
                                 default:
                                         DLOG("Passing to original handler\n");
                                         /* Use original handler */
-                                        xcb_event_handle(&evenths, inside_event);
+                                        handle_event(type, inside_event);
                                         break;
                         }
                         if (last_motion_notify != inside_event)
index d531b951fd5143bd223f7012ef5197a241369722..263b303668c003403590b974a8e2360adfa9dcac 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 #include <time.h>
+#include <limits.h>
+
+/* Contains compatibility definitions for old libxcb versions */
+#ifdef XCB_COMPAT
+#include "xcb_compat.h"
+#endif
 
 #include <xcb/xcb.h>
 #include <xcb/xcb_atom.h>
@@ -22,7 +28,7 @@
 #include <X11/XKBlib.h>
 
 #include "i3.h"
-#include "debug.h"
+#include "handlers.h"
 #include "table.h"
 #include "layout.h"
 #include "commands.h"
@@ -41,6 +47,8 @@
 #include "container.h"
 #include "ipc.h"
 
+int randr_base = -1;
+
 /* After mapping/unmapping windows, a notify event is generated. However, we don’t want it,
    since it’d trigger an infinite loop of switching between the different windows when
    changing workspaces */
@@ -82,6 +90,154 @@ static bool event_is_ignored(const int sequence) {
         return false;
 }
 
+ /*
+ * Takes an xcb_generic_event_t and calls the appropriate handler, based on the
+ * event type.
+ *
+ */
+void handle_event(int type, xcb_generic_event_t *event) {
+    /* XXX: remove the NULL and conn parameters as soon as this version of libxcb is required */
+
+    if (randr_base > -1 &&
+        type == randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
+        handle_screen_change(NULL, global_conn, event);
+        return;
+    }
+
+    switch (type) {
+        case XCB_KEY_PRESS:
+            handle_key_press(NULL, global_conn, (xcb_key_press_event_t*)event);
+            break;
+
+        case XCB_BUTTON_PRESS:
+            handle_button_press(NULL, global_conn, (xcb_button_press_event_t*)event);
+            break;
+
+        case XCB_MAP_REQUEST:
+            handle_map_request(NULL, global_conn, (xcb_map_request_event_t*)event);
+            break;
+
+        case XCB_UNMAP_NOTIFY:
+            handle_unmap_notify_event(NULL, global_conn, (xcb_unmap_notify_event_t*)event);
+            break;
+
+        case XCB_DESTROY_NOTIFY:
+            handle_destroy_notify_event(NULL, global_conn, (xcb_destroy_notify_event_t*)event);
+            break;
+
+        case XCB_EXPOSE:
+            handle_expose_event(NULL, global_conn, (xcb_expose_event_t*)event);
+            break;
+
+        case XCB_MOTION_NOTIFY:
+            handle_motion_notify(NULL, global_conn, (xcb_motion_notify_event_t*)event);
+            break;
+
+        /* Enter window = user moved his mouse over the window */
+        case XCB_ENTER_NOTIFY:
+            handle_enter_notify(NULL, global_conn, (xcb_enter_notify_event_t*)event);
+            break;
+
+        /* Client message are sent to the root window. The only interesting
+         * client message for us is _NET_WM_STATE, we honour
+         * _NET_WM_STATE_FULLSCREEN */
+        case XCB_CLIENT_MESSAGE:
+            handle_client_message(NULL, global_conn, (xcb_client_message_event_t*)event);
+            break;
+
+        /* Configure request = window tried to change size on its own */
+        case XCB_CONFIGURE_REQUEST:
+            handle_configure_request(NULL, global_conn, (xcb_configure_request_event_t*)event);
+            break;
+
+        case XCB_CONFIGURE_NOTIFY:
+            handle_configure_event(NULL, global_conn, (xcb_configure_notify_event_t*)event);
+            break;
+
+        /* Mapping notify = keyboard mapping changed (Xmodmap), re-grab bindings */
+        case XCB_MAPPING_NOTIFY:
+            handle_mapping_notify(NULL, global_conn, (xcb_mapping_notify_event_t*)event);
+            break;
+
+        case XCB_PROPERTY_NOTIFY:
+            DLOG("Property notify\n");
+            xcb_property_notify_event_t *e = (xcb_property_notify_event_t*)event;
+            property_notify(e->state, e->window, e->atom);
+            break;
+
+        default:
+            DLOG("Unhandled event of type %d\n", type);
+            break;
+    }
+}
+
+typedef int (*cb_property_handler_t)(void *data, xcb_connection_t *c, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *property);
+
+struct property_handler_t {
+    xcb_atom_t atom;
+    uint32_t long_len;
+    cb_property_handler_t cb;
+};
+
+static struct property_handler_t property_handlers[] = {
+    { 0, 128, handle_windowname_change },
+    { 0, UINT_MAX, handle_hints },
+    { 0, 128, handle_windowname_change_legacy },
+    { 0, UINT_MAX, handle_normal_hints },
+    { 0, UINT_MAX, handle_clientleader_change },
+    { 0, UINT_MAX, handle_transient_for },
+    { 0, UINT_MAX, handle_windowclass_change }
+};
+#define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t))
+
+/*
+ * Sets the appropriate atoms for the property handlers after the atoms were
+ * received from X11
+ *
+ */
+void property_handlers_init() {
+    property_handlers[0].atom = A__NET_WM_NAME;
+    property_handlers[1].atom = A_WM_HINTS;
+    property_handlers[2].atom = A_WM_NAME;
+    property_handlers[3].atom = A_WM_NORMAL_HINTS;
+    property_handlers[4].atom = A_WM_CLIENT_LEADER;
+    property_handlers[5].atom = A_WM_TRANSIENT_FOR;
+    property_handlers[6].atom = A_WM_CLASS;
+}
+
+/*
+ * Requests the property and invokes the appropriate callback.
+ *
+ */
+int property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom) {
+    struct property_handler_t *handler = NULL;
+    xcb_get_property_reply_t *propr = NULL;
+    int ret;
+
+    for (int c = 0; c < sizeof(property_handlers) / sizeof(struct property_handler_t); c++) {
+        if (property_handlers[c].atom != atom)
+            continue;
+
+        handler = &property_handlers[c];
+        break;
+    }
+
+    if (handler == NULL) {
+        DLOG("Unhandled property notify for atom %d (0x%08x)\n", atom, atom);
+        return 0;
+    }
+
+    if (state != XCB_PROPERTY_DELETE) {
+        xcb_get_property_cookie_t cookie = xcb_get_property(global_conn, 0, window, atom, XCB_GET_PROPERTY_TYPE_ANY, 0, handler->long_len);
+        propr = xcb_get_property_reply(global_conn, cookie, 0);
+    }
+
+    ret = handler->cb(NULL, global_conn, state, window, atom, propr);
+    FREE(propr);
+    return ret;
+}
+
+
 /*
  * There was a key press. We compare this key code with our bindings table and pass
  * the bound action to parse_command().
@@ -271,7 +427,7 @@ int handle_mapping_notify(void *ignored, xcb_connection_t *conn, xcb_mapping_not
  * A new window appeared on the screen (=was mapped), so let’s manage it.
  *
  */
-int handle_map_request(void *prophs, xcb_connection_t *conn, xcb_map_request_event_t *event) {
+int handle_map_request(void *invalid, xcb_connection_t *conn, xcb_map_request_event_t *event) {
         xcb_get_window_attributes_cookie_t cookie;
 
         cookie = xcb_get_window_attributes_unchecked(conn, event->window);
@@ -279,7 +435,7 @@ int handle_map_request(void *prophs, xcb_connection_t *conn, xcb_map_request_eve
         DLOG("window = 0x%08x, serial is %d.\n", event->window, event->sequence);
         add_ignore_event(event->sequence);
 
-        manage_window(prophs, conn, event->window, cookie, false);
+        manage_window(conn, event->window, cookie, false);
         return 1;
 }
 
@@ -836,8 +992,8 @@ int handle_expose_event(void *data, xcb_connection_t *conn, xcb_expose_event_t *
  *
  */
 int handle_client_message(void *data, xcb_connection_t *conn, xcb_client_message_event_t *event) {
-        if (event->type == atoms[_NET_WM_STATE]) {
-                if (event->format != 32 || event->data.data32[1] != atoms[_NET_WM_STATE_FULLSCREEN])
+        if (event->type == A__NET_WM_STATE) {
+                if (event->format != 32 || event->data.data32[1] != A__NET_WM_STATE_FULLSCREEN)
                         return 0;
 
                 Client *client = table_get(&by_child, event->window);
@@ -888,17 +1044,17 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w
 
         /* If the hints were already in this event, use them, if not, request them */
         if (reply != NULL)
-                xcb_get_wm_size_hints_from_reply(&size_hints, reply);
+                xcb_icccm_get_wm_size_hints_from_reply(&size_hints, reply);
         else
-                xcb_get_wm_normal_hints_reply(conn, xcb_get_wm_normal_hints_unchecked(conn, client->child), &size_hints, NULL);
+                xcb_icccm_get_wm_normal_hints_reply(conn, xcb_icccm_get_wm_normal_hints_unchecked(conn, client->child), &size_hints, NULL);
 
-        if ((size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE)) {
+        if ((size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE)) {
                 // TODO: Minimum size is not yet implemented
                 DLOG("Minimum size: %d (width) x %d (height)\n", size_hints.min_width, size_hints.min_height);
         }
 
         bool changed = false;
-        if ((size_hints.flags & XCB_SIZE_HINT_P_RESIZE_INC)) {
+        if ((size_hints.flags & XCB_ICCCM_SIZE_HINT_P_RESIZE_INC)) {
                 if (size_hints.width_inc > 0 && size_hints.width_inc < 0xFFFF)
                         if (client->width_increment != size_hints.width_inc) {
                                 client->width_increment = size_hints.width_inc;
@@ -919,10 +1075,10 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w
         /* base_width/height are the desired size of the window.
            We check if either the program-specified size or the program-specified
            min-size is available */
-        if (size_hints.flags & XCB_SIZE_HINT_BASE_SIZE) {
+        if (size_hints.flags & XCB_ICCCM_SIZE_HINT_BASE_SIZE) {
                 base_width = size_hints.base_width;
                 base_height = size_hints.base_height;
-        } else if (size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE) {
+        } else if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) {
                 /* TODO: is this right? icccm says not */
                 base_width = size_hints.min_width;
                 base_height = size_hints.min_height;
@@ -947,7 +1103,7 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w
         }
 
         /* If no aspect ratio was set or if it was invalid, we ignore the hints */
-        if (!(size_hints.flags & XCB_SIZE_HINT_P_ASPECT) ||
+        if (!(size_hints.flags & XCB_ICCCM_SIZE_HINT_P_ASPECT) ||
             (size_hints.min_aspect_num <= 0) ||
             (size_hints.min_aspect_den <= 0)) {
                 return 1;
@@ -996,13 +1152,13 @@ int handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t
                 DLOG("Received WM_HINTS for unknown client\n");
                 return 1;
         }
-        xcb_wm_hints_t hints;
+        xcb_icccm_wm_hints_t hints;
 
         if (reply != NULL) {
-                if (!xcb_get_wm_hints_from_reply(&hints, reply))
+                if (!xcb_icccm_get_wm_hints_from_reply(&hints, reply))
                         return 1;
         } else {
-                if (!xcb_get_wm_hints_reply(conn, xcb_get_wm_hints_unchecked(conn, client->child), &hints, NULL))
+                if (!xcb_icccm_get_wm_hints_reply(conn, xcb_icccm_get_wm_hints_unchecked(conn, client->child), &hints, NULL))
                         return 1;
         }
 
@@ -1013,7 +1169,7 @@ int handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t
         }
 
         /* Update the flag on the client directly */
-        client->urgent = (xcb_wm_hints_get_urgency(&hints) != 0);
+        client->urgent = (xcb_icccm_wm_hints_get_urgency(&hints) != 0);
         CLIENT_LOG(client);
         LOG("Urgency flag changed to %d\n", client->urgent);
 
@@ -1050,10 +1206,10 @@ int handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state, xcb_
         xcb_window_t transient_for;
 
         if (reply != NULL) {
-                if (!xcb_get_wm_transient_for_from_reply(&transient_for, reply))
+                if (!xcb_icccm_get_wm_transient_for_from_reply(&transient_for, reply))
                         return 1;
         } else {
-                if (!xcb_get_wm_transient_for_reply(conn, xcb_get_wm_transient_for_unchecked(conn, window),
+                if (!xcb_icccm_get_wm_transient_for_reply(conn, xcb_icccm_get_wm_transient_for_unchecked(conn, window),
                                                     &transient_for, NULL))
                         return 1;
         }
@@ -1075,7 +1231,7 @@ int handle_clientleader_change(void *data, xcb_connection_t *conn, uint8_t state
                         xcb_atom_t name, xcb_get_property_reply_t *prop) {
         if (prop == NULL) {
                 prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
-                                        false, window, WM_CLIENT_LEADER, WINDOW, 0, 32), NULL);
+                                        false, window, A_WM_CLIENT_LEADER, A_WINDOW, 0, 32), NULL);
                 if (prop == NULL)
                         return 1;
         }
index be4713e654353cbb20ec170892af74720065adc4..b9665e45521ecbfff4c8aea1e3bdcf37d056c737 100644 (file)
@@ -26,8 +26,6 @@
 #include <xcb/xcb.h>
 #include <xcb/xcb_atom.h>
 #include <xcb/xcb_aux.h>
-#include <xcb/xcb_event.h>
-#include <xcb/xcb_property.h>
 #include <xcb/xcb_keysyms.h>
 #include <xcb/xcb_icccm.h>
 
@@ -35,7 +33,6 @@
 
 #include "config.h"
 #include "data.h"
-#include "debug.h"
 #include "handlers.h"
 #include "click.h"
 #include "i3.h"
@@ -77,11 +74,6 @@ struct assignments_head assignments = TAILQ_HEAD_INITIALIZER(assignments);
 /* This is a list of Stack_Windows, global, for easier/faster access on expose events */
 struct stack_wins_head stack_wins = SLIST_HEAD_INITIALIZER(stack_wins);
 
-/* The event handlers need to be global because they are accessed by our custom event handler
-   in handle_button_press(), needed for graphical resizing */
-xcb_event_handlers_t evenths;
-xcb_atom_t atoms[NUM_ATOMS];
-
 xcb_window_t root;
 int num_screens = 0;
 
@@ -105,7 +97,7 @@ static void xcb_got_event(EV_P_ struct ev_io *w, int revents) {
  *
  */
 static void xcb_prepare_cb(EV_P_ ev_prepare *w, int revents) {
-        xcb_flush(evenths.c);
+        xcb_flush(global_conn);
 }
 
 /*
@@ -116,8 +108,17 @@ static void xcb_prepare_cb(EV_P_ ev_prepare *w, int revents) {
 static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
         xcb_generic_event_t *event;
 
-        while ((event = xcb_poll_for_event(evenths.c)) != NULL) {
-                xcb_event_handle(&evenths, event);
+        while ((event = xcb_poll_for_event(global_conn)) != NULL) {
+                if (event->response_type == 0) {
+                        ELOG("X11 Error received! sequence %x\n", event->sequence);
+                        continue;
+                }
+
+                /* Strip off the highest bit (set if the event is generated) */
+                int type = (event->response_type & 0x7F);
+
+                handle_event(type, event);
+
                 free(event);
         }
 }
@@ -191,14 +192,12 @@ static void xkb_got_event(EV_P_ struct ev_io *w, int revents) {
 
 
 int main(int argc, char *argv[], char *env[]) {
-        int i, screens, opt;
+        int screens, opt;
         char *override_configpath = NULL;
         bool autostart = true;
         bool only_check_config = false;
         bool force_xinerama = false;
         xcb_connection_t *conn;
-        xcb_property_handlers_t prophs;
-        xcb_intern_atom_cookie_t atom_cookies[NUM_ATOMS];
         static struct option long_options[] = {
                 {"no-autostart", no_argument, 0, 'a'},
                 {"config", required_argument, 0, 'c'},
@@ -275,9 +274,6 @@ int main(int argc, char *argv[], char *env[]) {
         /* Initialize the table data structures for each workspace */
         init_table();
 
-        memset(&evenths, 0, sizeof(xcb_event_handlers_t));
-        memset(&prophs, 0, sizeof(xcb_property_handlers_t));
-
         conn = global_conn = xcb_connect(NULL, &screens);
 
         if (xcb_connection_has_error(conn))
@@ -303,30 +299,10 @@ int main(int argc, char *argv[], char *env[]) {
         expand_table_rows(TAILQ_FIRST(workspaces));
 
         /* Place requests for the atoms we need as soon as possible */
-        #define REQUEST_ATOM(name) atom_cookies[name] = xcb_intern_atom(conn, 0, strlen(#name), #name);
-
-        REQUEST_ATOM(_NET_SUPPORTED);
-        REQUEST_ATOM(_NET_WM_STATE_FULLSCREEN);
-        REQUEST_ATOM(_NET_SUPPORTING_WM_CHECK);
-        REQUEST_ATOM(_NET_WM_NAME);
-        REQUEST_ATOM(_NET_WM_STATE);
-        REQUEST_ATOM(_NET_WM_WINDOW_TYPE);
-        REQUEST_ATOM(_NET_WM_DESKTOP);
-        REQUEST_ATOM(_NET_WM_WINDOW_TYPE_DOCK);
-        REQUEST_ATOM(_NET_WM_WINDOW_TYPE_DIALOG);
-        REQUEST_ATOM(_NET_WM_WINDOW_TYPE_UTILITY);
-        REQUEST_ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR);
-        REQUEST_ATOM(_NET_WM_WINDOW_TYPE_SPLASH);
-        REQUEST_ATOM(_NET_WM_STRUT_PARTIAL);
-        REQUEST_ATOM(WM_PROTOCOLS);
-        REQUEST_ATOM(WM_DELETE_WINDOW);
-        REQUEST_ATOM(UTF8_STRING);
-        REQUEST_ATOM(WM_STATE);
-        REQUEST_ATOM(WM_CLIENT_LEADER);
-        REQUEST_ATOM(_NET_CURRENT_DESKTOP);
-        REQUEST_ATOM(_NET_ACTIVE_WINDOW);
-        REQUEST_ATOM(_NET_WORKAREA);
-        REQUEST_ATOM(WM_TAKE_FOCUS);
+        #define xmacro(atom) \
+                xcb_intern_atom_cookie_t atom ## _cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
+        #include "atoms.xmacro"
+        #undef xmacro
 
         /* TODO: this has to be more beautiful somewhen */
         int major, minor, error;
@@ -392,15 +368,7 @@ int main(int argc, char *argv[], char *env[]) {
         /* Grab the server to delay any events until we enter the eventloop */
         xcb_grab_server(conn);
 
-        xcb_event_handlers_init(conn, &evenths);
-
-        /* DEBUG: Trap all events and print them */
-        for (i = 2; i < 128; ++i)
-                xcb_event_set_handler(&evenths, i, handle_event, 0);
-
-        for (i = 0; i < 256; ++i)
-                xcb_event_set_error_handler(&evenths, i, (xcb_generic_error_handler_t)handle_event, 0);
-
+#if 0
         /* Expose = an Application should redraw itself, in this case it’s our titlebars. */
         xcb_event_set_expose_handler(&evenths, handle_expose_event, NULL);
 
@@ -440,12 +408,7 @@ int main(int argc, char *argv[], char *env[]) {
         /* Client message are sent to the root window. The only interesting client message
            for us is _NET_WM_STATE, we honour _NET_WM_STATE_FULLSCREEN */
         xcb_event_set_client_message_handler(&evenths, handle_client_message, NULL);
-
-        /* Initialize the property handlers */
-        xcb_property_handlers_init(&prophs, &evenths);
-
-        /* Watch size hints (to obey correct aspect ratio) */
-        xcb_property_set_handler(&prophs, WM_NORMAL_HINTS, UINT_MAX, handle_normal_hints, NULL);
+#endif
 
         /* set event mask */
         uint32_t mask = XCB_CW_EVENT_MASK;
@@ -461,66 +424,34 @@ int main(int argc, char *argv[], char *env[]) {
         check_error(conn, cookie, "Another window manager seems to be running");
 
         /* Setup NetWM atoms */
-        #define GET_ATOM(name) { \
-                xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, atom_cookies[name], NULL); \
-                if (!reply) { \
-                        ELOG("Could not get atom " #name "\n"); \
-                        exit(-1); \
-                } \
-                atoms[name] = reply->atom; \
-                free(reply); \
-        }
+        #define xmacro(name) \
+                do { \
+                        xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name ## _cookie, NULL); \
+                        if (!reply) { \
+                                ELOG("Could not get atom " #name "\n"); \
+                                exit(-1); \
+                        } \
+                        A_ ## name = reply->atom; \
+                        free(reply); \
+                } while (0);
+        #include "atoms.xmacro"
+        #undef xmacro
+
+        property_handlers_init();
 
-        GET_ATOM(_NET_SUPPORTED);
-        GET_ATOM(_NET_WM_STATE_FULLSCREEN);
-        GET_ATOM(_NET_SUPPORTING_WM_CHECK);
-        GET_ATOM(_NET_WM_NAME);
-        GET_ATOM(_NET_WM_STATE);
-        GET_ATOM(_NET_WM_WINDOW_TYPE);
-        GET_ATOM(_NET_WM_DESKTOP);
-        GET_ATOM(_NET_WM_WINDOW_TYPE_DOCK);
-        GET_ATOM(_NET_WM_WINDOW_TYPE_DIALOG);
-        GET_ATOM(_NET_WM_WINDOW_TYPE_UTILITY);
-        GET_ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR);
-        GET_ATOM(_NET_WM_WINDOW_TYPE_SPLASH);
-        GET_ATOM(_NET_WM_STRUT_PARTIAL);
-        GET_ATOM(WM_PROTOCOLS);
-        GET_ATOM(WM_DELETE_WINDOW);
-        GET_ATOM(UTF8_STRING);
-        GET_ATOM(WM_STATE);
-        GET_ATOM(WM_CLIENT_LEADER);
-        GET_ATOM(_NET_CURRENT_DESKTOP);
-        GET_ATOM(_NET_ACTIVE_WINDOW);
-        GET_ATOM(_NET_WORKAREA);
-        GET_ATOM(WM_TAKE_FOCUS);
-
-        xcb_property_set_handler(&prophs, atoms[_NET_WM_WINDOW_TYPE], UINT_MAX, handle_window_type, NULL);
-        /* TODO: In order to comply with EWMH, we have to watch _NET_WM_STRUT_PARTIAL */
-
-        /* Watch _NET_WM_NAME (= title of the window in UTF-8) property */
-        xcb_property_set_handler(&prophs, atoms[_NET_WM_NAME], 128, handle_windowname_change, NULL);
-
-        /* Watch WM_TRANSIENT_FOR property (to which client this popup window belongs) */
-        xcb_property_set_handler(&prophs, WM_TRANSIENT_FOR, UINT_MAX, handle_transient_for, NULL);
-
-        /* Watch WM_NAME (= title of the window in compound text) property for legacy applications */
-        xcb_watch_wm_name(&prophs, 128, handle_windowname_change_legacy, NULL);
-
-        /* Watch WM_CLASS (= class of the window) */
-        xcb_property_set_handler(&prophs, WM_CLASS, 128, handle_windowclass_change, NULL);
-
-        /* Watch WM_CLIENT_LEADER (= logical parent window for toolbars etc.) */
-        xcb_property_set_handler(&prophs, atoms[WM_CLIENT_LEADER], UINT_MAX, handle_clientleader_change, NULL);
-
-        /* Watch WM_HINTS (contains the urgent property) */
-        xcb_property_set_handler(&prophs, WM_HINTS, UINT_MAX, handle_hints, NULL);
+        /* Set up the atoms we support */
+        xcb_atom_t supported_atoms[] = {
+#define xmacro(atom) A_ ## atom,
+#include "atoms.xmacro"
+#undef xmacro
+        };
 
         /* Set up the atoms we support */
-        check_error(conn, xcb_change_property_checked(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_SUPPORTED],
-                       ATOM, 32, 7, atoms), "Could not set _NET_SUPPORTED");
+        check_error(conn, xcb_change_property_checked(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED,
+                       A_ATOM, 32, 7, supported_atoms), "Could not set _NET_SUPPORTED");
         /* Set up the window manager’s name */
-        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_SUPPORTING_WM_CHECK], WINDOW, 32, 1, &root);
-        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_WM_NAME], atoms[UTF8_STRING], 8, strlen("i3"), "i3");
+        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTING_WM_CHECK, A_WINDOW, 32, 1, &root);
+        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3"), "i3");
 
         keysyms = xcb_key_symbols_alloc(conn);
 
@@ -529,18 +460,11 @@ int main(int argc, char *argv[], char *env[]) {
         translate_keysyms();
         grab_all_keys(conn, false);
 
-        int randr_base = -1;
         if (force_xinerama) {
                 initialize_xinerama(conn);
         } else {
                 DLOG("Checking for XRandR...\n");
                 initialize_randr(conn, &randr_base);
-
-                if (randr_base != -1)
-                    xcb_event_set_handler(&evenths,
-                                          randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY,
-                                          handle_screen_change,
-                                          NULL);
         }
 
         xcb_flush(conn);
@@ -562,7 +486,7 @@ int main(int argc, char *argv[], char *env[]) {
         DLOG("Starting on %p\n", screen->current_workspace);
         c_ws = screen->current_workspace;
 
-        manage_existing_windows(conn, &prophs, root);
+        manage_existing_windows(conn, root);
 
         /* Create the UNIX domain socket for IPC */
         if (config.ipc_socket_path != NULL) {
index 089d62cbfa40057918216e25bcaca20306cf9eca..0b33034e5eafce7e0b34ad62c9b21691959ee29f 100644 (file)
@@ -37,7 +37,7 @@
  * Go through all existing windows (if the window manager is restarted) and manage them
  *
  */
-void manage_existing_windows(xcb_connection_t *conn, xcb_property_handlers_t *prophs, xcb_window_t root) {
+void manage_existing_windows(xcb_connection_t *conn, xcb_window_t root) {
         xcb_query_tree_reply_t *reply;
         int i, len;
         xcb_window_t *children;
@@ -57,7 +57,7 @@ void manage_existing_windows(xcb_connection_t *conn, xcb_property_handlers_t *pr
 
         /* Call manage_window with the attributes for every window */
         for (i = 0; i < len; ++i)
-                manage_window(prophs, conn, children[i], cookies[i], true);
+                manage_window(conn, children[i], cookies[i], true);
 
         free(reply);
         free(cookies);
@@ -89,7 +89,7 @@ void restore_geometry(xcb_connection_t *conn) {
  * Do some sanity checks and then reparent the window.
  *
  */
-void manage_window(xcb_property_handlers_t *prophs, xcb_connection_t *conn,
+void manage_window(xcb_connection_t *conn,
                    xcb_window_t window, xcb_get_window_attributes_cookie_t cookie,
                    bool needs_to_be_mapped) {
         xcb_drawable_t d = { window };
@@ -127,13 +127,13 @@ void manage_window(xcb_property_handlers_t *prophs, xcb_connection_t *conn,
                         geom->border_width);
 
         /* Generate callback events for every property we watch */
-        xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, WM_CLASS);
-        xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, WM_NAME);
-        xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, WM_NORMAL_HINTS);
-        xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, WM_HINTS);
-        xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, WM_TRANSIENT_FOR);
-        xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, atoms[WM_CLIENT_LEADER]);
-        xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, atoms[_NET_WM_NAME]);
+        property_notify(XCB_PROPERTY_NEW_VALUE, window, A_WM_CLASS);
+        property_notify(XCB_PROPERTY_NEW_VALUE, window, A_WM_NAME);
+        property_notify(XCB_PROPERTY_NEW_VALUE, window, A_WM_NORMAL_HINTS);
+        property_notify(XCB_PROPERTY_NEW_VALUE, window, A_WM_HINTS);
+        property_notify(XCB_PROPERTY_NEW_VALUE, window, A_WM_TRANSIENT_FOR);
+        property_notify(XCB_PROPERTY_NEW_VALUE, window, A_WM_CLIENT_LEADER);
+        property_notify(XCB_PROPERTY_NEW_VALUE, window, A__NET_WM_NAME);
 
         free(geom);
 out:
@@ -167,13 +167,13 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
         xcb_change_window_attributes(conn, child, mask, values);
 
         /* Place requests for properties ASAP */
-        wm_type_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_WINDOW_TYPE], UINT32_MAX);
-        strut_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_STRUT_PARTIAL], UINT32_MAX);
-        state_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_STATE], UINT32_MAX);
-        utf8_title_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_NAME], 128);
-        leader_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[WM_CLIENT_LEADER], UINT32_MAX);
-        title_cookie = xcb_get_any_property_unchecked(conn, false, child, WM_NAME, 128);
-        class_cookie = xcb_get_any_property_unchecked(conn, false, child, WM_CLASS, 128);
+        wm_type_cookie = xcb_get_any_property_unchecked(conn, false, child, A__NET_WM_WINDOW_TYPE, UINT32_MAX);
+        strut_cookie = xcb_get_any_property_unchecked(conn, false, child, A__NET_WM_STRUT_PARTIAL, UINT32_MAX);
+        state_cookie = xcb_get_any_property_unchecked(conn, false, child, A__NET_WM_STATE, UINT32_MAX);
+        utf8_title_cookie = xcb_get_any_property_unchecked(conn, false, child, A__NET_WM_NAME, 128);
+        leader_cookie = xcb_get_any_property_unchecked(conn, false, child, A_WM_CLIENT_LEADER, UINT32_MAX);
+        title_cookie = xcb_get_any_property_unchecked(conn, false, child, A_WM_NAME, 128);
+        class_cookie = xcb_get_any_property_unchecked(conn, false, child, A_WM_CLASS, 128);
 
         Client *new = table_get(&by_child, child);
 
@@ -270,7 +270,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
         xcb_get_property_reply_t *preply = xcb_get_property_reply(conn, wm_type_cookie, NULL);
         if (preply != NULL && preply->value_len > 0 && (atom = xcb_get_property_value(preply))) {
                 for (int i = 0; i < xcb_get_property_value_length(preply); i++)
-                        if (atom[i] == atoms[_NET_WM_WINDOW_TYPE_DOCK]) {
+                        if (atom[i] == A__NET_WM_WINDOW_TYPE_DOCK) {
                                 DLOG("Window is a dock.\n");
                                 Output *t_out = get_output_containing(x, y);
                                 if (t_out == NULL)
@@ -289,10 +289,10 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
                                 /* If it’s a dock we can’t make it float, so we break */
                                 new->floating = FLOATING_AUTO_OFF;
                                 break;
-                        } else if (atom[i] == atoms[_NET_WM_WINDOW_TYPE_DIALOG] ||
-                                   atom[i] == atoms[_NET_WM_WINDOW_TYPE_UTILITY] ||
-                                   atom[i] == atoms[_NET_WM_WINDOW_TYPE_TOOLBAR] ||
-                                   atom[i] == atoms[_NET_WM_WINDOW_TYPE_SPLASH]) {
+                        } else if (atom[i] == A__NET_WM_WINDOW_TYPE_DIALOG ||
+                                   atom[i] == A__NET_WM_WINDOW_TYPE_UTILITY ||
+                                   atom[i] == A__NET_WM_WINDOW_TYPE_TOOLBAR ||
+                                   atom[i] == A__NET_WM_WINDOW_TYPE_SPLASH) {
                                 /* Set the dialog window to automatically floating, will be used below */
                                 new->floating = FLOATING_AUTO_ON;
                                 DLOG("dialog/utility/toolbar/splash window, automatically floating\n");
@@ -337,16 +337,16 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
                  * changes. It is important that the client was already inserted into the by_child table,
                  * because the callbacks won’t work otherwise. */
                 preply = xcb_get_property_reply(conn, utf8_title_cookie, NULL);
-                handle_windowname_change(NULL, conn, 0, new->child, atoms[_NET_WM_NAME], preply);
+                handle_windowname_change(NULL, conn, 0, new->child, A__NET_WM_NAME, preply);
 
                 preply = xcb_get_property_reply(conn, title_cookie, NULL);
-                handle_windowname_change_legacy(NULL, conn, 0, new->child, WM_NAME, preply);
+                handle_windowname_change_legacy(NULL, conn, 0, new->child, A_WM_NAME, preply);
 
                 preply = xcb_get_property_reply(conn, class_cookie, NULL);
-                handle_windowclass_change(NULL, conn, 0, new->child, WM_CLASS, preply);
+                handle_windowclass_change(NULL, conn, 0, new->child, A_WM_CLASS, preply);
 
                 preply = xcb_get_property_reply(conn, leader_cookie, NULL);
-                handle_clientleader_change(NULL, conn, 0, new->child, atoms[WM_CLIENT_LEADER], preply);
+                handle_clientleader_change(NULL, conn, 0, new->child, A_WM_CLIENT_LEADER, preply);
 
                 /* if WM_CLIENT_LEADER is set, we put the new window on the
                  * same window as its leader. This might be overwritten by
@@ -485,7 +485,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
             (state = xcb_get_property_value(preply)) != NULL)
                 /* Check all set _NET_WM_STATEs */
                 for (int i = 0; i < xcb_get_property_value_length(preply); i++) {
-                        if (state[i] != atoms[_NET_WM_STATE_FULLSCREEN])
+                        if (state[i] != A__NET_WM_STATE_FULLSCREEN)
                                 continue;
                         /* If the window got the fullscreen state, we just toggle fullscreen
                            and don’t event bother to redraw the layout – that would not change
index f6b6da74a644e4f9f27429635e5ce8a27e24dfe2..363de0b80efed8a70fb058ecdcfc611b088ca774 100644 (file)
@@ -15,7 +15,6 @@
 #include <assert.h>
 
 #include <xcb/xcb.h>
-#include <xcb/xcb_event.h>
 
 #include "i3.h"
 #include "data.h"
index d789f30b8148917f0ebe32c65d24d584b95690c9..162edbc8e4a7c25b2355d7139662c14d5077d064 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <xcb/xcb.h>
 #include <xcb/xcb_aux.h>
-#include <xcb/xcb_event.h>
 #include <xcb/xcb_keysyms.h>
 
 #include <X11/keysym.h>
index d119b35a532b0485d97c5c845ed37a4e164bb9c8..ae5c86a004e8cf0bb8ddcbb4f4ebe765031483a3 100644 (file)
@@ -233,9 +233,9 @@ void take_focus(xcb_connection_t *conn, Client *client) {
 
     ev.response_type = XCB_CLIENT_MESSAGE;
     ev.window = client->child;
-    ev.type = atoms[WM_PROTOCOLS];
+    ev.type = A_WM_PROTOCOLS;
     ev.format = 32;
-    ev.data.data32[0] = atoms[WM_TAKE_FOCUS];
+    ev.data.data32[0] = A_WM_TAKE_FOCUS;
     ev.data.data32[1] = XCB_CURRENT_TIME;
 
     DLOG("Sending WM_TAKE_FOCUS to the client\n");