Skip to content

Can't create event loop ondemand #2431

@emilk

Description

@emilk

I want to be able to open a window, use event_loop.run_return to process some events on it, then close it, and then later open another window. When I try this on my Mac, I find that the second time I run run_return I get Event::LoopDestroyed almost immediately, and the new window is destroyed. This is the code I'm running:

fn main() {
    use winit::{
        event::{Event, WindowEvent},
        event_loop::EventLoop,
        platform::run_return::EventLoopExtRunReturn,
        window::WindowBuilder,
    };

    fn show_window(event_loop: &mut EventLoop<()>, window_name: &str) {
        eprintln!("Creating window {:?}", window_name);

        let window = WindowBuilder::new()
            .with_title(window_name)
            .build(event_loop)
            .unwrap();

        event_loop.run_return(|event, _, control_flow| {
            control_flow.set_wait();

            match event {
                Event::LoopDestroyed => {
                    eprintln!("Event::LoopDestroyed.");
                }

                // Platform-dependent event handlers to workaround a winit bug
                // See: https://github.com/rust-windowing/winit/issues/987
                // See: https://github.com/rust-windowing/winit/issues/1619
                Event::RedrawEventsCleared if cfg!(windows) => {
                    println!("rendering");
                }
                Event::RedrawRequested(_) if !cfg!(windows) => {
                    println!("rendering");
                }

                Event::WindowEvent { window_id, .. } if window_id != window.id() => {
                    // This can happen if we close a window, and then reopen a new one,
                    // or if we have multiple windows open.
                    eprintln!("Ignoring event to old window");
                }
                Event::WindowEvent {
                    event: WindowEvent::CloseRequested,
                    ..
                } => {
                    eprintln!("WindowEvent::CloseRequested");
                    control_flow.set_exit();
                }
                Event::WindowEvent {
                    event: WindowEvent::Destroyed,
                    ..
                } => {
                    eprintln!("WindowEvent::Destroyed");
                    control_flow.set_exit();
                }
                _ => (),
            }
        });

        eprintln!("-----------------");
    }

    let mut event_loop = EventLoop::new();
    show_window(&mut event_loop, "First Window");
    show_window(&mut event_loop, "Second Window");
}

And this is the output:

Creating window "First Window"
rendering
rendering
WindowEvent::CloseRequested
Event::LoopDestroyed.
-----------------
Creating window "Second Window"
rendering
rendering
Event::LoopDestroyed.
-----------------

The WindowEvent::CloseRequested is me closing the window, but the second window also closes without any reason.

According to @zu1k, this is also a problem on Windows, but there it can be fixed by adding the following code after the first run_return:

    event_loop.run_return(|_, _, control_flow| {
        control_flow.set_exit();
    });

Related issue: emilk/egui#1919


One very bad work-around is to calli run_return multiple times, like so:

        let mut quit = false;
        while !quit {
            event_loop.run_return(|event, _, control_flow| {
                // Only set `quit = true;` when we really want to close the window.
            });
        }

This still spams Event::LoopDestroyed over and over again, but the window stays up. However, it uses up ALL the CPU of one core, so this is NOT a viable solution.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DS - appkitAffects the AppKit/macOS backendH - help wantedSomeone please save us

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions