備忘録的なもの

XKB の設定で capslock を ctrl として使えるようにする

CapsLock を Ctrl として使える様にするための設定方法を変えたのでそのメモ。

自分の場合は入れ替えでは無く単純に CapsLock を Ctrl に置き換えたい派。

まとめ

以下コマンドで設定した。

localectl --no-convert set-x11-keymap us pc104 "" ctrl:nocaps

背景

もともとは CapsLock を Ctrl として動作させるため、 .Xmodmap で以下の様に設定して使っていた。

clear lock
clear control
keycode 66 = Control_L
add control = Control_L Control_R

ただ、自分はキーボードを USB 切替器経由で使っている(PC2台で共有している)のだが、 接続先PCを切り替えたタイミングで上記の設定が効かなくなり若干不便していた。

軽く調べたところ XKB (X KeyBoard extention) の設定を変更する形で解消しそうだったので、その方法で再設定した。

設定

設定は ArchWiki を参考にしてるので、詳細はそちらを見てもらうのが良さげ。
やったこと自体は冒頭のコマンド一発という話ではあるが、自分で忘れそうと思った部分や関連して調べたことなどをメモとして残す。

まずコマンドの使い方としてはArchWiki にある通りこう

localectl [--no-convert] set-x11-keymap layout [model [variant [options]]]

それぞれのパラメータの補足としては以下

  • –no-convert
    • これを指定するとコンソール環境には反映されない、 X 環境にのみ設定したい場合はこのオプションを指定する
    • コンソールのキーマップを設定したい場合は localectl set-keymap サブコマンドが別途存在する
      • ただこっちはレイアウト(JIS配列とかUS配列とか)くらいしか設定できなさそうではあった
        • 今回の ctrl:nocaps のように個別のキーの設定みたいなことはできなさそう
  • layout
    • localectl list-x11-keymap-layouts からの選択式
    • 眺めれば分かるがレイアウトと言いつつほぼ言語指定(国コード)
      • custom と言うのもあるらしい(自作キーボードとかで使うんだろうか)
  • model
    • localectl list-x11-keymap-models からの選択式
    • 一般的な配列のUSBキーボードを使ってる場合、日本語配列なら pc105 、英語配列なら pc104 辺りにしておけば良さげ
    • ラップトップの場合、適切なモデルを選択すれば追加キー(輝度調整とかメディアキーのことだろうか)が使えるようになるらしい
      • ( DELL のラップトップで pc104 で設定したが、輝度調整とかのキーも問題無く効いてるので何か理解が間違ってるかもしれない)
  • variant
    • localectl list-x11-keymap-variants からの選択式
    • 同じ言語でもキーのレイアウトに差がある場合があって、それらを variant と呼ぶっぽい
      • ArchWiki の方にも書いてある qwerty 、 dvorak だったり、他にも mac 用キーボードだったり
    • model とどう違う概念なのかはあんまりピンと来てない
    • とりあえずデフォルト指定 "" にしておいて、使ってて変なところが見つかれば考えるくらいで良さそう
  • options

各パラメータの選択肢は上記の通りコマンドでも確認できるが、 /usr/share/X11/xkb/rules/base.lst に説明付きでリストされているので、 最初からそっちを見つつ選ぶでも良さげ。

ということで、記事の冒頭にあるコマンドを実行すると /etc/X11/xorg.conf.d/00-keyboard.conf に以下のようなファイルが作られ、再起動後に機能するようになる。

# Written by systemd-localed(8), read by systemd-localed and Xorg. It's
# probably wise not to edit this file manually. Use localectl(1) to
# instruct systemd-localed to update it.
Section "InputClass"
        Identifier "system-keyboard"
        MatchIsKeyboard "on"
        Option "XkbLayout" "us"
        Option "XkbModel" "pc104"
        Option "XkbOptions" "ctrl:nocaps"
EndSection

確認

設定が効いてるかどうかは実際に CapsLock キー使えば分かるという話ではあるが、一応 xev というコマンドでも確認できる。

xev ( X EVent の略?) は自身が認識した X のイベントを表示するアプリケーションで、 キー入力であれば押した時、離した時、GUI ウィンドウ上でのカーソルの移動とかも逐一表示する。

まず自分が使っているキーボードの場合、左 Ctrl を入力した場合はこんな感じ。

KeyPress event, serial 37, synthetic NO, window 0x4a00001,
    root 0x559, subw 0x0, time 17575768, (-94,290), root:(1737,1309),
    state 0x10, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyRelease event, serial 37, synthetic NO, window 0x4a00001,
    root 0x559, subw 0x0, time 17575894, (-94,290), root:(1737,1309),
    state 0x14, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XFilterEvent returns: False

