mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-05-24 05:40:15 +00:00
macOS: add review windows when quitting
Inspired by Terminal.app
This commit is contained in:
@@ -404,20 +404,7 @@ class AppDelegate: NSObject,
|
||||
// If our app says we don't need to confirm, we can exit now.
|
||||
if !ghostty.needsConfirmQuit { return .terminateNow }
|
||||
|
||||
// We have some visible window. Show an app-wide modal to confirm quitting.
|
||||
let alert = NSAlert()
|
||||
alert.messageText = "Quit Ghostty?"
|
||||
alert.informativeText = "All terminal sessions will be terminated."
|
||||
alert.addButton(withTitle: "Close Ghostty")
|
||||
alert.addButton(withTitle: "Cancel")
|
||||
alert.alertStyle = .warning
|
||||
switch alert.runModal() {
|
||||
case .alertFirstButtonReturn:
|
||||
return .terminateNow
|
||||
|
||||
default:
|
||||
return .terminateCancel
|
||||
}
|
||||
return terminate()
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ notification: Notification) {
|
||||
@@ -1305,6 +1292,79 @@ extension AppDelegate: NSMenuItemValidation {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Termination Flow
|
||||
|
||||
extension AppDelegate {
|
||||
func terminate() -> NSApplication.TerminateReply {
|
||||
let controllersNeedConfirmation = NSApplication.shared.windows
|
||||
.compactMap { $0.windowController as? BaseTerminalController }
|
||||
.filter { !$0.windowCanBeClosedWithoutConfirmation() }
|
||||
|
||||
guard !controllersNeedConfirmation.isEmpty else {
|
||||
return .terminateNow
|
||||
}
|
||||
|
||||
if controllersNeedConfirmation.count == 1 {
|
||||
Task {
|
||||
let response = await controllersNeedConfirmation[0].confirmCloseAsync(
|
||||
messageText: "Quit Ghostty?",
|
||||
informativeText: "The terminal still has a running process. If you quit, the process will be killed.",
|
||||
confirmButtonTitle: "Terminate",
|
||||
)
|
||||
|
||||
if [.OK, .alertFirstButtonReturn].contains(response) {
|
||||
await NSApp.reply(toApplicationShouldTerminate: true)
|
||||
} else {
|
||||
await NSApp.reply(toApplicationShouldTerminate: false)
|
||||
}
|
||||
}
|
||||
|
||||
return .terminateLater
|
||||
} else {
|
||||
let alert = NSAlert()
|
||||
alert.messageText = "You have \(controllersNeedConfirmation.count) windows with running processes. Do you want to review these windows before quitting?"
|
||||
alert.informativeText = "If you don't review your windows, any running processes will be terminated"
|
||||
alert.addButton(withTitle: "Review Windows...")
|
||||
alert.addButton(withTitle: "Terminate Processes")
|
||||
alert.addButton(withTitle: "Cancel")
|
||||
alert.alertStyle = .warning
|
||||
|
||||
switch alert.runModal() {
|
||||
case .alertFirstButtonReturn:
|
||||
reviewWindows(controllersNeedConfirmation)
|
||||
return .terminateLater
|
||||
case .alertSecondButtonReturn:
|
||||
return .terminateNow
|
||||
default:
|
||||
return .terminateCancel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func reviewWindows(_ controllers: [BaseTerminalController]) {
|
||||
Task {
|
||||
for controller in controllers {
|
||||
let response = await controller.confirmCloseAsync(
|
||||
messageText: "Quit Ghostty?",
|
||||
informativeText: "The terminal still has a running process. If you quit, the process will be killed.",
|
||||
confirmButtonTitle: "Terminate",
|
||||
)
|
||||
|
||||
if [.OK, .alertFirstButtonReturn].contains(response) {
|
||||
// Close this window and until next review is cancelled
|
||||
await controller.window?.close()
|
||||
continue
|
||||
} else {
|
||||
await NSApp.reply(toApplicationShouldTerminate: false)
|
||||
// Cancel the review
|
||||
return
|
||||
}
|
||||
}
|
||||
await NSApp.reply(toApplicationShouldTerminate: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the state of the quick terminal controller.
|
||||
private enum QuickTerminalState {
|
||||
/// Controller has not been initialized and has no pending restoration state.
|
||||
|
||||
Reference in New Issue
Block a user