LECTURE 15 ウィンドウの属性

○ はじめに

これまでの LECTURE において、XCreateSimpleWindow() を使ってウィンドウを作成する際に、ウィンドウのサイズや位置に関する情報以外にバックグラウンドカラーとボーダの色を指定しました。サイズや位置情報は LECTURE 8 で述べたようにジオメトリ情報と呼びますが、それ以外のウィンドウに関する情報を一般にウィンドウの属性と呼びます。それらを設定することで、ウィンドウの見た目や動作を変えることができます。

ここでは、ジオメトリ情報以外のウィンドウの属性について説明していきます。

○ ウィンドウの属性項目

ウィンドウの持つ属性( ジオメトリ以外 )は、XSetWindowAttributes 構造体( <X11/Xlib.h> )の各メンバが対応しています(全部で15個)。

typedef struct
{
  Pixmap        background_pixmap;     /* 背景のパターン */
  unsigned long background_pixel;      /* 背景の色 */
  Pixmap        border_pixmap;         /* ボーダのパターン */
  unsigned long border_pixel;          /* ボーダの色 */
  int           bit_gravity;           /* リサイズ時の描画内容の扱い */
  int           win_gravity;           /* リサイズ時の子ウィンドウの扱い */
  int           backing_store;         /* バッキングストア */
  unsigned long backing_planes;        /* バッキングプレーン */
  unsigned long backing_pixel;         /* バッキングピクセル */
  Bool          save_under;            /* セーブアンダ */
  long          event_mask;            /* イベントマスク */
  long          do_not_propagate_mask; /* 非伝播マスク */
  Bool          override_redirect;     /* リダイレクト無効 */
  Colormap      colormap;              /* カラーマップ */
  Cursor        cursor;                /* マウスカーソル */
} XSetWindowAttributes;

それぞれのメンバがどういうものであるかについて、

  1. 背景の色とパターン
  2. ボーダの色とパターン
  3. リサイズ時の描画内容と子ウィンドウの扱い
  4. バッキングストア/セーブアンダ/パッキング プレーンバッキングピクセル
  5. イベントマスク/非伝播マスク
  6. リダイレクト無効
  7. カラーマップ
  8. マウスカーソル

の順に説明していきます。なお、各項目の説明において設定関数についての記述が無いものについては

で説明する方法で設定/変更を行います。

● 背景の色とパターン

バックグラウンド(背景)に関する属性には、塗りつぶすための色と敷きつめるパターンの 2 つがあります。いずれかを設定しますが、双方とも設定された場合には色の設定が使用されます。

  • バックグラウンドカラー(background_pixel)

    ウィンドウのバックグラウンドを塗りつぶす色のピクセル値を指定します。設定した瞬間に色が 変わるのではなく、XClearWindow() などでウィンドウがクリアされた時にはじめて設定した色で塗 りつぶされます。デフォルトは未定義です。

    ウィンドウのバックグラウンドカラーを指定するには XSetWindowBackground() を使います。

      XSetWindowBackground( Display*      display, 
                            Window        w, 
                            unsigned long background_pixel 
                           );
      background_pixel : 設定したい色のピクセル値
    
    

  • バックグラウンドのパターン(background_pixmap)

    ウィンドウのバックグラウンドに敷きつめる(タイリングする)パターンに使うピクスマップ を指定します。ピクスマップIDでピクスマップを指定する他に、定数 None(透過バックグラウ ンド)と ParentRelative (親ウィンドウと同じパターンを使用)が指定できます。

    バックグラウンドカラー同様、設定した瞬間にタイリングされるのではありません。また、 指定するピクスマップの深さはそれを使用するウィンドウの深さと同じである必要があります。

    タイリングパターンを指定するには、XSetWindowBackgroundPixmap()を使います。

      XSetWindowBackgroundPixmap( Display* dpy, 
                                  Window   w, 
                                  Pixmap   background_pixmap 
                                );
      background_pixmap : ピクスマップのID
    
    

● ボーダの色とパターン

