My sandbox app on MAS (Hide Icons) simply toggles the visibility of the Desktop icons and Widgets on or off. It does this by display customized NSWindow on window level given by NSWindow.Level(rawValue: Int(CGWindowLevelForKey(.desktopIconWindow))+1)
This custom NSWindow can either have a copy of the Desktop background/wallpaper CGImage or a solid color depending on user preference.
Until macOS 27, this worked fine. To find all the Desktop background/wallpaper images (there can be multiple screens and each screen can have multiple Spaces), Apple provided code that avoided any TCC dialog boxes. Namely
func getDesktopWindowIds() -> [CGWindowID] {
let windows = CGWindowListCopyWindowInfo([.optionAll], kCGNullWindowID)! as! [[String: AnyObject]]
let DesktopWindowLevel = CGWindowLevelForKey(.desktopWindow)-1
let DesktopWindows = windows.filter {
let windowLevel = $0[kCGWindowLayer as String] as! CGWindowLevel
return windowLevel == desktopWindowLevel
}
return desktopWindows.map {
$0[kCGWindowNumber as String] as! CGWindowID
}
}
which returns [CGWindowID] of all the Desktop background/wallpaper windows. Then for any one, say cgID, a simple
let cgImage = CGWindowListCreateImage(CGRectNull, [.optionIncludingWindow], cgID, [.bestResolution])
gave an CGImage which then can be applied to my custom NSWindow. No where is TCC triggered. All is great. I followed Apple's ideas about Security and Privacy since I'm only using the data I need (i.e. [CGWindowID]) and the data is only used during execution. Never saved or shared.
macOS 27 beta 4 and beyond broke CGWindowListCreateImage(...). It compiles and when called it returns some gray image. Documentation tells me to use ScreenCaptureKit.
The newest versions of ScreenCaptureKit introduce SCScreenshotManager.captureImage(contentFilter:, configuration) which can return a CGImage of the CGWindowID.
Here is when the problem occurs. To capture that CGWindowID CGImage, one would use SCContentFilter(desktopIndependentWindow: desktopWindow) but to get desktopWindow you first need to find the SCWindow that corresponds to CGWindowID. You can grab a set of SCWindow with
SCShareableContent.excludingDesktopWindows(false, onScreenWindowsOnly: false)
But when any method of SCShareableContent is called, TCC throws up this warning
I do not want this. Too many permissions are being granted. I only want the [CGWindowID] of the Desktop background/wallpaper. This, if the user grants, gives me much more which is bad for Security and Privacy.
One way to avoid the TCC in ScreenCaptureKit is to use the new SCContentSharingPicker.shared. This allows the user to pick what they want to share. I first tried
var pickerConfiguration = SCContentSharingPickerConfiguration()
pickerConfiguration.allowedPickerModes = [.multipleWindows, .singleWindow]
but the picker does not allow the user to select the Desktop background/wallpaper. Using
var pickerConfiguration = SCContentSharingPickerConfiguration()
pickerConfiguration.allowedPickerModes = [.singleDisplay]
also doesn't give me Desktop background/wallpaper access. Trying to use [.singleApplication] and limiting the choices to WindowServer (what SCWindow claims is the owner) also doesn't allow picking of the Desktop background/wallpaper.
So, is it true to get access to the Desktop background/wallpaper CGWindowID's CGImage, I must have the user give me full access via TCC?
Please tell me of a work around.
The obvious fix is on Apple's side. The corresponding list of [SCWindow] corresponding to [CGWindowID] should always be included in SCContentFilter.includedWindows. Or simply leave them out of the TCC domain as before.