1
0
Fork 0

wayland: Port drag and drop to MetaWaylandEventInterface

This collection of event handlers is the most special of them all, as
they want to unset any pointer/touch/stylus/keyboard/pad/etc focus,
and handle events from a selected device/sequence combination through
the MetaWaylandDragDest interfaces.

The same interfaces also replace the MetaWaylandKeyboardGrabInterface
in effect that handled DnD action changes.

On the XDnD special grab side, we mainly need to let the current
client (i.e. the drag source) keep receiving input events, as they
drive the DnD operation from the X11 realm.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3420>
This commit is contained in:
Carlos Garnacho 2023-11-16 12:05:18 +01:00 committed by Robert Mader
parent 5ade2060a7
commit 5fa112c298
3 changed files with 323 additions and 195 deletions

View file

@ -131,9 +131,10 @@ create_and_send_dnd_offer (MetaWaylandDataSource *source,
}
struct _MetaWaylandDragGrab {
MetaWaylandPointerGrab generic;
MetaWaylandEventHandler *handler;
MetaWaylandKeyboardGrab keyboard_grab;
ClutterInputDevice *device;
ClutterEventSequence *sequence;
MetaWaylandSeat *seat;
struct wl_client *drag_client;
@ -327,13 +328,10 @@ meta_wayland_drag_grab_update_feedback_actor (MetaWaylandDragGrab *drag_grab,
event);
}
static void
drag_grab_focus (MetaWaylandPointerGrab *grab,
MetaWaylandSurface *surface)
MetaWaylandSeat *
meta_wayland_drag_grab_get_seat (MetaWaylandDragGrab *drag_grab)
{
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
meta_wayland_drag_grab_set_focus (drag_grab, surface);
return drag_grab->seat;
}
static void
@ -352,27 +350,6 @@ data_source_update_user_dnd_action (MetaWaylandDataSource *source,
meta_wayland_data_source_set_user_action (source, user_dnd_action);
}
static void
drag_grab_motion (MetaWaylandPointerGrab *grab,
const ClutterEvent *event)
{
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
graphene_point_t point;
uint32_t time_ms;
if (drag_grab->drag_focus)
{
clutter_event_get_coords (event, &point.x, &point.y);
time_ms = clutter_event_get_time (event);
meta_wayland_surface_drag_dest_motion (drag_grab->drag_focus,
point.x, point.y, time_ms);
}
if (drag_grab->drag_surface)
meta_feedback_actor_update (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
event);
}
static void
data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
{
@ -401,17 +378,13 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
drag_grab->seat->data_device.current_grab = NULL;
/* There might be other grabs created in result to DnD actions like popups
* on "ask" actions, we must not reset those, only our own.
*/
if (drag_grab->generic.pointer->grab == (MetaWaylandPointerGrab *) drag_grab)
if (drag_grab->handler)
{
MetaWaylandCompositor *wayland_compositor =
meta_wayland_seat_get_compositor (data_device->seat);
MetaWaylandInput *input;
meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
meta_wayland_keyboard_end_grab (drag_grab->keyboard_grab.keyboard);
meta_wayland_compositor_sync_focus (wayland_compositor);
input = meta_wayland_seat_get_input (data_device->seat);
meta_wayland_input_detach_event_handler (input, drag_grab->handler);
drag_grab->handler = NULL;
}
g_free (drag_grab);
@ -460,76 +433,140 @@ meta_wayland_data_source_fake_read (MetaWaylandDataSource *source,
g_io_add_watch (channel, G_IO_HUP, on_fake_read_hup, source);
}
static void
drag_grab_button (MetaWaylandPointerGrab *grab,
const ClutterEvent *event)
static MetaWaylandSurface *
drag_grab_get_focus_surface (MetaWaylandEventHandler *handler,
ClutterInputDevice *device,
ClutterEventSequence *sequence,
gpointer user_data)
{
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
MetaWaylandSeat *seat = drag_grab->seat;
ClutterEventType event_type = clutter_event_type (event);
MetaWaylandDragGrab *drag_grab = user_data;
if (drag_grab->generic.pointer->grab_button ==
clutter_event_get_button (event) &&
event_type == CLUTTER_BUTTON_RELEASE)
{
MetaWaylandDataSource *source = drag_grab->drag_data_source;
gboolean success;
if (device != drag_grab->device ||
sequence != drag_grab->sequence)
return NULL;
if (drag_grab->drag_focus && source &&
meta_wayland_data_source_has_target (source) &&
meta_wayland_data_source_get_current_action (source))
{
meta_wayland_surface_drag_dest_drop (drag_grab->drag_focus);
meta_wayland_data_source_notify_drop_performed (source);
meta_wayland_data_source_update_in_ask (source);
success = TRUE;
}
else if (!drag_grab->drag_focus && source &&
meta_wayland_data_source_has_target (source) &&
meta_wayland_data_source_get_current_action (source) &&
meta_wayland_data_source_has_mime_type (source,
ROOTWINDOW_DROP_MIME))
{
/* Perform a fake read, that will lead to notify_finish() being called */
meta_wayland_data_source_fake_read (source, ROOTWINDOW_DROP_MIME);
success = TRUE;
}
else
{
if (source)
meta_wayland_data_source_set_current_offer (source, NULL);
meta_wayland_data_device_set_dnd_source (&seat->data_device, NULL);
unset_selection_source (&seat->data_device, META_SELECTION_DND);
success = FALSE;
}
/* Finish drag and let actor self-destruct */
meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor),
success);
drag_grab->feedback_actor = NULL;
}
if (seat->pointer->button_count == 0 &&
event_type == CLUTTER_BUTTON_RELEASE)
data_device_end_drag_grab (drag_grab);
return meta_wayland_event_handler_chain_up_get_focus_surface (handler,
device,
sequence);
}
static const MetaWaylandPointerGrabInterface drag_grab_interface = {
drag_grab_focus,
drag_grab_motion,
drag_grab_button,
};
static void
drag_grab_focus (MetaWaylandEventHandler *handler,
ClutterInputDevice *device,
ClutterEventSequence *sequence,
MetaWaylandSurface *surface,
gpointer user_data)
{
MetaWaylandDragGrab *drag_grab = user_data;
meta_wayland_event_handler_chain_up_focus (handler, device, sequence, NULL);
if (device == drag_grab->device &&
sequence == drag_grab->sequence)
meta_wayland_drag_grab_set_focus (drag_grab, surface);
}
static gboolean
keyboard_drag_grab_key (MetaWaylandKeyboardGrab *grab,
const ClutterEvent *event)
drag_grab_motion (MetaWaylandEventHandler *handler,
const ClutterEvent *event,
gpointer user_data)
{
MetaWaylandDragGrab *drag_grab = user_data;
graphene_point_t point;
uint32_t time_ms;
if (drag_grab->device != clutter_event_get_device (event) ||
drag_grab->sequence != clutter_event_get_event_sequence (event))
return CLUTTER_EVENT_STOP;
if (drag_grab->drag_focus)
{
clutter_event_get_coords (event, &point.x, &point.y);
time_ms = clutter_event_get_time (event);
meta_wayland_surface_drag_dest_motion (drag_grab->drag_focus,
point.x, point.y, time_ms);
}
if (drag_grab->drag_surface)
{
meta_feedback_actor_update (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
event);
}
return CLUTTER_EVENT_STOP;
}
static gboolean
drag_grab_release (MetaWaylandEventHandler *handler,
const ClutterEvent *event,
gpointer user_data)
{
MetaWaylandDragGrab *drag_grab = user_data;
MetaWaylandSeat *seat = drag_grab->seat;
MetaWaylandDataSource *source = drag_grab->drag_data_source;
gboolean success;
if (drag_grab->device != clutter_event_get_device (event) ||
drag_grab->sequence != clutter_event_get_event_sequence (event))
return CLUTTER_EVENT_STOP;
if (__builtin_popcount (clutter_event_get_state (event) &
(CLUTTER_BUTTON1_MASK |
CLUTTER_BUTTON2_MASK |
CLUTTER_BUTTON3_MASK |
CLUTTER_BUTTON4_MASK |
CLUTTER_BUTTON5_MASK)) > 1)
return CLUTTER_EVENT_STOP;
if (drag_grab->drag_focus && source &&
meta_wayland_data_source_has_target (source) &&
meta_wayland_data_source_get_current_action (source))
{
meta_wayland_surface_drag_dest_drop (drag_grab->drag_focus);
meta_wayland_data_source_notify_drop_performed (source);
meta_wayland_data_source_update_in_ask (source);
success = TRUE;
}
else if (!drag_grab->drag_focus && source &&
meta_wayland_data_source_has_target (source) &&
meta_wayland_data_source_get_current_action (source) &&
meta_wayland_data_source_has_mime_type (source,
ROOTWINDOW_DROP_MIME))
{
/* Perform a fake read, that will lead to notify_finish() being called */
meta_wayland_data_source_fake_read (source, ROOTWINDOW_DROP_MIME);
success = TRUE;
}
else
{
if (source)
meta_wayland_data_source_set_current_offer (source, NULL);
meta_wayland_data_device_set_dnd_source (&seat->data_device, NULL);
unset_selection_source (&seat->data_device, META_SELECTION_DND);
success = FALSE;
}
/* Finish drag and let actor self-destruct */
meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor),
success);
drag_grab->feedback_actor = NULL;
data_device_end_drag_grab (drag_grab);
return CLUTTER_EVENT_STOP;
}
static gboolean
drag_grab_key (MetaWaylandEventHandler *handler,
const ClutterEvent *event,
gpointer user_data)
{
MetaWaylandDragGrab *drag_grab = user_data;
ClutterModifierType modifiers;
if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_Escape)
{
MetaWaylandDragGrab *drag_grab;
drag_grab = wl_container_of (grab, drag_grab, keyboard_grab);
meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device,
NULL);
unset_selection_source (&drag_grab->seat->data_device, META_SELECTION_DND);
@ -539,38 +576,40 @@ keyboard_drag_grab_key (MetaWaylandKeyboardGrab *grab,
FALSE);
drag_grab->feedback_actor = NULL;
data_device_end_drag_grab (drag_grab);
return TRUE;
}
return FALSE;
}
static void
keyboard_drag_grab_modifiers (MetaWaylandKeyboardGrab *grab,
ClutterModifierType modifiers)
{
MetaWaylandDragGrab *drag_grab;
drag_grab = wl_container_of (grab, drag_grab, keyboard_grab);
/* The modifiers here just contain keyboard modifiers, mix it with the
* mouse button modifiers we got when starting the drag operation.
*/
modifiers |= drag_grab->buttons;
if (drag_grab->drag_data_source)
else if (clutter_seat_query_state (clutter_input_device_get_seat (drag_grab->device),
drag_grab->device,
drag_grab->sequence,
NULL,
&modifiers) &&
drag_grab->drag_data_source &&
clutter_event_get_state (event) != modifiers)
{
data_source_update_user_dnd_action (drag_grab->drag_data_source, modifiers);
if (drag_grab->drag_focus)
meta_wayland_surface_drag_dest_update (drag_grab->drag_focus);
}
return CLUTTER_EVENT_STOP;
}
static const MetaWaylandKeyboardGrabInterface keyboard_drag_grab_interface = {
keyboard_drag_grab_key,
keyboard_drag_grab_modifiers
static gboolean
drag_grab_discard_event (MetaWaylandEventHandler *handler,
const ClutterEvent *event,
gpointer user_data)
{
return CLUTTER_EVENT_STOP;
}
static const MetaWaylandEventInterface dnd_event_interface = {
drag_grab_get_focus_surface,
drag_grab_focus,
drag_grab_motion,
drag_grab_discard_event, /* press */
drag_grab_release,
drag_grab_key,
drag_grab_discard_event, /* other */
};
static void
@ -612,30 +651,31 @@ destroy_data_device_icon (struct wl_listener *listener,
}
void
meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device,
struct wl_client *client,
const MetaWaylandPointerGrabInterface *funcs,
MetaWaylandSurface *surface,
MetaWaylandDataSource *source,
MetaWaylandSurface *icon_surface)
meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device,
struct wl_client *client,
const MetaWaylandEventInterface *event_iface,
MetaWaylandSurface *surface,
MetaWaylandDataSource *source,
MetaWaylandSurface *icon_surface,
ClutterInputDevice *device,
ClutterEventSequence *sequence,
graphene_point_t drag_start)
{
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
MetaWaylandDragGrab *drag_grab;
graphene_point_t pos, surface_pos;
ClutterModifierType modifiers;
MetaSurfaceActor *surface_actor;
MetaWaylandInput *input;
data_device->current_grab = drag_grab = g_new0 (MetaWaylandDragGrab, 1);
drag_grab->generic.interface = funcs;
drag_grab->generic.pointer = seat->pointer;
drag_grab->keyboard_grab.interface = &keyboard_drag_grab_interface;
drag_grab->keyboard_grab.keyboard = seat->keyboard;
drag_grab->drag_client = client;
drag_grab->seat = seat;
drag_grab->device = device;
drag_grab->sequence = sequence;
drag_grab->drag_origin = surface;
drag_grab->drag_origin_listener.notify = destroy_data_device_origin;
wl_resource_add_destroy_listener (surface->resource,
@ -644,16 +684,16 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data
surface_actor = meta_wayland_surface_get_actor (surface);
clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface_actor),
seat->pointer->grab_x,
seat->pointer->grab_y,
drag_start.x,
drag_start.y,
&surface_pos.x, &surface_pos.y);
drag_grab->drag_start_x = surface_pos.x;
drag_grab->drag_start_y = surface_pos.y;
drag_grab->need_initial_focus = TRUE;
clutter_seat_query_state (clutter_input_device_get_seat (seat->pointer->device),
seat->pointer->device, NULL, NULL, &modifiers);
clutter_seat_query_state (clutter_input_device_get_seat (device),
device, sequence, &pos, &modifiers);
drag_grab->buttons = modifiers &
(CLUTTER_BUTTON1_MASK | CLUTTER_BUTTON2_MASK | CLUTTER_BUTTON3_MASK |
CLUTTER_BUTTON4_MASK | CLUTTER_BUTTON5_MASK);
@ -687,14 +727,15 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data
0, 0);
clutter_actor_add_child (drag_grab->feedback_actor, drag_surface_actor);
clutter_seat_query_state (clutter_input_device_get_seat (seat->pointer->device),
seat->pointer->device, NULL, &pos, NULL);
meta_feedback_actor_set_position (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
pos.x, pos.y);
}
meta_wayland_pointer_start_grab (seat->pointer,
(MetaWaylandPointerGrab*) drag_grab);
input = meta_wayland_seat_get_input (seat);
drag_grab->handler =
meta_wayland_input_attach_event_handler (input,
event_iface,
drag_grab);
meta_wayland_data_source_set_seat (source, seat);
}
@ -718,6 +759,9 @@ data_device_start_drag (struct wl_client *client,
MetaWaylandSurface *surface = NULL, *icon_surface = NULL;
MetaWaylandDataSource *drag_source = NULL;
MetaSelectionSource *selection_source;
ClutterInputDevice *device;
ClutterEventSequence *sequence;
float x, y;
if (origin_resource)
surface = wl_resource_get_user_data (origin_resource);
@ -725,16 +769,18 @@ data_device_start_drag (struct wl_client *client,
if (!surface)
return;
if (seat->pointer->button_count == 0 ||
seat->pointer->grab_serial != serial ||
!seat->pointer->focus_surface ||
seat->pointer->focus_surface != surface)
if (!meta_wayland_seat_get_grab_info (seat,
surface,
serial,
TRUE,
&device,
&sequence,
&x, &y))
return;
/* FIXME: Check that the data source type array isn't empty. */
if (data_device->current_grab ||
seat->pointer->grab != &seat->pointer->default_grab)
if (data_device->current_grab)
return;
if (icon_resource)
@ -758,14 +804,11 @@ data_device_start_drag (struct wl_client *client,
selection_source);
g_object_unref (selection_source);
meta_wayland_pointer_set_focus (seat->pointer, NULL);
meta_wayland_data_device_start_drag (data_device, client,
&drag_grab_interface,
surface, drag_source, icon_surface);
if (meta_wayland_seat_has_keyboard (seat))
meta_wayland_keyboard_start_grab (seat->keyboard,
&seat->data_device.current_grab->keyboard_grab);
&dnd_event_interface,
surface, drag_source, icon_surface,
device, sequence,
GRAPHENE_POINT_INIT (x, y));
}
static void
@ -788,7 +831,7 @@ meta_wayland_drag_dest_focus_in (MetaWaylandDataDevice *data_device,
struct wl_client *client;
struct wl_resource *resource;
uint32_t source_actions;
wl_fixed_t sx, sy;
graphene_point_t pos;
if (!grab->drag_focus_data_device)
return;
@ -810,11 +853,19 @@ meta_wayland_drag_dest_focus_in (MetaWaylandDataDevice *data_device,
wl_data_offer_send_source_actions (resource, source_actions);
}
meta_wayland_pointer_get_relative_coordinates (grab->generic.pointer,
surface, &sx, &sy);
clutter_seat_query_state (clutter_input_device_get_seat (grab->device),
grab->device,
grab->sequence,
&pos, NULL);
meta_wayland_surface_get_relative_coordinates (surface, pos.x, pos.y,
&pos.x, &pos.y);
wl_data_device_send_enter (grab->drag_focus_data_device,
wl_display_next_serial (display),
surface->resource, sx, sy, resource);
surface->resource,
wl_fixed_from_double (pos.x),
wl_fixed_from_double (pos.y),
resource);
}
static void
@ -839,17 +890,15 @@ meta_wayland_drag_dest_motion (MetaWaylandDataDevice *data_device,
uint32_t time_ms)
{
MetaWaylandDragGrab *grab = data_device->current_grab;
wl_fixed_t sx, sy;
if (!grab->drag_focus_data_device)
return;
meta_wayland_pointer_get_relative_coordinates (grab->generic.pointer,
grab->drag_focus,
&sx, &sy);
meta_wayland_surface_get_relative_coordinates (surface, x, y, &x, &y);
wl_data_device_send_motion (grab->drag_focus_data_device,
time_ms,
sx, sy);
wl_fixed_from_double (x),
wl_fixed_from_double (y));
}
static void