バックグラウンドと同じく色とタイリングパターンという 2 つの属性があり、いずれかを指定することができます。両方指定した場合には、色の属性が使用されます。

  • ボーダの色(border_pixel)

    ウィンドウのボーダを塗りつぶす色のピクセル値を指定します。デフォルトは未定義です。ウィ ンドウのボーダカラーを設定するには、XSetWindowBorder()を使います。

      XSetWindowBorder( Display* dpy, Window w, unsigned int border_pixel );
      border_pixel : 設定したい色のピクセル値
    
    

  • ボーダのパターン(border_pixmap)

    ウィンドウのボーダに使用するタイリングパターンをピクスマップで指定します。ピクスマッ プIDの他に、定数 CopyFromParent ( 親ウィンドウと同じパターン(デフォルト) )を指定できます。 指定するピクスマップの深さはそれを使用するウィンドウの深さと同じでなければなりません。

    タイリングパターンを指定するには XSetWindowBorderPixmap()を使います。

      XSetWindowBorderPixmap( Display* dpy, Window w, Pixmap border_pixmap );
      border_pixmap : ピクスマップ ID
    
    

● リサイズ時の描画内容と子ウィンドウの扱い

親ウィンドウのリサイズ時には、ウィンドウの描画内容(および子ウィンドウ)が指定した方向に引き寄せられます。これを設定する属性がグラビティ( gravity )です。

グラビティには子ウィンドウの位置を制御するためのウィンドウグラビティ( win_gravity )と、ウィンドウの描画内容の位置を制御するビットグラビティ( bit_gravity )があります。

以下の 9つは両グラビティで共通で、名前が表す方向にウィンドウの表示内容が引き寄せられます。

  • NorthWestGravity ( 左上 )
  • NorthGravity ( 上 )
  • NorthEastGravity ( 右上 )
  • WestGravity ( 左 )
  • CenterGravity ( 真中 )
  • EastGravity ( 右 )
  • SouthWestGravity ( 左下 )
  • SouthGravity ( 下 )
  • SouthEastGravity ( 右下 )

以下は各グラビティ個有の属性値です。

  • ビットグラビティ
    • StaticGravity ルートウィンドウに対して固定
    • ForgetGravity 描画内容を捨てて Expose イベントを発生する

  • ウィンドウグラビティ
    • UnmapGravity ウィンドウをアンマップする

ビットグラビティのデフォルトは ForgetGravity、ウィンドウグラビティのデフォルトは NorthWestGravity です。

● バッキングストア/セーブアンダ/バッキングプレーン/バッキングピクセル

バッキングストアとセーブアンダーは、X サーバにウィンドウの内容をセーブしておくように依頼して Expose されたときに X サーバに再描画してもらう機能です。バッキングプレーンとバッキングピクセルはバッキングストアとセーブアンダーの動作設定用属性と思ってもらえればいいです。

これらの機能は

  • X サーバにかかる負荷が重い
  • X サーバが勝手に処理を中止したりすることがある
  • そもそもサポートされていない場合がある

という性格があるので、使う場合は注意してください。

  1. バッキングストア(backing_store)

    指定ウィンドウが他のウィンドウに隠された場合、もしくはアンマップされたときにそのウィン ドウの描画内容を X サーバがセーブするかどうかを指定します。

    説明
    NotUseful セーブしない(デフォルト)
    WhenMappedマップ時にセーブする
    Always アンマップ時にも内容をセーブする

  2. セーブアンダー(save_under)

    指定ウィンドウのマップ時に、下に隠れることになるウィンドウの内容を X サーバがセーブする かどうかを指定します。指定ウィンドウのアンマップ時にセーブされた内容が再描画され、下のウ ィンドウに対する Expose イベントは発生しません。メニューウィンドウを表示するときなどに使 うと便利なようです。

    説明
    Falseセーブしない(デフォルト)
    True セーブする

  3. バッキングプレーン(backing_planes)

    バッキングストア/セーブアンダー時にセーブするプレーンをビットパターンで指定します。 1 が立っているプレーンのみをセーブします。デフォルトは全てのプレーンをセーブします。

  4. バッキングピクセル(backing_pixel)

    再描画時に、バッキングプレーンによってセーブしないと指定されたプレーンに描画する値を指 定します。デフォルトは 0 です。

