Ubuntuにおけるキーボードレイアウトカスタマイズ : xmodmap問題をxkbで解決

<!---
	Ubuntuにおけるキーボードレイアウトカスタマイズ : xmodmap問題をxkbで解決
-->

# 対象
* Linux(Ubuntu)でキーマップを変更したい

* 「`xmodmap`がちゃんと動かないんだけど？」

というビギナーさん向けです. xkbについての詳しい解説は載せていません. 環境は Ubuntu 16.04 LTS を想定しています. 

# あらまし
かつては, Linuxでキーボードレイアウトをカスタムしたいときは`xmodmap`を使うのがふつうでした. `xev`でキーコードを調べて, ホーム直下にある`.Xmodmap`に

```bash
keycode 51 = Return
```
とでも書き込んでシェルで`xmodmap .Xmodmap`と打ち込んであげれば, 51番のキーコードを持つキーがReturn(Enter)キーになってくれるのです. この方法の解説はネットにたくさんあります. 

しかし最近のUbuntuではこの方法が有効ではなくなってしまいました. 設定した直後はちゃんと動くものの, しばらくすると元のキーマップに戻ってしまいます[^1]. 

最近のUbuntuではキーボードレイアウトの変更は`xkb`というものを使うことが推奨されているようです. **さて, この`xkb`なるものの使い方は`xmodmap`とどのように異なるのでしょうか？**

## 個人的な動機
(読み飛ばしてもらって頂いても結構です)

最近HHKBの英字配列を自宅用に買いました. すこぶる快適です. これを受けて, 研究室にある日本語配列のキーボード(Libertouch)を英字配列に変えたくなりました. 「システム設定」→「テキスト入力」にて入力ソースの「日本語」を「英語(US)」に変えればいいだろう, と思いました. だいたいOKでした. 

しかし, 下の青いキーは思ったとおりに動作しませんでした. 

![key1.gif](https://qiita-image-store.s3.amazonaws.com/0/146775/1bc5c3e7-1835-aecf-e64a-5b976b620785.gif)
[富士通コンポーネントさんより](http://www.vshopu.com/item/207Y-3001/)

右シフトのとなりはまあどうでもいいのですが, Backspaceのとなりは「\\(backslash), |(bar)」になってほしいです. ちなみにHHKBの配列はこんなかんじです:

![key2.gif](https://qiita-image-store.s3.amazonaws.com/0/146775/8f8852b5-c929-cdb2-5976-e37a3afcc525.gif)
[PFUさんより](http://www.pfu.fujitsu.com/hhkeyboard/kb_collection/#hhkeyboard)

しかし残念なことに, 英字配列のキーは日本語配列よりも少ないので上の2つのキーコードが存在しません. `xmodmap`では辛うじて設定できたのですが, 前述の通り何者かによってキーマップが上書きされてしまいます. というわけで, キーコードが存在しないならしょうがない. 「システムの日本語配列の設定をUS配列と同等のものに置き換えてしまおう」と考えました[^2]. 調べると`xkb`なるものを使えばよいことがわかりました. というわけで, 本題です. 

# 手順
繰り返しになりますが, `xmodmap`では

* `xev`でキーコードの取得
* `.Xmodmap`に設定を書き込み

という手順を踏むことになります. では`xkb`ではどのようにしてキーコードを取得すればよいのでしょうか？ まずはシェルで`setxkbmap -print`と入力してみましょう:

```bash
xkb_keymap {
	xkb_keycodes  { include "evdev+aliases(qwerty)"	};
	xkb_types     { include "complete"	};
	xkb_compat    { include "complete"	};
	xkb_symbols   { include "pc+jp"};
	xkb_geometry  { include "pc(pc105)"	};
};

```
こんなのが出てきました. **注目すべきは`xkb_symbols`のところです.** `pc+jp`は`pc`と`jp`というファイルを読み込むことを意味しています. つまりこの`pc`や`jp`が設定ファイルに相当するのです. もし英字配列に設定している方は`jp`が`us`になっているでしょう. ではこの設定ファイルはどこにあるのでしょうか. 自分の環境では`/usr/share/X11/xkb/symbols/`内にありました. では, 試しに`jp`内を覗いてみましょう:

![key3.png](https://qiita-image-store.s3.amazonaws.com/0/146775/ce0ef23c-f438-3f3f-dc94-c10829974d69.png)
とある理由によりバッファ名は`_jp`になってます

もうなんとなくわかりましたね, **たとえば「1, !」のキーコードは\<AE01\>, 「e, E」のキーコードは\<AD03\>です.** これでめでたく`xkb`におけるキーコードを調べることができました. しかし, キーコード自体はそんなに重要ではありません. なぜかというと, キーマップを変更するには**この設定ファイルをそのまま書き換えてしまえばよいからです[^3].** どこをどう変更するかは設定ファイルを眺めていればだいたいわかると思います. 自分はUS配列ぽくしたいのでこんなかんじにしました:

![key4.png](https://qiita-image-store.s3.amazonaws.com/0/146775/fd3284f8-e8dc-4a9f-9765-aab2d0904251.png)

(自分にとって)大事なことは英字配列の設定ファイル`us`には存在しない\<AE13\>のキーコードが日本語配列の設定ファイル`jp`にはちゃんとあることです. これで上の青いキーを英字配列っぽくマップすることができました. 

# まとめ
1. `setxkbmap -print`の`xkb_symbols`を見て, どの設定ファイルが読み込まれているのかを確認(普通の日本語配列なら`jp`)
* `/usr/share/X11/xkb/symbols/`内のお目当ての設定ファイルを見つける
* お好きに書き換えましょう
* 再ログイン

挙動がおかしくなってもすぐに元に戻せるようにバックアップを取っておきましょう. 自分は`jp`のバックアップを`_jp`としました. 

常識的に考えれば, `/usr/share/X11/...`なんてところにあるファイルを直接書き換えることはかなりの暴挙であるように思います[^4]. 可搬性も悪いです. `xmodmap`における`.Xmodmap`みたいな間接的な設定ファイルを作ることはできるのかな？ 何にしても場当たり的であることは間違いないので, もっとクレバーな方法を知っているクレバーな方に是非教えていただきたいです.

[^1]: 一説によるとFcitxが`xmodmap`が変更したキーマップを上書きしてしまうらしいです. 
[^2]: 絶対にもっと上手い方法があるはず...
[^3]: いや絶対にもっと上手い方法があるはず...
[^4]: いやいや絶対にもっと上手い方法があるはず...