View file

@ -29,6 +29,7 @@
#include "meta/meta-selection-source.h"
#include "wayland/meta-wayland-data-offer.h"
#include "wayland/meta-wayland-data-source.h"
#include "wayland/meta-wayland-input.h"
#include "wayland/meta-wayland-types.h"
typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab;
@ -73,12 +74,15 @@ void meta_wayland_data_device_unset_dnd_selection (MetaWaylandDataDevice *da
const MetaWaylandDragDestFuncs *
meta_wayland_data_device_get_drag_dest_funcs (void);
void meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device,
struct wl_client *client,
const MetaWaylandPointerGrabInterface *funcs,
MetaWaylandSurface *surface,
MetaWaylandDataSource *source,
MetaWaylandSurface *icon_surface);
void meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device,
struct wl_client *client,
const MetaWaylandEventInterface *event_iface,
MetaWaylandSurface *surface,
MetaWaylandDataSource *source,
MetaWaylandSurface *icon_surface,
ClutterInputDevice *device,
ClutterEventSequence *sequence,
graphene_point_t drag_start);
void meta_wayland_data_device_end_drag (MetaWaylandDataDevice *data_device);
@ -88,3 +92,5 @@ MetaWaylandSurface *
meta_wayland_drag_grab_get_focus (MetaWaylandDragGrab *drag_grab);
void meta_wayland_drag_grab_update_feedback_actor (MetaWaylandDragGrab *drag_grab,
const ClutterEvent *event);
MetaWaylandSeat * meta_wayland_drag_grab_get_seat (MetaWaylandDragGrab *drag_grab);

