ScreenCaptureKit is NOT a full replacement for CGWindowListCreateImage

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.

Answered by DTS Engineer in 908437022

Thanks for the detailed write-up, including the picker modes you've already tried, and for limiting your app to only the data it needs.

What you describe on macOS 27 differs from what WWDC 2019 described. Advances in macOS Security, the session that introduced the getDesktopWindowIds() approach, says: "Apps can freely record the contents of their own windows, the menu bar and the desktop background image."

The ScreenCaptureKit documentation says to "Request screen recording permission from the person before capturing content." It also recommends SCContentSharingPicker for letting people choose what to share. Those are the two documented ways for the person to give consent: the Screen Recording permission that SCShareableContent requested in your testing, and the picker. With the picker not offering those windows, that leaves Screen Recording. I can't offer a way to capture them with ScreenCaptureKit without it. The Screen Recording alert is how the person grants that access.

I suggest filing two separate Feedback Assistant reports:

  • a bug report about the CGWindowListCreateImage change, showing what it returns for the same desktop background window on macOS 26 and on macOS 27
  • an enhancement request for a narrower grant that covers only the wallpaper windows, as you suggest

Please post the Feedback numbers here so we can make sure they get routed to the right team.

Please note that filing an enhancement request does not guarantee Apple will add any requested functionality to Apple products in the future. However, with that said, filing an enhancement request is a good way to get your ideas in front of the folks who make decisions about that sort of thing.

If you're not familiar with how to file reports, take a look at Bug Reporting: How and Why? I also replied in your related thread, Get Desktop background image, including a note about the first-run problem you mention there.

Thanks for the detailed write-up, including the picker modes you've already tried, and for limiting your app to only the data it needs.

What you describe on macOS 27 differs from what WWDC 2019 described. Advances in macOS Security, the session that introduced the getDesktopWindowIds() approach, says: "Apps can freely record the contents of their own windows, the menu bar and the desktop background image."

The ScreenCaptureKit documentation says to "Request screen recording permission from the person before capturing content." It also recommends SCContentSharingPicker for letting people choose what to share. Those are the two documented ways for the person to give consent: the Screen Recording permission that SCShareableContent requested in your testing, and the picker. With the picker not offering those windows, that leaves Screen Recording. I can't offer a way to capture them with ScreenCaptureKit without it. The Screen Recording alert is how the person grants that access.

I suggest filing two separate Feedback Assistant reports:

  • a bug report about the CGWindowListCreateImage change, showing what it returns for the same desktop background window on macOS 26 and on macOS 27
  • an enhancement request for a narrower grant that covers only the wallpaper windows, as you suggest

Please post the Feedback numbers here so we can make sure they get routed to the right team.

Please note that filing an enhancement request does not guarantee Apple will add any requested functionality to Apple products in the future. However, with that said, filing an enhancement request is a good way to get your ideas in front of the folks who make decisions about that sort of thing.

If you're not familiar with how to file reports, take a look at Bug Reporting: How and Why? I also replied in your related thread, Get Desktop background image, including a note about the first-run problem you mention there.

ScreenCaptureKit is NOT a full replacement for CGWindowListCreateImage
 
 
Q