ハチャコン: キーボードの時代は終わったんだよ これからは DualSense の時代さ
DualSense ワイヤレスコントローラーで Mac を操作する常駐ツール「ハチャコン」を作った。スティックでカーソル、ボタンでショートカット、タッチパッドでリングメニュー。
PS5 の DualSense ワイヤレスコントローラー (以下 DualSense) で Mac を操作するツール「ハチャコン」を作った。
ハチャコンとは
DualSense をつないでおくと、いろいろ操作ができるアプリ。ハチャメチャなコントローラ、略してハチャコン。
- 左スティックでカーソル移動、右スティックでスクロール
- ボタンにキーボードショートカットやクリックを割り当てられる
- DualSense のマイクで音声入力できる。ボタンを押している間だけ Mac のマイクが DualSense に切り替わる
- タッチパッドを押し込むと、ゲームのリングメニューみたいなものが出て、スティックで選べる
開発の動機
songmu さんの フットペダルデバイスと最近の音声入力環境 を読んで、音声入力ソフトの Handy とフットペダルを導入した。ペダルを踏んでいる間だけしゃべって入力する。
文字を声で打てるようになると、あとはカーソル操作さえできればキーボードを触る機会は減る。椅子にゆったり座って、ハンズフリーで作業できたらいいなと思った。
ところが、自分は トラックボール一体型のキーボード を使っているので、カーソルを動かすにもキーボードに手を置くことになる。結局ほぼキーボードを触っているようなものだった。
手元でカーソルを動かせて、音声入力のモードにも入れて、その他の操作もできるデバイスがあると便利だなと思って探していたところ、DualSense がいいのではと気づいた。
アプリとセット
DualSense をつないでも、Mac はゲームコントローラーとして認識するだけで、スティックでカーソルが動いたりはしない。なので、コントローラーの入力を読み取って、キーボードやマウスの操作に置き換えてくれるアプリが必要になる。
DualSenseでmacOSを操作するアプリはいくつかあるが、自分好みのものがないので作ることにした。丁寧に作ってはいるが、ほぼバイコー(バイブコーディングの略)なのと、自分への最適化を優先したいのでアプリストアに出したりOSSにはしていない。Coding Agent があれば誰でもサッと作れるだろうし。コントローラーを可愛くしたり、見た目を面白くしたりといった作り込みで価値が出てきたら、出してもいいかなと思っている。
もう数ヶ月はハチャコンで仕事もしていて、音声入力のトリガーもコントローラーでやるようになったので、フットペダルの出番がなくなってしまった。相変わらずよく検討せずに散財をしてしまう。
音声入力は Handy
Handy はローカルで動く OSS の音声入力アプリで、認識に使うモデルを選べる。モデルの選定はある程度の精度を重視したいところだが、Coding Agent への指示なら、多少おかしくても意図を汲んでくれるので問題にならない。というか、普段キーボードで打っているときも誤字だらけで投げている。
モデルは Whisper large-v3
モデルは Whisper large-v3 を使っている。日本語の認識精度も良いし、言語の自動判定もできるところが魅力。
たとえばChromeの履歴からGoogle Calendarを検索するときは、日本語で「カレンダー」としゃべってカタカナが入っても検索できない。こういうときは英語で発音すれば、そのまま英語で入力される。日本語と英語を切り替えずにしゃべり分けられるのが便利。英語の勉強のモチベーションはだいぶ落ちているけど、少しだけ発音の練習をしていたのがここで役に立った。
Qwen ASR など中国系のモデルも試したけど、偏りがあって、日本語でしゃべっても中国語に変換されることが多かった。自動判定で複数の言語を使い分けるつもりがないなら、言語を日本語に固定すればいいので、Whisper にこだわらなくてもいいと思う。
DualSense を選んだ理由
理由は 2 つある。ひとつは、DualSense がいろんな機能を持っていること。もうひとつは、家に持て余している PlayStation 5 があること。
DualSense の機能はこんな感じ。
- ハプティックフィードバック。細かいパターンで振動させられる。フィードバックの欲しい処理では使っている。
- タッチパッド。押し込みは左半分と右半分で別のボタンとして使えて、指で払えば上下左右のスワイプにもなる。トラックパッドの「戻る・進む」を割り当てたりしている。
- ライトバー。レイヤーやメニューに合わせて色が変わるので、今どのモードなのかが手元で分かる。まあ手元見ないけど。
- マイク。DualSense に向かってしゃべれば音声入力できる。
- スピーカー。まだ使っていないが、操作音や通知を手元で鳴らせそう。
- ジャイロ 。まだ実装していないが、何かに使えないか考えている。
- アダプティブトリガー。何かに使えるといい。
機能
スティックとボタン
- 左右のスティックにはいろいろ割り当てあられるが、基本的にカーソル操作とスクロールを当てることになると思う。倒し量に対して指数カーブをかけていて、浅く倒すとゆっくり、倒し切ると速く動く
- ボタンにはキー (
cmd+shift+4のような組み合わせも)、クリック、アプリ起動のコマンドを割り当てられる - 押している間だけカーソルとスクロールを遅くする精密モードがある。小さいボタンを狙うとき用
- タッチパッドは押し込んだ位置 (左半分 / 右半分) で別のボタンになり、上下左右のスワイプにも割り当てられる。
レイヤー
自作キーボードでおなじみのレイヤー。レイヤーを切り替えると、ボタンやスティックの意味がまるごと切り替わる。
- 切り替え方は「押している間だけ」「トグル」「固定」の 3 種類
- レイヤーごとにライトバーの色を変えたり、振動させたりできる
自分は、押している間だけ矢印キーやタブ移動になる nav レイヤーと、R3 でトグルする記号レイヤーを用意している。記号レイヤーでは - / [ ] や括弧などをボタンに並べている。
DualSense のマイクで音声入力
DualSense にはマイクがついている。ハチャコンはこれを Mac の音声入力に使えるようにした。
椅子にもたれてコントローラーを握っていると、普段使いのマイクから遠くて声が届きにくい「かもしれない」と思って実装したが、特に使っていない。スピーカーの機能があるので、Coding Agent からの通知を読み上げさせて、それに対して音声で指示するということもできれば、PC の前にいなくてもよい「かもしれない」。まあ使わないだろうね。
リングメニュー
ここはいちばん気合いが入っている。ゲームでよくあるリングメニューを表示させて、ショートカット機能などを割り当てる。メニューを割り当てたボタンを押している間だけ画面中央にリングが出て、スティックで方向を選んで、離した瞬間に確定する。トグルモードもあるがあんまり使わない。

