入り口に戻る

原文はこちら。

翻訳にあたって、オープンソースグループ・ジャパンの MIT ライセンスの訳、たなかともひさ氏の部分訳、及び「Xプロトコル・リファレンス・マニュアル」(Adrian Nye著・石川和也訳・ソフトバンク)のICCCMver1.0の訳を参考にした。

# Inter-Client Communication Conventions Manual(日本語訳)

## X Consortium Standard

### David Rosenthal

Sun Microsystems, Inc.

#### Edited by

### Stuart W. Marks

SunSoft, Inc.

X Version 11, Release 7.7

Version 2.0

Copyright © 1988, 1991, 1993, 1994 X Consortium

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium.

X Window System is a trademark of The Open Group.

(訳)

(本ソフトウェアおよび関連する文書のファイル（以下「ソフトウェア」）の複製を取得した全ての人物に対し、以下の条件に従うことを前提に、ソフトウェアを無制限に扱うことを無償で許可する。これには、ソフトウェアの複製を使用、複製、改変、結合、公開、頒布、再許諾、および/または販売する権利、およびソフトウェアを提供する人物に同様の行為を許可する権利が含まれるが、これらに限定されない。)

(上記の著作権表示および本許諾表示を、ソフトウェアの全ての複製または実質的な部分に記載するものとする。)

(ソフトウェアは「現状有姿」で提供され、明示的であるか黙示的であるかを問わず、いかなる種類の保証も行われない。ここでいう保証には、商品性、特定目的への適合性、および権利の非侵害性に関する保証も含まれるが、これらに限定されるものではない。THE X CONSORTIUM は、契約、不法行為、またはその他の行為であるかを問わず、ソフトウェアまたはソフトウェアの使用もしくはその他に取り扱いに起因または関連して生じるいかなる請求、損害賠償、その他の責任について、一切の責任を負わない。)

(X Consortium の名称は、この表示に記載されている場合を除き、X Consortium の事前の書面による承認を得ずに、宣伝であろうとその他の形であろうと、ソフトウェアの販売を促進するもの、またはソフトウェアの使用その他の扱いを奨励するものに使用してはならない。)

(X Window System は The Open Group の商標である。)

Copyright © 1987, 1988, 1989, 1993, 1994 Sun Microsystems, Inc

Permission to use, copy, modify, and distribute this documentation for any purpose and without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. Sun Microsystems makes no representations about the suitability for any purpose of the information in this document. This documentation is provided as is without express or implied warranty.

(訳)

(本文書を使用、複写、変更、および頒布することは、目的を問わず無償で許可する。但し、上記の著作権表示および本許諾表示を文書のすべての複製に記載するものとする。Sun Microsystems は、本文書に含まれる情報のいかなる目的への適切性についても、何ら表明を行わない。本文書は明示または暗黙の保証なしに提供される。)

## バージョン 2.0 の前書き

ICCCM バージョン 2.0 製作の狙いは、前の版との互換性を保ったまま、新しい機能を追加し、前版の問題点を修正し、その上で読みやすく分かりやすい規約を作ることであった。本文書は、X Consortium(X 協会)の `wmtalk` 作業部会の会員達が二年間討議を重ねて出来上がったものである。以下に挙げる方々は、この取組みに大いに貢献してくれたので、この場でお礼を申し上げる。

    Gabe Beged-Dov     Bill Janssen
    Chan Benson     Vania Joloboff
    Jordan Brown     Phil Karlton
    Larry Cable     Kaleb Keithley
    Ellis Cohen     Mark Manasse
    Donna Converse     Ralph Mor
    Brian Cripe     Todd Newman
    Susan Dahlberg     Bob Scheifler
    Peter Daifuku     Keith Taylor
    Andrew deBlois     Jim VanGilder
    Clive Feather     Mike Wexler
    Stephen Gildea     Michael Yee
    Christian Jacobi

このような素晴らしい方々と一緒に仕事ができて光栄であった。

Stuart W. Marks

1993 年 12 月

## 1.1 版の前書き

本文書に定める規約のアーキテクチャの総責任者は David Rosenthal である。氏が文章の大半を書き上げて本文書に編輯したけれども、同文書の開発自体は共同作業によって進められてきた。本文書の細部は、1988 年 1 月の MIT X Conference と 1988年 Summer Usenix Conference とで開かれた会合や、`wmtalk` のメーリングリストの何ヶ月(何メガバイト)にも及ぶ議論を通じて、徹底的に練り上げられた。手伝ってくれた方々皆に感謝する。以下に挙げる方々には特に。

セレクションの部分：

    Jerry Farrell
    Phil Karlton
    Loretta Guarino Reid
    Mark Manasse
    Bob Scheifler

カット・バッファの部分：

    Andrew Palay

ウィンドウとセッション・マネージャの部分：

    Todd Brunhoff     Matt Landau
    Ellis Cohen       Mark Manasse
    Jim Fulton        Bob Scheifler
    Hania Gajewska    Ralph Swick
    Jordan Hubbard    Mike Wexler
    Kerry Kimbrough   Glenn Widener
    Audrey Ishizaki

Device Color Characterization の部分：

    Keith Packard

また、public review に参加してくれた方々にも感謝する：

    Gary Combs        John Irwin
    Errol Crary       Vania Joloboff
    Nancy Cyprych     John Laporta
    John Diamant      Ken Lee
    Clive Feather     Stuart Marks
    Burns Fisher      Alan Mimms
    Richard Greco     Colas Nahaboo
    Tim Greenwood     Mark Patrick
    Kee Hinckley      Steve Pitschke
    Brian Holt        Brad Reed
    John Interrante   John Thomas

## 第１章　序論

X バージョン 11が標榜していた目標は、仕組み(mechanism)を設計することであり、方針(policy)を定めることではなかった。結果として、X Window System Protocol Version 11 で定義されたプロトコルに則ってサーバと対話を行うクライアントは、自分しか居ない状況では正しく動作できるものの、同一サーバを共用する他のクライアントとの共存には失敗することがある。

X バージョン 11の世界で良き市民となるには、下に列挙した領域でクライアント間通信を律している規約に対して、忠実でなければならない。

- セレクション機構

- カット・バッファ

- ウィンドウ・マネージャ

- セッション・マネージャ

- 共有資源の操作

- 装置色特性評価(Device color characterization)

本文書で提示する規約は、特定のユーザ・インターフェイスの使用を強制するものではない。異なる言語で書かれたクライアント同士が通信し合えるように、上記の規約は専らプロトコルの操作を使って記述していく。プロトコル操作に対応する Xlib インターフェイスを使って記述していく、という方法は採らない。こちらの方が一般的かもしれないが。プロトコルの操作を C 言語の Xlib インターフェイスや他言語の同等なインターフェイスで表すのは、他の文書の仕事である。

## 規約の発展

公表する時機を逃さないようにしたため、Inter-Client Communication Conventions Manual (ICCCM) では必要な規約の中の最低限のものしか扱っていない。将来、X Consortium の得た知見に基づいて、この規約に適切な追加・更新が行われるであろう。

ICCCM の規約は、できる限り１９８８年２月２５日の草案の上位互換となるように作られている。この草案は、X バージョン １１リリース２(X11R2)のソフトウェアとともに配られたものである。同草案は幾つかの分野で意味論上の問題があることが分かっており、従って、完全な上位互換性は確保できなかった。問題のあった分野については、本文中にその旨の記述があり、附録 A にまとめがある。

ICCCM の規約を開発してゆく中で、X プロトコルに細かな修正を多数施すのが望ましいことが判明した。この部分についても、本文中でそれとわかるように記述があり、また、附録 B にまとめがある。将来の X プロトコル改訂作業において考慮すべき課題である。この修正を含むような X プロトコル改訂が行われる場合、ICCCM の改訂も必要になると思われる。クライアントとサーバが同時に新しい版へ切り替わるように計らうことは難しいので、改訂後の規約を利用するクライアントは、プロトコルの下位の改訂番号を確認するものとし、古いサーバと通信する場合に古い規約も使えるよう備えておくものとする。

X プロトコルの改訂は、下位の改訂番号が n の X プロトコルに合う規約を利用しているクライアントと、下位の改訂番号が n + 1 の X プロトコルに合う規約を利用しているクライアントとが問題なく通信し合える形で行われるであろう(サーバが両者に対応している場合の話である)。

## アトム

ICCCM の規約の多くでアトムが使われている。X プロトコル仕様書にもアトムの説明はあるが、読者のために、以下の節でもっと詳しく説明する。

### アトムとは?

概念としては、アトムは、クライアントが互いに情報をやり取りする際に使える一意の(唯一無二の、uniqueな)名前である。この名前というのはバイトの羅列だと考えてよい。但し、特定の符号化方式を持たない文字列のようなバイトの羅列である。 この羅列の要素は ASCII 文字であるとは限らず、大文字小文字の統一も行われない。[1]

プロトコルの設計者らは、このようなバイト列が回線上を行ったり来たりするのはあまりにも不経済であると考えた。これに加えて、回線を通る際にはイベントのサイズが一定であること(実際 32 バイトである)、及び一部のイベントの内部にアトムが含まれていることから、バイト列を固定長で表現することが必要になった。

固定長の表現を可能にするため、サーバにバイト列を登録するプロトコル・リクエスト(`InternAtom`)が用意された。このリクエストは登録したバイト列と結び付いた３２ビットの値(上位３ビットは 0)を返す。逆の操作を行う関数も存在する(`GetAtomName`)。

### 既定のアトム

X11プロトコルでは、多くのアトムを既定のものとして定めている。

> 既定のアトム(predefined atoms)は、絶対に必要というわけではないし、あらゆる環境で役に立つわけでもない。しかし、このアトムがあるお陰で、大概のアプリケーションはリクエスト `InternAtom` の回数を大きく減らすことができるようになる。「予め定義された」とは、用途が決まっている(having required semantics)という意味ではなく、単に数値が決まっているという意味であることに注意。

「既定のアトム」という実装の技巧は、あらゆるアプリケーションが起動段階で使うであろうアトムを何度も設定(intern)しなくても済むようにするためのものである。リクエスト `InternAtom` は、ハンドシェイクを必要とするけれども、その結果は仕様から(a priori)予測可能である。

言語インターフェイスは、アトム-名前の対応表を手元に保持し、用のある時以外はこの情報を取得しないようにするべきだろう。例えば、CLX インターフェイスは、既定のアトムと他のアトムを区別しない。即ち、同インターフェイスでは全てのアトムはシンボルと見做される(訳註：要確認)。しかしながら、CLXの実装では大抵、シンボルもしくはアトムのキャッシュを保持し、且つ、このキャッシュを既定のアトムで初期化する。

### 命名規約

組み込みアトムは、ASCIIの大文字を連ねた単語と、それを区切るアンダースコア(_)から成る。例えば「WM_ICON_NAME」のようなものである。X11 プロトコルの仕様書においては、各開発組織が独自の理由で使用するアトムの名前は、アンダースコアから始めるよう推奨している。組織間で名前が被らないように、適当な接頭辞を追加するものとする(例えば「_DEC_WM_DECORATION_GEOMETRY」)。

組み込みアトムの名前を上記の形式で定めたおかげで、LISP でもこのアトム名を自然な方法で扱えるようになった。「keyword constructors」を使えば、プログラマは組み込みアトムを LISP のアトムとして扱うことができる。もし組み込みアトムが全て大文字でなかったとしたら、特別なクォートの規約(special quoting conventions)を用いる必要があったであろう。

### 意味

アトムの意味は、構造体 FONTPROP で使用する例を除き、X Window System コア・プロトコルの中に定めがない。FONTPROP における意味(使い方)について詳しく知りたければ、X Logical Font Description Conventions を見よ。

### 名前空間

X プロトコルでは独立した空間を６つ定義しており、アトムの解釈はこの中で行われる。どのアトムも、６つの名前空間のそれぞれに応じて、有効な解釈を持ったり持たなかったりする。

空間 | 略称 | 例
--- | --- | ---
Property name | Name(名前) | WM_HINTS, WM_NAME, RGB_BEST_MAP, ...
Property type | Type(型) | WM_HINTS, CURSOR, RGB_COLOR_MAP, ...
Selection name | Selection(セレクション) | PRIMARY, SECONDARY, CLIPBOARD
Selection target | Target(ターゲット) | FILE_NAME, POSTSCRIPT, PIXMAP, ...
Font property |  | QUAD_WIDTH, POINT_SIZE, ...
`ClientMessage` type |  | WM_SAVE_YOURSELF, _DEC_SAVE_EDITS, &...

### 辨別名

あるプロトコルにおいて、一意の名前を持つ、同じ種類のオブジェクトが不特定数必要になることがある(この必要が生じるのは通常、オブジェクトが動的に生成され、前もって名前を決めておくことができないからである)。例えば、カラーマップを生成するプログラムでは、各スクリーン(screen)にカラーマップを提示するにあたって、セレクション機構を使うことがあり得る。その場合、同プログラムは各スクリーンに対して一つづつセレクション名を用意する必要がある。このような名前は辨別名(discriminated names)と呼ばれ、プログラム的な実体(entity)を利用して名前の差別化を図る。ここでいうプログラム的な実体(entity)には、次のようなものがある。

        スクリーン(screen)
        X リソース (ウィンドウ、カラーマップ、ビジュアルなど)
        クライアント

もし差別化に使う実体(entity)のそれぞれに対してその値に応じた名前を生成し、これによって一定不変の名前集合を一つ作ればよいというのであれば、辨別名は、通常の名前の後ろへ実体(entity)の値に応じた接尾辞を付けたものとなる。

辨別名の内容説明部分を name、頭に０の来ない１０進数を d、８桁の１６進数を x とし、大文字だけを使用した場合、辨別名は次のような形になる。

名前を差別化するもの(entity) | 形式 | 例
--- | --- | ---
screen number | name_Sd | WM_COMMS_S2
X resource | name_Rx | GROUP_LEADER_R1234ABCD

クライアントによって名前を差別化する場合は、そのクライアントが作成した X リソースの ID を用いる。このリソースはどんな型(type)でも良い。

単に被りのない名前の集合を生成すれば良いということもある(例えば、MULTIPLE セレクションの作業ウィンドウに属するプロパティ群の名前の集合)。このような名前は、集合が一つしかない場合、

    Ud     (例、 U0  U1  U2  U3  ...)

のような形をとる。集合が複数ある場合(ここでは「FOO」と「BAR」という二つの集合があるとしよう)、

    name_Ud     (例、FOO_U0  BAR_U0  FOO_U1  BAR_U1  ...)

のような形になる。Ud 単独の形を使用するのは、次の二つの場合に限るものとする。即ち、この名前を使用しているモジュールによって、関連する名前空間が完全に統制されていると分かっている場合、あるいは、同モジュールがこの名前を使う可能性のある実体(entities)全てと共同作業を行っている場合である。(特定のセレクションの為に作られたウィンドウに属するプロパティに名前を付ける時は、この作法で名前を定めてよい。名前を付けたいプロパティがルート・ウィンドウに属する時は、勿論そうではない。)

特に複雑な場合には、両方の差別化手法を組み合わせる必要が生じ得る。その時は、U 形式の部分を他方の形式の部分の後ろに持ってくることにする。

        FOO_R12345678_U23

> 玄論

> 既存のプロトコルに対して、この規約が使えるように変更を加えたりはしない。あまりにも多くの齟齬が生じるためである。しかしながら、将来のプロトコルは、公式のものであれ非公式のものであれ、この規約を用いることになるであろう。

[1] X11 プロトコル仕様書の `InternAtom` の説明では、符号化方式 ISO Latin-1 を使うべきだと書いてある。これは、サーバは文字列をバイト列として扱う、という規約と実質的には同じことである。

## 第２章 セレクションを用いた２者間通信

セレクションは、X バージョン 11がクライアント間の情報交換を担う仕組みとして用意したものの中、最も重要なものである。ここで云うクライアント間の情報交換とは、例えば、ウィンドウ間のカット・アンド・ペーストのような操作のこと。セレクションの数は任意であり、１個のセレクションには１個のアトムが名前として与えられ、且つどのセレクションもサーバに対してグローバル(大域的)である、ということに注意する。セレクション・アトムの利用の節では、どんなアトムを使用するべきなのか説明する。１つのセレクションは、１つのクライアントに所有され、１つのウィンドウに所属する。

セレクションは、所有者と要求者の間でやり取りされる。所有者は、所有セレクションの値であるデータを持っており、要求者はこれを受け取る。セレクションの値を取得したい要求者は、以下の情報を提示する。

- セレクションの名前

- プロパティの名前

- ウィンドウ

- 希望のデータ型を表すアトム

- リクエストの引数(任意)

指定したセレクションが現在所有されている場合、所有者はイベントを受信し、以下の動作を行う。

- セレクションの内容を、要求されたデータ型に変換する。

- 指定されたウィンドウの指定されたプロパティに、変換したデータを格納する。

- このプロパティが有効になったことを知らせるため、要求者にイベントを送信する。

クライアントは、この仕組みを是非とも採用すべきである。特に、一時的でないウィンドウにテキストを表示するにもかかわらず、同テキストを選択して文字列に変換する機能を提供しないのであれば、その行為は反社会的だと言わざるを得ない。

X バージョン 11の環境では、所有者と要求者の間で転送されるデータは全て、通常は X サーバを通さなければならないことに注意。クライアントには、相手クライアントが同じファイルを開けるかどうか判らないし、その上、同者と直接通信できるかすら判らない。相手のクライアントが全く異なるネットワーク・メカニズムで X サーバと会話している可能性もある(例えば、一方のクライアントが DECnet 、他方のクライアントが TCP/IP の場合)。従って、データへの間接参照(ファイル名、ホスト名、ポート番号など)をやり取りするのは、双方のクライアントが特に合意している場合にしか認められない。

## セレクションの所有権の獲得

セレクションの所有権を取得したいクライアントは、`SetSelectionOwner` を呼び出すものとする。この関数の定義は次の通り。

`SetSelectionOwner`

selection: ATOM
owner: WINDOW もしくは `None`
time: TIMESTAMP もしくは `CurrentTime`

クライアントは、目的のセレクションを表すアトムを selection に指定し、自分が作成したウィンドウを owner に指定し、time には、目的セレクションの最終変更時刻(関数呼び出し時における)と現在のサーバの時刻との間の時刻を設定する。この time の値は通常、セレクション獲得動作の切っ掛けとなったイベントのタイムスタンプから得ることになる。クライアントは time の値として `CurrentTime` を渡してはならない。もしそうしてしまうと、セレクション所有権の獲得時刻を知る術がなくなってしまうからである。クライアントは、後々要求者がセレクションの所有者にイベントを配送できるように、自分が作成したウィンドウを指定しなければならない。[2]

> 規約

> セレクションを獲得しようとするクライアントは、リクエスト `SetSelectionOwner` の time の値として、同セレクションの獲得を試みる切っ掛けとなったイベントのタイムスタンプを渡さなければならず、`CurrentTime` を渡してはならない。このためのタイムスタンプは、プロパティに長さ 0 のデータを追加するという方法で入手することができる。この場合、タイムスタンプはデータ追加によって起こる `PropertyNotify` イベントの中にある。

リクエスト `SetSelectionOwner` の time が、サーバの現在時刻より後(未来)を指しているか、もしくは selection の持ち主が最後に交替した時刻より前(過去)を指している場合、クライアントからはリクエスト `SetSelectionOwner` が成功したように見えるものの、実際には所有権は移らない。

クライアントは直接に他のクライアントを指名することができないので、所有権を持つクライアントを参照するには、`GetSelectionOwner` に対する返答、`SelectionRequest` イベント、及び `SelectionClear` イベントの owner のウィンドウが使用される。また、この owner のウィンドウは、目的のセレクションを格納するプロパティの設置場所としても使われる。セレクションの所有者を知るには、クライアントは `GetSelectionOwner` を呼び出すものとする。この関数の定義は次の通り。

`GetSelectionOwner`

selection: ATOM
->
owner: WINDOW もしくは `None`

> 規約

> クライアントは、セレクションの所有権をはっきり確認する仕組みを備えるべきである。このフィードバックが信頼できるものとなるように、クライアントは次のような手順を実行しなければならない。

    SetSelectionOwner(selection=PRIMARY, owner=Window, time=timestamp)
    owner = GetSelectionOwner(selection=PRIMARY)
    if (owner != Window) Failure

リクエスト `SetSelectionOwner` が成功した場合(単に成功したように見えるのではなく)、そのリクエストを発行したクライアントは、time の時刻以降のセレクション所有者としてサーバに記録される。

## セレクション所有者の仕事

要求者がセレクションの値を取得しようとする時、所有者はイベント `SelectionRequest` を受け取る。同イベントの定義は次の通り。

`SelectionRequest`

owner: WINDOW
selection: ATOM
selection: ATOM
target: ATOM
property: ATOMもしくは `None`
requestor: WINDOW
time: TIMESTAMPもしくは `CurrentTime`

このイベントの owner と selection には、リクエスト `SetSelectionOwner` で指定した値が入る。所有者は、指定されたタイムスタンプと自身のセレクション所有期間とを比べ、もし time が同期間に含まれなければ、受け取った `SelectionRequest` を拒否するものとする。これは、イベント・マスクが空の `SendEvent` リクエストを呼び出し、requestor のウィンドウに宛てて property が `None` の `SelectionNotify` イベントを送信することで達成される。

高度なセレクション所有者は、セレクションの値の履歴を保持しすることができ、たとえ今はセレクションを所有していなくても、所有していた時期のセレクションの値を求めるリクエストに返答することができる。

property が `None` の場合、要求者は旧版のクライアントである。所有者は、指定された target アトムを返答用のプロパティ名として利用することによって、こうしたクライアントに対応するのが望ましい。

property が `None` でなければ、所有者は target を見てセレクションをどのような形に変換すべきか判断するものとする。ターゲットの中には、要求者がリクエストに引数を渡せるよう定義されているものもある。所有者は、このような引数を SelectionRequest で指定されたプロパティから取得することになる。このプロパティの型(type)、形式(format)、内容は、ターゲットの定義次第である。ターゲットが引数を取るように定義されていなければ、所有者は同プロパティが存在しても無視するべきである。ターゲット(及び、もしあれば外部引数)が示す形にセレクションを変換できない時は、上記と同様に所有者は `SelectionRequest` を拒否するものとする。

また、property が `None` でない場合、所有者は、セレクションの変換結果たるデータを requestor のウィンドウの指定されたプロパティに書き込み、同プロパティの型(type)を適当な値に設定するものとする。この型は、target で指定されたものと同じである必要は無い。

> 規約

> イベント `SelectionRequest` の返答に用いるプロパティは、全て「requestor」で指定されたウィンドウに設置しなければならない。

どちらの場合でも、requestor で指定されたウィンドウにセレクションを構成するデータが格納できない時は(例えばサーバ側で十分なメモリを確保できなかったなど)、所有者は上記と同様に `SelectionRequest` を拒否しなければならない。「大量のデータの転送」 も参照。

プロパティの格納に成功した場合、所有者は、マスクが空の `SendEvent` リクエストを使って requestor で指定されたウィンドウに `SelectionNotify` イベントを送信し、変換の成功を知らせる。`SelectionNotify` の定義は次の通り。

`SelectionNotify`

requestor: WINDOW
selection, target: ATOM
property: ATOMもしくは `None`
time: TIMESTAMPもしくは `CurrentTime`

所有者は、selection、target、time、property に `SelectionRequest` イベントで受け取った値を設定する。(property に `None` を設定することは、要求された変換が行えなかったことを意味する。)

> 規約

> `SelectionNotify` イベント中の selection、target、time、property には、`SelectionRequest` イベントで受け取った値を設定する。

所有者は、同じ requestor、selection、target 及び timestamp の入った `SelectionRequest` イベントを複数受け取った場合、届いたのと同じ順番でそれらに応答しなければならない。

> 玄論

> 要求者は、同一の要求元ウィンドウ、同一のセレクション、同一のターゲット及び同一のタイムスタンプを使用し、プロパティだけが異なるリクエストを、各リクエストが未処理のまま同時に複数発行することができる。この時、そうしたセレクション変換要求の１つが失敗すると、その結果生じる `SelectionNotify` イベントの property には `None` が設定されることになる。こうなると、リクエストが順番通りに応答されなければ、要求者にはどのセレクション変換リクエストが失敗したのか判らなくなるであろう。

プロパティに格納されたデータは、最終的には削除しなければならない。この仕事を(誰かに)割り当てる規約が必要である。

> 規約

> `SelectionNotify` イベントで指定されたプロパティ(Requesting a Selection を見よ)と、MULTIPLE 型変換要求の過程で指定されたプロパティとを削除するのは、セレクション要求者の仕事である。

セレクションの所有者は大抵、セレクションを構成するデータの転送が実際に行われたことの裏付けを必要とするであろう。（例えば、ある操作が所有者の内部のデータ構造に対して副作用を持つ場合、無事にデータを受け取ったことが要求者から示されるまでは、そうした副作用が起きないようにしなければならない。）所有者は、requestor で指定されたウィンドウに関する `PropertyNotify` イベントへの関心を表明し、`SelectionNotify` イベントで知らせたプロパティが削除されるのを待ってから、初めてセレクション・データが転送されたものと判断する。MULTIPLE リクエストの場合、各変換ごとに確認する必要があるのであれば、セレクションの所有者はさらに `SelectionNotify` イベントの property で伝えたプロパティの一つ一つが削除されるのを看視することになる。

別のクライアントがセレクションを獲得すると、それまでの所有者には `SelectionClear` イベントが届く。同イベントの定義は次の通り。

`SelectionClear`

owner: WINDOW
selection: ATOM
time: TIMESTAMP

time には所有権が移った時刻が入る。owner は、それまでの所有者が自身の `SetSelectionOwner` リクエストの際に指定したウィンドウである。(訳註：Xlib - C Language X Interface の「SelectionClear Events」の項によると、「The window member is the window that was specified by the current owner (the owner losing the selection) in its XSetSelectionOwner call. 」)(訳註：X Window System Protocol の「SelectionClear」の項によると、「The owner argument is the window that was specified by the current owner in its SetSelectionOwner request. 」)

所有者は、転送の途中で(即ち要求者から全データを受領したという通知が来る前に)所有権を失った場合、進行中の転送が完了するまで作業を続行しなければならない。

セレクションの値がそっくり変わったものの、所有者が再び同一のクライアントであった場合(例えば同一の `xterm` でテキストの全く違う部分を選択した時)、同クライアントは、まるで自分が所有者でなかったかのように、新しいタイムスタンプを用いてセレクションの所有権を取得し直すものとする。また、セレクションの値が変更されたものの、それが依然として同一の選択対象であると見做せる場合[3]、所有者は何もしない。

## セレクションの所有権の抛棄

クライアントは自発的にセレクションの所有権を抛棄することができる。また、他のクライアントの行動の結果、強制的にセレクションの所有権を失うこともある。

### 自発的なセレクション所有権の抛棄

クライアントは、セレクションの所有権を自発的に手放したい場合、同セレクションのアトムに対して `SetSelectionOwner` リクエストを実行する。その際、owner には `None` を指定し、time には同セレクション取得時に用いたタイムスタンプを指定する。

他にも方法はあり、クライアントは `SetSelectionOwner` リクエストの owner の値として使ったウィンドウを破壊してもよいし、クライアント自身が終了してもよい。どちらの場合も、消えたウィンドウやクライアントに属していたセレクションの所有権は `None` に戻ることになる。

