macOS: attach close confirmation alert to the first window that actually needs it
parent
fbabafe8e3
commit
f94cb01ec8
|
|
@ -287,6 +287,7 @@ class BaseTerminalController: NSWindowController,
|
||||||
func confirmClose(
|
func confirmClose(
|
||||||
messageText: String,
|
messageText: String,
|
||||||
informativeText: String,
|
informativeText: String,
|
||||||
|
attachedWindow: NSWindow? = nil,
|
||||||
completion: @escaping () -> Void
|
completion: @escaping () -> Void
|
||||||
) {
|
) {
|
||||||
// If we already have an alert, we need to wait for that one.
|
// If we already have an alert, we need to wait for that one.
|
||||||
|
|
@ -294,7 +295,7 @@ class BaseTerminalController: NSWindowController,
|
||||||
|
|
||||||
// If there is no window to attach the modal then we assume success
|
// If there is no window to attach the modal then we assume success
|
||||||
// since we'll never be able to show the modal.
|
// since we'll never be able to show the modal.
|
||||||
guard let window else {
|
guard let window = attachedWindow ?? self.window else {
|
||||||
completion()
|
completion()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -817,32 +817,37 @@ 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 {
|
var confirmWindow: NSWindow?
|
||||||
$0.surfaceTree.contains { $0.needsConfirmQuit }
|
var needsConfirm = false
|
||||||
|
for controller in all {
|
||||||
|
if let surfaceToConfirm = controller.surfaceTree.first(where: { $0.needsConfirmQuit }) {
|
||||||
|
needsConfirm = true
|
||||||
|
confirmWindow = surfaceToConfirm.window
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!needsConfirm) {
|
guard needsConfirm 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
|
guard let confirmWindow else {
|
||||||
|
if (alert.runModal() == .alertFirstButtonReturn) {
|
||||||
|
// This is important so that we avoid losing focus when Stage
|
||||||
|
// Manager is used (#8336)
|
||||||
|
alert.window.orderOut(nil)
|
||||||
|
closeAllWindowsImmediately()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
|
@ -1163,12 +1168,18 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr
|
||||||
// reason we check ourselves.
|
// reason we check ourselves.
|
||||||
let windows: [NSWindow] = window.tabGroup?.windows ?? [window]
|
let windows: [NSWindow] = window.tabGroup?.windows ?? [window]
|
||||||
|
|
||||||
|
var confirmWindow: NSWindow?
|
||||||
|
var needsConfirm = false
|
||||||
// Check if any windows require close confirmation.
|
// Check if any windows require close confirmation.
|
||||||
let needsConfirm = windows.contains { tabWindow in
|
for tabWindow in windows {
|
||||||
guard let controller = tabWindow.windowController as? TerminalController else {
|
guard let controller = tabWindow.windowController as? TerminalController else {
|
||||||
return false
|
continue
|
||||||
|
}
|
||||||
|
if let surfaceToConfirm = controller.surfaceTree.first(where: { $0.needsConfirmQuit }) {
|
||||||
|
needsConfirm = true
|
||||||
|
confirmWindow = surfaceToConfirm.window
|
||||||
|
break
|
||||||
}
|
}
|
||||||
return controller.surfaceTree.contains(where: { $0.needsConfirmQuit })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If none need confirmation then we can just close all the windows.
|
// If none need confirmation then we can just close all the windows.
|
||||||
|
|
@ -1179,7 +1190,8 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr
|
||||||
|
|
||||||
confirmClose(
|
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.",
|
||||||
|
attachedWindow: confirmWindow,
|
||||||
) {
|
) {
|
||||||
self.closeWindowImmediately()
|
self.closeWindowImmediately()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue