Wayland: support move/resize of subwindow independently from parent (#1003)
This commit is contained in:
parent
ee05d4bd3a
commit
fd257a7bf3
@ -1771,7 +1771,36 @@ int Fl_Wayland_Window_Driver::set_cursor_4args(const Fl_RGB_Image *rgb, int hotx
|
||||
}
|
||||
|
||||
|
||||
struct xid_and_rect {
|
||||
struct wld_window *xid;
|
||||
Fl_Window *win;
|
||||
int X, Y, W, H;
|
||||
bool need_resize;
|
||||
};
|
||||
|
||||
|
||||
static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) {
|
||||
struct xid_and_rect *xid_rect = (xid_and_rect *)data;
|
||||
wl_callback_destroy(cb);
|
||||
xid_rect->xid->frame_cb = NULL;
|
||||
if (xid_rect->need_resize) {
|
||||
xid_rect->win->Fl_Group::resize(xid_rect->X, xid_rect->Y, xid_rect->W, xid_rect->H);
|
||||
xid_rect->win->redraw();
|
||||
} else {
|
||||
xid_rect->win->Fl_Widget::resize(xid_rect->X, xid_rect->Y, xid_rect->W, xid_rect->H);
|
||||
wl_surface_commit(xid_rect->xid->wl_surface);
|
||||
}
|
||||
delete xid_rect;
|
||||
}
|
||||
|
||||
|
||||
static const struct wl_callback_listener surface_frame_listener = {
|
||||
.done = surface_frame_done,
|
||||
};
|
||||
|
||||
|
||||
void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) {
|
||||
static int depth = 0;
|
||||
struct wld_window *fl_win = fl_wl_xid(pWindow);
|
||||
if (fl_win && fl_win->kind == DECORATED && !xdg_toplevel()) {
|
||||
pWindow->wait_for_expose();
|
||||
@ -1789,20 +1818,32 @@ void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) {
|
||||
int is_a_resize = (W != w() || H != h() || true_rescale);
|
||||
if (is_a_move) force_position(1);
|
||||
else if (!is_a_resize && !is_a_move) return;
|
||||
depth++;
|
||||
if (shown() && !(parent() || popup_window())) {
|
||||
X = Y = 0;
|
||||
}
|
||||
if (is_a_resize) {
|
||||
if (pWindow->parent()) {
|
||||
if (W < 1) W = 1;
|
||||
if (H < 1) H = 1;
|
||||
struct wld_window *parent_xid = parent() ? fl_wl_xid(pWindow->window()) : NULL;
|
||||
xid_and_rect *xid_rect = NULL;
|
||||
if (parent_xid && parent_xid->frame_cb && wl_proxy_get_listener((struct wl_proxy*)parent_xid->frame_cb) == &surface_frame_listener) {
|
||||
xid_rect = (xid_and_rect*)wl_callback_get_user_data(parent_xid->frame_cb);
|
||||
if (xid_rect->win != pWindow) xid_rect = NULL;
|
||||
}
|
||||
// When moving or resizing a non-GL subwindow independently from its parent, this condition
|
||||
// delays application of X,Y,W,H values until the compositor signals
|
||||
// it's ready for a new frame using the frame callback mechanism.
|
||||
if (depth > 1 || pWindow->as_gl_window() || !parent_xid || wait_for_expose_value || (parent_xid->frame_cb && !xid_rect)) {
|
||||
if (is_a_resize) {
|
||||
if (pWindow->parent()) {
|
||||
if (W < 1) W = 1;
|
||||
if (H < 1) H = 1;
|
||||
}
|
||||
pWindow->Fl_Group::resize(X,Y,W,H);
|
||||
//fprintf(stderr, "resize: win=%p to %dx%d\n", pWindow, W, H);
|
||||
if (shown()) {pWindow->redraw();}
|
||||
} else {
|
||||
x(X); y(Y);
|
||||
//fprintf(stderr, "move win=%p to %dx%d\n", pWindow, X, Y);
|
||||
}
|
||||
pWindow->Fl_Group::resize(X,Y,W,H);
|
||||
//fprintf(stderr, "resize: win=%p to %dx%d\n", pWindow, W, H);
|
||||
if (shown()) {pWindow->redraw();}
|
||||
} else {
|
||||
x(X); y(Y);
|
||||
//fprintf(stderr, "move win=%p to %dx%d\n", pWindow, X, Y);
|
||||
}
|
||||
|
||||
if (shown()) {
|
||||
@ -1860,14 +1901,35 @@ void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) {
|
||||
}
|
||||
}
|
||||
|
||||
struct wld_window *parent_xid = parent() ? fl_wl_xid(pWindow->window()) : NULL;
|
||||
if (fl_win && parent_xid) {
|
||||
if (pWindow->as_gl_window() && fl_win->frame_cb) {
|
||||
wl_callback_destroy(fl_win->frame_cb);
|
||||
fl_win->frame_cb = NULL;
|
||||
} else wl_surface_commit(parent_xid->wl_surface);
|
||||
if (pWindow->as_gl_window()) {
|
||||
if (fl_win->frame_cb) {
|
||||
wl_callback_destroy(fl_win->frame_cb);
|
||||
fl_win->frame_cb = NULL;
|
||||
}
|
||||
Fl_Wayland_Graphics_Driver::buffer_commit(parent_xid);
|
||||
} else {
|
||||
if (!parent_xid->frame_cb) {
|
||||
// use the frame callback mechanism and memorize current X,Y,W,H values
|
||||
xid_rect = new xid_and_rect;
|
||||
xid_rect->xid = parent_xid;
|
||||
xid_rect->win = pWindow;
|
||||
parent_xid->frame_cb = wl_surface_frame(parent_xid->wl_surface);
|
||||
wl_callback_add_listener(parent_xid->frame_cb, &surface_frame_listener, xid_rect);
|
||||
xid_rect->X = X; xid_rect->Y = Y; xid_rect->W = W; xid_rect->H = H;
|
||||
xid_rect->need_resize = is_a_resize;
|
||||
wl_surface_commit(parent_xid->wl_surface);
|
||||
} else if (xid_rect) {
|
||||
// update the active frame callback with new X,Y,W,H values
|
||||
xid_rect->X = X; xid_rect->Y = Y; xid_rect->W = W; xid_rect->H = H;
|
||||
xid_rect->need_resize |= is_a_resize;
|
||||
} else {
|
||||
wl_surface_commit(parent_xid->wl_surface);
|
||||
}
|
||||
}
|
||||
checkSubwindowFrame(); // make sure subwindow doesn't leak outside parent
|
||||
}
|
||||
depth--;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user