x11: Find nearest input affecting _NET_WM_MOVERESIZE X11 requests on Wayland
The _NET_WM protocol, written before the birth of XInput 2.x, does have no notion of different input devices whatsoever. Anyways, in a X11 session it is safe to assume this refers about the Virtual Core Pointer since every input device by default drives it (incl. touchscreens through the "pointer emulating sequence", and styli). This assumption falls apart in a Wayland session with non-pointer input, since we do actually distinguish between all the distinct pointer devices and touchpoints, and do not let them emulate mouse input. We do need to specify a device/sequence there to drive the window move/resize operation. The _NET_WM_MOVERESIZE message just gives us the x/y root coordinates the resize was started from, so work from there into guessing what is the most likely device/sequence that did trigger the request on the client side. Conversely, on Wayland we do not need to check for possible race conditions in the pressed button states since we have larger guarantees about not missing these events if we checked for the button modifier mask beforehand, so make that race condition check specific to the X11 sessions. Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2836 Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3059>
This commit is contained in:
parent
4269f85bcc
commit
af10ead918
@ -3022,6 +3022,96 @@ handle_net_restack_window (MetaDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_XWAYLAND
|
||||
typedef struct {
|
||||
ClutterInputDevice *device;
|
||||
ClutterEventSequence *sequence;
|
||||
graphene_point_t device_point;
|
||||
graphene_point_t coords;
|
||||
int button;
|
||||
} NearestDeviceData;
|
||||
|
||||
static gboolean
|
||||
nearest_device_func (ClutterStage *stage,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
gpointer user_data)
|
||||
{
|
||||
NearestDeviceData *data = user_data;
|
||||
graphene_point_t point;
|
||||
ClutterModifierType mods;
|
||||
const int nearest_threshold = 64;
|
||||
|
||||
clutter_seat_query_state (clutter_input_device_get_seat (device),
|
||||
device,
|
||||
sequence,
|
||||
&point,
|
||||
&mods);
|
||||
|
||||
if (!sequence)
|
||||
{
|
||||
ClutterModifierType accepted_buttons = 0;
|
||||
ClutterModifierType mask =
|
||||
(CLUTTER_BUTTON1_MASK | CLUTTER_BUTTON2_MASK |
|
||||
CLUTTER_BUTTON3_MASK | CLUTTER_BUTTON4_MASK |
|
||||
CLUTTER_BUTTON5_MASK);
|
||||
|
||||
if (data->button != 0)
|
||||
accepted_buttons = (CLUTTER_BUTTON1_MASK << (data->button - 1)) & mask;
|
||||
else
|
||||
accepted_buttons = mask;
|
||||
|
||||
/* Check that pointers have any of the relevant buttons pressed */
|
||||
if (!(mods & accepted_buttons))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (ABS (point.x - data->coords.x) < nearest_threshold &&
|
||||
ABS (point.y - data->coords.y) < nearest_threshold &&
|
||||
(!data->device ||
|
||||
(ABS (point.x - data->coords.x) < ABS (data->device_point.x - data->coords.x) &&
|
||||
ABS (point.y - data->coords.y) < ABS (data->device_point.y - data->coords.y))))
|
||||
{
|
||||
data->device = device;
|
||||
data->sequence = sequence;
|
||||
data->device_point = point;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
guess_nearest_device (MetaWindow *window,
|
||||
int root_x,
|
||||
int root_y,
|
||||
int button,
|
||||
ClutterInputDevice **device,
|
||||
ClutterEventSequence **sequence)
|
||||
{
|
||||
MetaDisplay *display = meta_window_get_display (window);
|
||||
MetaContext *context = meta_display_get_context (display);
|
||||
MetaBackend *backend = meta_context_get_backend (context);
|
||||
ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
|
||||
NearestDeviceData data = { 0, };
|
||||
|
||||
data.button = button;
|
||||
graphene_point_init (&data.coords, root_x, root_y);
|
||||
clutter_stage_pointing_input_foreach (stage,
|
||||
nearest_device_func,
|
||||
&data);
|
||||
|
||||
if (!data.device)
|
||||
return FALSE;
|
||||
|
||||
if (device && data.device)
|
||||
*device = data.device;
|
||||
if (sequence && data.sequence)
|
||||
*sequence = data.sequence;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* HAVE_XWAYLAND */
|
||||
|
||||
gboolean
|
||||
meta_window_x11_client_message (MetaWindow *window,
|
||||
XEvent *event)
|
||||
@ -3325,11 +3415,10 @@ meta_window_x11_client_message (MetaWindow *window,
|
||||
break;
|
||||
}
|
||||
|
||||
window_drag =
|
||||
meta_compositor_get_current_window_drag (window->display->compositor);
|
||||
|
||||
if (action == _NET_WM_MOVERESIZE_CANCEL)
|
||||
{
|
||||
window_drag =
|
||||
meta_compositor_get_current_window_drag (window->display->compositor);
|
||||
if (window_drag)
|
||||
meta_window_drag_end (window_drag);
|
||||
}
|
||||
@ -3357,15 +3446,38 @@ meta_window_x11_client_message (MetaWindow *window,
|
||||
MetaBackend *backend = meta_context_get_backend (context);
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend);
|
||||
ClutterInputDevice *device = NULL;
|
||||
ClutterEventSequence *sequence = NULL;
|
||||
int button_mask;
|
||||
|
||||
#ifdef HAVE_XWAYLAND
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
if (!guess_nearest_device (window, x_root, y_root, button,
|
||||
&device, &sequence))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
device = clutter_seat_get_pointer (seat);
|
||||
sequence = NULL;
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Beginning move/resize with button = %d", button);
|
||||
meta_window_begin_grab_op (window, op,
|
||||
clutter_seat_get_pointer (seat),
|
||||
NULL,
|
||||
device,
|
||||
sequence,
|
||||
timestamp);
|
||||
|
||||
window_drag =
|
||||
meta_compositor_get_current_window_drag (window->display->compositor);
|
||||
|
||||
#ifdef HAVE_XWAYLAND
|
||||
if (!meta_is_wayland_compositor ())
|
||||
#endif
|
||||
{
|
||||
button_mask = query_pressed_buttons (window);
|
||||
|
||||
if (button == 0)
|
||||
@ -3402,6 +3514,7 @@ meta_window_x11_client_message (MetaWindow *window,
|
||||
meta_window_drag_end (window_drag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user