◆

Mac 双显示器鼠标切换 Hammerspoon 配置

2023-12-19 09:480

要解决什么问题

外接一块显示器之后,最消耗精力的操作是把鼠标从一块屏拖到另一块。屏幕尺寸大、两屏拼在一起横向距离将近一米,鼠标要划过整个屏幕宽度才过去,中途还容易在屏幕边缘卡住(两块屏的可用区域没完全对齐时,边界上有一段是过不去的)。

窗口挪动同理。把一个窗口从主屏搬到副屏,得按住标题栏一路拖过去,松手位置还不一定合适。macOS 自带的窗口管理只有全屏和左右分屏,跨屏移动没有快捷键。

Hammerspoon 能补上这块。它是 macOS 的自动化工具,用 Lua 脚本调用系统 API,屏幕、窗口、鼠标位置都能直接读写,几行代码就能实现「一个键把鼠标传送到另一块屏」。

配置步骤

1、下载 Hammerspoon https://download.csdn.net/download/weixin_40013817/88462061

也可以用 Homebrew 装:brew install --cask hammerspoon,或者去官网下最新版。

2、在【安全性与隐私】->【辅助功能】中开启控制权限

这一步不能跳过。Hammerspoon 要控制其他应用的窗口、移动鼠标,属于系统敏感操作,必须显式授权。没授权的话脚本能加载、快捷键能注册,但按下去没有任何反应也不报错——这是最容易卡住的地方,配置写对了却不生效,八成是权限没给。

新系统上路径是「系统设置 → 隐私与安全性 → 辅助功能」,把 Hammerspoon 的开关打开。如果之前授权过又重装了应用,需要先移除再重新添加,否则系统认的还是旧的签名。

3、在任务栏点击图标,选择 Open Config,也就是打开 /Users/gld/.hammerspoon/init.lua,填写以下代码并保存

配置文件路径是 ~/.hammerspoon/init.lua,上面那个 gld 是原作者的用户名,换成自己的。文件不存在的话点 Open Config 会自动创建。

-- 使用【command+esc】在不同屏幕之间移动鼠标
hs.hotkey.bind({'command'}, 'escape', function()
    local screen = hs.mouse.getCurrentScreen()
    local nextScreen = screen:next()
    local rect = nextScreen:fullFrame()
    local center = hs.geometry.rectMidPoint(rect)
    hs.mouse.absolutePosition(center)
end)

-- 使用【Option+`】在不同屏幕之间移动窗口
hs.hotkey.bind({'option'}, '`', function()
    -- get the focused window
    local win = hs.window.focusedWindow()
    -- get the screen where the focused window is displayed, a.k.a. current screen
    local screen = win:screen()
    -- compute the unitRect of the focused window relative to the current screen
    -- and move the window to the next screen setting the same unitRect
    win:move(win:frame():toUnitRect(screen:frame()), screen:next(), true, 0)
end)

4、在任务栏点击图标,选择 Reload Config,重载配置,使配置生效

代码在做什么

鼠标切换这段的逻辑很直接:hs.mouse.getCurrentScreen() 判断鼠标现在在哪块屏,screen:next() 取下一块(多屏时循环,两屏就是来回切),fullFrame() 拿到那块屏的矩形范围,hs.geometry.rectMidPoint 算中心点,hs.mouse.absolutePosition 把鼠标直接放过去。没有移动过程,是瞬移。

用 fullFrame() 而不是 frame() 是有讲究的:frame() 排除了菜单栏和 Dock 占的区域,fullFrame() 是屏幕的完整物理范围。算中心点用完整范围更符合直觉,落点就在屏幕正中间。

窗口切换这段的关键是 toUnitRect。它把窗口的绝对坐标换算成相对于所在屏幕的比例值——比如窗口占据屏幕左半边,就表示成 (0, 0, 0.5, 1)。然后用这组比例在新屏幕上重新定位,所以两块屏分辨率不一样也没问题,窗口在原屏占多大比例,到新屏还是占多大比例。如果直接搬绝对坐标,从 4K 屏挪到 1080p 屏窗口就会超出边界。

win:move(unitRect, screen, ensureInScreenBounds, duration) 的后两个参数:true 表示确保窗口落在屏幕可见范围内,0 是动画时长,设 0 是瞬间完成——加动画看着好看但有延迟,高频操作时反而累。

实用调整

键位可以按自己习惯改。command + escape 我用着还行,但左手要伸一下,改成 option + tab 之类更顺手的也可以。选键位的原则是避开系统占用的组合,option 加符号键(`、,、.)比较安全。

如果想让鼠标切过去之后落在屏幕的固定位置而不是中央(比如常用的窗口位置),把 rectMidPoint(rect) 换成手动算的坐标即可,hs.geometry.point(x, y) 接受绝对坐标。

多于两块屏的话 screen:next() 会按系统的屏幕顺序循环,想直接跳到指定屏幕用 hs.screen.find() 按名称查找。

改完配置一定要 Reload Config,Lua 文件保存了但不重载是不生效的。想省这一步可以在配置里加个文件监听,改动自动重载,Hammerspoon 官方文档里有现成的写法。

调试时打开菜单栏图标里的 Console,脚本报错会打印在那里。写 Lua 容易出低级语法错误(漏 end、变量名打错),Console 是唯一的排查入口。

💬留言板0

还没有留言,来发表第一条吧~

PAGE LOAD / LIVEMac 双显示器鼠标切换 Hammerspoon 配置加载中