Skip to content

Windows: set_control_flow has no effect from AboutToWait event #3215

@ogoffart

Description

@ogoffart

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:

let control_flow_timeout = match runner.control_flow() {

And then sends the AboutToWait shortly after via
runner.prepare_wait();

I believe this line should be moved before the line 363. Is that right?

Metadata

Metadata

Assignees

No one assigned

    Labels

    B - bugDang, that shouldn't have happenedDS - win32Affects the Win32/Windows backend

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions