emacs on WSLでSuper/Hyperキーを使う


はじめに

Emacs勉強会(に限った話ではないが)だとMacユーザが多いので、私が普段使っている Control/Meta以外に、Superキー/Hyperキーを割りあててる人もそこそこいる。 以前、Windowsの場合はwinキーがsuperキーになると聞いた覚えもあったのだけど、 うまくいかなかったのでWSLで使ってないキーにSuper/Hyperを割りあててデビューしようと調べてみた。

環境

  • WSL
  • WSL上で動くEmacs
  • X410(Xサーバ)

上記前提なので、 Emacs for windows とか、 mingw 上のemacsの話ではない。 これであれば、他の手段1が使えるはず。

なお、Xサーバはやはり無償で利用できる xming とか vcxsrv とかが利用者多いと思うが、 emacsとの相性がよくない2ので、有償のものを使っている。 X410 は、ストアアプリとして購入でき、しょっちゅう割引きセールしているので、そのタイミングで買うのが吉。

目指したゴール

無変換キーをSuperキー、変換キーをHyperキーとして使えるようにする。

本来は冒頭の通り、WindowsキーがSuperキーなのが普通だと思うのだけど、 なんかトラップされてうまくうごかなかったのと、Win+○のキーバインドも 結構使うので、それを潰してしまうのも惜しかったので、そのようにした。

前置きおわり。

Superキー/Hyperキーを設定する

手段その1 AutoHotKeyを使う

多分これが一番早いと思います。 サンプルも多いはず。

自分は、なんとなくWindowsのユーザランドでキーいじるやつが嫌だったので採用しなかった。 (CapsとCtrlの入れかえで、結局レジストリいじらないとうまくいかなかったりというのに以前ぶつかったりしたので)

手段その2 xmodmapを使う

xmodmap はlinuxというか、Xの世界でキーマップ変更するためのもの。 調べてみると最近は別のがあるっぽいけど、xmodmapでうまく動いたので気にしない。

そうそうキーコードなんて変わらないと思うので、同じ設定で同じように動くはず。

手順1. キーコードを特定する

xev というコマンドを使うと、Xのアプリが起動して、そこでもろもろのイベントを標準出力に出して確認することができる。 これを使うと、変換と無変換のキーコードは以下のとおり、変換が 129 、無変換が 131 であることがわかる。

KeyRelease event, serial 33, synthetic NO, window 0x800001,
    root 0xf4, subw 0x0, time 426541921, (67,97), root:(179,232),
    state 0x0, keycode 131 (keysym 0xff22, Muhenkan), same_screen YES,
    XLookupString gives 0 bytes:
    XFilterEvent returns: False

KeyPress event, serial 33, synthetic NO, window 0x800001,
    root 0xf4, subw 0x0, time 426596187, (843,330), root:(955,465),
    state 0x0, keycode 129 (keysym 0xff23, Henkan_Mode), same_screen YES,
    XLookupString gives 0 bytes:
    XmbLookupString gives 0 bytes:
    XFilterEvent returns: False

手順2. xmodmapの動作確認する

キーコードがわかったら、=xmodmap= コマンドで一時的にキーシムを書きかえて動作確認してみる。

# xmodmap -e "keycode 131 = Super_L Super_L"
# xmodmap -e "keycode 129 = Hyper_L Hyper_L"

実行後、再度xevを使って期待通り変わっていることを確認する。

KeyPress event, serial 33, synthetic NO, window 0x800001,
    root 0xf4, subw 0x0, time 426819890, (125,123), root:(263,284),
    state 0x0, keycode 131 (keysym 0xffeb, Super_L), same_screen YES,
    XKeysymToKeycode returns keycode: 115
    XLookupString gives 0 bytes:
    XmbLookupString gives 0 bytes:
    XFilterEvent returns: False

先程はキーコード131が無変換だったのが、Superに変わっていることがわかる。

手順3. xmodmapの設定を作成する

調べると、 xmodmap -pke を実行して、必要なところだけ書きかえましょう。というのが出てくるのだが、実際のところ必要な設定だけ書けばよかったので、いきなり .Xmodmap ファイルを作成する。 WSLで手持ちのXサーバ使う分には別にファイル名は何でもいいと思うのだが、ここは慣例に従っておく。(なお、 startx コマンドでXを起動するときは、雛形で =.Xmodmap=を読み込むのでファイル名重要)

自分の設定は、こんなかんじ。

https://github.com/grugrut/dotfiles/blob/master/.Xmodmap

clear  mod3
clear  mod4
!<muhenkan>
keycode 129 = Hyper_L Hyper_L Hyper_L Hyper_L
!<henkan>
keycode 131 = Super_L Super_L Super_L Super_L
add    mod3 = Hyper_L
add    mod4 = Super_L Super_R

デフォルトの状態だと、SuperキーとHyperキーが同じ修飾キーとしてあつかわれていて、Hyperキー単体でうまくうけとれないので使われていないmod3にHyperキーを割当ておいた。

手順4. 自動で適用されるようにする

xmodmap ~/.Xmodmap とコマンド実行すればよいのだけど、注意点が一つ。 xmodmapはXサーバに対して設定をおこなうコマンドなので、Xサーバが起動していない状態ではうまく動かない。 LinuxやBSD使ってるときにもxmodmap使ってたけど、当時は常にxorg-serverが起動してたので今回はじめてそのこと知った。

ついでなので、OSログイン時にXサーバを起動すべく適当なbatを作成した。 https://github.com/grugrut/dotfiles/blob/master/_windows/startx.bat

start /b x410.exe

ubuntu.exe run "DISPLAY=127.0.0.1:0.0 xmodmap ~/.Xmodmap"

x410.exeが使っているXサーバ。バックグラウンド実行させたいので、 /b オプションをつけてる。 そして、 ubuntu.exe run をすることでwslでコマンド実行できる。

これを Windowsの shell:startup に配置することでスタートアップ時に自動実行することができる。 ただし、直接おくよりもショートカットを配置することをおすすめする。直接配置すると、実行時にコマンドプロンプトが一瞬表示されてうっとうしいが、ショートカットであれば最小化して実行することができるので気にならないからだ。

まとめ

xmodmapを使うことで、他のアプリには影響なくwslのX使うアプリだけにいろいろ手をいれられることが確認できた。他にもその手の機能で便利なのありそう。


  1. たぶん w32-lwindow-modifier とかが使えるはず ↩︎

  2. https://speakerdeck.com/grugrut/emacs-on-wsldefalsekun-rigoto  ↩︎


関連記事