|
36 | 36 | return path;
|
37 | 37 | }
|
38 | 38 |
|
| 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 | + |
39 | 88 | // Returns a status indicating whether the user has authorized Contacts
|
40 | 89 | // access.
|
41 | 90 | std::string ContactAuthStatus() {
|
|
112 | 161 | NSNumber *ourProcessIdentifier =
|
113 | 162 | [NSNumber numberWithInteger:runningApplication.processIdentifier];
|
114 | 163 |
|
115 |
| - CFArrayRef windowList = CGWindowListCopyWindowInfo( |
116 |
| - kCGWindowListOptionOnScreenOnly, kCGNullWindowID); |
| 164 | + CFArrayRef windowList = |
| 165 | + CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID); |
117 | 166 | int numberOfWindows = CFArrayGetCount(windowList);
|
118 | 167 | for (int index = 0; index < numberOfWindows; index++) {
|
119 | 168 | // get information for each window
|
@@ -536,24 +585,28 @@ void AskForScreenCaptureAccess(const Napi::CallbackInfo &info) {
|
536 | 585 | // to the list in sysprefs if the user previously denied.
|
537 | 586 | // https://stackoverflow.com/questions/56597221/detecting-screen-recording-settings-on-macos-catalina
|
538 | 587 | CGDisplayStreamRef stream = CGDisplayStreamCreate(
|
539 |
| - CGMainDisplayID(), 1, 1, kCVPixelFormatType_32BGRA, nil, |
| 588 | + CGMainDisplayID(), 1, 1, kCVPixelFormatType_32BGRA, NULL, |
540 | 589 | ^(CGDisplayStreamFrameStatus status, uint64_t displayTime,
|
541 | 590 | IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef){
|
542 | 591 | });
|
| 592 | + |
543 | 593 | if (stream) {
|
544 | 594 | CFRelease(stream);
|
545 | 595 | } 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 | + } |
550 | 603 | }
|
551 | 604 | }
|
552 | 605 | }
|
553 | 606 |
|
554 | 607 | // Request Accessibility Access.
|
555 | 608 | void AskForAccessibilityAccess(const Napi::CallbackInfo &info) {
|
556 |
| - NSDictionary *options = @{(id)kAXTrustedCheckOptionPrompt : @(YES)}; |
| 609 | + NSDictionary *options = @{(id)kAXTrustedCheckOptionPrompt : @(NO)}; |
557 | 610 | bool trusted = AXIsProcessTrustedWithOptions((CFDictionaryRef)options);
|
558 | 611 |
|
559 | 612 | if (!trusted) {
|
|
0 commit comments