原文はこちら。
翻訳にあたって、オープンソースグループ・ジャパンの MIT ライセンスの訳、aznote のSHAPE拡張に関する記事、及び一瀬亮の非矩形のウィンドウに関する記事を参考にした。
X Version 11, Release 7.7
Version 1.0
Copyright © 1989 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 OpenGroup.
(訳)
(以下に定める条件に従い、本ソフトウェアおよび関連文書のファイル(以下「ソフトウェア」)の複製を取得するすべての人に対し、ソフトウェアを無制限に扱うことを無償で許可する。これには、ソフトウェアの複製を使用、複写、変更、結合、掲載、頒布、サブライセンス、および/または販売する権利、およびソフトウェアを提供する相手に同じことを許可する権利も無制限に含まれる。)
(上記の著作権表示および本許諾表示を、ソフトウェアのすべての複製または重要な部分に記載するものとする。)
(ソフトウェアは「現状のまま」で、明示であるか暗黙であるかを問わず、何らの保証もなく提供される。ここでいう保証には、商品性、特定の目的への適合性、および権利非侵害についての保証も含まれるが、それに限定されるものではない。X CONSORTIUM は、契約行為、不法行為、またはそれ以外であろうと、ソフトウェアに起因または関連し、あるいはソフトウェアの使用またはその他の扱いによって生じる一切の請求、損害、その他の義務について何らの責任も負わないものとする。)
(X Consortium の名称は、この表示に記載されている場合を除き、X Consortium の事前の書面による承認を得ずに、宣伝であろうとその他の形であろうと、ソフトウェアの販売を促進するもの、またはソフトウェアの使用その他の扱いを奨励するものに使用してはならない。)
(X Window System は The Open Group の商標である。)
この拡張は、X11 プロトコルの枠内で任意の形状のウィンドウやボーダ(枠)を実現する機能を提供するものである。
X プロトコルにおける「矩形のウィンドウ」という決まりは、さまざまな様式のユーザ・インタフェイスを実装するにあたっての重大な制約である。例えば、多くの一時的な(transient)ウィンドウは、3次元の錯覚を作り出すために「drop shadow」を表示したいと考えるであろう。また別の例を挙げると、ユーザ・インタフェイスの様式(style guide)の中には、角の丸いボタンを必要とするものもある。特にイベントの配送やカーソルの形状が絡む場面で、四角くない形状を完全に実現することは、X プロトコル本体のみでは不可能である。最後の例は丸い時計と四角くないアイコンであり、これはデスクトップの視覚的添加物として欠かせないものである。
この拡張は次の機構を提供する。即ち、ウィンドウの視覚的な形状を任意の、場合によっては繋がっていない、非矩形の形に変更する機構を提供する。この拡張の狙いは既存の機能(semantics)を補うことであって、これを置き換えることではない。とりわけ、この拡張を認識しないクライアントであっても形状変更されたウィンドウに適切に対処できるのが望ましい。例えば、ウィンドウ・マネージャは、矩形の要素を単位としてスクリーン上の実際の配置を交渉できるべきである。この目的を達成するために、あるウィンドウに与えられた形状は、X プロトコルのウィンドウ・ジオメトリによって定まる矩形であって且つ同ウィンドウの境界を構成するものによって、(周囲を)切り取られる。クライアント・プログラムはウィンドウ・マネージャが用意した領域の範囲まで自身の形状を広げられる、という規約を定めるのが望ましい。
各ウィンドウは(形状が設定されてない時でも)次の2つの領域で構成される。bounding region (境界領域)と clip region (クリップ領域)である。あるウィンドウの境界領域は、親ウィンドウの領域の中、同ウィンドウ(ボーダも含む)が占める部分である。あるウィンドウのクリップ領域は、同ウィンドウの境界領域の部分(subset)であり、子ウィンドウのため、あるいはグラフィクス表示のために利用可能な領域である。境界領域とクリップ領域との間の領域がそのウィンドウのボーダ(枠)を構成する。
形状が設定されていないウィンドウの境界領域は、同ウィンドウの範囲全体に広がる矩形であり、この矩形には同ウィンドウのボーダも含まれる。同ウィンドウのクリップ領域は、内部の範囲(ボーダは含まない)を満たす矩形である。本文書においては、これらの領域を「デフォルト境界領域」(default bounding region)、「デフォルト・クリップ領域」(default clip region)と呼ぶ。ウィンドウの内部のサイズが width ✕ height であり、ボーダの幅が bwidth である場合、デフォルトの境界領域・クリップ領域は以下の矩形になる(座標はウィンドウの座標系の原点からのもの)。
bounding.x = -bwidth
bounding.y = -bwidth
bounding.width = width + 2 * bwidth
bounding.height = height + 2 * bwidth
clip.x = 0
clip.y = 0
clip.width = width
clip.height = height
この拡張においては、クライアントは、デフォルト領域と掛け合わせて使用する新たな領域を指定することで、境界領域とクリップ領域の両方あるいはどちらか一方を変更することができる。これによって生じる新たな領域を「クライアント境界領域」(client bounding region)、「クライアント・クリップ領域」(client clip region)と呼ぶ。これらは、ウィンドウの原点からの相対座標で設定され、常にオフセット(offset)の分だけウィンドウの原点から移動した状態で構成される(つまり、ウィンドウが移動しても領域の調整は必要ない)。領域を設定するための手段は3つある。1つは矩形のリスト(訳註:基本的には配列)、1つはビットマップ、もう1つはウィンドウの既存の境界領域やクリップ領域である。これは X プロトコルのグラフィクス・コンテクストの領域に関する規定を元にしたものであり、この手法のおかげでこの拡張がさまざまな用途に使えるようになる。
ウィンドウの既存の形状を演算対象(オペランド)として用いて新たな形状を設定する場合、クライアント領域を使用する。但し、未だクライアント領域が設定されてない場合は例外で、この場合には代わりにデフォルト領域を使用する。
ウィンドウの「有効境界領域」( effective bounding region)は、クライアント境界領域とデフォルト境界領域の共通部分(共通集合)によって構成する。クライアント境界領域の一部であってデフォルト境界領域に含まれない部分は全て、スクリーン上の有効境界領域には含まれない。これは次のことを意味する。即ち、矩形のクライアント・ウィンドウを扱ってきたウィンドウ・マネージャ(あるいは他のジオメトリ・マネージャ)は、今後もクライアントをスクリーンの矩形領域に押し込めることができることを意味する。(訳註:デフォルト境界領域は定義上、常に矩形であるため。)
有効境界領域の構築は動的に行われる。クライアント境界領域そのものが変化して有効境界領域になるわけではない。クライアント境界領域が現在のデフォルト境界領域の範囲をからはみ出すように設定されている場合、後ほどウィンドウが拡大されると、有効境界領域は拡大されてクライアント境界領域をより多く含むようになる。
ウィンドウの「有効クリップ領域」( effective clip region)は、クライアント・クリップ領域とデフォルト・クリップ領域とクライアント境界領域の3つの共通部分で構成される。クライアント・クリップ領域の一部であって、デフォルト・クリップ領域とクライアント境界領域の両方に含まれていない部分は全て、スクリーン上の有効クリップ領域には含まれない。
有効クリップ領域の構築は動的に行われる。クライアント・クリップ領域そのものが変化して有効クリップ領域になるわけではない。クライアント・クリップ領域が現在のデフォルト・クリップ領域の範囲からはみ出すように設定されている場合、後ほどウィンドウやその境界領域が拡大すると、有効クリップ領域は拡大されてクライアント・クリップ領域(有効境界領域に含まれる部分に限る)をより多く含むようになる。
ウィンドウのボーダ(枠)は、有効境界領域と有効クリップ領域の差で構成される。この領域が存在しなければ、ボーダは一切表示されない。この領域が存在する場合、ボーダは、X プロトコルの規定通りにウィンドウの border-tile もしくは border-pixel を用いて塗りつぶされる。ゼロではない幅のボーダを持つウィンドウであっても、ウィンドウのデフォルト・クリップ領域の範囲外に描画することはできないことに注意。また、ボーダの幅がゼロであってもウィンドウはボーダを持つことができることにも注意。この場合でもクリップ形状を境界形状より小さく作ることは可能であるため。
ウィンドウと、全ての下位ウィンドウの可視領域とへ向かう出力は全て、有効クリップ領域の範囲に(周囲を)切り取られる。X サーバは、ウィンドウの内容の中の有効境界領域からはみ出した部分を控えの記憶領域(backing store)に保持してはならない。ウィンドウの原点(の位置)(グラフィクスの操作、背景のタイル描画、及び下位ウィンドウの配置にあたっての原点)は、境界領域やクリップ領域の存在によっては変化しない。
デフォルト境界領域の内部であるが有効境界領域の外部である領域は、ウィンドウの一部にはならない。スクリーンのこうした領域は、他のウィンドウが埋めることになる。入力イベントが起きたのがウィンドウのデフォルト境界領域の内部であり且つ有効境界領域の外部であった場合、同イベントは、あたかもそのウィンドウがイベント発生の位置を覆っていなかったかのような仕方で配送される。ウィンドウの矩形でないボーダの中で発生したイベントは、通常の矩形のボーダの中で発生したイベントと同じように、同ウィンドウに配送される。
InputOnly のウィンドウには境界領域を設定することができる。けれども、 InputOnly のウィンドウにクリップ領域の設定を試みたり、この拡張のリクエストの「source」として同ウィンドウのクリップ領域を指定しようと試みたりすると、Match エラーとなる。
X サーバは、ルート・ウィンドウのクリップ領域に起きた変更を受け入れなければならないが、ルート・ウィンドウの境界領域の変更(requested changesリクエストされた変更)は無視することができる。X サーバが境界領域の変更を受け入れる場合、境界領域の外側のスクリーンの内容は実装依存である。
C の関数は、SHAPE 拡張のプロトコルを直接利用できるようにするものであり、追加の機能(semantics)は無い。
この拡張を利用するために取り込むべきファイル(include file)は <X11/extensions/shape.h> である。定義してある形状の種類(shape kind)は、ShapeBounding
と
ShapeClip
である。定義してある領域操作は、ShapeSet
、ShapeUnion
、ShapeIntersect
、ShapeSubtract
、及び ShapeInvert
である。
XShapeQueryExtension
は、指定されたディスプレイが SHAPE 拡張に対応していれば True
を返し、そうでなければ False
を返す。SHAPE 拡張に対応している場合、*event_base には ShapeNotify
のイベント番号が入り、*error_base には将来はこの拡張の最初のエラーのエラー番号が入るであろう。この版の SHAPE 拡張ではエラーは一切定義してないので、この関数で返ってくる値は未定義(あるいは役に立たないもの)である。
SHAPE 拡張に対応していれば、XShapeQueryVersion
は、指定されたディスプレイが対応している SHAPE 拡張の版番号の上位・下位の数字を(引数の場所に)格納し、0 でない値を返す。SHAPE 拡張に対応してない場合、引数には何も設定されず、0 が返る。
XShapeCombineRegion(
Display *display, Window dest, int dest_kind, int x_off, int y_off, int region, int op, REGION *region)
;
(訳註:X11/extensions/shape.h では、「REGION」型ではなく「Region」型で、引数「int region」は存在しない。「Region」の定義は X11/Xutil.h、X11/Xregion.h にあり、X11/Xregion.h では「REGION」型。REGION は BOX の配列を持つ。)
XShapeCombineRegion
は、指定された REGION を矩形の配列に変換し、XShapeCombineRectangles
を呼び出す。
XShapeCombineRectangles(
Display *display, Window dest, int dest_kind, int x_off, int y_off, XRectangle *rectangles, int n_rects, int op, int ordering)
;
SHAPE 拡張に対応していれば、XShapeCombineRectangles
はプロトコル操作 ShapeRectangles
を実行する。SHAPE 拡張に対応してない場合、このリクエストは無視される。
XShapeCombineMask(
Display *display, int dest, int dest_kind, int x_off, int y_off, Pixmap src, int op)
;
SHAPE 拡張に対応していれば、XShapeCombineMask
はプロトコル操作 ShapeMask
を実行する。SHAPE 拡張に対応してない場合、このリクエストは無視される。
XShapeCombineShape(
Display *display, Window dest, int dest_kind, int x_off, int y_off, Window src, int src_kind, int op)
;
SHAPE 拡張に対応していれば、XShapeCombineShape
はプロトコル操作 ShapeCombine
を実行する。SHAPE 拡張に対応してない場合、このリクエストは無視される。
SHAPE 拡張に対応していれば、XShapeOffsetShape
はプロトコル操作 ShapeOffset
を実行する。SHAPE 拡張に対応してない場合、このリクエストは無視される。
Status XShapeQueryExtents(
Display *display, Window window, Bool *bounding_shaped, int *x_bounding, int *y_bounding, unsigned int *w_bounding, unsigned int *h_bounding, Bool *clip_shaped, int *x_clip, int *y_clip, unsigned int *w_clip, unsigned int *h_clip)
;
SHAPE 拡張に対応していれば、XShapeQueryExtents
は、x_bounding、y_bounding、 w_bounding、h_bounding に境界形状の位置と大きさを返し、x_clip、y_clip、w_clip、h_clip にクリップ形状の位置と大きさを返す。未設定のクライアント領域については、同じ種類のデフォルト領域の位置と大きさが使用される。
SHAPE 拡張に対応していれば、0 ではない値が返る。そうでなければ 0 が返る。
SHAPE 拡張(のインタフェイス)を通じて選択できるイベントの型は1つしかないけれども、この拡張を他のインタフェイスと親和的なものにするために、XShapeSelectInput
として、ウィンドウ・イベントに対する標準の Xlib バインディングと同形式の(見た目だけ)汎用な機構を用意している。mask に入る値は既定であり、ShapeNotifyMask
である。この ShapeNotifyMask
が同マスクにおける唯一の有効なビットであり、これ以外は指定できない。ShapeNotify イベントの構造体の定義は次の通り。
typedef struct {
int type; /* イベントの型 */
unsigned long serial; /* # サーバが処理した最後のリクエストの通し番号 */
Bool send_event; /* SendEvent から送られて来た場合、True である */
Display *display; /* イベントが読み込まれる Display */
Window window; /* イベントのウィンドウ */
int kind; /* ShapeBounding もしくは ShapeClip */
int x, y; /* 新たな領域の位置と大きさ */
unsigned width, height;
Time time; /* 領域が変更された時点でのサーバのタイムスタンプ */
Bool shaped; /* 領域が存在すれば True */
} XShapeEvent;
XShapeInputSelected
は、指定されたウィンドウにおける、SHAPE 拡張イベントの現在の入力マスクを返す。ShapeNotify
が選択されている場合の戻り値は ShapeNotifyMask
であり、そうでない場合は 0 が返る。SHAPE 拡張に対応していない場合も 0 が返る。
XRectangle *XShapeGetRectangles(
Display *display, Window window, int kind, int *count, int *ordering)
;
SHAPE 拡張に対応していない場合、XShapeGetRectangles
は NULL を返す。そうでなければ、XShapeGetRectangles
は kind で指定された種類の領域を表す矩形の配列を返す。
親ウィンドウの領域の中、このウィンドウが占める部分。この領域は2つの部分に分かれる。枠(borderボーダ)と内部領域である。
ウィンドウの内部領域であり、境界領域(bounding region)の一部である。この領域は、ウィンドウ(の内容)が消された場合に「ウィンドウの背景」で描画される領域であり、同ウィンドウに対するグラフィクス出力の全てが入る領域であり、そして子ウィンドウ(の描画されない領域)を切り取る(clip)領域である。
X プロトコルでウィンドウ・サイズに関連して説明されている通りの矩形の領域であり、ウィンドウの内部とその枠(ボーダ)を含む。
X プロトコルでウィンドウ・サイズに関連して説明されている通りの矩形の領域であり、ウィンドウの内部を含み、枠(ボーダ)は含まない。
ウィンドウに結び付けられた領域であり、この拡張が直接変更を加える領域である(変更の際には ShapeBounding
を指定する)。この領域とデフォルト境界領域とを合わせて用いることで、有効境界領域が定まる。
ウィンドウに結び付けられた領域であり、この拡張が直接変更を加える領域である(変更の際には ShapeClip
を指定する)。この領域とデフォルト・クリップ領域とクライアント境界領域とを合わせて用いることで、有効クリップ領域が定まる
スクリーン上のウィンドウの実際の形状であり、枠と内部を含む領域(但し、重なっているウィンドウ群の影響は計算に入れない)。ウィンドウがクライアント境界領域を持っている場合、有効境界領域は、デフォルト境界領域とクライアント境界領域の共通部分(重なる領域)となる。ウィンドウがクライアント境界領域を持ってない場合、有効境界領域はデフォルト境界領域と等しくなる。
スクリーン上のウィンドウの内部の実際の形状である(但し、重なっているウィンドウ群の影響は計算に入れない)。ウィンドウがクライアント・クリップ領域もしくはクライアント境界領域を持っている場合、有効クリップ領域は、デフォルト・クリップ領域と(もし存在すれば)クライアント・クリップ領域と(もし存在すれば)クライアント境界領域との共通部分(3つが重なる領域)となる。ウィンドウがクライアント・クリップ領域もクライアント境界領域も持っていない場合、有効クリップ領域はデフォルト・クリップ領域と等しくなる。