Skip to content

Commit a3db05f

Browse files
committed
Revert "fix: use item identities instead of window IDs to detect app restarts"
This reverts commit 457fb74.
1 parent 80a4bd1 commit a3db05f

File tree

1 file changed

+22
-42
lines changed

1 file changed

+22
-42
lines changed

Thaw/MenuBar/MenuBarItems/MenuBarItemManager.swift

Lines changed: 22 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -426,11 +426,6 @@ extension MenuBarItemManager {
426426
/// of the previous cache.
427427
private(set) var cachedItemWindowIDs = [CGWindowID]()
428428

429-
/// A list of the menu bar item tags (namespace:title) at the time
430-
/// of the previous cache. Used to detect actual app restarts
431-
/// instead of relying on window IDs which can be reassigned.
432-
private(set) var cachedItemTags = [String]()
433-
434429
/// Runs the given async closure as a task and waits for it to
435430
/// complete before returning.
436431
///
@@ -448,15 +443,9 @@ extension MenuBarItemManager {
448443
cachedItemWindowIDs = itemWindowIDs
449444
}
450445

451-
/// Updates the list of cached menu bar item tags.
452-
func updateCachedItemTags(_ itemTags: [String]) {
453-
cachedItemTags = itemTags
454-
}
455-
456446
/// Clears the list of cached menu bar item window identifiers.
457447
func clearCachedItemWindowIDs() {
458448
cachedItemWindowIDs.removeAll()
459-
cachedItemTags.removeAll()
460449
}
461450
}
462451

@@ -808,7 +797,6 @@ extension MenuBarItemManager {
808797
}
809798

810799
let previousWindowIDs = await cacheActor.cachedItemWindowIDs
811-
let previousItemTags = await cacheActor.cachedItemTags
812800
let displayID = Bridging.getActiveMenuBarDisplayID()
813801
MenuBarItemManager.diagLog.debug("cacheItemsRegardless: displayID=\(displayID.map { "\($0)" } ?? "nil"), previousWindowIDs count=\(previousWindowIDs.count)")
814802

