From c92ac695afc12f46e7a7d0b6e944fa950c6679d3 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Tue, 9 May 2017 09:20:35 -0700 Subject: [PATCH 1/5] Fix x11 poll_events to drain queue It was only processing a single event per call. The docs say > Fetches all the events that are pending, calls the callback function > for each of them, and returns. which suggests that was incorrect. --- src/platform/linux/x11/mod.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/platform/linux/x11/mod.rs b/src/platform/linux/x11/mod.rs index 78eb9586..c21f6203 100644 --- a/src/platform/linux/x11/mod.rs +++ b/src/platform/linux/x11/mod.rs @@ -111,16 +111,22 @@ impl EventsLoop { let xlib = &self.display.xlib; let mut xev = unsafe { mem::uninitialized() }; - unsafe { - // Ensure XNextEvent won't block - let count = (xlib.XPending)(self.display.display); - if count == 0 { - return; + loop { + // Get next event + unsafe { + // Ensure XNextEvent won't block + let count = (xlib.XPending)(self.display.display); + if count == 0 { + break; + } + + (xlib.XNextEvent)(self.display.display, &mut xev); + } + self.process_event(&mut xev, &mut callback); + if self.interrupted.load(::std::sync::atomic::Ordering::Relaxed) { + break; } - - (xlib.XNextEvent)(self.display.display, &mut xev); } - self.process_event(&mut xev, &mut callback); } pub fn run_forever(&self, mut callback: F) From 8288d419fd0370e84e703a9ce678aff91fa911e9 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Tue, 9 May 2017 09:50:16 -0700 Subject: [PATCH 2/5] Remove unnecessary mut --- src/platform/linux/x11/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/linux/x11/mod.rs b/src/platform/linux/x11/mod.rs index c21f6203..7fbccda8 100644 --- a/src/platform/linux/x11/mod.rs +++ b/src/platform/linux/x11/mod.rs @@ -234,7 +234,7 @@ impl EventsLoop { let mut ev_mods = ModifiersState::default(); - let mut keysym = unsafe { + let keysym = unsafe { (self.display.xlib.XKeycodeToKeysym)(self.display.display, xkev.keycode as ffi::KeyCode, 0) }; From f3db0ba641658e52ed564f0fe9c50bd4d86a2a14 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Tue, 9 May 2017 09:51:00 -0700 Subject: [PATCH 3/5] 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) From 6c5bc52a5f98d04fb7805dd5832b8f0e9c79eef9 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Tue, 9 May 2017 09:55:10 -0700 Subject: [PATCH 4/5] Bump Cargo.toml version to match crates.io This makes is possible for consumers to use cargo [replace] with the latest Glutin. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 31c72d1e..23adc010 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "winit" -version = "0.6.3" +version = "0.6.4" authors = ["The winit contributors, Pierre Krieger "] description = "Cross-platform window creation library." keywords = ["windowing"] From 46057d71220ea6072d9bce1d3504aca2fe3a86a4 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Tue, 9 May 2017 21:30:31 -0700 Subject: [PATCH 5/5] Remove unnecessary locking For X11 interrupt, we can just use the root window which doesn't require taking a lock to find. --- src/platform/linux/x11/mod.rs | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/platform/linux/x11/mod.rs b/src/platform/linux/x11/mod.rs index 2c8ac3f3..9f9f06f3 100644 --- a/src/platform/linux/x11/mod.rs +++ b/src/platform/linux/x11/mod.rs @@ -105,22 +105,9 @@ impl EventsLoop { 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, + window: self.root, format: 32, message_type: 0, serial: 0, @@ -130,7 +117,7 @@ impl EventsLoop { }; unsafe { - (self.display.xlib.XSendEvent)(self.display.display, window, 0, 0, mem::transmute(&mut xev)); + (self.display.xlib.XSendEvent)(self.display.display, self.root, 0, 0, mem::transmute(&mut xev)); (self.display.xlib.XFlush)(self.display.display); self.display.check_errors().expect("Failed to call XSendEvent after wakeup"); }