● イベントマスク/非伝播マスク

  1. イベントマスク(event_mask)

    ウィンドウが受け取るイベントを指定します(既に XSelectInput() を使ってイベント指定を 行ってきました)。デフォルトでは 0 が指定されており、一部の無条件に送られて来るイベント (ノンマスカブルイベント)以外のイベントは X サーバから送られてきません。

  2. 非伝播マスク(do_not_propagate_mask)

    あるウィンドウであるイベントが発生した場合、そのウィンドウで該当するイベントを選択し ていなかった場合には通常その親ウィンドウをたどっていきます(イベントの伝播)。イベントは 受け取らないが、親ウィンドウへの伝播はさせたくないという場合には、非伝播マスク( do_not_propagate_mask )に対象となるイベントマスクを設定します。

    デフォルトでは非伝播マスクには 0 が指定されていて、そのウィンドウで選択されていない全 てのイベントが親ウィンドウに伝播されます。非伝播マスクは XChangeWindowAttributes() でし か設定/変更することができません。

● リダイレクト無効

ウィンドウマネージャを起動している場合、通常はウィンドウマネージャがクライアントと X サーバの間に入るため、要求を直接 X サーバに伝えることができません。これによってウィンドウマネージャ独自の制御が実現されていますが、自分がプログラム中に記述した通りに表示されなかったり、警告ダイアログをちょっと出したい時にいちいちウィンドウマネージャの機能によってマウスで表示位置を決めなければいけないということがあるため、都合が悪いと感じるときもあります。

リダイレクト無効属性は、ウィンドウマネージャをスルーしてしまうかどうかを決定します。次の 2 つが指定できます。

説明
Falseウィンドウマネージャが間に入る(デフォルト)
True スルーする

● カラーマップ

画面に同時に表示できる色数は、プレーンを何枚持っているかによって決定されます。例えば 3 プレーンしか無い場合、ピクセル値は 2 の 3 乗( 8 )個までしかないので、カラーマップ中には最大 8 色までしか登録できません。そのため同時に表示できる色は 8 色 までとなります。

X ウィンドウシステムではウィンドウごとに別々のカラーマップを割り当てることで、1 つのウィンドウでは同時に 8 色しか表示できないが別のウィンドウでは他の 8 色を表示できるという仕組みを実現しています。

独自のカラーマップを指定するための属性が colormap です。次の2つが指定可能です。

説明
CopyFromParent親と同じカラーマップを使用(デフォルト)
カラーマップID指定したカラーマップを使用

カラーマップ ID を指定する場合は、独自に生成したカラーマップを設定するのが普通です。カラーマップの扱いについては、今後の LECTURE で取り挙げたいと思います。

● マウスカーソル( cursor )

ウィンドウに表示するマウスカーソルを指定します。デフォルトでは親ウィンドウと同じマウスカーソルが使用されます。ウィンドウにカーソルを設定するには XDefineCursor() を使います。また、元に戻すには XUndefineCursor() を使います( LECTURE 9 で説明済 )。

XDefineCursor( display, w, cursor );
XUndefineCursor( display, w );

XDefineCursor() には表示したいマウスカーソルのリソース ID を指定します。X ウィンドウシステムでは、よく使うマウスカーソルがフォントとして用意されています(フォントカーソル)ので、これを使うと簡単にマウスカーソルの表示を変えることができます。フォントカーソルの使い方については、LECTURE 9 で説明しているので、参照してください。

○ ウィンドウの属性の設定

今までの LECTURE では、XCreateSimpleWindow() を使ってウィンドウを作成してきました。この関数ではバックグラウンドカラーとボーダの色以外の属性については、親ウィンドウの持つ属性と同じ値を持ったウィンドウが作られます。

これに対して、ウィンドウ生成時にすべてのウィンドウの属性を指定できるウィンドウ生成関数 XCreateWindow() があります。

Window XCreateWindow( Display*              display, 
                      Window                parent, 
                      int                   x, 
                      int                   y, 
                      unsigned int          width, 
                      unsigned int          height,
                      unsigned int          border_width, 
                      int                   depth, 
                      unsigned int          class, 
                      Visual*               visual, 
                      unsigned long         valuemask, 
                      XSetWindowAttributes* attributes 
                    );

parent     : 親ウィンドウ
x, y       : 親ウィンドウ内での座標 
width, height, border_width
           : 幅、高さ、ボーダの幅 
depth      : ウィンドウの深さ 
class      : クラス(入力専用、入出力用)
visual     : ビジュアル(CopyFromParent)
valuemask  : 指定する属性のマスク
attributes : 属性値 

ウィンドウに設定する属性は valuemask と attributes で指定します。valuemask には attributes のどのメンバに値を設定したかを、メンバに対応するマスクを論理和で設定します。valuemask に 0 を指定するとデフォルトの属性を持ったウィンドウが作られます。

