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.
This commit is contained in:
Joe Wilm 2017-05-09 09:51:00 -07:00
parent 8288d419fd
commit f3db0ba641

View file

@ -103,6 +103,37 @@ impl EventsLoop {
pub fn interrupt(&self) { pub fn interrupt(&self) {
self.interrupted.store(true, ::std::sync::atomic::Ordering::Relaxed); 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<F>(&self, mut callback: F) pub fn poll_events<F>(&self, mut callback: F)