From: Michael Stapelberg Date: Fri, 18 Mar 2011 15:07:02 +0000 (+0100) Subject: Make i3 compatible with the very latest xcb X-Git-Tag: 3.e-bf3~12 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=86117db4345190302b73ca4e95e8431459b3868b;p=i3%2Fi3 Make i3 compatible with the very latest xcb 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. --- diff --git a/common.mk b/common.mk index 0334ac61..bcb77142 100644 --- 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 diff --git a/i3-input/main.c b/i3-input/main.c index 2a3f02fd..fc9afd30 100644 --- a/i3-input/main.c +++ b/i3-input/main.c @@ -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 index 00000000..2543ffd2 --- /dev/null +++ b/include/atoms.xmacro @@ -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) diff --git a/include/handlers.h b/include/handlers.h index c7cbb322..6a4d0a4b 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -13,6 +13,28 @@ #include +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(). diff --git a/include/i3.h b/include/i3.h index 9b20e2a9..f081a129 100644 --- a/include/i3.h +++ b/include/i3.h @@ -10,7 +10,6 @@ */ #include #include -#include #include #include @@ -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 diff --git a/include/manage.h b/include/manage.h index 9c87a08e..02410f87 100644 --- a/include/manage.h +++ b/include/manage.h @@ -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); diff --git a/include/xcb.h b/include/xcb.h index 8d867553..22d0bcda 100644 --- a/include/xcb.h +++ b/include/xcb.h @@ -43,30 +43,9 @@ 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 index 00000000..1282f6cb --- /dev/null +++ b/include/xcb_compat.h @@ -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 diff --git a/src/click.c b/src/click.c index d8183269..164912de 100644 --- a/src/click.c +++ b/src/click.c @@ -19,6 +19,11 @@ #include #include +/* Contains compatibility definitions for old libxcb versions */ +#ifdef XCB_COMPAT +#include "xcb_compat.h" +#endif + #include #include #include diff --git a/src/client.c b/src/client.c index e2868faf..fc0d46ac 100644 --- a/src/client.c +++ b/src/client.c @@ -15,6 +15,11 @@ #include #include +/* Contains compatibility definitions for old libxcb versions */ +#ifdef XCB_COMPAT +#include "xcb_compat.h" +#endif + #include #include @@ -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); } diff --git a/src/debug.c b/src/debug.c index de47fca2..d2bd62b9 100644 --- a/src/debug.c +++ b/src/debug.c @@ -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); } diff --git a/src/ewmh.c b/src/ewmh.c index 6bfa3096..2c1c157a 100644 --- a/src/ewmh.c +++ b/src/ewmh.c @@ -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, ¤t_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); diff --git a/src/floating.c b/src/floating.c index 93a5b11c..7b9d3ffe 100644 --- a/src/floating.c +++ b/src/floating.c @@ -15,19 +15,18 @@ #include #include -#include #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) diff --git a/src/handlers.c b/src/handlers.c index d531b951..263b3036 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -13,6 +13,12 @@ #include #include #include +#include + +/* Contains compatibility definitions for old libxcb versions */ +#ifdef XCB_COMPAT +#include "xcb_compat.h" +#endif #include #include @@ -22,7 +28,7 @@ #include #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; } diff --git a/src/mainx.c b/src/mainx.c index be4713e6..b9665e45 100644 --- a/src/mainx.c +++ b/src/mainx.c @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include #include @@ -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) { diff --git a/src/manage.c b/src/manage.c index 089d62cb..0b33034e 100644 --- a/src/manage.c +++ b/src/manage.c @@ -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 diff --git a/src/resize.c b/src/resize.c index f6b6da74..363de0b8 100644 --- a/src/resize.c +++ b/src/resize.c @@ -15,7 +15,6 @@ #include #include -#include #include "i3.h" #include "data.h" diff --git a/src/sighandler.c b/src/sighandler.c index d789f30b..162edbc8 100644 --- a/src/sighandler.c +++ b/src/sighandler.c @@ -21,7 +21,6 @@ #include #include -#include #include #include diff --git a/src/util.c b/src/util.c index d119b35a..ae5c86a0 100644 --- a/src/util.c +++ b/src/util.c @@ -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");