【问题标题】:CGWindowListCopyWindowInfo returns info with kCGWindowSharingState set to 0CGWindowListCopyWindowInfo 返回 kCGWindowSharingState 设置为 0 的信息
【发布时间】:2020-06-03 07:39:32
【问题描述】:

我正在尝试从另一个进程获取窗口的 kCGWindowSharingState 值。

我创建了一个新项目并将NSWindow.sharingType 设置为NSWindowSharingReadWrite

我创建了另一个项目,并从该项目中运行以下代码以获取 kCGWindowSharingState 的值:

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

它返回具有kCGWindowSharingState 值的字典数组,但它始终设置为0

任何有关这方面的帮助都会很好。提前致谢。

【问题讨论】:

  • 确实编辑了您的问题,以更清楚地说明您的要求和回答。让我知道我的编辑是否有误,而您要求其他内容。
  • @zrzka 弄得一团糟,编辑搞砸了:),我不想获取共享类型,问题是共享类型在其他进程中始终为 0,即使我设置它到 NSWindowSharingReadWrite 或 NSWindowSharingReadOnly
  • 如果有人需要,我也可以添加项目示例代码。
  • 我不明白。你说我不想获取共享类型,然后问题是共享类型在其他进程中始终为0,这意味着你正在获取它并检查值。无需添加示例代码,正如我在答案中所写,您的 另一个项目 必须具有屏幕录制权限,否则无论您在第一个项目中设置什么,kCGWindowSharingState 将始终为 0 .
  • 我想要来自 CGWindowListCopyWindowInfo api 的信息,而不是名为 kCGWindowSharingState 的共享类型,所以这可能会让你感到困惑。

标签: objective-c cocoa nswindow


【解决方案1】:

您的另一个项目必须具有屏幕录制权限。是否有 API 可以请求它们?不,您必须尝试录制屏幕才能获得系统对话框。

- (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;
}

您可以在没有这些权限的情况下使用CGWindowListCopyWindowInfo,但kCGWindowSharingState 的值将始终为0。一旦您的另一个应用获得这些权限,就会返回正确的值。

WWDC 2019 - Advances in macOS Security简单讨论。

此安全舞适用于kCGWindowSharingStatekCGWindowName


我的应用程序委托:

- (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);
}

没有录屏权限

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;
}

屏幕录制权限

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;
}

【讨论】:

  • 感谢您的回复。我已授予这两个项目的所有权限。但是当从 CGWindowListCopyWindowInfo api 询问时它仍然给我 0
  • 从上面的 api 仅窗口服务器和扩展坞的 kCGWindowSharingState 为 1,这意味着 NSWindowSharingReadOnly 我找不到任何使用 NSWindowSharingReadOnly 的示例,当它从一个应用程序设置并从其他应用程序读取时
  • 那你做错了,看看我更新的答案和代码和输出。
  • 感谢我发现了错误,实际上我认为需要访问权限,但现在需要运行时权限。谢谢您的帮助。我已经投票并接受了答案。一个简单的问题,如果共享状态为 1 或 2,我可以从窗口编号获取 NSWindow 并为该 NSWindow 设置一些参数吗?
  • 仅当它是 your 窗口时,请查看此答案,例如:stackoverflow.com/a/31890095/581190。请注意,cmets 不适用于其他问题,您应该创建一个新问题。如果您想修改窗口的某些属性(移动它,...),请搜索关于 SO 的可访问性问题。
猜你喜欢
  • 1970-01-01
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
  • 2021-01-30
  • 2020-01-17
  • 1970-01-01
  • 1970-01-01
  • 2016-10-21
相关资源
最近更新 更多