ポップアップウィンドウ
xdg-shell で、xdg_popup を使って、ポップアップウィンドウを表示してみます。
ウィンドウを画面の端に移動させた後、ポップアップウィンドウを表示してみると、サーバーによるウィンドウ位置の調整が確認できます。
<14-popup.c>
$ cc -o test 14-popup.c client.c imagebuf.c xdg-shell-protocol.c -lwayland-client -lrt
- 左ドラッグで、ウィンドウ位置を移動します。
- 右クリックで、青いポップアップウィンドウを表示します。
- ポップアップウィンドウ内で右クリックするか、ポップアップウィンドウ外をクリックすると、ポップアップウィンドウを閉じます。
- トップレベルウィンドウを中ボタン押しで、終了します。
- Space キー押しで、次にポップアップを表示する時の位置を、以下の2通りから切り替えます。
[1] ウィンドウ内の黒い矩形の右上位置を基準にする。
[2] (0, 0) - (1 x 1) の左上位置を基準にする。
ウィンドウを画面の端に移動させた後、ポップアップウィンドウを表示してみると、サーバーによるウィンドウ位置の調整が確認できます。
<14-popup.c>
#include <stdio.h> #include <stdlib.h> #include <linux/input-event-codes.h> #include <wayland-client.h> #include "xdg-shell-client-protocol.h" #include "client.h" #include "imagebuf.h" //------------------ typedef struct { Surface sf; client *cl; struct xdg_surface *xdg_surface; struct xdg_popup *xdg_popup; Toplevel *parent; }popupwindow; void popupwindow_destroy(popupwindow *p); typedef struct { client b; Toplevel *win; popupwindow *popup; struct wl_surface *enter_surface; int popup_pos; }client_ex; #define ANCHOR_X 100 #define ANCHOR_Y 100 #define ANCHOR_W 100 #define ANCHOR_H 80 //------------------ static void _clientex_popup_finish(client_ex *p) { popupwindow_destroy(p->popup); p->popup = NULL; } //======================== // xdg_surface (popup) //======================== static void _popup_xdg_surface_configure( void *data,struct xdg_surface *surface,uint32_t serial) { printf("[popup] xdg_surface # configure\n"); xdg_surface_ack_configure(surface, serial); surface_update(&((popupwindow *)data)->sf); } static const struct xdg_surface_listener g_popup_xdg_surface_listener = { _popup_xdg_surface_configure }; //======================== // xdg_popup //======================== /* 位置やサイズ変更時 * * サーバーによって位置やサイズが調整される場合がある */ static void _popup_configure(void *data, struct xdg_popup *popup, int32_t x, int32_t y, int32_t width, int32_t height) { popupwindow *p = (popupwindow *)data; printf("xdg_popup # configure | (%d, %d)-(%d x %d)\n", x, y, width, height); if(surface_resize(&p->sf, p->cl, width, height)) imagebuf_fill(p->sf.img, 0xff0000ff); } /* ポップアップ終了時 */ static void _popup_done(void *data, struct xdg_popup *popup) { popupwindow *p = (popupwindow *)data; printf("xdg_popup # done\n"); _clientex_popup_finish((client_ex *)p->cl); } static const struct xdg_popup_listener g_popup_listener = { _popup_configure, _popup_done }; //======================== // popupwindow //======================== /* ポップアップ用 xdg_positioner 作成 */ static struct xdg_positioner *_create_popup_positioner( client *cl,int w,int h,int pos_point) { struct xdg_positioner *xdgpos; //xdg_positioner 作成 xdgpos = xdg_wm_base_create_positioner(cl->xdg_wm_base); //ウィンドウサイズ xdg_positioner_set_size(xdgpos, w, h); // if(pos_point) { //(0, 0) 左上 xdg_positioner_set_anchor_rect(xdgpos, 0, 0, 1, 1); xdg_positioner_set_anchor(xdgpos, XDG_POSITIONER_ANCHOR_TOP_LEFT); } else { //黒い矩形の右上 xdg_positioner_set_anchor_rect(xdgpos, ANCHOR_X, ANCHOR_Y, ANCHOR_W, ANCHOR_H); xdg_positioner_set_anchor(xdgpos, XDG_POSITIONER_ANCHOR_TOP_RIGHT); } xdg_positioner_set_gravity(xdgpos, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT); //サーバー側で位置やサイズを調整できるようにする xdg_positioner_set_constraint_adjustment(xdgpos, XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y); return xdgpos; } /* ポップアップウィンドウ作成 */ popupwindow *popupwindow_create(client *cl,Toplevel *parent, int width,int height,uint32_t serial,int pos_point) { popupwindow *p; struct xdg_positioner *xdgpos; p = (popupwindow *)calloc(1, sizeof(popupwindow)); if(!p) return NULL; p->cl = cl; p->parent = parent; surface_create(&p->sf, cl, width, height); imagebuf_fill(p->sf.img, 0xff0000ff); //xdg_surface p->xdg_surface = xdg_wm_base_get_xdg_surface(cl->xdg_wm_base, p->sf.surface); xdg_surface_add_listener(p->xdg_surface, &g_popup_xdg_surface_listener, p); //xdg_positioner 作成 xdgpos = _create_popup_positioner(cl, width, height, pos_point); //xdg_popup 作成 p->xdg_popup = xdg_surface_get_popup(p->xdg_surface, parent->xdg_surface, xdgpos); xdg_positioner_destroy(xdgpos); xdg_popup_add_listener(p->xdg_popup, &g_popup_listener, p); //グラブ xdg_popup_grab(p->xdg_popup, cl->seat, serial); //適用 wl_surface_commit(p->sf.surface); return p; } /* 破棄 */ void popupwindow_destroy(popupwindow *p) { if(p) { xdg_popup_destroy(p->xdg_popup); xdg_surface_destroy(p->xdg_surface); surface_destroy(&p->sf); free(p); } } //======================== // wl_pointer //======================== static const char *_get_surface_name(client_ex *p,struct wl_surface *surface) { return (surface == p->win->sf.surface)? "toplevel": "popup"; } static void _pointer_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y) { client_ex *p = (client_ex *)data; printf("wl_pointer # enter | %s\n", _get_surface_name(p, surface)); p->enter_surface = surface; client_set_cursor(CLIENT(p), serial); } static void _pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface) { client_ex *p = (client_ex *)data; printf("wl_pointer # leave | %s\n", _get_surface_name(p, surface)); p->enter_surface = NULL; } static void _pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y) { printf("wl_pointer # motion | (%d, %d)\n", x >> 8, y >> 8); } /* ボタン */ static void _pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { client_ex *p = (client_ex *)data; Toplevel *win; printf("wl_pointer # button | %s, serial:%u\n", (state == WL_POINTER_BUTTON_STATE_PRESSED)? "press":"release", serial); if(state != WL_POINTER_BUTTON_STATE_PRESSED) return; win = p->win; // if(p->enter_surface == win->sf.surface) { //トップレベル if(p->popup) _clientex_popup_finish(p); else { switch(button) { //左ボタン:ウィンドウ位置移動 case BTN_LEFT: xdg_toplevel_move(win->xdg_toplevel, p->b.seat, serial); break; //右ボタン:ポップアップ表示 case BTN_RIGHT: printf("-- create popup\n"); p->popup = popupwindow_create(CLIENT(p), win, 200, 300, serial, p->popup_pos); break; //中ボタン:終了 case BTN_MIDDLE: p->b.finish_loop = 1; break; } } } else { //ポップアップ if(button == BTN_RIGHT) _clientex_popup_finish(p); } } static void _pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { } static void _pointer_frame(void *data, struct wl_pointer *pointer) { } static void _pointer_axis_source(void *data, struct wl_pointer *pointer, uint32_t axis_source) { } static void _pointer_axis_stop(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis) { } static void _pointer_axis_discrete(void *data, struct wl_pointer *pointer, uint32_t axis, int32_t discrete) { } //ver 5 static const struct wl_pointer_listener g_pointer_listener = { _pointer_enter, _pointer_leave, _pointer_motion, _pointer_button, _pointer_axis, _pointer_frame, _pointer_axis_source, _pointer_axis_stop, _pointer_axis_discrete }; //======================== static void _keyboard_press(client *cl,uint32_t key,uint32_t serial) { client_ex *p = (client_ex *)cl; //Space キーで表示位置を切り替え if(key == KEY_SPACE) { p->popup_pos ^= 1; printf("# popup pos: %s\n", (p->popup_pos)? "(0,0)": "anchor"); } } /* main */ int main(void) { client_ex *p; Toplevel *win; p = (client_ex *)client_new(sizeof(client_ex)); p->b.init_flags = CLIENT_INIT_FLAGS_SEAT | CLIENT_INIT_FLAGS_POINTER | CLIENT_INIT_FLAGS_KEYBOARD | CLIENT_INIT_FLAGS_CREATE_CURSOR; p->b.pointer_listener = &g_pointer_listener; p->b.xdg_shell_need_ver = 3; p->b.func_keyboard_key_press = _keyboard_press; client_init(CLIENT(p)); //ウィンドウ p->win = win = toplevel_create(CLIENT(p), 256, 256, NULL); imagebuf_fill(win->sf.img, 0xffff0000); imagebuf_box(win->sf.img, 0, 0, 256, 256, 0xff00ff00); imagebuf_box(win->sf.img, ANCHOR_X, ANCHOR_Y, ANCHOR_W, ANCHOR_H, 0xff000000); //イベントループ client_loop_simple(CLIENT(p)); //解放 toplevel_destroy(win); client_destroy(CLIENT(p)); return 0; }
ポップアップについて
xdg_popup を使うと、ポップアップウィンドウや、ツールチップなどを表示できます。
xdg_popup が xdg_toplevel と異なる点は、親ウィンドウ内の座標を基準にして、表示位置を指定できることと、一度表示した後は、ウィンドウを削除する以外の機能はないということです。
xdg_popup が xdg_toplevel と異なる点は、親ウィンドウ内の座標を基準にして、表示位置を指定できることと、一度表示した後は、ウィンドウを削除する以外の機能はないということです。
作成手順
ポップアップの作成手順は以下の通りです。
- wl_surface を作成。
- xdg_surface を作成。
- 親ウィンドウに配置するための xdg_positioner を作成。
- xdg_positioner を指定して、xdg_popup を作成。
- xdg_positioner を破棄。
- xdg_popup にハンドラを設定。
- ポインタ操作が必要な場合は、xdg_popup_grab() を実行する。
(単に表示するだけのツールチップなどでは必要ない) - wl_surface_commit() で、以上の内容を適用する。
処理
ポップアップの作成後は、以下のように処理を行っていきます。
- ポップアップウィンドウが表示される前に、xdg_popup:configure イベントが来る。
ここでは、サーバーによって調整された、最終的なウィンドウの位置やサイズが渡される。
ここで wl_buffer イメージを作成しても良いし、サイズが変更された場合はイメージの再作成などを行う。
- その後 xdg_surface:configure イベントが来るので、xdg_surface_ack_configure() を実行した後、更新処理を行う。
- サーバー側の判断でポップアップが終了する時、xdg_popup:popup_done イベントが来るので、ポップアップの破棄などの処理を行う。
任意のタイミングで終了したい時は、xdg_popup_destroy() で破棄する。
xdg_positioner
xdg_popup を作成する前に、xdg_positioner が必要になるので、まずはそちらを作成しておきます。
xdg_positioner は、親ウィンドウの任意の位置にウィンドウを表示する時、表示するウィンドウの位置やサイズ、配置などの設定を指定するためのものです。
xdg_wm_base から、xdg_positioner を作成します。
表示するウィンドウのサイズを設定します。
※実際には、サーバー側でサイズが調整される場合があります。
アンカー矩形を、親の座標で指定します。
アンカー矩形は、ウィンドウの位置を決める時に基準となる、四角形の範囲です。
実際の表示位置は、この矩形の、4隅の点や4辺を基準にして調整されます。
例えば、親ウィンドウ内にボタンがあって、そのボタンの位置を基準にして、周囲にポップアップウィンドウを表示したい場合、親ウィンドウ内でのボタンの位置とサイズを指定します。
任意の点の位置に表示したい場合は、(x, y) - (1 x 1) とします。
※xdg_popup では、デスクトップ画面の任意の位置 (クライアントのウィンドウ外) にポップアップを表示することはできません。
子の表示位置を決める時に、アンカー矩形のどの位置・辺を基準にするかを指定します。
以下の値から、一つ指定します。
NONE の場合は、矩形内の中央に配置されます。
TOP または BOTTOM の場合、X は中央、Y は上下の端に配置されます。
LEFT または RIGHT の場合、X は左右の端、Y は中央に配置されます。
TOP_RIGHT などの場合、矩形の指定隅が基準になります。左上や右下などです。
後述する設定で、位置の反転を許可した場合、サーバー側の調整によって、反対側の辺に配置される場合があります。
子の配置方向を指定します。
指定されていない軸は、中央揃えにされます。
BOTTOM_RIGHT の場合は、アンカーの基準位置がウィンドウの左上として、右下方向に配置します。
TOP_LEFT の場合は、アンカーの基準位置がウィンドウの右下として、左上方向に配置します。
設定された位置やサイズで、実際に子を配置した時に、子が画面からはみ出す場合、サーバー側で位置やサイズを調整させるようにすることができます。
指定する値はフラグになっているので、必要であれば複数指定してください。
デフォルトは NONE です。
指定されていない軸は、調整を許可しないという意味になります。
同じ軸で複数の値が指定されている場合は、優先順によって、適切なものが一つ使われます。
子の表示位置を、実際に表示される位置から、指定 px 分ずらします。
xdg_positioner は、親ウィンドウの任意の位置にウィンドウを表示する時、表示するウィンドウの位置やサイズ、配置などの設定を指定するためのものです。
作成
//作成 struct xdg_positioner *xdg_wm_base_create_positioner( struct xdg_wm_base *xdg_wm_base); //破棄 void xdg_positioner_destroy(struct xdg_positioner *xdg_positioner);
xdg_wm_base から、xdg_positioner を作成します。
サイズのセット
void xdg_positioner_set_size(struct xdg_positioner *xdg_positioner, int32_t width, int32_t height);
表示するウィンドウのサイズを設定します。
※実際には、サーバー側でサイズが調整される場合があります。
アンカー矩形の設定
void xdg_positioner_set_anchor_rect( struct xdg_positioner *xdg_positioner, int32_t x, int32_t y, int32_t width, int32_t height);
アンカー矩形を、親の座標で指定します。
アンカー矩形は、ウィンドウの位置を決める時に基準となる、四角形の範囲です。
実際の表示位置は、この矩形の、4隅の点や4辺を基準にして調整されます。
例えば、親ウィンドウ内にボタンがあって、そのボタンの位置を基準にして、周囲にポップアップウィンドウを表示したい場合、親ウィンドウ内でのボタンの位置とサイズを指定します。
任意の点の位置に表示したい場合は、(x, y) - (1 x 1) とします。
※xdg_popup では、デスクトップ画面の任意の位置 (クライアントのウィンドウ外) にポップアップを表示することはできません。
アンカー矩形の辺を設定
void xdg_positioner_set_anchor( struct xdg_positioner *xdg_positioner, uint32_t anchor);
子の表示位置を決める時に、アンカー矩形のどの位置・辺を基準にするかを指定します。
以下の値から、一つ指定します。
enum xdg_positioner_anchor { XDG_POSITIONER_ANCHOR_NONE = 0, XDG_POSITIONER_ANCHOR_TOP = 1, XDG_POSITIONER_ANCHOR_BOTTOM = 2, XDG_POSITIONER_ANCHOR_LEFT = 3, XDG_POSITIONER_ANCHOR_RIGHT = 4, XDG_POSITIONER_ANCHOR_TOP_LEFT = 5, XDG_POSITIONER_ANCHOR_BOTTOM_LEFT = 6, XDG_POSITIONER_ANCHOR_TOP_RIGHT = 7, XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT = 8, };
NONE の場合は、矩形内の中央に配置されます。
TOP または BOTTOM の場合、X は中央、Y は上下の端に配置されます。
LEFT または RIGHT の場合、X は左右の端、Y は中央に配置されます。
TOP_RIGHT などの場合、矩形の指定隅が基準になります。左上や右下などです。
後述する設定で、位置の反転を許可した場合、サーバー側の調整によって、反対側の辺に配置される場合があります。
配置方向を設定
void xdg_positioner_set_gravity( struct xdg_positioner *xdg_positioner, uint32_t gravity);
子の配置方向を指定します。
enum xdg_positioner_gravity { XDG_POSITIONER_GRAVITY_NONE = 0, XDG_POSITIONER_GRAVITY_TOP = 1, XDG_POSITIONER_GRAVITY_BOTTOM = 2, XDG_POSITIONER_GRAVITY_LEFT = 3, XDG_POSITIONER_GRAVITY_RIGHT = 4, XDG_POSITIONER_GRAVITY_TOP_LEFT = 5, XDG_POSITIONER_GRAVITY_BOTTOM_LEFT = 6, XDG_POSITIONER_GRAVITY_TOP_RIGHT = 7, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT = 8, };
指定されていない軸は、中央揃えにされます。
BOTTOM_RIGHT の場合は、アンカーの基準位置がウィンドウの左上として、右下方向に配置します。
TOP_LEFT の場合は、アンカーの基準位置がウィンドウの右下として、左上方向に配置します。
サーバーによる調整を設定
void xdg_positioner_set_constraint_adjustment( struct xdg_positioner *xdg_positioner, uint32_t constraint_adjustment);
設定された位置やサイズで、実際に子を配置した時に、子が画面からはみ出す場合、サーバー側で位置やサイズを調整させるようにすることができます。
指定する値はフラグになっているので、必要であれば複数指定してください。
enum xdg_positioner_constraint_adjustment { XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE = 0, XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X = 1, XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y = 2, XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X = 4, XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y = 8, XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X = 16, XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 32 };
デフォルトは NONE です。
指定されていない軸は、調整を許可しないという意味になります。
同じ軸で複数の値が指定されている場合は、優先順によって、適切なものが一つ使われます。
SLIDE | ウィンドウ位置をスライドして移動します。 画面の端からはみ出している場合は、画面内に収まるように移動します。 |
---|---|
FLIP | ウィンドウ位置を反転します。 各軸ごとに、アンカー矩形の反対側の辺と、反対側の配置方向で調整します。 |
RESIZE | ウィンドウサイズを変更します。 幅や高さが画面サイズを超える場合、画面サイズに合わせます。 位置の調整がなく、サイズ変更のみ許可している場合は、位置はそのままで、画面内に収まるようにサイズを小さくします。 |
オフセット位置を設定
void xdg_positioner_set_offset( struct xdg_positioner *xdg_positioner, int32_t x, int32_t y);
子の表示位置を、実際に表示される位置から、指定 px 分ずらします。
xdg_popup
xdg_positioner が作成できたら、xdg_popup を作成します。
parent には、親サーフェスを指定します。
xdg_toplevel か xdg_popup のサーフェスを指定できます。
任意のタイミングでポップアップを閉じたい場合は、xdg_popup_destroy() で破棄してください。
xdg_positioner は、xdg_popup を作成する時のみ必要になるので、作成後はすぐに破棄して構いません。
作成
//作成 struct xdg_popup *xdg_surface_get_popup(struct xdg_surface *xdg_surface, struct xdg_surface *parent, struct xdg_positioner *positioner); //破棄 void xdg_popup_destroy(struct xdg_popup *xdg_popup); //ハンドラ設定 int xdg_popup_add_listener(struct xdg_popup *xdg_popup, const struct xdg_popup_listener *listener, void *data); struct xdg_popup_listener { void (*configure)(void *data, struct xdg_popup *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height); void (*popup_done)(void *data, struct xdg_popup *xdg_popup); //ver 3 void (*repositioned)(void *data, struct xdg_popup *xdg_popup, uint32_t token); };
parent には、親サーフェスを指定します。
xdg_toplevel か xdg_popup のサーフェスを指定できます。
任意のタイミングでポップアップを閉じたい場合は、xdg_popup_destroy() で破棄してください。
xdg_positioner は、xdg_popup を作成する時のみ必要になるので、作成後はすぐに破棄して構いません。
グラブ
ポップアップの範囲外がクリックされたら、ポップアップを終了させるようにしたい場合、ポインタのグラブを行う必要があります。
ツールチップウィンドウなど、単純に一定期間表示するだけのポップアップであれば、グラブは必要ありませんが、ポインタ操作によって何らかの処理を行うポップアップの場合は、ポップアップの開始時に、以下の関数でグラブを行う必要があります。
serial には、ポインタのボタン押しや、キー押しイベント時に渡されたシリアル値を指定します。
何らかの理由でグラブが行えなかった場合は、すぐに xdg_popup:popup_done イベントが来て、ポップアップはキャンセル扱いになります。
階層メニューなど、ポップアップの実行中に、さらにポップアップを表示したい場合は、1つのポップアップごとに1回実行することができます。
その場合は、最後に作成したポップアップから順に、ポップアップを破棄する必要があります。
クライアントの他のウィンドウ上のポインタイベントは、通常通り送られてくるので、注意してください。
(ポップアップのサーフェスに対して送られてくるのではなく、それぞれのサーフェスに対して送られてきます)
そのため、ポップアップ以外のウィンドウ上でボタンが押された時は、クライアント側で、ポップアップを閉じる処理を行う必要があります。
ツールチップウィンドウなど、単純に一定期間表示するだけのポップアップであれば、グラブは必要ありませんが、ポインタ操作によって何らかの処理を行うポップアップの場合は、ポップアップの開始時に、以下の関数でグラブを行う必要があります。
void xdg_popup_grab(struct xdg_popup *xdg_popup, struct wl_seat *seat, uint32_t serial);
serial には、ポインタのボタン押しや、キー押しイベント時に渡されたシリアル値を指定します。
何らかの理由でグラブが行えなかった場合は、すぐに xdg_popup:popup_done イベントが来て、ポップアップはキャンセル扱いになります。
階層メニューなど、ポップアップの実行中に、さらにポップアップを表示したい場合は、1つのポップアップごとに1回実行することができます。
その場合は、最後に作成したポップアップから順に、ポップアップを破棄する必要があります。
終了処理
グラブ中に、クライアントのウィンドウ内以外の位置でボタンが押された場合、サーバー側の処理によって xdg_popup:popup_done イベントが来るので、そこでポップアップを終了させます。クライアントの他のウィンドウ上のポインタイベントは、通常通り送られてくるので、注意してください。
(ポップアップのサーフェスに対して送られてくるのではなく、それぞれのサーフェスに対して送られてきます)
そのため、ポップアップ以外のウィンドウ上でボタンが押された時は、クライアント側で、ポップアップを閉じる処理を行う必要があります。
xdg_popup のイベント
struct xdg_popup_listener { void (*configure)(void *data, struct xdg_popup *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height); void (*popup_done)(void *data, struct xdg_popup *xdg_popup); //ver 3 void (*repositioned)(void *data, struct xdg_popup *xdg_popup, uint32_t token); };
configure
サーバーによって、ポップアップの位置やサイズが確定した時に来ます。
最初にポップアップが表示される時は、常に送信されます。
サーバーによる位置やサイズの調整を許可した場合は、ここで、調整された値が送られてきます。
このイベントの後に、xdg_surface:configure イベントが来ます。
最初にポップアップが表示される時は、常に送信されます。
サーバーによる位置やサイズの調整を許可した場合は、ここで、調整された値が送られてきます。
このイベントの後に、xdg_surface:configure イベントが来ます。
popup_done
ポップアップの表示後、サーバー側の判断で、ポップアップを終了するタイミングが来た時に送られてきます。
ポップアップを実際に終了させる場合は、xdg_popup_destroy() で破棄します。
クライアントが任意のタイミングで xdg_popup_destroy() を実行した場合、このイベントは来ません。
ポップアップを実際に終了させる場合は、xdg_popup_destroy() で破棄します。
クライアントが任意のタイミングで xdg_popup_destroy() を実行した場合、このイベントは来ません。
repositioned (ver 3)
xdg_popup_reposition() によって、ポップアップの表示中に位置を変更した時、その応答として送信されます。