tinywl: stabilize resize from top-left edges

When resizing from the left or top edges, wait until the client
commits its resized buffer before updating the scene node position.

This keeps the unmoved edge anchored to the committed geometry instead
of the requested configure size.

This fixes visible jitter when resizing weston-terminal with the mouse
from the top-left corner, where the terminal can quantize its size and
otherwise cause the window position to oscillate during interactive resize.
This commit is contained in:
YaoBing Xiao 2026-06-06 16:36:52 +08:00
parent a94cd29eb1
commit 42f615fe60
No known key found for this signature in database
GPG key ID: E53D050E0BA828D3

View file

@ -399,6 +399,30 @@ static void process_cursor_move(struct tinywl_server *server) {
server->cursor->y - server->grab_y);
}
static void update_resize_position(struct tinywl_toplevel *toplevel) {
struct tinywl_server *server = toplevel->server;
if (server->cursor_mode != TINYWL_CURSOR_RESIZE ||
server->grabbed_toplevel != toplevel) {
return;
}
struct wlr_box *geo_box = &toplevel->xdg_toplevel->base->geometry;
int lx = server->grab_geobox.x;
int ly = server->grab_geobox.y;
if (server->resize_edges & WLR_EDGE_LEFT) {
lx = server->grab_geobox.x + server->grab_geobox.width -
geo_box->width;
}
if (server->resize_edges & WLR_EDGE_TOP) {
ly = server->grab_geobox.y + server->grab_geobox.height -
geo_box->height;
}
wlr_scene_node_set_position(&toplevel->scene_tree->node,
lx - geo_box->x, ly - geo_box->y);
}
static void process_cursor_resize(struct tinywl_server *server) {
/*
* Resizing the grabbed toplevel can be a little bit complicated, because we
@ -406,9 +430,8 @@ static void process_cursor_resize(struct tinywl_server *server) {
* toplevel on one or two axes, but can also move the toplevel if you resize
* from the top or left edges (or top-left corner).
*
* Note that some shortcuts are taken here. In a more fleshed-out
* compositor, you'd wait for the client to prepare a buffer at the new
* size, then commit any movement that was prepared.
* Movement is applied on commit so that surfaces which quantize their size
* can keep the unmoved edge stable.
*/
struct tinywl_toplevel *toplevel = server->grabbed_toplevel;
double border_x = server->cursor->x - server->grab_x;
@ -441,10 +464,6 @@ static void process_cursor_resize(struct tinywl_server *server) {
}
}
struct wlr_box *geo_box = &toplevel->xdg_toplevel->base->geometry;
wlr_scene_node_set_position(&toplevel->scene_tree->node,
new_left - geo_box->x, new_top - geo_box->y);
int new_width = new_right - new_left;
int new_height = new_bottom - new_top;
wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel, new_width, new_height);
@ -701,7 +720,10 @@ static void xdg_toplevel_commit(struct wl_listener *listener, void *data) {
* configures the xdg_toplevel with 0,0 size to let the client pick the
* dimensions itself. */
wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel, 0, 0);
return;
}
update_resize_position(toplevel);
}
static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) {