ぐるっとぐりっど

日曜プログラマがいろいろ試してみたことを、後の自分のためにまとめておく場所

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

はじめに

この前の東京Emacs勉強会で雑談してたときに、Superキー、Hyperキーの話になり、Macは修飾キーが多くてうらやましかった。 キーバインド覚えやすいところうまっていて、追加で悩む状況でもあるし。

ということで自分もSuper/Hyperデビューすべく、WSLでのやりかたを調べてみた。

tokyo-emacs.connpass.com

環境

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

なので、emacs for windowsとか、mingwemacsではないです。その場合は、また他の手段を取る必要があるはず 1

なお、wslで使うXサーバといえば、xmingかvcxsrvが有名ですが、emacsとの相性がよくない(※)ので別の有償のXサーバを使ってる。 X410は、ストアアプリとして購入できるが、しょっちゅう80%Offセールしているので割引タイミングを狙いましょう。

(※) emacsとの相性がわるい問題については以下のスライドを

speakerdeck.com

目指すゴール

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

一般的には、WindowsキーがSuperキーにあたると思うし、なんなら設定なしでもそう動いてしかるべきなのだけど、そもそもOS側にトラップされてアプリケーションまでうまく届かなかったのと、Windows10になって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サーバが起動していない状態ではうまく動かない。 LinuxBSD使ってるときにも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でコマンド実行できる。

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

まとめ

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


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