rust-windowing / winit

Window handling library in pure Rust

Home Page:https://docs.rs/winit/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Not receiving `RedrawRequested` events for all windows that `.request_redraw()`

ickk opened this issue · comments

commented

Description

When I create multiple windows with winit, and for each window call window.request_redraw() in the AboutToWait handler, I do not receive the corresponding WindowEvent::RedrawRequested for all of the windows that requested.


minimal reproduction:

use winit::{
    event::{Event, WindowEvent},
    event_loop::EventLoop,
    window::WindowBuilder,
};

const WINDOW_COUNT: usize = 5;

fn main() {
    let event_loop = EventLoop::new().unwrap();

    let windows = Vec::from_iter(
        std::iter::repeat_with(|| WindowBuilder::new().build(&event_loop).unwrap()).take(WINDOW_COUNT),
    );

    let mut ticks = 500;
    event_loop
        .run(|event, elwt| match event {
            Event::AboutToWait => {
                for (i, window) in windows.iter().enumerate() {
                    eprintln!("request_redraw for window {i}",);
                    window.request_redraw();
                }
                ticks -= 1;
                if ticks <= 0 {
                    elwt.exit()
                }
            }
            Event::WindowEvent {
                window_id,
                event: WindowEvent::RedrawRequested,
            } => {
                let i = windows.iter().position(|w| w.id() == window_id).unwrap();
                eprintln!("received RedrawRequested for window {i}");
            }
            _ => (),
        })
        .unwrap();
}

output observed:

..
request_redraw for window 0
request_redraw for window 1
request_redraw for window 2
request_redraw for window 3
request_redraw for window 4
received RedrawRequested for window 4
received RedrawRequested for window 3
request_redraw for window 0
request_redraw for window 1
request_redraw for window 2
request_redraw for window 3
request_redraw for window 4
received RedrawRequested for window 4
received RedrawRequested for window 3
..

that is, I only receive the RedrawRequested event for the last 2 windows.


If I also call request_redraw() inside the RedrawRequested handler for the given window, as follows:

            Event::WindowEvent {
                window_id,
                event: WindowEvent::RedrawRequested,
            } => {
                let i = windows.iter().position(|w| w.id() == window_id).unwrap();
                eprintln!("received RedrawRequested for window {i}, requesting redraw for window {i}");
                windows[i].request_redraw();
            }
            _ => (),

then I observe the following:

..
request_redraw for window 0
request_redraw for window 1
request_redraw for window 2
request_redraw for window 3
request_redraw for window 4
received RedrawRequested for window 4, requesting redraw for window 4
received RedrawRequested for window 4, requesting redraw for window 4
request_redraw for window 0
request_redraw for window 1
request_redraw for window 2
request_redraw for window 3
request_redraw for window 4
received RedrawRequested for window 4, requesting redraw for window 4
received RedrawRequested for window 4, requesting redraw for window 4
..

that is, I receive two consecutive RedrawRequested events (sometimes just 1), but only ever for the last window.


Neither approach behaves as I would expect. I would expect to reliably receive a single RedrawRequested event for each window

Windows version

Microsoft Windows [Version 10.0.19045.4291]

Winit version

v0.29.15

commented

I skimmed the source, and I think this might be because of the way winit tries to get RedrawWindow/WM_PAINT to throttle redraws?

Yes, redraws are throttled by the compositor usually, though, WM_PAINT looks so broken that winit should likely use something else.