window: Do not go past size hints on resize

On interactive resize, mutter calculates the difference in size based on
the pointer location and relies on window constraints to ensure the
minimum size is honored.

Wayland however does asynchronous window configuration, meaning that not
checking for size hints early enough may lead to the window moving as
the locations was initially computed on a size which will be invalidate
by the client eventually.

Make sure to respect the client size hint on update_resize() so that we
don't end up with a window moving unexpectedly when the client
eventually acked the configuration.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1495
This commit is contained in:
Olivier Fourdan 2020-10-13 17:59:38 +02:00
parent 554f7984e9
commit 03c69ed8cf

View File

@ -6248,9 +6248,9 @@ update_resize (MetaWindow *window,
gboolean force) gboolean force)
{ {
int dx, dy; int dx, dy;
int new_w, new_h;
MetaGravity gravity; MetaGravity gravity;
MetaRectangle old; MetaRectangle new_rect;
MetaRectangle old_rect;
double remaining = 0; double remaining = 0;
window->display->grab_latest_motion_x = x; window->display->grab_latest_motion_x = x;
@ -6269,8 +6269,8 @@ update_resize (MetaWindow *window,
dy *= 2; dy *= 2;
} }
new_w = window->display->grab_anchor_window_pos.width; new_rect.width = window->display->grab_anchor_window_pos.width;
new_h = window->display->grab_anchor_window_pos.height; new_rect.height = window->display->grab_anchor_window_pos.height;
/* Don't bother doing anything if no move has been specified. (This /* Don't bother doing anything if no move has been specified. (This
* happens often, even in keyboard resizing, due to the warping of the * happens often, even in keyboard resizing, due to the warping of the
@ -6299,14 +6299,16 @@ update_resize (MetaWindow *window,
} }
if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_EAST) if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_EAST)
new_w += dx; new_rect.width += dx;
else if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_WEST) else if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_WEST)
new_w -= dx; new_rect.width -= dx;
if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_SOUTH) if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_SOUTH)
new_h += dy; new_rect.height += dy;
else if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_NORTH) else if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_NORTH)
new_h -= dy; new_rect.height -= dy;
ensure_size_hints_satisfied (&new_rect, &window->size_hints);
/* If we're waiting for a request for _NET_WM_SYNC_REQUEST, we'll /* If we're waiting for a request for _NET_WM_SYNC_REQUEST, we'll
* resize the window when the window responds, or when we time * resize the window when the window responds, or when we time
@ -6336,7 +6338,7 @@ update_resize (MetaWindow *window,
/* Remove any scheduled compensation events */ /* Remove any scheduled compensation events */
g_clear_handle_id (&window->display->grab_resize_timeout_id, g_source_remove); g_clear_handle_id (&window->display->grab_resize_timeout_id, g_source_remove);
meta_window_get_frame_rect (window, &old); meta_window_get_frame_rect (window, &old_rect);
/* One sided resizing ought to actually be one-sided, despite the fact that /* One sided resizing ought to actually be one-sided, despite the fact that
* aspect ratio windows don't interact nicely with the above stuff. So, * aspect ratio windows don't interact nicely with the above stuff. So,
@ -6344,10 +6346,10 @@ update_resize (MetaWindow *window,
*/ */
if ((window->display->grab_op & (META_GRAB_OP_WINDOW_DIR_WEST | META_GRAB_OP_WINDOW_DIR_EAST)) == 0) if ((window->display->grab_op & (META_GRAB_OP_WINDOW_DIR_WEST | META_GRAB_OP_WINDOW_DIR_EAST)) == 0)
new_w = old.width; new_rect.width = old_rect.width;
if ((window->display->grab_op & (META_GRAB_OP_WINDOW_DIR_NORTH | META_GRAB_OP_WINDOW_DIR_SOUTH)) == 0) if ((window->display->grab_op & (META_GRAB_OP_WINDOW_DIR_NORTH | META_GRAB_OP_WINDOW_DIR_SOUTH)) == 0)
new_h = old.height; new_rect.height = old_rect.height;
/* compute gravity of client during operation */ /* compute gravity of client during operation */
gravity = meta_resize_gravity_from_grab_op (window->display->grab_op); gravity = meta_resize_gravity_from_grab_op (window->display->grab_op);
@ -6355,16 +6357,19 @@ update_resize (MetaWindow *window,
/* Do any edge resistance/snapping */ /* Do any edge resistance/snapping */
meta_window_edge_resistance_for_resize (window, meta_window_edge_resistance_for_resize (window,
&new_w, &new_rect.width,
&new_h, &new_rect.height,
gravity, gravity,
update_resize_timeout, update_resize_timeout,
flags); flags);
meta_window_resize_frame_with_gravity (window, TRUE, new_w, new_h, gravity); meta_window_resize_frame_with_gravity (window, TRUE,
new_rect.width, new_rect.height,
gravity);
/* Store the latest resize time, if we actually resized. */ /* Store the latest resize time, if we actually resized. */
if (window->rect.width != old.width || window->rect.height != old.height) if (window->rect.width != old_rect.width ||
window->rect.height != old_rect.height)
window->display->grab_last_moveresize_time = g_get_real_time (); window->display->grab_last_moveresize_time = g_get_real_time ();
} }