diff --git a/CHANGELOG.md b/CHANGELOG.md index e57ea66b..5140ea6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Unreleased +- On macOS, fix segmentation fault after dropping the main window. - On Android, `InputEvent::KeyEvent` is partially implemented providing the key scancode. - Added `is_maximized` method to `Window`. - On Windows, fix bug where clicking the decoration bar would make the cursor blink. diff --git a/src/platform_impl/macos/app_state.rs b/src/platform_impl/macos/app_state.rs index 29fafbe5..cf2f8280 100644 --- a/src/platform_impl/macos/app_state.rs +++ b/src/platform_impl/macos/app_state.rs @@ -341,9 +341,7 @@ impl AppState { unsafe { let app: id = NSApp(); let windows: id = msg_send![app, windows]; - let window: id = msg_send![windows, objectAtIndex:0]; let window_count: usize = msg_send![windows, count]; - assert_ne!(window, nil); let dialog_open = if window_count > 1 { let dialog: id = msg_send![windows, lastObject]; @@ -373,16 +371,19 @@ impl AppState { data2: 0 ]; // To stop event loop immediately, we need to post some event here. - let _: () = msg_send![window, postEvent: dummy_event atStart: YES]; + let _: () = msg_send![app, postEvent: dummy_event atStart: YES]; } pool.drain(); - let window_has_focus = msg_send![window, isKeyWindow]; - if !dialog_open && window_has_focus && dialog_is_closing { - HANDLER.dialog_is_closing.store(false, Ordering::SeqCst); - } - if dialog_open { - HANDLER.dialog_is_closing.store(true, Ordering::SeqCst); + if window_count > 0 { + let window: id = msg_send![windows, objectAtIndex:0]; + let window_has_focus = msg_send![window, isKeyWindow]; + if !dialog_open && window_has_focus && dialog_is_closing { + HANDLER.dialog_is_closing.store(false, Ordering::SeqCst); + } + if dialog_open { + HANDLER.dialog_is_closing.store(true, Ordering::SeqCst); + } } }; } diff --git a/src/platform_impl/macos/util/async.rs b/src/platform_impl/macos/util/async.rs index 96f8e5b0..7f8e7b87 100644 --- a/src/platform_impl/macos/util/async.rs +++ b/src/platform_impl/macos/util/async.rs @@ -207,7 +207,10 @@ pub unsafe fn set_title_async(ns_window: id, title: String) { // `close:` is thread-safe, but we want the event to be triggered from the main // thread. Though, it's a good idea to look into that more... -pub unsafe fn close_async(ns_window: id) { +// +// ArturKovacs: It's important that this operation keeps the underlying window alive +// through the `IdRef` because otherwise it would dereference free'd memory +pub unsafe fn close_async(ns_window: IdRef) { let ns_window = MainThreadSafe(ns_window); Queue::main().exec_async(move || { autoreleasepool(move || { diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index 94a2f541..82c1b6ae 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -1158,7 +1158,7 @@ impl Drop for UnownedWindow { trace!("Dropping `UnownedWindow` ({:?})", self as *mut _); // Close the window if it has not yet been closed. if *self.ns_window != nil { - unsafe { util::close_async(*self.ns_window) }; + unsafe { util::close_async(self.ns_window.clone()) }; } } }