分离 CGWindowListCopyWindowInfo 返回的真实窗口和虚拟窗口

Him*_*u P 7 macos objective-c swift

我正在为 macOS 创建一个窗口切换器。

我用来CGWindowListCopyWindowInfo获取打开的窗口的列表。

    let windows = CGWindowListCopyWindowInfo([.excludeDesktopElements], kCGNullWindowID)
Run Code Online (Sandbox Code Playgroud)

我没有使用该optionOnScreenOnly选项,CGWindowListCopyWindowInfo因为它排除了非空间窗口。

但是,这会导致某些虚拟窗口也包含在窗口列表中。例如,Xcode 上每个打开的选项卡都有一个窗口。除了实际窗口之外,VLC 播放器还有一个额外的隐形窗口。如果我使用optionOnScreenOnly.

有没有办法将这些虚拟窗口与实际窗口分开?

我已经探索了返回的字典中的kCGWindowLayer和键,但无法区分窗口。kCGWindowStoreTypeCGWindowListCopyWindowInfo

编辑

我对 Swift 和 Objective-C 解决方案以及私有 API 调用持开放态度。

编辑2

我知道这是可能的,因为应用程序Witch可以正确处理这些情况。

Ted*_*ley 2

我不确定这是否捕获了您感兴趣的所有情况,但如果我们采用 返回的字典数组并按(窗口 ID)CGWindowListCopyWindowInfo()对条目进行分组kCGWindowNumber,看起来我们最终会得到以下三个之一案例:

  • 只有一个字典条目具有该窗口号(它是一个简单的窗口,可能在屏幕上或屏幕外)
  • 几个字典都有该窗口 ID,并且组中只有一个字典将键kCGWindowIsOnscreen设置为 1:其他字典要么缺少键,要么将其设置为 0。这意味着我们有一个带有多个选项卡的窗口,并且条目带有kCGWindowIsOnscreenset是可见的选项卡。
  • 多个字典都有该窗口 ID,但没有一个字典将键kCGWindowIsOnscreen设置为 1(在所有情况下都丢失或设置为 0)。这意味着我们有一个带有多个选项卡的窗口当前位于屏幕外。

我假设您可能已经过滤掉了第 0 层 ( ) 之外的所有内容kCGWindowLayer = 0。看起来我们视觉上感知为“窗口”的大部分内容都位于第 0 层(状态菜单项似乎位于单位数或低两位数的层中;小部件似乎位于第 100 层左右......)。

我没有看到任何简单、直接的方法来解决这个问题,但您应该能够将此逻辑构建成可行的东西。