如何编写Applescript固定Safari外接屏位置并解决窗口移位、尺寸异常问题
故障根因
之前的脚本存在两个核心认知误区,直接导致了位置偏移:
- macOS窗口定位使用全局统一坐标系,所有连接的显示器共享同一个坐标空间,坐标原点固定在系统显示器排列面板中最靠左上角的屏幕的左上角,不存在单屏独立从(0,0)开始计数的规则。
- 硬编码的窗口边界值
{170, 0, 2560, 1440},整体落在MacBook内置屏的坐标覆盖范围内(内置屏x方向跨度为0-1440,y方向跨度为0-900)。系统检测到目标窗口位置在内置屏区域,自动将窗口拽回内置屏;又因为内置屏最大显示高度仅900,窗口高度被系统自动截断到900,和实际出现的现象完全吻合。
修正方案
放弃硬编码外接屏坐标的写法,先动态读取外接显示器在全局坐标系下的实际边界值,再在这个边界范围内计算符合需求的窗口位置,保证窗口完全落在外接屏的显示区域内。
修正后的可运行脚本如下:
tell application "System Events" -- 枚举所有连接的显示器,找到分辨率为2560x1440的外接屏 set externalDisplayBounds to missing value repeat with d in displays set dBounds to bounds of d set dispWidth to (item 3 of dBounds) - (item 1 of dBounds) set dispHeight to (item 4 of dBounds) - (item 2 of dBounds) if dispWidth is 2560 and dispHeight is 1440 then set externalDisplayBounds to dBounds exit repeat end if end repeat -- 未匹配到目标显示器时直接退出 if externalDisplayBounds is missing value then return "未找到2560x1440分辨率的外接显示器" end if -- 按需求计算窗口坐标:左侧预留170px边距,撑满外接屏剩余显示区域 set winLeft to (item 1 of externalDisplayBounds) + 170 set winTop to item 2 of externalDisplayBounds set winRight to item 3 of externalDisplayBounds set winBottom to item 4 of externalDisplayBounds tell application "Safari" activate -- 退出全屏状态,避免bounds设置失效 if value of attribute "AXFullScreen" of window 1 is true then set value of attribute "AXFullScreen" of window 1 to false delay 0.3 end if set bounds of window 1 to {winLeft, winTop, winRight, winBottom} end tell end tell
落地注意事项
- 脚本运行前,需要在「系统偏好设置-安全性与隐私-辅助功能」中,给承载脚本运行的程序(脚本编辑器、终端、快捷指令等)授予辅助功能权限,否则无法读取显示器参数、修改窗口位置。
- 动态获取坐标的逻辑不受屏幕排列方向影响:无论你把外接屏拖到内置屏的左、右、上、下哪个位置,脚本都能正确定位外接屏,不会因为调整屏幕排列规则就失效。
- 如果外接屏开启了系统显示缩放,实际像素坐标和标称分辨率存在偏差,可以调整脚本中的分辨率匹配阈值,或者通过显示器序号直接指定目标外接屏。
内容的提问来源于stack exchange,提问作者Colin
相关产品推荐
相关产品推荐