View file

@ -820,55 +820,111 @@ repick_drop_surface (MetaWaylandCompositor *compositor,
}
}
static void
drag_xgrab_focus (MetaWaylandPointerGrab *grab,
MetaWaylandSurface *surface)
static MetaWaylandSurface *
drag_xgrab_get_focus_surface (MetaWaylandEventHandler *handler,
ClutterInputDevice *device,
ClutterEventSequence *sequence,
gpointer user_data)
{
/* Do not update the focus here. First, the surface may perfectly
ClutterSeat *clutter_seat;
clutter_seat = clutter_input_device_get_seat (device);
if (sequence ||
device != clutter_seat_get_pointer (clutter_seat))
return NULL;
return meta_wayland_event_handler_chain_up_get_focus_surface (handler,
device,
sequence);
}
static void
drag_xgrab_focus (MetaWaylandEventHandler *handler,
ClutterInputDevice *device,
ClutterEventSequence *sequence,
MetaWaylandSurface *surface,
gpointer user_data)
{
meta_wayland_event_handler_chain_up_focus (handler, device,
sequence, surface);
/* Do not update the DnD focus here. First, the surface may perfectly
* be the X11 source DnD icon window's, so we can only be fooled
* here. Second, delaying focus handling to XdndEnter/Leave
* makes us do the negotiation orderly on the X11 side.
*/
}
static void
drag_xgrab_motion (MetaWaylandPointerGrab *grab,
const ClutterEvent *event)
static gboolean
drag_xgrab_motion (MetaWaylandEventHandler *handler,
const ClutterEvent *event,
gpointer user_data)
{
MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (grab->pointer);
MetaWaylandDragGrab *drag_grab = user_data;
MetaWaylandSeat *seat = meta_wayland_drag_grab_get_seat (drag_grab);
MetaWaylandCompositor *compositor = meta_wayland_seat_get_compositor (seat);
MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd;
repick_drop_surface (compositor,
(MetaWaylandDragGrab *) grab,
event);
if (clutter_event_type (event) != CLUTTER_MOTION ||
clutter_event_get_device_tool (event))
return CLUTTER_EVENT_STOP;
repick_drop_surface (compositor, drag_grab, event);
dnd->last_motion_time = clutter_event_get_time (event);
meta_wayland_pointer_send_motion (seat->pointer, event);
return CLUTTER_EVENT_PROPAGATE;
}
static void
drag_xgrab_button (MetaWaylandPointerGrab *grab,
const ClutterEvent *event)
static gboolean
drag_xgrab_release (MetaWaylandEventHandler *handler,
const ClutterEvent *event,
gpointer user_data)
{
MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (grab->pointer);
MetaWaylandDragGrab *drag_grab = user_data;
MetaWaylandSeat *seat = meta_wayland_drag_grab_get_seat (drag_grab);
MetaWaylandCompositor *compositor = meta_wayland_seat_get_compositor (seat);
MetaWaylandDataSource *data_source;
meta_wayland_pointer_send_button (seat->pointer, event);
if (clutter_event_type (event) != CLUTTER_BUTTON_RELEASE ||
clutter_event_get_device_tool (event))
return CLUTTER_EVENT_STOP;
data_source = compositor->seat->data_device.dnd_data_source;
if (seat->pointer->button_count == 0 &&
(!meta_wayland_drag_grab_get_focus ((MetaWaylandDragGrab *) grab) ||
(!meta_wayland_drag_grab_get_focus (drag_grab) ||
meta_wayland_data_source_get_current_action (data_source) ==
WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE))
meta_xwayland_end_dnd_grab (&seat->data_device, FALSE);
return CLUTTER_EVENT_PROPAGATE;
}
static const MetaWaylandPointerGrabInterface drag_xgrab_interface = {
static gboolean
drag_xgrab_key (MetaWaylandEventHandler *handler,
const ClutterEvent *event,
gpointer user_data)
{
return CLUTTER_EVENT_PROPAGATE;
}
static gboolean
drag_xgrab_ignore_event (MetaWaylandEventHandler *handler,
const ClutterEvent *event,
gpointer user_data)
{
return CLUTTER_EVENT_STOP;
}
static const MetaWaylandEventInterface xdnd_event_interface = {
drag_xgrab_get_focus_surface,
drag_xgrab_focus,
drag_xgrab_motion,
drag_xgrab_button,
drag_xgrab_ignore_event, /* press */
drag_xgrab_release,
drag_xgrab_key,
drag_xgrab_ignore_event, /* other */
};
static gboolean
@ -1016,7 +1072,8 @@ meta_xwayland_dnd_handle_xfixes_selection_notify (MetaWaylandCompositor *composi
{
XFixesSelectionNotifyEvent *event = (XFixesSelectionNotifyEvent *) xevent;
MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd;
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
MetaWaylandSeat *seat = compositor->seat;
MetaWaylandDataDevice *data_device = &seat->data_device;
MetaX11Display *x11_display = x11_display_from_dnd (dnd);
MetaWaylandSurface *focus;
@ -1029,15 +1086,31 @@ meta_xwayland_dnd_handle_xfixes_selection_notify (MetaWaylandCompositor *composi
if (event->owner != None && event->owner != x11_display->selection.xwindow &&
focus && meta_wayland_surface_is_xwayland (focus))
{
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);
meta_wayland_data_device_start_drag (data_device,
wl_resource_get_client (focus->resource),
&drag_xgrab_interface,
focus, dnd->source,
NULL);
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),
&xdnd_event_interface,
focus, dnd->source,
NULL,
seat->pointer->device, NULL,
pos);
}
}
else if (event->owner == None)
{