mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 10:00:45 -05:00
wayland: Allow XDnD with other devices than the pointer
While every kind of input is seen as coming from the Virtual Core Pointer in the X11 case, we can largely abstract away from that fact, and lock XDnD pointer input to the most plausible source (e.g. a device with a pressed button), instead of only working with pointer input. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3420>
This commit is contained in:
parent
b09374735b
commit
c931ed0d81
@ -334,6 +334,16 @@ meta_wayland_drag_grab_get_seat (MetaWaylandDragGrab *drag_grab)
|
||||
return drag_grab->seat;
|
||||
}
|
||||
|
||||
ClutterInputDevice *
|
||||
meta_wayland_drag_grab_get_device (MetaWaylandDragGrab *drag_grab,
|
||||
ClutterEventSequence **sequence)
|
||||
{
|
||||
if (sequence)
|
||||
*sequence = drag_grab->sequence;
|
||||
|
||||
return drag_grab->device;
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_update_user_dnd_action (MetaWaylandDataSource *source,
|
||||
ClutterModifierType modifiers)
|
||||
|
@ -94,3 +94,6 @@ void meta_wayland_drag_grab_update_feedback_actor (MetaWaylandDragGrab *drag
|
||||
const ClutterEvent *event);
|
||||
|
||||
MetaWaylandSeat * meta_wayland_drag_grab_get_seat (MetaWaylandDragGrab *drag_grab);
|
||||
|
||||
ClutterInputDevice * meta_wayland_drag_grab_get_device (MetaWaylandDragGrab *drag_grab,
|
||||
ClutterEventSequence **sequence);
|
||||
|
@ -67,6 +67,17 @@ struct _MetaXWaylandDnd
|
||||
int current_dnd_window;
|
||||
};
|
||||
|
||||
typedef struct _DndCandidateDevice DndCandidateDevice;
|
||||
|
||||
struct _DndCandidateDevice
|
||||
{
|
||||
MetaWaylandSeat *seat;
|
||||
ClutterInputDevice *device;
|
||||
ClutterEventSequence *sequence;
|
||||
MetaWaylandSurface *focus;
|
||||
graphene_point_t pos;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ATOM_DND_SELECTION,
|
||||
@ -669,10 +680,15 @@ meta_x11_drag_dest_update (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandSeat *seat = meta_wayland_data_device_get_seat (data_device);
|
||||
MetaWaylandCompositor *compositor = meta_wayland_seat_get_compositor (seat);
|
||||
MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd;
|
||||
MetaWaylandDragGrab *drag_grab = compositor->seat->data_device.current_grab;
|
||||
ClutterInputDevice *device;
|
||||
ClutterEventSequence *sequence;
|
||||
graphene_point_t pos;
|
||||
|
||||
clutter_seat_query_state (clutter_input_device_get_seat (seat->pointer->device),
|
||||
seat->pointer->device, NULL, &pos, NULL);
|
||||
device = meta_wayland_drag_grab_get_device (drag_grab, &sequence);
|
||||
|
||||
clutter_seat_query_state (clutter_input_device_get_seat (device),
|
||||
device, sequence, &pos, NULL);
|
||||
xdnd_send_position (dnd, dnd->dnd_dest,
|
||||
clutter_get_current_event_time (),
|
||||
pos.x, pos.y);
|
||||
@ -892,7 +908,12 @@ drag_xgrab_release (MetaWaylandEventHandler *handler,
|
||||
|
||||
data_source = compositor->seat->data_device.dnd_data_source;
|
||||
|
||||
if (seat->pointer->button_count == 0 &&
|
||||
if (__builtin_popcount (clutter_event_get_state (event) &
|
||||
(CLUTTER_BUTTON1_MASK |
|
||||
CLUTTER_BUTTON2_MASK |
|
||||
CLUTTER_BUTTON3_MASK |
|
||||
CLUTTER_BUTTON4_MASK |
|
||||
CLUTTER_BUTTON5_MASK)) <= 1 &&
|
||||
(!meta_wayland_drag_grab_get_focus (drag_grab) ||
|
||||
meta_wayland_data_source_get_current_action (data_source) ==
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE))
|
||||
@ -1031,13 +1052,17 @@ meta_xwayland_dnd_handle_client_message (MetaWaylandCompositor *compositor,
|
||||
}
|
||||
else if (event->message_type == xdnd_atoms[ATOM_DND_POSITION])
|
||||
{
|
||||
ClutterInputDevice *device;
|
||||
ClutterEventSequence *sequence;
|
||||
graphene_point_t pos;
|
||||
uint32_t action = 0;
|
||||
|
||||
dnd->client_message_timestamp = event->data.l[3];
|
||||
|
||||
clutter_seat_query_state (clutter_input_device_get_seat (seat->pointer->device),
|
||||
seat->pointer->device, NULL, &pos, NULL);
|
||||
device = meta_wayland_drag_grab_get_device (drag_grab, &sequence);
|
||||
|
||||
clutter_seat_query_state (clutter_input_device_get_seat (device),
|
||||
device, sequence, &pos, NULL);
|
||||
|
||||
action = atom_to_action ((Atom) event->data.l[4]);
|
||||
meta_wayland_data_source_set_user_action (dnd->source, action);
|
||||
@ -1066,6 +1091,42 @@ meta_xwayland_dnd_handle_client_message (MetaWaylandCompositor *compositor,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
find_dnd_candidate_device (ClutterStage *stage,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
gpointer user_data)
|
||||
{
|
||||
DndCandidateDevice *candidate = user_data;
|
||||
graphene_point_t pos;
|
||||
ClutterModifierType modifiers;
|
||||
MetaWaylandSurface *focus;
|
||||
|
||||
clutter_seat_query_state (clutter_input_device_get_seat (device),
|
||||
device, sequence, &pos, &modifiers);
|
||||
|
||||
if (!sequence)
|
||||
{
|
||||
if (modifiers &
|
||||
(CLUTTER_BUTTON1_MASK | CLUTTER_BUTTON2_MASK |
|
||||
CLUTTER_BUTTON3_MASK | CLUTTER_BUTTON4_MASK |
|
||||
CLUTTER_BUTTON5_MASK))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
focus = meta_wayland_seat_get_current_surface (candidate->seat,
|
||||
device, sequence);
|
||||
if (!focus || !meta_wayland_surface_is_xwayland (focus))
|
||||
return TRUE;
|
||||
|
||||
candidate->device = device;
|
||||
candidate->sequence = sequence;
|
||||
candidate->pos = pos;
|
||||
candidate->focus = focus;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_xwayland_dnd_handle_xfixes_selection_notify (MetaWaylandCompositor *compositor,
|
||||
XEvent *xevent)
|
||||
@ -1075,42 +1136,33 @@ meta_xwayland_dnd_handle_xfixes_selection_notify (MetaWaylandCompositor *composi
|
||||
MetaWaylandSeat *seat = compositor->seat;
|
||||
MetaWaylandDataDevice *data_device = &seat->data_device;
|
||||
MetaX11Display *x11_display = x11_display_from_dnd (dnd);
|
||||
MetaWaylandSurface *focus;
|
||||
MetaContext *context = meta_wayland_compositor_get_context (compositor);
|
||||
MetaBackend *backend = meta_context_get_backend (context);
|
||||
ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
|
||||
DndCandidateDevice candidate = { seat, };
|
||||
|
||||
if (event->selection != xdnd_atoms[ATOM_DND_SELECTION])
|
||||
return FALSE;
|
||||
|
||||
dnd->owner = event->owner;
|
||||
focus = compositor->seat->pointer->focus_surface;
|
||||
|
||||
if (event->owner != None && event->owner != x11_display->selection.xwindow &&
|
||||
focus && meta_wayland_surface_is_xwayland (focus))
|
||||
!clutter_stage_pointing_input_foreach (stage, find_dnd_candidate_device,
|
||||
&candidate))
|
||||
{
|
||||
graphene_point_t pos;
|
||||
ClutterModifierType modifiers;
|
||||
|
||||
dnd->source = meta_wayland_data_source_xwayland_new (dnd, compositor);
|
||||
meta_wayland_data_device_set_dnd_source (&compositor->seat->data_device,
|
||||
dnd->source);
|
||||
|
||||
clutter_seat_query_state (clutter_input_device_get_seat (seat->pointer->device),
|
||||
seat->pointer->device, NULL, &pos, &modifiers);
|
||||
|
||||
if (modifiers &
|
||||
(CLUTTER_BUTTON1_MASK |
|
||||
CLUTTER_BUTTON2_MASK |
|
||||
CLUTTER_BUTTON3_MASK |
|
||||
CLUTTER_BUTTON4_MASK |
|
||||
CLUTTER_BUTTON5_MASK))
|
||||
{
|
||||
meta_wayland_data_device_start_drag (data_device,
|
||||
wl_resource_get_client (focus->resource),
|
||||
wl_resource_get_client (candidate.focus->resource),
|
||||
&xdnd_event_interface,
|
||||
focus, dnd->source,
|
||||
candidate.focus, dnd->source,
|
||||
NULL,
|
||||
seat->pointer->device, NULL,
|
||||
pos);
|
||||
}
|
||||
candidate.device,
|
||||
candidate.sequence,
|
||||
candidate.pos);
|
||||
}
|
||||
else if (event->owner == None)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user