Linux でキーボードのレイアウトを変更する

# はじめに

Linux でキーボドのレイアウトを変更し用途思ったのですが、意外とハマったので自分のメモ用も兼ねてまとめます。一時的な設定ではなく永続的な設定について述べます。

間違い等あればご指摘いただけると嬉しいです。


# 環境

ディストリビューション: Arch Linux


目標
=====
- キーボードのUS配列への変更（元々JIS配列にしていた）
- Caps lock と 左Ctrl キーの入れ替え


# 設定内容

色々と調べてみた結果、Arch Linux (Linux一般？) は仮想コンソールとXorg(GUI)でのキーボード設定を別々に管理しているようです。

[コンソールでのキーボード設定 - ArchWiki](https://wiki.archlinuxjp.org/index.php/%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%81%A7%E3%81%AE%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E8%A8%AD%E5%AE%9A)
[Xorg でのキーボード設定 - ArchWiki](https://wiki.archlinuxjp.org/index.php/Xorg_%E3%81%A7%E3%81%AE%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E8%A8%AD%E5%AE%9A)

## コンソールでのキーボード設定

### 基本設定

[コンソールでのキーボード設定 - ArchWiki](https://wiki.archlinuxjp.org/index.php/%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%81%A7%E3%81%AE%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E8%A8%AD%E5%AE%9A) によると、

> 仮想コンソールのキーボードマッピング (keymap) やコンソールフォント、コンソールマップは kbd パッケージ (既にインストールされているはずです) によって提供されています。

とのこと。具体的なコマンドは `localectl` になるそうです。

設定は以下のように行います。

```
$ localectl set-keymap --no-convert jp106
```

ここで、 `--no-convert` は Xorg(GUI) への設定にも影響を及ぼさないようにするためのオプションです。Xorg への個別設定方法は後述します。


### 特殊設定

さて、Caps lock と Ctrl キーの入れ替えを行っていきます。以下のページを参考にしました。

[コンソールでの特別なキーボードキー - ArchWiki](https://wiki.archlinuxjp.org/index.php/%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%81%A7%E3%81%AE%E7%89%B9%E5%88%A5%E3%81%AA%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E3%82%AD%E3%83%BC)

US配列のキーボードマップをベースにしたいため、以下のコマンドを実行しベースとなるUS配列をコピーします。

```
$ sudo cp /usr/share/kbd/keymaps/i386/qwerty/us.map.gz /usr/local/share/kbd/keymaps/
$ sudo gunzip /usr/local/share/kbd/keymaps/us.map.gz
```
テキストエディタで、展開した `/usr/local/share/kbd/keymaps/us.map` に以下を追記します。

```
keycode 29 = Caps_Lock
keycode 58 = Control
```
最後に、作成したキーマップを起動時に読み込むように設定します。`/etc/vconsole.conf` に以下を追記します。

```/etc/vconsole.conf
KEYMAP=/usr/local/share/kbd/keymaps/us.map
```

以上でコンソールのキーボード設定の変更は完了です。


## Xorgでのキーボード設定

### 基本設定と特殊設定

[Xorg でのキーボード設定 - ArchWiki](https://wiki.archlinuxjp.org/index.php/Xorg_%E3%81%A7%E3%81%AE%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E8%A8%AD%E5%AE%9A) によると、Xorg のキーボドレイアウト管理は、

> Xorg は X KeyBoard extension (XKB) を使ってキーボードレイアウトを管理しています。

となっているそうです。また、それを利用したキーボードの設定方法には3種類あるようです。

1. setxkbmap を使う
2. X の設定ファイルを使う
3. localectl を使う

今回は3. を使用します。理由は以下の通り。

- 1. はそのセッション内のみ有効なため、永続化できない（xinitrcを利用することで可能ではある）
- 2. は3. を実行することで自動で上書きされる。

つまり、コンソールのキーボド設定でも使用した `localectl` がまた利用できるわけです。

設定は、基本設定と特殊設定（Caps lock, 左Ctrl キーの入れ替え）を同時に、以下のコマンドで行います。

```
$ localectl --no-convert set-x11-keymap us pc105 "" ctrl:swapcaps   
```

`--no-convert` オプションはコンソールの設定に影響を及ぼさないためのものです。

また、`ctrl:swapcaps` が入れ替えのためのオプションとなります。

以上でせって終わりです。


# 設定確認

`localectl` を利用した設定の確認には以下のコマンドを実行します。

```
$ localectl status
```

実行結果としては以下のようになります。

```bash:実行結果
   System Locale: LANG=en_US.UTF-8
       VC Keymap: /usr/local/share/kbd/keymaps/us.map
      X11 Layout: us
       X11 Model: pc105
     X11 Options: ctrl:swapcaps
```

また、Xorg の設定結果は以下のコマンドで見たほうが良さそうです。理由はGNOMEなどのデスクトップ環境（ソフト）によって上書きされてします可能性があるからです。

```
$ setxkbmap -print -verbose 10
```

実行結果は

```bash:実行結果
Setting verbose level to 10
locale is C
Trying to load rules file ./rules/evdev...
Trying to load rules file /usr/share/X11/xkb/rules/evdev...
Success.
Applied rules from evdev:
rules:      evdev
model:      pc105
layout:     us,jp
variant:    ,
options:    ctrl:swapcaps
Trying to build keymap using the following components:
keycodes:   evdev+aliases(qwerty)
types:      complete
compat:     complete
symbols:    pc+us+jp:2+inet(evdev)+ctrl(swapcaps)
geometry:   pc(pc105)
xkb_keymap {
        xkb_keycodes  { include "evdev+aliases(qwerty)" };
        xkb_types     { include "complete"      };
        xkb_compat    { include "complete"      };
        xkb_symbols   { include "pc+us+jp:2+inet(evdev)+ctrl(swapcaps)" };
        xkb_geometry  { include "pc(pc105)"     };
};
```

となりました。


# ハマったところ
冒頭にお話しましたが、元々JIS配列環境に初期設定していたものをUS配列に変更しました。故に、以前自分でJIS配列用に設定していたアプリがXorgの設定を上書きして、一旦US配列設定にしたのに、JIS配列に上書きしていた事象が起こりました。

その時の設定確認結果が以下です。

```bash:
   System Locale: LANG=en_US.UTF-8
       VC Keymap: /usr/local/share/kbd/keymaps/us.map
      X11 Layout: us
       X11 Model: pc105
     X11 Options: ctrl:swapcaps
```
```bash:
Setting verbose level to 10                                                             
locale is C                                                                             
Trying to load rules file ./rules/evdev...                                              
Trying to load rules file /usr/share/X11/xkb/rules/evdev...                             
Success.                                                                                
Applied rules from evdev:                                                               
rules:      evdev                                                                       
model:      pc105                                                                       
layout:     jp,us                                                                       
variant:    ,                                                                          
options:    ctrl:swapcaps                                                              
Trying to build keymap using the following components:
keycodes:   evdev+aliases(qwerty)                                                      
types:      complete                               
compat:     complete         
symbols:    pc+jp+us:2+inet(evdev)+ctrl(swapcaps)                                      
geometry:   pc(pc105)            
xkb_keymap {                               
        xkb_keycodes  { include "evdev+aliases(qwerty)" };
        xkb_types     { include "complete"      };                                     
        xkb_compat    { include "complete"      };                                     
        xkb_symbols   { include "pc+jp+us:2+inet(evdev)+ctrl(swapcaps)" };             
        xkb_geometry  { include "pc(pc105)"     };                                     
};                                          
}; 
```

細かいですが、後者の結果のうち、`layout` の項目の `jp`, `us` が逆転していることがわかります。

原因を探るうち、`~/.xsession-errors` のファイルを見てみると以下の記述を発見。

```bash:~/.xsession-errors
(INFO-2846 /build/fcitx/src/fcitx-4.2.9.1/src/lib/fcitx/addon.c:151) Load Addon Config File:fcitx-xkb.conf
```
なんと、日本語入力用に入れた Fcitx が設定を上書きしているようでした。GUIで Fcitx の設定を確認してみると、予想通り日本語キーボード設定がされていました（以前自分がしたもの）。

Fcitx の設定を英語キーボードに設定しなおしたところ正常に動きました。


# まとめ
以上の、調査により以下のことがわかりました。

- 仮想コンソールと Xorg のキーボード設定は別々に行う必要がある。
- 基本的にはどちらも `localectl` で設定可能。
- Xorg のキーボード設定はデスクトップ環境やインプとメッソドなどによって上書きされる場合があるので注意が必要。

GUI のxkb についてはまだまだ分からないことが多いので、機会があったら調べてみたいと思います。