From e5eb2536987f13151bf05b595ce01ad5aaa4b333 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 4 Jul 2023 23:28:43 +0100 Subject: [PATCH] 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. --- examples/window_ondemand.rs | 73 +++++++++++++++---------------------- 1 file changed, 29 insertions(+), 44 deletions(-) diff --git a/examples/window_ondemand.rs b/examples/window_ondemand.rs index 1960b163..b1b3c56d 100644 --- a/examples/window_ondemand.rs +++ b/examples/window_ondemand.rs @@ -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, window: Option, } 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 }