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:
parent
5ade2060a7
commit
5fa112c298
@ -131,9 +131,10 @@ create_and_send_dnd_offer (MetaWaylandDataSource *source,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct _MetaWaylandDragGrab {
|
struct _MetaWaylandDragGrab {
|
||||||
MetaWaylandPointerGrab generic;
|
MetaWaylandEventHandler *handler;
|
||||||
|
|
||||||
MetaWaylandKeyboardGrab keyboard_grab;
|
ClutterInputDevice *device;
|
||||||
|
ClutterEventSequence *sequence;
|
||||||
|
|
||||||
MetaWaylandSeat *seat;
|
MetaWaylandSeat *seat;
|
||||||
struct wl_client *drag_client;
|
struct wl_client *drag_client;
|
||||||
@ -327,13 +328,10 @@ meta_wayland_drag_grab_update_feedback_actor (MetaWaylandDragGrab *drag_grab,
|
|||||||
event);
|
event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
MetaWaylandSeat *
|
||||||
drag_grab_focus (MetaWaylandPointerGrab *grab,
|
meta_wayland_drag_grab_get_seat (MetaWaylandDragGrab *drag_grab)
|
||||||
MetaWaylandSurface *surface)
|
|
||||||
{
|
{
|
||||||
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
|
return drag_grab->seat;
|
||||||
|
|
||||||
meta_wayland_drag_grab_set_focus (drag_grab, surface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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);
|
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
|
static void
|
||||||
data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
|
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;
|
drag_grab->seat->data_device.current_grab = NULL;
|
||||||
|
|
||||||
/* There might be other grabs created in result to DnD actions like popups
|
if (drag_grab->handler)
|
||||||
* on "ask" actions, we must not reset those, only our own.
|
|
||||||
*/
|
|
||||||
if (drag_grab->generic.pointer->grab == (MetaWaylandPointerGrab *) drag_grab)
|
|
||||||
{
|
{
|
||||||
MetaWaylandCompositor *wayland_compositor =
|
MetaWaylandInput *input;
|
||||||
meta_wayland_seat_get_compositor (data_device->seat);
|
|
||||||
|
|
||||||
meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
|
input = meta_wayland_seat_get_input (data_device->seat);
|
||||||
meta_wayland_keyboard_end_grab (drag_grab->keyboard_grab.keyboard);
|
meta_wayland_input_detach_event_handler (input, drag_grab->handler);
|
||||||
meta_wayland_compositor_sync_focus (wayland_compositor);
|
drag_grab->handler = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (drag_grab);
|
g_free (drag_grab);
|
||||||
@ -460,21 +433,91 @@ meta_wayland_data_source_fake_read (MetaWaylandDataSource *source,
|
|||||||
g_io_add_watch (channel, G_IO_HUP, on_fake_read_hup, source);
|
g_io_add_watch (channel, G_IO_HUP, on_fake_read_hup, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static MetaWaylandSurface *
|
||||||
drag_grab_button (MetaWaylandPointerGrab *grab,
|
drag_grab_get_focus_surface (MetaWaylandEventHandler *handler,
|
||||||
const ClutterEvent *event)
|
ClutterInputDevice *device,
|
||||||
|
ClutterEventSequence *sequence,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
|
MetaWaylandDragGrab *drag_grab = user_data;
|
||||||
MetaWaylandSeat *seat = drag_grab->seat;
|
|
||||||
ClutterEventType event_type = clutter_event_type (event);
|
|
||||||
|
|
||||||
if (drag_grab->generic.pointer->grab_button ==
|
if (device != drag_grab->device ||
|
||||||
clutter_event_get_button (event) &&
|
sequence != drag_grab->sequence)
|
||||||
event_type == CLUTTER_BUTTON_RELEASE)
|
return NULL;
|
||||||
|
|
||||||
|
return meta_wayland_event_handler_chain_up_get_focus_surface (handler,
|
||||||
|
device,
|
||||||
|
sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
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;
|
MetaWaylandDataSource *source = drag_grab->drag_data_source;
|
||||||
gboolean success;
|
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 &&
|
if (drag_grab->drag_focus && source &&
|
||||||
meta_wayland_data_source_has_target (source) &&
|
meta_wayland_data_source_has_target (source) &&
|
||||||
meta_wayland_data_source_get_current_action (source))
|
meta_wayland_data_source_get_current_action (source))
|
||||||
@ -508,28 +551,22 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
|
|||||||
meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor),
|
meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor),
|
||||||
success);
|
success);
|
||||||
drag_grab->feedback_actor = NULL;
|
drag_grab->feedback_actor = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (seat->pointer->button_count == 0 &&
|
|
||||||
event_type == CLUTTER_BUTTON_RELEASE)
|
|
||||||
data_device_end_drag_grab (drag_grab);
|
data_device_end_drag_grab (drag_grab);
|
||||||
|
|
||||||
|
return CLUTTER_EVENT_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const MetaWaylandPointerGrabInterface drag_grab_interface = {
|
|
||||||
drag_grab_focus,
|
|
||||||
drag_grab_motion,
|
|
||||||
drag_grab_button,
|
|
||||||
};
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
keyboard_drag_grab_key (MetaWaylandKeyboardGrab *grab,
|
drag_grab_key (MetaWaylandEventHandler *handler,
|
||||||
const ClutterEvent *event)
|
const ClutterEvent *event,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
|
MetaWaylandDragGrab *drag_grab = user_data;
|
||||||
|
ClutterModifierType modifiers;
|
||||||
|
|
||||||
if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_Escape)
|
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,
|
meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device,
|
||||||
NULL);
|
NULL);
|
||||||
unset_selection_source (&drag_grab->seat->data_device, META_SELECTION_DND);
|
unset_selection_source (&drag_grab->seat->data_device, META_SELECTION_DND);
|
||||||
@ -539,38 +576,40 @@ keyboard_drag_grab_key (MetaWaylandKeyboardGrab *grab,
|
|||||||
FALSE);
|
FALSE);
|
||||||
drag_grab->feedback_actor = NULL;
|
drag_grab->feedback_actor = NULL;
|
||||||
data_device_end_drag_grab (drag_grab);
|
data_device_end_drag_grab (drag_grab);
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
else if (clutter_seat_query_state (clutter_input_device_get_seat (drag_grab->device),
|
||||||
return FALSE;
|
drag_grab->device,
|
||||||
}
|
drag_grab->sequence,
|
||||||
|
NULL,
|
||||||
static void
|
&modifiers) &&
|
||||||
keyboard_drag_grab_modifiers (MetaWaylandKeyboardGrab *grab,
|
drag_grab->drag_data_source &&
|
||||||
ClutterModifierType modifiers)
|
clutter_event_get_state (event) != 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)
|
|
||||||
{
|
{
|
||||||
data_source_update_user_dnd_action (drag_grab->drag_data_source, modifiers);
|
data_source_update_user_dnd_action (drag_grab->drag_data_source, modifiers);
|
||||||
|
|
||||||
if (drag_grab->drag_focus)
|
if (drag_grab->drag_focus)
|
||||||
meta_wayland_surface_drag_dest_update (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 = {
|
static gboolean
|
||||||
keyboard_drag_grab_key,
|
drag_grab_discard_event (MetaWaylandEventHandler *handler,
|
||||||
keyboard_drag_grab_modifiers
|
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
|
static void
|
||||||
@ -614,28 +653,29 @@ destroy_data_device_icon (struct wl_listener *listener,
|
|||||||
void
|
void
|
||||||
meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device,
|
meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device,
|
||||||
struct wl_client *client,
|
struct wl_client *client,
|
||||||
const MetaWaylandPointerGrabInterface *funcs,
|
const MetaWaylandEventInterface *event_iface,
|
||||||
MetaWaylandSurface *surface,
|
MetaWaylandSurface *surface,
|
||||||
MetaWaylandDataSource *source,
|
MetaWaylandDataSource *source,
|
||||||
MetaWaylandSurface *icon_surface)
|
MetaWaylandSurface *icon_surface,
|
||||||
|
ClutterInputDevice *device,
|
||||||
|
ClutterEventSequence *sequence,
|
||||||
|
graphene_point_t drag_start)
|
||||||
{
|
{
|
||||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||||
MetaWaylandDragGrab *drag_grab;
|
MetaWaylandDragGrab *drag_grab;
|
||||||
graphene_point_t pos, surface_pos;
|
graphene_point_t pos, surface_pos;
|
||||||
ClutterModifierType modifiers;
|
ClutterModifierType modifiers;
|
||||||
MetaSurfaceActor *surface_actor;
|
MetaSurfaceActor *surface_actor;
|
||||||
|
MetaWaylandInput *input;
|
||||||
|
|
||||||
data_device->current_grab = drag_grab = g_new0 (MetaWaylandDragGrab, 1);
|
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->drag_client = client;
|
||||||
drag_grab->seat = seat;
|
drag_grab->seat = seat;
|
||||||
|
|
||||||
|
drag_grab->device = device;
|
||||||
|
drag_grab->sequence = sequence;
|
||||||
|
|
||||||
drag_grab->drag_origin = surface;
|
drag_grab->drag_origin = surface;
|
||||||
drag_grab->drag_origin_listener.notify = destroy_data_device_origin;
|
drag_grab->drag_origin_listener.notify = destroy_data_device_origin;
|
||||||
wl_resource_add_destroy_listener (surface->resource,
|
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);
|
surface_actor = meta_wayland_surface_get_actor (surface);
|
||||||
|
|
||||||
clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface_actor),
|
clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface_actor),
|
||||||
seat->pointer->grab_x,
|
drag_start.x,
|
||||||
seat->pointer->grab_y,
|
drag_start.y,
|
||||||
&surface_pos.x, &surface_pos.y);
|
&surface_pos.x, &surface_pos.y);
|
||||||
drag_grab->drag_start_x = surface_pos.x;
|
drag_grab->drag_start_x = surface_pos.x;
|
||||||
drag_grab->drag_start_y = surface_pos.y;
|
drag_grab->drag_start_y = surface_pos.y;
|
||||||
|
|
||||||
drag_grab->need_initial_focus = TRUE;
|
drag_grab->need_initial_focus = TRUE;
|
||||||
|
|
||||||
clutter_seat_query_state (clutter_input_device_get_seat (seat->pointer->device),
|
clutter_seat_query_state (clutter_input_device_get_seat (device),
|
||||||
seat->pointer->device, NULL, NULL, &modifiers);
|
device, sequence, &pos, &modifiers);
|
||||||
drag_grab->buttons = modifiers &
|
drag_grab->buttons = modifiers &
|
||||||
(CLUTTER_BUTTON1_MASK | CLUTTER_BUTTON2_MASK | CLUTTER_BUTTON3_MASK |
|
(CLUTTER_BUTTON1_MASK | CLUTTER_BUTTON2_MASK | CLUTTER_BUTTON3_MASK |
|
||||||
CLUTTER_BUTTON4_MASK | CLUTTER_BUTTON5_MASK);
|
CLUTTER_BUTTON4_MASK | CLUTTER_BUTTON5_MASK);
|
||||||
@ -687,14 +727,15 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data
|
|||||||
0, 0);
|
0, 0);
|
||||||
clutter_actor_add_child (drag_grab->feedback_actor, drag_surface_actor);
|
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),
|
meta_feedback_actor_set_position (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
|
||||||
pos.x, pos.y);
|
pos.x, pos.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_wayland_pointer_start_grab (seat->pointer,
|
input = meta_wayland_seat_get_input (seat);
|
||||||
(MetaWaylandPointerGrab*) drag_grab);
|
drag_grab->handler =
|
||||||
|
meta_wayland_input_attach_event_handler (input,
|
||||||
|
event_iface,
|
||||||
|
drag_grab);
|
||||||
meta_wayland_data_source_set_seat (source, seat);
|
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;
|
MetaWaylandSurface *surface = NULL, *icon_surface = NULL;
|
||||||
MetaWaylandDataSource *drag_source = NULL;
|
MetaWaylandDataSource *drag_source = NULL;
|
||||||
MetaSelectionSource *selection_source;
|
MetaSelectionSource *selection_source;
|
||||||
|
ClutterInputDevice *device;
|
||||||
|
ClutterEventSequence *sequence;
|
||||||
|
float x, y;
|
||||||
|
|
||||||
if (origin_resource)
|
if (origin_resource)
|
||||||
surface = wl_resource_get_user_data (origin_resource);
|
surface = wl_resource_get_user_data (origin_resource);
|
||||||
@ -725,16 +769,18 @@ data_device_start_drag (struct wl_client *client,
|
|||||||
if (!surface)
|
if (!surface)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (seat->pointer->button_count == 0 ||
|
if (!meta_wayland_seat_get_grab_info (seat,
|
||||||
seat->pointer->grab_serial != serial ||
|
surface,
|
||||||
!seat->pointer->focus_surface ||
|
serial,
|
||||||
seat->pointer->focus_surface != surface)
|
TRUE,
|
||||||
|
&device,
|
||||||
|
&sequence,
|
||||||
|
&x, &y))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* FIXME: Check that the data source type array isn't empty. */
|
/* FIXME: Check that the data source type array isn't empty. */
|
||||||
|
|
||||||
if (data_device->current_grab ||
|
if (data_device->current_grab)
|
||||||
seat->pointer->grab != &seat->pointer->default_grab)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (icon_resource)
|
if (icon_resource)
|
||||||
@ -758,14 +804,11 @@ data_device_start_drag (struct wl_client *client,
|
|||||||
selection_source);
|
selection_source);
|
||||||
g_object_unref (selection_source);
|
g_object_unref (selection_source);
|
||||||
|
|
||||||
meta_wayland_pointer_set_focus (seat->pointer, NULL);
|
|
||||||
meta_wayland_data_device_start_drag (data_device, client,
|
meta_wayland_data_device_start_drag (data_device, client,
|
||||||
&drag_grab_interface,
|
&dnd_event_interface,
|
||||||
surface, drag_source, icon_surface);
|
surface, drag_source, icon_surface,
|
||||||
|
device, sequence,
|
||||||
if (meta_wayland_seat_has_keyboard (seat))
|
GRAPHENE_POINT_INIT (x, y));
|
||||||
meta_wayland_keyboard_start_grab (seat->keyboard,
|
|
||||||
&seat->data_device.current_grab->keyboard_grab);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -788,7 +831,7 @@ meta_wayland_drag_dest_focus_in (MetaWaylandDataDevice *data_device,
|
|||||||
struct wl_client *client;
|
struct wl_client *client;
|
||||||
struct wl_resource *resource;
|
struct wl_resource *resource;
|
||||||
uint32_t source_actions;
|
uint32_t source_actions;
|
||||||
wl_fixed_t sx, sy;
|
graphene_point_t pos;
|
||||||
|
|
||||||
if (!grab->drag_focus_data_device)
|
if (!grab->drag_focus_data_device)
|
||||||
return;
|
return;
|
||||||
@ -810,11 +853,19 @@ meta_wayland_drag_dest_focus_in (MetaWaylandDataDevice *data_device,
|
|||||||
wl_data_offer_send_source_actions (resource, source_actions);
|
wl_data_offer_send_source_actions (resource, source_actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_wayland_pointer_get_relative_coordinates (grab->generic.pointer,
|
clutter_seat_query_state (clutter_input_device_get_seat (grab->device),
|
||||||
surface, &sx, &sy);
|
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_data_device_send_enter (grab->drag_focus_data_device,
|
||||||
wl_display_next_serial (display),
|
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
|
static void
|
||||||
@ -839,17 +890,15 @@ meta_wayland_drag_dest_motion (MetaWaylandDataDevice *data_device,
|
|||||||
uint32_t time_ms)
|
uint32_t time_ms)
|
||||||
{
|
{
|
||||||
MetaWaylandDragGrab *grab = data_device->current_grab;
|
MetaWaylandDragGrab *grab = data_device->current_grab;
|
||||||
wl_fixed_t sx, sy;
|
|
||||||
|
|
||||||
if (!grab->drag_focus_data_device)
|
if (!grab->drag_focus_data_device)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
meta_wayland_pointer_get_relative_coordinates (grab->generic.pointer,
|
meta_wayland_surface_get_relative_coordinates (surface, x, y, &x, &y);
|
||||||
grab->drag_focus,
|
|
||||||
&sx, &sy);
|
|
||||||
wl_data_device_send_motion (grab->drag_focus_data_device,
|
wl_data_device_send_motion (grab->drag_focus_data_device,
|
||||||
time_ms,
|
time_ms,
|
||||||
sx, sy);
|
wl_fixed_from_double (x),
|
||||||
|
wl_fixed_from_double (y));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "meta/meta-selection-source.h"
|
#include "meta/meta-selection-source.h"
|
||||||
#include "wayland/meta-wayland-data-offer.h"
|
#include "wayland/meta-wayland-data-offer.h"
|
||||||
#include "wayland/meta-wayland-data-source.h"
|
#include "wayland/meta-wayland-data-source.h"
|
||||||
|
#include "wayland/meta-wayland-input.h"
|
||||||
#include "wayland/meta-wayland-types.h"
|
#include "wayland/meta-wayland-types.h"
|
||||||
|
|
||||||
typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab;
|
typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab;
|
||||||
@ -75,10 +76,13 @@ const MetaWaylandDragDestFuncs *
|
|||||||
|
|
||||||
void meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device,
|
void meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device,
|
||||||
struct wl_client *client,
|
struct wl_client *client,
|
||||||
const MetaWaylandPointerGrabInterface *funcs,
|
const MetaWaylandEventInterface *event_iface,
|
||||||
MetaWaylandSurface *surface,
|
MetaWaylandSurface *surface,
|
||||||
MetaWaylandDataSource *source,
|
MetaWaylandDataSource *source,
|
||||||
MetaWaylandSurface *icon_surface);
|
MetaWaylandSurface *icon_surface,
|
||||||
|
ClutterInputDevice *device,
|
||||||
|
ClutterEventSequence *sequence,
|
||||||
|
graphene_point_t drag_start);
|
||||||
|
|
||||||
void meta_wayland_data_device_end_drag (MetaWaylandDataDevice *data_device);
|
void meta_wayland_data_device_end_drag (MetaWaylandDataDevice *data_device);
|
||||||
|
|
||||||
@ -88,3 +92,5 @@ MetaWaylandSurface *
|
|||||||
meta_wayland_drag_grab_get_focus (MetaWaylandDragGrab *drag_grab);
|
meta_wayland_drag_grab_get_focus (MetaWaylandDragGrab *drag_grab);
|
||||||
void meta_wayland_drag_grab_update_feedback_actor (MetaWaylandDragGrab *drag_grab,
|
void meta_wayland_drag_grab_update_feedback_actor (MetaWaylandDragGrab *drag_grab,
|
||||||
const ClutterEvent *event);
|
const ClutterEvent *event);
|
||||||
|
|
||||||
|
MetaWaylandSeat * meta_wayland_drag_grab_get_seat (MetaWaylandDragGrab *drag_grab);
|
||||||
|
@ -820,55 +820,111 @@ repick_drop_surface (MetaWaylandCompositor *compositor,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static MetaWaylandSurface *
|
||||||
drag_xgrab_focus (MetaWaylandPointerGrab *grab,
|
drag_xgrab_get_focus_surface (MetaWaylandEventHandler *handler,
|
||||||
MetaWaylandSurface *surface)
|
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
|
* be the X11 source DnD icon window's, so we can only be fooled
|
||||||
* here. Second, delaying focus handling to XdndEnter/Leave
|
* here. Second, delaying focus handling to XdndEnter/Leave
|
||||||
* makes us do the negotiation orderly on the X11 side.
|
* makes us do the negotiation orderly on the X11 side.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
drag_xgrab_motion (MetaWaylandPointerGrab *grab,
|
drag_xgrab_motion (MetaWaylandEventHandler *handler,
|
||||||
const ClutterEvent *event)
|
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);
|
MetaWaylandCompositor *compositor = meta_wayland_seat_get_compositor (seat);
|
||||||
MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd;
|
MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd;
|
||||||
|
|
||||||
repick_drop_surface (compositor,
|
if (clutter_event_type (event) != CLUTTER_MOTION ||
|
||||||
(MetaWaylandDragGrab *) grab,
|
clutter_event_get_device_tool (event))
|
||||||
event);
|
return CLUTTER_EVENT_STOP;
|
||||||
|
|
||||||
|
repick_drop_surface (compositor, drag_grab, event);
|
||||||
|
|
||||||
dnd->last_motion_time = clutter_event_get_time (event);
|
dnd->last_motion_time = clutter_event_get_time (event);
|
||||||
meta_wayland_pointer_send_motion (seat->pointer, event);
|
|
||||||
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
drag_xgrab_button (MetaWaylandPointerGrab *grab,
|
drag_xgrab_release (MetaWaylandEventHandler *handler,
|
||||||
const ClutterEvent *event)
|
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);
|
MetaWaylandCompositor *compositor = meta_wayland_seat_get_compositor (seat);
|
||||||
MetaWaylandDataSource *data_source;
|
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;
|
data_source = compositor->seat->data_device.dnd_data_source;
|
||||||
|
|
||||||
if (seat->pointer->button_count == 0 &&
|
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) ==
|
meta_wayland_data_source_get_current_action (data_source) ==
|
||||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE))
|
WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE))
|
||||||
meta_xwayland_end_dnd_grab (&seat->data_device, FALSE);
|
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_focus,
|
||||||
drag_xgrab_motion,
|
drag_xgrab_motion,
|
||||||
drag_xgrab_button,
|
drag_xgrab_ignore_event, /* press */
|
||||||
|
drag_xgrab_release,
|
||||||
|
drag_xgrab_key,
|
||||||
|
drag_xgrab_ignore_event, /* other */
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -1016,7 +1072,8 @@ meta_xwayland_dnd_handle_xfixes_selection_notify (MetaWaylandCompositor *composi
|
|||||||
{
|
{
|
||||||
XFixesSelectionNotifyEvent *event = (XFixesSelectionNotifyEvent *) xevent;
|
XFixesSelectionNotifyEvent *event = (XFixesSelectionNotifyEvent *) xevent;
|
||||||
MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd;
|
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);
|
MetaX11Display *x11_display = x11_display_from_dnd (dnd);
|
||||||
MetaWaylandSurface *focus;
|
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 &&
|
if (event->owner != None && event->owner != x11_display->selection.xwindow &&
|
||||||
focus && meta_wayland_surface_is_xwayland (focus))
|
focus && meta_wayland_surface_is_xwayland (focus))
|
||||||
{
|
{
|
||||||
|
graphene_point_t pos;
|
||||||
|
ClutterModifierType modifiers;
|
||||||
|
|
||||||
dnd->source = meta_wayland_data_source_xwayland_new (dnd, compositor);
|
dnd->source = meta_wayland_data_source_xwayland_new (dnd, compositor);
|
||||||
meta_wayland_data_device_set_dnd_source (&compositor->seat->data_device,
|
meta_wayland_data_device_set_dnd_source (&compositor->seat->data_device,
|
||||||
dnd->source);
|
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,
|
meta_wayland_data_device_start_drag (data_device,
|
||||||
wl_resource_get_client (focus->resource),
|
wl_resource_get_client (focus->resource),
|
||||||
&drag_xgrab_interface,
|
&xdnd_event_interface,
|
||||||
focus, dnd->source,
|
focus, dnd->source,
|
||||||
NULL);
|
NULL,
|
||||||
|
seat->pointer->device, NULL,
|
||||||
|
pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (event->owner == None)
|
else if (event->owner == None)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user