Skip to content

Commit 8db4a9c

Browse files
authored
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).
1 parent a4ab7dc commit 8db4a9c

File tree

3 files changed

+21
-2
lines changed

3 files changed

+21
-2
lines changed

src/changelog/unreleased.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,4 @@ changelog entry.
241241
- On Windows, fixed ~500 ms pause when clicking the title bar during continuous redraw.
242242
- On macos, `WindowExtMacOS::set_simple_fullscreen` now honors `WindowExtMacOS::set_borderless_game`
243243
- On X11 and Wayland, fixed pump_events with `Some(Duration::Zero)` blocking with `Wait` polling mode
244+
- On macOS, fixed `run_app_on_demand` returning without closing open windows.

src/platform_impl/apple/appkit/app_state.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use objc2_foundation::NSNotification;
1111

1212
use super::super::event_handler::EventHandler;
1313
use super::super::event_loop_proxy::EventLoopProxy;
14-
use super::event_loop::{stop_app_immediately, ActiveEventLoop, PanicInfo};
14+
use super::event_loop::{notify_windows_of_exit, stop_app_immediately, ActiveEventLoop, PanicInfo};
1515
use super::menu;
1616
use super::observer::{EventLoopWaker, RunLoop};
1717
use crate::application::ApplicationHandler;
@@ -156,7 +156,8 @@ impl AppState {
156156

157157
pub fn will_terminate(self: &Rc<Self>, _notification: &NSNotification) {
158158
trace_scope!("NSApplicationWillTerminateNotification");
159-
// TODO: Notify every window that it will be destroyed, like done in iOS?
159+
let app = NSApplication::sharedApplication(self.mtm);
160+
notify_windows_of_exit(&app);
160161
self.event_handler.terminate();
161162
self.internal_exit();
162163
}
@@ -365,6 +366,7 @@ impl AppState {
365366
if self.exiting() {
366367
let app = NSApplication::sharedApplication(self.mtm);
367368
stop_app_immediately(&app);
369+
notify_windows_of_exit(&app);
368370
}
369371

370372
if self.stop_before_wait.get() {

src/platform_impl/apple/appkit/event_loop.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,22 @@ pub(super) fn stop_app_immediately(app: &NSApplication) {
407407
});
408408
}
409409

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

0 commit comments

Comments
 (0)