|
○ はじめに
突然ですが、これまでに表示してきたウィンドウは全て四角系でした。まあ困ることはそんなに無いかもしれませんが、例えば丸いボタンをウィンドウとして作れないのか?とか、あの丸い時計のアプリケーションはどうやってあの形のウィンドウを表示しているのか? などといったふとした疑問が湧いて来ることはありませんか?
X には拡張機能と呼ばれる機能があって、その中の一つである SHAPE Extension という機能を使うことで四角形以外のウィンドウを表示することが出来ます。
ここでは、SHAPE Extension を使用する際の前提事項をまず説明した後に SHAPE Extension の使い方を説明します。
○ bounding region と clip region
SHAPE extension から導入された考え方ですが、全ての Window は bounding region と clip region と呼ばれる領域から構成されます。
bounding region とは、ボーダを含んだ Window の形を表す領域を表します。clip region は bounding region の一部であり、グラフィックスを描画したり子ウィンドウを表示したりできる領域を表します。よって bounding region と clip region の間に挟まれる領域がボーダとなります。
通常の Window では bounding region および clip region 共に矩形であると考えれば、全ての形の Window について同様に考えることができます。なお、矩形の Window の bounding region および clip region をそれぞれデフォルトの bounding region、clip region と呼びます。
bounding region および clip region は自由に変更することができます。仮に、作成した Window よりも大きい領域を bounding region および clip region として設定した場合、Window からはみ出る部分は無視されます。しかし Window の表示領域は動的に計算されるため、Window の大きさをマウスのドラッグなどで大きくした場合には、より大きな region が表示される様になります。
○ サンプルプログラム
非矩形のウィンドウをボタンとして表示し、クリックする度にボタンの表示色を変化させるサンプルプログラム xshape.c です。また、使用している X11 ビットマップ btn_bd.h および btn_cl.h も併せてリンクしておきます。ブラウザ上はヘッダの内容ではなくビットマップイメージが表示されるかもしれません。その場合はソースを見るなどして下さい。はじめに のページから、全てのサンプルプログラムを固めた tar ボールをダウンロードすることもできます。
これまでのサンプルでは X のライブラリのリンク指定は -lX11 のみで良かったのですが、ここでは拡張機能を使用しているので、-lXext も同時に指定して下さい。
gcc -I/usr/X11R6/include -L/usr/X11R6/lib -o xshape xshape.c -lX11 -lXext
X11 ビットマップデータは bitmap コマンドで作ることができます。が、僕は面倒だったので、まず Xlib で円と長方形を使ってボタンの形を表示したウィンドウを作ってそれを画像ツールでダンプし、白黒 2 色の X11 ビットマップとして保存しました。
実行直後は、背景色が青のウィンドウ上に白色で非矩形のウィンドウ ( ボタン ) が表示されます。ボタンをマウスの左ボタンでクリックする度に、白=>赤、赤=>白と表示色が変化します。ウィンドウに関わらず、マウスの右ボタンをクリックすると終了します。
↑と↓が交互に切り替わります。
--- xshape.c ---
1 /* 2 * Shape Extension を使って矩形ではない Window を表示するサンプルコード 3 */ 4 5 #include <stdio.h> 6 #include <X11/Xlib.h> 7 #include <X11/Xutil.h> /* shape.h の前に必要 */ 8 #include <X11/extensions/shape.h> /* Shape Extension */ 9 10 11 /* 12 * bounding 領域および clip 領域を表す X11 形式のビットマップデータ 13 */ 14 #include "btn_bd.h" 15 #include "btn_cl.h" 16 17 18 #define WIN_X 100 19 #define WIN_Y 100 20 21 #define SPC_X 25 22 #define SPC_Y 25 23 24 #define WIN_W ( btn_bd_width + SPC_X * 2 ) 25 #define WIN_H ( btn_bd_height + SPC_Y * 2 ) 26 27 28 int 29 main( void ) 30 { 31 Display* dpy; 32 int screen; 33 34 Window base; 35 Window button; 36 GC gc; 37 38 Pixmap pixmap_bounding; /* bounding 領域を決定するビットマップ */ 39 Pixmap pixmap_clip; /* clip 領域を決定するビットマップ */ 40 int event_no_base; /* ShapeNotify イベントの番号 */ 41 int error_no_base; /* Shape Extension で発生するエラーの最初の番号 */ 42 43 unsigned long white, black, blue, red; 44 45 46 dpy = XOpenDisplay( NULL ); 47 screen = DefaultScreen( dpy ); 48 49 50 /* 51 * 接続した X サーバが、Shape Extension をサポートしているか 52 * どうかを調べる。 53 */ 54 if ( ! XShapeQueryExtension( dpy, &event_no_base, &error_no_base ) ) { 55 fprintf( stderr, "Shape extension is not available\n" ); 56 XCloseDisplay( dpy ); 57 return 1; 58 } 59 60 61 /* 62 * 色設定 63 */ 64 { 65 XColor color, exact; 66 Colormap cmap; 67 68 white = WhitePixel( dpy, screen ); 69 black = BlackPixel( dpy, screen ); 70 71 cmap = DefaultColormap( dpy, screen ); 72 73 XAllocNamedColor( dpy, cmap, "blue", &color, &exact ); 74 blue = color.pixel; 75 76 XAllocNamedColor( dpy, cmap, "red", &color, &exact ); 77 red = color.pixel; 78 } 79 80 81 /* 82 * Window 作成 83 */ 84 { 85 /* 86 * base Window を作成する。 87 */ 88 base = XCreateSimpleWindow( dpy, DefaultRootWindow( dpy ), 89 WIN_X, WIN_Y, 90 WIN_W, WIN_H, 91 0, black, blue ); 92 XStoreName( dpy, base, "Button" ); 93 94 95 /* 96 * bounding ビットマップの幅と高さを使って button Window を作成する。 97 */ 98 button = XCreateSimpleWindow( dpy, base, 99 SPC_X, SPC_Y, 100 btn_bd_width, btn_bd_height, 101 0, black, white ); 102 103 gc = XCreateGC( dpy, button, 0, NULL ); 104 XSetBackground( dpy, gc, white ); 105 } 106 107 108 /* 109 * bounding 領域および clip 領域の設定 110 */ 111 { 112 /* 113 * bounding 領域および clip 領域を表現するビットマップを作成する。 114 */ 115 pixmap_bounding = XCreateBitmapFromData( 116 dpy, button, 117 ( char* )btn_bd_bits, 118 btn_bd_width, btn_bd_height ); 119 120 pixmap_clip = XCreateBitmapFromData( 121 dpy, button, 122 ( char* )btn_cl_bits, 123 btn_cl_width, btn_cl_height ); 124 125 /* 126 * bounding 領域および clip 領域を設定する。 127 */ 128 XShapeCombineMask( dpy, button, ShapeBounding, 129 0, 0, pixmap_bounding, ShapeSet ); 130 131 XShapeCombineMask( dpy, button, ShapeClip, 132 0, 0, pixmap_clip, ShapeSet ); 133 } 134 135 136 XSelectInput( dpy, base, ButtonPressMask ); 137 XSelectInput( dpy, button, ButtonPressMask ); 138 139 XMapWindow( dpy, base ); 140 XMapSubwindows( dpy, base ); 141 142 143 /* 144 * 真中の Window 内でマウスの左ボタンをクリックする度に、 145 * 表示色を 赤<==>白 で切替える。 146 * Window に関係無く、右ボタンをクリックすると終了する。 147 */ 148 while ( 1 ) { 149 static XEvent event; 150 static char flag = 0; 151 152 XNextEvent( dpy, &event ); 153 154 switch ( event.type ) { 155 case ButtonPress: 156 switch ( event.xbutton.button ) { 157 case Button1: /* Left Button */ 158 if ( event.xbutton.window == button ) { 159 if ( ! flag ) { 160 XSetForeground( dpy, gc, red ); 161 flag ++; 162 } 163 else { 164 XSetForeground( dpy, gc, white ); 165 flag --; 166 } 167 168 XFillRectangle( dpy, button, gc, 169 0, 0, btn_bd_width, btn_bd_height ); 170 } 171 break; 172 173 case Button3: /* Right Button */ 174 XFreeGC( dpy, gc ); 175 XDestroyWindow( dpy, base ); 176 XCloseDisplay( dpy ); 177 return 0; 178 } 179 180 default: 181 break; 182 } 183 } 184 } 185 186 187 /* End of xshape.c */
--- btn_bd.h ---
1 #define btn_bd_width 101 2 #define btn_bd_height 51 3 static unsigned char btn_bd_bits[] = { 4 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 5 0xe0, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 6 0x00, 0xe0, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 7 0x7f, 0x00, 0xe0, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 8 0xff, 0xff, 0x01, 0xe0, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 9 0xff, 0xff, 0xff, 0x07, 0xe0, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 10 0xff, 0xff, 0xff, 0xff, 0x0f, 0xe0, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 11 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x80, 0xff, 0xff, 0xff, 0xff, 12 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0xc0, 0xff, 0xff, 0xff, 13 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xe0, 0xff, 0xff, 14 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xf0, 0xff, 15 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xf0, 16 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 17 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 18 0xe3, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 19 0xff, 0xe3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 20 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 21 0xff, 0xff, 0xff, 0xe7, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 22 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 23 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 24 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 25 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 26 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 27 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 28 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 29 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 30 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 31 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 32 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 33 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 34 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 35 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 36 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 37 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 38 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 39 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 40 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 41 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xfc, 42 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 43 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 44 0xe7, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 45 0xff, 0xe3, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 46 0xff, 0xff, 0xe3, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 47 0xff, 0xff, 0xff, 0xe1, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 48 0xff, 0xff, 0xff, 0xff, 0xe1, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 49 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 50 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0x80, 0xff, 0xff, 0xff, 0xff, 51 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x80, 0xff, 0xff, 0xff, 52 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x00, 0xfe, 0xff, 53 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xe0, 0x00, 0xfc, 54 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xe0, 0x00, 55 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xe0, 56 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 57 0xe0, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 58 0x00, 0xe0, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 59 0x07, 0x00, 0xe0};
--- btn_cl.h ---
1 #define btn_cl_width 101 2 #define btn_cl_height 51 3 static unsigned char btn_cl_bits[] = { 4 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 5 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 6 0x00, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 7 0x1f, 0x00, 0xe0, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 8 0xff, 0x3f, 0x00, 0xe0, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 9 0xff, 0xff, 0x7f, 0x00, 0xe0, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 10 0xff, 0xff, 0xff, 0xff, 0x01, 0xe0, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 11 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xe0, 0x00, 0xfe, 0xff, 0xff, 0xff, 12 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xe0, 0x80, 0xff, 0xff, 0xff, 13 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x80, 0xff, 0xff, 14 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0xc0, 0xff, 15 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xe0, 16 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 17 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 18 0xe1, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 19 0xff, 0xe1, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 20 0xff, 0xff, 0xe3, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 21 0xff, 0xff, 0xff, 0xe3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 22 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 23 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 24 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 0xff, 0xff, 25 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 0xff, 26 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 27 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 28 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 29 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 30 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 31 0xe7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 32 0xff, 0xe7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 33 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 34 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 35 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 36 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 37 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 0xff, 0xff, 38 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 0xff, 39 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 40 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 41 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf8, 42 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 43 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 44 0xe3, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 45 0xff, 0xe1, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 46 0xff, 0xff, 0xe1, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 47 0xff, 0xff, 0xff, 0xe0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 48 0xff, 0xff, 0xff, 0x7f, 0xe0, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 49 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 50 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x00, 0xfe, 0xff, 0xff, 0xff, 51 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xe0, 0x00, 0xfc, 0xff, 0xff, 52 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xe0, 0x00, 0xf0, 0xff, 53 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xe0, 0x00, 0xc0, 54 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xe0, 0x00, 55 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xe0, 56 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 57 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 58 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 59 0x00, 0x00, 0xe0};
○ サンプルプログラムの説明
では、サンプルプログラムについて説明していきます。
- 8 行目
SHAPE extension を使用するために必要な <X11/extensions/shape.h> をインクルードしています。
- 14 〜 15 行目
bounding 領域および clip 領域を表す X11 形式のビットマップデータをインクルード しています。X11 形式のビットマップデータは C 言語のヘッダファイルの形式であるため、 この様にして使用します。
- 24 〜 25 行目
ビットマップデータの中で定義されているビットマップの幅と高さを使って、 ボタンを表示するウィンドウの幅を決めています。
- 38 〜 41 行目
SHAPE extension を使う際に必要となる bounding region および clip region を格納するための Pixmap と、その他の変数を定義しています。event_no_base と error_no_base については後程説明します。
- 50 〜 58 行目
X サーバに接続した直後に、まず SHAPE extension をサポートしているかどうかを XShapeQueryExtension() を使って問い合わせています。サポートしていない場合は、 プログラムを終了しています。
Bool XShapeQueryExtension( Display* display, int* event_basep, int* error_basep ); event_basep : ShapeNotify イベントを表す番号が格納される error_basep : SHAPE extension で発生するエラー番号の最初の番号が格納される
SHAPE extension がサポートされている場合は True、サポートされていない場合は False を返します。サポートされている場合は event_basep に ShapeNotify イベントを表す番号が格納されます。また、error_basep に、SHAPE extension で発生するエラー番号の最初の番号が格納されます。
ShapeNotify イベントについては後述します。
- 61 〜 78 行目
ベースとなるウィンドウとボタンウィンドウの表示色となる、青、赤、白、黒 のピクセル値を取得しています。
- 81 〜 105 行目
ベースウィンドウとボタンウィンドウを作成しています。ボタンウィンドウは、 ビットマップデータに定義されている幅と高さを使って作成しています。 また、ボタンウィンドウの表示色を変える際に使用する GC を作成して、 最初の表示色を設定しています。
ベースウィンドウの作成で使用している XStoreName() は、ウィンドウマネージャに対して タイトルバーに表示する文字列を通知する関数です。ここまでに説明した記憶が無いので ここであらためて。
XStoreName( Display* display, Window win, char* name ); name : タイトルバーに表示する文字列
- 108 〜 133 行目
ここが本題です。作成したばかりのウィンドウの bounding region と clip region はデフォルト状態ですが、これを変更します。 まず、ビットマップデータを使って region の指定に使用する Pixmap を XCreateBitmapFromData() を使って作成します。XCreateBitmapFromData() については、 Appendix ( 付録 ) で説明していますので、 そちらを参照して下さい。
作成した Pixmap を、XShapeCombineMask() を使って bounding region および clip region として設定します。
XShapeCombineMask( Display* display, Window dst, int dst_kind, x_off, y_off, Pixmap src, int op ); dst : region を設定する対象となる Window dst_kind : bounding region を設定する場合は ShapeBounding clip region を設定する場合は ShapeClip を指定 x_off, y_off : src をその幅と高さで表される四角形と考えた場合に、左上の角を dst 上のどの位置において設定するかを指定 src : region の設定に使用する Pixmap デフォルトに戻す場合は None を指定する op : src と dst による region 決定の演算方法を指定
op には ShapeSet、ShapeUnion、ShapeIntersect、ShapeSubtract、ShapeInvert が設定できます。
- ShapeSet
src を dst_kind で指定した region として設定する
- ShapeUnion
dst および src を合わせた領域を、dst_kind で指定した region として設定する
- ShapeIntersect
dst および src の重なる領域を、dst_kind で指定した region として設定する
- ShapeSubtract
dst から src を除いた領域を、dst_kind で指定した region として設定する
- ShapeInvert
src から dst を除いた領域を、dst_kind で指定した region として設定する
ちなみに xshape.c で ShapeSet の代わりに ShapeUnion および ShapeSubtract を指定した場合の表示は以下の様になります。 ShapeIntersect と ShapeInvert は各自で何か作って表示してみて下さい ! ( 自分でやるのが面倒だっただけです。。。m(__)m )
--- ShapeUnion ---
--- ShapeSubtract ---
↑白い箇所がボタンウィンドウなので、ShapeSubtract の場合面白いことになってます。 4 つのウィンドウがあるかの様ですね!
- ShapeSet
- 143 〜 183 行目
イベントループです。マウスの左ボタンをクリックした場合、ボタンウィンドウであれば ( 158 行目 ) flag の値によって表示色を GC に設定して、168 行目の XFillRectangle() でボタンウィンドウを塗りつぶしています。XFillRectangle() で長方形領域を塗りつぶしても、 表示される領域はこれまでと変わりません。
マウスの右ボタンをクリックした場合は、リソースを解放して終了します。
以上で xshape.c の解説は終わりです。 これを機に、すごく変わった形のアプリケーションでも作ってみてはいかがでしょう?
○ SHAPE extension で使用できるその他の関数
ここでは SHAPE extension で使用できるその他の関数のうちのいくつかについて説明します。
- XShapeQueryVersion()
SHAPE extension のバージョンを取得します。 実行すると、major および minor に指定した変数に番号が格納されます。
Status XShapeQueryVersion( Display* display, int* major, int* minor ); major : メジャー番号 minor : マイナー番号
- XShapeCombineRectangles()
XRectangle の配列を使って、region の設定を行います。
XShapeCombineRectangles( Display* display, Window dst, int dst_kind, x_off, y_off, XRectangles* rectangles, int n_rects, op, ordering ); dst : region を設定する対象となる Window dst_kind : bounding region を設定する場合は ShapeBounding clip region を設定する場合は ShapeClip を指定 x_off, y_off : rectangles による region の設定を、 dst 上のどの位置において設定するかを指定 rectangles : region の設定に使用する領域を XRectangle の配列で指定する n_rects : rectangles に指定した XRectangle の数 op : src と dst による region 決定の演算方法を指定(XShapeCombineMask()と同じ) ordering : rectangles に指定した XRectangle の並び方を指定
ordering には Expose イベント で説明した XSetClipRectangles() の ordering に使用できる定数を使います。
- XShapeCombineShape()
Pixmap ではなく、Window を使って region の設定を行います。
XShapeCombineShape( Display* display, Window dst, int dst_kind, x_off, y_off, Window src, int src_kind, op ); dst : region を設定する対象となる Window dst_kind : bounding region を設定する場合は ShapeBounding clip region を設定する場合は ShapeClip を指定 x_off, y_off : src をその幅と高さで表される四角形と考えた場合に、左上の角を dst 上のどの位置において設定するかを指定 src : region の設定に使用する Window src_kind : bounding region を使用する場合は ShapeBounding clip region を使用する場合は ShapeClip を指定 op : src と dst による region 決定の演算方法を指定(XShapeCombineMask と同じ)
- XShapeOffsetShape()
現在設定されている region を指定量だけ移動させます。
XShapeOffsetShape( Display* display, Window dst, int dst_kind, int x_off, int y_off ); dst_kind : bounding region を設定する場合は ShapeBounding clip region を設定する場合は ShapeClip を指定 x_off, y_off : region の移動量を X および Y 座標それぞれについて指定
- XShapeQueryExtents()
現在設定されている bounding region および clip region についての情報を取得します。
Status XShapeQueryExtents( Display* display, Window win, Bool *bounding, int *x_bounding, *y_bounding, *w_bounding, *h_bounding, Bool *clip, int *x_clip, *y_clip, *w_clip, *h_clip ); bounding : bounding region が設定されている場合に True が格納される x_bounding, y_bounding : bounding region の左上角の座標が格納される w_bounding, h_bounding : bounding region の幅と高さが格納される clip : clip region が設定されている場合に True が格納される x_clip, y_clip : clip region の左上角の座標が格納される w_clip, h_clip : clip region の幅と高さが格納される
- XShapeSelectInput()
bounding region もしくは clip region に変化があった場合に、ShapeNotify イベントを送ってもらう様に X サーバに通知します。
XShapeSelectInput( Display* display, Window win, unsigned long mask ); mask : ShapeNotifyMask を指定
ShapeNotify イベント構造体は以下の様に定義されています。
typedef struct { int type; /* イベントの種類 */ unsigned long serial; /* サーバが処理した最後のリクエスト番号 */ Bool send_event; /* クライアントから送られたイベントなら True */ Display* display; /* イベントが読み込まれたdisplay */ Window window; /* イベントが起こった window のID */ int kind; /* ShapeBounding もしくは ShapeClip */ int x, y; /* 新しい region の左上角の座標 */ unsigned width, height; /* 新しい region の幅と高さ */ Time time; /* region が変更された時刻 */ Bool shaped; /* region が存在する場合は True */ } XShapeEvent;
- XShapeInputSelected()
ShapeNotify イベントを送ってもらう様に XShapeSelectInput() で指定した場合に ShapeNotifyMask を、そうでない場合には 0 を返します。
unsigned long XShapeInputSelected( Display* display, Window win );
- XShapeGetRectangles()
現在の bounding region あるいは clip region を表現する XRectangle の配列を取得します。 XShapeCombineRectangles() の逆操作の様なものです。
XRectangle* XShapeGetRectangles( Display* display, Window win, int kind, int* count, int* ordering ); kind : bounding region を指定する場合は ShapeBounding clip region を指定する場合は ShapeClip を指定 count : 返却値に設定されている XRectangle の数 ordering : 返却値に設定されている XRectangle の並び方 XSetClipRectangles() の ordering に使用できる定数