macOS: attach close confirmation alert to the first window that actually needs it (#9509)

Currently, close confirmation is always attached to the first tab in the
window group.

**This pr will attach the alert to the window that actually needs that
confirmation, so upon close, the window with the running process will be
focused.**


https://github.com/user-attachments/assets/8fddd4ce-a3f9-4e18-a645-80c85b5ba995
pull/9515/head
Mitchell Hashimoto 2025-11-07 14:26:00 -08:00 committed by GitHub
commit 0d26bace25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 17 additions and 29 deletions

View File

@ -817,32 +817,25 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr
/// Close all windows, asking for confirmation if necessary. /// Close all windows, asking for confirmation if necessary.
static func closeAllWindows() { static func closeAllWindows() {
let needsConfirm: Bool = all.contains { // The window we use for confirmations. Try to find the first window that
$0.surfaceTree.contains { $0.needsConfirmQuit } // needs quit confirmation. This lets us attach the confirmation to something
} // that is running.
guard let confirmWindow = all
if (!needsConfirm) { .first(where: { $0.surfaceTree.contains(where: { $0.needsConfirmQuit }) })?
.surfaceTree.first(where: { $0.needsConfirmQuit })?
.window
else {
closeAllWindowsImmediately() closeAllWindowsImmediately()
return return
} }
// If we don't have a main window, we just close all windows because
// we have no window to show the modal on top of. I'm sure there's a way
// to do an app-level alert but I don't know how and this case should never
// really happen.
guard let alertWindow = preferredParent?.window else {
closeAllWindowsImmediately()
return
}
// If we need confirmation by any, show one confirmation for all windows
let alert = NSAlert() let alert = NSAlert()
alert.messageText = "Close All Windows?" alert.messageText = "Close All Windows?"
alert.informativeText = "All terminal sessions will be terminated." alert.informativeText = "All terminal sessions will be terminated."
alert.addButton(withTitle: "Close All Windows") alert.addButton(withTitle: "Close All Windows")
alert.addButton(withTitle: "Cancel") alert.addButton(withTitle: "Cancel")
alert.alertStyle = .warning alert.alertStyle = .warning
alert.beginSheetModal(for: alertWindow, completionHandler: { response in alert.beginSheetModal(for: confirmWindow, completionHandler: { response in
if (response == .alertFirstButtonReturn) { if (response == .alertFirstButtonReturn) {
// This is important so that we avoid losing focus when Stage // This is important so that we avoid losing focus when Stage
// Manager is used (#8336) // Manager is used (#8336)
@ -1162,24 +1155,19 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr
// if we're closing the window. If we don't have a tabgroup for any // if we're closing the window. If we don't have a tabgroup for any
// reason we check ourselves. // reason we check ourselves.
let windows: [NSWindow] = window.tabGroup?.windows ?? [window] let windows: [NSWindow] = window.tabGroup?.windows ?? [window]
guard let confirmController = windows
// Check if any windows require close confirmation. .compactMap({ $0.windowController as? TerminalController })
let needsConfirm = windows.contains { tabWindow in .first(where: { $0.surfaceTree.contains(where: { $0.needsConfirmQuit }) })
guard let controller = tabWindow.windowController as? TerminalController else { else {
return false
}
return controller.surfaceTree.contains(where: { $0.needsConfirmQuit })
}
// If none need confirmation then we can just close all the windows.
if !needsConfirm {
closeWindowImmediately() closeWindowImmediately()
return return
} }
confirmClose( // We call confirmClose on the proper controller so the alert is
// attached to the window that needs confirmation.
confirmController.confirmClose(
messageText: "Close Window?", messageText: "Close Window?",
informativeText: "All terminal sessions in this window will be terminated." informativeText: "All terminal sessions in this window will be terminated.",
) { ) {
self.closeWindowImmediately() self.closeWindowImmediately()
} }