From fd1b2e50ce5e237a94d176b937b4c664e3addb4b Mon Sep 17 00:00:00 2001 From: Amir Zarrinkafsh <3339418+nightah@users.noreply.github.com> Date: Wed, 13 May 2026 08:45:48 +1000 Subject: [PATCH 1/2] fix(menubar): stop double-counting NSStatusItemSpacing in notch overflow budget The notch overflow check in `applyProfileLayout` was subtracting `(count - 1) * userSpacing` from `availableWidth` while the per-item widths it summed into `profileBaseline` already had the spacing baked in by macOS. The deduction therefore over-counted layout cost by `(count - 1) * userSpacing` pixels. The error scaled linearly with the spacing value, so it was invisible at `offset=-12` (spacing `4`) but ejected several profile items into the hidden section at `offset=0` (the macOS default of `16`) even when the menu bar visibly had room. Applying the Built-in Retina Display profile at default spacing pushed six items into hidden while leaving roughly 200px of empty bar between the rightmost visible item and Control Center. Empirical measurements taken from the `Notch overflow budget:` diagnostic log with the same 11 profile items at three spacing values (`-12`, `-6`, `0`) showed the average reported `item.bounds.width` rising linearly from `24.8` to `31.2` to `36.8`, an implied icon-only width of about `20.8` plus exactly the current spacing value. The Control Center item's `bounds.minX` (used as `rightBoundary`) also shifted left by about `2px` per `1px` of spacing for the same reason. Both inputs to the budget already reflect the spacing, so the explicit `(count - 1) * userSpacing` deduction was pure double-counting. This change removes that deduction and rewrites the comment block above `userSpacing` to record the empirical relationship instead of the inverted assumption that was there before. `userSpacing` itself is retained because the `Notch overflow budget:` diagnostic line continues to log it. With the fix in place the Built-in Retina apply at `offset=0` reports `availableWidth=424` against `profileBaseline=419`; the profile fits, no overflow is triggered, and the visible section matches what the bar actually has room for. Signed-off-by: Amir Zarrinkafsh <3339418+nightah@users.noreply.github.com> --- .../MenuBarItems/MenuBarItemManager.swift | 33 +++++-------------- 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/Thaw/MenuBar/MenuBarItems/MenuBarItemManager.swift b/Thaw/MenuBar/MenuBarItems/MenuBarItemManager.swift index 42ba474c..9e2a77a6 100644 --- a/Thaw/MenuBar/MenuBarItems/MenuBarItemManager.swift +++ b/Thaw/MenuBar/MenuBarItems/MenuBarItemManager.swift @@ -5540,17 +5540,14 @@ extension MenuBarItemManager { let rightBoundary = ccItem.map(\.bounds.minX) ?? screen.frame.maxX var availableWidth = rightBoundary - (notch.maxX + notchGap) - // Read the actual NSStatusItemSpacing applied to the system. - // This is the inter-item gap at render time. The width sum - // below uses item.bounds.width, which is the button's - // clickable rectangle and does NOT include the gap. Without - // adding it, the budget under-counts total layout cost by - // (count - 1) × spacing px and overflow can be silently - // missed once the user has enough items in the menu bar — - // most visibly when the spacing has been customised away - // from the default 16, since the per-item miscount stops - // matching the historical buffer the check happened to - // have. + // NSStatusItemSpacing is recorded here for diagnostic logging + // only. macOS bakes the spacing into each status item's frame + // (verified empirically: item.bounds.width grows 1:1 with the + // spacing value), so item.bounds.width and the Control Center + // item's bounds.minX already account for it. Subtracting a + // separate (count - 1) * spacing gap here used to double-count + // the spacing and ejected items into hidden when the bar still + // had room, most visibly at the macOS default of 16. let userSpacing = CGFloat(max(0, 16 + appState.spacingManager.offset)) // Subtract the layout footprint of items that occupy the @@ -5601,19 +5598,7 @@ extension MenuBarItemManager { } } - // Account for the (count - 1) inter-item gaps across all - // items in the visible area, profile and non-profile - // combined. Slightly conservative: when items overflow, - // the gap count drops by 1 per overflowed item, but using - // the pre-overflow total is the right starting point and - // the loop below removes overflow items one at a time - // until the remaining footprint fits. - let totalItemCount = visibleUIDs.count + nonProfileCount - if totalItemCount > 1 { - availableWidth -= CGFloat(totalItemCount - 1) * userSpacing - } - - // Find the Thaw visible control icon — it must always stay visible. + // Find the Thaw visible control icon, which must always stay visible. let visibleCtrlUID = items.first(where: { $0.tag == .visibleControlItem })?.uniqueIdentifier let chevronWidth = visibleCtrlUID.flatMap { uidWidths[$0] } ?? 0 From 8751e995a5c049495d6d5601b92984fa14d08d76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9?= Date: Tue, 12 May 2026 15:56:27 -0700 Subject: [PATCH 2/2] fix: add explicit Xcode version selection Specify Xcode version to resolve compatibility issues. --- .github/workflows/build-dmg.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build-dmg.yml b/.github/workflows/build-dmg.yml index 87e2d0fd..cc77ecf8 100644 --- a/.github/workflows/build-dmg.yml +++ b/.github/workflows/build-dmg.yml @@ -12,6 +12,9 @@ jobs: steps: - uses: actions/checkout@v6 + # Issues with other Xcode versions, so we need to specify the version explicitly + - run: sudo xcode-select -s /Applications/Xcode_26.5.app/Contents/Developer + - name: Configure signing uses: ./.github/actions/configure-signing with: