筆者について
FreeBSDを通じてOSSにささかな貢献を。
- 日本xrdpユーザ会発起人
- xrdp developer
- FreeBSD developer
OSS活動をご支援いただける方を募集しています
2015-01-28 xrdp がキー配列を適用するしくみ
■ xrdp がキー配列を適用するしくみ
この記事を書いた時点でのキー配列適用のしくみをメモ。情報は不正確である可能性があります。また、VNC をバックエンドに使う機能は将来削除される予定であるため、VNC を使った場合の挙動には触れません。
本記事中では RDP のプロトコルと各実装を区別するため、明確にプロトコルを表すときは頭痛が痛くても RDP プロトコルと呼びます。Windows に付属する RDP クライアントソフトウェアのことは、その実行ファイルの名前を取って mstsc または mstsc.exe と呼びます。どの実装か特定せずにクライアントソフトウェアを表すときは、クライアントまたは RDP クライアント と呼びます。
xrdp がキー配列を適用する流れは大まかに次のような流れになっていて、本記事でもこの通りに順を追ってメモします。
- クライアントから送られてくるキーボード種別情報を読み込む
- 対応するキー配列のキーマップファイルを読み込む
- X11 にキー配列を適用する
クライアントからキー配列情報の受け取り
RDP プロトコルにはクライアントからサーバへクライアントのキーボード種別を送信するしくみがあり、xrdp はまずクライアントから送られてきたキーボード種別情報を受け取ります。キーボード種別は 0xe0210411 といった16進数の値で送られます。 クライアントから受け取ったクライアント情報は xrdp_client_info (common/xrdp_client_info.h)という構造体に格納されていて、キーボード種別は layout という int 型の変数に入っています。
実際にどの部分のコードでキー配列情報を受け取って xrdp_client_info に格納しているのかは調査中。
キーマップファイルの読み込み
次に、対応するキー配列のキーマップファイルを読み込みます。キーマップファイルは通常 /etc/xrdp 以下に km-*.ini という名前で存在します。キーマップファイルの仕様は genkeymap/readme.txt に書かれています。
キーマップファイルの各行は以下の様になっていて、最初の38は X11 のキーのスキャンコードです。2番目の97は KeySym 値です。3番目の97は Unicode のコード番号です。値はすべて10進数です。
[noshift] Key38=97:97
上の例でいくと、スキャンコード38は A キー、KeySym 値も A の値、そして Unicode で a の文字コード番号である97が定義されています。つまり、A キーを単独で押すと小文字の a が出ると定義されています。これをキーの数だけ、同時に押す modifier キー (Shift,Ctrl,Alt など)の数だけ繰り替えして定義されているのがキーマップファイルです。
modifier キーを併用する部分を以下の様に書きかえると、Shift + A で小文字の z になるという定義になります。
[shift] Key38=122:122
このようにキーマップファイルを書き換えることで、A を単独で押すと小文字の a だが、Shift と一緒に押すと小文字の z になるという風に、自在に定義することができます。もちろん実際には、Shift + A は大文字の A となるように定義されています。
キーマップファイルの仕様の話に脱線しましたが、実際にキーマップファイルをパースして読み込んでいるのは xrdp/lang.c:224 あたりです。
X11 側にキー配列を適用する
最後に、実際にクライアント側から送られてきたキー配列を X11 に適用し、デスクトップ環境のキー配列が変更されるのがこの部分です。現在のxrdp では xrdp_keyboard.ini という設定ファイルが導入されています。クライアントから送られてきたキー配列が、X11 上でどの model, layout, variant に対応するかを記述するファイルです。
バックエンドに x11rdp と xorg-driver-rdp (仮称) のどちらを使っているかによって実際に走る処理のコードは違いますが、xorg-driver-rdp は調査中なので X11rdp のみ触れます。
- X11rdp のキー配列適用部分の処理
- xorg/X11R7.6/rdp/rdpinput.c:283
このコードにより setxkbmap でキー配列を設定するのと同じような処理が走り、キー配列が設定されます。実際の処理の流れは以下のような感じです。
- クライアントからキー配列情報 0xe0010411 が送られてくる
- xrdp_keyboard.ini から対応する model, layout, variant を探す
- 0xe0010411 は rdp_layout_jp2 に対応する
- rdp_keyboard_jp セクションを見に行く
- model=jp106, layout=jp であることがわかる
- "setxkbmap -moddel jp106 -layout jp" コマンドを実行したのと同じような処理が走る
- キー配列が日本語106キーボードになる
このような処理を経て、RDP クライアント側のキー配列がサーバ側にも伝わり、クライアント側とサーバ側のキー配列を一致させています。