Swift获取带桌面编号与位置信息的已打开应用窗口列表
macOS 获取带桌面编号的全量应用窗口列表实现方案
注意你给出的返回示例里size和position的字段定义写反了,实际窗口属性中x/y为窗口左上角坐标(对应position),width/height为窗口宽高(对应size),实现时注意字段映射不要出错。
Swift 原生实现(推荐,可满足全部需求)
你之前用的CGWindowListCopyWindowInfo已经可以覆盖大半需求,搭配少量未在头文件公开的CoreGraphics接口就能拿到桌面编号,不需要完全依赖AppleScript:
- 基础信息&可见性判断:调用
CGWindowListCopyWindowInfo时传入[.optionAll, .excludeDesktopElements]作为选项,可过滤掉菜单栏、Dock、桌面图标等系统级窗口。返回的字典中:kCGWindowOwnerName对应应用名kCGWindowBounds直接返回窗口的x/y坐标、width/height尺寸kCGWindowIsOnscreen为布尔值,可直接判断窗口是否处于可见状态(未最小化、未隐藏)
- 桌面(Space)编号获取:公开API未暴露该字段,可直接调用CoreGraphics的稳定内部接口实现,不需要关闭SIP,仅需要在应用entitlements中关闭App Sandbox(沙盒环境限制跨进程窗口信息读取),核心代码如下:
import CoreGraphics // 获取系统CGS主连接 let cgsConnection = CGSMainConnectionID() // 遍历所有拿到的窗口,取每个窗口的windowID var windowSpaceID: UInt64 = 0 // 查询窗口所属的Space ID CGSGetWindowSpace(cgsConnection, windowID, &windowSpaceID) // 调用CGSCopyManagedDisplaySpaces拿到所有桌面/全屏空间的有序列表,匹配windowSpaceID对应的序号即为desktopNumber // 全屏应用会占用独立的Space条目,自动对应独立的桌面编号,不需要额外做尺寸判断
该方案兼容性覆盖macOS 10.15到最新正式版系统,仅当应用需要上架Mac App Store时会因为调用未公开接口被拒,非上架类工具应用可放心使用。
AppleScript 备选方案(存在明显局限性)
如果不想调用上述内部接口,可以用AppleScript配合辅助功能权限实现部分能力,但无法完全满足需求:
- 前置要求:必须给应用开启辅助功能权限,否则无法读取其他应用的窗口信息
- 存在的缺陷:
- 无法枚举所有Space下的窗口,仅能读取当前显示Space上的窗口内容
- 没有暴露Space唯一ID映射关系,无法精准匹配desktopNumber
- 部分沙盒严格的应用、系统进程的窗口无法被读取
核心参考脚本:
tell application "System Events" -- 枚举所有可见的应用进程 set runningApps to every application process whose visible is true repeat with targetApp in runningApps set appName to name of targetApp set appWindows to every window of targetApp repeat with targetWin in appWindows -- 读取窗口坐标、尺寸 set winPosition to position of targetWin set winSize to size of targetWin end repeat end repeat end tell
内容的提问来源于stack exchange,提问作者Lich
相关产品推荐
相关产品推荐