- 項目は 1〜10 個。キー入力、アプリ起動 (
open -a) など、普通のボタンと同じアクションを置ける - 項目に別のメニューを置くとサブリングに入れる。スティックを向けたまま 0.35 秒待つと、ボタンを押したままサブリングに入って、そのまま選んで離せば確定
見た目はシンプルなアニメーションだが、ハチャコンイメージキャラクターの「はちゃ子」を立てて、キャラクターがアニメーションする感じの野望を持っている。まあやらないだろうね。
yasai と連携してワークスペースを覗く
ウィンドウマネージャは自作の yasai を使っている。yashiki の置き換えとして作ったタイリングウィンドウマネージャで、ウィンドウをタグ (ワークスペースのようなもの) で切り替える。
リングメニューの項目には画像を添えられるようにしていて、選んでいる項目の方向、リングの外側にその画像が出る。yasai がタグごとのスクショを書き出しているので、それを指定すると、タグを切り替える前に行き先の画面が見える。どのタグに何を置いたか覚えていなくても、スティックを倒していけば見つかる。項目に付いた画像を見せるだけの機能なので、どんな画像でも出せるが、yasai 以外の用途はあまり思いついていない。

アプリごとのメニュー
appMenu を割り当てたボタンを押すと、カーソルの下にあるアプリに合わせたリングメニューが開く。メニューの中身は設定で変えられる。Chrome の上であれば新規タブを選べたり、Slack であれば検索したり、特定チャンネルを開いたり。

カーソルの下のアプリに合わせて挙動を変える仕組みは、もう少し詰めていくと便利になりそう。たとえば、音声入力は基本的に Handy を使うけど、Claude アプリの上では Claude の音声入力を使う、みたいなことができてもいいかもしれない。
自分の設定
設定は ~/.config/hachacon/config.json の JSON ファイル。中身はおおまかに、スティックの速度などの全体設定、レイヤーごとのボタン割り当て (layers)、リングメニューの定義 (menus)、アプリ名とメニューの対応 (appMenus) の 4 つを変更できる。
要点だけ抜き出すとこんな感じ。
{
"mouse": { "speed": 4200, "curve": 2.0, "deadzone": 0.12 },
"layers": {
"base": {
"light": "#2050ff",
"leftStick": "mouse",
"rightStick": "scroll",
"buttons": {
"cross": { "type": "mouse", "button": "left" },
"circle": { "type": "mouse", "button": "right" },
"l1": { "type": "layer", "name": "nav", "mode": "hold" }, // 押している間 nav レイヤー
"r1": { "type": "precision", "factor": 0.15 }, // 押している間カーソルを遅く
"l2": { "type": "menu", "name": "main" }, // リングメニュー
"r2": { "type": "voice", "key": "cmd+ctrl+opt+shift+v", "mode": "hold", "mic": false }, // 押している間 Handy のショートカットを押しっぱなし
"touchpadLeft": { "type": "appMenu" } // カーソルの下のアプリのメニュー
// ...
}
},
"nav": {
"fallback": "base", // 書いていないボタンは base のまま
"light": "#00c060",
"leftStick": "arrows",
"buttons": {
"triangle": { "type": "key", "key": "shift+enter" }
// ...
}
}
},
"menus": {
"main": {
"color": "#ff3060",
"items": [
{ "label": "Raycast", "icon": "magnifyingglass", "action": { "type": "shell", "command": "open -a Raycast" } },
{ "label": "Screenshot", "icon": "camera.viewfinder", "action": { "type": "key", "key": "cmd+shift+4" } }
// ...
]
},
"chrome": {
"color": "#f0c040",
"items": [
{ "label": "アドレスバー", "icon": "link", "action": { "type": "key", "key": "cmd+l" } },
{ "label": "タブを復元", "icon": "arrow.uturn.backward", "action": { "type": "key", "key": "cmd+shift+t" } }
// ...
]
}
},
"appMenus": { "Google Chrome": "chrome", "Slack": "slack" }
}
まとめ
ハチャコンを作ってから数ヶ月、この体制で作業している。
今後は DualSense のほかの機能を使った機能も実装してみたいと考えているが、便利になるかは不明。それよりも、会社の人に教えてもらったのだけど、DualSense には Edge というものもあって、そっちは背面ボタンなどボタンがたくさんあるので、さらに便利になりそう。値段を調べたら 3 万円くらいして、めっちゃ高いんだけどね。
あと、いい感じの充電スタンドが欲しいかもしれない。置いたり取ったりが簡単にできて、充電もできるやつ。やむを得ずキーボードを使うときなどにコントローラーを置くと、トリガーが反応してしまったりする。
今はハチャコンがないと困るくらいには、自分でよく使っている。これからは DualSense の時代さ。