data-device: Implement DnD progress notification

Weston now sends wl_data_source.dnd_drop_performed and .dnd_finished in
order to notify about the different phases of DnD.

wl_data_source.cancelled is also used as mentioned in the docs, being
emitted also on DnD when the operation is meant to fail (eg. source
and dest didn't agree on a mimetype).

The dnd demo is also fixed so the struct dnd_drag isn't leaked.

https://bugs.freedesktop.org/show_bug.cgi?id=91943
https://bugs.freedesktop.org/show_bug.cgi?id=91944

Changes since v6:
  - Add client-side version checks. Minor code shuffling.

Changes since v5:
  - Dissociate source and offer after cancel. Updated to
    apply on top of c9f8f8a7f.

Changes since v4:
  - Make wl_data_offer.finish with the wrong state an error.

Changes since v3:
  - Fixed wl_data_source.dnd_finished vs cancelled emission on
    when interoperating with version < 3 drag destinations.

Changes since v2:
  - Handle wl_data_offer.finish. Fixed commit log inconsistencies.
    Added version checks. Spaces vs tabs fixes. Fixed resource
    versioning.

Changes since v1:
  - Updated to protocol v2.

Signed-off-by: Carlos Garnacho <carlosg@gnome.org>
Reviewed-by: Michael Catanzaro <mcatanzaro@igalia.com>
Reviewed-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Bryce Harrington <bryce@osg.samsung.com>
diff --git a/clients/dnd.c b/clients/dnd.c
index e6a0c39..974429b 100644
--- a/clients/dnd.c
+++ b/clients/dnd.c
@@ -318,14 +318,8 @@
 }
 
 static void
-data_source_cancelled(void *data, struct wl_data_source *source)
+dnd_drag_destroy(struct dnd_drag *dnd_drag)
 {
-	struct dnd_drag *dnd_drag = data;
-
-	/* The 'cancelled' event means that the source is no longer in
-	 * use by the drag (or current selection).  We need to clean
-	 * up the drag object created and the local state. */
-
 	wl_data_source_destroy(dnd_drag->data_source);
 
 	/* Destroy the item that has been dragged out */
@@ -339,10 +333,39 @@
 	free(dnd_drag);
 }
 
+static void
+data_source_cancelled(void *data, struct wl_data_source *source)
+{
+	struct dnd_drag *dnd_drag = data;
+
+	/* The 'cancelled' event means that the source is no longer in
+	 * use by the drag (or current selection).  We need to clean
+	 * up the drag object created and the local state. */
+	dnd_drag_destroy(dnd_drag);
+}
+
+static void
+data_source_dnd_drop_performed(void *data, struct wl_data_source *source)
+{
+}
+
+static void
+data_source_dnd_finished(void *data, struct wl_data_source *source)
+{
+	struct dnd_drag *dnd_drag = data;
+
+	/* The operation is already finished, we can destroy all
+	 * related data.
+	 */
+	dnd_drag_destroy(dnd_drag);
+}
+
 static const struct wl_data_source_listener data_source_listener = {
 	data_source_target,
 	data_source_send,
-	data_source_cancelled
+	data_source_cancelled,
+	data_source_dnd_drop_performed,
+	data_source_dnd_finished,
 };
 
 static cairo_surface_t *
diff --git a/clients/window.c b/clients/window.c
index 7d45acd..1b3cbb1 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -3812,6 +3812,7 @@
 {
 	struct data_offer *offer =
 		container_of(task, struct data_offer, io_task);
+	struct display *display = offer->input->display;
 	unsigned int len;
 	char buffer[4096];
 
@@ -3820,6 +3821,9 @@
 		    offer->x, offer->y, offer->user_data);
 
 	if (len == 0) {
+		if (display->data_device_manager_version >=
+		    WL_DATA_OFFER_FINISH_SINCE_VERSION)
+			wl_data_offer_finish(offer->offer);
 		close(offer->fd);
 		data_offer_destroy(offer);
 	}
@@ -5413,7 +5417,7 @@
 		d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
 		wl_shm_add_listener(d->shm, &shm_listener, d);
 	} else if (strcmp(interface, "wl_data_device_manager") == 0) {
-		d->data_device_manager_version = MIN(version, 2);
+		d->data_device_manager_version = MIN(version, 3);
 		d->data_device_manager =
 			wl_registry_bind(registry, id,
 					 &wl_data_device_manager_interface,