Xmodmapからhwdb + xkbへ
新しい環境をセットアップするたびに問題になる「X.orgのままにするか、Waylandに移行するか」問題。実家に帰省中にやることがなかったので、その作業を進めてみた。
設定したいキー読み替え
物理的に押すキー | 機能してほしいキー |
---|---|
CapsLock | Escape |
Right Alt | 変換 |
Right Shift | 無変換 |
PgUp | Home |
PgDown | End |
: |
; |
; |
: |
- NeoVimを使う際にEscは連打したいので、Capsに割り当てる。
- 日本語切り替えにはMozc側で「変換で日本語入力ON」、「変換無変換で日本語入力OFF」としている(日本語キーボードを使っていたなごり)ので、変わりにR AltとRシフトを使う。
- XPS13はカーソルキーの斜め上にPageUp/Downが付いているが、Home/Endとして使う。
- コロンはシフトなしで押せるようにする。
という状況である。.Xmodmap
は
! vi: set ft=xmodmap :
clear lock
keysym Caps_Lock = Escape
remove mod1 = Alt_R
keysym Alt_R = Henkan_Mode
remove shift = Shift_R
keysym Shift_R = Muhenkan
! 47 -> : ;
keycode 47 = colon semicolon
!PageUp -> Home
keycode 112 = Home Home Home Home
!PageDown -> End
keycode 117 = End End End End
という感じであった。これと同等の設定をWaylandで実現できればいい。
hwdb
基本的にスキャンコードをキーコードにマップ - ArchWikiを参考に設定する。
こいつはキーボードのボタン自体のコードを書き換えるやつである。CapsをEscやCtrlにするなどボタンのラベルを変えたり、位置をまるごと逆にする場合などは適切だが、Modキーとのコンビネーションについてはこいつでは扱えない。例えばシフトキーの状態で入力が変化するコロンとセミコロンを逆にしたりはできない。
アプリケーションによってはキーコードを直接拾うものもあるので、こちらでいじれるものはできるだけこっちでやる。
キーコードは以下のように調べる。
$ ls -l /dev/input/by-path/* | grep kbd
lrwxrwxrwx 1 root root 9 9月 25 03:48 /dev/input/by-path/platform-i8042-serio-0-event-kbd -> ../event4
で番号を調べて、evtest
でイベントを調べる。
# sudo evtest /dev/input/event4
(**中略**)
Event: time 1664045570.619893, -------------- SYN_REPORT ------------
Event: time 1664045570.653465, type 4 (EV_MSC), code 4 (MSC_SCAN), value 3a
Event: time 1664045570.653465, type 1 (EV_KEY), code 1 (KEY_ESC), value 2
Event: time 1664045570.653465, -------------- SYN_REPORT ------------
Event: time 1664045570.682258, type 4 (EV_MSC), code 4 (MSC_SCAN), value 3a
Event: time 1664045570.682258, type 1 (EV_KEY), code 1 (KEY_ESC), value 2
Event: time 1664045570.682258, -------------- SYN_REPORT ------------
Event: time 1664045570.715827, type 4 (EV_MSC), code 4 (MSC_SCAN), value 3a
Event: time 1664045570.715827, type 1 (EV_KEY), code 1 (KEY_ESC), value 2
Event: time 1664045570.715827, -------------- SYN_REPORT ------------
これは変更後の出力だが、例えばCapsLockを押すとこのような出力になり、CapsLockのキーコードはvalue 3a
であることがわかる。そして実際にcode 1
のEscとして機能していることがわかる。
設定するには/etc/udev/hwdb.d/*.hwdb
という感じでファイルを作る。自分の場合はXPS 13 9305を使っているので、/etc/udev/hwdb.d/10-xps.hwdb
とした。
evdev:atkbd:dmi:*
KEYBOARD_KEY_3a=esc
KEYBOARD_KEY_36=muhenkan
KEYBOARD_KEY_b8=henkan
KEYBOARD_KEY_c9=home
KEYBOARD_KEY_d1=end
一応evdev:
のセクションでキーボードのモデルの指定できるが、今回はatkbd:dmi:*
であらゆるATキーボードを対象としている。
ちなみに新しいキーコードは、
$ sed -n '/KEY_/{s/.*KEY_\([A-Za-z0-9_]\+\).*/\L\1/g;p}' /usr/include/linux/input-event-codes.h | fzf
といった感じに調べることができる。
XKB
これでレイアウトを指定する。JPキーボードからUSキーボードに移行した際に入力がおかしくなるのを経験すると思うが、レイアウト指定がずれることによって起こる齟齬である。
このレイアウト設定自体をカスタマイズすることで好きなキー割当を実現できる。
デフォルトで様々なレイアウトや固定の読み替えオプション(Caps as Ctrl)が定義されており、デフォルトレイアウトにそれらを組み合わせることもできるが、今回は特殊な事例なのでus
レイアウトやjp
レイアウトなどとともに提供される、custom
レイアウトをいじることにする。
:::message "XKBレイアウトとfcitx5組み込みのレイアウトについて"
実際に使用するレイアウトはfcitx5で設定するが、そのレイアウトは$XDG_CONFIG_HOME/fcitx5/conf/cached_layouts
としてキャッシュされている。そしてこのレイアウトはおそらく/usr/share/X11/xkb/rules/base.lst
などから読み取られている。
しかし単純にbase.lst
の方にエントリーを追加するだけではキャッシュ側に反映されなかった。validなレイアウトを追加には他にも記述すべきファイルがあるはずだが、それを調べる手間もあるし、何より編集するファイル数が増え、手続きが煩雑となるはずである。
なので今回は元から用意されているcustom
レイアウトを流用する。
:::
/usr/share/X11/xkb/symbols/custom
というファイルを作って以下のように記述する。
default partial alphanumeric_keys modifier_keys
xkb_symbols "basic" {
include "us(basic)"
name[Group1]= "CUSTOM";
key <AC10> {[ colon, semicolon ]};
// hwdbを使わずここで設定することも可能である
// key <CAPS> {[ Escape ]};
// key <RALT> {[ Henkan_Mode, Henkan_Mode ]};
// key <RTSH> {[ Muhenkan ]};
// key <UP> {[ Home, Home, Home, Home ] };
// key <DOWN> {[ End, End, End, End ] };
};
xkb_symbols
セクションではinclude "us(basic)"
とった形で、他のシンボル定義をインクルードできる。基本的なUS配列をコピーした上で、上記のコロンとセミコロンの入れ替えを定義する。
fcitxでレイアウト指定する
:::figure "「A user-defined custom Layout」というエントリがcustomのそれ" :::
ここでcustom
を指定すれば設定完了。
あとがき
「なんだれ面倒くせえなあ」と思っていたが、キーボードの入力は
物理ボタン→キーコード→文字の対応
という2つのフェーズがあることがわかる。hwdbは1つ目の矢印、xkbは2つ目の矢印を制御するものだと思えば、それぞれどちらも必要であることがわかる。
この調子で自宅のデスクトップも移行したいが、Waylandだとデスクトップセッションが起動すらしなかった。NVIDIA関連に落とし穴が多そうなのでまた時間があるときにゆっくりやろうと思う。