使用 AppKit

问题描述

我正在尝试构建一个 macOS 实用程序,它允许我以编程方式更改机器上全屏应用程序的顺序。

例如,假设我机器上的全屏应用目前按从左到右的顺序排列:

  1. iTerm
  2. Xcode

我希望能够在 AppKit 中调用一个方法来说出诸如“将 Xcode 从全屏索引 2 移动到索引 0”之类的内容。但是,我无法确定可以帮助我做到这一点的 AppKit API。

  • NSScreen 只提供物理显示,不提供全屏应用程序/空间
  • NSApplication 仅提供我的 应用程序窗口的列表
  • CGWindowListcopyWindowInfo 看起来很有希望,但它没有关于全屏应用程序顺序的信息。它也不允许我获得一个 NSWindow 对象来希望改变订单

我想用 AppKit 做的事情是否可行?

谢谢!

解决方法

空间(桌面和全屏应用都只是空间)是系统窗口管理器的一项功能,只能由用户通过应用 Mission Control 进行管理。

当然,Window Manager 需要暴露一个 API 来管理,否则 Mission Control 怎么与之交互?但该 API 不是公开的。

可以在线找到这些私有 API 的反向工程标头,例如
https://github.com/NUIKit/CGSInternal

有了这些标头,您可以编写如下代码:

#import "CGSInternal/CGSSpace.h"

CGSSpaceID activeSpace = 
    CGSGetActiveSpace(_CGSDefaultConnection());
NSLog(@"activeSpace: %zu",activeSpace);

CFArrayRef spaceArray = 
    CGSCopySpaces(_CGSDefaultConnection(),kCGSAllSpacesMask);
NSLog(@"allSpaces: %@",(__bridge id)spaceArray);

但通常的警告在这里适用:

您不能将使用私有 API 的代码提交到 Apple 的 App Store。没有官方文档,关于该 API 的所有已知信息都已被逆向工程,并且可能并不总是正确的。由于 API 不是公开的,Apple 可以在没有任何事先警告的情况下随时更改它,因此您的工作代码可能会随着每次系统更新而中断。