From 80a6f2f510dfd39f852d80481e447a12f205a540 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 9 Apr 2016 15:44:54 +0200 Subject: [PATCH 1/3] Clean up static variables in event_handle This function needs the event numbers for events from some extensions. These are assigned dynamically by the server. Right now, this is done by having a bunch of static variables that are initialized when needed. Refactor this to have a function event_init() instead that sets variable in globalconf (where all of our state should be saved). Also, a preprocessor macro is introduced to handle event dispatch which also looks a bit nicer. Signed-off-by: Uli Schlachter --- awesome.c | 2 ++ event.c | 63 ++++++++++++++++++++-------------------------------- event.h | 1 + globalconf.h | 7 ++++-- 4 files changed, 32 insertions(+), 41 deletions(-) diff --git a/awesome.c b/awesome.c index 2c4caa82b..db4221f11 100644 --- a/awesome.c +++ b/awesome.c @@ -637,6 +637,8 @@ main(int argc, char **argv) query = xcb_get_extension_data(globalconf.connection, &xcb_shape_id); globalconf.have_shape = query->present; + event_init(); + /* Allocate the key symbols */ globalconf.keysyms = xcb_key_symbols_alloc(globalconf.connection); diff --git a/event.c b/event.c index b08ce2f82..f7cdb0af8 100644 --- a/event.c +++ b/event.c @@ -976,49 +976,34 @@ void event_handle(xcb_generic_event_t *event) #undef EVENT } - static uint8_t randr_screen_change_notify = 0; - static uint8_t randr_output_change_notify = 0; - static uint8_t shape_notify = 0; - static uint8_t xkb_notify = 0; +#define EXTENSION_EVENT(base, offset, callback) \ + if (globalconf.event_base_ ## base != 0 \ + && response_type == globalconf.event_base_ ## base + (offset)) \ + callback((void *) event) + EXTENSION_EVENT(randr, XCB_RANDR_SCREEN_CHANGE_NOTIFY, event_handle_randr_screen_change_notify); + EXTENSION_EVENT(randr, XCB_RANDR_NOTIFY, event_handle_randr_output_change_notify); + EXTENSION_EVENT(shape, XCB_SHAPE_NOTIFY, event_handle_shape_notify); + EXTENSION_EVENT(xkb, 0, event_handle_xkb_notify); +#undef EXTENSION_EVENT +} - if(randr_screen_change_notify == 0 || randr_output_change_notify == 0) - { - /* check for randr extension */ - const xcb_query_extension_reply_t *randr_query; - randr_query = xcb_get_extension_data(globalconf.connection, &xcb_randr_id); - if(randr_query->present) { - xcb_randr_select_input(globalconf.connection, globalconf.screen->root, XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE); - randr_screen_change_notify = randr_query->first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY; - randr_output_change_notify = randr_query->first_event + XCB_RANDR_NOTIFY; - } +void event_init(void) +{ + const xcb_query_extension_reply_t *reply; + + reply = xcb_get_extension_data(globalconf.connection, &xcb_randr_id); + if (reply && reply->present) { + xcb_randr_select_input(globalconf.connection, globalconf.screen->root, XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE); + globalconf.event_base_randr = reply->first_event; } - if(shape_notify == 0) - { - /* check for shape extension */ - const xcb_query_extension_reply_t *shape_query; - shape_query = xcb_get_extension_data(globalconf.connection, &xcb_shape_id); - if(shape_query->present) - shape_notify = shape_query->first_event + XCB_SHAPE_NOTIFY; - } + reply = xcb_get_extension_data(globalconf.connection, &xcb_shape_id); + if (reply && reply->present) + globalconf.event_base_shape = reply->first_event; - if(xkb_notify == 0) - { - /* check for xkb extension */ - const xcb_query_extension_reply_t *xkb_query; - xkb_query = xcb_get_extension_data(globalconf.connection, &xcb_xkb_id); - if(xkb_query->present) - xkb_notify = xkb_query->first_event; - } - - if (response_type == randr_screen_change_notify) - event_handle_randr_screen_change_notify((void *) event); - if (response_type == randr_output_change_notify) - event_handle_randr_output_change_notify((void *) event); - if (response_type == shape_notify) - event_handle_shape_notify((void *) event); - if (response_type == xkb_notify) - event_handle_xkb_notify((void *) event); + reply = xcb_get_extension_data(globalconf.connection, &xcb_xkb_id); + if (reply && reply->present) + globalconf.event_base_xkb = reply->first_event; } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/event.h b/event.h index f47add4bf..1d471aa3b 100644 --- a/event.h +++ b/event.h @@ -50,6 +50,7 @@ awesome_refresh(void) return xcb_flush(globalconf.connection); } +void event_init(void); void event_handle(xcb_generic_event_t *); void event_drawable_under_mouse(lua_State *, int); diff --git a/globalconf.h b/globalconf.h index be4a65354..dc407596b 100644 --- a/globalconf.h +++ b/globalconf.h @@ -82,8 +82,6 @@ typedef struct screen_array_t screens; /** The primary screen, access through screen_get_primary() */ screen_t *primary_screen; - /** Do we have RandR 1.3 or newer? */ - bool have_randr_13; /** Root window key bindings */ key_array_t keys; /** Root window mouse bindings */ @@ -92,10 +90,15 @@ typedef struct xcb_atom_t selection_atom; /** Window owning the WM_Sn selection */ xcb_window_t selection_owner_window; + /** Do we have RandR 1.3 or newer? */ + bool have_randr_13; /** Check for XTest extension */ bool have_xtest; /** Check for SHAPE extension */ bool have_shape; + uint8_t event_base_shape; + uint8_t event_base_xkb; + uint8_t event_base_randr; /** Clients list */ client_array_t clients; /** Embedded windows */ From cb46a1163e904d37deee0e069cc81320ff34ea37 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 9 Apr 2016 15:56:44 +0200 Subject: [PATCH 2/3] Update root window size on ConfigureNotify This commit copies part of what XRRUpdateConfiguration() would do. When the root window is resized, we update the information that the X11 server sent to us when we connected to it to contain the new size of the root window. This is 50% ugly, but having our own copy of the root window size would be 51% ugly, so it's better to write to the XCB-owned structure. Right now this is all dead code anyway, because we restart anyway, but since the goal is to get rid of that restart, this is a step in the right direction (e.g. root.size() will automatically return the new size). Signed-off-by: Uli Schlachter --- event.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/event.c b/event.c index f7cdb0af8..2809916f9 100644 --- a/event.c +++ b/event.c @@ -397,13 +397,19 @@ event_handle_configurerequest(xcb_configure_request_event_t *ev) static void event_handle_configurenotify(xcb_configure_notify_event_t *ev) { - const xcb_screen_t *screen = globalconf.screen; + xcb_screen_t *screen = globalconf.screen; if(ev->window == screen->root && (ev->width != screen->width_in_pixels || ev->height != screen->height_in_pixels)) /* it's not that we panic, but restart */ awesome_restart(); + + /* Copy what XRRUpdateConfiguration() would do: Update the configuration */ + if(ev->window == screen->root) { + screen->width_in_pixels = ev->width; + screen->height_in_pixels = ev->height; + } } /** The destroy notify event handler. From 8a63c589a6e81f574a0984895ded2e2a6db9a6c1 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 9 Apr 2016 16:06:21 +0200 Subject: [PATCH 3/3] Update root window size on RandR notify The code that claims to do what XRRUpdateConfiguration() would do was actually wrong. That function does not send any requests to the X11 server, but it just updates the local, in-memory state. This commit makes us do the same: We update the size of the root window if it changed. The code is directly inspired from the code in libXrandr. Signed-off-by: Uli Schlachter --- event.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/event.c b/event.c index 2809916f9..83d388d2d 100644 --- a/event.c +++ b/event.c @@ -771,22 +771,18 @@ event_handle_unmapnotify(xcb_unmap_notify_event_t *ev) static void event_handle_randr_screen_change_notify(xcb_randr_screen_change_notify_event_t *ev) { - /* Code of XRRUpdateConfiguration Xlib function ported to XCB - * (only the code relevant to RRScreenChangeNotify) as the latter - * doesn't provide this kind of function */ - if(ev->rotation & (XCB_RANDR_ROTATION_ROTATE_90 | XCB_RANDR_ROTATION_ROTATE_270)) - xcb_randr_set_screen_size(globalconf.connection, ev->root, ev->height, ev->width, - ev->mheight, ev->mwidth); - else - xcb_randr_set_screen_size(globalconf.connection, ev->root, ev->width, ev->height, - ev->mwidth, ev->mheight); + /* Ignore events for other roots (do we get them at all?) */ + if (ev->root != globalconf.screen->root) + return; - /* XRRUpdateConfiguration also executes the following instruction - * but it's not useful because SubpixelOrder is not used at all at - * the moment - * - * XRenderSetSubpixelOrder(dpy, snum, scevent->subpixel_order); - */ + /* Do (part of) what XRRUpdateConfiguration() would do (update our state) */ + if (ev->rotation & (XCB_RANDR_ROTATION_ROTATE_90 | XCB_RANDR_ROTATION_ROTATE_270)) { + globalconf.screen->width_in_pixels = ev->height; + globalconf.screen->height_in_pixels = ev->width; + } else { + globalconf.screen->width_in_pixels = ev->width; + globalconf.screen->height_in_pixels = ev->height; + } awesome_restart(); }