@@ -831,9 +819,6 @@ extension MenuBarItemManager {
831819
let itemWindowIDs = currentItemWindowIDs ?? items.reversed().map { $0.windowID }
832820
await cacheActor.updateCachedItemWindowIDs(itemWindowIDs)
833821

834-
let itemTags = items.map { "\($0.tag.namespace):\($0.tag.title)" }
835-
await cacheActor.updateCachedItemTags(itemTags)
836-
837822
await MainActor.run {
838823
MenuBarItemTag.Namespace.pruneUUIDCache(keeping: Set(itemWindowIDs))
839824
self.pruneMoveOperationTimeouts(keeping: Set(items.map(\.tag)))
@@ -912,8 +897,7 @@ extension MenuBarItemManager {
912897
let didRestoreSections = await restoreItemsToSavedSections(
913898
items,
914899
controlItems: controlItems,
915-
previousWindowIDs: previousWindowIDs,
916-
previousItemTags: previousItemTags
900+
previousWindowIDs: previousWindowIDs
917901
)
918902
if didRestoreSections {
919903
MenuBarItemManager.diagLog.debug("Restored item to saved section; scheduling recache")
@@ -935,8 +919,7 @@ extension MenuBarItemManager {
935919
let didRestoreOrder = await restoreSavedItemOrder(
936920
items,
937921
controlItems: controlItems,
938-
previousWindowIDs: previousWindowIDs,
939-
previousItemTags: previousItemTags
922+
previousWindowIDs: previousWindowIDs
940923
)
941924

942925
if didRestoreOrder {
@@ -2842,26 +2825,23 @@ extension MenuBarItemManager {
28422825
private func restoreItemsToSavedSections(
28432826
_ items: [MenuBarItem],
28442827
controlItems: ControlItemPair,
2845-
previousWindowIDs _: [CGWindowID],
2846-
previousItemTags: [String]
2828+
previousWindowIDs: [CGWindowID]
28472829
) async -> Bool {
28482830
guard !savedSectionOrder.isEmpty else { return false }
28492831
guard !suppressNextNewLeftmostItemRelocation else { return false }
28502832
guard !lastMoveOperationOccurred(within: .seconds(2)) else { return false }
28512833

2852-
// Use item tags (namespace:title) instead of window IDs to detect app restarts.
2853-
// Window IDs can be reassigned by the WindowServer even when apps are still running,
2854-
// which would incorrectly trigger restore and cause items to move randomly.
2855-
let currentTags = Set(items.map { "\($0.tag.namespace):\($0.tag.title)" })
2856-
let previousTagsSet = Set(previousItemTags)
2857-
2858-
// Only restore when previous item tags have disappeared (actual app restart).
2859-
// If same items are present (even with different window IDs), skip restore.
2860-
guard !previousTagsSet.isEmpty && !previousTagsSet.isSubset(of: currentTags) else {
2861-
MenuBarItemManager.diagLog.debug("restoreItemsToSavedSections: no app restart detected (same items present), skipping")
2834+
// Only restore when previous window IDs have disappeared (app restarted).
2835+
// This prevents undoing the user's manual section moves on regular cache refreshes.
2836+
let currentWindowIDSet = Set(items.map(\.windowID))
2837+
let previousWindowIDSet = Set(previousWindowIDs)
2838+
guard !previousWindowIDSet.isEmpty && !previousWindowIDSet.isSubset(of: currentWindowIDSet) else {
2839+
MenuBarItemManager.diagLog.debug("restoreItemsToSavedSections: no app restart detected (window IDs unchanged), skipping")
28622840
return false
28632841
}
28642842

2843+
// Get current item tags.
2844+
let currentTags = Set(items.map { "\($0.tag.namespace):\($0.tag.title)" })
28652845
let savedTags = Set(savedSectionOrder.values.flatMap { $0 })
28662846
let savedTagsInCurrent = savedTags.intersection(currentTags)
28672847

@@ -3001,8 +2981,7 @@ extension MenuBarItemManager {
30012981
private func restoreSavedItemOrder(
30022982
_ items: [MenuBarItem],
30032983
controlItems: ControlItemPair,
3004-
previousWindowIDs _: [CGWindowID],
3005-
previousItemTags: [String]
2984+
previousWindowIDs: [CGWindowID]
30062985
) async -> Bool {
30072986
guard !savedSectionOrder.isEmpty else { return false }
30082987

@@ -3018,15 +2997,16 @@ extension MenuBarItemManager {
30182997
// will have no recent move timestamp.
30192998
guard !lastMoveOperationOccurred(within: .seconds(2)) else { return false }
30202999

3021-
// Use item tags (namespace:title) instead of window IDs to detect app restarts.
3022-
// Window IDs can be reassigned by the WindowServer even when apps are still running,
3023-
// which would incorrectly trigger restore and cause items to move randomly.
3024-
let currentTags = Set(items.map { "\($0.tag.namespace):\($0.tag.title)" })
3025-
let previousTagsSet = Set(previousItemTags)
3026-
3027-
// Only restore when previous item tags have disappeared (actual app restart).
3028-
// If same items are present (even with different window IDs), skip restore.
3029-
guard !previousTagsSet.isSubset(of: currentTags) else { return false }
3000+
// Only restore when previous window IDs have disappeared, indicating
3001+
// an app restarted (old windows destroyed, new ones created). During
3002+
// move operations macOS can briefly report duplicate windows for the
3003+
// same item, which adds transient IDs to the current set. Checking
3004+
// for removed IDs (rather than any set difference) avoids false
3005+
// positives from these duplicates and from user drag-and-drop, which
3006+
// only repositions existing windows without removing any.
3007+
let currentWindowIDSet = Set(items.lazy.map(\.windowID))
3008+
let previousWindowIDSet = Set(previousWindowIDs)
3009+
guard !previousWindowIDSet.isSubset(of: currentWindowIDSet) else { return false }
30303010

30313011
// Don't interfere with items that are currently temporarily shown.
30323012
let activelyShownTags = Set(temporarilyShownItemContexts.map {

0 commit comments

Comments
 (0)