-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Windows: set_control_flow has no effect from AboutToWait event #3215
Description
Consider this modified version of the timer.rs example:
#![allow(clippy::single_match)]
use std::time::Duration;
use simple_logger::SimpleLogger;
use winit::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
#[path = "util/fill.rs"]
mod fill;
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new().unwrap();
let window = WindowBuilder::new()
.with_title("A fantastic window!")
.build(&event_loop)
.unwrap();
event_loop.run(move |event, elwt| {
println!("{event:?}");
match event {
// New iteration: reset the control flow to Wait as we don't know if we will need to wait
Event::NewEvents(_) => elwt.set_control_flow(ControlFlow::Wait),
// ... some other event change internal data structures ...
Event::AboutToWait => {
// About to wait: query internal data structure to know how long we need to sleep
elwt.set_control_flow(ControlFlow::wait_duration(Duration::from_secs(1)));
}
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => elwt.exit(),
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
fill::fill_window(&window);
}
_ => (),
}
})
}
The gist here is that we set ControlFlow::Wait from NewEvents.
In our application some events such as mouse or keyboard event may start timers in a timer or actions. So at the end of the iteration, in AboutToWait, we set the control flow to the computed waiting time.
That works on Linux: we get new event every second from that example.
But on Windows, this blocks forever unless you move the mouse or something.
I've tried debugging this quickly, and it seems like the wait_and_dispatch_message function queries the control_flow here:
winit/src/platform_impl/windows/event_loop.rs
Line 363 in c89e6df
| let control_flow_timeout = match runner.control_flow() { |
And then sends the AboutToWait shortly after via
winit/src/platform_impl/windows/event_loop.rs
Line 416 in c89e6df
| runner.prepare_wait(); |
I believe this line should be moved before the line 363. Is that right?