xrdp のキーボード設定を解読する

xrdp をサーバに導入して、Windows マシンから接続する環境を構築したところ、キーボードが正しく認識されないトラブルに遭遇した。そのため、xrdp のキーボード設定がどのような手順で行われているのかの解読を試みた。

色々なページで、xrdp を日本語キーボード配列に対応させるため、[/etc/xrdp/km-0411.ini をインストールする方法](http://d.hatena.ne.jp/chofutaro/20140404/1396615665)が紹介されている。ただ、本来なら、この変更は [PR #194](https://github.com/neutrinolabs/xrdp/pull/194) により xrdp 本体に反映済みのはずである。しかし実際には、Debian GNU/Linux の開発版から xrdp パッケージをビルド・インストールしたところ、当該ファイル群は存在しなかった。これらのファイルが存在しない場合には、やはり設定が必要と思われる。

Remote Desktop Protocol の公式な定義内容は、[Microsoft 社によって提示](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/5073f4ed-1e93-45e1-b039-6e30c385867c)されている。特に、[Input Capability Set](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/b3bc76ae-9ee5-454f-b197-ede845ca69cc) が重要で、RDP クライアントはキーボードについて、以下の3種類の情報を送出することになっている。

 * keyboardLayout: [キーボード配列を示す 4byte の符号なし整数](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-vista/cc766503(v=ws.10))（日本語配列は 0x00000411）
 * keyboardType: キーボード種別を示す 4byte の符号なし整数（日本語キーボードは 0x00000007）
 * keyboardSubType:

また、接続元の Windows マシンがどのようにキーボード配列を認識しているかは、以下のレジストリを確認すれば良い。

 * HKEY_CURRENT_USER
   * Keyboard Layout
     * Preload
       * 1 - 0x00000411
       * 2 - 0xe0010411
       * 3 - 0xe0200411

はずなのだが、HHK を接続している Windows10 マシンでも 0x00000411 となっており、どうしてそうなるのか？が良く分からない。

RDP クライアントによって送出されたキーボード種別コードが、xrdp サーバによってどのように解釈されるかという情報は、/etc/xrdp/xrdp_keyboard.ini に記述されている。

```ini
; How this file works:
;   1. load the file and scan each section to find matching "keyboard_type"
;      and "keyboard_subtype" based on the values received from the client.
;      If not found, then jump to default section.
;   2. in the selected section, look for "rdp_layouts" and "layouts_map".
;      Based on the "keylayout" value from the client, find the right x11
;      layout value.
;   3. model/variant are inferred based on the "keyboard_type" and
;      "keyboard_subtype", but they can be overridden.

[default_rdp_layouts]
rdp_layout_jp=0x00000411
rdp_layout_jp=0xe0010411
rdp_layout_jp=0xe0200411
rdp_layout_jp=0xe0210411

[default_layouts_map]
rdp_layout_jp=jp

(snip)
```

Xサーバが、自身のキーボードをどのように認識しているかは、setxkbmap コマンドで確認できる。例えば、[Debian GNU/Linux で動作している Let's Note CF-SZ6](https://qiita.com/tsuchm/items/1b28d1bb7714e3847ac1) で確認してみると、以下のような結果が得られる。

```shell-session
$ setxkbmap -query
rules:      evdev
model:      pc105
layout:     jp
options:    ctrl:nocaps
```

xrdp 上で動作している端末では、以下のような結果が得られる。

```shell-session
$ setxkbmap -query
rules:      base
model:      pc104
layout:     jp,us
variant:    ,
```

以下のように正しくレイアウトを設定すると、少なくとも「全角/半角」キーが正しく認識される。

```shell-session
$ setxkbmap -layout jp
```

なお、正しく認識されているかどうかは、xev コマンドで確認できる。

ここまで確認すると、とりあえず X のレイヤーまでのキーボード配列は正しくなっているはずである。加えて、Fcitx などの GUI フレームワークレベルの入力メソッドの設定が正しいかを確認する必要がある。Fcitx の場合、以下のように正しいキーボードが最上位に設定されていなければならない。この設定が間違っていると、X のレイヤーでは正しくキーシンボルが送出されているにも関わらず、Fcitx によって違うシンボルに変換されて、異なる文字が入力される現象が起きる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79826/b97347d0-2bb5-5716-0d89-e5141695bb04.png)

最後に、Fcitx の起動時に、以下のようなエラーが表示されることがある。

![mozc-error-message.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79826/bea90e4d-44b7-cd19-8c57-f7861fac2415.png)

この場合も、Fcitx の起動が不完全で、正しくキーボードが読み取られないことがあるようだ。以下の2つのコマンドを実行して、再ログインすれば回避できる。

```shell-session
$ rm -f ~/.mozc/.server.lock
$ rm -f ~/.mozc/.session.ipc
```

将来的には、[TLS接続の設定](https://web.archive.org/web/20160804223851/https://xrdp.vmeta.jp/%E3%83%8E%E3%83%BC%E3%83%88/TLS%E6%8E%A5%E7%B6%9A)も必要。