From de7782221a75cff2b9d39dba54627be2c4ddcd08 Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Wed, 29 Jan 2020 00:11:18 +0100 Subject: [PATCH] wayland/data-device: Cancel drag source when the drag finished unsuccessfully When a drag was performed but did not finish successfully, e.g. because no mimetype was accepted, we need to send the source cancel event so clients know they can destroy the drag source (since version 3). Fixes https://gitlab.gnome.org/GNOME/mutter/issues/740 https://gitlab.gnome.org/GNOME/mutter/merge_requests/1031 (cherry picked from commit 6cc748cce9bb7cb47a4098cdc251c554d9f99b6b) --- src/wayland/meta-wayland-data-device.c | 30 ++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c index f2ff09630..b286fb9ad 100644 --- a/src/wayland/meta-wayland-data-device.c +++ b/src/wayland/meta-wayland-data-device.c @@ -75,6 +75,7 @@ typedef struct _MetaWaylandDataSourcePrivate MetaWaylandSeat *seat; guint actions_set : 1; guint in_ask : 1; + guint drop_performed : 1; } MetaWaylandDataSourcePrivate; typedef struct _MetaWaylandDataSourcePrimary @@ -95,6 +96,9 @@ meta_wayland_data_source_new (struct wl_resource *resource); static MetaWaylandDataSource * meta_wayland_data_source_primary_new (struct wl_resource *resource); +static void +meta_wayland_source_cancel (MetaWaylandDataSource *source); + static void drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was); @@ -363,6 +367,15 @@ meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source, data_offer_update_action (offer); } +static gboolean +meta_wayland_data_source_get_drop_performed (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + return priv->drop_performed; +} + static void data_offer_accept (struct wl_client *client, struct wl_resource *resource, @@ -577,11 +590,17 @@ destroy_data_offer (struct wl_resource *resource) if (offer == meta_wayland_data_source_get_current_offer (offer->source)) { - if (seat->data_device.dnd_data_source == offer->source && - wl_resource_get_version (offer->resource) < - WL_DATA_OFFER_ACTION_SINCE_VERSION) + if (seat->data_device.dnd_data_source == offer->source) { - meta_wayland_data_source_notify_finish (offer->source); + if (wl_resource_get_version (offer->resource) < + WL_DATA_OFFER_ACTION_SINCE_VERSION) + meta_wayland_data_source_notify_finish (offer->source); + else if (meta_wayland_data_source_get_drop_performed (offer->source) && + meta_wayland_data_source_get_resource(offer->source) && + wl_resource_get_version( + meta_wayland_data_source_get_resource(offer->source)) >= + WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) + meta_wayland_source_cancel (offer->source); } else { @@ -1377,6 +1396,8 @@ meta_wayland_source_drop_performed (MetaWaylandDataSource *source) MetaWaylandDataSourcePrivate *priv = meta_wayland_data_source_get_instance_private (source); + priv->drop_performed = TRUE; + if (wl_resource_get_version (priv->resource) >= WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION) wl_data_source_send_dnd_drop_performed (priv->resource); @@ -1427,6 +1448,7 @@ meta_wayland_data_source_init (MetaWaylandDataSource *source) wl_array_init (&priv->mime_types); priv->current_dnd_action = -1; + priv->drop_performed = FALSE; } static void