From f4ff99494616aa92a9afc3b582704fdce4c57525 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Sat, 2 Apr 2022 21:34:51 -0400 Subject: [PATCH] cursor: Fix "jumping opposite edges" issue when resizing. Commit ec68806354f2 ("xwayland: Honor size increments from WM_SIZE_HINTS") adjusted only the window width/height according to the size hints. If resizing from the top or left edge of the window, we also need to adjust the window position to keep the bottom or right edge from jumping around. --- include/labwc.h | 2 +- src/cursor.c | 40 ++++++++++++++++++---------------------- src/view.c | 45 ++++++++++++++++++++++++++------------------- src/xdg.c | 9 +++------ src/xwayland.c | 27 ++++----------------------- 5 files changed, 52 insertions(+), 71 deletions(-) diff --git a/include/labwc.h b/include/labwc.h index 4f7aafe2..ff74ef72 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -417,7 +417,7 @@ void view_update_title(struct view *view); void view_update_app_id(struct view *view); void view_impl_map(struct view *view); -void view_min_size(struct view *view, int *w, int *h); +void view_adjust_size(struct view *view, int *w, int *h); void foreign_toplevel_handle_create(struct view *view); diff --git a/src/cursor.c b/src/cursor.c index a91d091d..3f482831 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -136,32 +136,28 @@ process_cursor_resize(struct server *server, uint32_t time) .x = view->x, .y = view->y, .width = view->w, .height = view->h }; - int min_width, min_height; - view_min_size(view, &min_width, &min_height); + if (server->resize_edges & WLR_EDGE_TOP) + new_view_geo.height = server->grab_box.height - dy; + else if (server->resize_edges & WLR_EDGE_BOTTOM) + new_view_geo.height = server->grab_box.height + dy; + + if (server->resize_edges & WLR_EDGE_LEFT) + new_view_geo.width = server->grab_box.width - dx; + else if (server->resize_edges & WLR_EDGE_RIGHT) + new_view_geo.width = server->grab_box.width + dx; + + view_adjust_size(view, &new_view_geo.width, &new_view_geo.height); if (server->resize_edges & WLR_EDGE_TOP) { - if (server->grab_box.height - dy < min_height) { - dy = server->grab_box.height - min_height; - } - new_view_geo.y = server->grab_box.y + dy; - new_view_geo.height = server->grab_box.height - dy; - } else if (server->resize_edges & WLR_EDGE_BOTTOM) { - if (server->grab_box.height + dy < min_height) { - dy = min_height - server->grab_box.height; - } - new_view_geo.height = server->grab_box.height + dy; + // anchor bottom edge + new_view_geo.y = server->grab_box.y + + server->grab_box.height - new_view_geo.height; } + if (server->resize_edges & WLR_EDGE_LEFT) { - if (server->grab_box.width - dx < min_width) { - dx = server->grab_box.width - min_width; - } - new_view_geo.x = server->grab_box.x + dx; - new_view_geo.width = server->grab_box.width - dx; - } else if (server->resize_edges & WLR_EDGE_RIGHT) { - if (server->grab_box.width + dx < min_width) { - dx = min_width - server->grab_box.width; - } - new_view_geo.width = server->grab_box.width + dx; + // anchor right edge + new_view_geo.x = server->grab_box.x + + server->grab_box.width - new_view_geo.width; } resistance_resize_apply(view, &new_view_geo); diff --git a/src/view.c b/src/view.c index 5587b1dc..a101d97c 100644 --- a/src/view.c +++ b/src/view.c @@ -4,6 +4,8 @@ #include "labwc.h" #include "ssd.h" +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) + void view_set_activated(struct view *view, bool activated) { @@ -49,32 +51,37 @@ view_move_resize(struct view *view, struct wlr_box geo) #define MIN_VIEW_WIDTH (100) #define MIN_VIEW_HEIGHT (60) +#if HAVE_XWAYLAND +static int +round_to_increment(int val, int base, int inc) { + if (base < 0 || inc <= 0) + return val; + return base + (val - base + inc / 2) / inc * inc; +} +#endif + void -view_min_size(struct view *view, int *w, int *h) +view_adjust_size(struct view *view, int *w, int *h) { int min_width = MIN_VIEW_WIDTH; int min_height = MIN_VIEW_HEIGHT; #if HAVE_XWAYLAND - if (view->type != LAB_XWAYLAND_VIEW) { - goto out; - } - if (!view->xwayland_surface->size_hints) { - goto out; - } - if (view->xwayland_surface->size_hints->min_width > 0 - || view->xwayland_surface->size_hints->min_height > 0) { - min_width = view->xwayland_surface->size_hints->min_width; - min_height = view->xwayland_surface->size_hints->min_height; - } -out: -#endif + if (view->type == LAB_XWAYLAND_VIEW) { + struct wlr_xwayland_surface_size_hints *hints = + view->xwayland_surface->size_hints; + if (hints) { + *w = round_to_increment(*w, hints->base_width, + hints->width_inc); + *h = round_to_increment(*h, hints->base_height, + hints->height_inc); - if (w) { - *w = min_width; - } - if (h) { - *h = min_height; + min_width = MAX(1, hints->min_width); + min_height = MAX(1, hints->min_height); + } } +#endif + *w = MAX(*w, min_width); + *h = MAX(*h, min_height); } void diff --git a/src/xdg.c b/src/xdg.c index b66341fc..412e799b 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -183,19 +183,17 @@ handle_set_app_id(struct wl_listener *listener, void *data) view_update_app_id(view); } -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) static void xdg_toplevel_view_configure(struct view *view, struct wlr_box geo) { - int min_width, min_height; - view_min_size(view, &min_width, &min_height); + view_adjust_size(view, &geo.width, &geo.height); view->pending_move_resize.update_x = geo.x != view->x; view->pending_move_resize.update_y = geo.y != view->y; view->pending_move_resize.x = geo.x; view->pending_move_resize.y = geo.y; - view->pending_move_resize.width = MAX(geo.width, min_width); - view->pending_move_resize.height = MAX(geo.height, min_height); + view->pending_move_resize.width = geo.width; + view->pending_move_resize.height = geo.height; uint32_t serial = wlr_xdg_toplevel_set_size(view->xdg_surface, (uint32_t)geo.width, (uint32_t)geo.height); @@ -208,7 +206,6 @@ xdg_toplevel_view_configure(struct view *view, struct wlr_box geo) damage_all_outputs(view->server); } } -#undef MAX static void xdg_toplevel_view_move(struct view *view, double x, double y) diff --git a/src/xwayland.c b/src/xwayland.c index 9eaee138..3ad89a42 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -103,22 +103,20 @@ handle_destroy(struct wl_listener *listener, void *data) free(view); } -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) static void handle_request_configure(struct wl_listener *listener, void *data) { struct view *view = wl_container_of(listener, view, request_configure); struct wlr_xwayland_surface_configure_event *event = data; - int min_width, min_height; - view_min_size(view, &min_width, &min_height); + int width = event->width; + int height = event->height; + view_adjust_size(view, &width, &height); wlr_xwayland_surface_configure(view->xwayland_surface, - event->x, event->y, MAX(event->width, min_width), - MAX(event->height, min_height)); + event->x, event->y, width, height); damage_all_outputs(view->server); } -#undef MAX static void handle_request_activate(struct wl_listener *listener, void *data) @@ -170,26 +168,9 @@ handle_set_class(struct wl_listener *listener, void *data) view_update_app_id(view); } -static int -round_to_increment(int val, int base, int inc) { - if (base < 0 || inc <= 0) - return val; - return base + (val - base + inc / 2) / inc * inc; -} - static void configure(struct view *view, struct wlr_box geo) { - // honor size increments from WM_SIZE_HINTS - struct wlr_xwayland_surface_size_hints *hints = - view->xwayland_surface->size_hints; - if (hints) { - geo.width = round_to_increment(geo.width, - hints->base_width, hints->width_inc); - geo.height = round_to_increment(geo.height, - hints->base_height, hints->height_inc); - } - view->pending_move_resize.update_x = geo.x != view->x; view->pending_move_resize.update_y = geo.y != view->y; view->pending_move_resize.x = geo.x;