XKB で〔Esc〕キーを入れ替えてみた

# はじめに
[XKB](https://www.x.org/wiki/XKB/)[^xkb] のファイルを書き換えて、〔Esc〕キーと〔`〕(Grave) キーを入れ替えてみました。これに限らず、キーの入れ替えを試してみたい方は少なからずいらっしゃらるのではないでしょうか? この文書は、そのような方々への情報提供を目的としています。

 [^xkb]: より正確には、「[X Keyboard Configuration Database](https://www.freedesktop.org/wiki/Software/XKeyboardConfig/) のファイル」です。

 
# おことわり
* [Ubuntu  MATE](https://ubuntu-mate.org/) 22.04 で動作確認をしています。これに類似の環境[^matedist]であれば、同じように動作することが期待されます。
* Ubuntu のインストールや、キーボードの設定などは完了しているものとします。
* ここに記載の内容は全て、ANSI (US) 配列キーボードを前提としています。JIS (日本語) 配列など他の配列については対象外です。ご容赦ください。

[^matedist]: [MATE Desktop Environment](https://mate-desktop.org/) の 「Which distributions support MATE?」の項が参考になるかもしれません。

# 動機
Ubuntu MATE (と類似の環境) では、下図スクリーンショットに表示されているツールで、キーマップを変更することができます。このツールは mate-keyboard-properties[^matesrc] というものですが、これは gnome-keyboard-properties と広く呼ばれているものです。このツールでの設定変更はすぐに反映されますし、その変更内容は自動的に保存されます。よくある、設定ファイルを作成・修正 → 保存 → 再起動などの一連の動作は不要です。使いたいキーボードを PC に接続して、すぐに設定変更することができます。

[^matesrc]: mate-keyboard-properties のソースコードは[こちら](https://github.com/mate-desktop/mate-control-center/tree/master/capplets/keyboard)

しかも、あらかじめ用意された変更項目が豊富です (**そのように見えました**)。

そこで、この仕組みに乗っかって、〔Esc〕と〔`〕キーを入れ替えることができないかと目論みました。

![2048.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65370/12162053-c317-4d26-4656-c8d778d2fae8.png "mate-keyboard-properties")

私は、HHKB のように〔1〕の左隣に〔Esc〕キーがあるキーボードを好んで使用しています。しかしながら、〔Esc〕が由緒正しい場所についているキーボードを使わなければならない時もあります。大抵は〔1〕の左上あたりにあります。101 キーボードのように少し離れた場所についているキーボードもあります。

以下に、HHKB と 101 キーボードの写真を示します。〔Esc〕キーを赤丸してあります。(写真出典: [HHKB](https://happyhackingkb.com/jp/life/hhkb_life10.html), [101 Keyboard](https://commons.wikimedia.org/w/index.php?curid=37410391))

* HHKB
![hhkb_life10-2-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65370/544799a2-04a5-dd54-dc70-c2500780137d.jpeg "HHKB Keyboard Layout")
&nbsp;
* 101 キーボード
![IBM_Model_M.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65370/1d455bd3-921d-b25b-a78c-e03e38b9e66b.png "101 Keyboard Layout")

そして私は、vi 系のエディターのヘビーユーザーです。ご存知のように、vi では〔Esc〕キーを多用します[^vimesc]。タイピングの基本に立ち戻って試してみてもらえればわかると思います。左手人差し指を〔F〕(キートップに突起がある) に触れたまま、左手小指で〔Esc〕キーを押すのです。〔Esc〕キーの位置の違いが、左手に相当な負担を与えることがわかると思います。

この負担を軽減するために、〔Esc〕と〔`〕キーを入れ替えます。これまでは xmodmap などでキーマップを変更していました。しかし、前述の仕組みを利用して GUI でポチポチするのがとても素敵に思えてきました。

[^vimesc]: 〔Esc〕キーを使用しない回避策もありますがここでは触れません。

# XKB ファイルを書き換える
修正対象となるファイルは `/usr/share/X11/xkb` 配下のファイルです。これらは全て xkb-data パッケージに属するファイルです。修正差分を[文末](#xkb-data-修正差分)に示します。この修正差分を patch コマンドに流し込んでも構いませんし、手作業で修正しても構いません。

patch コマンドを利用する場合は、あらかじめ xkb-data パッケージのバージョンが 2.41-2ubuntu1.1 であることを確認してください[^xkbv]。バージョンは以下のコマンドで確認できます。空白とタブの違いについても注意してください。

```console
$ dpkg -l xkb-data
```

修正が完了したら、以下のコマンドを実行してください。 `/usr/share/X11/xkb` 配下を書き換えた時はこのコマンドの実行が必要みたいです。

```console
$ sudo dpkg-reconfigure xkb-data
```

書き換えについは Ubuntu の公式ドキュメント「[Custom keyboard layout definitions](https://help.ubuntu.com/community/Custom%20keyboard%20layout%20definitions)」も参考になります。とても[古い](https://help.ubuntu.com/community/Custom%20keyboard%20layout%20definitions?action=info)のでご注意ください。

## 補足説明
* この修正は XKB 的に正しいのかどうかはわかりません。mate-keyboard-properties と連携して期待どうりに動作しているので、これでよしとしています。
* 今回のキーの入れ替えは `/usr/share/X11/xkb/rules/base*` ファイルを修正しなくても機能させることができました。このやり方が正しいのかどうかはわかりません。

[^xkbv]:このバージョンは現時点 (2024-11-14) で最新のものです。

# 動作確認
mate-keyboard-properties を再度起動し、以下に示すパネルを表示させます (上記スクリーンショット参照)。赤枠に示した、「> Escape position」という項目が追加されていると思います。これを開くと「□ Swap Escape and Grave/Tilde」というチェックボックスが表示されるはずです。これにチェックを入れればキーの交換は終わりです。チェックを入れてすぐにキーが入れ替わっているはずです。

![1348.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65370/bc8ae157-bd72-a0f5-2633-79431a2d197c.png "Escape position Menu")

# `/usr/share/X11/xkb` の読みどころ
キー配列の設定は、`/usr/share/X11/xkb` 配下のファイルにのテキストで記述されています。キー配列の変更を試みる方向けに、どのファイルを見ればいいのかメモしておきます。
* 基本となる配列情報は `xkb/symbols/us` に登録されています。日本語配列の場合は `xkb/symbols/jp` がそれに該当します。
* キーの入れ替えや、修飾キーを変更したいのであれば、`xkb/symbols/capslock` や `xkb/symbols/ctrl` が参考になります。いろいろな定義が登録されています。
* 実現しようとする配列変更に類似のものがあるのならば、その定義ファイルに新しい定義を追加してやればいいと思います。見当たらない場合 (今回のような場合)、`xkb/symbols/` に新しくファイルを作成しましょう。 `xkb/symbols/parens` は定義が一つしかなく、新規作成する場合は参考になると思います。
* 以下のファイルは定義のメニューリスト的なものです。
    * `xib/rules/base`
    * `xkb/rules/base.lst`
    * `xkb/rules/base.xml`
* `evdev*` も同様です。冗長な構成になっています。[^redundant]
    * `xkb/rules/evdev`
    * `xkb/rules/evdev.lst`
    * x`kb/rules/evdev.xml`

[^redundant]: `base*`, `evdev*` が冗長な件についての[クレーム例](https://unix.stackexchange.com/questions/186631/how-can-the-xkb-layout-settings-be-simplified)を紹介します。

# 困りごと
みなさんお気づきのように、上記で実現した機能は OS のファイルを直接編集することにより実現しています。OS のアップデート (xkb-data パッケージのアップデート) により、修正内容が上書きされてしまいます。その場合、期待動作が得られる保証はありません。

これに関して、2017 年に提出された[バグ報告 (改善要求)](https://bugs.launchpad.net/ubuntu/+source/xkeyboard-config/+bug/1738630) を見つけました。実質放置状態のように思えます。

今回実現した機能は、ユーザー個人の好みによるところが大きいと思います。できれば、ホームディレクトリ配下のファイルなどで設定したい機能です。「`~/.xkb` 配下にファイルを作成して…(ごにょごにょ)」という記述をネット上で見かけますが、mate-keyboard-properties と連携させたものを見つけることはできませんでした。

需要があるのならアップストリームで取り込んでもらうことはできないかと考えました。活動場所はこちら「[xkeyboard-config](https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config)」のようです。[半年 ROM](https://dic.nicovideo.jp/a/%E5%8D%8A%E5%B9%B4rom) ってみようかと思います。

# まとめ
* XKB と mate-keyboard-properties の連携によりキー配列の変更がいい感じにできます。
* この仕組みを利用したキー配列の変更 (今回は〔Esc〕と〔`〕キーの入れ替え) を紹介しました。試してみたくなった方もいらっしゃるのではないでしょうか。
* 今回実現したキー配列の変更を、個人設定として保存する仕組みが現時点で存在しないことを愚痴りました。

# xkb-data 修正差分
```diff
--- a/usr/share/X11/xkb/symbols/escape	1970-01-01 09:00:00.000000000 +0900
+++ b/usr/share/X11/xkb/symbols/escape	2024-11-13 17:02:02.328461617 +0900
@@ -0,0 +1,5 @@
+partial alphanumeric_keys
+xkb_symbols "swapgrave" {
+    key <ESC>  { [ grave, asciitilde ] };
+    key <TLDE> { [ Escape ], type[group1] = "ONE_LEVEL" };
+};
--- a/usr/share/X11/xkb/rules/base	2024-07-05 18:01:06.000000000 +0900
+++ b/usr/share/X11/xkb/rules/base	2024-11-13 17:03:16.360710274 +0900
@@ -1037,6 +1037,7 @@
   grp:ralt_rshift_toggle	= +group(ralt_rshift_toggle)
   grp:alt_shift_toggle		= +group(alt_shift_toggle)
   grp:alt_shift_toggle_bidir	= +group(alt_shift_toggle_bidir)
+  escape:swapgrave		= +escape(swapgrave)
 
 ! option		=	compat
   grp_led:num		=	+lednum(group_lock)
--- a/usr/share/X11/xkb/rules/evdev	2024-07-05 18:01:06.000000000 +0900
+++ b/usr/share/X11/xkb/rules/evdev	2024-11-13 17:02:02.326461665 +0900
@@ -926,6 +926,7 @@
   grp:ralt_rshift_toggle	= +group(ralt_rshift_toggle)
   grp:alt_shift_toggle		= +group(alt_shift_toggle)
   grp:alt_shift_toggle_bidir	= +group(alt_shift_toggle_bidir)
+  escape:swapgrave		= +escape(swapgrave)
 
 ! option		=	compat
   grp_led:num		=	+lednum(group_lock)
--- a/usr/share/X11/xkb/rules/base.lst	2024-07-05 18:01:06.000000000 +0900
+++ b/usr/share/X11/xkb/rules/base.lst	2024-11-13 17:02:23.241963856 +0900
@@ -1011,3 +1011,4 @@
   terminate:ctrl_alt_bksp Ctrl+Alt+Backspace
   custom               Miscellaneous options
   custom:types         Use user-defined custom XKB types
+  escape:swapgrave     Swap Escape and Grave/Tilde
--- a/usr/share/X11/xkb/rules/evdev.lst	2024-07-05 18:01:06.000000000 +0900
+++ b/usr/share/X11/xkb/rules/evdev.lst	2024-11-13 17:02:02.327461641 +0900
@@ -1011,3 +1011,4 @@
   terminate:ctrl_alt_bksp Ctrl+Alt+Backspace
   custom               Miscellaneous options
   custom:types         Use user-defined custom XKB types
+  escape:swapgrave     Swap Escape and Grave/Tilde
--- a/usr/share/X11/xkb/rules/base.xml	2024-07-05 18:01:06.000000000 +0900
+++ b/usr/share/X11/xkb/rules/base.xml	2024-11-13 17:03:57.733743746 +0900
@@ -8298,6 +8298,19 @@
         </configItem>
       </option>
     </group>
+    <group allowMultipleSelection="true">
+      <!-- Tweaking the position of the "Escape" key -->
+      <configItem>
+        <name>escape</name>
+        <description>Escape position</description>
+      </configItem>
+      <option>
+        <configItem>
+          <name>escape:swapgrave</name>
+          <description>Swap Escape and Grave/Tilde</description>
+        </configItem>
+      </option>
+    </group>
   </optionList>
 
 </xkbConfigRegistry>
--- a/usr/share/X11/xkb/rules/evdev.xml	2024-07-05 18:01:06.000000000 +0900
+++ b/usr/share/X11/xkb/rules/evdev.xml	2024-11-13 17:02:02.328461617 +0900
@@ -8298,6 +8298,19 @@
         </configItem>
       </option>
     </group>
+    <group allowMultipleSelection="true">
+      <!-- Tweaking the position of the "Escape" key -->
+      <configItem>
+        <name>escape</name>
+        <description>Escape position</description>
+      </configItem>
+      <option>
+        <configItem>
+          <name>escape:swapgrave</name>
+          <description>Swap Escape and Grave/Tilde</description>
+        </configItem>
+      </option>
+    </group>
   </optionList>
 
 </xkbConfigRegistry>