Macでトラックボールをカスタマイズし、生産性を上げる

会社でMacを支給されてしまいましたUbunterです。こんばんは。

会社のコード(一応機密情報)を扱う上で、会社支給のパソコンを使わざるを得ないのは仕方がないですよね。

現在31.5インチディスプレイをミラーリングして使っています。
大画面2つ並べると生産性はそこそこ高くなり満足しています。

そこで問題になるのが、マウス問題。画面が広くなればなるほど、デスクスペースも必要になります。
Macであればトラックパッド(Magic Track Pad)も、外面が広くなればなるほど、操作における腕や指の負荷が大きくなります。
エンジニア的にはトラックボールを使いたくなってしまいますよね。

私は、ド定番のLogicoolのERGO M575を使っています。
トラックボールで1番人気のやつですね。

作業効率を上げるために行った設定をご紹介します。

## 中央ボタン押しっぱなしでスクロール

Hammerspoonは、macOS用の強力な自動化・カスタマイズツールです。macOS上のシステム動作を細かく制御・自動化するために利用されます。スクリプト言語Luaで、「こういう操作があれば便利なのに」といった要望を事細かに設定できます。

私は、真ん中ボタン押しっぱなしでトラックボールをグリグリすることで、左右にスクロール出来るように設定しました。
トラックボールで画面が上下左右に思うがままスクロール出来るのはやみつきになります。
軽いスクロールはホイール、ガッツリスクロールするときはボールと使い分けると便利です。

以下に私が実際に使っているコードを置いておきます。
そのままコピペしてもよいですし、

```lua
-- HANDLE SCROLLING WITH MOUSE BUTTON PRESSED
local scrollMouseButton = 2
local deferred = false

overrideOtherMouseDown = hs.eventtap.new({ hs.eventtap.event.types.otherMouseDown }, function(e)
    -- print("down")
    local pressedMouseButton = e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber'])
    if scrollMouseButton == pressedMouseButton 
        then 
            deferred = true
            return true
        end
end)

overrideOtherMouseUp = hs.eventtap.new({ hs.eventtap.event.types.otherMouseUp }, function(e)
     -- print("up")
    local pressedMouseButton = e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber'])
    if scrollMouseButton == pressedMouseButton 
        then 
            if (deferred) then
                overrideOtherMouseDown:stop()
                overrideOtherMouseUp:stop()
                hs.eventtap.otherClick(e:location(), 0, pressedMouseButton)
                overrideOtherMouseDown:start()
                overrideOtherMouseUp:start()
                return true
            end
            return false
        end
        return false
end)

local oldmousepos = {}
local scrollmult = -4	-- negative multiplier makes mouse work like traditional scrollwheel

dragOtherToScroll = hs.eventtap.new({ hs.eventtap.event.types.otherMouseDragged }, function(e)
    local pressedMouseButton = e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber'])
    -- print ("pressed mouse " .. pressedMouseButton)
    if scrollMouseButton == pressedMouseButton 
        then 
            -- print("scroll");
            deferred = false
            oldmousepos = hs.mouse.getAbsolutePosition()    
            local dx = e:getProperty(hs.eventtap.event.properties['mouseEventDeltaX'])
            local dy = e:getProperty(hs.eventtap.event.properties['mouseEventDeltaY'])
            local scroll = hs.eventtap.event.newScrollEvent({dx * scrollmult, dy * scrollmult},{},'pixel')
            -- put the mouse back
            hs.mouse.setAbsolutePosition(oldmousepos)
            return true, {scroll}
        else 
            return false, {}
        end 
end)

overrideOtherMouseDown:start()
overrideOtherMouseUp:start()
dragOtherToScroll:start()
```

### 進むボタン押しっぱなしジェスチャーで画面切り替え系

LogiOption+を使って、ジェスチャーを設定します

私はこんな設定にしています。
進むボタンでコピー、戻るボタンでペーストの機能をつけても便利かもしれませんね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293892/6593aabf-03ea-f017-1aa0-809d2c806b0c.png)

### 戻るボタン押しっぱなしジャスチャーでよく使うアプリケーションの切り替え

開発をしていてよく使う4つのアプリケーションをそれぞれに割り当てました。
- Raycast(ランチャー)
- Warp(シェルターミナル)
- Visual Studio Code(開発環境)
- Google Chrome(ブラウザ)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293892/5d67e4bc-e654-90fc-e315-fd8291770242.png)

特にWEB開発をしていると、Chromeのウィンドウが大量に増殖して何処に何があるかわからなくなります。
そういうときに、進むボタンで設定したジェスチャーのエクスポーゼとミッションコントロールがいい感じに機能してくれます。
戻るボタン左でChromeにして、進むボタン下のミッションコントロールを押すと、ウィンドウ迷子がかなり減りました。