Mac 多屏幕窗口管理神器

使用多個顯示器可以避免在任務窗口或應用之間來回切換,從而提高效率。然而隨著工作空間的擴大,同時也帶來了其它問題,包括:

  1. 使用鼠標的效率進一步降低;
  2. 活動窗口過多容易失去焦點;
  3. 更多時候是以上兩點同時發生:找半天不知道鼠標指針在哪,多屏幕之間拖動、管理窗口變得更加困難。

不管你是不是 VIM 黨,不停地在鼠標與鍵盤之間切換絕對是一件分心且低效的事,很多“懶人”寧可花時間記住數量龐大的組合快捷鍵(當然如果記不住也沒關系,有一款作弊神器可以幫助你快速查看當前應用的快捷鍵:Cheatsheet),也不愿讓自己的右手離開鍵盤。

雖然為了避免使用鼠標你甚至可以給 Chrome 裝上 VIM 映射的插件,但總有些時候不得不依賴鼠標完成一些精確的點擊、拖動等操作,然而根據心理物理學中著名的費茨定律(Fitt's law),鼠標移動時間與目標距離成正比,與目標大小成反比:

也就是說隨著工作空間的擴大,使用鼠標的效率將會越來越低。除了鼠標的問題之外,當同時有多個應用窗口在你面前打開的時候,即使想要通過組合快捷鍵操作,也容易搞混當前捕獲焦點的應用是哪個。當然就算有多個窗口重疊出現,你可以通過查看左上角工具欄所顯示的應用名稱來確定當前焦點,不過費茨定律對于視覺搜索也是同樣適用的,對于連眼睛都懶得抬起來的人來說寧可通過 Command+Tab 嘗試切換來找到當前焦點的應用。

不過這個問題可以通過另外一款作弊神器來解決:HazeOver

它可以讓當前出于焦點的窗口正常顯示,而其它所有窗口都蒙上一層半透明的黑紗:

macOS 提供了一個有趣的小功能,只要快速晃動鼠標就可以讓指針放大,從而讓你快速定位自己的鼠標。然而這點微小的工作遠遠無法彌補它在窗口管理上的不足。與 Windows 上貼邊停靠、甩一甩甩掉其它窗口的功能相比,macOS 窗口左上角紅黃綠的三個小圓點幾乎毫無存在感,拋開面積太小不易點擊不說,綠色的放大按鈕只能進入或退出全屏模式,雖然后來加入了長按進入雙全屏模式,也基本上是個雞肋:在小屏幕筆記本上沒什么用,有擴展屏的時候更沒必要用。于是乎在蘋果強大的生態號召力之下出現了許多第三方解決方案,但是我的需求很簡單,我覺得將一塊屏幕劃分成皿、田之類的格局沒有任何必要,我只需要最簡單的功能:

  1. 可以最大化但不是全屏;
  2. 可以占據左半邊或右半邊;
  3. 可以在不同顯示器之間快速移動。

前兩條根本就是 Windows 的基本功能,我嘗試了一些窗口管理應用之后,最終選擇可以通過代碼精確配置的 Hammerspoon,與一般的工具不同,首先它是開源的,其次使用 Lua 腳本作為配置文件。

我的配置文件在 這里 Gist-hammerspoon.init.lua,保存到本地~/.hammerspoon/init.lua,然后 Reload Config 即可。Hammerspoon 還提供一個 Console 界面,可以方便調試:

配置文件說明

-- 一般組合鍵為 Shift + Command + ?
local hyper = {'shift', 'cmd'}

-- 最大化窗口
-- 快捷鍵為 Shift + Command + ↑
hs.hotkey.bind(hyper, 'up', function()
    hs.grid.maximizeWindow()
end)

-- 讓窗口占據左半邊(Windows 下面的向左貼邊停靠)
-- 快捷鍵為 Shift + Command + ←
hs.hotkey.bind(hyper, "Left", function()
  local win = hs.window.focusedWindow()
    local f = win:frame()
    local screen = win:screen()
    local max = screen:frame()

    f.x = max.x
    f.y = max.y
    f.w = max.w / 2
    f.h = max.h
    win:setFrame(f)
end)

-- 向右停靠類似

-- 將當前窗口移動到第 n 個屏幕
-- 并最大化窗口
-- 快捷鍵為 Ctrl + Command + 屏幕數字
local hyper2 = {'ctrl', 'cmd'}
moveto = function(win, n)
  local screens = hs.screen.allScreens()
  if n > #screens then
    hs.alert.show("No enough screens " .. #screens)
  else
    local toWin = hs.screen.allScreens()[n]:name()
    hs.alert.show("Move " .. win:application():name() .. " to " .. toWin)
    hs.layout.apply({{nil, win:title(), toWin, hs.layout.maximized, nil, nil}})
  end
end

hs.hotkey.bind(hyper2, "1", function()
  local win = hs.window.focusedWindow()
  moveto(win, 1)
end)
hs.hotkey.bind(hyper2, "2", function()
  local win = hs.window.focusedWindow()
  moveto(win, 2)
end)
hs.hotkey.bind(hyper2, "3", function()
  local win = hs.window.focusedWindow()
  moveto(win, 3)
end)

錄屏演示效果

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容