### 強制的なセレクション所有権の剥奪

あるクライアントがセレクションの所有権を抛棄した時、あるいは別のクラアントが先のクライアントの所有するセレクションに対して `SetSelectionOwner` を実行し、強制的にセレクションが移った時、それまでの所有者は `SelectionClear` イベントを受け取ることになる。イベント `SelectionClear` の定義は、セレクション所有者の仕事を見よ。

`SelectionClear` の timestamp は、セレクションの所有権が移った時刻である。同イベントの owner は、現在の所有者(訳註：前所有者)が `SetSelectionOwner` リクエストの際に指定したウィンドウである。

## セレクションを要求する

セレクションの値を特定型式に変換して取得したいクライアント(要求者)は、リクエスト `ConvertSelection` を発行する。同リクエストの定義は次の通り。

`ConvertSelection`

selection, target: ATOM
property: ATOM もしくは `None`
requestor: WINDOW
time: TIMESTAMP もしくは `CurrentTime`

引数 selection には目的のセレクションを指定する。引数 target には、どのような型に変換した情報が必要なのか、その型式を指定する。ターゲット型の指定に用いるアトムの選び方は、「セレクション・アトムの使い方」 を参照。要求者は、引数 requestor に自分が生成したウィンドウを指定するものとする。このウィンドウに所有者が返答用のプロパティを置くことになる。要求者が引数 time に渡すタイムスタンプは、目的のセレクションの値を要求する切っ掛けとなったイベントのタイムスタンプとする。クライアントは `CurrentTime` を指定してはならない。

> 規約

> クライアントは `ConvertSelection` リクエストの引数 time に `CurrentTime` を指定してはならない。代わりに、同リクエスト発行の原因となったイベントのタイムスタンプを使用する。

要求者は、セレクションの値の報告に所有者が使ってよいプロパティの名前を引数 property に指定する。また要求者は、指定したプロパティが requestor で指定したウィンドウに存在しないようにしてから、`ConvertSelection` リクエストを発行するものとする[4]。但し、要求者がリクエストに外部引数を設ける場合は、この規則の例外である(詳細は下記)。

> 玄論

> 要求者は、リクエストを発行する前に、使用するプロパティを消去する必要がある。これは、将来ターゲットが外部引数を取るように拡張された時に、互換性の問題が生じないようにするためである。また、セレクションの要求者は、目的のセレクションを所有しているクライアントも、目的セレクションが所属しているウィンドウも、ともに知る必要がないことに注意。

ターゲットの定義によっては、要求者が `ConvertSelection` リクエストの引数に加えて外部引数を渡せることもある。要求者は、`ConvertSelection` リクエストに外部引数を渡したい場合、同リクエストの発行に先立って、requestor で指定する予定のウィンドウの property で指定する予定のプロパティに外部引数を格納しておき、その上で `ConvertSelection` リクエストにて同プロパティを指定するものとする。

ターゲットの定義によっては、外部引数を与えても与えなくても良いということもある。要求者は、そのようなターゲットを指定する `ConvertSelection` リクエストに外部引数を与えない場合、引数 property のプロパティが存在しないように手を打ってから同リクエストを発行するようにしなければならない。

X プロトコルでは property フィールドに `None` を渡すことが認められており、その場合、所有者がプロパティ名を選択するものと想定している。しかしながら、所有者がこの選択を安全に実行するのは難しい。

> 規約

> - 要求者は、`ConvertSelection` リクエストの引数 property に `None` を使用してはならない。

> - 引数 property が `None` である `ConvertSelection` リクエストを受け取った所有者は、古いクライアントと話していることになる。そうした所有者は、target のアトムを返答用のプロパティの名前として使用しなければならない。

`ConvertSelection` リクエストを送信すると、要求者の元にはイベント `SelectionNotify` が返って来る。`SelectionNotify` イベントの定義は「セレクション所有者の仕事」を参照。

このイベントの requestor、selection、time、target は、`ConvertSelection` リクエストの引数と同じになる。(訳註：libX11.htmlによると「The time member is set to the time the conversion took place and can be a timestamp or CurrentTime. 」。xsel.cのINCR転送ではtargetにincr_atomを入れている。)

property が `None` であれば、変換が拒否されたことを意味する。その原因には次の３つのものが考えられる。即ち、要求されたセレクションに所有者が存在しなかったため、target で指定された変換処理に所有者が対応していなかったため、あるいはデータを受け入れるのに十分な領域がサーバに無かったためである。

property が `None` でなければ、そのプロパティは requestor のウィンドウにあるはずである。セレクションの値はリクエスト `GetProperty` を用いて同プロパティから取り出すことができる。このリクエストの定義は次の通り。

`GetProperty`

window: WINDOW
property: ATOM
type: ATOM もしくは `AnyPropertyType`
long-offset, long-length: CARD32
delete: BOOL
->
type: ATOM もしくは `None`
format: {0, 8, 16, 32}
bytes-after: CARD32
value: LISTofINT8 or LISTofINT16 or LISTofINT32 (訳註：「LISTof〜」の定義はX Window System Protocol(x11protocol.html)にある。)

`GetProperty` を使用してセレクションの値を取得する場合、引数 property には `SelectionNotify` イベントの property の値を入れる。引数 type には `AnyPropertyType` を指定する。セレクションの所有者がどの型を採用するのかを要求者があらかじめ知る術は無いからである。セレクションの全データを取得するために複数回の `GetProperty` リクエストが必要になることもある。その場合、同リクエストの呼び出しの度に、引数 long-offset に受け取り済みのデータ量を指定し、引数 size (訳註：long-length)に適当なバッファ・サイズを指定する(「大量のデータの転送」を見よ)。bytes-after に入れられた戻り値が 0 であれば、プロパティ全体の転送が完了したということである。

要求者は、セレクションの全データを取り出し終えたら(これには複数のプロパティから値を得なければならない場合もある、「セレクション・プロパティの使用」 を参照)、引数 delete に `True` を指定した `GetProperty` リクエストを用いて、`SelectionNotify` イベントの property が指すプロパティを削除するものとする。前述のように、使用したプロパティが削除されない限り、所有者にはデータが要求者に届いたことを知る術がない。

> 規約

> 要求者は、全データを取り出し終えたら、`SelectionNotify` で指定されたプロパティを削除しなければならない。要求者は、セレクションの全データを問題なく取り出し終えたならば、`DeleteProperty` か `GetProperty`(delete==True) のどちらかを呼び出さなければならない。詳しくは「大量のデータの転送」を見よ。

## 大量のデータの転送

セレクションのデータは大きくなることがある。これには２つの問題がある。

- サーバへ大量のデータを転送するのは高くつく。

- 全てのサーバには、プロパティに格納できるデータの量に上限がある。この上限を超えてしまうと、セレクションの所有者がデータを格納するために呼び出す `ChangeProperty` リクエストにおいて、`Alloc` エラーが生じることになる。

サーバの資源が有限であることから生じる問題は、次の規約で対処する。

> 規約

> - セレクションの所有者は、大きなセレクションの中身を転送するにあたって、INCR プロパティ機構を利用するものとする(ここでの「大きな」とは、所有者が接続開始時に受け取った maximum-request-size (訳註：X Window System Protocolでは「maximum-request-length」)の値より大きな、という意味)。INCR プロパティ を見よ。

> - `SetSelectionOwner` を用いてセレクションの所有権を取得するクライアントは全て、プロパティ変更リクエストの際に起きる `Alloc` エラーを処理できるよう予め備えておくものとする。Xlib を利用しているクライアントであれば、関数 `XSetErrorHandler` を呼び出して、デフォルトのハンドラを上書きする。

> - セレクションの所有者は、セレクションの内容をプロパティへ格納する際に一切 `Alloc` エラーが生じなかったことを確認するまで、データの格納完了を示す `SelectionNotify` イベントで応答してはならない。

> - 大量のデータ(maximum-request-size最大リクエスト・サイズと比べて)を格納する時は、クライアントは `ChangeProperty (mode==Append)` を連続で用いて、適量に小分けしたデータを順次格納していくものとする。これによって、サーバのロックを回避することができ、`Alloc` エラーが齎すデータの浪費を抑えられる。

> - セレクション・データを格納している途中で `Alloc` エラーが起きた場合、同セレクションのデータを格納したプロパティは全て削除し、`ConvertSelection` リクエストは拒否するものとする(セレクション所有者の仕事を見よ)。

> - セレクションの要求者は、プロパティから大量のデータを取り出す場合、長い時間に渡ってサーバをロックするのを避けるため、`GetProperty` リクエストを複数回に分けて実行し、１つ１つのリクエストでは適量のデータを要求するものとする。

> 実装者のために

> シングル・スレッドのサーバが大量のデータの転送中にロックしないよう気をつける。

## セレクション・アトムの使用

アトムを新たに定義するとサーバの資源が消費され、この資源はサーバを再び初期化するまで解放されない。セレクション・アトムを使用するのは、アトムを新たに造り出す必要性を減らすためである。

### セレクション・アトム

セレクションは任意の数だけ存在することができ、１つのセレクションには１つのアトムが名前として割り当てられる。しかし、クライアント間の規約(inter-client conventions)に合わせるには、クライアントは以下の３つのセレクションに対応するだけで良い。

- PRIMARY

- SECONDARY

- CLIPBOARD

他のセレクションも、仲の良いクライアント集団同士の私的な通信では自由に使用してよい。

#### PRIMARY セレクション

アトム PRIMARY を識別子とするセレクションは、引数を１つしか取らないコマンド全てで使用される。セレクション機構を用いるクライアント同士の通信においては、このセレクションが主要な通信手段となる。

#### SECONDARY セレクション

アトム SECONDARY を識別子とするセレクションの使い方は次の２つ。

- 引数を２つ取るコマンドの第２引数として使用(例えば「PRIMARY セレクションと SECONDARY セレクションを入れ換える」コマンド)。

- PRIMARY セレクションが存在し、利用者がそれを弄りたくないと考えた時、データを得る手段として使用。

#### CLIPBOARD セレクション

アトム CLIPBOARD を識別子とするセレクションは、クライアント間で転送中のデータの保持に用いる。転送中のデータというのは、通常、カット・アンド・ペーストやコピー・アンド・ペーストしている最中のデータである。クライアントは、クリップボードへデータを転送したい時、下記の動作を行う。

- CLIPBOARD の所有権を主張する。

- 所有権の獲得に成功した場合、CLIPBOARD の内容物を求めるリクエストに対して通常の方法で返答できるように備えておく(データを返せるように保持しておく)。このリクエストは、後述のクリップボード管理専門のクライアント(the clipboard client)が発行する可能性もある。

- 所有権の獲得に失敗した場合、カットを行う予定だったクライアントは、カットを実際に行ってはならず、またデータのクリップボードへの転送が完了していると思わせるようなフィードバックも提示してはならない。

所有者は、転送すべきデータが変わる度にこの手続きを再度実行するものとする。

クリップボードのデータをペーストしたいクライアントは、通常の方法で CLIPBOARD セレクションの内容物を要求する。

普通のクライアントが実際にデータを削除・複製している間を除き、CLIPBOARD セレクションを管理するために作られた特別なクライアント１つに同セレクションの所有者の役を固定する方法もある。この種のクライアントは、以下の手順に従って、クリップボードの内容を最新状態に保ち、クリップボードのデータを要求するリクエストに応じる。

- CLIPBOARD セレクションの所有権を主張し、クリップボードのデータが変更される度に所有権を再度主張する。

- クリップボードのセレクションを失った場合(他のクライアントがクリップボードの新しいデータを所持しているために)、

  - `SelectionClear` イベントのタイムスタンプを用いて、新たな所有者からクリップボード・セレクションの内容を取得する。

  - これと同じタイムスタンプを用いて、CLIPBOARD セレクションの所有権を再度主張する。

  - 所有権獲得の試みが失敗したら、新たにタイムスタンプを取得し、本手順を始めからやり直す。新しいタイムスタンプは、CLIPBOARD セレクションの現所有者に対して、同セレクションを TIMESTAMP 型へ変換するよう求めることによって取得する。この変換が拒否された場合、あるいは先のタイムスタンプと同じものがもう一度届いた場合、クリップボード・クライアントは通常の方法で新しいタイムスタンプを獲得するものとする(通常の方法とは例えば長さ 0 のデータをプロパティに追加してPropertyNotifyを発生させ、その中からタイムスタンプを得るやり方)。

- CLIPBOARD の内容を求めるリクエストに通常の方法で応答する。

特別な CLIPBOARD 管理クライアントは必須ではない。カットするクライアントとペーストするクライアントとが用いるプロトコルは、CLIPBOARD 管理クライアントが居ても居なくても同じものである。この特別なクライアントを常駐させるやり方には、以下の利点がある。

- 安定性 - もしカット作業中のクライアントが壊れたり終了したりしても、クリップボードの値は相変わらず取得可能である。

- フィードバック - クリップボード管理クライアントを使って、クリップボードの中身を表示することができる。

- 単純さ - クライアントがデータを削除する時、クリップボードのために長く同データを保持しておく必要がなくなる。結果、問題を起こすような競合状態(race condition)が発生し難くなる。

クリップボード管理クライアントを使わないやり方には、以下の利点がある。

- 性能 - データの転送は、実際に必要になった時しか行われない(即ち実際にデータを要求するクライアントが居た時だけ)。

- 柔軟性 - クリップボードのデータは、取得時に指定できるターゲットの種類を増やせば、複数の形式で取得できるようになる。

### ターゲット・アトム

要求者が `ConvertSelection` リクエストの引数 target に渡すアトムによって、返ってくるデータの型式(form)が決まる。この種のアトムの集合は拡張可能である。しかし、広く受け入れられ、基礎となってくれるような(ターゲット・アトムの)集合も必要である。この出発点として、現在までに提案されているものを下表に挙げる。

アトム | 型 | 受け取るデータ
--- | --- | ---
ADOBE_PORTABLE_DOCUMENT_FORMAT | STRING | [1]
APPLE_PICT | APPLE_PICT | [2]
BACKGROUND | PIXEL | ピクセル値のリスト(訳註：配列の仲間)
BITMAP | BITMAP | ビットマップ ID のリスト
CHARACTER_POSITION | SPAN | セレクションの最初と最後(単位はバイト)
CLASS | TEXT | (WM_CLASS プロパティを参照。)
CLIENT_WINDOW | WINDOW | セレクション所有者の最上位ウィンドウのどれか
COLORMAP | COLORMAP | カラーマップ ID のリスト
COLUMN_NUMBER | SPAN | 最初と最後の列番号
COMPOUND_TEXT | COMPOUND_TEXT | コンパウンド・テキスト
DELETE | NULL | (DELETE を参照。)
DRAWABLE | DRAWABLE | ドローアブル ID のリスト
ENCAPSULATED_POSTSCRIPT | STRING | [3]の「Appendix H」[a]
ENCAPSULATED_POSTSCRIPT_INTERCHANGE | STRING | [3]の「Appendix H」
FILE_NAME | TEXT | ファイルの完全パス名
FOREGROUND | PIXEL | ピクセル値の配列
HOST_NAME | TEXT | (WM_CLIENT_MACHINE プロパティ を参照。)
INSERT_PROPERTY | NULL | (INSERT_PROPERTY を参照。)
INSERT_SELECTION | NULL | (INSERT_SELECTION を参照。)
LENGTH | INTEGER | セレクションのバイト数[b]
LINE_NUMBER | SPAN | 最初と最後の行番号
LIST_LENGTH | INTEGER | セレクションの部分の数
MODULE | TEXT | 選択されている機能部品(module)の名前。(訳註：ICCCMver1.0では「module」。ver2.0では「procedure」であり、これは下の「PROCEDURE」の説明と全く同じ文である。)
MULTIPLE | ATOM_PAIR | (以降の説明を見よ。)
NAME | TEXT | (WM_NAME プロパティを参照。)
ODIF | TEXT | ISO Office Document Interchange Format
OWNER_OS | TEXT | 所有者クライアントのオペレーティング・システム
PIXMAP | PIXMAP[c] | ピクスマップ ID のリスト
POSTSCRIPT | STRING | [3]
PROCEDURE | TEXT | 選択されている手続き(procedure)の名前
PROCESS | INTEGER, TEXT | 所有者のプロセス ID
STRING | STRING | ISO Latin-1 (+TAB+NEWLINE) の文字列
TARGETS | ATOM | 有効なターゲット・アトムのリスト(訳註：配列の仲間)
TASK | INTEGER, TEXT | 所有者のタスク ID
TEXT | TEXT | 所有者が選んだ符号化方式に基づく文字列
TIMESTAMP | INTEGER | セレクション獲得に使用するタイムスタンプ
USER | TEXT | 所有者を動かしているユーザの名前
[a] ターゲット ENCAPSULATED_POSTSCRIPT と ENCAPSULATED_POSTSCRIPT_INTERCHANGE は(それぞれ)、セレクション・ターゲットのレジストリにあるターゲット「_ADOBE_EPS」と「_ADOBE_EPSI」に等しい。「_ADOBE_」ターゲットの使用は止めることになっているが、後方互換性のため、クライアントはこれに対応し続けるべきである。 [b] LENGTH の定義は曖昧である。なぜかというと、セレクションは複数のターゲットに変換される可能性があり、複数の変換のそれぞれでは帰ってくるデータの量が異なり得るからである。複数のターゲットに変換できる場合、その中のどれが LENGTH の結果に対応するのか、要求者には知る術がない。クライアントは、ターゲット LENGTH を指定した変換の結果が信用に値しないものだということを弁えておくべきである。したがって、LENGTH の使用は止めることになっている。 [c] この文書の以前の版には誤りがあり、ターゲットに PIXMAP を指定した変換は DRAWABLE 型のプロパティを返すと記載していた。正しくは PIXMAP 型のプロパティを返す。実装者は、このことを知っておくべきであり、古いクライアントとの互換性を保つため DRAWABLE 型にも対応してよい。

文献:

1. Adobe Systems, Incorporated. Portable Document Format Reference Manual. Reading, MA, Addison-Wesley, ISBN 0-201-62628-4.

2. Apple Computer, Incorporated. Inside Macintosh, Volume V. Chapter 4, "Color QuickDraw," Color Picture Format. ISBN 0-201-17719-6.

3. Adobe Systems, Incorporated. PostScript Language Reference Manual. Reading, MA, Addison-Wesley, ISBN 0-201-18127-4.

上の表は、時が経つに連れて大きくなると思われる。

セレクションの所有者は、下に挙げるターゲットには必ず対応していなければならない。これ以外のターゲットへの対応機能は、あってもなくても良い。

- TARGETS - 所有者は、アトムのリストを返す。このリストに入っているアトムは何れも、現セレクションの変換を試みた時(且つ `Alloc` エラーのような予期せぬ問題が起きなければ)、変換が成功するであろうターゲットを表す。このリストには、所有者が対応していなければならない必須アトムを全て載せるものとする。

- MULTIPLE - ターゲット・アトム MULTIPLE は、`ConvertSelection` リクエストでプロパティが指定された時しか有効にはならない。`SelectionRequest` イベントの property 部が `None`、且つ target 部が MULTIPLE の場合、リクエストは拒否するものとする。

  セレクションの所有者に `SelectionRequest (target==MULTIPLE)` イベントが届いたならば、同イベントで指定されたプロパティにはアトムの対のリストが入っているはずである。１組の対の中では、最初のアトムはターゲットを表し、２番目のアトムはプロパティを表す(ここでは`None` は無効)。所有者は、まるで `SelectionRequest` イベントを(各アトム対に対して１つづつ)連続で受け取ったかのように振舞う。但し、target == MULTIPLE でないイベントを本当に連続で受け取った場合とは、以下の点で振舞いが異なる。

  - 所有者は、要求された変換を全て実行し終えた時しか `SelectionNotify` を返さない。

  - 所有者は、MULTIPLE プロパティ(訳註：`SelectionRequest (target==MULTIPLE)` イベントで指定されたプロパティ)の中のあるアトムの表すターゲットへの変換に失敗した場合、同プロパティの同アトムを `None` で置き換える。

  > 規約

  > MULTIPLE プロパティに入っているアトムの対は、このプロパティに入っている順番通りに処理しなければならない。詳しくは「副作用のあるセレクション・ターゲット」を見よ。

  要求者は、(１回１回の)変換作業で生じたデータを複製し終える度に、同データの格納されていたプロパティを削除する。また、全てのデータを複製し終えたら、要求者は MULTIPLE リクエストの property で使用したプロパティを削除する。

  上記の点を除けば、MULTIPLE によるリクエスト群は個々独立に処理され、その成功・失敗も別々に決まる。ターゲット MULTIPLE は、所有者と要求者との間の通信量を減らす最適化手法であり、トランザクション処理(transaction)の機構ではない。例えば、クライアントが２つのターゲットを含んだ MULTIPLE リクエストを発行したとしよう。１つは何らかのデータを求めるターゲット、もう１つは DELETE ターゲットである。この時、仮にデータを求めるターゲットの変換が失敗に終わっても、DELETE ターゲットはそのまま処理されることになる。

- TIMESTAMP - ある種の競合状態(race condition)の発生を避けるには、所有者が所有権を獲得する際に使用したタイムスタンプを要求者側で取得できることが大切である。プロトコルが変更され、所有権を獲得した際のタイムスタンプを `GetSelectionOwner` リクエストが返すようになるまでは、セレクション所有者は、TIMESTAMP への変換に対応し続けなければならない。TIMESTAMP への変換では、所有者がセレクションの取得の際に用いたタイムスタンプを返す。

### 副作用のあるセレクション・ターゲット

副作用のあるターゲットも存在する(例えば DELETE)。この種のターゲットの処理から曖昧さを除くには、MULTIPLE のプロパティに入っているアトムの対は同プロパティ内での並び順の通りに処理されなければならない。

一般に、副作用のあるターゲットへの変換では情報を返さない。言いかえると、NULL 型で長さ 0 のプロパティを返す(NULL 型とは、`InternAtom` に文字列「NULL」を渡して得られる値のことであり、数値 0 のことではない)。副作用を伴うリクエストでは常に、副作用の処理が終わってから同リクエストの変換が完結するようにしなければならない。リクエストの副作用が実行できない場合、その変換リクエストは拒否しなければならない。

> 規約

> - 副作用のあるターゲットでは、情報は返さない(長さ 0 で NULL 型のプロパティを返す)。

> - ターゲットの副作用の処理が終わってから変換作業が完結するようにしなければならない。

> - ターゲットの副作用が実行できない場合、対応する変換リクエストを拒否しなければならない。

> 問題

> 追加の変換(訳註：副作用として実行される変換)が成功するまで元の `ConvertSelection` リクエストへの応答を遅らせなければならないために、イントリンシクスのインターフェイスに無視できない問題が発生している。

こうした副作用のあるターゲットは、「PRIMARY セレクションと SECONDARY セレクションを交換する」といった操作を実装するのに使用する。

#### DELETE

セレクションの所有者は、所有セレクション(の１つ)を DELETE に変換するよう要求された場合、そのセレクションを削除する(この動作が所有者の内部のデータ構造に関してどのような意味を持つのかは、本規約では定めない)。また、削除に成功すれば、所有者は NULL 型で長さ 0 のプロパティを返す。

#### INSERT_SELECTION

セレクションの所有者に所有セレクション(の１つ)を INSERT_SELECTION へ変換してほしいというリクエストが届いた場合、そのリクエストの property で指定されたプロパティには ATOM_PAIR 型のデータが格納されているはずである。このアトムの対の内、最初のものはセレクションを表し、２番目のものはターゲットを表す。所有者は、セレクション機構を用いて、指定されたセレクションを指定されたターゲットに変換し、その変換結果を INSERT_SELECTION リクエストの selection が指すセレクションの位置へ挿入する(この動作が所有者の内部のデータ構造に対してどのような意味を持つのかは、本規約では定めない)。

#### INSERT_PROPERTY

セレクションの所有者は、所有セレクション(の１つ)を INSERT_PROPERTY に変換するよう要求された場合、INSERT_PROPERTY リクエストで指定されたプロパティを同リクエストで指定されたセレクションの位置に挿入する(この動作が所有者の内部のデータ構造に対してどのような意味を持つのかは、本規約では定めない)。(訳註：原文では INSERT_SELECTION リクエストで指定された〜。)

## セレクション・プロパティの使用

セレクションのデータの転送に使用するプロパティの名前は、要求者が決める。`ConvertSelection` リクエストの property フィールドに `None` を渡すこと(即ちセレクションの所有者にプロパティ名の決定を委ねること)は、本規約では認めていない。

セレクションのデータの転送においては、使用するプロパティの型(type)は常にセレクションの所有者が決める。規約によって特別な役割を与えられている型が幾つかあり、それらを以下の節で説明する。

あるターゲットへの変換を求めるリクエストが返すものは、常に次の２つの中のどちらかである。即ち、前掲の表において同ターゲットに対応するものとして記載してあった型の中の１つを持つプロパティが返るか、さもなければ、まず INCR 型のプロパティが、次いで前掲の表に記載してあった型の中の１つを持つプロパティが返る。

セレクション・プロパティの中には、リソース ID を格納するものもある。セレクションの所有者は、リソースが破壊されていないことと、セレクションの転送が完了するまで同セレクションの内容が変わらないこととを保証するものとする。要求者は、リソースが存在することやリソースの内容が適正であることに依存しているのであれば、リソースの入ったセレクション・プロパティを削除する前にそのリソースを処理しておかなければならない(例えばピクスマップの内容を複製すること等によって)。

セレクションの所有者は、特定の型(「プロパティの型」として通知したもの)の要素(item)が０個以上入ったリストを返す。一般に、このリストの要素の数はセレクションの部分(disjoint parts)の数と一致する。セレクションの部分の数とは関係なく常に長さが 0 となるターゲットも存在する(例えば副作用のあるターゲット)。固定長の要素の場合、要求者はプロパティのサイズを見て要素数を判断することができる。セレクション・プロパティの型を下記の表に記した。テキストのような可変長の要素については、区切り文字も載っている。

型を示すアトム | フォーマット(単位) | 区切り文字
--- | --- | ---
APPLE_PICT | 8 | サイズは自己決定
ATOM | 32 | 固定長
ATOM_PAIR | 32 | 固定長
BITMAP | 32 | 固定長
C_STRING | 8 | Zero
COLORMAP | 32 | 固定長
COMPOUND_TEXT | 8 | Zero
DRAWABLE | 32 | 固定長
INCR | 32 | 固定長
INTEGER | 32 | 固定長
PIXEL | 32 | 固定長
PIXMAP | 32 | 固定長
SPAN | 32 | 固定長
STRING | 8 | Zero
WINDOW | 32 | 固定長

時が経つにつれ、上の表は大きくなると思われる。

### TEXT 型プロパティ

一般に、テキスト文字列(a text string)のプロパティで使われている文字の符号化方式は、そのプロパティの型(type)で表される。X コンソーシアムの採用した「フォントの命名基準」に則ったフォント名の中に現れる文字集合名と、文字列プロパティの型との間に、単純で可逆性のある対応関係があることが強く望まれる。

アトム TEXT は多型(polymorphic)のターゲットである。TEXT への変換を要求すると、所有者は、自分にとって都合の良い符号化方式のどれにでも変換することができる。どの符号化方式が選ばれたのかは、返されたプロパティの型で判断することになる。TEXT は、型として定義されてないので、セレクション変換リクエストが返すデータの型には成り得ない。

