From bd1ac6cb1ee9cf73eb0dbe0665dec815142766bc Mon Sep 17 00:00:00 2001 From: Murarth Date: Wed, 17 Jul 2019 11:09:02 -0700 Subject: [PATCH] X11: Fix events not being reported promptly (#1048) * X11: Fix events not being reported promptly * Add an entry to the changelog --- CHANGELOG.md | 1 + src/platform_impl/linux/x11/mod.rs | 46 +++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4665ca5..e602b73c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and `WindowEvent::HoveredFile`. - On Windows, fix `with_maximized` not properly setting window size to entire window. - On macOS, change `WindowExtMacOS::request_user_attention()` to take an `enum` instead of a `bool`. - On Windows, location of `WindowEvent::Touch` are window client coordinates instead of screen coordinates. +- On X11, fix delayed events after window redraw. # 0.20.0 Alpha 1 (2019-06-21) diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 45220f8b..45f1e3d3 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -60,6 +60,7 @@ pub struct EventLoop { _x11_source: ::calloop::Source<::calloop::generic::Generic<::calloop::generic::EventedRawFd>>, _user_source: ::calloop::Source<::calloop::channel::Channel>, pending_user_events: Rc>>, + event_processor: Rc>>, user_sender: ::calloop::channel::Sender, pending_events: Rc>>>, target: Rc>, @@ -171,7 +172,7 @@ impl EventLoop { // Handle X11 events let pending_events: Rc>> = Default::default(); - let mut processor = EventProcessor { + let processor = EventProcessor { target: target.clone(), dnd, devices: Default::default(), @@ -189,6 +190,9 @@ impl EventLoop { processor.init_device(ffi::XIAllDevices); + let processor = Rc::new(RefCell::new(processor)); + let event_processor = processor.clone(); + // Setup the X11 event source let mut x11_events = ::calloop::generic::Generic::from_raw_fd(get_xtarget(&target).xconn.x11_fd); @@ -197,17 +201,11 @@ impl EventLoop { .handle() .insert_source(x11_events, { let pending_events = pending_events.clone(); - let mut callback = move |event| { - pending_events.borrow_mut().push_back(event); - }; move |evt, &mut ()| { if evt.readiness.is_readable() { - // process all pending events - let mut xev = MaybeUninit::uninit(); - while unsafe { processor.poll_one_event(xev.as_mut_ptr()) } { - let mut xev = unsafe { xev.assume_init() }; - processor.process_event(&mut xev, &mut callback); - } + let mut processor = processor.borrow_mut(); + let mut pending_events = pending_events.borrow_mut(); + drain_events(&mut processor, &mut pending_events); } } }) @@ -220,6 +218,7 @@ impl EventLoop { _user_source, user_sender, pending_user_events, + event_processor, target, }; @@ -362,6 +361,10 @@ impl EventLoop { } } } + + // If the user callback had any interaction with the X server, + // it may have received and buffered some user input events. + self.drain_events(); } callback( @@ -378,6 +381,29 @@ impl EventLoop { self.run_return(callback); ::std::process::exit(0); } + + fn drain_events(&self) { + let mut processor = self.event_processor.borrow_mut(); + let mut pending_events = self.pending_events.borrow_mut(); + + drain_events(&mut processor, &mut pending_events); + } +} + +fn drain_events( + processor: &mut EventProcessor, + pending_events: &mut VecDeque>, +) { + let mut callback = |event| { + pending_events.push_back(event); + }; + + // process all pending events + let mut xev = MaybeUninit::uninit(); + while unsafe { processor.poll_one_event(xev.as_mut_ptr()) } { + let mut xev = unsafe { xev.assume_init() }; + processor.process_event(&mut xev, &mut callback); + } } fn get_xtarget(rt: &RootELW) -> &EventLoopWindowTarget {