X11: Fix events not being reported when using run_return (#1245)

* X11: Fix events not being reported using `run_return`

* Adapt examples to be more practical

* Add CHANGELOG entry
This commit is contained in:
Murarth 2019-11-10 11:24:43 -07:00 committed by Hal Gentz
parent c66784995d
commit 1ed15c7ec7
5 changed files with 88 additions and 78 deletions

View file

@ -1,6 +1,7 @@
# Unreleased # Unreleased
- On macOS, fix application termination on `ControlFlow::Exit` - On macOS, fix application termination on `ControlFlow::Exit`
- On X11, fix events not being reported when using `run_return`.
- On X11, fix key modifiers being incorrectly reported. - On X11, fix key modifiers being incorrectly reported.
# 0.20.0 Alpha 4 (2019-10-18) # 0.20.0 Alpha 4 (2019-10-18)

View file

@ -17,7 +17,10 @@ fn main() {
let timer_length = Duration::new(1, 0); let timer_length = Duration::new(1, 0);
event_loop.run(move |event, _, control_flow| { event_loop.run(move |event, _, control_flow| {
println!("{:?}", event); if let Event::WindowEvent { event, .. } = &event {
// Print only Window events to reduce noise
println!("{:?}", event);
}
match event { match event {
Event::NewEvents(StartCause::Init) => { Event::NewEvents(StartCause::Init) => {

View file

@ -9,6 +9,7 @@
target_os = "openbsd" target_os = "openbsd"
))] ))]
fn main() { fn main() {
use std::{thread::sleep, time::Duration};
use winit::{ use winit::{
event::{Event, WindowEvent}, event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop}, event_loop::{ControlFlow, EventLoop},
@ -17,36 +18,38 @@ fn main() {
}; };
let mut event_loop = EventLoop::new(); let mut event_loop = EventLoop::new();
let window = WindowBuilder::new() let _window = WindowBuilder::new()
.with_title("A fantastic window!") .with_title("A fantastic window!")
.build(&event_loop) .build(&event_loop)
.unwrap(); .unwrap();
println!("Close the window to continue."); let mut quit = false;
event_loop.run_return(|event, _, control_flow| match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
_ => *control_flow = ControlFlow::Wait,
});
drop(window);
let _window_2 = WindowBuilder::new() while !quit {
.with_title("A second, fantasticer window!") event_loop.run_return(|event, _, control_flow| {
.build(&event_loop) if let Event::WindowEvent { event, .. } = &event {
.unwrap(); // Print only Window events to reduce noise
println!("{:?}", event);
}
println!("Wa ha ha! You thought that closing the window would finish this?!"); match event {
event_loop.run_return(|event, _, control_flow| match event { Event::WindowEvent {
Event::WindowEvent { event: WindowEvent::CloseRequested,
event: WindowEvent::CloseRequested, ..
.. } => {
} => *control_flow = ControlFlow::Exit, quit = true;
_ => *control_flow = ControlFlow::Wait, *control_flow = ControlFlow::Exit;
}); }
Event::EventsCleared => {
*control_flow = ControlFlow::Exit;
}
_ => *control_flow = ControlFlow::Wait,
}
});
println!("Okay we're done now for real."); // Sleep for 1/60 second to simulate rendering
sleep(Duration::from_millis(16));
}
} }
#[cfg(any(target_os = "ios", target_os = "android", target_arch = "wasm32"))] #[cfg(any(target_os = "ios", target_os = "android", target_arch = "wasm32"))]

View file

@ -66,6 +66,13 @@ impl<T: 'static> EventProcessor<T> {
self.with_window(window_id, |_| ()).is_some() self.with_window(window_id, |_| ()).is_some()
} }
pub(super) fn poll(&self) -> bool {
let wt = get_xtarget(&self.target);
let result = unsafe { (wt.xconn.xlib.XPending)(wt.xconn.display) };
result != 0
}
pub(super) unsafe fn poll_one_event(&mut self, event_ptr: *mut ffi::XEvent) -> bool { pub(super) unsafe fn poll_one_event(&mut self, event_ptr: *mut ffi::XEvent) -> bool {
let wt = get_xtarget(&self.target); let wt = get_xtarget(&self.target);
// This function is used to poll and remove a single event // This function is used to poll and remove a single event

View file

@ -26,6 +26,7 @@ use std::{
rc::Rc, rc::Rc,
slice, slice,
sync::{mpsc, Arc, Mutex, Weak}, sync::{mpsc, Arc, Mutex, Weak},
time::{Duration, Instant},
}; };
use libc::{self, setlocale, LC_CTYPE}; use libc::{self, setlocale, LC_CTYPE};
@ -38,7 +39,7 @@ use self::{
}; };
use crate::{ use crate::{
error::OsError as RootOsError, error::OsError as RootOsError,
event::{Event, WindowEvent}, event::{Event, StartCause, WindowEvent},
event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW}, event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW},
platform_impl::{platform::sticky_exit_callback, PlatformSpecificWindowBuilderAttributes}, platform_impl::{platform::sticky_exit_callback, PlatformSpecificWindowBuilderAttributes},
window::WindowAttributes, window::WindowAttributes,
@ -262,6 +263,8 @@ impl<T: 'static> EventLoop<T> {
); );
loop { loop {
self.drain_events();
// Empty the event buffer // Empty the event buffer
{ {
let mut guard = self.pending_events.borrow_mut(); let mut guard = self.pending_events.borrow_mut();
@ -309,69 +312,58 @@ impl<T: 'static> EventLoop<T> {
); );
} }
let start = Instant::now();
let (mut cause, deadline, mut timeout);
match control_flow { match control_flow {
ControlFlow::Exit => break, ControlFlow::Exit => break,
ControlFlow::Poll => { ControlFlow::Poll => {
// non-blocking dispatch cause = StartCause::Poll;
self.inner_loop deadline = None;
.dispatch(Some(::std::time::Duration::from_millis(0)), &mut ()) timeout = Some(Duration::from_millis(0));
.unwrap();
callback(
crate::event::Event::NewEvents(crate::event::StartCause::Poll),
&self.target,
&mut control_flow,
);
} }
ControlFlow::Wait => { ControlFlow::Wait => {
self.inner_loop.dispatch(None, &mut ()).unwrap(); cause = StartCause::WaitCancelled {
callback( start,
crate::event::Event::NewEvents(crate::event::StartCause::WaitCancelled { requested_resume: None,
start: ::std::time::Instant::now(),
requested_resume: None,
}),
&self.target,
&mut control_flow,
);
}
ControlFlow::WaitUntil(deadline) => {
let start = ::std::time::Instant::now();
// compute the blocking duration
let duration = if deadline > start {
deadline - start
} else {
::std::time::Duration::from_millis(0)
}; };
self.inner_loop.dispatch(Some(duration), &mut ()).unwrap(); deadline = None;
let now = std::time::Instant::now(); timeout = None;
if now < deadline { }
callback( ControlFlow::WaitUntil(wait_deadline) => {
crate::event::Event::NewEvents( cause = StartCause::ResumeTimeReached {
crate::event::StartCause::WaitCancelled { start,
start, requested_resume: wait_deadline,
requested_resume: Some(deadline), };
}, timeout = if wait_deadline > start {
), Some(wait_deadline - start)
&self.target,
&mut control_flow,
);
} else { } else {
callback( Some(Duration::from_millis(0))
crate::event::Event::NewEvents( };
crate::event::StartCause::ResumeTimeReached { deadline = Some(wait_deadline);
start,
requested_resume: deadline,
},
),
&self.target,
&mut control_flow,
);
}
} }
} }
// If the user callback had any interaction with the X server, if self.events_waiting() {
// it may have received and buffered some user input events. timeout = Some(Duration::from_millis(0));
self.drain_events(); }
self.inner_loop.dispatch(timeout, &mut ()).unwrap();
if let Some(deadline) = deadline {
if deadline > Instant::now() {
cause = StartCause::WaitCancelled {
start,
requested_resume: Some(deadline),
};
}
}
callback(
crate::event::Event::NewEvents(cause),
&self.target,
&mut control_flow,
);
} }
callback( callback(
@ -395,6 +387,10 @@ impl<T: 'static> EventLoop<T> {
drain_events(&mut processor, &mut pending_events); drain_events(&mut processor, &mut pending_events);
} }
fn events_waiting(&self) -> bool {
!self.pending_events.borrow().is_empty() || self.event_processor.borrow().poll()
}
} }
fn drain_events<T: 'static>( fn drain_events<T: 'static>(