要求者は、所有者から特定の符号化方式でセレクションの中身を返してもらいたい場合、その符号化方式の名前をターゲットに指定して変換リクエストを出すものとする。

ターゲット・アトムの表の(型の欄の) TEXT という語は、登録されている符号化方式名の中の何れか１つを表す。実際の型は TEXT ではなく、STRING か、あるいは所有者が採用した符号化方式を表す ATOM である。

型・ターゲットとしての STRING は、ISO Latin-1 文字集合に制御文字の TAB (８進表記で 11)と NEWLINE (８進表記で 12)を加えたものを表す。TAB の幅の解釈は文脈(context)に依存する。現時点では、他の ASCII 制御文字は間違いなく STRING には含まれない。

型・ターゲットとしての COMPOUND_TEXT は、コンパウンド・テキスト相互変換形式を表す(訳註：要確認)。「Compound Text Encoding」を見よ。

テキスト・オブジェクトの中には、作り手も受け手の利用者も特定の文字集合を想定しておらず、0 を終端とするバイト列でありさえすれば足り、それ以外の縛りはない、という性質のものもある。セレクション機構の如何なる部分も、特定のバイト値が禁止されていると想定したり、２つの異なるバイト列が同じものとして扱われると想定したりはしない[5]。こうしたオブジェクトに対しては C_STRING 型を使用する。

> 玄論

> C_STRING が必要になるのは、例えばファイル名を伝える時である。多くのオペレーティング・システムでは、ファイル名の解釈にあたって文字集合を考えない。具体的に言うと、同一の文字列は ASCII と EBCDIC とでは異なるバイト列で表されるのだが、大部分のオペレーティング・システムは、この２つを異なるファイル名と見做してしまうし、これらを同じものとして扱う手段を一切備えていない。従って、この場合には文字集合に基づくようなプロパティ型の利用は適していない。

STRING、COMPOUND_TEXT、C_STRING 型のプロパティは、null 文字で区切られた要素のリストから成る。これ以外の符号化方式を用いる場合、適切なリストの形式を指定する必要がある。

### INCR 型プロパティ

セレクションの要求者は、セレクション・データを返す類のターゲットを指定した場合、返答として INCR 型[6]のプロパティを受け取ることがある。

これは、セレクションの所有者が実際のデータを複数回に分けて順次送信するつもりであることを表す。INCR プロパティの中身は整数１個であり、セレクションのデータのバイト数の下界の数値が入る。セレクションの要求者と所有者は、セレクションのデータを次のように転送する。

セレクションの要求者が、要求したセレクションの代わりに返ってきた「type==INCR」のプロパティを削除することによって、転送処理が始まる。

セレクションの所有者は続いて、

- 変換したセレクションの実際の型を伝えるセレクション・リプライで指定したものと同じウィンドウ、同じプロパティに、適当な大きさに小分けしたデータを格納する。データの大きさは、X サーバとの接続のハンドシェイクの際に受け取った最大リクエスト・サイズより小さく設定するものとする。

- データの追納と追納の間、要求者がデータを読み終えたことを示すイベント `PropertyNotify`(state==Deleted) を待ち受ける。これは、サーバの領域の消費量を限定するためである。

- サーバに全データを転送した後、要求者がデータを読み終えたことを示すイベント `PropertyNotify`(state==Deleted) を待ってから、長さ 0 のデータを先のプロパティに書き込む。

セレクションの要求者は、

- イベント `SelectionNotify` を待ち受ける。

- 次を繰り返す。

  - 引数 delete に `True` を指定して `GetProperty` を呼び出し、データを取ってくる。

  - state 部の値が `NewValue` の `PropertyNotify` を待ち受ける。

- `PropertyNotify` イベントの指すプロパティの長さが 0 になるまで待つ。

- 長さが 0 になった上記のプロパティを削除する。

分割されたデータを転送するプロパティの中、最初のものの型が変換済みセレクションの型になる。残りの部分を転送するプロパティも同じ型でなければならない。

### DRAWABLE 型プロパティ

要求者が受け取るプロパティには、PIXMAP 型、BITMAP 型、DRAWABLE 型、WINDOW 型のものもある。どの型のプロパティにも、その型に応じた リソース ID が格納されている。これらのドローアブルに関する情報はリクエスト `GetGeometry` を用いてサーバから取得可能だが、以下のものはそうではない。

- 前景ピクセル(Foreground pixel)

- 背景ピクセル(Background pixel)

- カラーマップ ID

一般に要求者は、ターゲット・アトムの表で戻り値の型がドローアブルの一種であると記載されているターゲットを変換対象に指定する場合、(MULTIPLE の仕組みを使って)以下のターゲットへの変換も考えておくべきである。

- FOREGROUND ターゲット。PIXEL 型の値が返る。

- BACKGROUND ターゲット。PIXEL 型の値が返る。

- COLORMAP ターゲット。カラーマップ ID が返る。

### SPAN 型プロパティ

SPAN 型のプロパティには、基数(cardinal)の対のリスト(訳註：配列の仲間のリスト)が入る。このリストの長さは、基数の個数と形式(訳註：format、８、１６、３２？)で決まる。基数の対の中、最初の数値は開始位置を表し、２番目のものは終了位置に 1 を加えたものを表す。先頭は 0 である。開始位置と終了位置の値が同じである場合、範囲(span)の幅は 0 であり、開始位置・終了位置はともに数値の指す位置の直前にある。数値の単位は、LINE_NUMBER や CHARACTER_POSITION といったターゲット・アトムで示す。

## マネージャ・セレクション(マネージャで管理するセレクション)

ある種のクライアントは共有資源の管理役を務める。マネージャと呼ばれることが多い。共有資源を管理するクライアントは、命名規約と辨別名の規約とに則った名前を持つ、適切なセレクションの所有権を取得するものとする。複数の共有資源を(あるいは複数の資源群を)管理するクライアントは、各資源に対して１つづつ、セレクションの所有権を取得する。

マネージャは、このようなセレクションを様々なターゲットに変換する機能を備えることができる。クライアントから管理資源を操作する際の主たる手段として、マネージャにこの機能を備え付けておくのが望ましい。ウィンドウ・マネージャとのやり取りに関する規約は本節の規約よりも古くからあることに注意。結果として、ウィンドウ・マネージャとのやり取りの多くは、別の仕組みを利用している。

マネージャは、マネージャ・セレクションの所有権を取得する前に `GetSelectionOwner` リクエストを用い、他のクライアントが既に同セレクションを所有してないか確認する。そして、他のクライアントが所有していた場合、古いマネージャと代わって良いかどうか、新しいマネージャは利用者に対して確認する(必要であれば)。両方の確認で問題がなければ、その時はマネージャは目的のセレクションの所有権を取得することができる。マネージャは、特にこの目的のために作成したウィンドウを用いて、セレクションを獲得するものとする。マネージャは「セレクションの所有権の獲得」と「セレクション所有者の仕事」で述べたセレクション所有者の規則に従わなければならず、また「セレクション・アトムの使用」で挙げた必須のターゲットに対応していなければならない。

マネージャがマネージャ・セレクションの所有権を失うことがあれば、それは新しいマネージャがその仕事を引き継ごうとしていることを意味する。前のマネージャは、自分が管理していた資源の全てを解放し、次いでマネージャ・セレクションを所有していたウィンドウを破壊しなければならない。例えば、WM_S2 の所有権を失うウィンドウ・マネージャは、同セレクション(WM_S2)を所有していたウィンドウを破壊する前に、スクリーン 2 のルート・ウィンドウの `SubstructureRedirect` マスクの選択を解除しなければならない。

新しいマネージャは、目的のセレクションを所有していたウィンドウが破壊されたことを知った場合、管理するつもりであった資源の制御に取りかかって良いものと判断する。古いマネージャが適正な時間の内にウィンドウを破壊しない場合、新しいマネージャは、同ウィンドウを破壊したり古いマネージャを終了させたりする前に、先ず利用者に問い合わせるべきである。

マネージャは、自分がセレクションによって制御している共有資源の管理を自発的に抛棄したい場合、先ず管理中の資源を解放し、それからセレクションを所有しているウィンドウを破壊するという手順でこれを行わなければならない。先にセレクションを抛棄するべきではない。このやり方だと競合状態(race condition)が生じる。

クライアントは、マネージャ・セレクションの所有者が同セレクションに対応する共有資源の管理を止めた時にその事実を知らせてほしいのであれば、セレクションを所有しているウィンドウの `StructureNotify` マスクを選択するものとする。こうすることで、同ウィンドウが破壊された時に通知を受けられるようになる。またクライアントは、`GetSelectionOwner` を実行し `StructureNotify` マスクを選択した後、再び `GetSelectionOwner` を実行するべきである。２回目の `GetSelectionOwner` によって、最初にセレクション所有者を把握してから `StructureNotify` マスクの選択までの間に所有者が代っていないことを確認できる。

マネージャは、マネージャ・セレクションの所有権の獲得に成功したら、直ちに `ClientMessage` イベントを送信し、所有権の移転を弘報する。このイベントの送信にはプロトコル・リクエスト `SendEvent` を使用し、引数は以下のように設定する。

引数 | 値
--- | ---
destination: | スクリーン 0 のルート・ウィンドウ。マネージャが特定スクリーンに固有の資源を管理している場合は、そのスクリーンのルート・ウィンドウ。
propogate: | False
event-mask: | `StructureNotify`
event: | `ClientMessage`
type: | MANAGER
format: | 32
data[0][a] | タイムスタンプ
data[1]: | マネージャ・セレクションのアトム
data[2]: | セレクションを所有しているウィンドウ
data[3]: | マネージャ・セレクション次第のデータが入る
data[4]: | マネージャ・セレクション次第のデータが入る
[a] data[n] は、`ClientMessage` の data フィールドにあるデータを format フィールドに従ってリストとして解釈したもの(LISTofINT8、LISTofINT16、あるいは LISTofINT32)の n 番目の要素を表す。このリストの要素番号は 0 から始まる。

クライアントは、特定のマネージャが起動した時に通知を受け取りたければ、適切なルート・ウィンドウの `StructureNotify` マスクを選択し、目的の MANAGER 型 `ClientMessage` を待ち受けるものとする。

[2] 今のところ、X11プロトコルの中には、セレクションの要求者が所有者にイベントを送信しなければいけない場面はない。この制限は、将来の拡張に備えてのものである。

[3] この二つの場合のどちらに当たるのかは、ソフトウェア開発者の判断次第である。

[4] この要件は 2.0 版で導入された。そのため、既存のクライアントは一般にこの要件を満たさない。そうしたクライアントが壊れるのを防ぐため、クライアントに十分な更新期間が与えられるまでは、既存のターゲット型を拡張して外部引数を取れるようにしてはならない。ターゲット MULTIPLE は、1.0 版にて外部引数が取れるように定義され、その定義は今版でも変わっていないことに注意。そのため、MULTIPLE 型ターゲットはこの要件に関する問題は無い。

[5] これは、禁止されたバイト値がたくさんある STRING とは異なる点である。また、バイト列 27,\ 40,\ 66 (ASCII を GL に写す：訳註：要確認)を先頭に挿入しても意味が変わらない COMPOUND_TEXT とも異なっている。

[6] 以前の草案では、このプロパティを INCREMENTAL と呼んでいた。このプロパティを使っているプロトコルが変更されたので、混同を避けるため名前も変更された。

## 第３章 カット・バッファを用いた２者間通信

カット・バッファ機構はセレクション機構に比べてとても単純であるが、とても貧弱である。セレクション機構は、所有者たるクライアントと要求者たるクライアントとの間に接続を提供することから、能動的(active)であると言える。一方、カット・バッファ機構は受動的(passive)であると言える。なぜかというと、所有者がカット・バッファにデータを置き、後になって要求者がそこから同データを取り出す仕組みであるから。

カット・バッファは、スクリーン「0」のルート・ウィンドウに属する８つのプロパティから成る。このプロパティ群は、予約アトムである CUT_BUFFER0 から CUT_BUFFER7 を使って表す。これらのプロパティは、現時点では、型は STRING、形式は「8」でなければならない。カット・バッファ機構を使うクライアントは先ず、８つのプロパティ全てに対して追加データ長 0 の `ChangeProperty` リクエストを発行し、同プロパティ全てが存在することを確かめなければならない。

カット・バッファにデータを格納しようとするクライアント(所有者)は、先ずリクエスト `RotateProperties` を使って、バッファの環を＋１だけ回転させ、各バッファの名前を替えなければならない。回転の結果、CUT_BUFFER0 が CUT_BUFFER1 に、CUT_BUFFER1 が CUT_BUFFER2 に、・・・、CUT_BUFFER7 が CUT_BUFFER0 になる。次いで同クライアントは、`Replace` モードを指定してリクエスト `ChangeProperty` を 呼び出し、CUT_BUFFER0 にデータを格納しなければならない。

カット・バッファからデータを取得しようとするクライアントは、リクエスト `GetProperty` を用いて CUT_BUFFER0 の中身を取り出すものとする。

利用者のリクエストが１つ届いたら、それに応じてクライアントは、リクエスト `RotateProperties` を使ってカット・バッファの環をー１だけ回転させ、各バッファの名前を付け替えることができる。回転の結果、 CUT_BUFFER7 が CUT_BUFFER6 に、CUT_BUFFER6 が CUT_BUFFER5 に、・・・、CUT_BUFFER0 が CUT_BUFFER7 になる。

利用者が明示的な動作によって要求した時に限って、カット・バッファへのデータの格納とバッファの環の回転とが行われるものとする。利用者は、自分の頭の中にあるカット・バッファ操作のモデルを頼りにしており、データを送受信する操作がどれなのか見つけられる必要がある。

## 第４章 クライアントとウィンドウ・マネージャの通信

スクリーン空間(screen space)のような資源に対して、競合する複数の要求が存在することがある。ウィンドウ・マネージャはそうした要求を調整する役割を持っているが、この役割を果たすには次の２つのことが必要である。１つは、マネージャによって管理されるクライアントがある種の規約を守ること、もう１つは同クライアントがウィンドウ・マネージャも自分と同様に振舞うものと想定して動作する(そのように作られている)ことである。以下では、クライアントの視点からこの種の規約を説明する。

一般に、このような規約はいくぶん複雑であり、しかもウィンドウ管理の新たなパラダイムが開発されれば同規約も変更されることになる。したがって、ウィンドウ管理のあらゆるパラダイムに漏れ無く対応可能で、且つ本質のみから成るような規約群しか定義しない、という態度が本章の基調となる。特定のウィンドウ・マネージャと一緒に動作するよう設計したクライアントならば、簡単に私的なプロトコルを定義して先の規約群に付け足すことができるだろう。しかし、そのようなクライアントは、利用者が他のウィンドウ・マネージャを使う場合のことも織り込んでおかなければならない。私的プロトコルの設計者が、自分はユーザ・インターフェイスの「真の光」を見たとどんなに確信しているとしても。

本章の規約群には原則がある。一般的なクライアントは、どのウィンドウ・マネージャが動作しているのか、あるいはそもそも動作しているウィンドウ・マネージャが存在するのかについて、知るべきではなく、関心を持つべきでもない、という原則である。ウィンドウ・マネージャが動作していない場合、本章の規約はクライアントの機能の全てを賄うわけではない。例えば、アイコン状態(Iconic)という概念はクライアントが直接解釈するものではない。ウィンドウ・マネージャが１つも動作していない状況では、アイコン状態という概念は役に立たない。本章の規約の目標は、クライアントの機能性を損なうことなくウィンドウ・マネージャを停止したり再起動したりできるようにすることである。

ウィンドウ・マネージャはそれぞれ、独自のウィンドウ管理方針を持つことになる。利用者の環境に合うようなウィンドウ管理方針の選択は、個々のクライアントによってではなく、利用者や利用者のシステムの管理人によって為される。これによって、私的なプロトコルを用い、結果として特定のウィンドウ・マネージャの下でしか動作しないようなクライアントの作成が禁止されるわけではない。むしろ、このウィンドウ管理方針の件は、そのようなクライアント・プログラムに対して汎用性は要求されないことを保証しているだけである。

「私が書いているクライアントは重要なので、一番手前に表示する必要がある」という要求がよくある。このクライアントが本格的に操作されている時は、これは重要なのだろう。この場合、何らかの私的なプロトコルを通じて「重要」なウィンドウを認識し、且つ必ずこの種のウィンドウを最前列に表示するようなウィンドウ・マネージャの管制下でこそ、同クライアントを動作させるべきである。しかしながら、例えば「重要な」クライアントがデバッグされているのを想像してみよ。すると、「重要な」ウィンドウを常に一番手前に表示するよう保証することは、もはや適切なウィンドウ管理方針ではない。この場合には、他のウィンドウ(例えばデバッガ)を手前に表示できるウィンドウ・マネージャの下で、同クライアントを動作させるべきである。

## クライアントの動作

X バージョン 11の設計目標に照らせば、一般にクライアントは、ウィンドウ・マネージャが存在する時もしない時も出来る限り同じ動きをするべきであるが、例外もある。以下の動作が例外である。

- 取得したい資源についてのヒントをウィンドウ・マネージャに提示する。

- 自分に割り当てられた資源が自分の要求したものでなかったとしても、素直にこれを受け取ってウィンドウ・マネージャと協働する。

- いつ資源の割当てが変わっても対処できるよう備えておく。

### 最上位ウィンドウの作成

クライアントの最上位ウィンドウとは、オーバライド・リダイレクト(override-redirect)の属性が `False` であるウィンドウのことである。また、最上位ウィンドウは、ルート・ウィンドウの子であるか、あるいはウィンドウ・マネージャによって親を変更される直前までルート・ウィンドウの子であったものでなければならない。クライアントがウィンドウの親をルート・ウィンドウでないものに変更すれば、そのウィンドウはもはや最上位ウィンドウではない。しかし、クライアントがそのウィンドウの親をルート・ウィンドウに戻せば、同ウィンドウは再び最上位ウィンドウになれる。

クライアントは通常、下記のような定形の式を用いて、１つ以上のルート・ウィンドウの子供として自身の最上位ウィンドウを作成する。

    window = XCreateSimpleWindow(display, DefaultRootWindow(display), xsh.x, xsh.y,
         xsh.width, xsh.height, border_width, border, background);

しかしながら、数あるルート・ウィンドウの中の特定のもの(１つ)を使いたい場合、クライアントは次のような式を用いる。

    window = XCreateSimpleWindow(display, RootWindow(display, screen), xsh.x, xsh.y,
         xsh.width, xsh.height, border_width, border, background);

ルート・ウィンドウの指定を上書きできて、クライアント(ウィンドウ・マネージャを含む)がルート・ウィンドウでないウィンドウを擬似ルート・ウィンドウとして扱えるのが理想である。これによって、例えばウィンドウ・マネージャの試験ができるようになったり、アプリケーション固有のウィンドウ・マネージャを用いて、仲間のクライアントが所有する下位ウィンドウ群を制御できるようになったりする。このような動作を正確に実現するには拡張が必要であり、その設計は研究中である。

クライアント側から見ると、ウィンドウ・マネージャはクライアントの最上位ウィンドウを下記のいづれかの状態にあると見做すものと考えられる。

- Normal(通常状態)

- Iconic(アイコン状態)

- Withdrawn(引っ込んでいる状態)

新たに作成されたウィンドウは、最初は Withdrawn 状態である。状態の遷移が起きるのは、最上位ウィンドウがマップされたり(訳註：表示可能状態になること)アンマップされたりした時と、ウィンドウ・マネージャが特定のメッセージを受け取った時である。詳しくは WM_HINTS プロパティ及びウィンドウの状態の変更を見よ。

### クライアント・プロパティ

クライアントは、１つ以上の最上位ウィンドウを持つに至った時は、このウィンドウにプロパティを設置し、自身の望む振る舞いをウィンドウ・マネージャに知らせるものとする。クライアントが指定しなかったプロパティについては、ウィンドウ・マネージャは自身にとって都合の良い値が設定されたものと見做す。特定のプロパティ値を当てにしているクライアントは、明示的にその値を指定しなければならない。ウィンドウ・マネージャは、クライアントが書き込んだプロパティを変更しないことになっている。

ウィンドウ・マネージャは、ウィンドウの状態が Withdrawn から別のものへ移る時には、これらのプロパティの内容を調査することになる。また、ウィンドウ・マネージャは、ウィンドウの状態が Iconic や Normal である時にも、一部のプロパティに変更がないか監視している。クライアントがこうしたプロパティの中の１つを変更する場合、`Replace` モードを用いて同プロパティ全体を新しいデータで上書きしなければならない。ウィンドウ・マネージャはこのプロパティの古い値は記憶していない。`Replace` モードを指定した `ChangeProperty` リクエスト１回で同プロパティのフィールド全てに適切な値が設定されなければならない。こうすることで、次のような場合でも新しいウィンドウ・マネージャが同プロパティの完全な内容を取得できるようになる。例えば、既存のウィンドウ・マネージャが壊れた場合、ウィンドウ・マネージャが一旦終了して再開する場合、あるいはセッション・マネージャによってセッションを一旦終了して再開する必要がある場合。

> 規約

> ウィンドウ・マネージャのためのプロパティを書いたり書き直したりするクライアントは、１つ１つのプロパティの内容全体が常に有効であるように計らわなければならない。

これらのプロパティの中には、ウィンドウやピクスマップのようなリソースの ID が入っているものもある。クライアントは、少なくともこの種のプロパティが設置されているウィンドウが存在する間は、そうしたリソースが存在し続けるように計らうものとする。

これらのプロパティ(クライアント・プロパティ)のサイズが予想よりも長かった場合、クライアントはそのプロパティの余った部分を無視するものとする。これらのプロパティを拡張する権限は X コンソーシアムにあり、私的な拡張を施すことは禁じられている。クライアントとウィンドウ・マネージャの間で私的な交信を追加で行うには、クライアント・プロパティとは別のプロパティを用いるべきである。この規則の唯一の例外は WM_PROTOCOLS プロパティである。このプロパティは、長さが任意であり、私的なプロトコルを表すアトムを保持することができる(WM_PROTOCOLS プロパティを見よ)。

以降の節では、クライアントが設定する必要のあるプロパティを１つづつ順番に説明する。これらのプロパティは「ウィンドウ・マネージャ・プロパティの型のまとめ」にある表に纏めてある。

#### WM_NAME プロパティ

WM_NAME プロパティは、解釈・翻訳されない文字列である。この文字列は、クライアントがウィンドウ・マネージャに対して「ウィンドウと協力して表示して欲しい」と思っているものである(例えば、ウィンドウのヘッドライン・バーに)。

この文字列(及び他の全ての解釈されない文字列プロパティ)の符号化方式は、プロパティの型(type)で示す。この目的で使用する、型を表すアトムについては、TEXT 型プロパティで説明してある。

ウィンドウ・マネージャは、この情報を表示する努力をするべきである。WM_NAME を完全に無視するのは、容認できない振る舞いである。クライアントは次の２つのことを想定して良い。即ち、この文字列の少なくとも最初の部分は利用者に見えているということと、もしこの情報が利用者に見えていないのであれば、それは利用者が明確な操作を行って見えなくしたということである。

一方、たとえウィンドウ・マネージャがウィンドウのヘッドライン(の表示)に対応しているとしても、利用者が WM_NAME の文字列を見ることができる保証は無い。利用者がヘッドラインをスクリーンの外に持っていったかもしれないし、ヘッドラインを他のウィンドウで隠したかもしれないからである。WM_NAME は、アプリケーションの重要な情報の表示のために用いるべきではなく、また、アプリケーションの状態の非同期的な変更(利用者の適時の応答を必要とするもの)を知らせるために用いるべきでもない。想定している用途は、利用者が同一クライアントの数あるインスタンスの中の１つを識別できるようにすることや、利用者にアプリケーションの重要でない状態情報を提供することである。

ヘッドライン・バーに対応しているウィンドウ・マネージャでも、表示できる WM_NAME 文字列の長さに制限を設けているはずである。簡潔であると後で良いことがある、と言える。

#### WM_ICON_NAME プロパティ

WM_ICON_NAME プロパティは、解釈・翻訳されない文字列である。この文字列は、クライアントが(ウィンドウ・マネージャに対して)「ウィンドウがアイコン化した時にウィンドウと協力して表示して欲しい」と思っているものである(例えば、アイコン・ラベルの中に)。この他の点では、型も含めて WM_NAME と同様である。ジオメトリ(大きさと位置)上の明らかな理由から、通常 WM_ICON_NAME では WM_NAME より少ない文字数しか表示されない。

クライアントは、自身のアイコン・ピクスマップやウィンドウにこの文字列を表示しようと試みてはいけない。ウィンドウ・マネージャにそうするよう頼むべきである。

#### WM_NORMAL_HINTS プロパティ

プロパティ WM_NORMAL_HINTS の型は WM_SIZE_HINTS である。その中身は下表の通り。

フィールド | 型(Type) | 註釈
--- | --- | ---
flags | CARD32 | (次の表を参照)
pad | 4*CARD32 | 後方互換性のために
min_width | INT32 | 空の場合、base_width と同じ値と見做す
min_height | INT32 | 空の場合、base_height と同じ値と見做す
max_width | INT32 |
max_height | INT32 |
width_inc | INT32 |
height_inc | INT32 |
min_aspect | (INT32,INT32) |
max_aspect | (INT32,INT32) |
base_width | INT32 | 空の場合、min_width と同じ値と見做す
base_height | INT32 | 空の場合、min_height と同じ値と見做す
win_gravity | INT32 | 空の場合、`NorthWest` と見做す

WM_SIZE_HINTS.flags の各ビットの定義は下表の通り。

名前 | 値 | フィールド
--- | --- | ---
`USPosition` | 1 | 利用者が指定した x、y
`USSize` | 2 | 利用者が指定した width、height
`PPosition` | 4 | プログラム指定の位置
`PSize` | 8 | プログラム指定のサイズ
`PMinSize` | 16 | プログラム指定の最小サイズ
`PMaxSize` | 32 | プログラム指定の最大サイズ
Withdrawn `PResizeInc` | 64 | プログラム指定の、サイズ変更の増加単位(resize increments)
`PAspect` | 128 | プログラム指定の最大・最小の縦横比
`PBaseSize` | 256 | プログラム指定の基本サイズ
`PWinGravity` | 512 | プログラム指定のウィンドウ・グラヴィティ(訳註：サブウィンドウを引き寄せる方角)

(Withdrawn 状態からの遷移が起きた時、)ウィンドウのサイズと位置が利用者によって指定されたことを示すには、クライアントは２つのフラグ `USPosition` と `USSize` を設定するものとする。これによってウィンドウ・マネージャは、利用者がウィンドウの位置とサイズとを具体的に指定してきており、且つこれ以上のやり取りは不要である、ということを知ることができる。ウィンドウのサイズと位置が利用者の関与無しにクライアントによって指定されたことを示すには、クライアントは２つのフラグ `PPosition` と `PSize` を設定するものとする。

サイズ指定の項目には、クライアントのウィンドウの高さ(height)と幅(width)を入れる。この高さと幅にはウィンドウの縁(border)は含まない。

win_gravity には、X プロトコルにて WINGRAVITY の値として規定されている値のどれかが入る(`Unmap` は除く)。`NorthWest` (1)、`North` (2)、`NorthEast` (3)、`West` (4)、`Center` (5)、`East` (6)、`SouthWest` (7)、`South` (8)、及び `SouthEast` (9)の９つである。これによって、クライアント・ウィンドウがウィンドウ・マネージャの枠(window manager frame)の中でどのように寄せられてどの方角に余白を作ることを望むのか、あるいはそもそもどの方角にも寄せられないことを望むのかを指定する。

