winit: [MacOS] Dialogues freeze when used in winit event loop

OS: OSX 10.15.6

Hi I’m working on RustyFileDialog crate, and in the process I found out weird issue related to winit event loop.

(To make it easier to reproduce I’ll use nfd2 as an example instead of my impl.) File dialogs, for example from nfd2 freeze when opened from winit event loop. Example:

fn main() {
    let el = EventLoop::new();
    let win = WindowBuilder::new().build(&el).unwrap();

    // This dialog works as expected
    nfd2::open_file_dialog(None,None).unwrap();

    el.run(move |event, _, control_flow| {
        match event {
            event::Event::WindowEvent {
                event: event::WindowEvent::MouseInput { .. },
                ..
            } => {
                // This dialog freezes
                nfd2::open_file_dialog(None,None).unwrap();
            }
            _ => {}
        }
    })
}

More info

  • For this test NSOpenPanel is used, and it is opened with runModal (blocking)
  • If I use beginWithCompletionHandler (non-blocking) dialog works as expected
  • SDL2-rs does not have this issue
  • winit window stays responsive, only NSOpenPanel is frozen

GIF

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 17 (14 by maintainers)

Commits related to this issue

Most upvoted comments

I managed to fix this by switching from event_loop.run(|…| { … file_dialog(); }) to loop { event_loop.run_return(…); … file_dialog(); }:

https://github.com/emilk/egui/pull/631

I’m using my fork in my neothesia project, and I haven’t heard any complaints yet. But as I said: I don't know the full impact of this change, so I would like to hear the opinion of someone with more knowledge about macOS backend. I’m essentially ignoring all incoming events in some cases, so I don’t like this solution at all, and I have 0 knowledge about macOS windowing.

I’ve implemented async/await syntax in rfd as a workaround to the problem, so if anyone is interested feel free to give it a try. It can be used with the crates.io version of winit (example).

Issue stays open, as the problem still exists inside winit and should be fixed nonetheless.