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 <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2016-10-22 10:46:49 +02:00 committed by Daniel Hahler
parent 0b17e5dac3
commit 3bd045b57c
2 changed files with 20 additions and 1 deletions

View file

@ -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);

View file

@ -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;