macOS 26 (Tahoe) compatibility — backport community fixes + new bug fixes + CI - #1
Draft
emindeniz99 wants to merge 25 commits into
Draft
macOS 26 (Tahoe) compatibility — backport community fixes + new bug fixes + CI#1emindeniz99 wants to merge 25 commits into
emindeniz99 wants to merge 25 commits into
Conversation
Ice's macos-26 branch left several critical issues that prevent the app from working correctly on Tahoe, especially 26.3+ / 26.4+. This change folds in the fixes from the three community PRs that address them (jordanbaird#903, jordanbaird#911, jordanbaird#922) and the cache-thrash guard from jordanbaird#874. Changes: * `Bridging.getActiveMenuBarDisplayID()` falls back to `CGMainDisplayID()` when `CGSCopyActiveMenuBarDisplayIdentifier` returns nil, which is now the case on macOS 26.4.1. Without the fallback, the item cache's `displayID` stayed `nil` and the layout preview rendered as "Unable to display menu bar items" even though items existed. * `MenuBarItemTag.Namespace` on macOS 26 recognizes Ice's own control items by window title ("Ice.ControlItem.*") and falls back to the owning application's identifiers when the owner isn't Control Center. This stops the UUID-namespace feedback loop that left the layout stuck on "Loading menu bar items..." after Control Center re-parented Ice's status items. * `SourcePIDCache` caches failed AX lookups for 30 seconds, and the item manager no longer invalidates the window-ID cache when `sourcePID` is nil. Those two together stopped the thrash where each failed lookup triggered another full scan, racing with `IceBarPanel.show()` and causing clicks to drop roughly half the time on notched Macs. * `AXHelpers.menuBarElement(nearDisplayOrigin:)` probes several inset points along the leftmost menu bar region instead of hit-testing the exact display corner. Single-point probing fails on notched displays (outside the rounded-corner mask), next to menu bar accessories such as NotchNook, and on Tahoe's translucent menu bar. `getApplicationMenuFrame()` and `hasValidMenuBar(in:for:)` both use the new helper. * `MenuBarItemImageCache.compositeCapture` falls back to `item.bounds` when `CGSGetScreenRectForWindow` fails and tolerates a one-pixel discrepancy in the composite width. This keeps items that Control Center has re-parented from being dropped entirely. * XPC `.isFromSameTeam()` requirement is only applied when the current process actually has a team identifier. Ad-hoc signed builds (the default when no signing team is configured) do not, and the old requirement refused every peer, leaving the `MenuBarItemService` unusable. A new `CodeSignInfo` helper inspects the process's code signature. * The settings detail pane is keyed by the current navigation identifier on macOS 26 so that `NavigationSplitView` reliably updates on the first sidebar click.
Follow-up to the macOS 26 compatibility commit, addressing four more issues reported against Tahoe: * jordanbaird#906 "App opens in dock when expanding the bar" — `hideApplicationMenus()` used to flip the activation policy to `.regular`, which on Tahoe manifests as a visible dock icon every time the bar expands. Accessory apps can already steal the menu bar via a plain `activate`, so drop the policy change and leave Ice as `.accessory` throughout. * jordanbaird#908 "System freeze after Missing control item" — when Control Center re-parents Ice's own control items on macOS 26 the hidden control item can momentarily drop out of the menu bar window list. The old handler replaced the cache with an empty one, which immediately triggered another re-cache via observers, and in pathological cases spiralled into a FrontBoard scene-request storm that took the whole compositor down. Keep the previous cache and wait for the next scheduled tick. * jordanbaird#914 "Ice Bar auto-hides before cursor reaches it" — Tahoe synthesises `activeSpaceDidChange` / `didChangeScreenParameters` notifications when the menu bar redraws after the panel is ordered front, causing an immediate auto-hide. Record a `lastShowTimestamp` and ignore those events during a 0.5s grace period. * jordanbaird#918 "Frame check timed out for Intego ONE" — the per-item move-event timeout cap of 150ms was too short for some third-party helpers on macOS 26 whose windows take several hundred ms to update their bounds after a mouse-down. Raise the cap to 500ms so the learned timeout has room to grow when an item is slow to respond.
On macOS 26, when Control Center re-parents Ice's hidden control item, the $frame / $screen publishers can briefly emit nil before the reparented window settles. If the user showed the Ice Bar just before the reparent, the observer here would immediately call hide() and the bar would vanish. Reuse the existing autoHideGracePeriod to swallow those transient nils.
…rd#928) Three follow-on changes inspired by hkfi's PR jordanbaird#928 against the macos-26 branch. All of them stem from System Settings behaving less predictably on macOS 26, and from the Screen Recording permission now sometimes needing the app to relaunch before capture actually starts working: * ScreenCapture.cachedCheckPermissions now only caches a *positive* result. Previously, if the first check returned false (the common case on first launch before the user has granted permission) the false was cached for the lifetime of the process, so granting the permission later had no visible effect until the user quit and reopened Ice. * AppState no longer stops permission timers at the end of setup. macOS 26 lets the user revoke or grant Screen Recording while Ice is running; stopping the timers meant Ice never noticed the change. * Permission.openSettingsPane tries multiple URLs and falls back to /usr/bin/open if NSWorkspace.open returns false. On macOS 26 the anchored `...?Privacy_ScreenCapture` URL is sometimes ignored and the bare Security pane URL is more reliable; if both fail we shell out so the user still lands in System Settings.
The space/screen-parameters Publishers.Merge I added the grace-period check to was calling hide() (which closes an NSPanel) from whatever thread posted the underlying Notification. Notifications from NSWorkspace and NSApplication are generally posted on main, but the contract isn't absolute, and reading lastShowTimestamp from a non-main thread is a data race. Add an explicit receive(on: .main) so the sink is always serialised with the rest of the IceBarPanel's state.
I could only read the descriptions of the community PRs before; after fetching the actual .patch files I realised my implementation had real gaps. Fill them in: * AXHelpers.menuBarElement walks the AX parent chain up to 4 hops when a probe point lands on a menu-bar item instead of the menu bar itself. Without this, hits on "File"/"Edit"/etc. were dropped as not-a-menu-bar. (PR jordanbaird#911) * MenuBarItem / MenuBarItemTag / Namespace accept an optional titleOverride. On some macOS 26 builds Control Center strips the titles off reparented status item windows entirely, so the title prefix check I added earlier doesn't match anything. The caller now frame-matches against live NSStatusItem windows and passes the correct "Ice.ControlItem.*" back in. MenuBarItemManager.cacheItemsRegardless builds that map by converting the ControlItem window frames from Cocoa to CG screen coordinates and looking them up in the current CGWindowList. Items without a precomputed identifier fall through to the existing title-prefix / owner-bundle / UUID chain. (PR jordanbaird#903) * Permission now carries a list of settingsURLs and a mayRequireRelaunch flag. ScreenRecordingPermission gets three URLs — the new macOS 26 PrivacySecurity extension URL with and without the ?Privacy_ScreenCapture anchor, plus the legacy com.apple.preference.security URL. openSettingsPane launches System Settings first (so the URL isn't ignored when it's cold), then walks the URL list via NSWorkspace, and finally shells out to /usr/bin/open. (PR jordanbaird#928) * AppState.relaunch reopens the current bundle via NSWorkspace.openApplication and terminates the current process. PermissionsView, AdvancedSettingsPane, and the Menu Bar Layout pane expose a "Relaunch Ice" button and explanatory copy when a permission has mayRequireRelaunch == true. (PR jordanbaird#928)
Apply ac/sourcetree's three fixes to MenuBarItemSpacingManager verbatim from the upstream patch: 1. applyOffset's per-PID guard uses continue instead of break, so hitting Control Center / the Ice process / a stale NSRunningApplication no longer silently aborts the whole apply. Each skip also logs the reason at debug level. 2. signalAppToQuit's continuation is guarded with a tryClaimOnce()-style OSAllocatedUnfairLock<Bool> helper so the force-terminate failsafe and the KVO observer can't both call resume and trap. A 1-second failsafe inside the timeout task makes sure we resume even if KVO never fires post-terminate. 3. launchApp takes a replacedPID and excludes it from the 'already running' check, so auto-respawning helpers (Login Items, launchd-managed agents) that come back under a new PID are still recognized as fresh rather than matching the dead process.
Four more call sites still went straight to MenuBarItem.getMenuBarItems without building the frame-based control-item map, so on macOS 26 their items.first(matching: .hiddenControlItem) and friends would not have found anything after Control Center reparented Ice's windows. Add MenuBarItemManager.menuBarItems(on:option:) which fetches the raw windows, builds the controlItemMap, and then asks MenuBarItem to turn the pair into items. Point the following through it: * temporarilyShow's destination lookup (needs .hiddenControlItem). * rehideTemporarilyShownItems' per-context rehide path. * LayoutBarPaddingView.performDragOperation's 1-item drag target lookup (needs .hiddenControlItem / .alwaysHiddenControlItem). * MenuBarManager.hideApplicationMenus' leftmost-item scan. MenuBarItemSpacingManager is intentionally left alone: it only reads sourcePID/ownerPID and already guards Control Center and self, so the control-item tag does not matter for its purposes.
Three indentation_width warnings on my own code from running SwiftLint
locally against Ice's .swiftlint.yml — multi-line if/else-if chains
that used column-aligned continuation (leading spaces matching the
opening 'if') instead of Ice's preferred style (keyword on its own
line, each condition indented one level, closing brace on its own
line). Match the existing pattern used elsewhere in the codebase.
Verified with:
swiftc 6.0.3 -parse (all 22 modified files clean)
swiftlint 0.57.1 (no warnings/errors on my code; the 3
pre-existing empty_count errors on integer
counts in MenuBarItemManager remain from
origin/macos-26)
* .github/workflows/build.yml runs on every push/PR.
- swift-parse: Linux job. Installs Swift 6.0.3 and runs
`swiftc -parse -enable-bare-slash-regex` on every .swift file in
Ice / MenuBarItemService / Shared. Catches raw syntax errors
cheaply on free runners before we burn macOS minutes.
- build: matrix over macos-26 (has the macOS 26 SDK and Xcode 26)
and macos-15 (sanity check that we haven't quietly leaked a
macOS 26-only API into an unguarded code path). Both build the
Ice and MenuBarItemService schemes in Debug with code signing
fully disabled, since we don't have Jordan's team identifier on
CI runners. Logs uploaded as artifacts on every run, errors
grepped out and surfaced in the job output.
* HIDEventManager.isMouseInsideEmptyMenuBarSpace now also rejects
"an overlay whose level is above the menu bar at the cursor". This
is AlexandrosAlexiou's PR jordanbaird#933, ported to the current codebase
(the file was renamed EventManager -> HIDEventManager and the
helper namespace MouseCursor -> MouseHelpers in the macos-26
branch refactor; the WindowInfo helper for getting on-screen
windows is also named differently here). Without it,
show-on-click toggles a section when the click was meant for a
third-party HUD/notification overlay drawn above the menu bar.
The first run revealed that the Ice codebase unconditionally calls the macOS 26-only XPCListener(service:requirement:incomingSessionHandler:) initializer, so Xcode 16 (the default on macos-15) cannot build it even with @available guards — the SDK headers simply do not define that overload. Both runners ship with Xcode 26 installed, so explicitly xcode-select to it. macos-15 stays in the matrix as a 'older host OS, newer SDK' canary.
The previous attempt hard-coded /Applications/Xcode_26.app, but the GitHub runners only ship point-version-suffixed apps (Xcode_26.0.app, Xcode_26.1.app, etc.). Glob the directory and take the highest version sorted lexically.
Both .github/workflows/build.yml and .github/workflows/lint.yml ran actions whose default entrypoint is still Node 20 (actions/checkout, actions/upload-artifact, action-swiftlint). GitHub announced that Node 20 is removed from runners on 2026-09-16; opt every job into Node 24 today via FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true so the warnings disappear and we don't get a hard break later. Also bump the lint workflow's checkout pin from @V3 to @v4.
Researched what's actually current: actions/checkout v4 -> v6 (v6.0.2 latest, native Node 24) actions/upload-artifact v4 -> v7 (v7.0.1 latest, native Node 24) Both are native node24 in their action.yml, so the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 escape hatch is no longer needed and is dropped from build.yml. norio-nomura/action-swiftlint runs in a Docker container, so the Node version doesn't apply to it. This silences the "Node 20 actions are deprecated" annotations and hardens both workflows against the 2026-09-16 Node 20 removal.
…a11y amber) * Updates.swift — when Sparkle wants to show a scheduled update prompt while Ice is in the background, activate the app with a regular policy and return `true` so the dialog comes up in front with key focus. Previously we returned `false` and Sparkle put the dialog up anyway, with Ice still .accessory — on macOS 26 the window then refused to accept clicks, which is the cluster of reports in jordanbaird#912 / jordanbaird#926 / jordanbaird#931 / jordanbaird#932 / jordanbaird#937. Same fix is applied to `standardUserDriverWillHandleShowingUpdate` for the user-initiated path. (Adapted from arifim's PR jordanbaird#945.) * PermissionsView.swift — replace plain `.yellow` on the "Continue in Limited Mode" button with a darker amber (sRGB 0.75/0.45/0). The original failed accessibility contrast against the light button background. (Adapted from aramb-dev's PR jordanbaird#942 — the asset-catalog refinement in later commits of that PR is deferred since the current Xcode-26 sync of the project doesn't include the new colorset directory.) Skipped this round: * PR jordanbaird#940 (lilaflo) is an 80-commit re-application of jordanbaird/macos-26 onto another branch — same commits we already carry, nothing new. * PR jordanbaird#944 (aathanwwt) targets CompactSlider 2.x's removed `gestureOptions:` parameter. Package.resolved locks us at 1.2.1 with the upper bound at <2.0, so the parameter still exists in the version we ship. * PR jordanbaird#941 (lixiaoning) notch-auto-hide. The diff references `MenuBarItem.info`, `MenuBarItemTag.iceIcon`, `controlItem.state == .hideItems`, and several private flags (`isMovingItem`, `isMouseButtonDown`, `tempShownItemContexts`, `itemMoveCount`) that don't exist in the macos-26 refactor of MenuBarItemManager. Adapting it would mean rewriting the helper against a different cache architecture, which I shouldn't do without a notched display to verify against. The negative windowNumber guard in the same PR is a no-op for us because we don't read `NSWindow.windowNumber` anywhere in the macos-26 branch.
Reference: https://astral.sh/blog/open-source-security-at-astral https://thehackernews.com/2026/05/mini-shai-hulud-worm-compromises.html Concrete hardening applied to .github/workflows/build.yml and .github/workflows/lint.yml: 1. **All third-party actions pinned to a 40-char commit SHA**, with the human-readable version kept as a trailing comment so Dependabot can still update them. A SHA is immutable; a tag isn't. Resolved: actions/checkout v6.0.2 -> de0fac2e4500dabe0009e67214ff5f5447ce83dd actions/upload-artifact v7.0.1 -> 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a norio-nomura/action-swiftlint 3.2.1 -> 9f4dcd7fd46b4e75d7935cf2f4df406d5cae3684 2. **Default-deny GITHUB_TOKEN permissions**: every workflow now starts with `permissions: {}` at the top level. Only the swiftlint job opts back in (`checks: write`) to post lint annotations. The build / parse jobs need nothing — `upload-artifact` uses the Actions storage API, not the contents API. 3. **Strict bash by default**: `defaults.run.shell: bash -euo pipefail {0}` so a piped failure or unset variable kills the step. 4. **`upload-artifact` if-no-files-found: warn** (was `ignore`) so a silently empty artifact doesn't paper over a broken build, without failing the run outright. 5. **Verified absent**: `pull_request_target`, `workflow_run`, and any `${{ github.event.* }}` / `${{ github.head_ref }}` injection sinks inside `run:` / `with:` blocks — none present, none introduced. These are the recurring entry point for Shai-Hulud-style worms. Phase-1 IoC scan was clean (no `router_init.js`, no obfuscated JS, no exfiltration endpoints, no committed tokens, no unexpected commit authors) so this commit is hardening-only, not incident response.
Reference: https://astral.sh/blog/open-source-security-at-astral Two ecosystems registered, both on a weekly cadence: * github-actions / — covers actions/checkout, actions/upload-artifact, norio-nomura/action-swiftlint (the third-party actions used in .github/workflows/build.yml and lint.yml, all pinned to SHA in the previous commit). Updates are grouped under "actions: { patterns: ["*"] }" so we get one PR per week, not five. * swift / — covers the six XCRemoteSwiftPackageReference entries in Ice.xcodeproj: Sparkle, LaunchAtLogin-Modern, AXSwift, CompactSlider, Ifrit, Semaphore. The `swift` ecosystem key is GitHub's documented identifier for SPM dependencies (SemVer v5). Pull-request budget capped at 5 per ecosystem; opens labelled `dependencies` + `github-actions` / `swift` so they're easy to filter in the issues UI.
zizmor (https://github.com/woodruffw/zizmor) is Astral's static analyzer for GitHub Actions. It catches expression injection, dangerous triggers, missing permissions, unpinned actions, and the rest of the supply-chain-relevant misconfigurations that the Astral playbook (https://astral.sh/blog/open-source-security-at-astral) recommends auditing for. The manual Phase-2 hardening pass already cleared the existing build.yml / lint.yml, but this recurring job catches regressions when someone (human or AI) adds a new workflow later — which is exactly the entry point the Mini-Shai-Hulud worm rides (https://thehackernews.com/2026/05/mini-shai-hulud-worm-compromises.html). Run mode: --persona=auditor --format sarif, output uploaded to GitHub code scanning so findings show up in the Security tab without being lost in CI logs. `continue-on-error: true` during the initial rollout so existing findings (if any) don't block PRs; flip it off once the backlog is triaged. Actions pinned to SHA, with the human-readable version as a trailing comment so Dependabot can still update them: actions/checkout v6.0.2 -> de0fac2e4500dabe0009e67214ff5f5447ce83dd astral-sh/setup-uv v8.1.0 -> 08807647e7069bb48b6ef5acd8ec9567f424441b github/codeql-action/upload-sarif codeql-bundle-v2.25.4 -> bc0b696b4103f5fe60f15749af68a046868d511a Workflow itself runs with permissions: {} at the top level; only the zizmor job opts back in to `security-events: write` (for SARIF upload) and `contents: read` (for checkout). `persist-credentials: false` on checkout so the runner's GITHUB_TOKEN is not left on disk for subsequent steps.
No-op header comment update to force the build.yml / lint.yml / zizmor.yml workflows to re-run on this PR. The previous three pushes only touched `.github/` paths that build.yml's path filter intentionally excludes (we don't rebuild macOS on Dependabot config changes), and the zizmor.yml workflow that was just added didn't fire on the same commit that introduced it. This Swift change brings them all back into scope.
SECURITY-REVIEW.md summarizes the hardening pass against branch
claude/fix-macos26-compatibility-Ar8K6, organized into the five phases
recommended by Astral's open-source security guide:
Phase 1 — IoC compromise scan (clean: no router_init.js, no
Session/webhook exfil endpoints, no committed secrets, no
risky publish actions, no pull_request_target /
workflow_run triggers, no expression injection sinks).
Phase 2 — Workflow hardening: SHA-pinned every third-party action
with the human-readable version as a trailing comment,
default-deny permissions:{} at workflow level with
narrowest per-job override, strict bash defaults, header
blocks documenting the policy.
Phase 3 — Repo-level controls (admin checklist that the maintainer
needs to apply in GitHub Settings: branch protection, tag
rulesets, secret scanning + push protection, code scanning).
Phase 4 — Dependabot for github-actions + swift ecosystems on a
weekly cadence.
Phase 5 — zizmor static analysis with SARIF upload to GitHub code
scanning.
References cited in the report:
https://astral.sh/blog/open-source-security-at-astral
https://thehackernews.com/2026/05/mini-shai-hulud-worm-compromises.html
Includes a verification checklist for the maintainer and a commit map
linking every concrete change to its SHA on this branch (c3f02f5,
6abfa1a, 23ec544, dda0bd4).
## Issue jordanbaird#946 — macOS 26.5 hidden items collapse into always-hidden On macOS Tahoe 26.5, items the user previously placed in the hidden section land in the always-hidden section instead, and dragging them back doesn't stick. Subagent investigation traced the cause to a likely Control Center re-parenting regression that briefly reports the two control items with overlapping/inverted frames. With overlapping bounds, the section predicates in `CacheContext.findSection` make `.hidden` unsatisfiable (`itemBounds.maxX <= hiddenControlItemBounds.minX && itemBounds.minX >= alwaysHiddenControlItemBounds.maxX` can never both hold when the always-hidden bounds touch or cross the hidden bounds), so every formerly-hidden item falls through to `.alwaysHidden`. That exactly matches the reported symptom. Two defensive changes (Swift): * `CacheContext.alwaysHiddenControlItemBounds` is now a computed property that returns `nil` whenever the raw bounds are not strictly to the left of `hiddenControlItemBounds`. The existing no-always- hidden predicate branches in `findSection` then take over, which classify every left-of-hidden item as `.hidden`. The user's hidden customization is preserved through the bad cache tick; the next tick re-derives bounds and, once the control items have settled, always-hidden starts working again. * `enforceControlItemOrder` now reads control-item bounds via `Bridging.getWindowBounds(for:)` instead of the stale CGWindowList snapshot in `item.bounds`. The two can disagree for a few hundred ms during a Control Center re-parent; without the live read, this routine occasionally "corrected" an order that was already right according to the live coordinates. Both changes degrade gracefully if the macOS 26.5 hypothesis is wrong: worst case is one extra `.warning` log per cache tick. Still needs hardware verification before claiming the regression is fixed. ## Phase 5 expansion — gitleaks and OSV-Scanner `.github/workflows/gitleaks.yml` runs gitleaks against the full git history (fetch-depth: 0, persist-credentials: false) on every push, PR, weekly Monday schedule, and workflow_dispatch. SARIF uploaded to GitHub Code Scanning. `continue-on-error: true` during rollout. `.github/workflows/osv-scanner.yml` calls the upstream `osv-scanner-reusable.yml` workflow against Package.resolved on the same schedule. Path-filtered to lockfile / workflow changes for push and PR. All four new `uses:` references pinned to 40-char SHAs with the human-readable version as a trailing comment so Dependabot can keep them current: actions/checkout v6.0.2 de0fac2e4500dabe0009e67214ff5f5447ce83dd gitleaks/gitleaks-action v2.3.9 ff98106e4c7b2bc287b24eaf42907196329070c7 github/codeql-action/upload-sarif codeql-bundle-v2.25.4 bc0b696b4103f5fe60f15749af68a046868d511a google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml v2.3.8 9a498708959aeaef5ef730655706c5a1df1edbc2 ## Documentation SECURITY-REVIEW.md updated to reflect that gitleaks and OSV-Scanner are now part of Phase 5 (no longer in the "deliberately skipped" section), and the new commit is added to the commit map.
…lder
The unquoted form 'shell: bash -euo pipefail {0}' is technically valid
YAML but the GitHub Actions workflow parser appears to have stopped
firing build.yml / lint.yml / zizmor.yml etc. on every push since the
hardening commit. The {0} placeholder reads as the start of a flow
mapping to stricter parsers. Quoting it ("bash -euo pipefail {0}")
keeps the same semantics in Actions and makes the file unambiguous.
The unchecked `as! NSBezierPath` in the shadow-drawing helper has been correlated with EXC_BREAKPOINT crashes on the main thread on macOS 26.5 (see jordanbaird#956). The runtime invariant 'NSBezierPath.copy() returns NSBezierPath' has held in practice, but the safe form costs nothing: switch to `guard let path = copy() as? NSBezierPath else { return }` so a runtime mismatch becomes a no-op draw instead of trapping the process. The displayID half of PR jordanbaird#956 is intentionally skipped: the patch introduces a syntax error (`deviceDescription((deviceDescription[…]` is unbalanced).
The jordanbaird#946 defensive guard turned alwaysHiddenControlItemBounds from a stored `lazy var` into a computed property. Its getter reads two `lazy var` backing properties (rawAlwaysHiddenControlItemBounds and hiddenControlItemBounds); accessing a lazy stored property mutates `self`, so a non-mutating computed getter on a struct fails to compile: error: cannot use mutating getter on immutable value: 'self' is immutable This was not caught earlier because `swiftc -parse` only checks syntax and the macOS build CI stopped firing after d23a15f, so the type-checking phase never ran on this commit. Reproduced and fixed locally with a minimal Swift 6.0.3 typecheck: - non-mutating computed getter reading lazy vars -> error (confirmed) - `mutating get` -> compiles, and the sole caller findSection(_:) is already `mutating func`, so the call sites are unaffected. Mark the getter `mutating get`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft PR opened so we can watch CI run.
Community PR backports
.id(), XPC ad-hoc bypassCGSCopyActiveMenuBarDisplayIdentifiernil →CGMainDisplayID()fallbackbreak→continue, double-resume guard, replacedPIDisMouseInsideOverlayAboveMenuBargate on show-on-clickSelf-authored fixes
Shared/Utilities/CodeSignInfo.swift— Security framework helper that returnsnilfor ad-hoc signed builds. Used so.isFromSameTeam()is only applied when there's a real team identifier.IceBarlastShowTimestamp+ 0.5s grace period to swallow synthesized space/screen events that fire when the panel is ordered front on macOS 26 ([Bug]: Ice Bar auto-hides before cursor reaches it (latest beta) jordanbaird/Ice#914).MenuBarManager.hideApplicationMenusno longer flips activation policy to.regular—.accessoryapps already steal the menu bar, the policy flip was materialising as a dock icon every bar expansion on Tahoe ([Bug]: App opens in dock when expanding the bar jordanbaird/Ice#906).MenuBarItemManager.cacheItemsRegardlesskeeps the previous cache when the hidden control item momentarily drops out of the window list during reparenting, instead of clearing it (which used to spiral into a FrontBoard scene-request storm — [Bug]: Ice appears to have caused system-wide freeze & kernel panic after ~33 hours of uptime jordanbaird/Ice#908).MenuBarItemManager.menuBarItems(on:option:)helper that builds the frame-based control-item map first; the four other call sites that look up Ice's own items by tag now go through it.CI
.github/workflows/build.yml:swiftc -parse -enable-bare-slash-regexon every Swift file underIce/,MenuBarItemService/,Shared/. Cheap; runs on free runners.macos-26+macos-15, code signing fully disabled, builds theIceandMenuBarItemServiceschemes. Logs uploaded as artifacts; errors greppped to job output.Both jobs trigger on every push to a feature branch and on every PR.
Remaining open issues — not fixed here
Generated by Claude Code