win_gravity が `Static` である場合、ウィンドウ・マネージャの枠の位置は、枠の中のクライアント・ウィンドウの内縁り(inside border)の位置(スクリーンに対する位置)が、クライアントが Withdrawn 状態からの遷移を要求した時の(同内縁りの)位置(スクリーンに対する位置)と同じになるように設定される。win_gravity の他の値は、ウィンドウの参照点(reference point 基準点)を指定するものである。`NorthWest`、`NorthEast`、`SouthWest`、及び `SouthEast` の場合、参照点はウィンドウの外側の角(外縁りの端outside border edge)に設置される。`North`、`South`、`East` 及び `West` の場合、参照点はウィンドウの指定された方角の縁(border)の外側の端(outer edge)の中心である。`Center` の場合、参照点はウィンドウの中心である。ウィンドウ・マネージャの枠の参照点は、スクリーン上の次の位置である。即ち、クライアントが Withdrawn 状態からの遷移を要求した時にクライアント・ウィンドウの参照点が存在した位置である。

min_width と min_height は、ウィンドウがクライアントにとって有用であり得る最小の大きさを指定するものである。max_width と max_height で最大サイズを指定する。base_width と base_height は、width_inc と height_inc とともに、ウィンドウの適切な幅と高さを表す等差数列を定義する。負でない整数 i と j を用いて、

    width = base_width + ( i x width_inc )

    height = base_height + ( j x height_inc )

ウィンドウ・マネージャがウィンドウ・サイズを利用者に報告する際には、width と height の代わりに i と j を用いるのが望ましい。基本サイズ(base size)が指定されてない場合、代わりに最小サイズを使用し、最小サイズが指定されてない場合、代わりに基本サイズを使用する。

min_aspect フィールドと max_aspect フィールドは分数であり、分子が先、分母が後に入っている。この２つによって、クライアントが自身の望む縦横比の範囲を指定できるようになる。縦横比の指定に対応しているウィンドウ・マネージャは、希望のウィンドウ・サイズを決定するにあたって、基本サイズ(base size)を考慮に入れるものとする。縦横比のフィールドに加えて基本サイズのフィールドも設定されている場合、縦横比が指定の範囲に収まるかを確かめる前に、ウィンドウ・サイズの値から基本サイズの値を減ずる。基本サイズが設定されていない場合、ウィンドウ・サイズの値からは何も引かない。(この用途に関しては、基本サイズの代わりに最小サイズを用いるべきではない。)

#### WM_HINTS プロパティ

WM_HINTS プロパティ(型は「WM_HINTS」)は、ウィンドウ・マネージャへ情報を伝えるために使用する。同プロパティはウィンドウ・マネージャが必要とする情報を運ぶのだが、以下の情報は除かれる。例えば、ウィンドウのジオメトリである。これはウィンドウ自体から手に入る。また、ウィンドウ・ジオメトリの制限(constraints)もそうである。これは構造体 WM_NORMAL_HINTS から手に入る。そして、WM_NAME をはじめとする、別個のプロパティを必要とする種々の文字列も除かれる。WM_HINTS プロパティの内容は下表の通り。

フィールド | 型 | 註釈
--- | --- | ---
flags | CARD32 | (次の表を見よ)
input | CARD32(訳注：XlibではBool) | クライアントの入力モデル
initial_state | CARD32 | 最初にマップされた時の状態
icon_pixmap | PIXMAP | アイコン画像のピクスマップ
icon_window | WINDOW | アイコン画像のウィンドウ
icon_x | INT32 | アイコンの位置
icon_y | INT32 |
icon_mask | PIXMAP | アイコンの形のマスク
window_group | WINDOW | グループ・リーダーたるウィンドウの ID

WM_HINTS.flags の各ビットの定義は次の通り。

名前 | 値 | フィールド
--- | --- | ---
`InputHint` | 1 | input
`StateHint` | 2 | initial_state
`IconPixmapHint` | 4 | icon_pixmap
`IconWindowHint` | 8 | icon_window
`IconPositionHint` | 16 | icon_x & icon_y
`IconMaskHint` | 32 | icon_mask
`WindowGroupHint` | 64 | window_group
`MessageHint` | 128 | (このビットはもはや使わない)
`UrgencyHint` | 256 | 緊急性

WM_HINTS プロパティ無しでウィンドウがマップされた場合、ウィンドウ・マネージャは同プロパティの全てのフィールドの値を自分の都合の良いように決めることができる。

input フィールドは、クライアントの用いる入力フォーカス・モデルをウィンドウ・マネージャに伝えるために使用する(入力フォーカスを見よ)。

Globally Active モデルもしくは No Input モデルのクライアントは、input フラグを `False` に設定する。Passive モデルもしくは Locally Active モデルのクライアントは、input フラグを `True` に設定する。

クライアント側から見ると、ウィンドウ・マネージャはクライアントの最上位ウィンドウを下記のいづれかの状態にあると見做すものと考えられる。

- Normal

- Iconic

- Withdrawn

これらの状態の意味については「ウィンドウの状態の変更」で述べる。作成されたばかりのウィンドウの状態は Withdrawn である。状態間の遷移が起こるのは、最上位ウィンドウがマップされたりアンマップされたりした時や、ウィンドウ・マネージャが特定のメッセージを受け取った時である。

initial_state フィールドの値は、最上位ウィンドウが Withdrawn 状態を脱してマップされた時にクライアントがそうありたいと望む状態を指定する。次表の値をとり得る。

状態 | 値 | 註釈
--- | --- | ---
NormalState | 1 | ウィンドウが見えている状態
IconicState | 3 | アイコンが見えている状態

icon_pixmap フィールドを用いて、アイコンとして使用するピクスマップを指定することができる。このピクスマップは下記の条件を満たすものとする。

- ルート・ウィンドウの WM_ICON_SIZE プロパティが存在する場合、同プロパティで指定されているサイズのいづれかである(「WM_ICON_SIZE プロパティ」を見よ)。

- １ビットの深さである。ウィンドウ・マネージャは、デフォルトのデータベースから適切な背景色(０のビットの部分に対して)と前景色(１のビットの部分に対して)を選択することになる。これらのデフォルト値は、もちろん、異なるクライアントのアイコンには異なる色を指定することができる。

icon_mask は、icon_pixmap のどのピクセルをアイコンとして使うべきなのかを指定する。これによって、アイコンが長方形以外の形をとることができるようになる。

icon_window フィールドは、クライアントが自身のアイコンとして使いたいウィンドウの ID である。全てではないがほとんどのウィンドウ・マネージャはアイコン・ウィンドウに対応するであろう。アイコン・ウィンドウに対応していないウィンドウ・マネージャのユーザ・インターフェイスは、アイコンのように振る舞う小さなウィンドウとは合わない可能性が高い。そのため、クライアントはこの機能の缺落を自力で解決しようと試みるべきでない。

単純な２色ビットマップより多くの機能をアイコンに持たせる必要のあるクライアントは、アイコン・ウィンドウを使うべきである。このようなクライアントが守るべき規則は「アイコン」で述べる。

座標 (icon_x, icon_y) は、ウィンドウ・マネージャがどこにアイコンを設置すべきかについての、ウィンドウ・マネージャ宛てのヒントである。 ウィンドウ・マネージャの方針によってアイコンの位置取りが決まるので、クライアントはこのヒントが採用されることを当てにしてはいけない。

window_group フィールドによって、クライアントはこのウィンドウが特定のウィンドウ・グループに所属していることを知らせることができる。例としては、単一のクライアントがルート・ウィンドウの複数の子を操作する場合が考えられる。

> 規約

> - window_group フィールドにはグループ・リーダーの ID を設定するものとする。ウィンドウ・グループ・リーダーは、この目的のためだけに存在するウィンドウであってもよい。この種のプレイスホルダ・グループ・リーダーは、クライアントによってもウィンドウ・マネージャによってもマップされない。

> - ウィンドウ・グループ・リーダーのプロパティは、グループ(の全体)に対するプロパティである(たとえば、グループ全体がアイコン化した時に表示されるアイコン。)。

ウィンドウ・マネージャは、グループ全体をまとめて操作する機能を提供することができる。今のところ、クライアントにはグループ全体をまとめて操作する手段は無い。

flags フィールドの中のメッセージのビット(MessageHint)が設定されている場合、クライアントが WM_PROTOCOLS プロパティで述べる WM_PROTOCOLS 機構ではなく、旧版のウィンドウ・マネージャ通信プロトコル[7]を使用していることがわかる。

flags フィールドの中の `UrgencyHint` フラグが設定されている場合、このフラグは次のことを示している。即ち、クライアントが、ウィンドウの内容が急を要するものだと考えており、利用者の適時の応答を要求しているということを示している。ウィンドウ・マネージャは、このフラグが設定されている間、利用者の注意をこのウィンドウに引きつけるべく何らかの努力をしなければならない。また、ウィンドウ・マネージャは、ウィンドウが Normal 状態もしくは Iconic 状態にある間はずっとこのフラグの状態を監視し続けなければならず、フラグの状態が変わった時は適切に処置しなければならない。このフラグは、上記以外の点ではウィンドウの状態とは無関係である。たとえば、クライアントがアイコン状態のウィンドウに対してこのフラグを設定した場合でも、ウィンドウ・マネージャは同ウィンドウを非アイコン化する必要はない。クライアントは、利用者が `UrgencyHint` フラグを０に設定したりウィンドウを Withdrawn 状態にしたりするための、何らかの手段を用意しなければならない。利用者が採った処置は、ウィンドウが「急を要する」状態になった原因の状況を解決するものかもしれないし、単に警告を止めるだけのものかもしれない。

> 玄論

> この仕組みは、次のような場合に、警告ダイアログ・ボックスや注意喚起ウィンドウ(reminder windows)に使える。ウィンドウをマップしただけでは不十分だが(たとえば、ワークスペースが複数あったり仮想デスクトップのウィンドウ・マネージャが存在したりする場合)、override-redirect のウィンドウを使うと主張が過剰である場合である。たとえばウィンドウ・マネージャは、「急を要する」ウィンドウのタイトル・バーやアイコンに合図の表示を加えることで、同ウィンドウに注意を引きつけることができる。またウィンドウ・マネージャは、新たに「急を要する」状態になったウィンドウに対して、そのアイコンを点滅させたり(同ウィンドウがアイコン状態の場合)、同ウィンドウを最前面に押し上げたりする等、追加の処置をとることもできる。

#### WM_CLASS プロパティ

WM_CLASS プロパティ(STRING 型で制御文字は含まない)には、null 文字終端の文字列が２つ並べて格納されている。この２つの文字列でインスタンス名(Instance name)とクラス名(Class name)を指定する。クライアントとウィンドウ・マネージャの両者はこの２つの名前を、アプリケーションのリソースを捜すために使用したり、識別情報として使用したりする。このプロパティは、ウィンドウが Withdrawn 状態を脱する時に存在しなければならず、ウィンドウが Withdrawn 状態にある間に限って変更することができる。ウィンドウ・マネージャがこのプロパティを調べる可能性があるのは、自身が起動する時とウィンドウが Withdrawn 状態を脱する時だけである。一方、クライアントはこのプロパティの状態を動的に変更する必要は無いはずである。

２つの文字列は、それぞれ、下記の通りである：

- １つ目の文字列は、このウィンドウを所有しているクライアントが属しているアプリケーションの特定のインスタンスを指定するものである。インスタンス名で指定されたリソースは、クラス名で指定されたどのようなリソースにも優先する。インスタンス名は、利用者が OS 固有のやり方で指定できる。POSIX 準拠のシステムでは、以下の規約に従う：

  - コマンド・ラインに「-name NAME」と入力すると、「NAME」がインスタンス名として使用される。

  - そうでない場合、もし環境変数 RESOURCE_NAME が設定してあれば、その値がインスタンス名として使用されることになる。

  - どちらでもない場合、プログラムの起動に使った名称の末尾の部分(argv[0]から全てのディレクトリ名を除いたもの)がインスタンス名として使用される。

- ２つ目の文字列は、このウィンドウを所有しているクライアントが属しているアプリケーションの一般的なクラスを指定するものである。クラスで指定されたリソースは、同じクラス名を持つアプリケーション全てに対して有効になる。クラス名はアプリケーションの作成者が指定する。「Emacs」「XTerm」「XClock」「XLoad」などが一般的なクラス名の例である。

WM_CLASS の文字列はヌル文字で終わるため、「STRING 型のプロパティはヌル文字で区切られる」という一般的な規約に則っていない。この不一致は後方互換性のために必要なものである。

#### WM_TRANSIENT_FOR プロパティ

WM_TRANSIENT_FOR プロパティは WINDOW 型であり、自分とは別の最上位ウィンドウの ID を格納している。これによって次のことがわかる。即ち、このウィンドウが同 ID で指定されたウィンドウのためのポップアップであること、及びウィンドウ・マネージャがこの一時的な(transient)ウィンドウを装飾しないことにしたり他のウィンドウとは別のやり方で取り扱ったりすることが可能であることがわかる。最上位ウィンドウをマップするには普通は利用者とのやり取りが必要であるけれども、WM_TRANSIENT_FOR ウィンドウの場合、ウィンドウ・マネージャは新たにマップされたウィンドウを利用者と何らやり取りすることなく表示すべきであることに注意。WM_TRANSIENT_FOR を設定すべきウィンドウの例としては、ダイアログ・ボックスがある。

WM_TRANSIENT_FOR と override-redirect を混同しないようにすることが重要である。WM_TRANSIENT_FOR は、ウィンドウがマップされている間にポインタを占有しない場合(言い換えると、一時的なウィンドウが上がっている間に他のウィンドウがアクティブであってもよい場合)に使用するものである。他のウィンドウが入力を処理してはならない場合(たとえば、ポップアップ・メニューを実装する場合)、override-redirect を用いてウィンドウがマップされている間はポインタを占有する。

#### WM_PROTOCOLS プロパティ

WM_PROTOCOLS プロパティは ATOM 型であり、アトムのリストである。各アトムは、クライアントが参加しようとする、クライアントとウィンドウ・マネージャとの間の通信プロトコル１つを表す。このアトムは、標準のプロトコルだけでなく、各ウィンドウ・マネージャ固有の私的なプロトコルも表すことができる。

クライアントが参加を申し出ることができるプロトコルでは、クライアントに `ClientMessage` イベントを送信するウィンドウ・マネージャと、それに対して適切な動作をとるクライアントとが必要である。このイベントの中身について詳しく知りたければ、ClientMessage イベントを見よ。いづれの場合でも、プロトコルの一連のやり取り(transactions)を開始するのはウィンドウ・マネージャである。

WM_PROTOCOLS プロパティは必須ではない。これが存在しない場合、クライアントが如何なるウィンドウ・マネージャ・プロトコルにも参加したいと考えていないことを意味する。

X 協会は、名前空間における衝突を避けるため、プロトコルのレジストリ(登記簿)を備えて管理する予定である。次の表には、これまでに定義されたプロトコルが載っている。

プロトコル | 説明のある節 | 目的
--- | --- | ---
WM_TAKE_FOCUS | 入力フォーカス | 入力フォーカスの割り当て
WM_SAVE_YOURSELF | 附録 C | クライアントの状態保存の要求(非推奨)
WM_DELETE_WINDOW | ウィンドウの削除 | 最上位ウィンドウの削除の要求

この表の内容は、時が経つと増えると思われる。

#### WM_COLORMAP_WINDOWS プロパティ

WM_COLORMAP_WINDOWS プロパティは WINDOW 型であり、最上位ウィンドウに設置される。このプロパティは、最上位ウィンドウのカラーマップとは異なるカラーマップを組み込む必要があるウィンドウの ID のリストである。ウィンドウ・マネージャはこのリストを看視し、同リスト中のウィンドウのカラーマップ属性の変化を待ち受ける。最上位ウィンドウは常に(暗黙にあるいは明示的に)この看視リストに含まれる。この仕組みの詳細は「カラーマップ」を参照。

#### WM_CLIENT_MACHINE プロパティ

クライアントは、同クライアントを実行しているマシン(X サーバを実行しているマシンの視点からそのように見えるもの)の名前を表す文字列を WM_CLIENT_MACHINE プロパティに設定する。WM_CLIENT_MACHINE プロパティの型は、TEXT 型の中のいづれかの型である。

### ウィンドウ・マネージャ・プロパティ

前の節で述べたプロパティは、クライアントが自身の最上位ウィンドウに保持しなければならないものである。この節では、ウィンドウ・マネージャがクライアントの最上位ウィンドウとルートとに設置するプロパティについて述べる。

#### WM_STATE プロパティ

ウィンドウ・マネージャは、WM_STATE プロパティ(型は WM_STATE)を Withdrawn 状態でない最上位クライアント・ウィンドウのそれぞれに設置する。Withdrawn 状態の最上位ウィンドウは、WM_STATE プロパティを持っていても持っていなくてもよい。最上位ウィンドウが Withdrawn 状態になったら、クライアントは同プロパティ(訳注：同プロパティの中身？)を別の目的のために再利用することができる。その場合、WM_STATE プロパティがまだ存在するのであれば、クライアントは同プロパティを削除するものとする。

クライアントの中には、プログラムの処理の対象となるウィンドウをクリックするよう利用者に求めるものがある(たとえば `xprop`)。基本的には、ここで求められているのは最上位ウィンドウである。最上位ウィンドウを見つけるために、クライアントはクリックで選択された位置のウィンドウ階層構造を調べ、WM_STATE プロパティを持っているウィンドウを探す。この探索は、ウィンドウ・マネージャによる親の変更の組み合わせ(考えられるもの)を網羅するために、再帰的に行わなければならない。WM_STATE プロパティを持つウィンドウが見つからなかった場合、ルートの子ウィンドウの中、マップされていて且つクリックで選択された位置に存在するものを使用するべきである。

WM_STATE プロパティの中身は次のように定義されている。

フィールド | 型 | 註釈
--- | --- | ---
state | CARD32 | (下の表を見よ)
icon | WINDOW | アイコン・ウィンドウの ID

次の表に挙げるのは WM_STATE.state の値である。

State | 値
--- | ---
WithdrawnState | 0
NormalState | 1
IconicState | 3

このプロパティに上記のもの以外のフィールドを加える権利は X 協会が持つ。state フィールドの値について、上の表で定義されたもの以外の値は X 協会による将来の使用のためにとっておく。

state フィールドは、ウィンドウ・マネージャの側から見たウィンドウの状態を表すものであり、クライアント側の認識(WM_HINTS プロパティの initial_state フィールドで表す)とは一致しないこともある(たとえば、利用者がウィンドウ・マネージャに同ウィンドウをアイコン化するよう依頼していた場合)。state フィールドの値が `NormalState` の場合、ウィンドウ・マネージャは、クライアントが自身のウィンドウを活動させているはずだと考えている。state フィールドの値が `IconicState` の場合、クライアントは自身のアイコン・ウィンドウを活動させているはずである。どちらの状態でも、クライアントは両ウィンドウからの Expose イベント(exposure events：訳注：可視状態になった時に発生)を処理できるよう備えておくべきである。

ウィンドウが Withdrawn 状態になった場合、ウィンドウ・マネージャは state フィールドの値を `WithdrawnState` に変更するか、さもなくば WM_STATE プロパティをまるごと削除する。

icon フィールドには、このプロパティが設定されているウィンドウのアイコンとして(ウィンドウ・マネージャが)使用するアイコン・ウィンドウのウィンドウ ID が入る。そのようなウィンドウが存在しない場合、icon フィールドには `None` を設定するべきである。このウィンドウは、クライアントが自身の WM_HINTS プロパティで指定したアイコン・ウィンドウと同じであっても良いし、違っても良い。WM_STATE の icon のアイコンは、ウィンドウ・マネージャが提供したウィンドウであってクライアントのアイコン・ピクスマップを保持するものであるか、もしくはクライアントのアイコン・ウィンドウの先祖である。

#### WM_ICON_SIZE プロパティ

アイコン・ピクスマップとアイコン・ウィンドウ(の両方もしくは一方)の大きさに制約を与えたいウィンドウ・マネージャは、WM_ICON_SIZE という名のプロパティをルートに設置するものとする。このプロパティの中身を次の表に挙げる。

フィールド | 型 | 註釈
--- | --- | ---
min_width | CARD32 | アイコン・サイズ関連のデータ
min_height | CARD32 |
max_width | CARD32 |
max_height | CARD32 |
width_inc | CARD32 |
height_inc | CARD32 |

詳細については「Xlib - C Language X Interface」の 14.1.12 の節を見よ。

### ウィンドウの状態の変更

クライアントの視点からは、ウィンドウ・マネージャはクライアントの最上位ウィンドウ(の１つ１つ)が下記の３つの状態のいづれかであると見做しているように見える。３つの状態の意味は次の通り。

- `NormalState` - クライアントの最上位ウィンドウは可視状態である。

- `IconicState` - クライアントの最上位ウィンドウはアイコン状態である(ウィンドウ・マネージャにとって何を意味するかはさておき)。クライアントは、自身の最上位ウィンドウが可視状態でなく且つ自身のアイコン・ウィンドウ(存在すれば)が可視状態になるものと仮定することができ、また、そのように仮定できない時は、自身のアイコン・ピクスマップ(存在すれば)もしくは WM_ICON_NAME が表示されるものと仮定することができる。

- `WithdrawnState` - クライアントの最上位ウィンドウもアイコンも不可視も状態である。

実際には、ウィンドウ・マネージャは上記以外の意味を持つ状態を実装することができる。たとえば、ウィンドウ・マネージャは「inactive(不活発)」状態という概念を実装して、ほとんど使われないクライアントのウィンドウをメニュー内の文字列として表示することができる。しかし、この状態はクライアントには認識できず、クライアントは自身がアイコン状態にあるものと考える。

新たに作成された最上位ウィンドウは Withdrawn 状態にある。ウィンドウに適切なプロパティが与えられた後は、クライアントは下記のように自由にその状態を変更することができる。

- Withdrawn -> Normal - クライアントは WM_HINTS.initial_state を `NormalState` にしてウィンドウをマップする。

- Withdrawn -> Iconic - クライアントは WM_HINTS.initial_state を `IconicState` にしてウィンドウをマップする。

- Normal -> Iconic - クライアントは、この節で後に述べる `ClientMessage` イベントを送信する。

- Normal -> Withdrawn - クライアントはウィンドウをアンマップした後、この節で後に述べる代用(synthetic、作り物の、本物でない) `UnmapNotify` イベントを送信する。

- Iconic -> Normal - クライアントはウィンドウをマップする。この場合、WM_HINTS.initial_state の内容は関係無い。

- Iconic -> Withdrawn - クライアントはウィンドウをアンマップした後、この節で後に述べる代用(synthetic、作り物の、本物でない) `UnmapNotify` イベントを送信する。

Withdrawn 状態への遷移及び Withdrawn 状態からの遷移を引き起こすことができるのは、クライアントだけである。クライアントのウィンドウが Withdrawn 状態を脱した場合、同ウィンドウが Normal 状態であれば同ウィンドウはマップされ、Iconic 状態であればアンマップされる。親の変更を行うウィンドウ・マネージャは、クライアントのウィンドウが Iconic 状態にある時は同ウィンドウをアンマップしなればならない。たとえ、同クライアント・ウィンドウが、アンマップされている先祖のウィンドウによって不可視にされているとしても。反対に、親変更を行うウィンドウ・マネージャがクライアントのウィンドウを、その先祖をアンマップすることによって不可視の状態にする場合、同クライアント・ウィンドウは定義上当然に Iconic 状態となり、アンマップされなければならない。

> 実装者のために

> クライアントは自身の最上位ウィンドウの `StructureNotify` マスクを選択して、Normal 状態と Iconic 状態の間の遷移を追跡することができる。`MapNotify` イベントの受領は Normal 状態への遷移を表し、`UnmapNotify` イベントの受領は Iconic 状態への遷移を表す。

ウィンドウの状態を Withdrawn へ変更する場合、クライアントは(同ウィンドウをアンマップするのに加えて)、下記の引数を与えた `SendEvent` リクエストを使って、代用の `UnmapNotify` イベントを送信しなければならない。

引数名 | 値
--- | ---
destination | ルート
propogate | False
event-mask | (SubstructureRedirect|SubstructureNotify)
event:以下の値を持つ `UnmapNotify`： |
event: | ルート
window: | そのウィンドウ自身
from-configure: | False

> 玄論

> クライアントに代用の `UnmapNotify` イベントを送信するよう要求しているのは、クライアントが状態の変更を望んでいることをについて、ウィンドウ・マネージャが通知を受けられるようにするためである。状態変更の要望が表明された時にはすでに当該ウィンドウはアンマップされている可能性があるとしてもである。

> 実装者のために

> 古いクライアントとの互換性のために、ウィンドウ・マネージャは本物の `UnmapNotify` を受け取った場合、代用の `UnmapNotify` を待つことなく、 Withdrawn 状態への遷移を開始させるべきである。ウィンドウ・マネージャは、未だ本物の `UnmapNotify` を受け取っていないウィンドウに関して、代用の `UnmapNotify` を受け取った場合にも、Withdrawn 状態への遷移を開始させるべきである。

クライアントがウィンドウを引っ込める(Withdrawn状態にする)場合には、ウィンドウ・マネージャは「WM_STATE プロパティ」で述べたように WM_STATE プロパティを更新するか削除する。クライアント・ウィンドウを引っ込めた後にそのまま同ウィンドウを再利用したい(再度マップしたり、別の場所に親を変更したり、等)と考えるクライアントは、退出(Withdrawn状態への変更)が完了するのを待ってから同処理を進めなければならない。この場合の望ましい方法は、ウィンドウ・マネージャによる WM_STATE プロパティの更新または削除をクライアントが待つことである。[8]

Normal 状態から Iconic 状態へ遷移する場合、クライアントは下記の値を設定した `ClientMessage` イベントをルートに送信するものとする。

- Window == アイコン化するウィンドウ

- Type[9] == WM_CHANGE_STATE アトム

- Format == 32

- Data[0] == IconicState

> 玄論

> 上で述べた `ClientMessage` の形式は「ClientMessage イベント」で説明する `ClientMessage` の形式とは一致しない。これは、後者がウィンドウ・マネージャからクライアントに送られるものであるのに対して、前者はクライアントからウィンドウ・マネージャに送られるものだからである。

data[0] の他の値は、この規約の将来の拡張のために予約されている。`SendEvent` リクエストの引数は、代用の `UnmapNotify` イベントのところで述べたものと同じである。

> 実装者のために

> クライアントは、自身の最上位ウィンドウまたはアイコン・ウィンドウに対して `VisibilityChange` イベント(訳注：マスク)を選択することもできる。その場合、クライアントは、そのウィンドウが完全に覆い隠されたときには、たとえマップされていても、`VisibilityNotify` (state==FullyObscured) イベントを受け取ることになり(結果として、おそらく更新が時間の無駄に終わる)、また、同ウィンドウが一部でも可視状態になったときは、`VisibilityNotify` (state!=FullyObscured) イベントを受け取ることになる。

> 実装者のために

