From f3db0ba641658e52ed564f0fe9c50bd4d86a2a14 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Tue, 9 May 2017 09:51:00 -0700 Subject: [PATCH] Fix x11 interrupt to actually wake event loop This is the same behavior as with WindowProxy::wakeup_event_loop in previous versions. Unfortunately, `EventsLoop::interrupt` is also the recommend way to exit a `run_forever` loop from within the event handler callback. Pushing an extra event on the queue in that case is simply wasteful. Changing this would require a refactor taking one of two possible forms: 1. Add a method *in addition* to interrupt intended for waking up the event loop 2. Add a return type to the event callback like enum Continue { True, False } which would be used in lieu of the atomic interrupt flag. --- src/platform/linux/x11/mod.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/platform/linux/x11/mod.rs b/src/platform/linux/x11/mod.rs index 7fbccda8..2c8ac3f3 100644 --- a/src/platform/linux/x11/mod.rs +++ b/src/platform/linux/x11/mod.rs @@ -103,6 +103,37 @@ impl EventsLoop { pub fn interrupt(&self) { self.interrupted.store(true, ::std::sync::atomic::Ordering::Relaxed); + + // Push an event on the X event queue so that methods like run_forever will advance. + + // Get a window for the event. + // + // It should not matter which window is used since the purpose is merely + // to advance the event loop. + let window = { + let windows = self.windows.lock().unwrap(); + match windows.keys().nth(0) { + Some(window_id) => window_id.0, + None => return + } + }; + + let mut xev = ffi::XClientMessageEvent { + type_: ffi::ClientMessage, + window: window, + format: 32, + message_type: 0, + serial: 0, + send_event: 0, + display: self.display.display, + data: unsafe { mem::zeroed() }, + }; + + unsafe { + (self.display.xlib.XSendEvent)(self.display.display, window, 0, 0, mem::transmute(&mut xev)); + (self.display.xlib.XFlush)(self.display.display); + self.display.check_errors().expect("Failed to call XSendEvent after wakeup"); + } } pub fn poll_events(&self, mut callback: F)