WM_HINTS
ウィンドウの WM_HINTS プロパティに、type = "WM_HINTS", format = 32 で各値を設定すると、ウィンドウの動作などに関する情報を、ウィンドウマネージャに伝えることができます。
プロパティが設定されていない場合は、ウィンドウマネージャによって、デフォルトの値が使用されます。
基本的に、ウィンドウを最初にマップする前に設定します。
プロパティが設定されていない場合は、ウィンドウマネージャによって、デフォルトの値が使用されます。
基本的に、ウィンドウを最初にマップする前に設定します。
関数と構造体
Xlib には、このプロパティを設定するための構造体と関数があるので、通常はそちらを使います (X11/Xutil.h)。
XWMHints 構造体のメンバは、将来的に増える可能性があるということで、XAllocWMHints() で確保してから使用することになっていますが、今後メンバが増えるようなことは、おそらくないと思います。
確保した構造体は、ゼロクリアされています。使用後は XFree() で解放します。
XSetWMHints() で、WM_HINTS プロパティに XWMHints 構造体の値をセットします。
プロパティのデータは、format = 32 の値の配列になります。
XGetWMHints() で、WM_HINTS プロパティから値を取得します。
typedef struct { long flags; Bool input; int initial_state; Pixmap icon_pixmap; Window icon_window; int icon_x, icon_y; Pixmap icon_mask; XID window_group; } XWMHints; //flags #define InputHint (1L << 0) #define StateHint (1L << 1) #define IconPixmapHint (1L << 2) #define IconWindowHint (1L << 3) #define IconPositionHint (1L << 4) #define IconMaskHint (1L << 5) #define WindowGroupHint (1L << 6) #define AllHints (InputHint|StateHint|IconPixmapHint\ |IconWindowHint|IconPositionHint|IconMaskHint|WindowGroupHint) #define XUrgencyHint (1L << 8) //initial_state #define WithdrawnState 0 //完全非表示 #define NormalState 1 //通常表示 #define IconicState 3 //アイコン化
XWMHints *XAllocWMHints(void); int XSetWMHints(Display *display, Window w, XWMHints *wm_hints); XWMHints *XGetWMHints(Display *display, Window w);
XWMHints 構造体のメンバは、将来的に増える可能性があるということで、XAllocWMHints() で確保してから使用することになっていますが、今後メンバが増えるようなことは、おそらくないと思います。
確保した構造体は、ゼロクリアされています。使用後は XFree() で解放します。
XSetWMHints() で、WM_HINTS プロパティに XWMHints 構造体の値をセットします。
プロパティのデータは、format = 32 の値の配列になります。
XGetWMHints() で、WM_HINTS プロパティから値を取得します。
XWMHints 構造体
flags | 使用するメンバのマスクとフラグ。 XUrgencyHint が ON の場合、ウィンドウに注意を引きつけるために、ウィンドウマネージャがウィンドウに対して何らかのアクションをします (フレームを点滅させるなど)。 |
---|---|
input | ウィンドウマネージャの制御によって、入力フォーカスが設定されるか。 True の場合、ウィンドウマネージャが XSetInputFocus() を行うことで、適切なウィンドウに入力フォーカスがセットされます。 False の場合、クライアントが明示的に XSetInputFocus() を使用しない限り、入力フォーカスがセットされることはありません。 |
initial_state | Withdrawn 状態からマップされる時のウィンドウ状態。 |
icon_* | アイコン化状態に関する値。 |
window_group | グループリーダーのウィンドウ。詳細は後述します。 |
プログラム (1)
最初のマップ時は、アイコン化状態で表示し、ウィンドウは入力フォーカスを全く受け取りません。
ポインタボタンを押すと終了します。
<d04a-wmhints.c>
ポインタボタンを押すと終了します。
$ cc -o run d04a-wmhints.c util.c -lX11
<d04a-wmhints.c>
#include <X11/Xlib.h> #include <X11/Xutil.h> #include "util.h" int main(int argc,char **argv) { Display *disp; Window win; XWMHints *wmh; disp = XOpenDisplay(NULL); if(!disp) return 1; win = create_test_window(disp, ButtonPressMask); //WM_HINTS wmh = XAllocWMHints(); wmh->flags = InputHint | StateHint; wmh->input = False; wmh->initial_state = IconicState; XSetWMHints(disp, win, wmh); XFree(wmh); //イベント XMapWindow(disp, win); eventloop_button_quit(disp); XCloseDisplay(disp); return 0; }
WM_NORMAL_HINTS
WM_NORMAL_HINTS プロパティに、type = "WM_SIZE_HINTS", format = 32 で各値を設定することで、通常状態で表示されている時のウィンドウの、位置やサイズに関する情報を指定します。
WM_HINTS の場合と同様に、XSizeHints 構造体を確保して、XSetWMNormalHints() でプロパティをセットします。
PPosition, PSize がある場合、ウィンドウの位置またはサイズは、プログラムによって指定されたことを示します。
このフラグが設定されていると、ウィンドウマネージャは、Withdrawn 状態からマップされた時に、ウィンドウの現在の位置やサイズをそのまま使用して表示します (ウィンドウマネージャの実装にもよる)。
例えば、前回のウィンドウ位置とサイズを復元したい場合などは、このフラグを設定すると、最初のマップ時に表示される位置やサイズを固定できます。
アスペクト比の指定がない場合、以下のように計算されます。
さらに、min と max のサイズで値が制限されます。
base の値がない場合は、min のサイズが使用されます。
min の値がない場合は、base のサイズが使用されます。
アスペクト比の指定がある場合は、ウィンドウサイズがその比率の範囲になるように調整されます。
その場合、base の値がある場合は、そのサイズを引いてからアスペクト比の計算を行います。
min_aspect と max_aspect で同じ値を指定すると、アスペクト比を固定できます。
関数
XSizeHints *XAllocSizeHints(void); void XSetWMNormalHints(Display *display, Window w, XSizeHints *hints); Status XGetWMNormalHints(Display *display, Window w, XSizeHints *hints_return, long *supplied_return);
WM_HINTS の場合と同様に、XSizeHints 構造体を確保して、XSetWMNormalHints() でプロパティをセットします。
XSizeHints 構造体
typedef struct { long flags; int x, y; int width, height; int min_width, min_height; int max_width, max_height; int width_inc, height_inc; struct { int x; //分子 int y; //分母 } min_aspect, max_aspect; int base_width, base_height; int win_gravity; } XSizeHints; //flags #define USPosition (1L<<0) #define USSize (1L<<1) #define PPosition (1L<<2) #define PSize (1L<<3) #define PMinSize (1L<<4) #define PMaxSize (1L<<5) #define PResizeInc (1L<<5) #define PAspect (1L<<6) #define PBaseSize (1L<<8) #define PWinGravity (1L<<9) #define PAllHints (PPosition|Psize|PMinSize|PMaxSize|PResizeInc|PAspect)
flags | 使用するメンバのマスクとフラグ |
---|---|
x,y,width,height | ※廃止 |
min_width min_height | 最小ウィンドウサイズ |
max_width max_height | 最大ウィンドウサイズ |
width_inc height_inc | ウィンドウサイズを計算する時の段階値 |
min_aspect max_aspect | ウィンドウサイズのアスペクト比の範囲 |
base_width base_height | ウィンドウサイズを計算する時の基本値 |
win_gravity | ウィンドウマネージャが作成したフレームウィンドウの基準位置。 ウィンドウ属性の win_gravity で設定できる値と同じ値。 |
ウィンドウの初期位置とサイズ
フラグに USPosition, USSize がある場合、ウィンドウの位置またはサイズは、ユーザーによって指定されたことを示します。PPosition, PSize がある場合、ウィンドウの位置またはサイズは、プログラムによって指定されたことを示します。
このフラグが設定されていると、ウィンドウマネージャは、Withdrawn 状態からマップされた時に、ウィンドウの現在の位置やサイズをそのまま使用して表示します (ウィンドウマネージャの実装にもよる)。
例えば、前回のウィンドウ位置とサイズを復元したい場合などは、このフラグを設定すると、最初のマップ時に表示される位置やサイズを固定できます。
ウィンドウのサイズ
ウィンドウのサイズは、各値を使って計算されます。アスペクト比の指定がない場合、以下のように計算されます。
width = base_width + i * width_inc height = base_height + j * height_inc
さらに、min と max のサイズで値が制限されます。
base の値がない場合は、min のサイズが使用されます。
min の値がない場合は、base のサイズが使用されます。
アスペクト比の指定がある場合は、ウィンドウサイズがその比率の範囲になるように調整されます。
その場合、base の値がある場合は、そのサイズを引いてからアスペクト比の計算を行います。
min_aspect と max_aspect で同じ値を指定すると、アスペクト比を固定できます。
固定ウィンドウサイズ
min_width = max_width, min_height = max_height の場合、ウィンドウサイズは固定となり、ユーザーによってリサイズができない状態となります。
この場合、ウィンドウ装飾が変更される場合があります (ウィンドウ枠に、リサイズを行うための領域がある場合、それがなくなる)。
この場合、ウィンドウ装飾が変更される場合があります (ウィンドウ枠に、リサイズを行うための領域がある場合、それがなくなる)。
プログラム (2)
実行時、引数に "0" を渡すか、指定しない場合、各ウィンドウサイズの指定を行います。
引数に "1" を渡した場合、アスペクト比を 4:3 に固定します。
ポインタボタンを押すと終了します。
"0" 時、ウィンドウサイズをリサイズすると、50 px 単位でサイズが変わり、50〜500 px の範囲までしかリサイズできないことを確認してください。また、ウィンドウ位置が (100, 100) で固定されていることも確認してください。
"1" 時、ウィンドウサイズは常に 4:3 のアスペクト比になっていることを確認してください。
(ウィンドウマネージャの実装によって、対応している場合と対応していない場合があります)
<d04b-normhints.c>
引数に "1" を渡した場合、アスペクト比を 4:3 に固定します。
ポインタボタンを押すと終了します。
"0" 時、ウィンドウサイズをリサイズすると、50 px 単位でサイズが変わり、50〜500 px の範囲までしかリサイズできないことを確認してください。また、ウィンドウ位置が (100, 100) で固定されていることも確認してください。
"1" 時、ウィンドウサイズは常に 4:3 のアスペクト比になっていることを確認してください。
(ウィンドウマネージャの実装によって、対応している場合と対応していない場合があります)
$ cc -o run d04b-normhints.c util.c -lX11
<d04b-normhints.c>
#include <stdlib.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include "util.h" int main(int argc,char **argv) { Display *disp; Window win; XSizeHints *sh; int type; if(argc < 2) type = 0; else type = atoi(argv[1]); disp = XOpenDisplay(NULL); if(!disp) return 1; win = create_test_window(disp, ButtonPressMask); //WM_NORMAL_HINTS sh = XAllocSizeHints(); switch(type) { //位置固定, min(50x50), max(500x500), 50 ずつサイズが変化 case 0: XMoveWindow(disp, win, 100, 100); sh->flags = PPosition | PMinSize | PMaxSize | PResizeInc; sh->min_width = sh->min_height = 50; sh->max_width = sh->max_height = 500; sh->width_inc = sh->height_inc = 50; break; //アスペクト比を 4:3 で固定 default: sh->flags = PAspect; sh->min_aspect.x = 4, sh->min_aspect.y = 3; sh->max_aspect.x = 4, sh->max_aspect.y = 3; break; } XSetWMNormalHints(disp, win, sh); XFree(sh); //イベント XMapWindow(disp, win); eventloop_button_quit(disp); XCloseDisplay(disp); return 0; }