What's is a reliable way to detect if user has enabled this API?
CGWindowListCreateImage
returns a valid object even if screen recording API is disabled. There are multiple combinations possible (kCGWindowListOptionIncludingWindow
, kCGWindowListOptionOnScreenBelowWindow
) and only some will return NULL.
- (CGImageRef)createScreenshotImage
{
NSWindow *window = [[self view] window];
NSRect rect = [window frame];
rect.origin.y = NSHeight([[window screen] frame]) - NSMaxY([window frame]);
CGImageRef screenshot = CGWindowListCreateImage(
rect,
kCGWindowListOptionIncludingWindow,
//kCGWindowListOptionOnScreenBelowWindow,
0,//(CGWindowID)[window windowNumber],
kCGWindowImageBoundsIgnoreFraming);//kCGWindowImageDefault
return screenshot;
}
The only reliable way is through CGDisplayStreamCreate
which is risky as Apple always changes privacy settings every year.
- (BOOL)canRecordScreen
{
if (@available(macOS 10.15, *)) {
CGDisplayStreamRef stream = CGDisplayStreamCreate(CGMainDisplayID(), 1, 1, kCVPixelFormatType_32BGRA, nil, ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) {
;
});
BOOL canRecord = stream != NULL;
if (stream) {
CFRelease(stream);
}
return canRecord;
} else {
return YES;
}
}
Apple provides direct low level api to check for access and grant access. No need to use tricky workarounds.
/* Checks whether the current process already has screen capture access */
@available(macOS 10.15, *)
public func CGPreflightScreenCaptureAccess() -> Bool
Use the above functions to check for screen capture access.
if access is not given use the below function to prompt for access
/* Requests event listening access if absent, potentially prompting */
@available(macOS 10.15, *)
public func CGRequestScreenCaptureAccess() -> Bool