From 29c0f525db372c31e2a94d5440c080214485185e Mon Sep 17 00:00:00 2001 From: Austin Wang Date: Mon, 30 Mar 2026 02:19:17 -0700 Subject: [PATCH] Add New Window to Dock menu (#2340) * Add Dock menu new-window regression test * Add New Window to Dock menu --- Sources/AppDelegate.swift | 12 ++++++ .../AppDelegateShortcutRoutingTests.swift | 38 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/Sources/AppDelegate.swift b/Sources/AppDelegate.swift index fe445861..cbf34779 100644 --- a/Sources/AppDelegate.swift +++ b/Sources/AppDelegate.swift @@ -5511,6 +5511,18 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent mainWindowContexts.values.first(where: { $0.windowId == windowId })?.sidebarState.isVisible } + func applicationDockMenu(_ sender: NSApplication) -> NSMenu? { + let menu = NSMenu(title: "") + let newWindowItem = NSMenuItem( + title: String(localized: "menu.file.newWindow", defaultValue: "New Window"), + action: #selector(openNewMainWindow(_:)), + keyEquivalent: "" + ) + newWindowItem.target = self + menu.addItem(newWindowItem) + return menu + } + @objc func openNewMainWindow(_ sender: Any?) { _ = createMainWindow() } diff --git a/cmuxTests/AppDelegateShortcutRoutingTests.swift b/cmuxTests/AppDelegateShortcutRoutingTests.swift index b3245cf7..7c1a6315 100644 --- a/cmuxTests/AppDelegateShortcutRoutingTests.swift +++ b/cmuxTests/AppDelegateShortcutRoutingTests.swift @@ -252,6 +252,44 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { XCTAssertEqual(secondManager.tabs.count, secondCount + 1, "Cmd+N should still route by event window metadata when object-key lookup misses") } + func testDockMenuNewWindowItemCreatesMainWindow() { + guard let appDelegate = AppDelegate.shared else { + XCTFail("Expected AppDelegate.shared") + return + } + + let existingWindowId = appDelegate.createMainWindow() + var createdWindowId: UUID? + defer { + if let createdWindowId { + closeWindow(withId: createdWindowId) + } + closeWindow(withId: existingWindowId) + } + + let existingWindowIds = mainWindowIds() + + let delegate: NSApplicationDelegate = appDelegate + guard let dockMenu = delegate.applicationDockMenu?(NSApp) else { + XCTFail("Expected Dock menu") + return + } + + let expectedTitle = String(localized: "menu.file.newWindow", defaultValue: "New Window") + guard let item = dockMenu.items.first(where: { $0.action == #selector(AppDelegate.openNewMainWindow(_:)) }) else { + XCTFail("Expected New Window item in Dock menu") + return + } + + XCTAssertEqual(item.title, expectedTitle) + XCTAssertTrue(NSApp.sendAction(#selector(AppDelegate.openNewMainWindow(_:)), to: item.target, from: item)) + RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) + + let newWindowIds = mainWindowIds().subtracting(existingWindowIds) + XCTAssertEqual(newWindowIds.count, 1, "Dock menu New Window should create one main window") + createdWindowId = newWindowIds.first + } + func testAddWorkspaceInPreferredMainWindowUsesKeyWindowWhenObjectKeyLookupIsMismatched() { guard let appDelegate = AppDelegate.shared else { XCTFail("Expected AppDelegate.shared")