Skip to content

Commit

Permalink
X11 - Move event insertion from interrupt to proxy wakeup.
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchmindtree committed May 31, 2017
1 parent 2b55b2e commit 38856b1
Showing 1 changed file with 36 additions and 23 deletions.
59 changes: 36 additions & 23 deletions src/platform/linux/x11/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ pub struct EventsLoop {

pub struct EventsLoopProxy {
pending_wakeup: Weak<AtomicBool>,
display: Weak<XConnection>,
root: ffi::Window,
}

impl EventsLoop {
Expand Down Expand Up @@ -111,29 +113,13 @@ impl EventsLoop {
pub fn create_proxy(&self) -> EventsLoopProxy {
EventsLoopProxy {
pending_wakeup: Arc::downgrade(&self.pending_wakeup),
display: Arc::downgrade(&self.display),
root: self.root,
}
}

pub fn interrupt(&self) {
self.interrupted.store(true, atomic::Ordering::Relaxed);

// Push an event on the X event queue so that methods like run_forever will advance.
let mut xev = ffi::XClientMessageEvent {
type_: ffi::ClientMessage,
window: self.root,
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, 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");
}
}

pub fn poll_events<F>(&self, mut callback: F)
Expand Down Expand Up @@ -165,13 +151,20 @@ impl EventsLoop {
where F: FnMut(Event)
{
self.interrupted.store(false, atomic::Ordering::Relaxed);
self.pending_wakeup.store(false, atomic::Ordering::Relaxed);

let xlib = &self.display.xlib;

let mut xev = unsafe { mem::uninitialized() };

loop {
unsafe { (xlib.XNextEvent)(self.display.display, &mut xev) }; // Blocks as necessary

if self.pending_wakeup.load(atomic::Ordering::Relaxed) {
self.pending_wakeup.store(false, atomic::Ordering::Relaxed);
callback(Event::Awakened);
}

self.process_event(&mut xev, &mut callback);
if self.interrupted.load(atomic::Ordering::Relaxed) {
break;
Expand Down Expand Up @@ -539,13 +532,33 @@ impl EventsLoop {
impl EventsLoopProxy {
pub fn wakeup(&self) -> Result<(), EventsLoopClosed> {
// Update the `EventsLoop`'s `pending_wakeup` flag.
match self.pending_wakeup.upgrade() {
Some(wakeup) => Ok(wakeup.store(true, atomic::Ordering::Relaxed)),
None => Err(EventsLoopClosed),
let display = match (self.pending_wakeup.upgrade(), self.display.upgrade()) {
(Some(wakeup), Some(display)) => {
wakeup.store(true, atomic::Ordering::Relaxed);
display
},
_ => return Err(EventsLoopClosed),
};

// Push an event on the X event queue so that methods like run_forever will advance.
let mut xev = ffi::XClientMessageEvent {
type_: ffi::ClientMessage,
window: self.root,
format: 32,
message_type: 0,
serial: 0,
send_event: 0,
display: display.display,
data: unsafe { mem::zeroed() },
};

unsafe {
(display.xlib.XSendEvent)(display.display, self.root, 0, 0, mem::transmute(&mut xev));
(display.xlib.XFlush)(display.display);
display.check_errors().expect("Failed to call XSendEvent after wakeup");
}

// TODO:
// Cause the `EventsLoop` to break if it is currently blocked.
Ok(())
}
}

Expand Down

0 comments on commit 38856b1

Please sign in to comment.