Skip to content

Commit 2822ce2

Browse files
author
Geoff Lawson
authored
fix: force prompt for screen capture access (#5)
1 parent f6c5126 commit 2822ce2

File tree

1 file changed

+49
-22
lines changed

1 file changed

+49
-22
lines changed

permissions.mm

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -104,27 +104,42 @@
104104
// Screen Capture access
105105
std::string ScreenAuthStatus() {
106106
std::string auth_status = "not determined";
107-
108-
// Screen Capture is considered allowed if the name of at least one normal
109-
// or dock window running on another process is visible.
110107
if (@available(macOS 10.15, *)) {
111-
CFArrayRef window_list = CGWindowListCopyWindowInfo(
108+
auth_status = "denied";
109+
NSRunningApplication *runningApplication =
110+
NSRunningApplication.currentApplication;
111+
NSNumber *ourProcessIdentifier =
112+
[NSNumber numberWithInteger:runningApplication.processIdentifier];
113+
114+
CFArrayRef windowList = CGWindowListCopyWindowInfo(
112115
kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
113-
int num_windows = (int)CFArrayGetCount(window_list);
114-
int num_named_windows = 0;
115-
for (int idx = 0; idx < num_windows; idx++) {
116-
NSDictionary *info =
117-
(NSDictionary *)CFArrayGetValueAtIndex(window_list, idx);
118-
NSString *window_name = info[(id)kCGWindowName];
119-
if (window_name) {
120-
num_named_windows++;
121-
} else {
122-
break;
116+
int numberOfWindows = CFArrayGetCount(windowList);
117+
for (int index = 0; index < numberOfWindows; index++) {
118+
// get information for each window
119+
NSDictionary *windowInfo =
120+
(NSDictionary *)CFArrayGetValueAtIndex(windowList, index);
121+
NSString *windowName = windowInfo[(id)kCGWindowName];
122+
NSNumber *processIdentifier = windowInfo[(id)kCGWindowOwnerPID];
123+
124+
// don't check windows owned by this process
125+
if (![processIdentifier isEqual:ourProcessIdentifier]) {
126+
// get process information for each window
127+
pid_t pid = processIdentifier.intValue;
128+
NSRunningApplication *windowRunningApplication =
129+
[NSRunningApplication runningApplicationWithProcessIdentifier:pid];
130+
if (windowRunningApplication) {
131+
NSString *windowExecutableName =
132+
windowRunningApplication.executableURL.lastPathComponent;
133+
if (windowName) {
134+
if (![windowExecutableName isEqual:@"Dock"]) {
135+
auth_status = "authorized";
136+
break;
137+
}
138+
}
139+
}
123140
}
124141
}
125-
126-
CFRelease(window_list);
127-
auth_status = (num_windows == num_named_windows) ? "authorized" : "denied";
142+
CFRelease(windowList);
128143
} else {
129144
auth_status = "authorized";
130145
}
@@ -364,11 +379,23 @@ void AskForFullDiskAccess(const Napi::CallbackInfo &info) {
364379

365380
// Request Screen Capture Access.
366381
void AskForScreenCaptureAccess(const Napi::CallbackInfo &info) {
367-
if (@available(macOS 10.14, *)) {
368-
NSWorkspace *workspace = [[NSWorkspace alloc] init];
369-
NSString *pref_string = @"x-apple.systempreferences:com.apple.preference."
370-
@"security?Privacy_ScreenCapture";
371-
[workspace openURL:[NSURL URLWithString:pref_string]];
382+
if (@available(macOS 10.15, *)) {
383+
// Tries to create a capture stream. This is necessary to add the app back
384+
// to the list in sysprefs if the user previously denied.
385+
// https://stackoverflow.com/questions/56597221/detecting-screen-recording-settings-on-macos-catalina
386+
CGDisplayStreamRef stream = CGDisplayStreamCreate(
387+
CGMainDisplayID(), 1, 1, kCVPixelFormatType_32BGRA, nil,
388+
^(CGDisplayStreamFrameStatus status, uint64_t displayTime,
389+
IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef){
390+
});
391+
if (stream) {
392+
CFRelease(stream);
393+
} else {
394+
NSWorkspace *workspace = [[NSWorkspace alloc] init];
395+
NSString *pref_string = @"x-apple.systempreferences:com.apple.preference."
396+
@"security?Privacy_ScreenCapture";
397+
[workspace openURL:[NSURL URLWithString:pref_string]];
398+
}
372399
}
373400
}
374401

0 commit comments

Comments
 (0)