- Windows11で、macOSライクなキーバインドを設定するための方法をご紹介
- Apple Magic Keyboard US配列前提
- emacs風キーバインド、VSCodeのショートカットにも触れています
僕は筋金入りのmacOS愛好家で、自分でOSを選べるのならmacOS一択です。当然キーバインドも手に馴染みきっていて、これがなければ始まらないぐらいになっています。
ですが、そんな僕でも、どうしてもWindowsの利用が避けられないときもあります。ただ、いざ使ってみるとどうしてもやっぱり脳が混線してしまって、どうもぎこちない動作になってしまうんですよね。
というわけで、今回Windowsの操作感を極力macOSに近づけるために本気で取り組んでみたので、その成果をご紹介しようと思います。
目指す姿
今回目指すゴールはこちら。
- キーボード: Apple Magic Keyboard US配列を使う
- すべてのアプリで: macOSにデフォルトで搭載されているemacs系ショートカットを使えるように
- コーディング周りで: 必要な各種操作、ショートカットもmacOSと同じ動きでできるように
僕は、趣味IT、仕事もITな人間なので、特にコーディング周りの体験は最重要になります。
普段macOSでは、VSCodeをエディタとして愛用していて、基本的にトラックパットやマウスをほぼ使わず、キーボード操作だけで動きを完結させています。
このmacOSと同じ動きをWindowsでも再現できるかが、今回の最大の課題でした。
縛り、制約
動きが再現できればなんでもいいかと言われると、そうでもなかったので、以下を制約として設けました。
- Windowsのレジストリエディタを使わない
- Windowsのgpeditを使わない
今回は、家族のWindowsをちょっと借りてるような状態だったので、すぐに現状復帰ができることが絶対でした。なので、レジストリを書き換えるような危険なことはNGとしました。
また、グループコントロールポリシーなるものをいじれるgpeditというツールもWindowsのエディションによっては使えるようでしたが、僕の試したHomeエディションではそもそも使えなかったこともあり、使わないことにしました。
利用するツール
いろいろ試して最終的に使ったのは、AutoHotKey v2です。これだけでやりたかったことは概ね達成できました。
AutoHotKey
かなり自由度高く、ショートカットやキーの割り当てを操作できるツール。
独自言語のスクリプトで設定するため高機能ですが、その分難解でもあります。
少し前にv2版が出たようなのですが、v1とは大きく文法が変わっているため要注意。ネットで見つかる記事がv1なのかv2なのかどちらかを見極めながら進めるのにやや苦戦しました。
ありがたいことにWikiも整備されていて、ドキュメントはかなり豊富。ただ、それでもいざ書いてみるとつまるところが多々あり、難易度は高かった印象です。
仕組みとして、レジストリを書き換えてキーを置き換えるのではなく、常駐タイプのアプリケーションがキーボードからの入力を監視して、指定されたキー入力がきたら都度巻き替え動作を行っているようです。
相当高機能でほぼなんでもできるくらいに高機能なのですが、1点弱点があるようで、Capslockの巻き替えだけは苦手としている様子。
参考: その他検討したツール
こちらはその他検討はしたものの、僕の環境では最終使わなかったツール類。
ただし、後述しますが、お手元の端末がApple Magic KeyboardのCapslockをどのキーと認識するかによっては、こちらも併用することになります。
PowerToys Keyboard Manager
Microsoftが公式でプレビューリリースしているユーティリティセット PowerToys
に同梱されているキーボードの割り当て変更ソフトです。
AutoHotKeyと比較すると、設定できるキーの組み合わせが限定されているなどの制約はありますが、GUI操作で簡単に設定できることが強みです。
こちらもAutoHotKeyと同様に、常駐タイプのアプリケーションがキーボードからの入力を監視して巻き替えを行なっているようにみえます。
はじめは、AutoHotKeyと併用して
- キーの割り当て: PowerToys Keyboard Manager
- 複雑なショートカットの割り当て: AutoHotKey
のように使うことを考えたのですが、2つの常駐タイプのアプリケーションが干渉して動作がかなり不安定になったため、最終AutoHotKeyに寄せました。
(PowerToys → AutoHotKeyのように動く場合もあれば、逆の場合もあり、同じ割り当てでも実行タイミングによって挙動が異なるなど相当不安定でした)
また、Capslockを巻き替えたときの動作は、AutoHotKeyに比べて安定しているようにみえました。
レジストリエディタ
Windowsのレジストリを直接編集するためのツールです。
キー配列の設定値を編集することで、キーの配列を抜本的に変更することができます。
今回は前提条件として、レジストリを触らないことを掲げているので、利用しませんでした。
各種設定
ではでは、いよいよここから具体的な設定値です。
AutoHotKeyのスクリプト全体は、GitHubに置いてあるので、そちらを参照ください。以下ではポイントに絞って解説しています。
初期状態の確認
まずは、諸々のカスタマイズの前に初期設定がどのようになっているかを確認しておきましょう。
自分の観測範囲だけでも、Apple Magic Keyboard US配列を接続した際に、Capslockがなにキーとして認識されるかに差があったため、はじめに状況を確認しておくことをおすすめします。
キーの認識状態は、上で述べたPowerToys Keyboard Managerを使うと、GUI操作でわかりやすく判別できます。
以降の設定値は以下のように認識していることを前提としているため、違った場合は適宜読み替えてください。
Magic Keyboardのキー | Windowsでの認識 |
---|---|
Command | Win |
Ctrl | Ctrl |
Option | Alt |
Shift | Shift |
Capslock | F13 |
(もし設定されていなかったら)CapslockをF13に置き換え
さて、キーの配列やショートカットを仕込んでいくわけなのですが、ここで1つ問題が。
それは自由に使える修飾キーの数問題です。
macOSの場合、修飾キーは Command
Ctrl
Option
Shift
の4つ。
OSレベルのショートカットが割り当てられているキーもいくつかあるにはあるのですが、無効化や上書きが簡単に行えるので、実質4つの修飾キーをかなり自由に使えます。
ではWindowsはというと、 Ctrl
Alt
Shift
Win
で一見4つで同じかのように思うのですが、このうち Winキー
にははじめからOSレベルのショートカットが大量に割り当てられているんですね。
さらにWinキーのショートカットは、優先度がかなり高く設定されているようにみえていて、無効化や上書きは容易ではありません(レジストリの書き換えやグループポリシーの変更で無効化もできるようですが、今回の前提条件を満たさない)。
なので、実質僕らが自由に修飾キーとして用いられるのは3つのみ。1つ足りないんです。
数が足りない状態で、macOSの挙動を再現するのはかなり無理が生じるため、はじめにここをなんとかする必要があります。
そこで、最高に押しやすい位置にいるもののあまり押すことはない Capslockキー
を、通常のキーボードにはあまり存在しない F13キー
に割り当てることで、修飾キー(っぽく使うキー)を1つ増やして対応するアプローチを取ることにします。
ありがたいことに僕のWindowsマシンは、はじめからApple Magic KeyboardのCapslockキーをF13として認識していたため追加設定不要でしたが、もしみなさんの端末が別のキーとして認識していた場合は巻き替えを行ってください。
上述のとおり、AutoHotKeyはCapslockの扱いは苦手としているようなので、巻き替える場合は
- 理想: レジストリエディタ
- 次点: PowerToys Keyboard Manager
を使っていただくとよいかと。
キーの割り当て変更
ここまでの事前準備が整ったら、どんどん設定をいれていきます。
まずは、キーの割り当てです。
Command
がCtrl
になっていた方が、コピペ時などなどmacOSに操作感が近いので、以下のように巻き替えました
Magic Keyboardのキー | 元のWindowsでの認識 | 巻き替え後 |
---|---|---|
Command | Win | **Ctrl** |
Ctrl | Ctrl | **Win** |
Option | Alt | Alt |
Shift | Shift | Shift |
Capslock | F13 | F13 |
; ----------------------------------------------------------- ; Ctrl/Winキーの割り当て ; - CmdキーをCtrlキーに割り当て ; - CtrlキーをWinキーに割り当て ; ----------------------------------------------------------- *LWin::{ SendInput("{Blind}{LCtrl down}") } *LWin up::{ SendInput("{Blind}{LCtrl up}") } *RWin::{ SendInput("{Blind}{RCtrl down}") } *RWin up::{ SendInput("{Blind}{RCtrl up}") } *LCtrl::SendInput("{Blind}{LWin down}") *LCtrl up::SendInput("{Blind}{LWin up}")
シンプルに LWin::LCtrl
、LCtrl::LWin
のように書いて動くことを期待したのですが、置き換え元のWinキーが押されたままになってしまう事象が観測されて、挙動不安定になったため、色々試した結果こうなっています。
(具体的には LWin
+A
で、LCtrl
+A
を入力したつもりがLWin
+LCtrl
+A
になる事象が、トリガー不明で定期的に発生しました)
Commandキー単体押しで、日本語/英語切り替え
日本語でApple Magic Keyboard US配列を使う際のあるあるの設定として、左Commandキー
で英語入力モード、右Commandキー
で日本語入力モードになる、というものがあります。
例に漏れず、僕も同じ設定を愛用しているため、Windowsでも同じ設定が利用できるようにしました。
Commandキー
(=WindowsはWinキー
として認識)への機能追加なので、先ほどのスクリプトに書き加える必要があります。
; ----------------------------------------------------------- ; IME切り替え ; - Cmdキーを単独で押して離した場合、変換/無変換キーとして扱う ; ----------------------------------------------------------- *LWin::{ SendInput("{Blind}{LCtrl down}") } *LWin up::{ SendInput("{Blind}{LCtrl up}") if (A_PriorKey == "LWin"){ ; upイベントの中では、この条件で単体押しを検知できる SendInput("{vk1D}") } } *RWin::{ SendInput("{Blind}{RCtrl down}") } *RWin up::{ SendInput("{Blind}{RCtrl up}") if (A_PriorKey == "RWin"){ ; upイベントの中では、この条件で単体押しを検知できる SendInput("{vk1C}") } }
ポイントは upイベントの中では、この条件で単体押しを検知できる
と書いてあるところで、Windowsキーと他のキーを組み合わせて押した際には、発火しないようにしています。
emacs風キーバインドを再現
macOSに標準搭載されているemac系のキーバインドの再現です。
もともと僕はmacOSでCapslockをCtrlに割り当てて、Capslock+他のキーで発動させているので、Windowsでも同じ状態を再現します。
ここまでの設定で、CapslockはF13になっているので、F13との組み合わせに登録します。
; ----------------------------------------------------------- ; macOS emacs風キーバインド ; Capslock + 各種キーで起動 ; ----------------------------------------------------------- ; NOTE: Apple Magic Keyboard US配列のCapslockを ; F13として認識させていることが前提 ; 矢印キー F13 & f::SendInput "{Right}" F13 & p::SendInput "{Up}" F13 & n::SendInput "{Down}" F13 & b::SendInput "{Left}" ; 行頭/行末移動 F13 & a::SendInput "{HOME}" F13 & e::SendInput "{END}" ; 削除 F13 & d::SendInput "{Del}" F13 & h::SendInput "{BS}" F13 & k::SendInput "+{End}{Del}" ; カーソルの右側を削除 F13 & w::SendInput "^+{Left}{Del}" ; 単語単位で削除
単語単位カーソル移動を再現
macOSでは、Optionキー
+左右
で単語単位でカーソル移動ができます。
同じくWindowsでは、Ctrlキー
+左右
で移動できるのですが、macOSに近づけたいため割り当てを変更します。
; ----------------------------------------------------------- ; macOS 単語移動操作風キーバインド ; Option+左右 の挙動を再現 ; ----------------------------------------------------------- ; 単語単位のカーソル操作 !Left::SendInput "^{Left}" !Right::SendInput "^{Right}" +!Left::SendInput "^+{Left}" +!Right::SendInput "^+{Right}"
拡張クリップボードを再現
僕はmacOSでは、Cmd
+Shift
+V
を拡張クリップボードの呼び出しに割り当てています(Paste, Alfred, maccyなど)。
Windowsでは、デフォルトで搭載されている拡張クリップボードを使うことにしたのですが、Win
+V
から割り当てを変える設定がないようだったので、これもAutoHotKeyで巻き替えました。
; ----------------------------------------------------------- ; 拡張クリップボード ; macOSで、Cmd+Shift+Vに割り当てている拡張クリップボードを ; Windowsのクリップボードで再現 ; ----------------------------------------------------------- Shift & v::{ If (GetKeyState("LWin","P")){ ; リマップの影響でCtrlが押下状態になっているので、明示的に外す SendInput("{Blind}{LCtrl Up}{RCtrl Up}") SendInput("#v") }else{ SendInput("V") } }
若干テクニカルな設定になっていますが、AutoHotKeyは、最大2つのキーの入力に対してしかホットキー設定を行えないため、3つ目以降の条件はロジック中で押されているかどうかの判定をすることになります。
本当はWin
+V
に対して設定を行いたかったのですが、なぜかうまくいかず、別途設定しているLWin
をLCtrl
に巻き替える設定が無効化される事象が発生したため、試行錯誤のすえこうなりました。
VSCode
最大の鬼門です。
修飾キー足りない問題再び
先にも述べましたが、macOSの4つの修飾キーはそれぞれデフォルトであまりショートカットが割り当たっておらず自由に使えるのに対し、Windowsは修飾キーのひとつである Winキー
にもともとショートキーが割り当たっている影響で、実質的になにも気にすることなく利用できる修飾キーは3つのみです。
この問題の回避のために、CapslockキーをF13キーに割り当ててこれまでの設定はしてきましたが、VSCodeの場合はこれだけだとまだ不足します。
というのも、VSCodeでショートカットキーとして設定できるのは、 修飾キーの組み合わせ
+通常キー1つ
だけなので、 F13と特定のキーの組み合わせはショートカットとして登録できないためです。
例えば、macOSでは Ctrl
+G
が行指定でカーソルを移動するショートカットになっています。ここまでに設定してきたキーバインドに従うと、F13
+G
を割り当てられるとmacOSと同じ挙動になるのですが、F13
は修飾キーではないので、この組み合わせは登録できません。
当然ながらその他の修飾キーとの組み合わせ、例えばF13
+Shift
+なにか
のような設定もできません。
AutoHotKey併用でなんとかする
対策として、かなりテクニカルな設定をAutoHotKeyで行って打開しています。
具体的には
- VSCodeのショートカットとして、
登録可能な適当なキーの組み合わせ
を実現したい動作に割り当てる - AutoHotKeyで、
F13
+なにか
の本当に実現したいショートカットキーの組み合わせ を↑の登録可能な適当なキーの組み合わせ
に巻き替える
の2段階の登録を行います。
例えば、先ほどの行指定のカーソル移動の例だと
- VSCodeのショートカットとして、
F13
→Ctrl
+G
を行指定のカーソル移動として割り当てる - AutoHotKeyで、
F13
+G
をF13
→Ctrl
+G
に巻き替える
とすると、F13
+G
で、行指定のカーソル移動ができるようになります。
ただ、メンテナビリティ/コードの見通しともに相当悪くなるので、本当に使うショートカットだけを登録することをおすすめします。
あまりにも数が多いので、コード全体は以下のGitHubをご確認いただくとして、いくつか代表的な設定方法だけ解説しておきます。
F13+なにか に割り当てたいケース
先ほどの行指定移動のようなケースです。
AutoHotKey
F13 & g::{ SendInput("{F13}") SendInput("^g") }
VSCode - keybindings.json
{ "key": "F13 ctrl+g", "command": "workbench.action.gotoLine", }
F13+なにか → F13+なにか に割り当てたいケース
特定のショートカットのあとにさらにショートカットを入力することで、トリガーするケースです。
例えば、以下では F13
+m
→ F13
+spaace
でターミナルの位置を移動できるようにしています。
AutoHotKey
# F13押下時にフラグを立てる f13AndMPressed := False F13 & m::{ # AutoHotKeyでグローバル変数を利用する際は # スクリプト内で再定義が必要 global f13AndMPressed if (not f13AndJPressed){ f13AndMPressed := True } } # フラグが立っている場合のみ動作させる F13 & space::{ global f13AndMPressed if (f13AndMPressed){ SendInput("{F13}") SendInput("+^{Space}") f13AndMPressed := False } }
VSCode - keybindings.json
{ "key": "F13 ctrl+shift+space", "command": "workbench.action.positionPanelRight", "when": "panelPosition == 'bottom'" }, { "key": "F13 ctrl+shift+space", "command": "workbench.action.positionPanelBottom", "when": "panelPosition == 'right'" }
実現できなかったこと
ここまでの設定でおおよそ快適な環境を手に入れられたのですが、残念ながら理想通りにできなかった部分もあるため、ご紹介しておきます。
VSCodeのターミナル操作
できればVSCodeのターミナル操作時だけは、Capslock
をCtrl
に巻き替えたかったのですが、できませんでした。
というのも、ターミナル=zshの各種ショートカットはCtrlとの組み合わせで登録されているので、これができるとよりmacOSに近い挙動を再現できるようになります。
AutoHotKeyの巻き替え設定で、ターミナルにフォーカスが当たっている場合だけF13
をCtrl
に巻き替えて実現しようとしたのですが、条件指定がうまくできず、実現できませんでした。
AutoHotKeyは、アクティブなウィンドウの名称が特定の場合に限り巻き替え操作を行う、という指定ができるのですが、VSCodeのターミナルにカーソルが当たっていることをトリガーにウィンドウ名を変更する術がなく、やりようがなかった感じです。
ここは本当になんとかしたいところなので、また方法が見つかったら追記します。
だいぶ快適になった
テクニカルすぎる設定もありましたが、一度設定して仕舞えばあとはなにも考えなくてOK。
Windowsでも快適なコーディング環境を作ることができました。
なによりもAutoHotKeyが、知れば知るほど多機能すぎて驚きでしたね。
同じくmacOS愛好家なみなさん、ぜひぜひお試しください〜。