From 3bd045b57cafd7e113bee8bf42aed8af79696581 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 22 Oct 2016 10:46:49 +0200 Subject: [PATCH] Check for pending events after the main loop (#1163) At the beginning of every main loop iteration, we check for new events from the X11 server. However, it's theoretically possible that during a main loop iteration new events arrive and are read by libxcb into its internal buffer. This would mean that the fd connected to the X11 server is not readable and thus we do not wake up to handle these events. Handle this by checking for pending events before calling poll(). If a new events appears, we set the timeout for poll() to zero and will then handle the new event in the following iteration of the main loop. Signed-off-by: Uli Schlachter --- awesome.c | 19 ++++++++++++++++++- globalconf.h | 2 ++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/awesome.c b/awesome.c index 16f5eed39..eb347d60f 100644 --- a/awesome.c +++ b/awesome.c @@ -295,12 +295,23 @@ acquire_WM_Sn(bool replace) xcb_send_event(globalconf.connection, false, globalconf.screen->root, 0xFFFFFF, (char *) &ev); } +static xcb_generic_event_t *poll_for_event(void) +{ + if (globalconf.pending_event) { + xcb_generic_event_t *event = globalconf.pending_event; + globalconf.pending_event = NULL; + return event; + } + + return xcb_poll_for_event(globalconf.connection); +} + static void a_xcb_check(void) { xcb_generic_event_t *mouse = NULL, *event; - while((event = xcb_poll_for_event(globalconf.connection))) + while((event = poll_for_event())) { /* We will treat mouse events later. * We cannot afford to treat all mouse motion events, @@ -364,6 +375,12 @@ a_glib_poll(GPollFD *ufds, guint nfsd, gint timeout) lua_settop(L, 0); } + /* Don't sleep if there is a pending event */ + assert(globalconf.pending_event == NULL); + globalconf.pending_event = xcb_poll_for_event(globalconf.connection); + if (globalconf.pending_event != NULL) + timeout = 0; + /* Check how long this main loop iteration took */ gettimeofday(&now, NULL); timersub(&now, &last_wakeup, &length_time); diff --git a/globalconf.h b/globalconf.h index ae729f2ac..2560531b6 100644 --- a/globalconf.h +++ b/globalconf.h @@ -192,6 +192,8 @@ typedef struct xcb_void_cookie_t pending_enter_leave_begin; /** List of windows to be destroyed later */ window_array_t destroy_later_windows; + /** Pending event that still needs to be handled */ + xcb_generic_event_t *pending_event; } awesome_t; extern awesome_t globalconf;