[mutter] wayland: Implement support for the x-rootwindow-drop target
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] wayland: Implement support for the x-rootwindow-drop target
- Date: Fri, 11 Mar 2016 13:53:19 +0000 (UTC)
commit 3d67bfda14e8fb52f882dc257b7020bfedd4a7fb
Author: Carlos Garnacho <carlosg gnome org>
Date: Wed Mar 9 16:53:26 2016 +0100
wayland: Implement support for the x-rootwindow-drop target
This target is set whenever DnD moves towards an area between surfaces.
Although no offer is set and data is actually not read, drag sources
offering this mimetype will be able to behave just like they used to
do in X11.
https://bugzilla.gnome.org/show_bug.cgi?id=762104
src/wayland/meta-wayland-data-device.c | 83 ++++++++++++++++++++++++++++++++
1 files changed, 83 insertions(+), 0 deletions(-)
---
diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c
index 28b870e..c7b324f 100644
--- a/src/wayland/meta-wayland-data-device.c
+++ b/src/wayland/meta-wayland-data-device.c
@@ -29,6 +29,7 @@
#include <unistd.h>
#include <stdio.h>
#include <glib.h>
+#include <glib-unix.h>
#include "meta-wayland-data-device.h"
#include "meta-wayland-data-device-private.h"
@@ -39,6 +40,8 @@
#include "gtk-primary-selection-server-protocol.h"
+#define ROOTWINDOW_DROP_MIME "application/x-rootwindow-drop"
+
#define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
@@ -726,6 +729,30 @@ meta_wayland_drag_grab_set_source (MetaWaylandDragGrab *drag_grab,
drag_grab);
}
+static void
+meta_wayland_drag_source_fake_acceptance (MetaWaylandDataSource *source,
+ const gchar *mimetype)
+{
+ uint32_t actions, user_action, action = 0;
+
+ actions = meta_wayland_data_source_get_actions (source);
+ user_action = meta_wayland_data_source_get_user_action (source);
+
+ /* Pick a suitable action */
+ if ((user_action & actions) != 0)
+ action = user_action;
+ else if (actions != 0)
+ action = 1 << (ffs (actions) - 1);
+
+ /* Bail out if there is none, source didn't cooperate */
+ if (action == 0)
+ return;
+
+ meta_wayland_data_source_target (source, mimetype);
+ meta_wayland_data_source_set_current_action (source, action);
+ meta_wayland_data_source_set_has_target (source, TRUE);
+}
+
void
meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab *drag_grab,
MetaWaylandSurface *surface)
@@ -750,6 +777,12 @@ meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab *drag_grab,
if (source)
meta_wayland_data_source_set_current_offer (source, NULL);
+ if (!surface && source &&
+ meta_wayland_data_source_has_mime_type (source, ROOTWINDOW_DROP_MIME))
+ meta_wayland_drag_source_fake_acceptance (source, ROOTWINDOW_DROP_MIME);
+ else if (source)
+ meta_wayland_data_source_target (source, NULL);
+
if (!surface)
return;
@@ -855,6 +888,47 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
g_slice_free (MetaWaylandDragGrab, drag_grab);
}
+static gboolean
+on_fake_read_hup (GIOChannel *channel,
+ GIOCondition condition,
+ gpointer data)
+{
+ MetaWaylandDataSource *source = data;
+
+ meta_wayland_data_source_notify_finish (source);
+ g_io_channel_shutdown (channel, FALSE, NULL);
+ g_io_channel_unref (channel);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+meta_wayland_data_source_fake_read (MetaWaylandDataSource *source,
+ const gchar *mimetype)
+{
+ GIOChannel *channel;
+ int p[2];
+
+ if (!g_unix_open_pipe (p, FD_CLOEXEC, NULL))
+ {
+ meta_wayland_data_source_notify_finish (source);
+ return;
+ }
+
+ if (!g_unix_set_fd_nonblocking (p[0], TRUE, NULL) ||
+ !g_unix_set_fd_nonblocking (p[1], TRUE, NULL))
+ {
+ meta_wayland_data_source_notify_finish (source);
+ close (p[0]);
+ close (p[1]);
+ return;
+ }
+
+ meta_wayland_data_source_send (source, mimetype, p[1]);
+ channel = g_io_channel_unix_new (p[0]);
+ g_io_add_watch (channel, G_IO_HUP, on_fake_read_hup, source);
+}
+
static void
drag_grab_button (MetaWaylandPointerGrab *grab,
const ClutterEvent *event)
@@ -883,6 +957,15 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
meta_wayland_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
{
meta_wayland_data_source_cancel (source);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]