You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断AXUIElement对应的窗口所在的NSScreen?

如何确定外部窗口所属的NSScreen

已通过Accessibility API获取到外部应用窗口的AXUIElement引用及窗口frame,也能设置窗口位置,但用窗口frame或原点是否包含在屏幕frame里的方法判断窗口所属屏幕时失效——比如存在窗口大部分区域在左屏,却被系统判定属于右屏的情况。

原尝试的无效代码:

let window: AXUIElement

// 从窗口读取kAXPositionAttribute、kAXSizeAttribute并反转Y轴计算得到
let windowFrame: CGRect 

// 这些方法无效
let screenWhereWindowIsDisplayed = NSScreen.screens.first(where: { $0.frame.contains(windowFrame) })
let screenWhereWindowIsDisplayed = NSScreen.screens.first(where: { $0.frame.contains(windowFrame.origin) })

解决方案

macOS中窗口的归属屏幕通常由窗口核心区域(如标题栏位置)或与屏幕的交集优先级决定,可采用以下两种更可靠的判断方式:

1. 基于窗口中心位置判断

系统通常会将窗口中心所在的屏幕判定为归属屏幕,这种方式简单高效:

let windowCenter = CGPoint(x: windowFrame.midX, y: windowFrame.midY)
let screenWhereWindowIsDisplayed = NSScreen.screens.first { screen in
    screen.frame.contains(windowCenter)
}

2. 基于交集面积判断

如果窗口跨屏且中心位置判断仍不符合预期,可计算窗口与每个屏幕的交集面积,取交集最大的屏幕:

func screenForWindowFrame(_ frame: CGRect) -> NSScreen? {
    var maxIntersectionArea: CGFloat = 0
    var targetScreen: NSScreen?
    
    for screen in NSScreen.screens {
        let intersectionRect = frame.intersection(screen.frame)
        let area = intersectionRect.width * intersectionRect.height
        if area > maxIntersectionArea {
            maxIntersectionArea = area
            targetScreen = screen
        }
    }
    
    return targetScreen
}

// 调用方法
let screenWhereWindowIsDisplayed = screenForWindowFrame(windowFrame)

原方法失效原因

原判断逻辑过于绝对:

  • $0.frame.contains(windowFrame)要求整个窗口完全处于某一屏幕内,跨屏窗口直接不满足;
  • $0.frame.contains(windowFrame.origin)仅以窗口左上角原点判断,当窗口原点在A屏但主体/标题栏在B屏时,系统仍会将窗口归属到B屏。

内容的提问来源于stack exchange,提问作者Guig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:22:36