From 387567a917e1944a3848ee7d21c14013a1a4f55d Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 4 Nov 2021 19:37:02 +0100 Subject: [PATCH] macOS: Fix native file dialogs freezing the event loop (#2027) * macOS: Ignore all events while in the callback Previously all native dialogs, such as [rfd](https://github.com/PolyMeilex/rfd), would cause the event loop (event_loop.run) to freeze. * Update changelog * spelling * Fix merge mistake * Add link to issue in the code Co-authored-by: Poly --- CHANGELOG.md | 1 + src/platform_impl/macos/app_state.rs | 35 +++++++++++++++------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59920a2bb8..e6d5f776de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - On Wayland, add an enabled-by-default feature called `wayland-dlopen` so users can opt out of using `dlopen` to load system libraries. - **Breaking:** On Android, bump `ndk` and `ndk-glue` to 0.4. - On Windows, increase wait timer resolution for more accurate timing when using `WaitUntil`. +- On macOS, fix native file dialogs hanging the event loop. # 0.25.0 (2021-05-15) diff --git a/src/platform_impl/macos/app_state.rs b/src/platform_impl/macos/app_state.rs index 5f1483339f..0824354b51 100644 --- a/src/platform_impl/macos/app_state.rs +++ b/src/platform_impl/macos/app_state.rs @@ -307,7 +307,9 @@ impl AppState { let panic_info = panic_info .upgrade() .expect("The panic info must exist here. This failure indicates a developer error."); - if panic_info.is_panicking() || !HANDLER.is_ready() { + + // Return when in callback due to https://github.com/rust-windowing/winit/issues/1779 + if panic_info.is_panicking() || !HANDLER.is_ready() || HANDLER.get_in_callback() { return; } let start = HANDLER.get_start_time().unwrap(); @@ -371,24 +373,25 @@ impl AppState { let panic_info = panic_info .upgrade() .expect("The panic info must exist here. This failure indicates a developer error."); - if panic_info.is_panicking() || !HANDLER.is_ready() { + + // Return when in callback due to https://github.com/rust-windowing/winit/issues/1779 + if panic_info.is_panicking() || !HANDLER.is_ready() || HANDLER.get_in_callback() { return; } - if !HANDLER.get_in_callback() { - HANDLER.set_in_callback(true); - HANDLER.handle_user_events(); - for event in HANDLER.take_events() { - HANDLER.handle_nonuser_event(event); - } - HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::MainEventsCleared)); - for window_id in HANDLER.should_redraw() { - HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::RedrawRequested( - window_id, - ))); - } - HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::RedrawEventsCleared)); - HANDLER.set_in_callback(false); + + HANDLER.set_in_callback(true); + HANDLER.handle_user_events(); + for event in HANDLER.take_events() { + HANDLER.handle_nonuser_event(event); + } + HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::MainEventsCleared)); + for window_id in HANDLER.should_redraw() { + HANDLER + .handle_nonuser_event(EventWrapper::StaticEvent(Event::RedrawRequested(window_id))); } + HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::RedrawEventsCleared)); + HANDLER.set_in_callback(false); + if HANDLER.should_exit() { unsafe { let app: id = NSApp();