Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
13dcefd
test: keep minimized windows hidden on background hotkey
austinywang Aug 25, 2026
792917a
fix: preserve minimized windows on background hotkey
austinywang Aug 25, 2026
0403bd6
Merge branch 'main' into issue-9991-hotkey-minimized
austinywang Sep 1, 2026
6768e55
Merge branch 'main' into issue-9991-hotkey-minimized
austinywang Sep 1, 2026
c070562
Merge branch 'main' into issue-9991-hotkey-minimized
austinywang Sep 1, 2026
397c643
Merge remote-tracking branch 'origin/main' into issue-9991-hotkey-min…
austinywang Sep 1, 2026
9565552
test: restore all-minimized windows on background hotkey
austinywang Sep 1, 2026
14259d1
fix: restore minimized windows when no visible targets
austinywang Sep 1, 2026
8ab0db5
Merge remote-tracking branch 'origin/main' into issue-9991-hotkey-min…
austinywang Sep 1, 2026
e7df022
Merge remote-tracking branch 'origin/main' into issue-9991-hotkey-min…
austinywang Sep 1, 2026
2a29fd9
Merge remote-tracking branch 'origin/main' into issue-9991-hotkey-min…
austinywang Sep 1, 2026
9f96e10
Merge remote-tracking branch 'origin/main' into issue-9991-hotkey-min…
austinywang Sep 1, 2026
e0d7fca
Merge remote-tracking branch 'origin/main' into issue-9991-hotkey-min…
austinywang Sep 1, 2026
dce38e9
Merge remote-tracking branch 'origin/main' into issue-9991-hotkey-min…
austinywang Sep 1, 2026
5eaf4b8
Merge remote-tracking branch 'origin/main' into issue-9991-hotkey-min…
austinywang Sep 1, 2026
0c65436
Merge remote-tracking branch 'origin/main' into issue-9991-hotkey-min…
austinywang Sep 1, 2026
3c8e971
Merge remote-tracking branch 'origin/main' into issue-9991-hotkey-min…
austinywang Sep 1, 2026
3d12fdd
Merge remote-tracking branch 'origin/main' into issue-9991-hotkey-min…
austinywang Sep 1, 2026
169ef38
ci: route browser skill contract through configured runner
austinywang Sep 1, 2026
d1bbc6e
Merge remote-tracking branch 'origin/main' into issue-9991-hotkey-min…
austinywang Sep 1, 2026
9262e59
Merge remote-tracking branch 'origin/main' into issue-9991-hotkey-min…
austinywang Sep 1, 2026
68435c7
Merge remote-tracking branch 'origin/main' into issue-9991-hotkey-min…
austinywang Sep 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions Sources/App/MainWindowVisibilityController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,8 @@ final class MainWindowVisibilityController {
consumeDismissedWindowRestoreTargets: Bool = true
) -> NSWindow? {
let allWindows = uniqueWindows(allWindows)
let visibleOrMiniaturizedTargets = allWindows.filter { window in
dependencies.windowOperations.isVisible(window) || dependencies.windowOperations.isMiniaturized(window)
let visibleTargets = allWindows.filter { window in
dependencies.windowOperations.isVisible(window) && !dependencies.windowOperations.isMiniaturized(window)
}
let revealTargets: [NSWindow]

Expand All @@ -314,14 +314,16 @@ final class MainWindowVisibilityController {
} else {
revealTargets = allWindows.filter { dependencies.windowOperations.isMiniaturized($0) }
}
} else if !visibleOrMiniaturizedTargets.isEmpty {
revealTargets = visibleOrMiniaturizedTargets
} else if !visibleTargets.isEmpty {
revealTargets = visibleTargets
Comment thread
coderabbitai[bot] marked this conversation as resolved.
} else {
let dismissedTargets = dismissedWindowRestoreTargets.filter { dismissedWindow in
allWindows.contains { $0 === dismissedWindow }
}
dismissedWindowRestoreTargets.removeAll()
revealTargets = dismissedTargets
revealTargets = dismissedTargets.isEmpty
? allWindows.filter { dependencies.windowOperations.isMiniaturized($0) }
: dismissedTargets
}

trace("show.begin", reason: reason, windows: revealTargets)
Expand Down
8 changes: 4 additions & 4 deletions cmuxTests/MainWindowVisibilityControllerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,20 +143,20 @@ final class MainWindowVisibilityControllerTests: XCTestCase {
XCTAssertFalse(deminiaturizedWindows.contains { $0 === miniaturizedWindow })
}

func testShowApplicationWindowsStillRestoresMiniaturizedWindowsWhenNoHiddenTargetsWereCaptured() {
func testHiddenApplicationStillRestoresMiniaturizedWindowsWhenNoTargetsWereCaptured() {
let miniaturizedWindow = makeWindow()
defer { miniaturizedWindow.orderOut(nil) }

var miniaturizedIds: Set<ObjectIdentifier> = [ObjectIdentifier(miniaturizedWindow)]
var deminiaturizedWindows: [NSWindow] = []
var madeKeyWindows: [NSWindow] = []
var deminiaturizedWindows: [NSWindow] = [], madeKeyWindows: [NSWindow] = []
var activationCount = 0

let controller = MainWindowVisibilityController(
dependencies: .init(
isActivationSuppressed: { false },
setActiveMainWindow: { _ in },
isApplicationHidden: { false },
isApplicationHidden: { true },
unhideApplication: {},
activateRunningApplication: { _ in activationCount += 1 },
windowOperations: makeWindowOperations(
isMiniaturized: { miniaturizedIds.contains(ObjectIdentifier($0)) },
Expand Down
83 changes: 83 additions & 0 deletions cmuxTests/MainWindowVisibilityLifecycleTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,89 @@ import Testing
@MainActor
@Suite
struct MainWindowVisibilityLifecycleTests {
@Test
func backgroundHotkeyLeavesMiniaturizedWindowsInTheDock() {
let visibleWindow = makeWindow()
let miniaturizedWindow = makeWindow()
defer {
visibleWindow.orderOut(nil)
miniaturizedWindow.orderOut(nil)
}

let visibleId = ObjectIdentifier(visibleWindow)
var miniaturizedIds: Set<ObjectIdentifier> = [ObjectIdentifier(miniaturizedWindow)]
var deminiaturizedWindows: [NSWindow] = []
var madeKeyWindows: [NSWindow] = []
var activationCount = 0

let controller = MainWindowVisibilityController(
dependencies: .init(
isActivationSuppressed: { false },
setActiveMainWindow: { _ in },
isApplicationActive: { false },
isApplicationHidden: { false },
activateRunningApplication: { _ in activationCount += 1 },
windowOperations: makeWindowOperations(
isVisible: { ObjectIdentifier($0) == visibleId },
isMiniaturized: { miniaturizedIds.contains(ObjectIdentifier($0)) },
deminiaturize: { window in
miniaturizedIds.remove(ObjectIdentifier(window))
deminiaturizedWindows.append(window)
},
makeKey: { madeKeyWindows.append($0) }
)
)
)

controller.toggleApplicationVisibility(
windows: [visibleWindow, miniaturizedWindow],
reason: .globalHotkey
)

#expect(activationCount == 1)
#expect(madeKeyWindows.contains { $0 === visibleWindow })
#expect(!deminiaturizedWindows.contains { $0 === miniaturizedWindow })
}

@Test
func backgroundHotkeyRestoresMiniaturizedWindowsWhenAllWindowsAreMinimized() {
let miniaturizedWindow = makeWindow()
defer { miniaturizedWindow.orderOut(nil) }

let miniaturizedId = ObjectIdentifier(miniaturizedWindow)
var miniaturizedIds: Set<ObjectIdentifier> = [miniaturizedId]
var deminiaturizedWindows: [NSWindow] = []
var madeKeyWindows: [NSWindow] = []
var activationCount = 0

let controller = MainWindowVisibilityController(
dependencies: .init(
isActivationSuppressed: { false },
setActiveMainWindow: { _ in },
isApplicationActive: { false },
isApplicationHidden: { false },
activateRunningApplication: { _ in activationCount += 1 },
windowOperations: makeWindowOperations(
isMiniaturized: { miniaturizedIds.contains(ObjectIdentifier($0)) },
deminiaturize: { window in
miniaturizedIds.remove(ObjectIdentifier(window))
deminiaturizedWindows.append(window)
},
makeKey: { madeKeyWindows.append($0) }
)
)
)

controller.toggleApplicationVisibility(
windows: [miniaturizedWindow],
reason: .globalHotkey
)

#expect(activationCount == 1)
#expect(deminiaturizedWindows.contains { $0 === miniaturizedWindow })
#expect(madeKeyWindows.contains { $0 === miniaturizedWindow })
}

@Test
func discardClosedWindowRemovesHiddenRestoreTarget() {
let window = makeWindow()
Expand Down
Loading