mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-12 05:31:31 +11:00
wayland: instantly wake up if events are pending (#1153)
Just before starting to poll/wait on calloop(mio), check if there are already events pending in the internal buffer of our wayland event queue. If so, dispatch them and force an instant wakeup from the polling, in order to behave as if we were instantly woken up by incoming wayland events. When using OpenGL, mesa shares our wayland socket, and also reads from it, especially if vsync is enabled as it'll do blocking reads. When doing so, it may enqueue events in the internal buffer of our event queue. As the socket has been read, mio will thus not notify it to calloop as read, and thus calloop will not know it needs to dispatch. In some cases this can lead to some events being delivered much later than they should. Combined with key repetition this can actually cause some flooding of the event queue making this effect event worse. Fixes #1148
This commit is contained in:
parent
068d114740
commit
a3739d6bad
|
@ -314,6 +314,25 @@ impl<T: 'static> EventLoop<T> {
|
||||||
// send pending events to the server
|
// send pending events to the server
|
||||||
self.display.flush().expect("Wayland connection lost.");
|
self.display.flush().expect("Wayland connection lost.");
|
||||||
|
|
||||||
|
// During the run of the user callback, some other code monitoring and reading the
|
||||||
|
// wayland socket may have been run (mesa for example does this with vsync), if that
|
||||||
|
// is the case, some events may have been enqueued in our event queue.
|
||||||
|
//
|
||||||
|
// If some messages are there, the event loop needs to behave as if it was instantly
|
||||||
|
// woken up by messages arriving from the wayland socket, to avoid getting stuck.
|
||||||
|
let instant_wakeup = {
|
||||||
|
let window_target = match self.window_target.p {
|
||||||
|
crate::platform_impl::EventLoopWindowTarget::Wayland(ref wt) => wt,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let dispatched = window_target
|
||||||
|
.evq
|
||||||
|
.borrow_mut()
|
||||||
|
.dispatch_pending()
|
||||||
|
.expect("Wayland connection lost.");
|
||||||
|
dispatched > 0
|
||||||
|
};
|
||||||
|
|
||||||
match control_flow {
|
match control_flow {
|
||||||
ControlFlow::Exit => break,
|
ControlFlow::Exit => break,
|
||||||
ControlFlow::Poll => {
|
ControlFlow::Poll => {
|
||||||
|
@ -328,7 +347,12 @@ impl<T: 'static> EventLoop<T> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ControlFlow::Wait => {
|
ControlFlow::Wait => {
|
||||||
self.inner_loop.dispatch(None, &mut ()).unwrap();
|
let timeout = if instant_wakeup {
|
||||||
|
Some(::std::time::Duration::from_millis(0))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
self.inner_loop.dispatch(timeout, &mut ()).unwrap();
|
||||||
callback(
|
callback(
|
||||||
crate::event::Event::NewEvents(crate::event::StartCause::WaitCancelled {
|
crate::event::Event::NewEvents(crate::event::StartCause::WaitCancelled {
|
||||||
start: Instant::now(),
|
start: Instant::now(),
|
||||||
|
@ -341,7 +365,7 @@ impl<T: 'static> EventLoop<T> {
|
||||||
ControlFlow::WaitUntil(deadline) => {
|
ControlFlow::WaitUntil(deadline) => {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
// compute the blocking duration
|
// compute the blocking duration
|
||||||
let duration = if deadline > start {
|
let duration = if deadline > start && !instant_wakeup {
|
||||||
deadline - start
|
deadline - start
|
||||||
} else {
|
} else {
|
||||||
::std::time::Duration::from_millis(0)
|
::std::time::Duration::from_millis(0)
|
||||||
|
|
Loading…
Reference in a new issue