Ubuntu で「変換」キーを Shift にする話 (xkb + dconf)

一月強の間日本を留守にしていたら、デスクトップの Ubuntu が起動しなくなっていた。
出発前から、フリーズが頻発していて、何かおかしかったので、覚悟はしていたが、思ったよりも復旧作業が大変で、ほぼ丸三日かけて、一昨日ようやく完了した。
その際、今まで xmodmap を用いて設定していたキーの再設定の挙動が不安定になったので、xkb をいじってみることにした。
そのメモ。
以下のサイトを参考にしました;

XKBの設定ファイルを直接編集してキーボードレイアウトをカスタマイズする - Qiita
An Unreliable Guide to XKB Configuration

なお、本記事は筆者の当時の環境を前提に書いている個人的なメモなので、他の環境でどうなのかは知りません。
万が一真似するとしても、自己責任でお願いします。
Ubuntu のバージョンだけ一応書いておくと、Ubuntu 16.04 です。



小手調べ:「Caps-Lock」を「左 Ctrl] にする

「変換」キーの話をする前に、簡単なものから。
「Caps-Lock」を「左 Ctrl」にするのは、得に何も考えずに、次のコマンドをたたけば良い:

$ dconf write /org/gnome/desktop/input-sources/xkb-options "['ctrl:nocaps']"

このコマンドは、dconf というものを通じて、xkb に「Caps-Lock」を「左 Ctrl」にせよ、というオプションをわたしてくれる。
自分は dconf の仕組みがよくわかっていないんだけれど、Windows でいうところのレジストリみたいなものらしい*1
自分が知っている限りでは

  • 設定ファイルは、(local なものは) $HOME/.config/dconf/user にある (system global なものは別の場所)
  • 値はキーによって管理されている
  • キーは階層構造の中に格納されている

これはバイナリファイルなので、直接は編集できないのだが、それを編集するためのコマンドラインツールが dconf といいうこと。
他にも gsettings でも設定できるが、違いがよくわからない。
また、dconf-editor という GUI ツールもあって、これは以下のコマンドでインストールできる (Ubuntu 16.04 の場合):

$ sudo apt install dconf-editor

新たにレポジトリとかを追加しなくてよいのが非常に好ましい。
こちらを使うと、階層構造がより直感的に理解できるようになる。
例えば、上で dconf を用いて行った設定は、dconf-editor では、ツリーを org→gnome→desktop→input-sources と辿ると、「xkb-options」というキーが見つかるので、それをダブルクリックして編集することでもできる。

なお、これらの設定は、dconf に頼らなくても X の設定を直接いじってもできる。
ただ、こうしてしまうと Gnome とか Unity とかの設定と競合するかも知れないと思い、今回は dconf 経由で xkb を設定する方法を考えることにする。

xkb-options に書けるもの

さて、dconf の中にあるキー「xkb-options」に書けるオプションは、勿論 xkb が認識するものでなければならない。
その一覧を知るためには、xkb の現在の設定を見ることがヒントになる:

$ setxkbmap -print -verbose 10
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:nocaps,
Trying to build keymap using the following components:
keycodes:   evdev+aliases(qwerty)
types:      complete
compat:     complete
symbols:    pc+jp+us:2+inet(evdev)+ctrl(nocaps)+jphenk(rshift)+jpmuhen(lshift)
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(nocaps)"	};
	xkb_geometry  { include "pc(pc105)"	};
};

「options」に上で設定した「ctrl:nocaps」が確認できるのと、xkb_keymap の xkb_symbols の末尾に「ctrl(nocaps)」も確認できる。
参考文献によると、これらの値は /usr/share/X11/xkb/rules/evdev というファイルの記述に則って設定される:

$ cat /usr/share/X11/xkb/rules/evdev
...
! option	=	symbols
...
  caps:ctrl_modifier	=	+capslock(ctrl_modifier)
  ctrl:nocaps		=	+ctrl(nocaps)
  ctrl:lctrl_meta	=	+ctrl(lctrl_meta)
...

直感的には、「ctrl:nocaps」というオプションが渡された時「xkb_symbols」に「ctrl(nocaps)」を加えなさい、というように読める。
では、この「ctrl(nocaps)」というものの実体がどこにあるかといえば、/usr/share/X11/xkb/symbols/ 以下のファイルに書かれているらしい。
例えば、このフォルダには「ctrl」というファイルがあり、それは以下のようになっている:

// Eliminate CapsLock, making it another Ctrl.
partial modifier_keys
xkb_symbols "nocaps" {
    replace key <CAPS> { [ Control_L, Control_L ] };
    modifier_map  Control { <CAPS>, <LCTL> };
};
...

ここまで来れば、xkb に渡すオプションを自分で追加する方法は何となく推測できる。
そうすれば、dconf を通じて好きなようにキー配置をいじれるじゃないか。

「変換」キーを「右 Shift」にする

それでは、設定ファイルを書くのだが、そもそも書式がわからない。
しかし、とりあえずはファイル「ctrl」とか「caps」とかを真似ておけばよかろう。
"<CAPS>" が「Caps-Lock」キーを表わしているようなので、「変換」キーを表わす記号を調べれば良い。
このあたりは、同フォルダに「jp」というファイルがあり、その中に以下の記述がある:

...
    key <NFER> { [ Muhenkan		] };

    key <XFER> {
	type[Group1]="PC_ALT_LEVEL2",
	symbols[Group1]= [ Henkan, Mode_switch ]
    };
...

また、「inet」というファイルにも次の記述がある:

...
    key <HKTG>   {      [ Hiragana_Katakana     ]       };
    key <HENK>   {      [ Henkan                ]       };
    key <MUHE>   {      [ Muhenkan              ]       };
...

setxkbmap -print で見ると「inet」の方が後に読み込まれており、xkb は後に読んだ方を優先するので、ここでは "<HENK>" を採用。
ファイル /usr/share/X11/xkb/symbols/jphenk を作成して、以下を書き込む:

partial modifier_keys
xkb_symbols "rshift" {
    replace key <HENK> { [ Shift_R, Shift_R ] };
    modifier_map Shift { <HENK>, <RFSH> };
};

さらに、これを xkb に有効な設定であることを伝えるために、以下の二行を /usr/share/X11/xkb/rules/evdev の末尾に以下を追加*2

! option = symbols
  jphenk:rshift  = +jphenk(rshift)

これで、xkb は「jphenk:rshift」をオプションとして認識してくれる。

$ dconf write /org/gnome/desktop/input-sources/xkb-options "['ctrl:nocaps', 'jphenk:rshift']"

まとめ

  • オプションの一覧は、setxkbmap -print -verbose 10 とした時の rules の項にあるファイルにあり、そこに追加することで、自分でオプションを定義できる!
  • オプションの実体は、/usr/share/X11/xkb/symbols/ 以下に適切な書式で記述する。

今回の試行錯誤の成果物を github に上げておきます。
https://github.com/Junology/dotfiles/tree/master/xkb

*1:もっとも、Windows とかいうブラックボックスで組み上げたような OS で例えられたところで、特にわかるようになったりはしないのだけれど

*2:ファイルの先頭にある警告は見なかったことにする