昨晚,想在当前桌面找个应用,但鼠标又正在充电中(Magjc Trackpad 2 也因为长期未用无电),没办法只能借助老派的 Cmd + Tab 操作。之前一直都是使用 Mission Control 加鼠标操作,这次遇到麻烦,又让我兴起了仅用键盘操作电脑的念头。没想到随便一谷歌,居然又把我带到了 Hammerspoon ,不得不感叹 Hammerspoon 的强大。

在 Hammerspoon 中有个模块 hs.expose 可以显示窗口的缩略图,并且可以通过快健键直接打开对应的窗口。为了实现类似 Mission Control 的效果,我们需要三个 API:

  • hs.expose.ui:定义外观和操作;
  • hs.expose.new:创建界面;
  • hs.expose:toggleShow:显示界面;

其中最后两个是必须的,UI 可以使用默认设置。另外这个模块支持多桌面、后台应用、当前桌面和当前活动窗口(应用之间)四种方式,这里主要以显示当前桌面活动窗口来说明。

首先创建一个能显示当前桌面所有活动窗口的实例:

-- hyper 指 Com + Con + Opt 三个修饰键
hs.hotkey.bind(hyper, 'T', function()
    hs.expose.new(nil):toggleShow()
end)

接下来实现当按下快健键时,能像 Mission Control 一样显示当前桌面的所有活动窗口:

mic_ui = {
    includeNonVisible = false, -- 不显示后台应用窗口
    includeOtherSpaces = false, -- 不显示其它桌面窗口
}

hs.hotkey.bind(hyper, 'T', function()
    hs.expose.new(nil, mic_ui):toggleShow()
end)

最后优化界面显示部分:

mic_ui = {
    includeNonVisible = false, -- 不显示后台应用窗口
    includeOtherSpaces = false, -- 不显示其它桌面窗口

    -- 颜色格式为 RGB,最后一位是透明度A
    highlightThumbnailStrokeWidth = 0, -- 取消橙色的边宽
    backgroundColor = {0, 0, 0, 0.1}, -- ui 的背景颜色,这里改为透明
    showTitles = false, -- 隐藏标题
}

至此,代码部分已经基本完成,唯一的问题是当执行时,桌面上原来的窗口并不会像 Mission Control 一样重新排列,这里我们要借助系统自带的显示桌面 功能,默认快捷键是 F11FN + F11。下面附上完整代码:

mic_ui = {
    includeNonVisible = false, -- 不显示后台应用窗口
    includeOtherSpaces = false, -- 不显示其它桌面窗口

    -- 颜色格式为 RGB,最后一位是透明度A
    highlightThumbnailStrokeWidth = 0, -- 取消橙色的边宽
    backgroundColor = {0, 0, 0, 0.1}, -- ui 的背景颜色,这里改为透明
    showTitles = false, -- 隐藏标题
}

-- 拆分代码,提升响应速度
mic_expose = hs.expose.new(nil, mic_ui)

-- 当按下快捷键时,首先执会执行 F11,显示桌面
hs.hotkey.bind(hyper, 'T', function()
    hs.eventtap.keyStroke("fn", "F11")
    mic_expose:toggleShow()
end)

最后

当写这篇文章的时候,发现可能有一个更好的方法可以实现,不过得等过段时间才有机会折腾。之所以需要一个更好的方法,因为这个模块的内存占用太大了,运行一段时间后,基本会保持在 500MB 左右,而且有时会导致其它模块运行出现问题。另外就是增加显示桌面那行代码时,会导致在选择 Finder 窗口时,需要执行两次同样的操作,这个可以那行代码去掉,然后去掉背景透明即可。

最后的最后,如果想仅显示同一个程序的窗口,可以在 mic_ui 加上一句 onlyActiveApplication = true

信息

版本

  • Hammerspoon:0.9.73
  • macOS Mojave:10.14.3

参考