ウィンドウの配置

参照: ICCCM 4.1.5

= ConfigureRequest =
== 雑多なメモ ==
クライアントはConfigureWindowリクエストによってウィンドウの以下の属性を変更できる。
 * (x,y)座標(ルートウィンドウに対する)
 * サイズ(枠を含まない)
 * 枠の幅
 * スタック順序
WMが存在しなければこのリクエストは直ちにXサーバによって処理されるが、WM存在下ではWMにリダイレクトされてConfigureRequestイベントとして届く(Xサーバはリクエストを処理しない)。
 * このときWMは要求をどのように扱っても良い(WMがクライアントの要求通りにする保証はない)
 * WMはリクエストされた値をウィンドウの初期座標を決定するときと同様に扱う
  * ウィンドウのgravityを尊重する

ConfigureRequestが処理され、クライアントの座標やサイズが実際に変化するとクライアントにはConfigureNotifyが送信される。ConfigureRequestがWMにリダイレクトされた場合、WMがどうするかでConfigureNotifyが届くかどうかが変わる。
 * 完全に無視した場合: 届かない
 * 座標やスタック順序だけを変更した場合: reperenting WMでは届かない
  * reparentしていると、クライアントウィンドウの座標系はフレームウィンドウに対するものになる
  * ウィンドウの移動はフレームウィンドウの移動によって行われるので、クライアントウィンドウの座標は変化しない
  * スタック順序についても同じ
  * WMは、クライアントウィンドウの移動をクライアントに通知するために人工の(synthetic)ConfigureNotifyを作ってクライアントに送る
 * ウィンドウサイズ、あるいはウィンドウ枠の幅を変更した場合: 届く
  * リサイズの場合はフレームと共にクライアントウィンドウをリサイズする必要がある
  * WMによってクライアントウィンドウに変更されるので、ConfigureNotifyが届く
  * ウィンドウ枠についても同様だが、reparenting WMは通常クライアントウィンドウの枠を取り去ってから自分で枠をつけるのであまり関係ない
WMがConfigureNotifyを作って送るとき、ウィンドウの座標はルートウィンドウの座標系での値でなければならない(フレーム内でのクライアントウィンドウの座標をルートウィンドウ内での座標に変換する必要がある)。

以下、注意点
 * ConfigureRequestにおいて、変更を求めない値については現在の値がそのまま入っている
  * 座標の変更を要求してきているかどうかで座標系が変わる
   * 座標変更を要求している場合: ルートウィンドウの座標系
   * 要求していない場合: フレームウィンドウの座標系

== で、結局どうすれば良いのか ==
 1. ConfigureRequestを投げてきたウィンドウがWMの管理下にあるか調べる
  * 管理していないウィンドウなら、リクエストしてきたとおりにConfigureWindowしておしまい
  * これをやらないと、MapRequestしてくる前に自前でウィンドウを設定するクライアントが正常に動作しない
   * 例えばxtermは初め1x1+0+0でウィンドウを作り、適切な位置、サイズにConfigureしてからMapする
 1. リクエストに従ってウィンドウのパラメータを変更する
  * リクエストをどう扱うかはWMの自由(ICCCMには、WMがリクエストの通りにする保証はないと書かれている)
  * gravityに基づいて座標の調整を行う
   * 計算の際、ウィンドウ枠幅はクライアントがリクエストしてきた値を用いる
 1. ConfigureWindowリクエストを発行してウィンドウに変更を加える
  * reparentしている場合、フレームウィンドウに対して変更を加えることになる
  * reparentしていてかつリサイズを行った場合は、クライアントウィンドウもリサイズする
 1. まったく変更を行わなかった場合、またはリサイズを行わずに移動だけを行った場合は、ConfigureNotifyイベントをクライアントウィンドウに送る
  * クライアントウィンドウに座標(ルートウィンドウに対する)とサイズを通知するため
  * リサイズした場合はXサーバから真のConfigureNotifyが送られる