ウィンドウのデフォルトの属性値と valuemask で指定するマスクの対応表を以下に示します。

メンバ デフォルト値 マスク
background_pixmap None CWBackPixmap
background_pixel 未定義 CWBackPixel
border_pixmap CopyFromParent CWBorderPixmap
border_pixel 未定義 CWBorderPixel
bit_gravity ForgetGravity CWBitGravity
win_gravity NorthWestGravityCWWinGravity
backing_store NotUseful CWBackingStore
backing_planes 全て1 CWBackingPlanes
backing_pixel 0 CWBackingPixel
save_under False CWSaveUnder
event_mask 0 CWEventMask
do_not_propagate_mask0 CWDontPropagate
override_redirect False CWOverrideRedirect
colormap CopyFromParent CWColormap
cursor None CWCursor

残りの引数であるウィンドウの深さ、クラス、ビジュアルの設定は下表に従います。

項目名説明
クラス InputOnly (入力専用)か InputOutput (入出力用)か CopyFromParent (親と同じクラス)を指定する。InputOnly の場合、 下の深さを 0 にしなくてはならない(親ウィンドウと同じ)。
ウィンドウの深さ InputOutput または CopyFromParent クラスのウィンドウに対して深さを 0 とすると親ウィンドウと同じ深さになる。
ビジュアル ピクセル値を画面上に表示する色にどのように変換するかを指定する (ビジュアルについてはLECTURE 2 を参照)。通常 CopyFromParent を指定する。

上の3つはウィンドウの特性と呼ばれ、ウィンドウ生成時にのみ設定できます(生成後の変更はできません)。

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

ウィンドウ生成後にウィンドウの属性値を変更するには、XSetWindowBackground() のような属性ごとに用意された設定用関数の他に、XChangeWindowAttributes() を使います。

XChangeWindowAttributes( Display*              display,
                         Window                w, 
                         unsigned long         valuemask, 
                         XSetWindowAttributes* attributes 
                       );

valuemask  : 指定する属性のマスク
attributes : 属性値

valuemask で指定した属性が attributes で指定した属性値に変更されます( XCreateWindow() の引数と同じ)。

○ ウィンドウの属性の取得

現在ウィンドウに設定されている属性を取得するには、XGetWindowAttributes() を使います。

Status XGetWindowAttributes( Display*           display, 
                             Window             w, 
                             XWindowAttributes* attributes 
                           );

attributes : 取得したウィンドウの属性情報が格納される

属性情報の取得に成功すると 0 以外の値を、失敗すると 0 を返します。成功した場合、XWindowAttributes 型構造体である attributes に指定したウィンドウに現在設定されている属性が格納されます。XWindowAttributes 型構造体は次のように定義されています。

typedef struct
{
  int           x, y;                  /* ウィンドウの位置 */
  int           width, height;         /* 幅、高さ */
  int           border_width;          /* ボーダの幅 */
  int           depth;                 /* ウィンドウの深さ */
  Visual*       visual;                /* ビジュアル構造体 */
  Window        root;                  /* スクリーンのルートウィンドウ */
  int           class;                 /* クラス(入力専用、入出力用) */
  int           bit_gravity;           /* リサイズ時の描画内容の扱い */
  int           win_gravity;           /* リサイズ時の子ウィンドウの扱い */
  int           backing_store;         /* バッキングストア */
  unsigned long backing_planes;        /* バッキングプレーン */
  unsigned long backing_pixels;        /* バッキングピクセル */
  Bool          save_under;            /* セーブアンダー */
  Colormap      colormap;              /* カラーマップ */
  Bool          map_installed;         /* 現在カラーマップはインストールされているか */
  int           map_state;             /* IsUnmapped、IsUnviewable、IsViewable */
  long          all_event_masks;       /* クライアント全てが見ているイベントマスク */
  long          your_event_mask;       /* 自分のイベントマスク */
  long          do_not_propagate_mask; /* 非伝播イベントの集合 */
  Bool          override_redirect;     /* リダイレクト無効属性 */
  Screen*       screen;                /* スクリーンへのポインタ */
} XWindowAttributes;

定義を見れば分かりますが、XGetWindowAttributes() を使うとジオメトリ情報も併せて取得することができます。