mirror of
https://github.com/fltk/fltk.git
synced 2026-05-30 13:05:35 +08:00
Simplify and improve function Fl_Wayland_Window_Driver::resize() (#1307)
This modified implementation improves support of subwindows that are moved or resized above their parent toplevel window. It also significantly shortens and clarifies the source code.
This commit is contained in:
@@ -1816,37 +1816,6 @@ 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);
|
|
||||||
if (xid_rect->xid->buffer && xid_rect->xid->buffer->draw_buffer_needs_commit) {
|
|
||||||
// for scenarios where the child window is moved and its parent is simultaneously modified
|
|
||||||
Fl_Wayland_Graphics_Driver::buffer_commit(xid_rect->xid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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) {
|
void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) {
|
||||||
static int depth = 0;
|
static int depth = 0;
|
||||||
struct wld_window *fl_win = fl_wl_xid(pWindow);
|
struct wld_window *fl_win = fl_wl_xid(pWindow);
|
||||||
@@ -1872,16 +1841,12 @@ void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) {
|
|||||||
}
|
}
|
||||||
Fl_Window *parent = this->parent() ? pWindow->window() : NULL;
|
Fl_Window *parent = this->parent() ? pWindow->window() : NULL;
|
||||||
struct wld_window *parent_xid = parent ? fl_wl_xid(parent) : NULL;
|
struct wld_window *parent_xid = parent ? fl_wl_xid(parent) : NULL;
|
||||||
xid_and_rect *xid_rect = NULL;
|
// When moving or resizing a subwindow independently from its parent, skip the move/resize
|
||||||
if (parent_xid && parent_xid->frame_cb && wl_proxy_get_listener((struct wl_proxy*)parent_xid->frame_cb) == &surface_frame_listener) {
|
// operation if the parent window is being redrawn, in line with the frame callback mechanism.
|
||||||
xid_rect = (xid_and_rect*)wl_callback_get_user_data(parent_xid->frame_cb);
|
if (depth == 1 && fl_win && parent_xid && parent_xid->frame_cb && is_a_move) {
|
||||||
if (xid_rect->win != pWindow) xid_rect = NULL;
|
depth--;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// 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 ((parent && parent->damage()) || depth > 1 || pWindow->as_gl_window() || !parent_xid ||
|
|
||||||
wait_for_expose_value || (parent_xid->frame_cb && !xid_rect)) {
|
|
||||||
if (is_a_resize) {
|
if (is_a_resize) {
|
||||||
if (pWindow->parent()) {
|
if (pWindow->parent()) {
|
||||||
if (W < 1) W = 1;
|
if (W < 1) W = 1;
|
||||||
@@ -1894,9 +1859,11 @@ void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) {
|
|||||||
x(X); y(Y);
|
x(X); y(Y);
|
||||||
//fprintf(stderr, "move win=%p to %dx%d\n", pWindow, X, Y);
|
//fprintf(stderr, "move win=%p to %dx%d\n", pWindow, X, Y);
|
||||||
}
|
}
|
||||||
|
if (!fl_win) {
|
||||||
|
depth--;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shown()) {
|
|
||||||
if (is_a_resize) {
|
if (is_a_resize) {
|
||||||
if (pWindow->as_overlay_window() && other_xid) {
|
if (pWindow->as_overlay_window() && other_xid) {
|
||||||
destroy_double_buffer();
|
destroy_double_buffer();
|
||||||
@@ -1935,49 +1902,28 @@ void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) {
|
|||||||
xdg_surface_set_window_geometry(fl_win->xdg_surface, 0, 0, W, H);
|
xdg_surface_set_window_geometry(fl_win->xdg_surface, 0, 0, W, H);
|
||||||
//printf("xdg_surface_set_window_geometry: %dx%d\n",W, H);
|
//printf("xdg_surface_set_window_geometry: %dx%d\n",W, H);
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!in_handle_configure && xdg_toplevel() && Fl::e_state == FL_BUTTON1) {
|
||||||
if (!in_handle_configure && xdg_toplevel()) {
|
// Wayland doesn't provide a way for the app to set the window position on screen.
|
||||||
// Wayland doesn't seem to provide a reliable way for the app to set the
|
// This is functional when the move is mouse-driven.
|
||||||
// window position on screen. This is functional when the move is mouse-driven.
|
|
||||||
Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
|
Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
|
||||||
if (Fl::e_state == FL_BUTTON1) {
|
|
||||||
xdg_toplevel_move(xdg_toplevel(), scr_driver->seat->wl_seat, scr_driver->seat->serial);
|
xdg_toplevel_move(xdg_toplevel(), scr_driver->seat->wl_seat, scr_driver->seat->serial);
|
||||||
Fl::pushed(NULL);
|
Fl::pushed(NULL);
|
||||||
Fl::e_state = 0;
|
Fl::e_state = 0;
|
||||||
}
|
}
|
||||||
} else if (pWindow->as_gl_window() && fl_win->kind == SUBWINDOW && fl_win->subsurface) {
|
|
||||||
wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fl_win && parent_xid) {
|
if (parent_xid) {
|
||||||
if (pWindow->as_gl_window()) {
|
if (depth > 1) {
|
||||||
if (fl_win->frame_cb) {
|
if (fl_win->subsurface) {
|
||||||
wl_callback_destroy(fl_win->frame_cb);
|
wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f);
|
||||||
fl_win->frame_cb = NULL;
|
wl_surface_commit(parent_xid->wl_surface);
|
||||||
}
|
}
|
||||||
if (parent_xid->buffer && !parent_xid->frame_cb) {
|
} else if (is_a_move && !parent_xid->frame_cb) {
|
||||||
Fl_Wayland_Graphics_Driver::buffer_commit(parent_xid);
|
// Use the frame callback mechanism applied to the object's parent window
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!(parent && parent->damage()) && !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);
|
parent_xid->frame_cb = wl_surface_frame(parent_xid->wl_surface);
|
||||||
wl_callback_add_listener(parent_xid->frame_cb, &surface_frame_listener, xid_rect);
|
wl_callback_add_listener(parent_xid->frame_cb,
|
||||||
xid_rect->X = X; xid_rect->Y = Y; xid_rect->W = W; xid_rect->H = H;
|
Fl_Wayland_Graphics_Driver::p_surface_frame_listener, parent_xid);
|
||||||
xid_rect->need_resize = is_a_resize;
|
if (fl_win->subsurface) wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f);
|
||||||
wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f);
|
|
||||||
wl_surface_commit(parent_xid->wl_surface);
|
wl_surface_commit(parent_xid->wl_surface);
|
||||||
} else if (!xid_rect) {
|
|
||||||
if (is_a_move && fl_win->subsurface) {
|
|
||||||
wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f);
|
|
||||||
}
|
|
||||||
wl_surface_commit(parent_xid->wl_surface);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
checkSubwindowFrame(); // make sure subwindow doesn't leak outside parent
|
checkSubwindowFrame(); // make sure subwindow doesn't leak outside parent
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user