4

I am trying to get the pixel colors from the screen for a specified portion of the display. I am using CGDIsplayCreateImage(_:) to do so, but for some reason instead of creating a screenshot of the currently open windows it just gives an image of the wallpaper and the task bar.

In order to visualize the screenshot I am using a SwiftUI view. In my application I actually don't need the screenshot displayed.

struct ScreenshotView: View {
    let cgImage: CGImage

    var body: some View {
        Image(decorative: cgImage, scale: 3)
    }
}

And the applicationDidFinishLaunching(_:) methods looks like this.

func applicationDidFinishLaunching(_ aNotification: Notification) {

  let contentRect = NSRect(x: 0, y: 0, width: 240, height: 240)

  // Create the window and set the content view.
  window = NSWindow(
      contentRect: contentRect,
      styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
      backing: .buffered, defer: false)
  window.center()
  window.setFrameAutosaveName("Main Window")
  window.contentView = NSHostingView(rootView: ScreenshotView(cgImage: CGDisplayCreateImage(CGMainDisplayID())!))
  window.makeKeyAndOrderFront(nil)
}

Since XCode and some other apps are open it should give me a screenshot of the current screen with all open windwos. Instead I get a screenshot of the wallpaper and the taskbar showing my apps name. No apps are showing and the dock is also missing.

enter image description here

Am I doing something wrong or is this a bug?

In this stackoverflow answers suggest that I am using the function correctly.

jns_ai_unr
  • 753
  • 1
  • 8
  • 19
  • I suspect this is part of the tightened security and privacy controls in Catalina. Your app may need additional entitlements or it may need a resource-access usage description string in Info.plist. However, I don't immediately find anything directly relevant to capturing screenshots. – Ken Thomases Nov 10 '19 at 12:06
  • See: https://stackoverflow.com/questions/56597221/detecting-screen-recording-settings-on-macos-catalina – Ken Thomases Nov 10 '19 at 12:10
  • Thank you for your answer. When executing the app, it asks me if I want to enable "Screen Recording". Also in `Settings -> Security & Privacy -> Privacy -> Screen Recording` my app is listed and access is allowed. So actually it should be working, or am I missing something in the link you gave? – jns_ai_unr Nov 10 '19 at 12:21
  • OK, well that's good as far it goes. Is your app being code-signed on each build? The permissions recognize an app by its code signature and designated requirements. If an app isn't code-signed, the system generates an ad hoc signature, but that applies to that specific build only. – Ken Thomases Nov 10 '19 at 13:34
  • Since I am greeted with the `"App" would like to record this computer's screen.` every time I run the build I assume it is newly signed on each build. Where would I change that? – jns_ai_unr Nov 10 '19 at 13:41
  • In the target settings, I think on the Info tab. If you run instead of build-and-run, does it work on a run after the system has prompted you for permission (and you grant it)? You might try deleting your app from the Privacy listing in System Peferences first and then try the experiment. – Ken Thomases Nov 10 '19 at 20:08
  • Yes if I start the app without building it works properly (after giving permissions). Only if I build and run then it does not work. But within XCode the bundle identifier is set properly. In the info tab and in the .plist it is set to `$(PRODUCT_BUNDLE_IDENTIFIER)` by default. so actually it should not change. Should I maybe set it manually instead of relying on env vars? – jns_ai_unr Nov 11 '19 at 13:33
  • The problem isn't the bundle ID. Is your app being code-signed? There should be a section about "Signing" in the target settings. You might need to toggle it open. – Ken Thomases Nov 11 '19 at 15:39
  • @KenThomases thank you. I gave an answer below based on your help. – jns_ai_unr Nov 12 '19 at 10:40

1 Answers1

4

Even if this might be obvious to some people I will answer my own question here using the help of Ken Thomases.

Below you can find the settings I set within my target. It now works after every rebuild. Make sure to deactivate automatic signing and set the signing certificate to 'Sign to Run Local'.

enter image description here

Hope this helps someone at some point.

jns_ai_unr
  • 753
  • 1
  • 8
  • 19