> ウィンドウが Normal 状態から Iconic 状態へ、または Normal 状態から Withdrawn 状態へ遷移する場合について、クライアントは次のことを知っておくべきである。即ち、ウィンドウ・マネージャは、状態遷移を行うウィンドウのために存在する一時的なウィンドウを利用不能状態にすることができるということである。クライアントは、一時的なウィンドウを所有するウィンドウが Normal 状態でない場合、その一時ウィンドウを利用者が利用可能であることを当てにしてはいけない。ウィンドウを引っ込める(Withdrawn状態にする)時、クライアントは同ウィンドウのために存在する一時的なウィンドウをも引っ込めるべきである。

### ウィンドウの構成

クライアントは、`ConfigureWindow` リクエストを用いて自身の最上位ウィンドウの大きさを変更したり、同ウィンドウの再配置をしたりすることができる。このリクエストで変更できるウィンドウの属性は以下のものである。

- ウィンドウ外側左上隅の座標[x, y]。

- ウィンドウの内部領域(ボーダを除く)の幅と高さ[width, height]。

- ウィンドウのボーダ(縁)の幅。

- ウィンドウの積み重ねの中での前後の順序。

位置を表す座標系は、いかなる親変更が起きたとしても関係なく、ルートの座標系である。ボーダ幅と win_gravity の位置のヒントとは、時間的に最も近くにクライアントが要求したものを使用する。クライアントの構成リクエスト(configure requests)をウィンドウ・マネージャが解釈する方法は、ウィンドウが Withdrawn 状態から脱した時、初めてウィンドウ・ジオメトリをマップする方法と同じである。この方法については「WM_NORMAL_HINTS プロパティ」で述べた。クライアントは、要求したサイズや位置をウィンドウ・マネージャが必ず割り付けてくれるとは限らないことを承知していなければならず、どのようなサイズや位置にも対処できるよう備えていなければならない。ウィンドウ・マネージャは `ConfigureRequest` に対して次のように応答する。

- ウィンドウのサイズ、位置、ボーダ幅、前後の順序を一切変更しない場合。

  クライアントは代用の(作り物の) `ConfigureNotify` イベントを受け取る。このイベントにはウィンドウの(無変更の)ジオメトリが書いてある。(x, y)座標は、親変更の有無に関わらず、ルートの座標系のものであり、クライアントが要求したボーダ幅を受けて調整されたものである。border_width はクライアントが要求したボーダ幅となる。実際には何の変更も行われていないため、クライアントは本物の `ConfigureNotify` イベントは受け取らない。

- ウィンドウのサイズやボーダ幅を変更せず、位置や前後の順序を変更した場合。

  クライアントは代用の `ConfigureNotify` イベントを受け取る。このイベントには変更の情報が載っており、ウィンドウの新しいジオメトリが書いてある。同イベントの(x, y)座標は、ルートの座標系のものであり、クライアントが要求したボーダ幅を受けて調整されたものである。border_width はクライアントが要求したボーダ幅となる。クライアントは、この変更の情報を記載した本物の `ConfigureNotify` イベントを受け取らない可能性がある。なぜかというと、ウィンドウ・マネージャが最上位ウィンドウの親を変更してしまっていることがあるからである。クライアントが本物のイベントを受け取る場合、その後に代用のイベントが続く。

- ウィンドウのサイズもしくはボーダ幅を変更した場合(位置や前後の順序の変更の有無は問わない)。

  `StructureNotify` イベント(訳注：マスク)を選択しているクライアントは、本物の `ConfigureNotify` イベントを受け取る。このイベントに入っている座標は親を基準とした相対座標であり、ウィンドウの親が変更されている場合、「親」はルートでないことがある。同座標は、ウィンドウの実際のボーダ幅(これをウィンドウ・マネージャが変更した可能性がある)を反映したものとなる。必要に応じ、`TranslateCoordinates` リクエストを用いて座標を変換することができる。

原則として、本物の `ConfigureNotify` イベントに入っている座標は親を基準としたものであり、代用のイベントに入っている座標はルートを基準としたものである。

> 実装者のために

> クライアントは次の２つの場合を区別できない。即ち、最上位ウィンドウのサイズと位置の両方が変更された場合と、最上位ウィンドウのサイズは変更されたが位置は移動しなかった場合とを区別できない。なぜかというと、どちらの場合も本物の `ConfigureNotify` イベントが届くからである。最上位ウィンドウの絶対座標を追跡し続けたいクライアントは、自分が同座標を知っているのか否かを表す状態情報を１つ保持する。最上位ウィンドウに関して本物の `ConfigureNotify` イベントを受け取った場合、クライアントは絶対座標が「不明」である旨を書き留める。代用の`ConfigureNotify` イベントを受け取った場合、クライアントは同イベントの中の座標を使用し、絶対座標が「既知」である旨を書き留める。クライアントは、最上位ウィンドウ(もしくはその子孫)に関して `KeyPress`、`KeyRelease`、`ButtonPress`、`ButtonRelease`、`MotionNotify`、`EnterNotify` もしくは `LeaveNotify` イベントを受け取った場合、イベントの中の２つの座標(event-x, event-y)と(root-x, root-y)の差を取ることで最上位ウィンドウの絶対座標を導き出すことができる。最上位ウィンドウの絶対座標を知るのに `TranslateCoordinates` リクエストを使う必要があるのは、同座標が「不明」の時だけである。

クライアントは、自身のボーダが表示されない可能性があることを承知しておくべきである。ウィンドウ・マネージャは、親変更の手法を用いてタイトルと操縦部品(controls)とその他の装飾(details)とを含む「ボーダ」でクライアントの最上位ウィンドウを自由に修飾し、一貫した look-and-feel を維持することができる。その場合、ウィンドウ・マネージャは、ボーダ幅を設定しようとするクライアントの試みを無視して、ボーダ幅を 0 にしてしまうことがある。したがって、クライアントは、最上位ウィンドウのボーダが表示されることを当てにしたり、最上位ウィンドウのボーダを用いて重要な情報を表示しようとしたりしないものとする。このような手法を用いないウィンドウ・マネージャは、最上位ウィンドウのボーダの表示を妨げない。

> 規約

> クライアントは、競合状態(race condition)の発生を避けるために、希望するボーダ幅の値をすべての `ConfigureWindow` リクエストに設定するものとする。

ウィンドウの前後の順序を変更するクライアントは、自身の親が変更されている可能性を考慮しなければならない。これは、かつて兄弟だったウィンドウが今では兄弟でない可能性を考慮しなければならないということである。`ConfigureWindow` リクエストの引数 sibling に兄弟でないウィンドウを渡すとエラーが起きる。

> 規約

> `ConfigureWindow` リクエストを使ってウィンドウの前後の順序の変更を要求するクライアントは、引数 sibling に `None` を指定するものとする。

かつて兄弟だったウィンドウを基準として自身の前後の順序を変えなければならないクライアントは、次のことを行わなければならない。即ち、`ConfigureWindow` リクエストを使用し(親変更を行わないウィンドウ・マネージャの下でクライアントが動作している場合)、その結果として生じるエラーに備え、次いで下記の値を設定した `SendEvent` リクエストを実行して代用の `ConfigureRequest` イベントを送信しなければならない。

Argument | 値
--- | ---
destination | ルート
propogate | False
event-mask | (SubstructureRedirect|SubstructureNotify)
event: 以下の値を設定した `ConfigureRequest`： |
event: | ルート
window: | ウィンドウ自身
... | ConfigureWindow リクエストから取り出した他の引数

いづれにしても、ウィンドウ・マネージャは自分が合うと思うようにウィンドウ群の前後の順序を変更することができる。そのため、クライアントは、自身が要求したとおりの積み重ね順序を与えられることを当てにするべきでない。クライアントは、自身の最上位ウィンドウに関して受信した `ConfigureNotify` イベント(本物・代用の両方)の above-sibling フィールドを無視するべきである。このフィールドの情報が有用でない可能性があるからである。

### ウィンドウの属性の変更

ウィンドウ作成時に与えられる属性(attributes)は、`ChangeWindowAttributes` リクエストを使って変更することができる。ウィンドウの属性を下表に挙げる。

Attribute | クライアント専用か否か
--- | ---
Background pixmap | Yes
Background pixel | Yes
Border pixmap | Yes
Border pixel | Yes
Bit gravity | Yes
Window gravity | No
Backing-store hint | Yes
Save-under hint | No
Event Mask | No
Do-not-propagate mask | Yes
Override-redirect flag | No
Colormap | Yes
Cursor | Yes

大半の属性はクライアント専用であり、ウィンドウ・マネージャに干渉されることはない。クライアント専用でない属性については以下の通り。

- ウィンドウ・マネージャはウィンドウ・グラヴィティ(win-gravity)を自由に置き換えることができる。親変更を行うウィンドウ・マネージャは、自分自身の目的のために最上位ウィンドウのウィンドウ・グラヴィティを設定することとができる。

- クライアントは、自身の最上位ウィンドウに対して自由に save-under ヒントを設定することができる。けれども、クライアントは、このヒントがウィンドウ・マネージャによって置き換えられる可能性があることを承知していなければならない。

- ウィンドウのイベント・マスクはクライアントごとに設定される。そのため、クライアントは、ウィンドウ・マネージャが選択しているイベントとは無関係に、自分にとって使いやすいイベントを何でも選択することができる。１度に１つのクライアントしか選択できないイベントも存在するが、ウィンドウ・マネージャは、そのようなイベントをいかなるクライアント・ウィンドウに関しても選択してはいけない。

- クライアントは最上位ウィンドウに override-redirect を設定する(override-redirect 属性をTrueに設定する)ことができるが、「ポップアップ・ウィンドウ」及び「リクエストをリダイレクトする」で述べる場合を除いては、設定しないのが望ましい。

### 入力フォーカス

入力処理には４つの型式がある。

- No Input - クライアントはキーボード入力を待ち受ける。例としては、`xload` その他の出力専用のクライアントがある。

- Passive Input - クライアントはキーボード入力を待ち受けるが、入力フォーカスを明示的に設定することは無い。下位ウィンドウ(subwindows)を持たない単純なクライアントが一例である。こうしたクライアントが入力を受け付けるのは、`PointerRoot` モードにある場合か、あるいはウィンドウ・マネージャが同クライアントの最上位ウィンドウに(click-to-type モードで)入力フォーカスを設定した場合である。

- Locally Active Input - クライアントは、キーボード入力を待ち受け、明示的に入力フォーカスを設定するけれども、そうするのは同クライアントのウィンドウのいづれかに既にフォーカスがある場合に限られる。データ入力フィールドたる下位ウィンドウを複数持つクライアントであって、Next キーと Prev キーを使って、あるフィールドから別のフィールドへ入力フォーカスの移動を行う者が一例である。こうしたクライアントがそのような動作を行うのは、`PointerRoot` モードでフォーカスを獲得した場合か、あるいはウィンドウ・マネージャが同クライアントの最上位ウィンドウに(click-to-type モードで)入力フォーカスを設定した場合である。

- Globally Active Input - クライアントは、入力フォーカスが自分の所有していないウィンドウにある場合でも、キーボード入力を待ち受け、明示的に入力フォーカスを設定する。たとえば、スクロール・バーを持つクライアントであって、入力フォーカスを移すことなく利用者がウィンドウのスクロールを行えるようにしたい者がその例である。この時、入力フォーカスが別のウィンドウにあってもかまわない。このクライアントは、利用者がスクロールによって動く領域をクリックした時には入力フォーカスを獲得したいけれども、利用者がスクロール・バー自体をクリックした時には入力フォーカスを獲得したくないのである。したがって、このクライアントは、自身のウィンドウのいづれにもウィンドウ・マネージャが入力フォーカスを設定するのを禁止する。

以上の４つの入力モデルと、それに対応する input フィールド(訳注：WM_HINTSの input フィールド)の値と WM_PROTOCOLS プロパティにおける WM_TAKE_FOCUS アトムの有無とを次の表にまとめる。

入力型式 | input フィールド | WM_TAKE_FOCUS
--- | --- | ---
No Input | False | 無し
Passive | True | 無し
Locally Active | True | 有り
Globally Active | False | 有り

Passive 型式と Locally Active 型式のクライアントは、WM_HINTS の input フィールドに `True` を設定して、入力フォーカスの取得にウィンドウ・マネージャの助力が必要であることを表す。No Input 型式と Globally Active 型式のクライアントは、input フィールドに `False` を設定することによって、ウィンドウ・マネージャが自身の最上位ウィンドウに入力フォーカスを設定しないよう要求する。

`SetInputFocus` リクエストを使用するクライアントは、その切っ掛けとなったイベントのタイムスタンプを引数 time に設定しなければならない。`FocusIn` イベントは、タイムタンプを持たないので、切っ掛けのイベントにはなり得ない。クライアントは、対応する `EnterNotify` 無しにフォーカスを取得することがある。クライアントは、引数 time に `CurrentTime` を渡してはならない。

Globally Active 型式を使うクライアントは、下記のイベントのいづれかを受け取った時に未だ入力フォーカスを持っていない場合に限って、入力フォーカスを取得する `SetInputFocus` リクエストを使用することができる。

- `ButtonPress`

- `ButtonRelease`

- 受動的に占有した(Passive-grabbed) `KeyPress`

- 受動的に占有した(Passive-grabbed) `KeyRelease`

原則として、クライアントは、受動的に占有したキー・イベントをこの目的に使用するのを避けるべきである。但し、これが避けられない場合(たとえば、カット、コピー、ペーストを行うキーに対して受動的な占有を確立するセレクション・ツールなど)は例外である。

あるウィンドウにフォーカスを設定するよう利用者がウィンドウ・マネージャへ命令する方法は、ウィンドウ・マネージャが決定する。たとえば、クライアントは、フォーカスを移すためのクリックをウィンドウ・マネージャが評価するか否かを決めることはできない。

WM_PROTOCOLS プロパティに WM_TAKE_FOCUS アトムがあるウィンドウは、ウィンドウ・マネージャから次のような `ClientMessage` イベントを受け取ることがある(ClientMessage イベントで述べるように)。即ち、data[0] フィールドにはアトム WM_TAKE_FOCUS が入っており、data[1] フィールドには有効なタイムスタンプ(すなわち `CurrentTime` でないタイムスタンプ)が入っている `ClientMessage` イベントを受け取ることがある。(クライアントは、)そのようなウィンドウへフォーカスを与えたい場合、次のように引数を指定した `SetInputFocus` リクエストで答える。即ち、引数 window には、クライアントのウィンドウの中で最後に入力フォーカスを持っていたもの、あるいはデフォルトの入力ウィンドウを指定し、引数 time には上記 `ClientMessage` に入っているタイムスタンプを指定した `SetInputFocus` リクエストで答える。「入力フォーカス」も参照。

アイコンから元に戻った場合(ウィンドウを開いた場合)、あるいは利用者が最上位ウィンドウの外側の領域の中、ウィンドウ・マネージャにフォーカスを割り当てるよう指示する領域をクリックした場合(たとえば、ヘッドライン・バーのクリックを以ってフォーカスを割り当てる合図と為すことができる)、クライアントは WM_TAKE_FOCUS を受け取ることがある。

こうした規則の目的は、ウィンドウ・マネージャが最上位ウィンドウへ入力フォーカスを割り当てるにあたって、最上位ウィンドウ(を持つクライアント)が入力フォーカスを自身の下位ウィンドウへ割り当てられるようにすること、及び同ウィンドウ(を持つクライアント)が入力フォーカスの提供を拒否できるようにすることである。たとえば、ウィンドウ・マネージャが通常「クライアントがアイコン状態を脱した時やそのウィンドウが前面に出た時には入力フォーカスを取得するべきだ」と考えているとしても、現在フレームが開いていない時計やテキスト・エディタは入力フォーカスの取得を望まない可能性がある。

入力フォーカスを設定するクライアントは、`SetInputFocus` リクエストの引数 revert-to の値を決める必要がある。これによって、フォーカスを設定したウィンドウが可視状態でなくなった時の入力フォーカスの動きが決まる。引数 revert-to が取り得る値は次のいづれかである。

- `Parent` - 通常、クライアントは、自身の下位ウィンドウのいづれかにフォーカスを割り当てる場合、この値を用いるべきである。下位ウィンドウをアンマップするとフォーカスは親に戻ることになる。大抵、これが望む動作であろう。

- `PointerRoot` - この値と「click-to-type」のフォーカス管理方針とを併用すると競合状態(race condition)が発生する。なぜかというと、ウィンドウが不可視になるのと、ウィンドウ・マネージャがフォーカスを他所へ移すよう決意するのとが同時になる可能性があるからである。

- `None` - ウィンドウ・マネージャが親を変更し(大抵のウィンドウ・マネージャはこれを行う)且つクラッシュした場合(故障で停止した場合)、この値を使用していると問題が発生する。入力フォーカスは `None` となり、おそらくこれを変更することはできなくなる。

`PointerRoot` も `None` も、使用するのは安全でない。

> 規約

> `SetInputFocus` リクエストを実行するクライアントは、引数 revert-to に `Parent` を指定するものとする。

入力フォーカスを抛棄したいクライアントのための規約も必要である。そのようなクライアントにとっては、入力フォーカスの設定先として安全な値が存在しない。したがって、そうしたクライアントは入力データを無視するものとする。

> 規約

> クライアントは、自分自身の判断で入力フォーカスを抛棄しないものとする。代わりに、受け取った入力を無視するべきである。

### カラーマップ

ウィンドウ・マネージャに管理される最上位ウィンドウを持つクライアントのためにカラーマップの組み込み(installing)と解放(uninstalling)を行うのは、ウィンドウ・マネージャの仕事である。

クライアントは、どのカラーマップを組み込んだり解放したりするのかについて、ヒントをウィンドウ・マネージャに提供する。クライアントはカラーマップを自分で組み込んだり解放したりしてはいけない(後ほど述べるような状況にある場合は除く)。クライアントの最上位ウィンドウがカラーマップ・フォーカスを得た場合(ウィンドウ・マネージャがどのようなカラーマップ・フォーカス指針を実装した結果なのかは問わない)、ウィンドウ・マネージャはクライアントのカラーマップの中の１個以上を必ず組み込む。

クライアントの最上位ウィンドウと下位ウィンドウが全て同じカラーマップを使う場合、同クライアントは最上位ウィンドウのウィンドウ属性の colormap フィールドにそのカラーマップの ID を設定するものとする。(訳註：この場合には、)クライアントは最上位ウィンドウに WM_COLORMAP_WINDOWS プロパティを設定してはいけない。クライアントは、カラーマップを変更したい場合、最上位ウィンドウのウィンドウ属性の colormap を変更する。ウィンドウ・マネージャはこの colormap 属性の変更を察知して適当なカラーマップを組み込む。

ウィンドウを作成するクライアントは、`CopyFromParent` という値を使って、親のカラーマップを引き継ぐことができる。ウィンドウ・マネージャは、ルート・ウィンドウの colormap フィールドにクライアントが継承するのに適したカラーマップが入っているよう取り計らう。特に、同カラーマップが `BlackPixel` と `WhitePixel` に区別可能な色を備えているようにする。

最上位ウィンドウとはカラーマップ要件を異にする下位ウィンドウと override-redirect・ポップアップ・ウィンドウとを持つ最上位ウィンドウには、WM_COLORMAP_WINDOWS プロパティを持たせるものとする。このプロパティには、次のようなカラーマップを持つウィンドウの ID のリストが入る。即ち、ウィンドウ・マネージャが自身のカラーマップ・フォーカス方針に則りカラーマップ・フォーカスを最上位ウィンドウに割り当てる時に組み込むべきとされるカラーマップである(WM_COLORMAP_WINDOWS プロパティ を見よ。)。このリストの中身は、クライアントから見てカラーマップを組み込む重要性が高いと思われる順に並んでいる。ウィンドウ・マネージャは、このプロパティの変更を監視し、同プロパティ中のウィンドウのカラーマップ属性の変更をも監視する。

クライアントは、カラーマップの重要性の順序に変更があった場合、新たな順序を反映するように WM_COLORMAP_WINDOWS プロパティを更新するものとする。最上位ウィンドウが同プロパティ中のリストに含まれていない場合、ウィンドウ・マネージャは、同ウィンドウの重要度がリスト中のどのウィンドウのものよりも高いと考える。

WM_TRANSIENT_FOR プロパティを持つウィンドウは、自分自身で WM_COLORMAP_WINDOWS プロパティを保持しても良いし、自分を一時的に活用しているウィンドウのプロパティ(WM_COLORMAP_WINDOWS)の中に(IDとして)納まるだけでも良い。

> 玄論

> クライアントが自身のカラーマップの要件をウィンドウ・マネージャに伝える方法について、別の設計も考えられていた。そちらの設計案では、ウィンドウのリストの代わりにカラーマップのリストを使用するよう定めていた。ウィンドウのリストを使用する現在の設計が採用されたのは、次の２つの理由からである。１つ目は、これによってウィンドウ・マネージャがカラーマップのヴィジュアル(visual)を見つけられるようになることであり、結果としてヴィジュアルに基づくカラーマップ組込み方針(policies)が実現可能になることである。２つ目の理由は、この設計によってウィンドウ・マネージャがリストにあるウィンドウに関して `VisibilityChange` イベントを選択できるようになることであり、結果としてウィンドウ・マネージャが、カラーマップを必要とするウィンドウが可視状態である場合に限ってカラーマップが組み込まれることを保証できるようになることである。採用されなかった別案の設計では、どちらの方針も実現できなかった。

> 実装者のために

> クライアントは、次の２つのものを知っておくべきである。１つは、X サーバへの接続設定時に通知された(スクリーンの) min-installed-maps フィールドと max-installed-maps フィールド(訳註：Xlib の Screen 構造体ではint max_maps, min_maps)の値。もう１つは、X Window System Protocol の「`InstallColormap` リクエスト」のところで定義した「必要リスト」("required list")に対してこの最小値(min-installed-maps)が与える影響である。要するに、最も近くに組み込まれた min-installed-maps 個のカラーマップは、組み込まれていることが保証される。この値は 1 であることが多く、複数のカラーマップを必要とするクライアントは注意すべきである。

> (訳註：「必要リスト」：常に「必要リスト」(required list)と呼ばれるものが存在する。これは、組み込まれた(インストールされた)カラーマップ群の部分集合であって、順序を持つリストである。必要リストの長さは、X サーバへの接続設定の際に通知されたスクリーンの min-installed-maps の値を M とすると、長くても M である。必要リストは次のように維持される。あるカラーマップが明示的な引数として `InstallColormap` に渡された場合、同カラーマップは必要リストの先頭に追加される。必要であれば、必要リストの長さが M を超えないように末尾部分が切り捨てられる。あるカラーマップが明示的な引数として `UninstallColormap` に渡され、しかもそのカラーマップが必要リストに入っていた場合、同カラーマップはリストから取り除かれる。X サーバが暗黙のうちにカラーマップを組み込む場合、同カラーマップは必要リストには加えられない。X サーバは、必要リストに含まれているカラーマップを暗黙のうちに取り外す(uninstall)ことができない。：初期状態では、スクリーンのデフォルトのカラーマップが組み込まれている(けれども、必要リストには含まれていない)。：必要リストにあるカラーマップはアンインストールされていない。：`ListInstalledColormaps`で手に入るリストは必要リストではない。)

クライアントは、可能な時はいつでも、上述の仕組みを利用するものとし、ウィンドウ・マネージャが自由にカラーマップを組み込めるようにするものとする。けれどもクライアントは、ポインタの占有を保持している間は、自力でカラーマップの組み込みを行うことが許されている。カラーマップの組み込みを行うクライアントは、最初の組み込みに先立ってウィンドウ・マネージャに下記の通知を行わなければならない。クライアントは、カラーマップ組み込みを終えた時にもウィンドウ・マネージャへの通知を行わなければならない。クライアントは、以下の引数を与えて `SendEvent` リクエストを発行することによって、ウィンドウ・マネージャへの通知を行う。

引数 | 値
--- | ---
destination | カラーマップを組み込もうとするスクリーンのルート・ウィンドウ
propogate | False
event-mask | ColormapChange
event: an `ClientMessage` with: |
window: | ルート・ウィンドウ(上と同じ)。
type: | WM_COLORMAP_NOTIFY
format | 32
data[0] | クライアントがカラーマップの組み込みを開始または終了する切っ掛けとなったイベントのタイムスタンプ。
data[1] | クライアントがカラーマップの組み込みを開始する時は「1」、終了した時は「0」。
data[2] | 予約。「0」でなければならない。
data[3] | 予約。「0」でなければならない。
data[4] | 予約。「0」でなければならない。

この機能は、本規約のバージョン 2.0 から採用されたものである。そのため、全てのウィンドウ・マネージャがこの機能を実装するまで(そのように想定できるようになるまで)相当の時間がかかるであろう。クライアントは、この機能を使う前に、ウィンドウ・マネージャが則っている規約の版を調べ、ウィンドウ・マネージャがこの機能に対応しているか確認しなければならない(「セレクションを通じてウィンドウ・マネージャと交信」で述べる仕組みを利用する)。これは、クライアントと古いウィンドウ・マネージャとの間でカラーマップの組み込みが衝突するのを防ぐために必要なことである。

ウィンドウ・マネージャは、クライアントがカラーマップ組み込みの制御権を要求している間、カラーマップの組み込みを差し控えるものとする。ウィンドウ・マネージャは、クライアントがカラーマップの組み込みを終えた時に自身のカラーマップ・フォーカス方針を復活させられるように、組み込まれたカラーマップの集合(の変更)を監視し続けるものとする。

この手続きには競合状態(race condition)がある。クライアントが通知を発した後もカラーマップの組み込みが続いてしまう状況が発生し得る。たとえば、ウィンドウ・マネージャがいくつかの `InstallColormap` リクエストを発行してしまい、そのリクエスト群がクライアントの `SendEvent` と `InstallColormap` リクエスト群の後でなければ実行されない場合、クライアントのカラーマップの解放が行われてしまう。(訳註：`InstallColormap` には副作用があり、組み込むよう指定したカラーマップとは別のカラーマップが X サーバによって暗黙のうちに解放されてしまうことがある。) これが起こった時、クライアントが依然としてポインタを占有しており、且つクライアントが未だ「完了」の通知を発していない場合、同クライアントは目的のカラーマップを再度組み込もうとするかもしれない。

> 実装者のために

> クライアントは、override-redirect ウィンドウを使ったアニメーションやポップアップ・ウィンドウ等のために、この仕組みを利用するであろう。

> クライアントが「完了」の通知の発行に失敗した場合、ウィンドウ・マネージャは、カラーマップ組み込み方針が停止されたままになる可能性がある。ウィンドウ・マネージャの実装者は、利用者からの命令によってカラーマップ組み込み方針をリセットする機能を実装するべきであろう。

### アイコン

クライアントは、自身のアイコンの望ましい外観について、ウィンドウ・マネージャにヒントを与えることができる。次の方法による。

- WM_ICON_NAME に文字列を設定する。

  すべてのクライアントはこの設定をするべきである。ウィンドウ・マネージャにとってのアイコンの概念がクライアントにとってのものと大きく異なる場合に、この設定がウィンドウ・マネージャに代替情報を提供してくれるからである。

- WM_HINTS プロパティの icon_pixmap フィールドにピクスマップを設定し、おそらくそれとは別のピクスマップを icon_mask フィールドに設定する。

  ウィンドウ・マネージャは、icon_mask のマスクでマスクしたピクスマップを表示することを期待されている。このピクスマップのサイズは、ルートの WM_ICON_SIZE プロパティに入っているサイズのいづれかとする。このプロパティが見当たらない場合、ウィンドウ・マネージャはおそらくアイコン・ピクスマップを表示しないであろう。ウィンドウ・マネージャは通常、WM_ICON_SIZE に合わないピクスマップを表示する際には、同ピクスマップの縁を削ったり同ピクスマップを反復表示したりすることになる。

