mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-11 13:31:29 +11:00
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:
parent
c66784995d
commit
1ed15c7ec7
|
@ -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)
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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"))]
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>(
|
||||||
|
|
Loading…
Reference in a new issue