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 <marynczak.bartlomiej@gmail.com>
This commit is contained in:
Emil Ernerfeldt 2021-11-04 19:37:02 +01:00 committed by GitHub
parent cfbe8462cc
commit 387567a917
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 16 deletions

View file

@ -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. - 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. - **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 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) # 0.25.0 (2021-05-15)

View file

@ -307,7 +307,9 @@ impl AppState {
let panic_info = panic_info let panic_info = panic_info
.upgrade() .upgrade()
.expect("The panic info must exist here. This failure indicates a developer error."); .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; return;
} }
let start = HANDLER.get_start_time().unwrap(); let start = HANDLER.get_start_time().unwrap();
@ -371,24 +373,25 @@ impl AppState {
let panic_info = panic_info let panic_info = panic_info
.upgrade() .upgrade()
.expect("The panic info must exist here. This failure indicates a developer error."); .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; return;
} }
if !HANDLER.get_in_callback() {
HANDLER.set_in_callback(true); HANDLER.set_in_callback(true);
HANDLER.handle_user_events(); HANDLER.handle_user_events();
for event in HANDLER.take_events() { for event in HANDLER.take_events() {
HANDLER.handle_nonuser_event(event); 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.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() { if HANDLER.should_exit() {
unsafe { unsafe {
let app: id = NSApp(); let app: id = NSApp();