X11には、クライアント間通信の仕組みとして、セレクション機構が用意されている。
セレクション機構を使ってクライアント間でデータを転送する時、転送するデータが大き過ぎるなら、分割して転送する。これは Incremental 転送と呼ばれる。INCR という型のプロパティを用いる。
INCR プロパティを用いたセレクション・データの転送は、以下の手順で行う(図の後に説明がある)。
- (1)要求者→Xサーバ[XConvertSelection]
- セレクションを要求するクライアント(要求者)が関数 XConvertSelection を呼び出す。これによって、セレクション・データが欲しいことを X サーバに伝える。(要求者が XSelectInput を使って SelectionNotify イベントの配信を依頼する必要はない。)
- (2)Xサーバ→所有者[SelectionRequest]
- X サーバは、セレクション・データの要求があったことをセレクションの所有者に伝える為に SelectionRequest イベントを発行する。
- (3)所有者→Xサーバ[XChangeProperty]
- セレクションの所有者は、通常、関数 XChangeProperty を用いて、指定されたウィンドウの指定されたプロパティに指定された型でセレクション・データを格納する。しかし、セレクションの中身のデータ量が一度に転送できる分量より多い場合、先ずセレクション・データの大きさを伝えるために、関数 XChangeProperty を用いて、指定されたウィンドウの指定されたプロパティに INCR 型で(int整数で)セレクション・データの大きさを格納する。
- (4)所有者→Xサーバ[XSelectInput]
- 同時にセレクションの所有者は XSelectInput を用いて、X サーバに PropertyNotify イベントの配信を依頼する。
- (5)所有者→Xサーバ[XSendEvent]
- さらに、セレクションの所有者は、どこのウィンドウの何というプロパティに INCR 型のデータを格納したのかを XSelectionEvent 構造体に記述し、これを要求者へ届けるよう XSendEvent で X サーバに依頼する。
- (6)Xサーバ→要求者[SelectionNotify]
- X サーバは、XSendEvent を受けて、SelectionNotify イベントを要求者に転送する。
- (7)要求者→Xサーバ[XSelectInput]
- セレクションの要求者は、受け取った SelectionNotify イベントを見て、指定したプロパティに格納されているのが INCR 型の整数値であることを知る。そして、Incremental 転送(分割転送)を開始するべく、PropertyChangeMask を指定して XSelectInput を呼び出す。
- (8)要求者→Xサーバ[XDeleteProperty]
- セレクションの要求者は次いで、XDeleteProperty を呼び出し、INCR 型データの入ったプロパティを削除するよう X サーバに依頼する。
- (9)Xサーバ→所有者→Xサーバ[PropertyNotify、XChangeProperty]
- 「state」に PropertyDelete が入った PropertyNotify イベントを初めて受け取った所有者は、引数 mode に PropModeReplace を指定して関数 XChangeProperty を呼び出し、最初の SelectionRequest で指定されたウィンドウ、プロパティ、型に従ってセレクション・データの一部を書き込む。
- ---以下繰り返し---
- (10)Xサーバ→要求者→Xサーバ→要求者[PropertyNotify、XGetWindowProperty]
- 「state」に PropertyNewValue が入った PropertyNotify イベントを受け取った要求者は、引数 delete に True を指定して関数 XGetWindowProperty を呼び出し、新たに書き込まれたデータを読み込む。この時、取得したデータの長さが 0 であれば、前回の転送でセレクション・データを全て取得し終えたということなので、この繰り返しから抜ける。
- (11)Xサーバ→所有者→Xサーバ[PropertyNotify、XChangeProperty]
- 「state」に PropertyDelete が入った PropertyNotify イベントを受け取った所有者は、引数 mode に PropModeAppend を指定して関数 XChangeProperty を呼び出し、データの続きの一部を上と同じプロパティに書き込む。但し、前回の転送で全データの引き渡しが済んでいた場合、同プロパティには長さ 0 のデータ(NULL)を書き込む。
- ---繰り返しここまで---
- (12)要求者→Xサーバ[XDeleteProperty]
- 長さ 0 のデータを受け取った要求者は、関数 XDeleteProperty を呼び出し、使用したプロパティを削除する。
- (13)終わり。
xsel-1.2.0 では、所有者は全データの転送完了後に property 部が None の XSelectionEvent 構造体を使用して SelectionNotify を送信している。多分、送信しなくても良い。分割転送が途中で失敗した場合は、SelectionNotify で通知する。
★★★
INCR Property、Selection Mechanism、Incremental Transfer、セレクション・メカニズム、順次転送、分割転送
PR