fix(quit): enforce Warn Before Quit when Cmd+Q arrives via app switcher (#2186)
applicationShouldTerminate was returning .terminateNow unconditionally, bypassing QuitWarningSettings. Now it shows the same confirmation alert used by handleQuitShortcutWarning, with an isQuitWarningConfirmed flag to prevent a double dialog when the Cmd+Q shortcut path already confirmed. Fixes #2139 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
46589f531c
commit
6a41c9f42f
1 changed files with 46 additions and 1 deletions
|
|
@ -2212,6 +2212,9 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent
|
|||
private var lastTypingActivityAt: TimeInterval = 0
|
||||
private var didHandleExplicitOpenIntentAtStartup = false
|
||||
private var isTerminatingApp = false
|
||||
// Set to true when the user has already confirmed quit via the warning dialog,
|
||||
// so applicationShouldTerminate does not show a second alert.
|
||||
private var isQuitWarningConfirmed = false
|
||||
private var didInstallLifecycleSnapshotObservers = false
|
||||
private var didDisableSuddenTermination = false
|
||||
private var commandPaletteVisibilityByWindowId: [UUID: Bool] = [:]
|
||||
|
|
@ -2701,7 +2704,46 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent
|
|||
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
|
||||
isTerminatingApp = true
|
||||
_ = saveSessionSnapshot(includeScrollback: true, removeWhenEmpty: false)
|
||||
return .terminateNow
|
||||
|
||||
// If the user already confirmed via the Cmd+Q shortcut warning dialog
|
||||
// (handleQuitShortcutWarning), skip the check to avoid a second alert.
|
||||
if isQuitWarningConfirmed {
|
||||
return .terminateNow
|
||||
}
|
||||
|
||||
// Respect the "Warn Before Quit" setting even when Cmd+Q arrives via
|
||||
// the Cmd+Tab app switcher, bypassing handleCustomShortcut.
|
||||
guard QuitWarningSettings.isEnabled() else {
|
||||
return .terminateNow
|
||||
}
|
||||
|
||||
// Show the same confirmation dialog used by the Cmd+Q shortcut path,
|
||||
// then reply asynchronously so we can return .terminateLater now.
|
||||
DispatchQueue.main.async {
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .warning
|
||||
alert.messageText = String(localized: "dialog.quitCmux.title", defaultValue: "Quit cmux?")
|
||||
alert.informativeText = String(localized: "dialog.quitCmux.message", defaultValue: "This will close all windows and workspaces.")
|
||||
alert.addButton(withTitle: String(localized: "dialog.quitCmux.quit", defaultValue: "Quit"))
|
||||
alert.addButton(withTitle: String(localized: "common.cancel", defaultValue: "Cancel"))
|
||||
alert.showsSuppressionButton = true
|
||||
alert.suppressionButton?.title = String(localized: "dialog.dontWarnCmdQ", defaultValue: "Don't warn again for Cmd+Q")
|
||||
|
||||
let response = alert.runModal()
|
||||
if alert.suppressionButton?.state == .on {
|
||||
QuitWarningSettings.setEnabled(false)
|
||||
}
|
||||
|
||||
let shouldQuit = response == .alertFirstButtonReturn
|
||||
if shouldQuit {
|
||||
self.isQuitWarningConfirmed = true
|
||||
} else {
|
||||
// Reset so that the next quit attempt can show the dialog again.
|
||||
self.isTerminatingApp = false
|
||||
}
|
||||
NSApp.reply(toApplicationShouldTerminate: shouldQuit)
|
||||
}
|
||||
return .terminateLater
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ notification: Notification) {
|
||||
|
|
@ -8983,6 +9025,9 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent
|
|||
}
|
||||
|
||||
if response == .alertFirstButtonReturn {
|
||||
// Mark as confirmed so applicationShouldTerminate does not show a
|
||||
// second alert when NSApp.terminate re-enters the delegate callback.
|
||||
isQuitWarningConfirmed = true
|
||||
NSApp.terminate(nil)
|
||||
}
|
||||
return true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue