Ubuntu でキーマップの変更

概要

Linux では古くから、xmodmap, xkbcomp, setxkbmap が有る。しかし、これは X11 や X.Org 用のツールなので、Ubuntu 21.04 で標準になる Wayland の環境だと動作しなかったり、アプリによって動きが変わる。そこで X.Org/Wayland 両方で対応できる方法を調べてみた

結果としては、udev なら両環境で対応できる

あたりを参考にした

ただしこの方法は、ユーザーごとの設定は出来ず、自分が管理する PC でのみ有効

半角/全角Esc に追加

まず、良く 半角/全角 (他には E/J 等の刻印) を Esc への割り当ては、入れ替えでなく単純な追加、つまり 半角/全角Esc に追加するなら、Gnome の設定に有るので、それを使えば良い。まず現在の設定を確認

$ gsettings get org.gnome.desktop.input-sources xkb-options

確認したら、それに 'japan:hztg_escape' を (複数なら , 区切りで) 追加する。例えば

  1. 半角/全角Esc に追加
  2. Alt+Ctrl+Back Space に X サーバーの終了
  3. Windows と同じく、Casp Lock の ON/OFF を Shift 押しながらで動作させる

の内私は 2, 3 は設定済みだったので、1 を追加する形で次のようなる

$ gsettings set org.gnome.desktop.input-sources xkb-options "['japan:hztg_escape', 'terminate:ctrl_alt_bksp', 'shift:both_capslock']"

ここで [ ] 内の順序は問われない

udev での設定

ハードウェアを調べる

: 部が省略部分だが、以下が実行/出力例

$ cat /proc/bus/input/devices : I: Bus=0011 Vendor=0001 Product=0001 Version=ab41 N: Name="AT Translated Set 2 keyboard" P: Phys=isa0060/serio0/input0 S: Sysfs=/devices/platform/i8042/serio0/input/input3 U: Uniq= H: Handlers=sysrq kbd event3 leds : I: Bus=0003 Vendor=0853 Product=011d Version=0111 N: Name="Topre Corporation Realforce 108U" P: Phys=usb-0000:00:14.0-3.1/input0 S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.1/1-3.1:1.0/0003:0853:011D.0001/input/input13 U: Uniq= H: Handlers=sysrq kbd event6 leds :

H: Handlers=sysrq kbd … の出力が有るパートがキーボードのもよう

私の場合は、前者がノート PC 付属のキーボードで、後者が USB キーボードで、設定に必要なのは

I: Bus=0003 Vendor=0853 Product=011d Version=0111

の部分だが、ノート PC 付属のキーボード AT キーボードとして統一して設定できるので、私の場合だと前者のハードウェア情報は使わずに済む

また USB 機器は I: Bus=0003 部分は共通

キーが押された時の情報を調べる

evtest を使う

無い場合は

$ sudo apt install -y evtest

次に実行して、キーを調べたいハードウェアを選択する。下記は USB キーボードの「Topre Corporation Realforce 108U」の選択例、: 部は省略部分

$ sudo evtest : /dev/input/event3: AT Translated Set 2 keyboard /dev/input/event4: Video Bus /dev/input/event5: SynPS/2 Synaptics TouchPad /dev/input/event6: Topre Corporation Realforce 108U : Select the device event number [0-16]: 6

以下は USB キーボードで半角/全角, Esc と、実際に私が変更したい 変換 (もしくは HENKAN 等と刻印) をタイプした例

Event: time 1617356978.040267, -------------- SYN_REPORT ------------ Event: time 1617356980.744286, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70035 Event: time 1617356980.744286, type 1 (EV_KEY), code 41 (KEY_GRAVE), value 1 Event: time 1617356980.744286, -------------- SYN_REPORT ------------ Event: time 1617356981.800108, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70029 Event: time 1617356981.800108, type 1 (EV_KEY), code 1 (KEY_ESC), value 1 Event: time 1617356981.800108, -------------- SYN_REPORT ------------ Event: time 1617356987.264067, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7008a Event: time 1617356987.264067, type 1 (EV_KEY), code 14 (KEY_HENKAN), value 1

設定で使うことになるのは、value に続く値で上記なら 70035, 70029, 7008a

ここで注意が必要なのは

  • 同じキーでもノート PC 付属のキーボードと USB キーボードでは value の値が違うので、それぞれ別々に調べる必要が有る
  • キーを押している間は出力が有り続けるので、よほど速くタイプしないと複数が一度に出力される

