macos: unify confirm close in our terminal controllers
parent
d1dce1e372
commit
b84b715ddb
|
|
@ -194,6 +194,40 @@ class BaseTerminalController: NSWindowController,
|
|||
savedFrame = .init(window: window.frame, screen: screen.visibleFrame)
|
||||
}
|
||||
|
||||
func confirmClose(
|
||||
messageText: String,
|
||||
informativeText: String,
|
||||
completion: @escaping () -> Void
|
||||
) {
|
||||
// If we already have an alert, we need to wait for that one.
|
||||
guard alert == nil else { return }
|
||||
|
||||
// If there is no window to attach the modal then we assume success
|
||||
// since we'll never be able to show the modal.
|
||||
guard let window else {
|
||||
completion()
|
||||
return
|
||||
}
|
||||
|
||||
// If we need confirmation by any, show one confirmation for all windows
|
||||
// in the tab group.
|
||||
let alert = NSAlert()
|
||||
alert.messageText = messageText
|
||||
alert.informativeText = informativeText
|
||||
alert.addButton(withTitle: "Close")
|
||||
alert.addButton(withTitle: "Cancel")
|
||||
alert.alertStyle = .warning
|
||||
alert.beginSheetModal(for: window) { response in
|
||||
self.alert = nil
|
||||
if response == .alertFirstButtonReturn {
|
||||
completion()
|
||||
}
|
||||
}
|
||||
|
||||
// Store our alert so we only ever show one.
|
||||
self.alert = alert
|
||||
}
|
||||
|
||||
// MARK: Notifications
|
||||
|
||||
@objc private func didChangeScreenParametersNotification(_ notification: Notification) {
|
||||
|
|
@ -287,37 +321,19 @@ class BaseTerminalController: NSWindowController,
|
|||
return
|
||||
}
|
||||
|
||||
// If we don't have a window to attach our modal to, we also exit immediately.
|
||||
// This should NOT happen.
|
||||
guard let window = target.window else {
|
||||
surfaceTree2 = surfaceTree2.remove(node)
|
||||
return
|
||||
}
|
||||
|
||||
// Confirm close. We use an NSAlert instead of a SwiftUI confirmationDialog
|
||||
// due to SwiftUI bugs (see Ghostty #560). To repeat from #560, the bug is that
|
||||
// confirmationDialog allows the user to Cmd-W close the alert, but when doing
|
||||
// so SwiftUI does not update any of the bindings to note that window is no longer
|
||||
// being shown, and provides no callback to detect this.
|
||||
let alert = NSAlert()
|
||||
alert.messageText = "Close Terminal?"
|
||||
alert.informativeText = "The terminal still has a running process. If you close the " +
|
||||
"terminal the process will be killed."
|
||||
alert.addButton(withTitle: "Close the Terminal")
|
||||
alert.addButton(withTitle: "Cancel")
|
||||
alert.alertStyle = .warning
|
||||
alert.beginSheetModal(for: window, completionHandler: { [weak self] response in
|
||||
switch (response) {
|
||||
case .alertFirstButtonReturn:
|
||||
alert.window.orderOut(nil)
|
||||
if let self {
|
||||
self.surfaceTree2 = self.surfaceTree2.remove(node)
|
||||
}
|
||||
|
||||
default:
|
||||
break
|
||||
confirmClose(
|
||||
messageText: "Close Terminal?",
|
||||
informativeText: "The terminal still has a running process. If you close the terminal the process will be killed."
|
||||
) { [weak self] in
|
||||
if let self {
|
||||
self.surfaceTree2 = self.surfaceTree2.remove(node)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func ghosttyDidNewSplit(_ notification: Notification) {
|
||||
|
|
@ -624,26 +640,12 @@ class BaseTerminalController: NSWindowController,
|
|||
if (!node.needsConfirmQuit()) { return true }
|
||||
|
||||
// We require confirmation, so show an alert as long as we aren't already.
|
||||
let alert = NSAlert()
|
||||
alert.messageText = "Close Terminal?"
|
||||
alert.informativeText = "The terminal still has a running process. If you close the " +
|
||||
"terminal the process will be killed."
|
||||
alert.addButton(withTitle: "Close the Terminal")
|
||||
alert.addButton(withTitle: "Cancel")
|
||||
alert.alertStyle = .warning
|
||||
alert.beginSheetModal(for: window, completionHandler: { response in
|
||||
self.alert = nil
|
||||
switch (response) {
|
||||
case .alertFirstButtonReturn:
|
||||
alert.window.orderOut(nil)
|
||||
window.close()
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
self.alert = alert
|
||||
confirmClose(
|
||||
messageText: "Close Terminal?",
|
||||
informativeText: "The terminal still has a running process. If you close the terminal the process will be killed."
|
||||
) {
|
||||
window.close()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -587,27 +587,6 @@ class TerminalController: BaseTerminalController {
|
|||
ghostty.newTab(surface: surface)
|
||||
}
|
||||
|
||||
private func confirmClose(
|
||||
window: NSWindow,
|
||||
messageText: String,
|
||||
informativeText: String,
|
||||
completion: @escaping () -> Void
|
||||
) {
|
||||
// If we need confirmation by any, show one confirmation for all windows
|
||||
// in the tab group.
|
||||
let alert = NSAlert()
|
||||
alert.messageText = messageText
|
||||
alert.informativeText = informativeText
|
||||
alert.addButton(withTitle: "Close")
|
||||
alert.addButton(withTitle: "Cancel")
|
||||
alert.alertStyle = .warning
|
||||
alert.beginSheetModal(for: window) { response in
|
||||
if response == .alertFirstButtonReturn {
|
||||
completion()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func closeTab(_ sender: Any?) {
|
||||
guard let window = window else { return }
|
||||
guard window.tabGroup != nil else {
|
||||
|
|
@ -618,7 +597,6 @@ class TerminalController: BaseTerminalController {
|
|||
|
||||
if surfaceTree?.needsConfirmQuit() ?? false {
|
||||
confirmClose(
|
||||
window: window,
|
||||
messageText: "Close Tab?",
|
||||
informativeText: "The terminal still has a running process. If you close the tab the process will be killed."
|
||||
) {
|
||||
|
|
@ -664,7 +642,6 @@ class TerminalController: BaseTerminalController {
|
|||
}
|
||||
|
||||
confirmClose(
|
||||
window: window,
|
||||
messageText: "Close Window?",
|
||||
informativeText: "All terminal sessions in this window will be terminated."
|
||||
) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue