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 6cc748cce9)
This commit is contained in:
Robert Mader 2020-01-29 00:11:18 +01:00
parent 651d2a57f8
commit de7782221a

View File

@ -75,6 +75,7 @@ typedef struct _MetaWaylandDataSourcePrivate
MetaWaylandSeat *seat; MetaWaylandSeat *seat;
guint actions_set : 1; guint actions_set : 1;
guint in_ask : 1; guint in_ask : 1;
guint drop_performed : 1;
} MetaWaylandDataSourcePrivate; } MetaWaylandDataSourcePrivate;
typedef struct _MetaWaylandDataSourcePrimary typedef struct _MetaWaylandDataSourcePrimary
@ -95,6 +96,9 @@ meta_wayland_data_source_new (struct wl_resource *resource);
static MetaWaylandDataSource * static MetaWaylandDataSource *
meta_wayland_data_source_primary_new (struct wl_resource *resource); meta_wayland_data_source_primary_new (struct wl_resource *resource);
static void
meta_wayland_source_cancel (MetaWaylandDataSource *source);
static void static void
drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was); 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); 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 static void
data_offer_accept (struct wl_client *client, data_offer_accept (struct wl_client *client,
struct wl_resource *resource, 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 (offer == meta_wayland_data_source_get_current_offer (offer->source))
{ {
if (seat->data_device.dnd_data_source == offer->source && if (seat->data_device.dnd_data_source == offer->source)
wl_resource_get_version (offer->resource) <
WL_DATA_OFFER_ACTION_SINCE_VERSION)
{ {
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 else
{ {
@ -1377,6 +1396,8 @@ meta_wayland_source_drop_performed (MetaWaylandDataSource *source)
MetaWaylandDataSourcePrivate *priv = MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source); meta_wayland_data_source_get_instance_private (source);
priv->drop_performed = TRUE;
if (wl_resource_get_version (priv->resource) >= if (wl_resource_get_version (priv->resource) >=
WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION) WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION)
wl_data_source_send_dnd_drop_performed (priv->resource); 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); wl_array_init (&priv->mime_types);
priv->current_dnd_action = -1; priv->current_dnd_action = -1;
priv->drop_performed = FALSE;
} }
static void static void