NICOA

Windows11をmacOSに極限まで近づけるための設定集(AutoHotKey v2)

Windows11をmacOSに極限まで近づけるための設定集(AutoHotKey v2)
どんな記事?

  • 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でも再現できるかが、今回の最大の課題でした。

縛り、制約

動きが再現できればなんでもいいかと言われると、そうでもなかったので、以下を制約として設けました。

  1. Windowsのレジストリエディタを使わない
  2. 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に置いてあるので、そちらを参照ください。以下ではポイントに絞って解説しています。

AutoHotKey v2をまじめに触るのは今回がはじめてだったため、非効率な実装も多々あると思います。

初期状態の確認

まずは、諸々のカスタマイズの前に初期設定がどのようになっているかを確認しておきましょう。

自分の観測範囲だけでも、Apple Magic Keyboard US配列を接続した際に、Capslockがなにキーとして認識されるかに差があったため、はじめに状況を確認しておくことをおすすめします。

キーの認識状態は、上で述べたPowerToys Keyboard Managerを使うと、GUI操作でわかりやすく判別できます。

以降の設定値は以下のように認識していることを前提としているため、違った場合は適宜読み替えてください。

Magic KeyboardのキーWindowsでの認識
CommandWin
CtrlCtrl
OptionAlt
ShiftShift
CapslockF13

(もし設定されていなかったら)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

を使っていただくとよいかと。

キーの割り当て変更

ここまでの事前準備が整ったら、どんどん設定をいれていきます。
まずは、キーの割り当てです。

CommandCtrlになっていた方が、コピペ時などなどmacOSに操作感が近いので、以下のように巻き替えました

Magic Keyboardのキー元のWindowsでの認識巻き替え後
CommandWin**Ctrl**
CtrlCtrl**Win**
OptionAltAlt
ShiftShiftShift
CapslockF13F13
; -----------------------------------------------------------
; 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::LCtrlLCtrl::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に対して設定を行いたかったのですが、なぜかうまくいかず、別途設定しているLWinLCtrlに巻き替える設定が無効化される事象が発生したため、試行錯誤のすえこうなりました。

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のショートカットとして、F13Ctrl+G を行指定のカーソル移動として割り当てる
  • AutoHotKeyで、F13+GF13Ctrl+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+mF13+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のターミナル操作時だけは、CapslockCtrlに巻き替えたかったのですが、できませんでした。

というのも、ターミナル=zshの各種ショートカットはCtrlとの組み合わせで登録されているので、これができるとよりmacOSに近い挙動を再現できるようになります。
AutoHotKeyの巻き替え設定で、ターミナルにフォーカスが当たっている場合だけF13Ctrlに巻き替えて実現しようとしたのですが、条件指定がうまくできず、実現できませんでした。

AutoHotKeyは、アクティブなウィンドウの名称が特定の場合に限り巻き替え操作を行う、という指定ができるのですが、VSCodeのターミナルにカーソルが当たっていることをトリガーにウィンドウ名を変更する術がなく、やりようがなかった感じです。

ここは本当になんとかしたいところなので、また方法が見つかったら追記します。

だいぶ快適になった

テクニカルすぎる設定もありましたが、一度設定して仕舞えばあとはなにも考えなくてOK。
Windowsでも快適なコーディング環境を作ることができました。

なによりもAutoHotKeyが、知れば知るほど多機能すぎて驚きでしたね。

同じくmacOS愛好家なみなさん、ぜひぜひお試しください〜。