0

I am currently developing an Electron application with a companion Swift application that takes screenshots of the user's screen on keypress. It also takes a 1x1 pixel screenshot of the screen from time to time to figure out if a specific app is in dark mode.

After joining the latest macOS Sequoia beta, I've been seeing this permission pop up multiple times a day:

[App] can access this computer's screen and audio. Do you want to continue to allow access?

Screenshot of permission nag

I think this is an unnecessary burden to my users especially after allowing it in the privacy settings. I want to get ahead of this and figure out if there is any way to get around having this shown multiple times a day.

I want the functionality to be when the user does allow permissions at the start of my app's onboarding, they never have to worry about it again.

func getPixelColor(at point: CGPoint) -> NSColor? {
    let captureRect = CGRect(x: point.x, y: point.y, width: 1, height: 1)
    guard let imageRef = CGWindowListCreateImage(captureRect, .optionOnScreenBelowWindow, kCGNullWindowID, [.nominalResolution]) else { return nil }
    
    let bitmapRep = NSBitmapImageRep(cgImage: imageRef)
    let color = bitmapRep.colorAt(x: 0, y: 0)
    
    return color
}
6
  • You didn't get the repeated privacy alerts before macOS Sequoia?
    – soundflix
    Commented Jun 21 at 6:36
  • Which screenshot API are you using?
    – soundflix
    Commented Jun 21 at 6:37
  • 1
    That "specific app" you want to check for dark mode is not yours, but third party?
    – soundflix
    Commented Jun 21 at 6:52
  • No, I didn't get repeated piracy alerts before macOS Sequoia. I've attached the screenshot API I'm using to the question, and I want to check dark mode for third-party apps. That's correct.
    – Krish Shah
    Commented Jun 21 at 18:45
  • CGWindowListCreateImage is deprecated. With macOS 15 you have to use ScreenCaptureKit.
    – soundflix
    Commented Jun 21 at 20:25

2 Answers 2

2

You seem to be looking for a solution to the wrong problem.

Taking a screenshot to determine if the app is in dark mode is far too complex for what you're trying to achieve, let alone a blatant privacy flaw (even though its only 1x1 pixels). It is only possible to circumvent OS-level privacy warnings if your users are on jailbroken devices and turn it off themselves.

Try looking at baking a variable into your companion app that indicates true/false if isDarkMode is enabled or something you can read instead, it'll be easier to determine, it won't have privacy issues and will require less code and computation.

4
  • 1
    I agree that it seems to be too complex for that simple task. And an app taking screenshots without direct user interaction should need regular permission reminders. I don't think Apple would bless that.
    – soundflix
    Commented Jun 21 at 6:34
  • I don't understand what "jailbroken devices" means in a macOS context.
    – soundflix
    Commented Jun 21 at 6:34
  • @soundflix My mistake, I assumed it was iOS. In that case disregard the jailbroken bit.
    – HyperionX
    Commented Jun 21 at 8:37
  • Unfortunately, this doesn't solve my problem. I have to reliably and scalably check if a third-party application is in dark mode. Moreover, I think I also get this issue even without the 1x1 screenshot and the fact that my app always takes screenshots on user interaction.
    – Krish Shah
    Commented Jun 21 at 18:48
0

The repeated reminders about continuing to grant an app screen recording permission are indeed new in the Sequoia betas. I haven't found a way to stop them. In one of the WWDC videos, it was implied that the newer API (ScreenCaptureKit) might be less draconian, but I'm getting the prompts when using that too.

As far as detecting Dark Mode, you can just check for it in your app if the app you're interested in always follows the system appearance. Look at the name of the effective appearance of the shared NSApplication instance and see if it contains the substring "Dark". Something like:

let appearanceName : String = NSApp.effectiveAppearance.name.rawValue;
if(appearanceName.contains("Dark")) {
    print("Dark Mode")
}
else {
    print("Light Mode")
}

However, if the external app you're interested in has its own themes or appearance controls that don't follow the system appearance, then you've gotta go the screen capture route.

Not the answer you're looking for? Browse other questions tagged or ask your own question.