Mac環境で安トラックボールを快適に使う
IYHじゃなくて雑記です
ELECOM HUGE
手首がダメになりかけてきたのと、MIDI鍵の上に乗っけて使うポインティングデバイスが欲しかったのでトラックボールを買うことにしました。買ったのはこれ
選定基準は以下
・安い
・ボールが大きい
・それなりにボタン数がある
本当はみんな大好きケンジントンのExpertMouseが欲しかったのですが、トラックボール初めてなので投げ捨てるリスクも鑑みて、安めでボールの大きいトラックボール、かつMagic Mouseぐらいの気持ちで使えるようにショートカットを割り当てられるボタン数が多い物をということでエレコムのHUGEにしました。エレコム製というところで抵抗感は大きかったものの、他にあまり選択肢がなかったのでこれに
使い心地とか
まずすでに色々なところで言われているかなと思いますが、トラックボールの回りはあまりスムーズではありません。しばらく使ってるとよくなるとの声もありますが、メンテのたびにリセットです。耐久性に関してはまだ使って浅いのでなんとも言えませんが、元気に使いすぎるとすぐにダメになりそうな気配はあります。Magic Mouseに調教されている体なのでスクロールホイールも嫌い。あとこのトラックボールで一番致命的なのは、エルゴノミクスっぽい形状してるのに、全然手首を労ってくれないところです。そのまま使うと腱鞘炎が悪化するのでやめた方がいいです。3Dプリンターで傾ける土台を作っている人もいますが、3Dプリンターがないと結構用意するコストがバカにならないので、僕はキーボード用の足をつけました。
中華感あふれるこれ。まだこれも試行錯誤中ですが、角度はかなり付けれるようになったので概ね良い感じです。
エレコムマウスアシスタント
悪名高き公式ユーティリティー。実際その使い勝手はあまりよくなく、再起動のたびに適用し直さないと効かなくなるという厳しさをもつ。また公式ユーティリティーの割にOSの上のレイヤーで動作しており、KVMソフトなどとの併用でうまく動作しなかったりなどがある。海外勢はまずこれを使うのを嫌がり、他の有料ユーティリティーを使ったりなどを試している模様。リマップソフトとしてはKarabiner-Elementsなどが有名ですが、こちらではそのままだとHUGEのいくつかのキーが認識されず、完璧には使えない状態でした。今現在はとりあえず公式ユーティリティーを利用しているものの使い勝手はよくないので別のソフトで代用できないか試行錯誤中です。Karabiner-DriverKit-VirtualHIDDeviceを利用してHUGEのリマップを行なっているgitリポジトリを発見したので、これをちょっと拝借していじっている最中ではあります。上のレイヤーでの動作でも良いというのであれば、後述するHammerspoonでのカスタマイズが割と手っ取り早いかなとは思います。
せっかくのトラックボール、ボールでスクロールしよう
使い心地でスクロールホイールが嫌いと書きましたが、せっかくトラックボールを使ってるのでどうせならこのボールをゴロゴロしてスクロールしたいと思うのです。HUGEのスクロールホイールは親指への負担もかなり大きいのでこれもなんとかしたい。ということでトラックボールを転がしてスクロールできないものか色々調べてみました。Macだと有料ソフトでSmart Scrollというものがあったり、また先ほど紹介したKarabiner-Elementsを使う方法などがありますが、前述したようにKarabiner-Elementsは一部ボタンが効かないので一旦Smart Scrollを試用で使ってはみたものの悪くはないが有料がやはりネック。ということで調べてる途中で出会ったHammerspoonというソフトを利用することに。
Hammerspoonはキーボードやマウスなどの挙動をカスタマイズしたり、ウィンドウの配置を制御したりなどさまざまな動作をオートメーション化できるソフトです。記述に用いる言語はLuaです。なのでちょっとした条件文を書いて制御したりみたいなことができ、動作するアプリケーションウィンドウを縛ったりもできます。Hammerspoonも性質上結構上の方のレイヤーで動作してしまうのでKVMアプリなどに飛ばしたりといった使い方はできませんが、そういった使い方でなければいい感じに使えます。ということで一旦こちらを使ってトラックボールスクロールを実現することに。
トラックボールでのスクロールさせる例がgithubのissueにあったのでこれをちょっといじってみました。
local scrollVerticalButton = 4
local scrollHorizontalButton = 3
local toggleVerticalScrollButton = 4
local toggleHorizontalScrollButton = 3
local deferred = false
local verticalScrollToggle = false
local horizontalScrollToggle = false
OverrideOtherMouseDown = hs.eventtap.new({
hs.eventtap.event.types.otherMouseDown
}, function(e)
local pressedMouseButton = e:getProperty(
hs.eventtap.event.properties['mouseEventButtonNumber'])
if scrollVerticalButton == pressedMouseButton or scrollHorizontalButton ==
pressedMouseButton then
deferred = true
return true
end
end)
ToggleMouseDown = hs.eventtap.new({hs.eventtap.event.types.otherMouseDown},
function(e)
local pressedMouseButton = e:getProperty(
hs.eventtap.event.properties['mouseEventButtonNumber'])
if toggleVerticalScrollButton == pressedMouseButton then
if (verticalScrollToggle) then
verticalScrollToggle = false
return true
else
verticalScrollToggle = true
horizontalScrollToggle = false
return true
end
end
if toggleHorizontalScrollButton == pressedMouseButton then
if (horizontalScrollToggle) then
horizontalScrollToggle = false
return true
else
horizontalScrollToggle = true
verticalScrollToggle = false
return true
end
end
end)
OverrideOtherMouseUp = hs.eventtap.new({hs.eventtap.event.types.otherMouseUp},
function(e)
local pressedMouseButton = e:getProperty(
hs.eventtap.event.properties['mouseEventButtonNumber'])
if scrollVerticalButton == pressedMouseButton or scrollHorizontalButton ==
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 scrollmult = -1 -- negative multiplier makes mouse work like traditional scrollwheel
local scrollmultHorizontal = -1
local moveX = 0
local moveY = 0
local function scrollFunction(x, y)
local oldmousepos = hs.mouse.absolutePosition()
local scroll = hs.eventtap.event.newScrollEvent({x, y}, {}, 'pixel')
hs.mouse.absolutePosition(oldmousepos)
return scroll
end
ToggleMouseButtonThenScroll = hs.eventtap.new({
hs.eventtap.event.types.mouseMoved
}, function(e)
if verticalScrollToggle then
local dy = e:getProperty(
hs.eventtap.event.properties['mouseEventDeltaY'])
moveY = -dy * scrollmult
return true, {scrollFunction(0, moveY)}
else
if horizontalScrollToggle then
local dx = e:getProperty(
hs.eventtap.event.properties['mouseEventDeltaX'])
moveX = -dx * scrollmultHorizontal
return true, {scrollFunction(moveX, 0)}
else
return false, {}
end
end
end)
DragOtherToScroll = hs.eventtap.new({hs.eventtap.event.types.otherMouseDragged},
function(e)
local pressedMouseButton = e:getProperty(
hs.eventtap.event.properties['mouseEventButtonNumber'])
if scrollVerticalButton == pressedMouseButton then
deferred = false
local dy = e:getProperty(
hs.eventtap.event.properties['mouseEventDeltaY'])
moveY = -dy * scrollmult
verticalScrollToggle = false
return true, {scrollFunction(0, moveY)}
else
if scrollHorizontalButton == pressedMouseButton then
deferred = false
local dx = e:getProperty(
hs.eventtap.event.properties['mouseEventDeltaX'])
moveX = -dx * scrollmultHorizontal
horizontalScrollToggle = false
return true, {scrollFunction(moveX, 0)}
else
return false, {}
end
end
end)
OverrideOtherMouseDown:start()
OverrideOtherMouseUp:start()
ToggleMouseDown:start()
ToggleMouseButtonThenScroll:start()
DragOtherToScroll:start()
改修の方針としては
・スクロール用ボタン押しっぱなしでちょっとだけスクロール。長距離スクロールするときはスクロールボタンをトグルで動作させてフリーハンドでスクロール
・垂直スクロールと水平スクロールを分けたい
というところです。スクロールボタンのトグルとホールドに関しては正直好みだと思うのであれですが、垂直スクロールと水平スクロールはきっちり分けてあげないとトラックボールだと制御が辛いかなと思ったのでここは分けました。ブラウジングならまだいいんですが、Cubaseのピアノロールとかでスクロールさせると上下と左右が一緒に動きまくって大変なことになっちゃうので・・・
大体今のでいい感じかなと思いますが、マウス位置の保持処理とかがなんかズレちゃったりするのが若干気になるのと、トラックボールでのスクロールがトグルで入ってるかどうかわかりにくいというのがあるので、スクロールトグル時はマウスのアイコン変えさせたりとか処理を追加した方がいいかもしれません。
あとはこれだけだと慣性スクロールが効かないので、mosとかを併用するとなかなかトラックパッドっぽくなっていい感じです。
まとめ
いろいろいじくり回していい感じにはなったものの、どこまで頑張ってもやはりマウスの速度・精度には及ばないというところもあるので、用途によって使い分けは必要かなと思いました。普段使い・(ギリギリ)DAWあたりはトラックボールでもいいかなと思いましたが、イラレみたいなソフトとか3D系のソフトとかはやはりマウスの方が良さそうに感じます。コーディングでも使えないことはないですが、長文のテキスト選択はめちゃくちゃやりづらいので工夫は必要そうです(コーディングだとそもそもキーボードだけで完結しちゃう人の方が多数派だと思いますが)。
今回組んだHammerspoonはHUGE以外のトラックボールでも使えるので、今後めちゃくちゃトラックボール気に入ったらExpertMouseとかGameBallに行きたいと思います。ポインティングデバイス、一番使うものなのでいいもの買った方がいいですよ