From 054b91f641ab5e16016e467176ad5b8b1e2d3239 Mon Sep 17 00:00:00 2001 From: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com> Date: Thu, 12 Mar 2026 05:25:14 -0700 Subject: [PATCH] Fix Return on Cmd+Ctrl+W close confirmation (#1279) * Add close-window return-key regression test * Focus close-window confirmation button * Keep Return on close-window alert * Address review feedback --- Sources/AppDelegate.swift | 9 ++-- .../CloseWindowConfirmDialogUITests.swift | 50 +++++++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/Sources/AppDelegate.swift b/Sources/AppDelegate.swift index 4da5cd1d..e441d37c 100644 --- a/Sources/AppDelegate.swift +++ b/Sources/AppDelegate.swift @@ -4446,10 +4446,13 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent alert.addButton(withTitle: String(localized: "common.close", defaultValue: "Close")) alert.addButton(withTitle: String(localized: "common.cancel", defaultValue: "Cancel")) + let alertWindow = alert.window if let closeButton = alert.buttons.first { - closeButton.keyEquivalent = "d" - closeButton.keyEquivalentModifierMask = [.command] - alert.window.defaultButtonCell = closeButton.cell as? NSButtonCell + alertWindow.defaultButtonCell = closeButton.cell as? NSButtonCell + alertWindow.initialFirstResponder = closeButton + DispatchQueue.main.async { + _ = alertWindow.makeFirstResponder(closeButton) + } } return alert.runModal() == .alertFirstButtonReturn diff --git a/cmuxUITests/CloseWindowConfirmDialogUITests.swift b/cmuxUITests/CloseWindowConfirmDialogUITests.swift index 275b33b2..f64078d4 100644 --- a/cmuxUITests/CloseWindowConfirmDialogUITests.swift +++ b/cmuxUITests/CloseWindowConfirmDialogUITests.swift @@ -33,6 +33,34 @@ final class CloseWindowConfirmDialogUITests: XCTestCase { XCTAssertTrue(app.windows.firstMatch.exists, "Expected the window to remain open after cancelling close") } + func testReturnConfirmsCloseWindowDialog() { + let app = XCUIApplication() + app.launchEnvironment["CMUX_TAG"] = launchTag + app.launch() + XCTAssertTrue( + ensureForegroundAfterLaunch(app, timeout: 12.0), + "Expected app to launch for close-window confirmation test. state=\(app.state.rawValue)" + ) + + app.typeKey("w", modifierFlags: [.command, .control]) + + XCTAssertTrue( + waitForCloseWindowAlert(app: app, timeout: 5.0), + "Expected Cmd+Ctrl+W to show the close window confirmation alert" + ) + + app.typeKey(.return, modifierFlags: []) + + XCTAssertTrue( + waitForCloseWindowAlertToDismiss(app: app, timeout: 5.0), + "Expected Return to dismiss the close window confirmation alert" + ) + XCTAssertTrue( + waitForMainWindowToClose(app: app, timeout: 5.0), + "Expected Return to confirm window close" + ) + } + private func isCloseWindowAlertPresent(app: XCUIApplication) -> Bool { if closeWindowDialog(app: app).exists { return true } if closeWindowAlert(app: app).exists { return true } @@ -50,6 +78,28 @@ final class CloseWindowConfirmDialogUITests: XCTestCase { return isCloseWindowAlertPresent(app: app) } + private func waitForCloseWindowAlertToDismiss(app: XCUIApplication, timeout: TimeInterval) -> Bool { + let deadline = Date().addingTimeInterval(timeout) + while Date() < deadline { + if !isCloseWindowAlertPresent(app: app) { + return true + } + RunLoop.current.run(until: Date().addingTimeInterval(0.05)) + } + return !isCloseWindowAlertPresent(app: app) + } + + private func waitForMainWindowToClose(app: XCUIApplication, timeout: TimeInterval) -> Bool { + let deadline = Date().addingTimeInterval(timeout) + while Date() < deadline { + if !app.windows.firstMatch.exists { + return true + } + RunLoop.current.run(until: Date().addingTimeInterval(0.05)) + } + return !app.windows.firstMatch.exists + } + private func clickCancelOnCloseWindowAlert(app: XCUIApplication) { let dialog = closeWindowDialog(app: app) if dialog.exists {