- WM_HINTS プロパティの icon_window フィールドにウィンドウを設定する。

  ウィンドウ・マネージャは、クライアントがアイコン状態の時は常に上記のウィンドウをマップすることを期待されている。原則としては、このアイコン・ウィンドウのサイズは、ルートの WM_ICON_SIZE が存在する場合、同プロパティに入っているサイズのいづれかとする。ウィンドウ・マネージャは自由にアイコン・ウィンドウのサイズを変更することができる。

ウィンドウがアイコン状態にある時、ウィンドウ・マネージャは以下のことを保証する。

- ウィンドウの WM_HINTS.icon_window が設定してあれば、そこで指定されているウィンドウが表示される。

- ウィンドウの WM_HINTS.icon_window は設定されてないものの、同ウィンドウの WM_HINTS.icon_pixmap が設定されている場合、そこで指定されているピクスマップが表示される。

- どちらでもない場合、ウィンドウの WM_ICON_NAME の文字列が表示される。

クライアントは、自身のアイコン・ウィンドウにつき、以下の規約を遵守すべきである。

> 規約

> - アイコン・ウィンドウは、ルートの `InputOutput` クラスの子ウィンドウとする。

> - アイコン・ウィンドウのサイズは、ルートの WM_ICON_SIZE プロパティに挙げられているサイズのいづれかとする。

> - アイコン・ウィンドウは、そのスクリーンのルートのヴィジュアルとデフォルト・カラーマップを使用するものとする。

> - クライアントは、自身のアイコン・ウィンドウをマップしないものとする。

> - クライアントは、自身のアイコン・ウィンドウをアンマップしないものとする。

> - クライアントは、自身のアイコン・ウィンドウの構成を変更(configure)しないものとする。

> - クライアントは、自身のアイコン・ウィンドウに override-redirect 属性を設定しないものとし、また、同アイコン・ウィンドウに関して `ResizeRedirect` イベントを選択しないものとする。

> - クライアントは、自身のアイコン・ウィンドウを介して入力イベントを受け取れることを当てにしてはならない。

> - クライアントは、自身のアイコン・ウィンドウのボーダを操作してはならない。

> - クライアントは、自身のアイコン・ウィンドウに関する `Exposure` を選択しなければならず、要求があれば同アイコン・ウィンドウを再描画しなければならない。

ウィンドウ・マネージャには、(クライアントの)アイコン・ウィンドウへの入力イベントに対応している者とそうでない者がある。大半のウィンドウ・マネージャは、クライアントが一部のキーやボタンを受け取ることを妨げない。

ウィンドウ・マネージャは、アイコン・ウィンドウが持つ次のプロパティを無視する。即ち、WM_NAME、WM_ICON_NAME、WM_NORMAL_HINTS、WM_HINTS、WM_CLASS、WM_TRANSIENT_FOR、WM_PROTOCOLS、WM_COLORMAP_WINDOWS、WM_COMMAND、及び WM_CLIENT_MACHINE プロパティを無視する。

### ポップアップ・ウィンドウ

ウィンドウをポップアップしたいクライアントは、次の３つの方法を用いることができる。

- クライアントは、通常の最上位ウィンドウを新たに作成してマップする。このウィンドウは、通常のウィンドウとしてウィンドウ・マネージャが装飾し管理することになる。後述のウィンドウ・グループの解説を参照。

- ウィンドウが可視状態である時間が比較的短く、扱い方が多少軽くても良い場合、クライアントは同ウィンドウに WM_TRANSIENT_FOR プロパティを設定することができる。装飾は少なくなるけれども、通常のウィンドウ・マネージャ・プロパティは全てこのウィンドウに設定することができる。ダイアログ・ボックスが一例である。

- ウィンドウが可視状態である時間がきわめて短く、全く装飾しない方が良い場合、クライアントは同ウィンドウに override-redirect 属性を設定することができる。原則として、この方法をとるのは、ウィンドウがマップされている間にポインタを占有しつづける場合に限るものとする。この種のウィンドウは、ウィンドウ・マネージャに動作を妨げられることがないので、慎重に利用するべきである。この方法を適切に用いているものとしては、ポップアップ・メニューがある。

> 実装者のために

> 利用者は、override-redirect ウィンドウに対して移動やサイズ変更を行うことができず、同ウィンドウの積み重ね順序の変更もできず、さらには入力フォーカスを同ウィンドウに移すこともできない。ウィンドウ・マネージャが override-redirect ウィンドウを管理していないからである。クライアントは、override-redirect ウィンドウへのキー入力を受け取る必要がある場合、次のどちらかの手法を採らなけれならない。即ち、キーボードを占有するか、さもなくば override-redirect でない新たな最上位ウィンドウであって Locally Active 型もしくは Globally Active 型のフォーカス型式を採用したものを用意するかしなければならない。クライアントは次の場合には override-redirect ウィンドウにフォーカスを設定してよい。即ち、override-redirect でないウィンドウが WM_TAKE_FOCUS メッセージを受け取った場合、もしくは同ウィンドウが「Input Focus」の Globally Active フォーカス型式の説明のところで挙げたイベントのいづれかを受け取った場合である。

ウィンドウ・マネージャは、 WM_TRANSIENT_FOR ウィンドウを一時的に活用しているウィンドウがアイコン状態になった場合に、当の WM_TRANSIENT_FOR ウィンドウをアイコン化するか否かを自由に決めることができる。WM_TRANSIENT_FOR ウィンドウを表示しているクライアントは、同ウィンドウを活用していたウィンドウがアイコン化された場合でも(もしくはアイコン化されるよう要求があった場合でも)、当の WM_TRANSIENT_FOR ウィンドウに対して同様の処理を実施するよう要請する必要は無い。このような WM_TRANSIENT_FOR ウィンドウの状態を変更することがウィンドウ・マネージャの方針であれば、同ウィンドウ・マネージャはそのように行動することになる。

### ウィンドウ・グループ

利用者から見て、互いに関連があるものとして扱うべきだと思われる最上位ウィンドウの群れは(たとえそれらが別々のクライアントに所属しているとしても)、WM_HINTS 構造体の window_group フィールドを用いて一纏めにするものとする。

一纏まりのウィンドウの中の１つ(他のウィンドウが参照する者)は、グループ・リーダーとなり、個々のプロパティとは違う形でそのグループの情報を保持する。ウィンドウ・マネージャは、グループ・リーダーの扱いとグループ内の他のウィンドウの扱いとに差をつけてもよい。たとえば、グループ・リーダーには完全な装飾を施し、他のグループ・メンバーには一部の装飾しか施さないということも可能である。

クライアントは、グループ・リーダーをマップしなくてもよい。グループ・リーダーは単にプレイスホルダとして存在するだけでもかまわないからである。

グループ内のウィンドウの扱い方を決めるのは、ウィンドウ・マネージャの仕事である。今のところ、クライントがグループ単位の処理を要求する手段は存在しない(ウィンドウ単位の場合とは異なる)。

## ウィンドウ・マネージャの動作へのクライアントの対応

ウィンドウ・マネージャは、クライアントの資源(主に最上位ウィンドウ)に対して数々の操作を施す。クライアントは、これに抵抗しようとしてはいけないが、ウィンドウ・マネージャの操作に関する通知を受け取ることはできる。

### 親の変更

クライアントは次のことを承知していなければならない。即ち、クライアントの最上位ウィンドウの親を変更するウィンドウ・マネージャが存在し、その結果、ルートの子として作成されたウィンドウが、同ウィンドウ・マネージャに属する何らかのウィンドウの子として表示される可能性があることを承知していなければならない。この親変更は、クライアントに対して以下の影響を与える。

- `QueryTree` リクエストが返す親ウィンドウの値は、親変更されたウィンドウを作成した時に `CreateWindow` に渡した値ではなくなっている。クライアントは、新たに最上位ウィンドウの親となったウィンドウが何者であるのか、知っておく必要は無い。特に、最上位ウィンドウを追加で作成したいクライアントは、新しいウィンドウの親としては引き続きルートを使用するものとする。

- X サーバは、`ConfigureWindow` リクエストの(x, y)座標を新しい親の座標空間で解釈する。けれども実際には、親変更を行うウィンドウ・マネージャが通常こうした操作を横取りするので、同座標が X サーバによって解釈されることはない(「操作のリダイレクト」を見よ)。クライアントは、この種のリクエストにルートの座標空間を使うものとする(「ウィンドウの構成」を見よ)。

- 兄弟ウィンドウを指定した `ConfigureWindow` リクエストは失敗する可能性がある。なぜなら、かつて兄弟だったウィンドウは、親変更の操作の後にはもはや兄弟ではなくなっているからである(「ウィンドウの構成」を見よ)。

- `GetGeometry` リクエストが返す(x, y)座標は親の座標空間のものであり、親変更の操作の後は直接役に立つものではない。

- background-pixmap 属性に `ParentRelative` を指定した場合、背景がどうなるかは予測不能である。

- cursor 属性に `None` を指定した場合、カーソル表示がどうなるかは予測不能である。

親が変更された時に通知を受け取りたいクライアントは、自身の最上位ウィンドウに関して `StructureNotify` イベントを選択することができる。同クライアントは、親変更が起きた場合、その時点で `ReparentNotify` イベントを受け取る。クライアントが最上位ウィンドウを引っ込めた(withdraw)場合、これまで同ウィンドウがルート・ウィンドウ以外の親を与えられていたのであれば、ウィンドウ・マネージャは同ウィンドウの親をルート・ウィンドウに戻すことになる。

ウィンドウ・マネージャがクライアントのウィンドウの親を変更した場合、親変更されたウィンドウは新たに親になったウィンドウ(訳註：を作成したクライアント･･･例えばウィンドウ・マネージャ)のセーブセット(save-set)に入る。これは次のことを意味する。即ち、親変更されたウィンドウは、ウィンドウ・マネージャが終了した場合でも破棄されないこと、また、アンマップされた状態であれば再マップされることを意味する。この処理は、ウィンドウ・マネージャが親変更を行うクライアント・ウィンドウ全てに適用されることに注意。一時的な(transient)ウィンドウ及びクライアントのアイコン・ウィンドウも、こうしたクライアント・ウィンドウに含まれる。

### 操作のリダイレクト

クライアントは、一部のウィンドウ・マネージャが一部のクライアント・リクエストを横取りしてリダイレクト(リクエストの配送先の変更)することを承知していなければならない。リダイレクトされたリクエストが実行されることはない。代わりにこのようなリクエストはイベントになってウィンドウ・マネージャへ送られる。同イベントを受け取ったウィンドウ・マネージャはクライアントに代わって、何もしなかったり引数を変更したりそのままのリクエストを実行したりする。

リクエストがリダイレクトされる可能性があるということは、クライアントは次のことを仮定できないこと意味する。即ち、リダイレクト可能なリクエストがリクエスト発行時に実際に実行されること、あるいは時点を問わずとにかく実際に実行されることを仮定できない。リダイレクトされる可能性があるリクエストは `MapWindow`、`ConfigureWindow`、及び `CirculateWindow` である。

> 実装者のために

> 次の手順は間違っている。なぜかというと、`MapWindow` リクエストが横取りされている可能性があり、`PolyLine` の出力がアンマップ状態のウィンドウに対して為されているかもしれないからである。

>     MapWindow A
>     PolyLine A GC <point> <point> ...

> クライアントは、`Expose` イベントを待ってからウィンドウ内の描画を実行しなければならない。[10]

> 次の例は、指定した引数で実際に `ConfigureWindow` リクエストが実行されていることを誤って仮定している。

>     ConfigureWindow width=N height=M
>     <ウィンドウが N ✕ M であることを仮定した出力>

> クライアントは、自身のウィンドウに関して `StructureNotify` マスクを選択し、`ConfigureNotify` イベントを追跡して自身のウィンドウのサイズを監視するものとする。

> クライアントは、マップしたばかりのウィンドウに対してフォーカスを設定しようとする時は特に注意しなければならない。次の手順は X プロトコル・エラーに終わる可能性がある。

>     MapWindow B
>     SetInputFocus B

> `MapWindow` リクエストが横取りされていた場合、リクエストで指定されたウィンドウは未だアンマップ状態であり、これによって `SetInputFocus` リクエストがエラーを起こす。この問題の解決方法は、クライアントが先のウィンドウに関して `VisibilityChange` マスクを選択し、同ウィンドウが可視状態になったことを示す `VisibilityNotify` イベントを(クライアントが)受信するまで `SetInputFocus` リクエストの発行を延期することである。

> この手法でも正しい処理は保証されない。利用者は `SetInputFocus` リクエストがサーバに届くまでにウィンドウをアイコン化してしまっているかもしれず、この場合にもエラーが起きる。また、ウィンドウ・マネージャがウィンドウをアイコン状態としてマップする可能性もある。この場合、ウィンドウは可視状態にならず、`VisibilityNotify` イベントの発生は無期限に延期される。クライアントは、これらの場合に対応できるよう備えていなければならない。

override-redirect のビットが立てられているウィンドウはリダイレクトされない。このビットは、override-redirect ウィンドウがマップされている間(「ポップアップ・ウィンドウ」を見よ)や `ResizeRequest` イベントに応答している間(「リクエストをリダイレクトする」を見よ)に他のウィンドウが入力を処理しないようにする場合に限って、最上位ウィンドウに設定するものとする。

Withdrawn 状態でない最上位ウィンドウを１つも持たないクライアントであって、且つ override-redirect の最上位ウィンドウを１つ持つ者は、システムの状態に対する全責任を引き継ぐ。このようなクライアントは以下の仕事をしなければならない。

- 元から存在するウィンドウ・マネージャがこのようなクライアントの活動を妨碍しないようにする。

- ウィンドウをアンマップした後は直ちに現状を復元し、元から存在するウィンドウ・マネージャが混乱しないようにする。

事実上、この種のクライアントは一時的なウィンドウ・マネージャとして振る舞う。このような手法を用いるのは止めるべきである。なぜかというと、このようなクライアントはウィンドウ・マネージャが維持しようとしているユーザ・インターフェイスの方針を知らない上、このようなクライアントのユーザ・インターフェイスの振る舞いは、多くを要求しないクライアントのユーザ・インターフェイスの振る舞いと衝突しがちだからである。

### ウィンドウの移動

ウィンドウ・マネージャが最上位ウィンドウのサイズを変更することなく位置を変更した(移動させた)場合、クライアントはウィンドウの移動直後に代用の `ConfigureNotify` イベントを受け取る。同イベントには、ルートの座標空間における新しい位置が入っている。クライアントはこの移動に対して、より良い位置に自分を移動させようとする試みで応えてはならない。

最上位ウィンドウに関する本物の `ConfigureNotify` イベントは全て、同ウィンドウのルートの座標空間における位置が変わった可能性があることを示す。たとえ同イベントが「ウィンドウの位置がその親の座標空間において変更されてない」と報告しているとしても、ウィンドウの親が変更されている可能性があるので、同様に解釈する。この場合、イベントに入っている座標は直接役に立つものではない。

ウィンドウ・マネージャがこのイベントを送信するには、次の引数を与えた `SendEvent` リクエストを用いる。

引数 | 値
--- | ---
destination | クライアントのウィンドウ
propagate | False
event-mask | StructureNotify

### ウィンドウのサイズ変更

クライアントは、自身の最上位ウィンドウに関して `StructureNotify` イベントを選択することで、サイズ変更の通知を受け取るよう設定することができる。クライアントが受け取るのは `ConfigureNotify` イベントである。同イベント内のサイズの情報は正しいものではあるが、位置情報は親ウィンドウ(ルートではない場合がある)の座標空間におけるものである。

サイズ変更に対してクライアントが取るべき反応は、与えられたサイズを受け入れ、そのサイズで最善を尽くすことである。クライアントはこのサイズ変更に対して、自分をより良いサイズに変更しようという試みで応えてはならない。そのサイズではうまく動けない場合、クライアントはアイコン状態への変更を要求することができる。

### アイコン化とアイコン状態の解除

Withdrawn 状態でない最上位ウィンドウは、マップされている時は Normal 状態であり、アンマップされている時は Iconic 状態である。これは、同ウィンドウの親が変更されている場合でも当てはまる。ウィンドウ・マネージャは、このウィンドウがアイコン状態へ移行する時、その親とともにこのウィンドウをアンマップする。

クライアントは、最上位ウィンドウに関して `StructureNotify` イベントを選択することで、上記の状態変更の通知を受け取るよう設定することができる。この設定をしたクライアントは、アイコン状態になる時には `UnmapNotify` イベントを、通常状態になる時には `MapNotify` イベントを受け取る。

### カラーマップの変更

クライアントは、自身のカラーマップの組み込みや解放について通知を受けたいのであれば、自身の最上位ウィンドウ、及び最上位ウィンドウの WM_COLORMAP_WINDOWS プロパティで指定した全てのウィンドウに関して、`ColormapNotify` イベントを選択するものとする。クライアントは、こうしたウィンドウのカラーマップが組み込まれたり解放されたりした時に、new フィールドに FALSE の入った `ColormapNotify` イベントを受け取ることになる。

### 入力フォーカス

クライアントは、自身の最上位ウィンドウに関して `FocusChange` イベントを選択して、入力フォーカスを得た時に通知を受けられるよう要求することができる。こうしたクライアントは、`FocusIn` イベントと `FocusOut` イベントを受け取ることになる。クライアントは、自身の下位ウィンドウのいづれかに入力フォーカスを設定する必要がある場合、自身の WM_PROTOCOLS プロパティに WM_TAKE_FOCUS を設定した上で下記のいづれかを行っていない限り、下位ウィンドウに入力フォーカスを設定しないものとする。

- WM_HINTS プロパティの input フィールドに `True` を設定し、実際に自身の最上位ウィンドウのいづれかに入力フォーカスを得た。

- WM_HINTS プロパティの input フィールドに `False` を設定し、「入力フォーカス」で述べたイベントを受け取った。

- 「入力フォーカス」で述べた WM_TAKE_FOCUS メッセージを受け取った。

クライアントは、フォーカスを移そうとしてポインタをワープさせたりしないものとする。ポインタには触れずにフォーカスだけを設定するべきである。「ポインタ」も参照。

クライアントは、一度上記の条件を満せば、`SetInputFocus` リクエストを用いて自分の有する別のウィンドウへフォーカスを移すことができる。このリクエストは次のように定義されている。

`SetInputFocus`

focus: WINDOW または PointerRoot または None
revert-to: { Parent, PointerRoot, None }
time: TIMESTAMP または CurrentTime

> 規約

> - クライアントは、`SetInputFocus` リクエストの引数 time には、このリクエストの切っ掛けとなったイベントのタイムスタンプを指定しなければならない。`FocusIn` イベントは、タイムスタンプを持っていないので、この切っ掛けたるイベントにはなり得ない。またクライアントは、対応する `EnterNotify` イベント無しにフォーカスを取得することができる。クライアントは、引数 time に `CurrentTime` を渡してはならない。

> - クライアントは、`SetInputFocus` リクエストを使って自分のウィンドウのいづれかにフォーカスを設定する場合、引数 revert-to に `Parent` を指定しなければならない。

### ClientMessage イベント

クライアントは、`ClientMessage` イベントが自分に送られてくるのを阻止することはできない。

WM_PROTOCOLS プロパティを持つ最上位ウィンドウには、同プロパティ内のアトムで指定したプロトコル固有の `ClientMessage` イベントが送られてくる(「WM_PROTOCOLS プロパティ」を見よ)。この `ClientMessage` イベントは、いづれのプロトコルのものであっても下記の内容を含んでいる。

- type フィールドにはアトム「WM_PROTOCOLS」。(訳註：[9]を参照)

- format フィールドには「32」。

- data[0] フィールドには、プロトコルを表すアトム。

- data[1] フィールドにはタイムスタンプ。

window フィールドをはじめとした同イベントのその他のフィールドの内容は、プロトコル次第である。

このイベントは、下記の引数を与えた `SendEvent` リクエストを使って送信される。

引数 | 値
--- | ---
destination | クライアントのウィンドウ
propagate | False
event-mask | () 空のマスク
event | プロトコルによって決まる

#### ウィンドウの削除

クライアントの中、複数の最上位ウィンドウを持っており、自身の最上位ウィンドウの一部が削除されてもサーバとの接続を保たなければならない者は、各最上位ウィンドウのプロパティ WM_PROTOCOLS にアトム WM_DELETE_WINDOW を書き加えるものとする。こうすることで、上で述べたような `ClientMessage` イベントがクライアントの元に届くようになる。この場合、ClientMessage イベントの data[0] 部分にアトム WM_DELETE_WINDOW が入っている。

メッセージ WM_DELETE_WINDOW を受信したクライアントは、まるで利用者が仮想のメニューから「ウィンドウを削除する」を選択したかのように振る舞うものとする。クライアントは、利用者に対して何らかのダイアログによる確認を行うものとし、その結果クライアントが削除を完遂すると決意した場合、以下の処理を行うものとする。

- ウィンドウの状態を Withdrawn(「ウィンドウの状態の変更」で説明)にするか、ウィンドウを破棄する。

- ウィンドウに結び付けられている内部状態を破棄する。

ダイアログによる確認の時に利用者が削除を中止した場合、クライアントは同メッセージを無視するものとする。

クライアントは、利用者とやり取りをして次のようなことを尋ねることができる。たとえば、削除するウィンドウと結び付いたファイルを保存するかどうか、あるいはウィンドウの削除を取り消すかどうか等。クライアントはウィンドウそのものを破棄しなければいけないわけではない。リソースは再利用してもよいが、結び付いている状態(バッキング・ストアなど)は全て解放すべきである。

クライアントがウィンドウの破棄を中止してから再度利用者が「ウィンドウを削除する」を選択した場合、ウィンドウ・マネージャは再び WM_DELETE_WINDOW の手続きを開始するものとする。ウィンドウ・マネージャは、ウィンドウの中、プロパティ WM_PROTOCOLS 内に WM_DELETE_WINDOW を持っている者に対して、リクエスト `DestroyWindow` を使用しないものとする。

プロパティ WM_PROTOCOLS に WM_DELETE_WINDOW を加えていないクライアントは、利用者が同クライアントの最上位ウィンドウの何れかを削除するよう要請した場合、サーバから接続を切られる可能性がある。

### リクエストをリダイレクトする

通常のクライアントは、親ウィンドウに関して `SubstructureRedirect` イベントを選択するか、あるいは子ウィンドウに関して `ResizeRedirect` イベントを選択すると、ウィンドウ・マネージャと同じようにリダイレクトの機構を使用することができる。但し、これらのイベントを選択できるのは１つのウィンドウにつき１つのクライアントだけなので、衝突を避けるために規約が必要となる。

> 規約

> クライアント(ウィンドウ・マネージャを含む)は、自分が所有するウィンドウに限って `SubstructureRedirect` イベントと `ResizeRedirect` イベントを選択するものとする。

クライアントは、自身がサイズ変更された時に特別な動作を行う必要がある場合、自身の最上位ウィンドウに関して `ResizeRedirect` イベントを選択することができる。こうしたクライアントはウィンドウ・マネージャが同クライアントのウィンドウのサイズを変更した時に `ResizeRequest` イベントを受け取るけれども、実際にはサイズ変更は行われない。クライアントは、ウィンドウ・マネージャがクライアントのサイズを変更したがっているという情報を好きなように利用できるけれども、適切な時間内に上記イベントで指定された幅と高さにウィンドウを構成しなければならない。この段階で、ウィンドウ・マネージャがサイズ変更のリクエストを横取りして実行するのではなく(つまりサイズ変更の手続きを最初からやり直すのではなく)、実際にサイズ変更が行われるようにするには、クライアントはウィンドウに対して一時的に override-redirect 属性を設定する必要がある。

> 規約

> `ResizeRequest` イベントを受け取ったクライアントは、以下のように応じなければならない。

> - イベントで指定されたウィンドウに override-redirect を設定する。

> - できるだけ早く且つ他のジオメトリ関係のリクエストを発する前に、イベントで指定されたウィンドウをイベントで指定された幅と高さに構成する(configure)。

> - イベントで指定されたウィンドウの override-redirect 属性を解除する。

ウィンドウ・マネージャは、クライアントがこの規約に従っていないことを発見した場合、このクライアントへの対処として相応しいと思われる処置を何でも自由に実行することができる。

## セレクションを使ってウィンドウ・マネージャと交信

ウィンドウ・マネージャは、自分が管理するスクリーンのそれぞれに関して、「WM_Sn」という名前のセレクションの所有権を取得する。「n」はスクリーンの番号である。これは「辨別名」のところで述べた通り。ウィンドウ・マネージャは、「マネージャ・セレクション」で述べた、マネージャ・セレクションのための規約を遵守するものとする。これによってクライアントは、同セレクションに対する変換リクエストの発行を通じて、様々な情報やサービスを要求することができるようになる。ウィンドウ・マネージャは、自身のマネージャ・セレクションを下記のターゲットへと変換する機能を備えるものとする。

アトム | 型 | 戻ってくるデータ
--- | --- | ---
VERSION | INTEGER | 整数が２つ。これはウィンドウ・マネージャが則っている ICCCM の版番号の上位の数字と下位の数字である。この版の ICCCM の場合、それぞれ「2」と「0」になる。 [a]
[a] 特殊な例だが、セレクション・リクエストを実装したくないクライアントは、適当な WM_Sn セレクションに対して単に `GetSelectionOwner` リクエストを発行するだけでも良い。このセレクションが所有されている場合、クライアントは、ウィンドウ・マネージャが ICCCM のバージョン 2.0 もしくはそれ以降の版のものを遵守していると考えることができる。

## ウィンドウ・マネージャ・プロパティの型のまとめ

ウィンドウ・マネージャ・プロパティを下の表にまとめる(「Xlib - C Language X Interface」の 14.1 節も参照)。

名前 | 型 | データ形式(format) | 参照すべき節
--- | --- | --- | ---
WM_CLASS | STRING | 8 | WM_CLASS Property
WM_CLIENT_MACHINE | TEXT |  | WM_CLIENT_MACHINE Property
WM_COLORMAP_WINDOWS | WINDOW | 32 | WM_COLORMAP_WINDOWS Property
WM_HINTS | WM_HINTS | 32 | WM_HINTS Property
WM_ICON_NAME | TEXT |  | WM_ICON_NAME Property
WM_ICON_SIZE | WM_ICON_SIZE | 32 | WM_ICON_SIZE Property
WM_NAME | TEXT |  | WM_NAME Property
WM_NORMAL_HINTS | WM_SIZE_HINTS | 32 | WM_NORMAL_HINTS Property
WM_PROTOCOLS | ATOM | 32 | WM_PROTOCOLS Property
WM_STATE | WM_STATE | 32 | WM_STATE Property
WM_TRANSIENT_FOR | WINDOW | 32 | WM_TRANSIENT_FOR Property

[7] この旧版プロトコルは、ICCCM の１９８８年７月２７日付けの草案に記載されている。このプロトコルを使っているウィンドウは、同ウィンドウの WM_HINTS プロパティが通常より４バイト長いことからも見分けることができる。ウィンドウ・マネージャは、後方互換モードを用いて、旧版のプロトコルを使っているクライアントに対応してもよい。

