Skip to content

Improve macOS 26 screen recording permission handling#928

Open
hkfi wants to merge 2 commits into
jordanbaird:macos-26from
hkfi:macos-26-permissions-fix
Open

Improve macOS 26 screen recording permission handling#928
hkfi wants to merge 2 commits into
jordanbaird:macos-26from
hkfi:macos-26-permissions-fix

Conversation

@hkfi
Copy link
Copy Markdown

@hkfi hkfi commented Apr 19, 2026

Summary

  • open the Screen Recording settings pane more reliably on newer macOS versions
  • keep permission state updating after setup instead of freezing the initial result
  • avoid caching stale negative screen-capture permission checks
  • add relaunch guidance and actions for the macOS 26 flow where capture may only work after restarting the app

Why

On macOS 26, Ice could open the wrong or no settings pane for Screen Recording, keep showing stale permission state after the user changed the setting, and leave the user without a clear way to recover when a relaunch was required for capture to start working.

Notes

  • based on the macos-26 branch
  • excludes local-only fork changes such as personal signing configuration

@hkfi hkfi changed the title Macos 26 permissions fix Improve macOS 26 screen recording permission handling Apr 19, 2026
emindeniz99 pushed a commit to emindeniz99/Ice that referenced this pull request Apr 23, 2026
…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.
emindeniz99 pushed a commit to emindeniz99/Ice that referenced this pull request Apr 23, 2026
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant