使用多個顯示器可以避免在任務視窗或應用之間來回切換,從而提高效率。然而隨著工作空間的擴大,同時也帶來了其它問題,包括:
- 使用滑鼠的效率進一步降低;
- 活動視窗過多容易失去焦點;
- 更多時候是以上兩點同時發生:找半天不知道滑鼠指標在哪,多螢幕之間拖動、管理視窗變得更加困難。
不管你是不是 VIM 黨,不停地在滑鼠與鍵盤之間切換絕對是一件分心且低效的事,很多“懶人”寧可花時間記住數量龐大的組合快捷鍵(當然如果記不住也沒關係,有一款作弊神器可以幫助你快速檢視當前應用的快捷鍵:Cheatsheet),也不願讓自己的右手離開鍵盤。
雖然為了避免使用滑鼠你甚至可以給 Chrome 裝上 VIM 對映的外掛,但總有些時候不得不依賴滑鼠完成一些精確的點選、拖動等操作,然而根據心理物理學中著名的費茨定律(Fitt's law),滑鼠移動時間與目標距離成正比,與目標大小成反比:
也就是說隨著工作空間的擴大,使用滑鼠的效率將會越來越低。除了滑鼠的問題之外,當同時有多個應用視窗在你面前開啟的時候,即使想要通過組合快捷鍵操作,也容易搞混當前捕獲焦點的應用是哪個。當然就算有多個視窗重疊出現,你可以通過檢視左上角工具欄所顯示的應用名稱來確定當前焦點,不過費茨定律對於視覺搜尋也是同樣適用的,對於連眼睛都懶得抬起來的人來說寧可通過 Command+Tab 嘗試切換來找到當前焦點的應用。
不過這個問題可以通過另外一款作弊神器來解決:HazeOver
它可以讓當前出於焦點的視窗正常顯示,而其它所有視窗都蒙上一層半透明的黑紗:
macOS 提供了一個有趣的小功能,只要快速晃動滑鼠就可以讓指標放大,從而讓你快速定位自己的滑鼠。然而這點微小的工作遠遠無法彌補它在視窗管理上的不足。與 Windows 上貼邊停靠、甩一甩甩掉其它視窗的功能相比,macOS 視窗左上角紅黃綠的三個小圓點幾乎毫無存在感,拋開面積太小不易點選不說,綠色的放大按鈕只能進入或退出全屏模式,雖然後來加入了長按進入雙全屏模式,也基本上是個雞肋:在小螢幕筆記本上沒什麼用,有擴充套件屏的時候更沒必要用。於是乎在蘋果強大的生態號召力之下出現了許多第三方解決方案,但是我的需求很簡單,我覺得將一塊螢幕劃分成皿、田之類的格局沒有任何必要,我只需要最簡單的功能:
- 可以最大化但不是全屏;
- 可以佔據左半邊或右半邊;
- 可以在不同顯示器之間快速移動。
前兩條根本就是 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)複製程式碼