XKBによるHHKB (US) のためのキーマップ変更 (Ubuntu 18.04 LST)

__🌾本記事の概要__
自作PCに`Ubuntu 18.04.04 LST`をインストールした際の手順を残しておきます。
以下，目次です。**今回は`fcitx-mozc`のインストールから`X keyboard extension (XKB)` によるキーマップ変更についてです。**

**＃ マシン構成について**
＃ `Ubuntu 18.04.4 LST`のインストール
＃ `NVIDIAドライバ` & `CUDA`の更新 (ログインループ改善)
**＃ `fcitx-mozc`のインストール & 設定
＃ `XKB`によるキーマップ変更 (for `HHKB [US]`)**
＃ 適宜追記

前回記事はこちら↓
[**Qiita『自作PCにUbuntu 18.04 LSTをインストール & セットアップ (NVIDIAドライバ関係)』**](https://qiita.com/ddd_ppp_story/items/a356cae678a769a03e2a)

## マシン構成について
今回`Ubuntu 18.04.04 LST`をインストールしたマシンの構成は以下の通りです。

| 構成要素              | 購入パーツ名                                 |
|:---------------------|:---------------------------------------|
| マザーボード           | X570 Taichi (BIOS ver. 2.70; ASRock)   |
| CPU                  | Ryzen 7 3700X (AMD)                    |
| CPUクーラー           | 虎徹 Mark II (サイズ)                    |
| グラフィックボード      | GeForce RTX 2080 Ti VENTUS GP OC (MSI) |
| メモリ                | DDR4-3200 16 GB×2 (Crucial)            |
| SSD (OSインストール先) | MX500 500 GB 2.5インチ (Crucial)        |
| HDD (データ保存用)     | WD Red 3 TB 3.5インチ (Western Degital) |
| 電源                  | RM850x 850 W (80PLUS GOLD; Corsair)    |
| ケース                | Define C (Fractal Design)              | 

## fcitx-mozcのインストール & 設定
今回インストールした`Ubuntu 18.04.04 LST` (ちなみに日本語 Remix) にはデフォルトのインプットメソッドとして`IBus`がインストールされていましたが，**好みの問題で`Fcitx`に変更します**。
([**二代目俺のメモ『Ubuntu 19.10の日本語入力をfcitx-mozcにする』**](https://www.kwonline.org/memo2/2019/11/13/fcitx-mozc-on-ubuntu-19-10/)を参考にさせていただきました)

`fcitx`と`fcitx-mozc`をインストールし，`ibus`をアンインストールします。

```.sh
$ sudo apt install fcitx fcitx-mozc
$ sudo apt --purge remove ibus
```

`入力メソッド`を起動します。

```.sh
$ im-config
```

`fcitx`をアクティブにしたら再起動します。

```.sh
$ sudo reboot
```

再起動できたら`Fcitx`および`Mozc`の設定を行います。私は，キーボードとして主に`HHKB Professional2 Type-S (US)`を使用しているので，`HHKB (US)` 向きの設定になります。
([**JUNのブログ『HHKBをUbuntuで使う』**](https://jun-networks.hatenablog.com/entry/2019/11/20/160003)を参考にさせていただきました)

まず，以下のコマンドを入力します。

```.sh
$ sudo dpkg-reconfigure keyboard-configuration
```

その後開くウィンドウで
**キーボードモデル：`Happy Hacking`**
**キーボードが由来する国：`英語 (US)`**
**キーボードのレイアウト：`英語 (US)`**
**AltGrとして機能させるキー：`キーボード配置のデフォルト`**
**コンポーズキー：`コンポーズキーなし`**
**Xサーバーを強制終了するのに〜：`<いいえ>`**

と選択していきます。設定が完了したら次に`Fcitx設定`を開きます。

```.sh
$ fcitx-configtool
```

`入力メソッド`タブにおいて入力メソッドを`Mozc`だけにし，歯車アイコンをクリックしてキーボードレイアウトを`既定の入力メソッド`から`英語 (US)`に変更します (不要？)。

`全体の設定`タブにおいて入力メソッドのオンオフを`空`にします (`Esc`を押すことで`空`にできます)。

デフォルトのスキンがダサい [要出典] ので[**`fcitx-skin-material`**](https://github.com/hrko99/fcitx-skin-material])に変更します。

`~/.config/fcitx/skin`ディレクトリを作成し，ダウンロードした`material`フォルダをコピーします。

`Fcitx`を再起動した後に`Fcitx設定`の`外観`タブを開き，`Show Advanced Options`にチェックを入れ，下の方にあるスキン名の欄に`material`と入力します。

ついでにフォントとメニューのフォントを`Noto Sans CJK JP Medium`に，表示するフォントロケールを`ja_JP.UTF-8`に変更し，再起動して完了です。

## XKBによるキーマップ変更 (for HHKB [US])
`Fcitx`に続いて`Mozc`の設定を行う前に**`HHKB (US)`用のキーマップをカスタムします**。

### なぜキーマップを変更したいのか
私は主にWindowsで`HHKB`を使用しているため，`HHKB`のDIPスイッチを下記のように設定しています。

| SW1 | SW2 | SW3 | SW4 | SW5 | SW6 |
|:---:|:---:|:---:|:---:|:---:|:---:|
| ON  | OFF | ON  | OFF | ON  | OFF |           

具体的には`Delete`キーが`BS (BackSpace)`キーになり，キーボード最下部の配列が下記のようになります。

`Windows-Left` `Alt-Left` `Space` `Alt-Left` `Windows-Left`

Ubuntuでは`Windows`キーは`Super`キーとして機能します。

Windowsで使用する際は，[**`alt-ime-ahk`**](https://www.karakaram.com/alt-ime-on-off)を使用して**`Alt`キー空打ちでIMEを切り替えられるように設定**していました。Ubuntuでこれを再現する方法をすぐには見つけられなかったので，**代替案としてUbuntu上で下記のようなキー配置にリマップ**することにしました。

`Alt-Left` `無変換` `Space` `変換` `Super-Left`

`無変換`および`変換`には，それぞれIMEの`オフ`および`オン`機能を`Mozc`で割り振ることにします。

### XKBで目的のキー配列にリマップする
はじめは`xmodmap`を使ってリマップしようとしましたが，いろいろ調べているうちに**最近のUbuntuでは`xmodmap`で変更したキーマップが`Fcitx`によってリセットされてしまう**，という情報を目にしました ([**Qiita『Ubuntuにおけるキーボードレイアウトカスタマイズ：xmodmap問題をxkbで解決』**](https://qiita.com/jabberwocky0139/items/40b28406daa6769a9c4d))。

で，最近の推奨としては`XKB`を使うのだ，ということらしいので，**`XKB`を経由して目的のキーマップ変更を試みる**ことにしました。
([**Honmushi blog『xkbでキーバインドを変更する』**](https://honmushi.com/2019/01/18/ubuntu-xkb/)を参考にさせていただきました)

以下のコマンドを実行すると現在の`XKB`の設定が確認できます。

```.sh
$ setxkbmap -print
xkb_keymap {
	xkb_keycodes  { include "evdev+aliases(qwerty)"	};
	xkb_types     { include "complete"	};
	xkb_compat    { include "complete"	};
	xkb_symbols   { include "pc+us+us:2+inet(evdev)"	};
	xkb_geometry  { include "hhk(basic)"	};
};
```

ここで重要なのは`xkb_symbols`の項目です。
結論から言ってしまうと，最終的に`xkb_symbols`の`pc+us+us:2+inet(evdev)`に上書きしたい設定 (例えば`myswap`) を追加することになります。
(つまり`pc+us+us:2+inet(evdev)+myswap`となります)

`myswap`を作成するに当たって，まず`pc`や`us`に何がどのように書かれているかを確認します。
各ファイルは`/usr/share/X11/xkb/symbols`ディレクトリに格納されています。

`pc`の中を見てみると

```.sh
default  partial alphanumeric_keys modifier_keys
xkb_symbols "pc105" {

    key <ESC>  {        [ Escape                ]       };

    // The extra key on many European keyboards:
    key <LSGT> {        [ less, greater, bar, brokenbar ] };

    // The following keys are common to all layouts.
    key <BKSL> {        [ backslash,    bar     ]       };
    key <SPCE> {        [        space          ]       };
```

のように記述されています。

ここで`key <ESC> { [ Escape ] }`は
**<キーシンボル>** `ESC`に`Escape`という **[機能]** を割り当てる，ことを意味します。

つまり目的の`myswap`を作成するためには，

- `Alt-Left`，`Alt-Right`，`Windows-Left`，および`Windows-Right`の **<キーシンボル>**
- `無変換`，`変換`，`Alt-Left`，および`Super-Left`の **[機能を表す文字]**

を調べる必要があります。

なんとなく`無変換`や`変換`については`jp`に書かれていそうだな，と予測して`/usr/share/X11/xkb/symbols/jp`の中身を見てみると

```.sh
key <NFER> { [ Muhenkan             ] };

key <XFER> {
    type[Group1]="PC_ALT_LEVEL2",
    symbols[Group1]= [ Henkan, Mode_switch ]
};
```
```.sh
key <LWIN> {        [ Super_L       ]       };
key <LALT> {        [ Alt_L         ]       };
key <SPCE> {        [ space         ]       };
key <RALT> {        [ Alt_R         ]       };
// For compatibility with other keyboards connected at the same time:
key <RWIN> {        [ Super_R       ]       };
key <RCTL> {        [ Control_R     ]       };
```

のような記述が見つかります。欲しかった情報をまとめると……，

|               | <キーシンボル> | [機能を表す文字列]     |
|:--------------|:------------:|:-------------------:|
| Alt-Left      | LALT         | Alt_L               |
| Alt-Right     | RALT         | Alt_R               |
| Windows-Left  | LWIN         | Super_L             |
| Windows-Right | RWIN         | Super_R             |
| 無変換         | NFER         | Muhenkan            |
| 変換           | XFER         | Henkan, Mode_switch |

となります。また，`Henkan, Mode_switch`のコンマ以下は`Shift`キー等を使った複合キー設定なので，今回の目的では特に必要ありません (`Henkan`だけでOK)。

記述方法が判ったので，実際の設定ファイルの作成に移ります。
まず，ホームディレクトリに`.xkb/symbols`および`.xkb/keymap`というディレクトリを作成します。

```.sh
$ mkdir ~/.xkb/symbols ~/.xkb/keymap
```

次に，さきほど特定したキーシンボル等を参考にして，`~/.xkb/symbols`ディレクトリ内に以下の`myswap`ファイルを作成します。

```.sh
partial modifier_keys
xkb_symbols "swapkeys" {
  key <LALT> { [ Muhenkan ] };
  key <RALT> { [ Henkan   ] };
  key <LWIN> { [ Alt_L    ] };
  key <RWIN> { [ Super_L  ] };
};
```

さらに，序盤に行った`setxkbmap -print`の出力結果を参考にして，`~/.xkb/keymap`内に以下の`mykbd`ファイルを作成します。

```.sh
xkb_keymap {
        xkb_keycodes  { include "evdev+aliases(qwerty)" };
        xkb_types     { include "complete"      };
        xkb_compat    { include "complete"      };
        xkb_symbols   { include "pc+us+us:2+inet(evdev)+myswap(swapkeys)"       };
        xkb_geometry  { include "pc(pc105)"     };
};
```

`xkb_symbols`に`myswap(swapkeys)`を`+`で追記しています。

以下のコマンドを入力することで作成したキーマップを反映させます。

```.sh
xkbcomp -I$HOME/.xkb ~/.xkb/keymap/mykbd $DISPLAY 2> /dev/null
```

ログイン時に自動で実行するために，`.bashrc`等に上記コマンドを記述しておきます。

最後に`Mozc`の設定を行い，`無変換`および`変換`に対して，それぞれIMEの`オフ`および`オン`機能を割り当てます。

`Mozcの設定`を起動し，`一般`タブにあるキーの選択の`編集`ボタンを押します。

`Mozcキー設定`ウィンドウが開いたら，`Muhenkan`および`Henkan`入力キーに対して，それぞれ`IMEを無効化`および`IMEを有効化`コマンドを割り当てます。

再起動してキーマップが目的のとおりに変更されることを確認しましょう。

以上，お疲れ様でした。