[8] この規約の前の版では、クライアントが WM_STATE プロパティを読み取ることは禁じられていた。前の版に基づいて動作するクライアントは、`ReparentNotify` イベントを監視して最上位ウィンドウがルート・ウィンドウへ親を変更されるのを待つ、という手法を用いていた。これは今でも有効な手法である。しかしながら、この手法が機能するのは親変更を行うウィンドウ・マネージャに対してだけなので、WM_STATE プロパティを使う手法を使うべきである。

[9] `ClientMessage` イベントの「type」フィールド(Xlib では「message_type」フィールド)をイベント・コードを表すフィールド(訳注：Xlib では「type」フィールド)と間違えてはいけない。後者には、`ClientMessage` イベントであることを表す値「33」が入る。

[10] この記述は、クライアントがウィンドウの backing-store 属性を `Always` に設定していた場合でも正しい。backing-store 属性はヒントにすぎず、X サーバはバッキング・ストアの内容を保持することをいつでも止めることができる。

## 第五章　セッション・マネジメントのためのクライアント間交信機構

この章では、セッション・マネジメントに参加するクライアントのための規約をいくつか定める。詳しくは X Session Management Protocol(X セッション・マネジメント・プロトコル) を見よ。このプロトコルに対応していないクライアントは、セッションを跨いで自身のウィンドウの状態(WM_STATE、位置、大きさ、表示の重なり順序)が保存されることを期待できない。

## セッション・マネジメントのためにクライアントが持つべき機能

セッション参加者は各々、セッション・マネージャから唯一無二のクライアント識別子(クライアント ID)を取得する。クライアントは、最上位ウィンドウの中の一つを「クライアント・リーダ」(client leader)に指定しなければならない。このウィンドウはどうクライアントが作成したものでなければならない。このウィンドウの状態はどんなものでも良く、Withdrawn 状態でもかまわない。クライアント・リーダ・ウィンドウは、プロパティ SM_CLIENT_ID を持たねばならない。このプロパティにはセッション・マネジメント・プロトコルの手続きで得たクライアント ID が入る。同プロパティの形式は次のものでなければならない。

- STRING 型である

- 形式は format 8 である(8bit が単位のデータ列)

- ISO 8859-1 で符号化された XPCS 文字列一つから成るクライアント ID が入る

あるクライアントによって作られたウィンドウであって、同クライアントのクライアント・リーダ(client leader)と同一のディスプレイ上にあり、最上位であり、且つ一時的でない(nontransient)ウィンドウは全て、プロパティ WM_CLIENT_LEADER を持たなければならない。このプロパティには、クライアント・リーダ・ウィンドウを特定するためのウィンドウ ID が入る。クライアント・リーダ・ウィンドウは、自身のウィンドウ ID の入った WM_CLIENT_LEADER プロパティを持たなければならない(つまり、クライアント・リーダ・ウィンドウは自分自身を指す。)。一時的な(transient)ウィンドウは、WM_TRANSIENT_FOR プロパティの情報を用いてクライアント・リーダを特定できるのであれば、WM_CLIENT_LEADER プロパティを持たなくても良い。プロパティ WM_CLIENT_LEADER の形式は次のものでなければならない。

- WINDOW 型である

- 形式は format 32 である(32bit 単位のデータ)

- クライアント・リーダ・ウィンドウのウィンドウ ID が入る

クライアントは、同じディスプレイにある自身の最上位ウィンドウ全てを非表示にした(withdraw)後でなければ、自身のクライアント・リーダ・ウィンドウの WM_CLIENT_LEADER プロパティや SM_CLIENT_ID プロパティを変更してはならない。

同一のクライアント ID を持つウィンドウ全ての中から一つのウィンドウを(セッションを跨いで)一意に特定する、という動作が他のクライアントから実行可能でなければならない。例えば、ウィンドウ・マネージャが前回セッションのジオメトリ情報を復元するためにこのような唯一無二の ID を要求することもあり得る。また、ワークスペース・マネージャも、どのワークスペースにどのウィンドウ群が存在したのかという情報を復元するためにこの ID を利用するかもしれない。 クライアントは、前述の範囲でウィンドウを一意に特定するために、WM_WINDOW_ROLE プロパティを作ることができる(任意)。他のクライアントは、SM_CLIENT_ID と WM_WINDOW_ROLE の組み合わせを使って、ウィンドウを(セッションを跨いで)一意に特定する。

最上位ウィンドウにプロパティ WM_WINDOW_ROLE が設定されていない場合、同ウィンドウを一意に特定する必要のあるクライアントは、代わりに WM_CLASS と WM_NAME の値を使おうとするであろう。クライアントは、WM_CLASS プロパティと WM_NAME プロパティの値が同じウィンドウを複数抱えている場合、WM_WINDOW_ROLE プロパティを用意するべきである。

クライアントはプロパティ WM_WINDOW_ROLE に次のような文字列を設定しなければならない。即ち、同一のクライアント・リーダ・ウィンドウを持つウィンドウ全ての中から目的のウィンドウを一意に特定できるような文字列に設定しなければならない。このプロパティの形式は以下に示すものでなければならない。

- STRING 型である

- 形式は format 8 である(8bit 単位のデータ列)

- ISO 8859-1 で符号化した XPCS 文字から成る文字列が入る

## セッション・マネジメントのためにウィンドウ・マネージャが持つべき機能

セッション・マネジメントに対応しているウィンドウ・マネージャは、セッション・マネージャに登録して自身のクライアント ID を取得しなければならない。ウィンドウ・マネージャは次のような情報を保存し、復元すべきである。即ち、クライアント・ウィンドウの中、有効な SM_CLIENT_ID プロパティを備えていて(自ウィンドウに、もしくは WM_CLIENT_LEADER で指し示したウィンドウに)、一意に特定可能なもの全てについて、WM_STATE とスクリーン上の配置と前後の表示順序とを保存し復元すべきである。クライアントには、セッションのチェックポイント処理の第一段階において、これらの状態を変更することが認められている。したがって、ウィンドウ・マネージャはチェックポイント処理の第二段階を要請すべきであり、この段階に限ってクライアントの状態を保存するものとする。

## ICE クライアント待合せ機構のための機能

Inter-Client Exchange protocol (ICE) は、X11R6 の一部であり、X サーバから独立した汎用な(generic、基礎的な)通信の枠組みを定めている。この枠組みは、任意のクライアントの間でデータ交換を行うためのものである。ICE はまた、同一の X サーバに接続している(X コネクションを持つ)任意の二つの ICE クライアントが互いを見つけ出す(待ち合わせする)ためのプロトコルも定めている。

このプロトコルは、「ICE X Rendezvous」プロトコルと呼ばれ、ICE の文書の附録 B に規定されており、ICE_PROTOCOLS プロパティと `ClientMessage` イベントを用いる。詳しくは ICE の文書を参照。

## 第六章 共有リソースの操作

X11 では、クライアントは、入力フォーカス、ポインタ、カラーマップをはじめとする多くの共有リソースを操作することができる。複数のクライアントが揉めることなくリソースを共同利用するには、以下の規約が必要である。

## 入力フォーカス

明示的に入力フォーカスを設定するクライアントは、次の二つのモードのどちらかに従わなければならない。

- Locally active mode(訳註：ローカルに稼働する状態)

- Globally active mode(訳註：大域的に稼働する状態)

> 規約

> - 「locally active」モードで稼働するクライアントは、自身のウィンドウの中の一つに既に入力フォーカスがある場合、または、同クライアントが WM_TAKE_FOCUS メッセージを受け取った場合に限って、自身のウィンドウの中の一つに入力フォーカスを設定するものとする。このようなクライアントは構造体 WM_HINTS の input フィールド(訳註：flags フィールドの input フラグ？)に `True` を設定する。

> - 「globally active」モードで稼働するクライアントは、ボタン・イベントもしくは受動的に占有された(passive-grabbed)キー・イベントを受け取った場合、または、同クライアントが WM_TAKE_FOCUS メッセージを受け取った場合に限って、自身のウィンドウの中の一つに入力フォーカスを設定するものとする。このようなクライアントは構造体 WM_HINTS の input フィールド(訳註：flags フィールドの input フラグ？)に `False` を設定する。

> - 加えて、クライアントは、同者に入力フォーカス設定の切っ掛けを与えたイベントのタイムスタンプを `SetInputFocus` リクエストの引数 time に設定するものとする。`CurrentTime` を入れてはいけない。

## ポインタ

原則として、クライアントはポインタをワープさせるべきでない。しかし、ウィンドウ・マネージャはそうすることがある(例えば、入力フォーカスの存在するウィンドウに必ずポインタが存在するという不変性を維持するために)。また、別のウィンドウ・マネージャは、ユーザがポインタを独占支配しているかのような状態(幻想)を保とうとするかもしれない。

> 規約

> - クライアントはポインタをワープさせない。

> - ポインタをどうしてもワープさせたいクライアントは、必ずリクエスト `WarpPointer` の引数 src-window に自分のウィンドウのいづれかを設定する。(訳註：X11R7.7/lib/libX11-1.5.0/src/WarpPtr.c、「XWarpPointer」「src-win」)

## 占有(Grabs)

あるウィンドウでクライアントがボタンやキーの占有をしようとしても、他のクライアントが同じウィンドウで既に占有を確立していれば、占有の試みは失敗する。したがって、占有は共有資源であり、使用にあたっては規約が必要になる。

ウィンドウ・マネージャが稼働している時でもクライアントはできるだけウィンドウ・マネージャが稼働してない時と同じように振る舞うべきである、という原則に従えば、入力フォーカスを持つクライアントは受け取り得るキーとボタンは全て受け取れるものと仮定して良いことになる。

> 規約

> ウィンドウ・マネージャは、同者のクライアントがあらゆるキーとボタンからイベントを受け取れる仕組みを用意するものとする。但し、ウィンドウ・マネジメント機能用として登録されているキーシム(KeySyms)を持つキーに関するイベントは除く(例えば、仮想的 WINDOW キーシム(訳註：hypothetical WINDOW KeySym、要確認))。

言い換えると、X コンソーシアムがウィンドウ・マネジメント機能用にキーシムを予約して登録してない限り、あるいは登録するまでは、ウィンドウ・マネージャは、クライアントがあらゆるキーとボタン(修飾キーにかかわらず)からイベントを受け取れる仕組みを用意しなければならない。現在、ウィンドウ・マネジメント機能用として登録されているキーシムは無い。

といっても、クライアントは、プログラムの動作を引き起こすのに使う、キーとボタンの組み合わせを変更できるようにしておくべきである。何故かというと、ウィンドウ・マネージャによっては、この規約を遵守しなかったり、ユーザに対して一部のキーからイベントを送る手段を提供しなかったりする可能性があるからである。

> 規約

> クライアントは、自分の所有するウィンドウ上のものに限って、ボタンとキーを占有するものとする。

この規約は、とりわけ、次のことを意味する。即ち、ウィンドウ・マネージャがクライアントの最上位ウィンドウ上で占有を確立したい場合、同ウィンドウ・マネージャは、ルートに対して占有を確立するか、または目的のウィンドウの親を変更した上で適当な祖先ウィンドウに対して占有を確立すべきであることを意味する。場合によっては、ウィンドウ・マネージャは、受け取ったイベントを自分で消費し、後続の同種のイベントがクライアントへ行くような状態にウィンドウを置こうとする。例えば、

- フォーカスを設定するためにあるウィンドウの内部がクリックされたが、そのクリックはクライアントに向けられたものではない場合。

- 隠れているウィンドウを前面に出すだめに同ウィンドウの内部がクリックされたが、そのクリックはクライアントに向けられたものでない場合。

