0

I am trying to get the kCGWindowSharingState value for a window from another process.

I created a new project and and set the NSWindow.sharingType to NSWindowSharingReadWrite.

I created another project and from that project I am running the following code to get the value of kCGWindowSharingState:

CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
NSLog(@"windowList: %@", windowList);

It returns an array of dictionaries with the kCGWindowSharingState value, but it's always set to 0.

Any help regarding this would be good. Thanks in advance.

zrzka
  • 20,249
  • 5
  • 47
  • 73
Amit Hooda
  • 2,133
  • 3
  • 23
  • 37
  • Did edit your question to make it more clear what you're asking for and replied. Let me know if my edit is wrong and you asked for something else. – zrzka Jun 03 '20 at 11:07
  • @zrzka it made a mess, things got messed up with the edit :) , i don't want to get the sharingtype, the issues is sharingtype is always 0 in other process, even if i set it to NSWindowSharingReadWrite or NSWindowSharingReadOnly – Amit Hooda Jun 03 '20 at 11:12
  • I can also add sample code of projects if anyone needs it. – Amit Hooda Jun 03 '20 at 11:13
  • I don't get it. You say _I don't want to get the sharingtype_ and then _the issues is sharingtype is always 0 in other process_ which means that you're getting it and checking the value. No need to add sample code, as I wrote in the answer, your _another project_ must have screen recording permissions otherwise the `kCGWindowSharingState` will be always be `0` no matter what you set in the first project. – zrzka Jun 03 '20 at 11:19
  • i want information from CGWindowListCopyWindowInfo api and its not the sharingtype its named as kCGWindowSharingState so that might have got you confused. – Amit Hooda Jun 03 '20 at 11:23
  • Just to clarify `sharingType` & `kCGWindowSharingState` - `NSWindow.sharingType` value == `kCGWindowSharingState` value. – zrzka Jun 03 '20 at 11:47

1 Answers1

2

Your another project must have screen recording permissions. Is there an API to ask for them? No. You have to try to record a screen to get the system dialog.

- (BOOL)doWeHaveScreenRecordingPermissions {
    // Try to record -> triggers system dialog
    CGDisplayStreamRef stream = CGDisplayStreamCreate(CGMainDisplayID(), 1, 1, kCVPixelFormatType_32BGRA, nil, ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) {
    });

    // NULL = No permissions
    BOOL result = stream != NULL;

    if (stream) {
        CFRelease(stream);
    }

    return result;
}

You can use CGWindowListCopyWindowInfo without these permissions, but the value for the kCGWindowSharingState will always be 0. Correct value will be returned once your another app gains these permissions.

Briefly discussed in the WWDC 2019 - Advances in macOS Security.

This security dance applies to kCGWindowSharingState & kCGWindowName.


My application delegate:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    NSLog(@"Screen Recording permissions: %@", [self doWeHaveScreenRecordingPermissions] ? @"Yay!" : @"N/A");

    CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
    if (windowList == NULL) {
        return;
    }

    CFIndex count = CFArrayGetCount(windowList);
    for (CFIndex index = 0 ; index < count ; index++) {
        CFDictionaryRef windowInfo = CFArrayGetValueAtIndex(windowList, index);

        CFStringRef owner = CFDictionaryGetValue(windowInfo, kCGWindowOwnerName);
        if (owner == NULL) {
            continue;
        }

        if (CFStringCompare(owner, CFSTR("ShareWindow"), 0) != kCFCompareEqualTo) {
            continue;
        }

        NSLog(@"Got a window from ShareWindow! %@", windowInfo);
    }

    CFRelease(windowList);
}

No screen recording permissions

2020-06-03 13:22:36.073581+0200 GetSharedWindow[54889:828225] Screen Recording permissions: N/A
2020-06-03 13:22:36.074951+0200 GetSharedWindow[54889:828225] Got a window from ShareWindow! {
    kCGWindowAlpha = 1;
    kCGWindowBounds =     {
        Height = 292;
        Width = 480;
        X = 235;
        Y = 538;
    };
    kCGWindowIsOnscreen = 1;
    kCGWindowLayer = 0;
    kCGWindowMemoryUsage = 1152;
    kCGWindowNumber = 5672;
    kCGWindowOwnerName = ShareWindow;
    kCGWindowOwnerPID = 54445;
    kCGWindowSharingState = 0;         <-----
    kCGWindowStoreType = 1;
}

Screen recording permissions

2020-06-03 13:24:33.823247+0200 GetSharedWindow[55697:832599] Screen Recording permissions: Yay!
2020-06-03 13:24:33.824580+0200 GetSharedWindow[55697:832599] Got a window from ShareWindow! {
    kCGWindowAlpha = 1;
    kCGWindowBounds =     {
        Height = 292;
        Width = 480;
        X = 235;
        Y = 538;
    };
    kCGWindowIsOnscreen = 1;
    kCGWindowLayer = 0;
    kCGWindowMemoryUsage = 1152;
    kCGWindowName = Window;
    kCGWindowNumber = 5672;
    kCGWindowOwnerName = ShareWindow;
    kCGWindowOwnerPID = 54445;
    kCGWindowSharingState = 2;         <-----
    kCGWindowStoreType = 1;
}
zrzka
  • 20,249
  • 5
  • 47
  • 73
  • Thanks for the reply. I have given all the the permissions to both the projects. But it still gives me 0 when asked from CGWindowListCopyWindowInfo api – Amit Hooda Jun 03 '20 at 11:18
  • from the above api only window server & dock have kCGWindowSharingState as 1 which means NSWindowSharingReadOnly and i could not find any example of using NSWindowSharingReadOnly when its set from one application and read from other application – Amit Hooda Jun 03 '20 at 11:21
  • Then you're doing something wrong, see my updated answer with code & output. – zrzka Jun 03 '20 at 11:25
  • thanks i found the mistake, actually i was thinking that accessiblity permission was needed but there is a runtime permission which is required now. Thanks for the help. I have upvoted and accepted the ans. One quick question though can i get NSWindow from the window number if the shareing state is 1 or 2 and set some parameters to that NSWindow ? – Amit Hooda Jun 03 '20 at 11:28
  • Only if it's _your_ window, see this answer for example: https://stackoverflow.com/a/31890095/581190. Be aware that comments are not for additional questions, you should create a new one. Search for accessibility questions on SO if you'd like modify some properties of the window (move it, ...). – zrzka Jun 03 '20 at 11:46
  • Yes i understand that SO is not for additional questions in comments, either we could move in chat or ask another question, but there is one thing missing how i can't tag any user there in comments so as to ask to particular user. – Amit Hooda Jun 03 '20 at 11:58
  • I know how to do when its my own app, but the think is i have multiple apps in my bundle, so its my app but in a way its completely another app so can i have something like that in that case. – Amit Hooda Jun 03 '20 at 12:01
  • I have asked another question if you can help me with that here is the link https://stackoverflow.com/questions/62178732/showing-one-nswindow-from-one-nsapplication-on-top-of-another-nswindow-from-nsap – Amit Hooda Jun 03 '20 at 17:16