Skip to content

Commit 7f6b56b

Browse files
author
Geoff Lawson
authored
fix: remove occasional double prompting for screen capture and accessibility (#11)
1 parent 6225fdd commit 7f6b56b

File tree

1 file changed

+61
-8
lines changed

1 file changed

+61
-8
lines changed

permissions.mm

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,55 @@
3636
return path;
3737
}
3838

39+
// This method determines whether or not a system preferences security
40+
// authentication request is currently open on the user's screen and foregrounds
41+
// it if found
42+
bool HasOpenSystemPreferencesDialog() {
43+
int MAX_NUM_LIKELY_OPEN_WINDOWS = 4;
44+
bool isDialogOpen = false;
45+
CFArrayRef windowList;
46+
47+
// loops for max 1 second, breaks if/when dialog is found
48+
for (int index = 0; index <= MAX_NUM_LIKELY_OPEN_WINDOWS; index++) {
49+
windowList = CGWindowListCopyWindowInfo(
50+
kCGWindowListOptionOnScreenAboveWindow, kCGNullWindowID);
51+
int numberOfWindows = CFArrayGetCount(windowList);
52+
53+
for (int windowIndex = 0; windowIndex < numberOfWindows; windowIndex++) {
54+
NSDictionary *windowInfo =
55+
(NSDictionary *)CFArrayGetValueAtIndex(windowList, windowIndex);
56+
NSString *windowOwnerName = windowInfo[(id)kCGWindowOwnerName];
57+
NSNumber *windowLayer = windowInfo[(id)kCGWindowLayer];
58+
NSNumber *windowOwnerPID = windowInfo[(id)kCGWindowOwnerPID];
59+
60+
if ([windowLayer integerValue] == 0 &&
61+
[windowOwnerName isEqual:@"universalAccessAuthWarn"]) {
62+
// make sure the auth window is in the foreground
63+
NSRunningApplication *authApplication = [NSRunningApplication
64+
runningApplicationWithProcessIdentifier:[windowOwnerPID
65+
integerValue]];
66+
67+
[NSRunningApplication.currentApplication
68+
activateWithOptions:NSApplicationActivateAllWindows];
69+
[authApplication activateWithOptions:NSApplicationActivateAllWindows];
70+
71+
isDialogOpen = true;
72+
break;
73+
}
74+
}
75+
76+
CFRelease(windowList);
77+
78+
if (isDialogOpen) {
79+
break;
80+
}
81+
82+
usleep(250000);
83+
}
84+
85+
return isDialogOpen;
86+
}
87+
3988
// Returns a status indicating whether the user has authorized Contacts
4089
// access.
4190
std::string ContactAuthStatus() {
@@ -112,8 +161,8 @@
112161
NSNumber *ourProcessIdentifier =
113162
[NSNumber numberWithInteger:runningApplication.processIdentifier];
114163

115-
CFArrayRef windowList = CGWindowListCopyWindowInfo(
116-
kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
164+
CFArrayRef windowList =
165+
CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID);
117166
int numberOfWindows = CFArrayGetCount(windowList);
118167
for (int index = 0; index < numberOfWindows; index++) {
119168
// get information for each window
@@ -536,24 +585,28 @@ void AskForScreenCaptureAccess(const Napi::CallbackInfo &info) {
536585
// to the list in sysprefs if the user previously denied.
537586
// https://stackoverflow.com/questions/56597221/detecting-screen-recording-settings-on-macos-catalina
538587
CGDisplayStreamRef stream = CGDisplayStreamCreate(
539-
CGMainDisplayID(), 1, 1, kCVPixelFormatType_32BGRA, nil,
588+
CGMainDisplayID(), 1, 1, kCVPixelFormatType_32BGRA, NULL,
540589
^(CGDisplayStreamFrameStatus status, uint64_t displayTime,
541590
IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef){
542591
});
592+
543593
if (stream) {
544594
CFRelease(stream);
545595
} else {
546-
NSWorkspace *workspace = [[NSWorkspace alloc] init];
547-
NSString *pref_string = @"x-apple.systempreferences:com.apple.preference."
548-
@"security?Privacy_ScreenCapture";
549-
[workspace openURL:[NSURL URLWithString:pref_string]];
596+
if (!HasOpenSystemPreferencesDialog()) {
597+
NSWorkspace *workspace = [[NSWorkspace alloc] init];
598+
NSString *pref_string =
599+
@"x-apple.systempreferences:com.apple.preference."
600+
@"security?Privacy_ScreenCapture";
601+
[workspace openURL:[NSURL URLWithString:pref_string]];
602+
}
550603
}
551604
}
552605
}
553606

554607
// Request Accessibility Access.
555608
void AskForAccessibilityAccess(const Napi::CallbackInfo &info) {
556-
NSDictionary *options = @{(id)kAXTrustedCheckOptionPrompt : @(YES)};
609+
NSDictionary *options = @{(id)kAXTrustedCheckOptionPrompt : @(NO)};
557610
bool trusted = AXIsProcessTrustedWithOptions((CFDictionaryRef)options);
558611

559612
if (!trusted) {

0 commit comments

Comments
 (0)