一般的には、ウィンドウ・マネージャは、自分がイベントを処理した後にクライアントが同じイベントを使えるようにし、これによってキーとボタンの組み合わせに対するクライアント側の効果(the client's semantics for key+button combinations)を置き換えるのではなく増やすようにすべきである。このようなやり方を確実に実践するには、ウィンドウ・マネージャは次のモードで親ウィンドウに対して占有を確立する。

    pointer/keyboard-mode == Synchronous

次いでウィンドウ・マネージャは、次のモードを指定した `AllowEvents` リクエストで占有を解く。

    mode == ReplayPointer/Keyboard

こうすることで、クライアントはまるで横取りが起きなかったかのような形でイベントを受け取ることになる。

言うまでもなく、これらの規約はユーザ・インターフェイスの管理方針に若干の制約を課している。ウィンドウ・マネージャが自分のユーザ・インターフェイスの管理方針を実践する自由と、クライアントが自分のそれを実践する自由とは両立困難である。このジレンマは次の方法で解決する。

- 任意のキーとボタンについて、クライアントがそれらのイベントを受け取るかどうかと、いつ受け取るかとをウィンドウ・マネージャに決めさせる。

- ユーザが任意のキーやボタンのイベントをクライアントに送れる仕組み、「Quote」キーのようなもの、を用意するようウィンドウ・マネージャに義務付ける。

## カラーマップ

「カラーマップ」の節では、クライアントが自分のカラーマップの需要についてウィンドウ・マネージャと話し合うための規約を定めている。クライアントが `DirectColor` 型のアプリケーションの場合、「Xlib - C Language X Interface」の 14.3 節に規定されている標準カラーマップの共有に関する規約を調べること。クライアントは、カラーマップのスクリーンのルート・ウィンドウ(the root window of the appropriate screen)に対して、同文書が規定するプロパティを問い合わせたり作ったりする。

RGB_COLOR_MAP 型のプロパティの内容は下の通り。

フィールド | 型 | 説明
--- | --- | ---
colormap | COLORMAP | カラーマップの ID
red_max | CARD32 | ピクセルの計算に使う値
red_mult | CARD32 |
green_max | CARD32 |
green_mult | CARD32 |
blue_max | CARD32 |
blue_mult | CARD32 |
base_pixel | CARD32 |
visual_id | VISUALID | カラーマップが属するビジュアル(visual)
kill_id | CARD32 | リソースの破毀に使う ID

RGB_COLOR_MAP を削除したり置き換えたりする場合、同プロパティを削除するだけでは充分ではなく、対応するカラーマップ・リソース群も解放することが大切である。kill_id が 1 より大きい場合、この kill_id を引数(訳註：第２引数 XID 型)として `KillClient` リクエストを発行してカラーマップ・リソース群を解放する。kill_id が 1 である場合、このプロパティの colormap フィールドの値を引数 colormap (第２引数 Colormap 型)に入れて `FreeColormap` を発行し、カラーマップ・リソース群を解放する。kill_id が 0 である場合、リソースの解放は行わない。 特定のカラーマップ・リソース１つのために RGB_COLOR_MAP を作ったクライアントは、kill_id を 1 に設定する(この場合、１つの接続を使ってそのような標準カラーマップを複数作ることができる)。(訳註：要確認。) 何らかの方法で共有されるカラーマップ・リソース(例えばルート・ウィンドウの標準カラーマップ)のために RGB_COLOR_MAP を作ったクライアントは、任意のリソースを作成してそのリソース ID を kill_id に設定する(この場合、同一接続上でそれ以外の標準カラーマップを作成しないものとする)。(訳註：要確認。)

> 規約

> プロパティ RGB_COLOR_MAP が短くて visual_id フィールドを格納できない場合、visual_id は、そのスクリーンのルートのビジュアルであると考えて良い。プロパティ RGB_COLOR_MAP が短くて kill_id フィールドを格納できない場合、その値はゼロであると考えて良い。

接続の開始(handshake)の際、X サーバはクライアントに各スクリーンのデフォルトのカラーマップを知らせる。このカラーマップはルートのビジュアルのものであり、クライアントがこのルート・ビジュアルを用いればカラーマップの共有度を高めることができる。

## キーボード・マッピング

X サーバは、サーバが生成する各キーコードと、それに対応するキーに書かれているシンボル(複数のシンボル記号の集合)との対応表(リクエスト `GetKeyboardMapping` で読める)を持っている。この表は、サーバの動作にはまったく影響を与えないものであり、クライアントが自分のところに届いたキーコードを理解するのに利用するデータベースにすぎない。とはいえ、この表も共有リソースであり、規約が必要である。

リクエスト `ChangeKeyboardMapping` を発行して、クライアントがこの表を修正することは可能である。けれども、原則としてクライアントはそのような修正はしないものとする。特に、クライアントはこの方法によってキーに対して機能の割当てを行ったり、キーとシンボルとの対応付けを変更したりすべきではない。サーバから受け取ったキーコードの羅列を特定の符号化方式の文字列へ変換するのは、各クライアントの私事である。なぜかというと、複数のアプリケーションが様々な言語とフォントとに対応するべく様々な符号化方式を用いているに違いないから。キーボード・イベントのテキストへの変換については、Xlib リファレンス・マニュアルを見よ。

リクエスト `ChangeKeyboardMapping` の使用に正当な理由があるとされるのは、キーの上に書かれたシンボル群が変わった場合に限られる。例えば、Dvorak キー変換キットや APL キー・キャップ一式が設置された場合である(訳註：キーボードの上に被せたり貼ったりするもの。APLはプログラミング言語であり、キーボードの上に貼るそれ専用のシール等があるらしい。)。もちろんクライアントは、キー・キャップの変更については、真偽を確認せずに受け入れざるを得ないであろう。

クライアントは、ユーザと以下のようにやり取りしてかまわない。

- 「Pause キーの無いサーバで起動されています。Pause キーとしてキーを一つ選んで押してください。」

- ユーザが「Scroll Lock」キーを押す。

- 「Scroll Lock キーのシンボル群を「Pause」に追加します：確定、または、中止」

- ユーザが確定する。

- クライアントはリクエスト `ChangeKeyboardMapping` を使用し、既にシンボル Scroll Lock を含んでいるキーコード(のシンボルの集合)に シンボル Pause を追加する。そして次のように要求する、「Scroll Lock キーの上に Pause と描いてください。」

> 規約

> クライアントはリクエスト `ChangeKeyboardMapping` を使うべきでない。

あるクライアントがキーボード・マッピングの表(対応表)の変更に成功すると、全てのクライアントに `MappingNotify`(request==Keyboard)イベントが届く。このイベントを受け取らないようにする仕組みは無い。

> 規約

> `MappingNotify`(request==Keyboard)を受け取ったクライントは、使用中の内部のキーコード変換表を全て更新する。

## 修飾キー(modifier)のマッピング

X11では修飾キー・ビット(modifier bit)を８個用意しており、その中の３個は Shift、Lock、Control として予約されている(訳註：「xmodmap -pm」を実行するとわかる？)。修飾キー・ビットの一つ一つは、複数のキーから成る集合一つの状態によって制御される。この集合はどれも、`GetModifierMapping` と `SetModifierMapping` の両リクエストで読み書きされる表に定められている。この表は共有リソースなので、規約が必要である。

予約されている修飾キーのどれかを使う必要のあるクライアントは、その修飾キーの制御ができるよう上述の修飾キー表が正確に設定されているものと想定する。修飾キー Lock は、その制御集合のキーコードに XK_Caps_Lock を含んでいるのか又は XK_Shift_Lock を含んでいるのかに従って、Caps Lock または Shift Lock として解釈される。

> 規約

> クライアントは、修飾キー・ビットの制御に使われるキーシムによって、同修飾キー・ビットの意味を判断する。

特別な修飾キー(例えば META)を使う必要のあるクライアントは、以下の手続きを行う。

- 既存の修飾キーのマッピング(対応表)を全部見る。修飾キーの中に、キーシムの集合に XK_Meta_L もしくは XK_Meta_R を持つキーコードを含むものがあれば、クライアントはその修飾キー・ビットを使う。

- XK_Meta_L もしくは XK_Meta_R によって制御される既存の修飾キーが無い場合、クライアントは未使用の修飾キー・ビット(制御集合が空のもの)を一つ選び、以下の手続きを行う。

  - もしキーシムの集合に XL_Meta_L を持つキーコードがあれば、そのキーコードを先に選んだ修飾キーの制御集合に加える。

  - もしキーシムの集合に XL_Meta_R を持つキーコードがあれば、そのキーコードを先に選んだ修飾キーの制御集合に加える。

  - 上の二つを経てもまだ制御集合が空であれば、ユーザとやり取りして一つ以上のキーを META として選択する。

- 未使用の修飾キー・ビットが無い場合、ユーザに修正処置をとるよう頼む。

> 規約

> - 現在使用されていない修飾キーを必要とするクライアントは、適切なキーシムを持つキーコードを未使用の修飾キー・ビットに割り当てる。

> - 自分自身の修飾キー・ビットを割り当てるため `SetModifierMapping` リクエストを発行したクライアントは、同リクエストが `Busy` を返した場合、問題となっているキーから手を離すようユーザに対して丁寧に頼む。

予約されていない５つの修飾キーが用済みになった時でも、これらの修飾キーに対する割当てを解除する良い方法は無い。

> 規約

> 使わなくなった修飾キーの割当てを手作業で解除するには、ユーザは `xmodmap` その他のユーティリティを使わなければならない。

あるクライアントが `SetModifierMapping` リクエストの実行に成功すると、全てのクライアントに `MappingNotify` イベント(request==Modifier)が届く。このイベントを受け取らないようにする仕組みは無い。予約されていない修飾キーのいづれかを使っているクライアントがこのイベントを受け取った場合、リクエスト `GetModifierMapping` を呼び出して新しい対応表を入手し、使っている修飾キーが消去されていれば同修飾キーを再度設定する。

これらの操作において `GrabServer` と `SetModifierMapping` の対を不可分な処理にするには、リクエスト `GrabServer` を使用しなければならないことに注意。

## 第７章 装置色の特性評価(Device Color Characterization)

X プロトコルには、Red、Green、Blue(RGB)の値(明確な値)が用意されている。これを使って直にモニターを操作したり、色名を扱ったりする。RGB 値のおかげでディスプレイ装置の性能を十分に引き出す仕組みが成り立つのだが、その代わり、ユーザが実際に認識する色は X プロトコルからは知ることができない。色名(color names)はもともと、装置から独立したカラー・データベースにアクセスするためのものであった。これは、文字列から成る同データベースの中の色の定義をサーバの開発者が調整することによって実現される。残念ながら、これだけでは依然として不可能なことがある。即ち、クライアントは既存の装置独立色(device-independent color)を用いる手段を持たないし、また、選択している色を元にして装置独立色の情報を得ることもできない。

さらに、クライアントは、どの色集合が装置(装置の色域)で表示可能なのか、知ることができなければならない。これは、一つには色を上手く修正して装置の表示性能内に収めるためであり(色域圧縮)、もう一つには到達可能な色空間を表したものをユーザ・インターフェイスがユーザに対して表示できるようにするためである(色域の表示)。

それゆえ、X クライアントが装置から独立した色空間へ十全にアクセスできるようなシステムが必要である。このシステムは次のようなものであるべきである。即ち、色を名付けるための標準化された仕組みを用いていて、既存の色に名前を付与できて、且つ、使用不可能な色を修正して装置の色域内に収められるような手段を備えているものであるべきである。

幸運にも、この分野では基礎となる重要な成果がすでにある。1931年の CIE color standard である。これは CRT 装置の色を記述するのに十分なものであると、ほとんどすべての人に認められている。この standard は CIE XYZ と呼ばれる３刺激モデルを用いる。CIE XYZ では、知覚できる色の一つ一つは３つの数値の組で指定する。他にも適当な装置独立色モデルは存在するけれども、そうしたものの大部分はこの最初の成果から直接派生したものである。

X 装置色特性評価によって、X クライアントは装置から独立した色空間を得る。この X 装置色特性評価のおかげで、クライアントは CIE XYZ と通常の X RGB による色表現との対応を自ら組み上げるのに最低限必要な量の(the barest possible amount of)情報を得ることができるのである。(それによって装置から独立した色空間を扱うことができる。)

装置色特性評価は、２つのウィンドウ・プロパティの名前と内容で定まる。この２つのウィンドウ・プロパティによって CIE XYZ 空間と線型 RGB 空間(標準の CRT など)との間の変換が可能になる。線型 RGB 装置の完全な特性評価に必要な情報要素は次の２つだけである。

- 3 x 3 の行列 M とその逆行列 M-1 。これは XYZ と RGB 輝度(RGBintensity)との間の変換を行う。

  > RGBintensity = M x XYZ

  > XYZ = M-1 x RGBintensity

- RGB の輝度と RGB のプロトコル上の値(RGB protocol value)とを対応させる方法。XDCCC(訳註：X Device Color Characterization Conventionsのこと。X11R7.7/app/xcmsdb-1.0.4/loadData.c:1424:「〜Using the X Device Color Characterization Convention (XDCCC)〜」)では、後ほど概略を述べる３つの仕組みを用意している。

のちのち他の装置の型が必要になれば、それらを評価するのに追加のプロパティが必要になるであろう。

## XYZ <-> RGB 変換行列

XYZ と RGB 輝度の両方の取りうる値の範囲が限られていることから、これらの行列は、２の補数の数値を 227 倍したものを 32-bit 且つ固定小数点で表したもので記録する(符号化する)。その範囲は -16〜16 - Ε(但し Ε = 2-27)となる。(訳註：X11R7.7/lib/libX11-1.5.0/src/xcms/LRGB.cなどを参照。)

この行列は 32-bit の値を持つ要素 18 個から成るリスト(配列)に格納されることになる。その際は、 XYZ -> RGB の行列が先、行を上位で、各スクリーンのルート・ウィンドウ上のXDCCC_LINEAR_RGB_MATRICES プロパティ(32ビット単位)の中に、そのスクリーンに適した値で格納される。

次の表のように符号化する。

フィールド | 型 | 補足
--- | --- | ---
M0,0 | INT32 | 固定小数点の数値 -16 ≤ x < 16 と解釈する。
M0,1 | INT32 |
... | INT32 |
M3,3 | INT32 |
M-10,0 | INT32 |
M-10,1 | INT32 |
... | INT32 |
M-13,3 | INT32 |

## 輝度 <-> RGB 値の変換

XDCCC には、RGB 輝度と実際の X プロトコル RGB 値との間の変換の仕方を記述する方法が２つある。

    0     RGB 値/RGB 輝度(intensity level)の 対
    1     RGB 輝度の傾斜

どちらの場合も、関連データは各スクリーンのルート・ウィンドウの XDCCC_LINEAR_RGB_CORRECTION プロパティに格納することになる。その際には、各スクリーンに適した値を、十分な解像度を持つデータ形式で格納する。スクリーンのヴィジュアル毎に異なるデータが必要になる場合、同プロパティには複数のエントリを繋げて入れることができる。VisualID が「0」のエントリは、そのスクリーンのヴィジュアルの中、(プロパティの中で)明示的に挙げられていないもの全てのためのデータを指定する。

第１の表現方法は RGB 値 / RGB 輝度の対の配列であり、RGB 値は完全に(strictly)昇順である。変換する時、クライアントは配列中の隣り合うエントリの間を線型補間して目的の値を計算しなければならない。これによってサーバがガンマ補正そのものを実行できるようになり、サーバはその結果(that fact)を２つの要素だけから成る補正表に記録することができる。(訳註：X11R7.7/lib/libX11-1.5.0/src/xcms/LRGB.c、及びX11R7.7/lib/libX11-1.5.0/src/xcms/Xcmsint.hを参照。) 輝度は正負の符号のない数として符号化され、「0」から「1」(境界を含む)の値として解釈される。この値の精度は、値を格納するプロパティの形式(8bit、16bitもしくは32bit)に依る。16-bit もしくは 32-bit 形式の場合、単純に同プロパティに格納されている値が RGB 値になる。8-bit 形式で格納されている時は、RGB 値は同プロパティに入っている値から次の式を用いて計算できる。

RGB value = { プロパティの値 × 65535 } ÷ 255

装置の３つの電子銃の応答特性(response characteristics、訳註：要確認)は、全く同じもののではなかろうから、３つの独立した表(table)を作って、赤、緑、青に１つづつ割り当てる必要がある。結果として、各表の前には各表に入っているエントリの数が置かれ、全表の前には表の数が置かれることになる。表が３つある場合、赤、緑、青の順になる。

これは、下記の表のように実装する。

XDCCC_LINEAR_RGB_CORRECTION プロパティの内容、「0」型(type フィールドの値が)の補正の場合。

フィールド | 型 | 補足
--- | --- | ---
VisualID0 | CARD | VisualID の最上位の部分
VisualID1 | CARD | プロパティの形式(format)が「8」の時だけ存在する
VisualID2 | CARD | プロパティの形式(format)が「8」の時だけ存在する
VisualID3 | CARD | 最下位部分。プロパティの形式(format)が「8」もしくは「16」の時だけ存在する
type | CARD | この補正の型では「0」
count | CARD | この後ろに続く表(table)の数(「1」もしくは「3」)
length | CARD | この後ろに続く表(table)の中の対の数 - 1
value | CARD | X プロトコルの RBG 値
intensity | CARD | 0 ≤ intensity(輝度) ≤ 1 の数値として解釈する
... | ... | 「length+1」個の「RGB値/輝度値」の対
lengthg | CARD | この後ろに続く表(table)の中の対の数 - 1(「count」が「3」の時だけ存在する)
value | CARD | X プロトコルの RBG 値
intensity | CARD | 0 ≤ intensity(輝度) ≤ 1 の数値として解釈する
... | ... | 「length+1」個の「RGB値/輝度値」の対
lengthb | CARD | この後ろに続く表(table)の中の対の数 - 1(「count」が「3」の時だけ存在する)
value | CARD | X プロトコルの RBG 値
intensity | CARD | 0 ≤ intensity(輝度) ≤ 1 の数値として解釈する
... | ... | 「length+1」個の「RGB値/輝度値」の対

VisualID は、プロパティの形式が「8」「16」もしくは「32」のいづれであるかに応じて、それぞれ４個、２個もしくは１個に分けて格納される。VisualID は常に最上位部分が先に格納される。「length」フィールドには実際の長さよりも１つ少ない値を入れるため、プロパティの形式が「8」なら２５６個のエントリを格納できることに注意。

第２の表現方法は、RGB 値の線型部分集合(a linear subset)に対する、輝度の単純な配列である。この表(table)の予想サイズは、そのスクリーンの bits-per-rgb-value(訳註：「bits」「per」「rgb-value」？)であるが、任意の長さでよい。これは第１の方法とよく似ているけれども、RGB の数値が配列の要素番号(index、「0」から始まる)によって自動的に決まる点が異なっている。

> RGB value = { 配列の要素番号 × 65535 } ÷ { 配列の要素数 - 1 }

変換する時、クライアントはこの表(table)のエントリとエントリの間を線型補間する。輝度の値は、第１の表現方法と同じように符号化する。

これは、下記の表のように実装する。

XDCCC_LINEAR_RGB_CORRECTION プロパティの内容、「1」型(type フィールドの値が)の補正の場合。

フィールド | 型 | 補足
--- | --- | ---
VisualID0 | CARD | VisualID の最上位の部分
VisualID1 | CARD | プロパティの形式(format)が「8」の時だけ存在する
VisualID2 | CARD | プロパティの形式(format)が「8」の時だけ存在する
VisualID3 | CARD | 最下位部分。プロパティの形式(format)が「8」もしくは「16」の時だけ存在する
type | CARD | この補正の型では「1」
count | CARD | この後ろに続く表(table)の数(「1」もしくは「3」)
length | CARD | この後ろに続く表(table)の中の対の数 - 1
intensity | CARD | 0 ≤ intensity(輝度) ≤ 1 の数値として解釈する
... | ... | 「length+1」個の「RGB値/輝度値」の対
lengthg | CARD | この後ろに続く表(table)の中の対の数 - 1(「count」が「3」の時だけ存在する)
intensity | CARD | 0 ≤ intensity(輝度) ≤ 1 の数値として解釈する
... | ... | 「length+1」個の「RGB値/輝度値」の対
lengthb | CARD | この後ろに続く表(table)の中の対の数 - 1(「count」が「3」の時だけ存在する)
intensity | CARD | 0 ≤ intensity(輝度) ≤ 1 の数値として解釈する
... | ... | 「length+1」個の「RGB値/輝度値」の対

## 第８章　結論

本文書では、プロトコル層の仕様を定めた。これは、X バージョン 11のクライアントが支障なく情報交換し合うのに欠かせない、最小限の規約群である。本文書で定めた情報交換に関する規約群は、専ら X バージョン 11のプロトコルを想定したものである。別のプロトコルを使えば X 環境でもっと上手く情報交換できるようになるかもしれないので、クライアントがそのようなプロトコルを認識できるようにしておくべきである。セッション・マネジメントについて知りたい方は X Session Management Protocol へ、特定用途に限定されないクライアント間通信について知りたい方は Inter-Client Exchange Protocol へ進んでほしい。

## X レジストリ

X 協会は、ある種の X 関連事項を載せたレジストリ(登記簿)を管理している。目的は、登記事項が衝突しないようにすることと、各事項の共有を容易にすることである。本文書の読者にも、積極的にレジストリを利用して頂きたい。レジストリに登録してある事項の中、ICCCM に関係のあるものは、プロパティの名前、プロパティの型、セレクションの名前、セレクション・ターゲット、WM_PROTOCOLS のプロトコル群、`ClientMessage` の型、アプリケーションのクラスなど。事項登記の申請、及び登記に関する質問は下記のメールアドレス・住所まで。

メール：

xregistry@x.org

住所：

The X.Org Foundation -- X11 Registry
c/o Alan Coopersmith
Oracle Corporation
M/S SCA17-3824
4170 Network Circle
Santa Clara, CA 95054
USA

電子メールが届いた時は、無事受信できたということを折り返して知らせる。登記申請や質問に対する公式の返答には、最大で四週間かかる。

このレジストリ(登記簿)は、X.Org Foundation の X ソフトウェア配布物の一部として刊行される。各登記事項には、その事項に責任を持つ人の住所、あるいは同事項について説明している文書の識別情報と同文書の請求先の住所とを記載しなければならない。

## 附録 A. 改訂履歴

この附録には本文書の改訂の履歴を記す。また、今版と以前の版との間にある非互換性についても述べる。

## X11R2 の草案

X バージョン 11、リリース 2 の一部として配布された1988年2月25日草案は、「草案(DRAFT)」とはっきり書いてあったし、変更されうる旨が多くの箇所に明記してあった。けれども、その後の改訂作業においては、我々は余計な非互換性が入り込まないよう非常に注意を払った。できる限り、X11R2 草案の規約を遵守するクライアントが依然として動作することを保証するべく努力した。

## 1988年7月27日付けの草案

X コンソーシアムは、1988年7月27日付けの草案に基いて検討を行った。この草案の何箇所かでは、X11R2 草案との間に非互換性が生ずるを避けられなかった。それを以下に挙げる。

- リクエスト `ConvertSelection` でプロパティ `None` を使うことができなくなった。このようなリクエストを受け取った所有者は、引数 target のアトムを応答用のプロパティと見做して使ってよい。大抵、これで上手く行く。

- セレクション要求への応答として INCREMENTAL 型のプロパティが使われる場合の手続き(protocol)が変わった。名前も INCR になった。セレクション要求者は、もし INCREMENTAL 型のプロパティが帰ってきたら、以前の手続き(protocol)に従って処理しても良い。

- セレクション要求への応答として INDIRECT 型のプロパティが使われる場合の手続き(protocol)が変わった。名前も MULTIPLE になった。セレクションの要求者は、もし INDIRECT 型のプロパティが帰ってきたら、以前の手続き(protocol)に従って処理しても良い。

- CLIPBOARD 管理専門のクライアントに関するプロトコルが変わった。以前のプロトコルは競合状態(race condition)が生じうるので使用しないこと。

- WM_HINTS.initial_state の取り得る値の数が減った(状態値の集合の要素が減った)。けれども、消えずに残った値には変更点は無い。ウィンドウ・マネージャは、削除された状態値は慎重に扱うべきである。

- アプリケーションが自身の最上位ウィンドウの状態を変える方法について変更があった。しかし、この変更は、これまで上手く動作していたものが今後も変わらず動作するような形で行われた。

- プロパティ WM_NORMAL_HINTS から x、y、width、height フィールドが削除され、pad フィールドに置き換えられた。削除されたフィールドに設定される値は無視される。ウィンドウの位置と大きさの設定は、適切なウィンドウ属性の設定を通じて行うものとする。

- 「base」で始まる二つのフィールドと win_gravity フィールドとをプロパティ WM_NORMAL_HINTS に追加した。クライアントが追加フィールドのない短いプロパティを設定した場合、ウィンドウ・マネージャはこれらの値を適当に仮定する。

## 公開検討用の草案

X コンソーシアムでの検討の結果、互換性のない変更がいくらか行われた。この変更は、1989年前半に公開検討用に配られた草案に記されている。

- プロパティ WM_HINTS の messages フィールドは扱いづらく、活用しづらいことが判った。同フィールドはプロパティ WM_PROTOCOLS と置き換えられたが、以前の仕組みを使っているクライアントはプロパティ WM_HINTS の flags フィールドに messages ビット(訳註：MessageHint、値は128)を設定していることから検知可能であり、ウィンドウ・マネージャは後方互換モードを提供することができる。

- 以前の草案には、クライアントが自身の下位ウィンドウ用カラーマップをインストールするための仕組みが規定されたいた。この仕組みは、信頼できる形で運用することができず、その上、特定の look & feel を要求するものであった。この仕組みの役割はプロパティ WM_COLORMAP_WINDOWS で置き換えられた。以前の仕組みを使っているクライアントは、同仕組みによって最上位ウィンドウに設定される WM_COLORMAPS プロパティで検知することができる。けれども、信頼できる後方互換モードを提供することは不可能である。

- ウィンドウ・マネージャが最上位ウィンドウの枠(borders)をどのように取り扱うべきかについて変更があった。以前の草案のやり方では Visibility イベントに関する問題が生ずるためである。ウィンドウ・マネージャ以外のクライアントには、非互換の変更は無い。

- 以前の草案で規定されていた擬似ルート機能が削除された。同機能は上手く実装できたのだが、想定される用途に応じるには不足があることが判った。想定される用途に完全に応じるには拡張機能が必要であり、そして、拡張機能の設計者に最大限の自由を与えるべきだと考えられた。全体として、以前の機構はクライアントからは見えないものであったので、非互換性は生じない。

- WM_DELETE_WINDOW プロトコルを追加した結果(これによって複数のウィンドウを持つクライアントが不意に終了してしまう事態を防止する)、WM_SAVE_YOURSELF プロトコルにいくらか変更があった。二つのプロトコルを直交させるためである(二つの手続きが被らないようにする)。以前のプロトコルを使っているクライアントは見分けることが可能であり(上述の WM_PROTOCOLS を見よ)、後方互換モードで対応することができる。

- Xlib - C Language X Interface の 14.3.1 節の RGB_COLOR_MAP 型のプロパティに関する規約が変更されたが、以前の規約を用いるクライアントは、同クライアントのプロパティが 4 バイト短いことから見分けることができる。このようなクライアントは、サーバが一つの Visual だけをサポートしている場合、もしくはクライアントがルートの Visual だけを使用している場合に限って正しく動作する。もともと、この二つの場合にしか上手く動作しなかったであろう。

## バージョン 1.0、1989年7月

公開検討の結果、主として規約の編輯上の変更が行われた。バージョン 1.0 の変更の中、以前の草案との間にある程度の非互換性を生じさせたものを以下に挙げる。

- ウィンドウ・マネージャによる占有について規定する節(占有)が追加された。この規定から生ずる制約がウィンドウ・マネージャ以外に影響を与えないようにすべきである。

- セレクションのターゲットの型の「TARGETS」の仕様が明確になった。場合によっては、クライアントに応答用の手続きを加える必要がある。

- セレクション所有者で INCR 転送を利用する者は、MULTIPLE プロパティの中のターゲット型を INCR アトムで置き換えないことになった。

- 自身をアイコン化しようとするクライアントによって送り出される `ClientMessage` イベントの内容が明確になった。以前の内容では実際には動作しなかったであろうから、非互換性は生じない。

- 代用の(synthetic、作り物の、本物でない) `ConfigureNotify` イベントの中の border-width に関する記述が追加された。しかし、これによって生じる非互換性は無い。

- クライアントは今後、すべての `ConfigureWindow` リクエストで border-width を設定する必要がある。

- アイコン・ウィンドウ上のウィンドウ・マネージャ・プロパティは無視することになった。しかし、以前には遵守すべき仕様が存在しなかったので、非互換性は生じない。

- 本物の `ConfigureNotify` イベントと代用の(synthetic) `ConfigureNotify` イベントの配信順序に関する記述が追加された。しかし、ウィンドウ・マネージャ以外の者には非互換性の影響は無い。

- WM_SAVE_YOURSELF の意味が明確になり、チェックポイント作業専用になった。終了(shutdown)手続きの一環として WM_SAVE_YOURSELF を用いるクライアントには修正が必要になることもある。とりわけ、終了作業中に利用者とやり取りするクライアントはそうである。

- プロパティ RGB_COLOR_MAP に kill_id フィールドが追加された。以前の規約を採用しているクライアントはプロパティ RGB_COLOR_MAP の大きさで見分けることができる。もともと上手く動作していた状況では、今後も上手く動作する。

## バージョン 1.1

バージョン 1.1 は1991年9月に X11R5 の一部として公開された。小さな編輯上の変更がある他、バージョン 1.0 からの内容上の(semantic)変更もいくつかあった。それを以下に挙げる。

- Device Color Characterization の節が追加された。

- 「NULL」というプロパティ型の意味が明確になった。

- コンパウンド・テキストについて、記述すべきことが記述された。

## 公開検討用の草案、1993年12月

バージョン 2.0 へ向けての公開検討用草案を作成する中で、下記の変更が生じた。

- [P01] クライアントが最上位ウィンドウの(スクリーン上の)絶対座標を追跡し続ける方法について、助言を書き加えた。

- [P03] 最上位ウィンドウを再利用しても危険が無いのは何時なのかについて、クライアントがこれを検知する方法が追加された。(訳註：何のことかわからない。要確認。)

- [P06] カラーマップを扱う節を書き直した。また、クライアントが自身のカラーマップをインストールできるように新しい機能が追加された。

- [P08] LENGTH というターゲット型は使わないことになった。

- [P11] マネージャ・セレクションという仕組みが追加された。

- [P17] プロパティ WM_NORMAL_HINTS のアスペクト比のフィールドの定義が変わった。計算に当たって「base」で始まるフィールドの値を考慮するようになった。

- [P19] プロパティ WM_HINTS の win_gravity フィールドの値として `StaticGravity` を指定できるようになった。`CenterGravity` という値の意味が明確になった。

- [P20] ウィンドウ・マネージャがどの版の ICCCM に対応しているのか、クライアントから問い合わせる手段ができた。

- [P22] MULTIPLE というセレクション・ターゲットの定義が明確になった。

- [P25]「最上位ウィンドウ」の定義を明記した。プロパティ WM_STATE が再定義され、同プロパティはクライアントからも見られるようになった。

- [P26] ウィンドウの状態群の定義が明確になった。また、ウィンドウの状態変更に関係する言葉遣いの統一が進んだ。

- [P27] ウィンドウ・マネージャが代用の `ConfigureNotify` イベントを送信するよう要求された時の規則が明確になった。

- [P28] ウィンドウがマップされたら直ちに同ウィンドウに入力フォーカスを設定したい場合の推奨手法の記述を加えた。

- [P29] ウィンドウ・マネージャ・プロパティで使われているリソースの ID の必要寿命についての規定ができた。

- [P30] キー・ストロークと override-redirect ウィンドウとの取り扱いについて、助言を加えた。

- [P31] セレクション機構を通じて転送されるリソースの所有者の振舞いについて、記述が追加された。

- [P32] CLIENT_WINDOW というターゲット型 の定義が明確になった。

- [P33] 特定の環境下でセレクション所有者にセレクションの再取得を要求する場合の規則が追加された。

- [P42] 新しいセレクション・ターゲットをいくつか追加した。

- [P44] 最上位ウィンドウの非表示化(withdrawal)にまつわる曖昧な表現(wording)を取り除いた。

- [P45] セレクションの要求者は、セレクション・リクエストの中で追加の情報(parameters)を渡せるようになった。(訳註：プロパティを使う。)

- [P49] discrimated names(辨別名)についての規約が追加された。

- [P57] C_STRING というプロパティ型が追加された。

- [P62] 複数のセレクション・リクエストを処理する際の順番についての要件が定められた。

- [P63] `VisibleHint` というフラグが追加された。

- [P64] セッション・マネジメントに関する節が更新され、新しいセッション・マネジメント・プロトコルに沿うようになった。古いセッション・マネジメント規約は附録 C に移された。

- 永久に完成しない「Window and Session Manager Conventions Manual」への言及が削除された。

- X Registry の情報が追加された。また、セッション・マネジメントの文書及び ICE の文書への言及が追加された。

- 編輯上・印刷上の改善がたくさん為された。

## バージョン 2.0、1994年4月

バージョン 2.0 の最終版(X11R6)の公開に向けた準備作業を通じて、下記の変更が為された。

- PIXMAP というセレクション・ターゲット型は、DRAWABLE 型ではなく PIXMAP 型のプロパティを返すように改められた。

- セッション・マネジメントの節に少し修正があった。これは、X Session Management Protocol の変更に対応するためである。

- ウィンドウ・マネージャが WM_TAKE_FOCUS メッセージの timestamp フィールドに `CurrentTime` を設定することは禁止された。

- プロパティ WM_HINTS の `VisibleHint` フラグは `UrgencyHint` に改名された。また、同フラグの意味がより詳しく定義された。

- 編輯上・印刷上の変更が為された。

## 附録 B. X11 プロトコル修正の提案

本規約の開発を進める中で、X11 プロトコルには不十分な点がたくさんあることが判った。今後のプロトコルの修正・設計作業に反映されるように、以下にそうした点を纏めておく。

- セレクションの最終変更時刻を知る術が無い(誰にも)。`GetSelectionOwner` リクエストは、「所有者」だけでなく「最終変更時刻」も返すように変更すべきである。

- どのセレクション・アトムが有効なのか、クライアントから調べる術が無い。

- `FocusIn` イベントに timestamp フィールドと previous-focus フィールドがあれば WM_TAKE_FOCUS は不要になる。これによって競合状態(race condition)の発生可能性を消すことができる。`FocusIn` イベントにはこの二つの情報を入れる空き領域があるので、次のプロトコル改訂時に追加すべきである。

- リクエスト `InstallColormap` で競合状態(race condition)が生じる。このリクエストは引数に timestamp を取らないので、最上位のカラーマップが解放された後に実行される可能性がある。次のプロトコル改訂では、`InstallColormap` リクエスト、`UninstallColormap` リクエスト、`ListInstalledColormaps` リクエスト、及び `ColormapNotify` イベントに timestamp (引数)を設けるべきである。この timestamp は、入力フォーカスにおける最終フォーカス変更時刻と同じように使用すべきである。カラーマップを読み込めるのがウィンドウ・マネージャに限られているのは、上記のパケット群にタイムスタンプが欠けているためである。

- 何らかの方法でカラーマップの Visual と Screen を特定できるように、X11 プロトコルを修正する必要がある。

- nonpreassigned modifiers(予約されていない修飾キー？)５個が不要になった時に、何らかの方法で割当てを解除できるようにすべきである。the manual(訳註：どの文書のことか、要確認)の方法は low-tech である。

## 附録 C - 古いセッション・マネージャの規約

この附録には、セッション管理の古い規約が書かれている。X のプロパティとメッセージとを用いたセッション管理である。この規約は今では無効となっている。ここに記載したのは専ら歴史的関心(を持つ人)のためである。セッション・マネジメントについて詳しく知りたければ、X セッション・マネジメント・プロトコル(X Session Management Protocol)を見てほしい。

## プロパティ

クライアントは、自身の最上位ウィンドウに２つのプロパティ(WM_COMMAND と WM_CLIENT_MACHINE)を用意し、このプロパティを使ってセッション・マネージャと通信する。クライアントが最上位ウィンドウの一団を抱えている場合、両プロパティは団長(group leader)たるウィンドウに設定するものとする。

最上位のクライアント・ウィンドウそれぞれにプロパティ WM_STATE を設定するのはウィンドウ・マネージャの仕事である。これは、最上位クライアント・ウィンドウを識別してその状態を把握できる必要のある者(セッション・マネージャや別のクライアント)が同プロパティを利用できるようにするためである。

### WM_COMMAND プロパティ

プロパティ WM_COMMAND には、クライアントを起動・再起動するためのコマンドを記す。クライアントは、このプロパティの更新を行って、同プロパティに常時適切なコマンドが記載されるようにするものとする。ここでいう適切なコマンドとは、クライアントをその時の状態のままに再開するようなコマンドのことである。プロパティの中身と型は、クライアントが動作している装置のオペレーティング・システムによって異なる。ISO Latin-1 形式の文字列で命令文を表す POSIX 準拠のシステムにおいて、プロパティは次のようなものとする。

- 型は STRING である

- null 文字終端の文字列の配列から成る

- argv によって初期化する

  他のシステムでは、プロパティ WM_COMMAND の型と中身について、別に適当な規約を定める必要があるであろう。ウィンドウ・マネージャとセッション・マネージャは、WM_COMMAND の型が STRING であると決めてかかるべきではないし、同プロパティの中身の解釈・表示が可能であると決めてかかるべきでもない。

WM_COMMAND の文字列は null 文字終端であり、「STRING のプロパティは null 文字で区切られる」とする一般の規約とは違っていることに注意する。この二律の並立が後方互換性のため必要である。

複数の最上位ウィンドウを持つクライアントは、長さの 0 でない WM_COMMAND が最上位ウィンドウ群中の唯だ一つだけに存在するようするべきである。その他の最上位ウィンドウにメッセージ WM_SAVE_YOURSELF が来た場合、長さ 0 の WM_COMMAND プロパティを用いて同メッセージに返答することができる。このような場合を除けば、長さ 0 の WM_COMMAND は無視される。

### WM_CLIENT_MACHINE プロパティ

このプロパティの説明は WM_CLIENT_MACHINE Property にある。

## 終了

クライアントは、信頼できないネットワーク接続を用いて通信しているので、サーバへの接続が突然警告無く切られることに備えていなければならない。クライアント側は、終了が迫っている旨の通知を受け取ることができると考えてはならないし、クライアントの生殺について、サーバを通じて利用者と交渉できるとも考えてはならない。例えば、クライアントは、自分の意思でダイアログ・ボックスを表示できることを前提にした動作をするべきでない。

同様に、クライアント側もセッション・マネージャに通知すること無く好きな時に終了してよい。セッション・マネージャによって終了させられたのではなく、クライアントが自ら終了する場合、同クライアントは属していたセッションから離脱したものと見做される。この場合、同セッションが復活しても離脱したクライアントは復活しない。

## セッション・マネージャの動作に対するクライアントの応答

セッション・マネージャの動作に対してクライアントが応答する必要がある場合がある。応答には２種類ある。

- クライアントの内部状態の保存

- ウィンドウの削除

### クライアントの状態の保存

クライアントの中には、セッション・マネージャ側がクライアント群の内部状態を保存しようと考えた時、警告をして貰いたいという者も存在する。そのようなクライアントは、プロトコル WM_SAVE_YOURSELF に参加するべく、自身の最上位ウィンドウ群のプロパティ WM_PROTOCOLS にアトム WM_SAVE_YOURSELF を書き加えるものとする。こうすることで、ClientMessage イベントのところで述べたような `ClientMessage` イベントがクライアントの元に届くようになる。この場合、`ClientMessage` イベントの data[0] 部分にアトム WM_SAVE_YOURSELF が入っている。

WM_SAVE_YOURSELF を受け取ったクライアントは、後になって再起動できるような状態へと移行し、その状態で再起動するためのコマンドを WM_COMMAND に書き込むものとする。クライアントが自身の状態を保存し終えたことを確認するため、セッション・マネージャは WM_COMMAND に関するイベント `PropertyNotify` を待ち受ける。したがって、WM_COMMAND の中身が既に正しく設定されていても、(追加データ長 0 で)同プロパティを更新するべきである。この処理の最中に利用者とやり取りすることは認められない。

セッション・マネージャは、一度この確認イベントを受信した後は、利用者の求め次第で何時でもクライアントを終了してよい。利用者の求めるものがセッションのスリープ状態への移行である場合、セッション・マネージャは、クライアントに一切のマウス・イベント、キーボード・イベントが届かないように取り計らう。

クライアントは、WM_SAVE_YOURSELF を受信し、自身の状態を保存し、WM_COMMAND を更新し終えたら、マウス・イベントかキーボード・イベントを受け取るまで状態を変更してはいけない。ここでいう状態の変更とは、WM_COMMAND の変更が必要になるような状態変更のことである。クライアント側では、一度マウス・イベントかキーボード・イベントが届けば、危機は既に去ったと考えて良い。セッション・マネージャは、危機が去るまで、あるいはクライアントの停止が完了するまで、これらのイベントがクライアントに届かないよう取り計らう。

複数の最上位ウィンドウを持つクライアントは、そのウィンドウの纏まり方・分かれ方に拘らず、次のように取り計らうものとする。

- 最上位ウィンドウの中、長さが 0 でない WM_COMMAND プロパティを持つ者は一つに限る。

- クライアントはメッセージ WM_SAVE_YOURSELF を受けて次のように応じる。

  - 先ず、必要であれば、長さが 0 でない WM_COMMAND プロパティを更新する。

  - 次に、メッセージ WM_SAVE_YOURSELF の届いたウィンドウに属する WM_COMMAND プロパティを更新する。但し、先の段で更新されなかった場合に限る。

あるウィンドウに WM_SAVE_YOURSELF が届いた、ということは、概念上、クライアントの状態全部を保存するよう命令が来たことを意味する。[11]

### ウィンドウの削除

ウィンドウは、プロトコル WM_DELETE_WINDOW を用いて削除する。ウィンドウの削除で説明している。

## セッション・マネージャのプロパティ型のまとめ

セッション・マネージャのプロパティを下表に挙げる。

名前 | 型 | 形式(Format) | 説明のある節
--- | --- | --- | ---
WM_CLIENT_MACHINE | TEXT |  | WM_CLIENT_MACHINE プロパティ
WM_COMMAND | TEXT |  | WM_COMMAND プロパティ
WM_STATE | WM_STATE | 32 | WM_STATE プロパティ

[11] この規約は、次節で述べるプロトコルを採用したため、以前の草案のものとは違っている。公開検討用の草案では、WM_SAVE_YOURSELF の役割がチェックポイント(状態をまるごと保存する動作)機能であるのか、それとも終了(shutdown)機能であるのかが曖昧であった。本規約では、明確にチェックポイント機能となった。終了を促す機能も必要であると判断された場合、別の WM_PROTOCOLS プロトコルを開発し、X 協会に登録することになる。

入り口に戻る