keycode 37 が Ctrl キーに対応する keycode で、 keysym 0xffe3, Contrl_L がそれに紐付いた keysym 。
また、 Ctrl 含む修飾キーの類が押されていたり CapsLock が効いてるような場合は state が変わる。 (上の例だと KeyPress イベントで state 0x10 だったのが KeyRelease 時には state 0x14 になっている)

で、今回の設定後に Caps Lock ( keycode 66 )を押した時の表示が以下。
keysym が上記と同じ keysym 0xffe3, Control_L になっていて、 state も Ctrl を押した時と同じ動きをしているのが確認できる。
(USB切替器で切り替えて設定が維持されているのも確認した)

KeyPress event, serial 36, synthetic NO, window 0x3600001,
    root 0x559, subw 0x0, time 20663183, (432,-158), root:(2263,861),
    state 0x10, keycode 66 (keysym 0xffe3, Control_L), same_screen YES,
    XKeysymToKeycode returns keycode: 37
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyRelease event, serial 36, synthetic NO, window 0x3600001,
    root 0x559, subw 0x0, time 20663261, (432,-158), root:(2263,861),
    state 0x14, keycode 66 (keysym 0xffe3, Control_L), same_screen YES,
    XKeysymToKeycode returns keycode: 37
    XLookupString gives 0 bytes: 
    XFilterEvent returns: False

ちなみに設定前の Caps Lock は以下のような感じだった。

KeyPress event, serial 37, synthetic NO, window 0x4a00001,
    root 0x559, subw 0x0, time 17261640, (-1013,822), root:(818,1841),
    state 0x10, keycode 66 (keysym 0xffe5, Caps_Lock), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyRelease event, serial 37, synthetic NO, window 0x4a00001,
    root 0x559, subw 0x0, time 17261750, (-1013,822), root:(818,1841),
    state 0x12, keycode 66 (keysym 0xffe5, Caps_Lock), same_screen YES,
    XLookupString gives 0 bytes: 
    XFilterEvent returns: False

あと長くなるので xev の出力は省略するが、 a -> CapsLock -> a -> CapsLock -> a とかやると state の動きが ctrl や shift と違うのがよく分かる。

その他の設定方法

今回使った方法以外にも設定方法としては色々あり、調べた感じ少なくとも以下の方法があることは認識した。

  1. .Xmodmap で設定するパターン
    • もともと使っていたやつ
    • xmodmap という XKB とは独立した仕組みで X におけるキーマップを変更する
    • システムなりユーザなりの xinitrc の中で xmodmap ~/.Xmodmap みたいな形で呼ばれて反映されている
  2. X サーバの設定ファイルを弄るパターン
    • 今回使ったやつ
    • キーボードの入力管理する XKB の設定を変更する形
    • /etc/X11/xorg.conf.d/ にファイルを直接作る派と localectl で生成する派が居る模様
  3. 実行中の XKB の設定を変更するパターン
    • コマンドを使って実行中の XKB の設定設定を変更する形
    • setxkbmap を使ってオプションを指定する形で変更する方法と、 xkbcomp を使ってキーマップをダンプ/ロードする方法があるっぽい
      • ただ ArchWiki の記載を見る限り xkbcomp でのキーマップを弄る方法は非推奨っぽい
    • どちらも実行中の XKB に対する操作で実行したセッション中しか効かないので、永続化させたい場合は .xinitrc .profile 辺りに追記する
  4. GNOME の設定を使うパターン
    • デスクトップ環境として GNOME を使っている場合 dconf の中で xkb-options というパラメータを持っているので、GUI もしくは gsettings dconf コマンドを使って指定する
    • XKBOPTIONS という環境変数での指定もできるっぽい
  5. dumpkeys , loadkeys を使うパターン
    • カーネルで持ってる keymap のテーブルを変更する形?(理解が怪しい)
    • 見かけた限りではコンソール環境でも効いてほしいって人が使ってた印象

2, 3, 4 に関しては設定方法が違うだけで XKB に手を加えるモノなのでまとめても良い気はするが、 何にせよ色んな設定方法があるなぁという印象。

ユーザ設定( dotfiles )として管理するなら 3 の方法でも良い気はしたが、 使っているキーボード(ハードウェア構成)に依存する設定というイメージでシステム設定かな、ということで今回は 2 の方法を取った。

参考リンク