cursor: Fix "jumping opposite edges" issue when resizing.

Commit ec68806354 ("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.
This commit is contained in:
John Lindgren 2022-04-02 21:34:51 -04:00 committed by Johan Malm
parent ec68806354
commit a50d27c770
5 changed files with 52 additions and 71 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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)

View file

@ -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;