設定ファイルの記述

  1. $ sudo vim /etc/udev/hwdb.d/90-Henkan2BS-keyboard.hwdb

    等で適当なファイルを開く
    • vim の部分は自分の使い慣れたエディタで
    • ファイル名先頭の 90- の数字部分は幾つでも良いが、他の設定から上書きされないように、大きな数字にしている
    • ファイル名の内、先頭の数字と拡張子の hwdb 以外は自由な名前をつければ良い
    • # 以降はコメントとして利用できる
  2. 開いたファイルで
    1. 変更したいハードウェア情報
    2. 変更したいキー (複数指定可能)
    をセットで記述していく
    1. 変更したいへーどウェア情報の書き方
      • ノート PC 付属のキーボードなど全ての AT キーボードにマッチさせたいなら
        evdev:atkbd:dmi:bvn*:bvr*:bd*:svn*:pn*:pvr*
      • USB キーボードは、次がマッチと有るが動作しなかった
        keyboard:usb:v*p*
      • 一般的な入力装置は、
        evdev:input:b<bus_id>v<vender_id>p<product_id>*
        で表され、<bus_id>, <vender_id>, <product_id> はハードウェアを調べるで調べた
        I: Bus=0003 Vendor=0853 Product=011d Version=0111
        といった出力に対応し、上記の場合なら
        <bus_id>
        0003
        <vender_id>
        0853
        <product_id>
        011d
        なので、次の様になる
        evdev:input:b0003v0853p011d*
    2. 変更したいキーの書き方
      • 書き方の基本は
        KEYBOARD_KEY_<value>=<key_code>
        キーが押された時の情報を調べる で調べた記載をする
        Event: time 1617356978.040267, -------------- SYN_REPORT ------------ Event: time 1617356980.744286, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70035 Event: time 1617356980.744286, type 1 (EV_KEY), code 41 (KEY_GRAVE), value 1 Event: time 1617356980.744286, -------------- SYN_REPORT ------------ Event: time 1617356981.800108, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70029 Event: time 1617356981.800108, type 1 (EV_KEY), code 1 (KEY_ESC), value 1
        から USB キーボードの 半角/全角, Esc を入れ替えるなら、
        • 半角/全角Esc
        • Esc半角/全角
        の変更となる
        変更先のキーは、全て小文字で https://hal.freedesktop.org/quirk/quirk-keymap-list.txt に使えるキー一覧に有り次の様になる
        KEYBOARD_KEY_70035=esc KEYBOARD_KEY_70029=zenkakuhankaku
    3. A, B を纏めると
      evdev:input:b0003v0853p011* KEYBOARD_KEY_70035=esc KEYBOARD_KEY_70029=zenkakuhankaku

      ただ私が使っている USB キーボードは <product_id> を全て書くとマッチしないので、最後の d を減らして設定した

      またここまでは、USB キーボードの設定例だけなので、ノート PC 付属のキーボードの様に、他にも設定が必要なキーボードが有る場合は、その分も続けて記述する

設定を反映させる

  1. 設定をハードウェア情報データベースを更新
  2. ハードウェア情報データベースをシステムに反映させる

の 2 段階が必要で次の通り

$ sudo systemd-hwdb update && sudo udevadm trigger

設定が認識されているか確認

udevadm info /dev/input/by-path/* | grep KEYBOARD_KEY

私のように Product_ID を全て書くと認識されなかった時は

E KEYBOARD_KEY_70035=esc E KEYBOARD_KEY_70029=zenkakuhankaku

といった出力が無いので設定からやり直す

纏めとしての私のシェル・スクリプト

私が実際に行った変更は

  • 半角/全角, Esc を入れ替えはせず、半角/全角 を単純に Esc を入れ替えはせず、半角/全角Esc に追加
  • 変換 を単純に Back Space に追加
  • ノート PC 付属、USB 両方のキーボード設定
なのでコメントも含めて次のシェル・スクリプトになる
# ・E/J を Esc に追加 gsettings get org.gnome.desktop.input-sources xkb-options | sed -E 's/.*\[(.*)\]/\1/' | awk -v FS='' '{ # 追加する設定 options[0] = "'\''japan:hztg_escape'\''" uniq["'\''japan:hztg_escape'\''"] = 1 # 以下同様に追加したい設定を書いていく j = 2 # 既存の設定を取り出し for (i = 1; i <= NF; i++){ if( end == "" && ( $i == "," || $i == " " ) ){ ; } else if( end == $i ){ option = " " option " " sub(/^ +/, "", option) sub(/ +$/, "", option) if ( option ~ /"/ )option = "\"" option "\"" else option = "'\''" option "'\''" if( uniq[option]++ == 0 ){# 追加設定する分は改めて配列に加えない options[j] = option j++ } option = "" end = "" } else if( "'\''" == $i )end = "'\''" else if( "\"" == $i )end = "\"" else option = option $i } } END{ options_s = "" for(i = 0; i < j; i ++){ options_s = options_s "," options[i] } print "\"[" substr(options_s, 2, length(options_s) - 1) "]\"" }' | xargs -I{} gsettings set org.gnome.desktop.input-sources xkb-options "{}" # Henkan を Back Space に追加 sudo sudo tee /etc/udev/hwdb.d/90-Henkan2BS-keyboard.hwdb <<_EOF_ # keymap Henkan to BackSpace # AT keyboard evdev:atkbd:dmi:bvn*:bvr*:bd*:svn*:pn*:pvr* KEYBOARD_KEY_79=backspace # Topre Corporation Realforce 108U evdev:input:b0003v0853p011* KEYBOARD_KEY_7008a=backspace _EOF_ sudo systemd-hwdb update && sudo udevadm trigger