X Window Systemプロトコルとアーキテクチャ

X Window System（X11、X）は、ネットワーク透過なビットマップディスプレイ用ウィンドウシステムである。本項目は、X11のプロトコルと技術的構造の詳細を解説する。 Xはクライアントサーバモデルに基づいている。「Xサーバ」プログラムはグラフィックディスプレイのあるコンピュータ上で動作し、各種「クライアントプログラム」と通信する。サーバはグラフィカルな出力（ウィンドウ）の要求を受け付け、（キーボードやマウスの）ユーザー入力をクライアントに送信する。 Xでは、サーバがユーザーの使っているマシン上で動作し、クライアントは他のマシンでも動作できる。これは一般的なクライアントサーバモデル(「クライアント」がユーザーのコンピュータ上で、「サーバ」が遠隔のコンピュータ上で動作する)とは逆であり、Xを新たに使おうとする人は、この逆転に戸惑うことが多い。Xの用語はエンドユーザーやハードウェアよりもプログラムの観点を採用している。遠隔にあるプログラムはローカルなマシン上で動作するXサーバのディスプレイと接続し、クライアントとして機能する。ローカルなXディスプレイは入っているトラフィックを受け付けるので、サーバとして機能する。 サーバとクライアント間の通信プロトコルは透過性を実現している。クライアントとサーバは同じマシン上でも動作できるし、異なったマシン上でも動作できる。それらマシンのアーキテクチャやオペレーティングシステムの差異は問題にならない。クライアントとサーバ間の通信をインターネット上で行う場合、暗号化されたコネクション上でトンネリングすることでコンピュータセキュリティを確保できる。 Bob ScheiflerとJim Gettysは設計にあたって、Xの基本原則を以下のように定めた（Scheifler/Gettys 1996）。 実際のアプリケーションでどうしても必要という場合以外は、新機能を追加するな。 システムが何でないのかを定義することは、何であるのかを定義するのと同じように重要である。あらゆるニーズに答える必要はない。むしろ、互換性を維持した状態で拡張可能にしておけ。 1つでも例を挙げて一般化したほうが、全く例を挙げずに一般化するよりもマシである。 問題が完全に把握できないときは、解決策も提供しないのが最善の方法である。 作業の10%について90%の効果しか得られないときは、単純な解法を使え。 複雑さは可能な限り分離せよ。 ポリシーよりも機構を提供せよ。特にユーザインタフェースのポリシーはクライアント側に任せておけ。 先頭の原則は、X11の設計中に「具体的アプリケーションがそれを必要としていることを知っている場合に限って、新たな機能を追加せよ」に修正された。X はだいたいにおいてこれらの原則に従ってきた。リファレンス実装は拡張性と改良を視野に入れて開発されており、1987年当時のプロトコルとほぼ完全な互換性を維持している。 サーバとクライアント間の通信は、ネットワーク経路上でパケットを交換することでなされる。コネクション確立はクライアント側から先にパケットを送ることでなされる。サーバはコネクション確立について受理または拒否のパケットを送り返すか、さらなる認証を求めるパケットを送る。コネクションが受理された場合、受理パケットにはクライアントがその後のサーバとのやり取りで必要とするデータが含まれている。 コネクション確立後、クライアントとサーバの間で以下の4種類のパケットがやり取りされる。 要求 (Request): クライアントがサーバから情報を要求するか、サーバに何らかの実行を要求する。 応答 (Reply): サーバへの要求に対する応答。全ての要求パケットに対して応答パケットが生成されるわけではない。 イベント (Event): サーバがクライアントに対して、キーボードやマウスからの入力、ウィンドウの移動、リサイズ、前面への露出などのイベントを知らせる。 エラー (Error): 要求が不正だった場合、サーバはエラーパケットを送る。要求はキューイングされるので、要求に対するエラーは即座に返ってくるとは限らない。 Xサーバは基本的なサービス群を提供する。クライアントはサーバとのやり取りによって、より複雑な機能を実現する。 他のグラフィカルユーザインタフェースでウィンドウと呼ばれるものは、X Window Systemでは「トップレベルウィンドウ」と呼ばれる。「ウィンドウ」は他のウィンドウの中にあるウィンドウも含めた用語である（「親ウィンドウ」と「子ウィンドウ」）。ボタン、メニュー、アイコンといったグラフィカルな要素も全てウィンドウを使って実現される。 ウィンドウは常に親ウィンドウの子ウィンドウとして生成される。このため、ウィンドウ群は木のような階層を形成する。この階層構造の根にあたるウィンドウを「ルートウィンドウ」と呼び、サーバが自動的に生成する。トップレベルウィンドウは、ルートウィンドウの直接の子ウィンドウである。見た目では、ルートウィンドウは画面と同じ大きさで、全てのウィンドウの背後にある。 ウィンドウ、フォントなどに関する全てのデータはサーバに格納される。クライアントはそれらオブジェクトの識別子を知っている。識別子は整数であり、サーバとやり取りする際のオブジェクトを指定する名前の役割を果たす。例えば、クライアントがウィンドウを生成したい場合、サーバに対して識別子を指定してウィンドウ生成を要求する。サーバはウィンドウを生成すると、それを指定された識別子と結びつける。この識別子はその後のクライアントからの要求に使われる（例えば、そのウィンドウに文字列を描画する場合など）。 識別子はサーバ上で一意であり、クライアント間でも重ならない。2つの異なるクライアントが作成したウィンドウであっても、2つのウィンドウが同じ識別子を持つことはない。クライアントは、自身が生成したオブジェクトでなくとも、識別子さえ知っていれば、そのオブジェクトにアクセスできる。 各ウィンドウには事前定義された属性群とプロパティ群があり、それらは全てサーバに格納されていて、クライアントは適切な要求によってそれらにアクセスできる。属性とは、大きさ、位置、背景色などのウィンドウに関するデータである。プロパティとは、ウィンドウに付加されたデータである。属性とは異なり、プロパティはX Window System コアプロトコルのレベルでは何の意味も持たない。クライアントは任意のデータをウィンドウのプロパティに格納できる。 プロパティには、名前と型と値がある。命令型プログラミング言語における変数に似ていて、アプリケーションは新たなプロパティを生成するときに名前と型を指定し、値を格納できる。プロパティはウィンドウ毎にあるので、各ウィンドウに同じ名前のプロパティがある場合、型と値はそれぞれ異なる。 プロパティはクライアント間通信で主に使われる。例えば、WM_NAMEという名前のプロパティはウィンドウの名前を格納するのに使われる。ウィンドウマネージャはこのプロパティを読んで、そのウィンドウの上辺に名前を表示する。 ウィンドウのプロパティ群はxpropプログラムを使って表示できる。特にxprop -rootとすればX resource（en:X resourcesを含むルートウィンドウのプロパティが表示される。 イベントとは、サーバからクライアントに送信されるパケットで、クライアントが関心を持つ可能性のある事象を通知する。クライアントはサーバに対して、別のクライアントにイベントを送信するよう要求でき、これを使ってクライアント間通信がなされる。例えば、あるクライアントが現在選択されているテキストを要求する場合、選択が行われているウィンドウを制御しているクライアントにイベントが送信される。 ウィンドウの内容は状況によって破壊されることがある（例えば、別のウィンドウの陰になった場合）。破壊された内容を見えるようにするため、サーバはExposeイベントをクライアントに送り、クライアントにウィンドウの再描画の必要があることを知らせる。 他には、キーボードやマウスからの入力を知らせるイベント、新たなウィンドウの生成を知らせるイベントなどがある。 ある種のイベントは常にクライアントに送られるが、ほとんどのイベントはクライアントが事前に指定していないと送信されない。例えば、キーボード入力しか受け付けないクライアントは、キーボードに関するイベントのみを指定し、マウスに関するイベントは指定しないといったことが考えられる。 X Window Systemでの色の扱い方はユーザーを混乱させることがあり、歴史的経緯からいくつかの異なるモードをサポートしている。多くのアプリケーションはTrueColor（24ビットで、赤・緑・青がそれぞれ8ビット）を使用するが、古いアプリケーションや特殊なアプリケーションは異なる色モードを要求することがある。特に商用の特殊アプリケーションはPseudoColorを使用する。 X11プロトコルでは、色は32ビットの符号なし整数で表され、これを「ピクセル値」と呼ぶ。原色の強さを指定する場合は、それぞれの色成分を16ビット整数で表す。色の表現には以下のモードがあるが、あるディスプレイ機器でこれらが全てサポートされているとは限らない。 DirectColor: ピクセル値は赤・緑・青のビット列に分割される。それぞれの成分に独立したカラーマップがある。カラーマップ上のエントリは全て変更可能である。 TrueColor: DirectColor と同じだが、カラーマップのエントリはハードウェアによって決まっていて、変更できない。通常、赤・緑・青はそれぞれの光の強さを表している。 GrayScale: ピクセル値は単一のカラーマップのインデックスであり、白黒階調を表す。カラーマップのエントリは変更可能である。 StaticGray: GrayScale と同じだが、カラーマップのエントリはハードウェアによって決まっていて、変更できない。 PseudoColor: ピクセル値は単一のカラーマップのインデックスであり、カラーマップの各エントリが色を示している。カラーマップのエントリは変更可能である。 StaticColor: PseudoColor と同じだが、カラーマップのエントリはハードウェアによって決まっていて、変更できない。 クライアントプログラムの多くは、Xlibというクライアント用ライブラリを経由してサーバと通信する。さらに、多くの場合Xlibを直接使うのではなく、Motif、GTK、Qt といったライブラリを使う。 X Window System コアプロトコルは、クライアント間の通信機構としてプロパティとイベントを提供しており、特にクライアント間のメッセージイベントがある。しかし、そのやり取りを規定するプロトコルは存在しない。そのようなプロトコルは個別のクライアント間通信規定で扱われる。 Inter-Client Communication Conventions Manualは、セレクションによるそのようなデータ交換のプロトコルとウィンドウマネージャとアプリケーションのやり取りを規定している。しかし、この仕様には混乱があり、理解するのが困難と言われてきた。アプリケーションのルック・アンド・フィールと通信の一貫性は、一般にデスクトップ環境を指定してプログラミングすることで保たれる。 Inter-Client Exchange (ICE) プロトコルはクライアント間のやり取りのためのプロトコル構築のフレームワークとなり、これを使って特定のプロトコルを構築できる。例えば、X Session Manager Protocol (XSMP) はICEに基づくプロトコルで、Xセッションマネージャ（後述）とアプリケーション間のやり取りを規定している。 より新しい規定としてfreedesktop.orgによる仕様群がある。これには、Xdnd（ドラッグ・アンド・ドロップ規定）、Xembed（あるアプリケーションを別のアプリケーションの子ウィンドウとして動作させる際の詳細な規定）などがある。 セレクション (selection)、カットバッファ (cut buffer)、ドラッグ・アンド・ドロップ (drag-and-drop) は、ユーザーがX Window Systemでウィンドウからウィンドウにデータを転送するための機構である。セレクションとカットバッファは一般に、ユーザーがウィンドウ内のテキストなどの何らかのデータを選択し、それを他のウィンドウに貼り付けるのに使われる。ドラッグ・アンド・ドロップは、ユーザーがウィンドウ内の何かを選択し、選択したものの上でマウスをクリックし、それを他のウィンドウにドラッグするという場合に使われる。 2つのウィンドウはそれぞれ独立した別々のアプリケーションが制御しているので、Xサーバに接続された2つのクライアントが相互にやり取りしないとデータ転送できない。X Window System コアプロトコルはセレクションの交換に対応した要求やイベントを用意しているが、転送自体はクライアント同士のイベント送信とウィンドウプロパティで実現され、これはセレクションの転送に限った話ではない。 クライアント間で転送されるデータには様々なものがある。テキストであることが多いが、ピクスマップや数値やオブジェクトのリストなどもある。 セレクションとドラッグ・アンド・ドロップは能動的機構である。あるウィンドウ上でテキストを選択した場合、そのウィンドウを制御しているクライアントがデータを要求しているアプリケーションにデータを転送するプロトコルを能動的にサポートしていなければならない。対照的にカットバッファは受動的機構である。ユーザーがテキストを選択した場合、その内容はカットバッファに転送され、元のウィンドウを制御していたアプリケーションが終了してウィンドウが消えても、カットバッファ内の内容は残る。 ウィンドウマネージャは、ウィンドウの全体的見た目や他のGUI要素を制御する。X Window System が使用されているマシン毎に異なる見た目となるのは、主にウィンドウマネージャが違うためか、あるいはウィンドウマネージャの設定が異なるためである。 ウィンドウマネージャは、ウィンドウの位置決め、ウィンドウ周囲の装飾の配置、アイコンの処理、特定キーストロークの処理（例えば ALT-F4 押下でウィンドウをアイコン化するなど）といった処理をする。 Xサーバから見れば、ウィンドウマネージャも通常のクライアントと違いはない。初期の位置決めや周囲の装飾の配置は、ウィンドウマネージャによる以下のような要求で制御される。 アプリケーションは、サーバがウィンドウの子ウィンドウを表示する前に、イベントを送信してもらうよう設定できる。 アプリケーションは、親ウィンドウの変更を要求できる。 ウィンドウマネージャは、第一の要求を使ってトップレベルウィンドウ（ルートウィンドウの子ウィンドウ）の表示要求をインターセプトする。他のアプリケーションがトップレベルウィンドウの表示を要求すると、サーバは表示する前にウィンドウマネージャにイベントを送る。多くのウィンドウマネージャはRe-parenting Window Managerと呼ばれ、フレームウィンドウと呼ばれる大きなトップレベルウィンドウを生成し、本来のウィンドウをその子ウィンドウとして表示する。画面上はフレームウィンドウの内側に本来のウィンドウが表示される。フレームウィンドウは若干大きいので、周辺部分は元のウィンドウで覆われない。この部分が周囲の装飾（ボーダーやタイトルバー）の表示に使われる。 ウィンドウマネージャはフレームウィンドウでのマウスクリックを管理する。このため、ボーダー部分やタイトルバー部分でマウスをクリックしてドラッグすることで、ウィンドウを移動させたり、サイズを変更したりできる。 ウィンドウマネージャはアイコンや関連するGUI要素の制御も行う。アイコンという概念はX Window System コアプロトコルのレベルでは存在せず、ウィンドウマネージャによって実装されている。例えば、ウィンドウを「アイコン化」するとき、FVWMなどのウィンドウマネージャがウィンドウをアンマップし、見えないようにし、アイコン名のウィンドウと（もしあれば）アイコンの画像のウィンドウを生成する。このようにアイコンの制御は完全にウィンドウマネージャが行っている。中には全くアイコンを実装していないウィンドウマネージャもある（例えば wm2）。 「セッション (session)」の状態とは、大まかに言えばある時点での「デスクトップの状態」、すなわちウィンドウ群の現在の内容の総体である。より正確に言えば、それらウィンドウ群を管理しているアプリケーションと、それらアプリケーションが要求されたときにウィンドウの状態を復元するのに必要とする情報の集まりである。Xセッションマネージャとは、セッションの状態を保存し復元するプログラムである。 セッションマネージャを使うと何ができるかというと、ログアウトして再びログインしたときに、ログアウト前と全く同じウィンドウ群が表示されるという効果がわかりやすい。このため、セッションマネージャはログアウト時点の動作中アプリケーションの名前を記録しておき、再度ログインした際にそれらを再開させる。各アプリケーションの状態も復元するには、アプリケーション自体が実行状態をセッションマネージャの要求に応じて保存し、再開時に復元できるようになっている必要がある。 X Window Systemにはデフォルトのセッションマネージャとしてxsmがある。他のセッションマネージャとしては、例えばKDEのデフォルトのセッションマネージャであるksmserverなどがある。 Xディスプレイマネージャは、X Window Systemのグラフィカルなログインプロンプトを表示するプログラムである。それだけでなく、Xディスプレイマネージャはローカルのコンピュータ上で1つ以上のXサーバを起動し、遠隔にあるコンピュータで動作するXクライアントからのコネクション要求を受信する。ローカルなサーバはディスプレイマネージャによって起動され、相互に接続し、ログイン画面を表示する。遠隔のサーバはディスプレイマネージャとは独立して起動され、ディスプレイマネージャと接続する。この場合、ディスプレイマネージャは一種のグラフィカルなtelnetサーバのように働く。Xサーバがディスプレイマネージャと接続することでセッションが開始される。このとき、このセッションで実行されるプログラムはディスプレイマネージャの動作しているコンピュータ上で動作するが、入出力はXサーバの動作するコンピュータ上で行われる（そして、ユーザーはそのXサーバの動作する遠隔のコンピュータを使っている）。 XDMはX Window Systemの基本のディスプレイマネージャである。他のディスプレイマネージャとしては、GNOME ディスプレイマネージャー (GDM)、KDEディスプレイマネージャ (KDM) などがある。 初期のX向けウィジェット・ツールキットとしては、Xaw (Athena Widget Set)、OLIT (OPEN LOOK Instrinsics Toolkit)、XView、Motif、Tkなどがある。OLITとXViewはサン・マイクロシステムズのかつてのデスクトップ環境 OpenWindows のベースとなっている。 Motifは Common Desktop Environment (CDE) のベースとなっており、Solaris、AIX、HP-UXといった商用UNIXのデスクトップ環境として使われていた。 比較的新しいツールキットとしては、Qt（KDE）、GTK（GNOME）、wxWidgets、FLTKなどがある。 Xサーバは単純だが拡張可能となるよう設計された。そのため、プロトコルに対して様々な機能拡張がなされている。 プロトコルレベルでは、拡張は要求/イベント/エラーのパケットの新たな型として認識される。クライアントのアプリケーションは拡張ライブラリを通して拡張機能にアクセスできる。Xサーバ実装への拡張の追加は、サーバがモジュール設計になっていないため、難しいと言われている[要出典]。XCBプロジェクトの長期目標の一つとして、XMLによるプロトコル記述から拡張機能のクライアント側とサーバ側のコードを自動生成するというものがある。 以下は、これまで開発された拡張の一部である。 Xlib Intrinsics (Xt) X Window System コアプロトコル Robert W. Scheifler and James Gettys: X Window System: Core and extension protocols, X version 11, releases 6 and 6.1, Digital Press 1996, ISBN 1-55558-148-X An Introduction to X11 User Interfaces Introduction to X Windows Open Source Desktop Technology Road Map (Jim Gettys, 09 Dec 2003) X.Org Foundation 公式サイト X.Org Foundation wiki Kenton Lee's pages on X Window and Motif