macOS: Close windows automatically when exiting (#4154)

This disallows carrying over open windows between calls of `run_app_on_demand`
(which wasn't intended to be supported anyhow).
This commit is contained in:
Mads Marquart 2025-03-17 11:29:53 +01:00 committed by GitHub
parent a4ab7dc64c
commit 8db4a9cc61
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 21 additions and 2 deletions

View file

@ -241,3 +241,4 @@ changelog entry.
- On Windows, fixed ~500 ms pause when clicking the title bar during continuous redraw.
- On macos, `WindowExtMacOS::set_simple_fullscreen` now honors `WindowExtMacOS::set_borderless_game`
- On X11 and Wayland, fixed pump_events with `Some(Duration::Zero)` blocking with `Wait` polling mode
- On macOS, fixed `run_app_on_demand` returning without closing open windows.

View file

@ -11,7 +11,7 @@ use objc2_foundation::NSNotification;
use super::super::event_handler::EventHandler;
use super::super::event_loop_proxy::EventLoopProxy;
use super::event_loop::{stop_app_immediately, ActiveEventLoop, PanicInfo};
use super::event_loop::{notify_windows_of_exit, stop_app_immediately, ActiveEventLoop, PanicInfo};
use super::menu;
use super::observer::{EventLoopWaker, RunLoop};
use crate::application::ApplicationHandler;
@ -156,7 +156,8 @@ impl AppState {
pub fn will_terminate(self: &Rc<Self>, _notification: &NSNotification) {
trace_scope!("NSApplicationWillTerminateNotification");
// TODO: Notify every window that it will be destroyed, like done in iOS?
let app = NSApplication::sharedApplication(self.mtm);
notify_windows_of_exit(&app);
self.event_handler.terminate();
self.internal_exit();
}
@ -365,6 +366,7 @@ impl AppState {
if self.exiting() {
let app = NSApplication::sharedApplication(self.mtm);
stop_app_immediately(&app);
notify_windows_of_exit(&app);
}
if self.stop_before_wait.get() {

View file

@ -407,6 +407,22 @@ pub(super) fn stop_app_immediately(app: &NSApplication) {
});
}
/// Tell all windows to close.
///
/// This will synchronously trigger `WindowEvent::Destroyed` within
/// `windowWillClose:`, giving the application one last chance to handle
/// those events. It doesn't matter if the user also ends up closing the
/// windows in `Window`'s `Drop` impl, once a window has been closed once, it
/// stays closed.
///
/// This ensures that no windows linger on after the event loop has exited,
/// see <https://github.com/rust-windowing/winit/issues/4135>.
pub(super) fn notify_windows_of_exit(app: &NSApplication) {
for window in app.windows() {
window.close();
}
}
/// Catches panics that happen inside `f` and when a panic
/// happens, stops the `sharedApplication`
#[inline]