このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
早く何でもよいので画面を出してみたい。
これだけコードを書いてもまだ UI がない理由は、
未だに裏で行われる交渉部分の実装途中だからだ。
なので、VNC 認証は少し置いておき、
先に交渉部分を終わらせて画面を出せるように進めよう。
ハンドシェイクが終了した後は、初期化段階となり、
クライアントとサーバの画面状態の初期化を行う。
これは、初期化メッセージを交換することで行われる。
初期化メッセージは、最初にクライアントからサーバに、
ClientInit メッセージを送信する。
U8 shared; // セッションを共有するかどうか
shared が 0 なら、RFB サーバは既存の接続を切断し、
今接続したクライアントに排他的なアクセスを提供する。
shared が 0 以外なら、画面(デスクトップ)は、
現在接続中の複数のクライアントで共有が可能となる。
画面を管理するのはサーバであるため、
shared に対する処理は実装に任されている。
例えば、サーバがユーザ単位で画面を用意する場合は、
shared が 0 でも別のユーザの接続は切断しなくとも良い。
さて、ClientInit を受け取ったサーバは、
ServerInit メッセージを送信する。
U16 width; // 仮想画面の幅
U16 height; // 仮想画面の高さ
PIXEL_FORMAT format; // 仮想画面の画素表現
String name; // 仮想画面の名前
ServerInit は仮想画面に関する情報である。
width, height は説明不要だろう。
name は画面の名前で、タイトルとして表示される事が多い。
format はビット深度や画素のパッキングに関する情報で、
以下に示す PIXEL_FORMAT というデータ構造である。
U8 bitPerPixel; // 詰め物を含めたビット数
U8 depth; // 1 ピクセルを表現するビット数
U8 isBigEndian; // バイトオーダー
U8 isTrueColor; // RGB かインデックスか
U16 redMax; // 赤のビットマスク(常に右寄せ)
U16 greenMax; // 緑のビットマスク(常に右寄せ)
U16 blueMax; // 青のビットマスク(常に右寄せ)
U8 redShift; // 赤を取り出すための右シフト量
U8 greenShift; // 緑を取り出すための右シフト量
U8 blueShift; // 青を取り出すための右シフト量
U8 padding[3]; // 予約済み。常に 0
この構造体は、画素の表現方法を定義している。
RFB では、常に RGB 表現を使うのだが、
それでもビット数や並びに関しては色々な形式がある。
それらを扱えるような構造となっている。
例えば、画素あたり 16 ビットで表現する 555 RGB で、
データをリトルエンディアンで格納するとすると、
1 画素は以下のようなバイトで表現されることになる。
gggbbbbb 0rrrrrgg (0 は詰め物)
この場合、bitPerPixel = 16, depth = 15、
isBigEndian = 0 (false)、isTrueColor = 1 (true)、
redMax = greenMax = blueMax = 0x001f、
redShift = 0、greenShift = 5、blueShift = 10 となる。
bitPerPixel ビット isBigEndian に沿って読み出し、
xxxShift 右シフトし xxxMax と AND を取れば、
色要素の値を取り出せる事になるわけだ。
読み出しの効率化のため、bitPerPixel は、
8, 16, 32 のどれかである必要がある。
一般的に使われている 24 ビット RGB の画素表現の場合、
bitPerPixel = 32、depth = 24 となる。
isTrueColor が 0 の場合は、読み出した値は、
RGB 表現ではなく、カラーテーブルのインデックスとなる。
ServerInit メッセージは、サーバのデフォルトを示すので、
クライアントがこの画素表現を使えるならば効率が良い。
なお、クライアントは、これ以降いつでも、
画素表現を好きに変更することができるため、
サーバは色々な形式に対応できなければならない。