Skip to content

pump_events blocks with timout set to 0 in wayland #4130

@sigmaSd

Description

@sigmaSd

Description

The docs of pump_events says it will never block if the timeout is 0

Passing a timeout of Some(Duration::ZERO) would ensure your external event loop is never blocked but you would likely need to consider how to throttle your own external loop.
(from https://docs.rs/winit/latest/winit/platform/pump_events/trait.EventLoopExtPumpEvents.html#tymethod.pump_events )

But there is a case in which it can block in wayland, and that is if the control flow is set to Wait and there are no events
Here is a simple reproduction, there are 3 XXX comments that explains my findings

fn main() -> std::process::ExitCode {
    use std::process::ExitCode;
    use std::thread::sleep;
    use std::time::Duration;

    use winit::application::ApplicationHandler;
    use winit::event::WindowEvent;
    use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
    use winit::platform::pump_events::{EventLoopExtPumpEvents, PumpStatus};
    use winit::window::{Window, WindowId};

    #[derive(Default)]
    struct PumpDemo {
        window: Option<Window>,
    }

    impl ApplicationHandler for PumpDemo {
        fn resumed(&mut self, event_loop: &ActiveEventLoop) {
            let window_attributes = Window::default_attributes().with_title("A fantastic window!");
            self.window = Some(event_loop.create_window(window_attributes).unwrap());
        }

        fn window_event(
            &mut self,
            event_loop: &ActiveEventLoop,
            _window_id: WindowId,
            event: WindowEvent,
        ) {
            println!("{event:?}");

            let window = match self.window.as_ref() {
                Some(window) => window,
                None => return,
            };

            match event {
                WindowEvent::CloseRequested => event_loop.exit(),
                WindowEvent::RedrawRequested => {
                    // XXX: If I uncomment this the event loop will continue working regardless of ControlFlow
                    // window.request_redraw();
                }
                _ => (),
            }
        }
    }

    let mut event_loop = EventLoop::new().unwrap();
    // XXX With Wait the event loop gets blocked unless I uncomment window redraw
   // If I change it to Poll the event loop never gets blocked even without redraw requests
   // In X11 even with Wait and no redraw requests, the event loop does not get blocked
    event_loop.set_control_flow(ControlFlow::Wait);

    let mut app = PumpDemo::default();

    loop {
        let timeout = Some(Duration::ZERO);
        // XXX: the block happen here
        let status = event_loop.pump_app_events(timeout, &mut app);

        if let PumpStatus::Exit(exit_code) = status {
            break ExitCode::from(exit_code as u8);
        }

        println!("Update()");
        sleep(Duration::from_millis(16));
    }
}

I reached here while debugging slint-ui/slint#7657

Window isn't shown unless you draw

  • I understand that windows aren't shown on Wayland unless I draw and present to them.

Winit version

0.30.9

Metadata

Metadata

Assignees

No one assigned

    Labels

    B - bugDang, that shouldn't have happenedDS - waylandAffects the Wayland backend, or generally free Unix platforms

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions