mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-02-02 14:56:34 +11:00
Linux: Sync with server/compositor before exiting run_ondemand
Although we document that applications can't keep windows between separate run_ondemand calls it's possible that the application has only just dropped their windows and we need to flush these requests to the server/compositor. This fixes the window_ondemand example - by ensuring the window from the first loop really is destroyed before waiting for 5 seconds and starting the second loop.
This commit is contained in:
parent
9e46dffcc5
commit
ec11b4877f
2 changed files with 42 additions and 7 deletions
|
@ -16,13 +16,13 @@ use sctk::reexports::client::globals;
|
|||
use sctk::reexports::client::{Connection, Proxy, QueueHandle, WaylandSource};
|
||||
|
||||
use crate::dpi::{LogicalSize, PhysicalSize};
|
||||
use crate::error::RunLoopError;
|
||||
use crate::error::{OsError as RootOsError, RunLoopError};
|
||||
use crate::event::{Event, StartCause, WindowEvent};
|
||||
use crate::event_loop::{ControlFlow, EventLoopWindowTarget as RootEventLoopWindowTarget};
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
use crate::platform_impl::platform::min_timeout;
|
||||
use crate::platform_impl::platform::sticky_exit_callback;
|
||||
use crate::platform_impl::EventLoopWindowTarget as PlatformEventLoopWindowTarget;
|
||||
use crate::platform_impl::{EventLoopWindowTarget as PlatformEventLoopWindowTarget, OsError};
|
||||
|
||||
mod proxy;
|
||||
pub mod sink;
|
||||
|
@ -153,7 +153,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
return Err(RunLoopError::AlreadyRunning);
|
||||
}
|
||||
|
||||
loop {
|
||||
let exit = loop {
|
||||
match self.pump_events_with_timeout(None, &mut event_handler) {
|
||||
PumpStatus::Exit(0) => {
|
||||
break Ok(());
|
||||
|
@ -165,7 +165,15 @@ impl<T: 'static> EventLoop<T> {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Applications aren't allowed to carry windows between separate
|
||||
// `run_ondemand` calls but if they have only just dropped their
|
||||
// windows we need to make sure those last requests are sent to the
|
||||
// compositor.
|
||||
let _ = self.roundtrip().map_err(RunLoopError::Os);
|
||||
|
||||
exit
|
||||
}
|
||||
|
||||
pub fn pump_events<F>(&mut self, event_handler: F) -> PumpStatus
|
||||
|
@ -574,6 +582,22 @@ impl<T: 'static> EventLoop<T> {
|
|||
error.into()
|
||||
})
|
||||
}
|
||||
|
||||
fn roundtrip(&mut self) -> Result<usize, RootOsError> {
|
||||
let state = match &mut self.window_target.p {
|
||||
PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(),
|
||||
#[cfg(feature = "x11")]
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let mut wayland_source = self.wayland_dispatcher.as_source_mut();
|
||||
let event_queue = wayland_source.queue();
|
||||
event_queue.roundtrip(state).map_err(|_| {
|
||||
os_error!(OsError::WaylandMisc(
|
||||
"failed to do a final roundtrip before exiting the loop."
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EventLoopWindowTarget<T> {
|
||||
|
|
|
@ -62,7 +62,7 @@ use self::{
|
|||
event_processor::EventProcessor,
|
||||
ime::{Ime, ImeCreationError, ImeReceiver, ImeRequest, ImeSender},
|
||||
};
|
||||
use super::common::xkb_state::KbdState;
|
||||
use super::{common::xkb_state::KbdState, OsError};
|
||||
use crate::{
|
||||
error::{OsError as RootOsError, RunLoopError},
|
||||
event::{Event, StartCause},
|
||||
|
@ -440,7 +440,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
return Err(RunLoopError::AlreadyRunning);
|
||||
}
|
||||
|
||||
loop {
|
||||
let exit = loop {
|
||||
match self.pump_events_with_timeout(None, &mut event_handler) {
|
||||
PumpStatus::Exit(0) => {
|
||||
break Ok(());
|
||||
|
@ -452,7 +452,18 @@ impl<T: 'static> EventLoop<T> {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Applications aren't allowed to carry windows between separate
|
||||
// `run_ondemand` calls but if they have only just dropped their
|
||||
// windows we need to make sure those last requests are sent to the
|
||||
// X Server.
|
||||
let wt = get_xtarget(&self.target);
|
||||
wt.x_connection().sync_with_server().map_err(|x_err| {
|
||||
RunLoopError::Os(os_error!(OsError::XError(Arc::new(X11Error::Xlib(x_err)))))
|
||||
})?;
|
||||
|
||||
exit
|
||||
}
|
||||
|
||||
pub fn pump_events<F>(&mut self, event_handler: F) -> PumpStatus
|
||||
|
|
Loading…
Add table
Reference in a new issue