compositor: Use relative anchor coordinates for window drags

The anchor position calculations are somewhat unnecessarily complex
based on root coordinates of pointer and frame positions. This requires
tracking both things, and we don't always get it quite right with the
latter (e.g. window repositions, resizes or overshrinks, leaving the
anchor position visually outside the window).

In order to improve this, capture the window-relative coordinates
when starting the window drag, and ensure the window is always repositioned
in that position, relative to its current size.

This avoids these glitches when unmaximizing a window (e.g. dragged from
the bottom through super+button1 press), or moving windows between monitors
with different scales.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2730
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2942>
This commit is contained in:
Carlos Garnacho 2023-03-29 16:03:49 +02:00 committed by Marge Bot
parent 179124dc61
commit 7eb0130425

View File

@ -57,6 +57,8 @@ struct _MetaWindowDrag {
ClutterInputDevice *leading_device;
ClutterEventSequence *leading_touch_sequence;
double anchor_rel_x;
double anchor_rel_y;
int anchor_root_x;
int anchor_root_y;
MetaRectangle anchor_window_pos;
@ -1188,7 +1190,7 @@ update_move (MetaWindowDrag *window_drag,
MetaWindow *window;
int dx, dy;
int new_x, new_y;
MetaRectangle old;
MetaRectangle old, frame_rect;
int shake_threshold;
window = window_drag->effective_grab_window;
@ -1203,15 +1205,16 @@ update_move (MetaWindowDrag *window_drag,
dx = x - window_drag->anchor_root_x;
dy = y - window_drag->anchor_root_y;
new_x = window_drag->anchor_window_pos.x + dx;
new_y = window_drag->anchor_window_pos.y + dy;
meta_window_get_frame_rect (window, &frame_rect);
new_x = x - (frame_rect.width * window_drag->anchor_rel_x);
new_y = y - (frame_rect.height * window_drag->anchor_rel_y);
meta_verbose ("x,y = %d,%d anchor ptr %d,%d anchor pos %d,%d dx,dy %d,%d",
meta_verbose ("x,y = %d,%d anchor ptr %d,%d rel anchor pos %f,%f dx,dy %d,%d",
x, y,
window_drag->anchor_root_x,
window_drag->anchor_root_y,
window_drag->anchor_window_pos.x,
window_drag->anchor_window_pos.y,
window_drag->anchor_rel_x,
window_drag->anchor_rel_y,
dx, dy);
/* Don't bother doing anything if no move has been specified. (This
@ -1879,6 +1882,15 @@ meta_window_drag_begin (MetaWindowDrag *window_drag,
&window_drag->initial_window_pos);
window_drag->anchor_window_pos = window_drag->initial_window_pos;
window_drag->anchor_rel_x =
CLAMP ((double) (root_x - window_drag->initial_window_pos.x) /
window_drag->initial_window_pos.width,
0, 1);
window_drag->anchor_rel_y =
CLAMP ((double) (root_y - window_drag->initial_window_pos.y) /
window_drag->initial_window_pos.height,
0, 1);
if (meta_is_wayland_compositor ())
{
meta_display_sync_wayland_input_focus (display);