window_ondemand: wait for Destroyed event before exiting app

Considering the strict requirement that applications can't keep windows
across run_ondemand calls, this tries to make the window_ondemand example
explicitly wait for its Window to be destroyed before exiting each
run_ondemand iteration.

This updates the example to only `.set_exit()` after it gets a
`Destroyed` event after the Window has been dropped.

On Windows this works to ensure the Window is destroyed before the
example waits for 5 seconds.

Unfortunately though:
1. The Wayland backend doesn't emit `Destroyed` events for windows
2. The macOS backend emits `Destroyed` events before the window is
   really destroyed.

and so the example isn't currently portable.
This commit is contained in:
Robert Bragg 2023-07-04 23:28:43 +01:00 committed by Kirill Chibisov
parent ec11b4877f
commit e5eb253698

View file

@ -3,13 +3,16 @@
// Limit this example to only compatible platforms.
#[cfg(any(windows_platform, macos_platform, x11_platform, wayland_platform,))]
fn main() -> Result<(), impl std::error::Error> {
use std::time::Duration;
use simple_logger::SimpleLogger;
use winit::{
error::RunLoopError,
event::{Event, WindowEvent},
event_loop::EventLoop,
platform::run_ondemand::EventLoopExtRunOnDemand,
window::{Window, WindowBuilder},
window::{Window, WindowBuilder, WindowId},
};
#[path = "util/fill.rs"]
@ -17,18 +20,19 @@ fn main() -> Result<(), impl std::error::Error> {
#[derive(Default)]
struct App {
window_id: Option<WindowId>,
window: Option<Window>,
}
SimpleLogger::new().init().unwrap();
let mut event_loop = EventLoop::new();
{
fn run_app(event_loop: &mut EventLoop<()>, idx: usize) -> Result<(), RunLoopError> {
let mut app = App::default();
event_loop.run_ondemand(move |event, event_loop, control_flow| {
control_flow.set_wait();
println!("Run 1: {:?}", event);
println!("Run {idx}: {:?}", event);
if let Some(window) = &app.window {
match event {
@ -36,8 +40,8 @@ fn main() -> Result<(), impl std::error::Error> {
event: WindowEvent::CloseRequested,
window_id,
} if window.id() == window_id => {
println!("--------------------------------------------------------- Window {idx} CloseRequested");
app.window = None;
control_flow.set_exit();
}
Event::MainEventsCleared => window.request_redraw(),
Event::RedrawRequested(_) => {
@ -45,56 +49,37 @@ fn main() -> Result<(), impl std::error::Error> {
}
_ => (),
}
} else if let Some(id) = app.window_id {
match event {
Event::WindowEvent {
event: WindowEvent::Destroyed,
window_id,
} if id == window_id => {
println!("--------------------------------------------------------- Window {idx} Destroyed");
app.window_id = None;
control_flow.set_exit();
}
_ => (),
}
} else if let Event::Resumed = event {
app.window = Some(
WindowBuilder::new()
let window = WindowBuilder::new()
.with_title("Fantastic window number one!")
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0))
.build(event_loop)
.unwrap(),
);
.unwrap();
app.window_id = Some(window.id());
app.window = Some(window);
}
})?;
})
}
run_app(&mut event_loop, 1)?;
println!("--------------------------------------------------------- Finished first loop");
println!("--------------------------------------------------------- Waiting 5 seconds");
std::thread::sleep_ms(5000);
let ret = {
let mut app = App::default();
event_loop.run_ondemand(move |event, event_loop, control_flow| {
control_flow.set_wait();
println!("Run 2: {:?}", event);
if let Some(window) = &app.window {
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
window_id,
} if window.id() == window_id => {
app.window = None;
control_flow.set_exit();
}
Event::MainEventsCleared => window.request_redraw(),
Event::RedrawRequested(_) => {
fill::fill_window(window);
}
_ => (),
}
} else if let Event::Resumed = event {
app.window = Some(
WindowBuilder::new()
.with_title("Fantastic window number two!")
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0))
.build(event_loop)
.unwrap(),
);
}
})
};
std::thread::sleep(Duration::from_secs(5));
let ret = run_app(&mut event_loop, 2);
println!("--------------------------------------------------------- Finished second loop");
ret
}