I'm seeing a behavior difference in CGWindowListCopyWindowInfo between macOS 26 Tahoe and macOS 27 Golden Gate beta regarding the Screen Recording / System Audio Recording privacy permission, and I'd like to confirm whether this is intentional or a beta regression.
Environment
macOS 26 Tahoe (26.x) — tested behavior below macOS 27 Golden Gate beta 4 (26A5388g) — tested behavior below
Expected behavior (matches Tahoe) When my app does NOT have permission under System Settings > Privacy & Security > Screen & System Audio Recording:
CGWindowListCopyWindowInfo still returns window list entries for other running apps. However, kCGWindowOwnerName for windows owned by processes other than my own app is nil.
When permission IS granted, kCGWindowOwnerName is populated correctly for all windows.
Actual behavior on Golden Gate Even without Screen Recording permission granted (verified in System Settings, and via CGPreflightScreenCaptureAccess() returning false), kCGWindowOwnerName is populated for windows owned by other running apps — i.e., the same as if permission had been granted.
Repro
swift let options: CGWindowListOption = [.optionOnScreenOnly, .excludeDesktopElements] let windowList = CGWindowListCopyWindowInfo(options, kCGNullWindowID) as? [[String: AnyObject]] for window in windowList ?? [] { let owner = window[kCGWindowOwnerName as String] as? String print(owner ?? "nil") } On Tahoe without permission: prints nil for other apps' windows. On Golden Gate beta 4 without permission: prints the actual owner name for other apps' windows.
Question
Is this a known/intentional change in Golden Gate, or a beta regression in the TCC enforcement path for this API? Since Apple has been steadily tightening screen-capture-adjacent APIs (Sonoma/Sequoia/Tahoe) and recommending migration to ScreenCaptureKit, should we treat any reliance on kCGWindowOwnerName's permission-gated nil behavior as unsupported going forward, and use a different API to check whether the process has Screen Recording access?
Any guidance from DTS would be appreciated. Happy to file a Feedback Assistant report with a sample project if useful — let me know the FB number format expected.
Thanks for the detailed comparison and the repro.
Start with the approach itself, because that is the fragile part. Using whether kCGWindowOwnerName comes back nil as a signal for "this process does not have Screen Recording permission" relies on undocumented behavior. The CGWindowListCopyWindowInfo reference does not document any permission gating of its keys. So which keys are populated without permission is undocumented and may change at any time.
The supported approaches are:
- To check Screen Recording authorization, use
CGPreflightScreenCaptureAccess(), which reports the current state without prompting. To request it, useCGRequestScreenCaptureAccess(), which prompts. These are the documented APIs for the permission state, which is what thenilcheck was approximating. Use them rather than inferring permission from which keys are populated. - For enumerating windows and apps going forward,
SCShareableContentin ScreenCaptureKit is the modern surface. The older Core Graphics screen-capture image APIs are deprecated in favor of ScreenCaptureKit.
Since there is a documented API for checking Screen Recording authorization, I do not think a Feedback report is justified in this case.
For reference: