summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2016-01-13 21:00:34 +0100
committerCarlos Garnacho <carlosg@gnome.org>2016-01-19 00:00:06 +0100
commita7c6d906ed964860513d17172b917867eae49e8d (patch)
tree106ab600f9b311087f4adc098fbc653138ff6070
parentb7bb9d90255187dd38d167751fcc4e1c0ebe63a9 (diff)
downloadgtk+-a7c6d906ed964860513d17172b917867eae49e8d.tar.gz
wayland: Implement DnD actions as per wl_data_device v3
Implement as a managed GdkDragContext, which actually fits nicely with the drag-and-drop model in wayland.
-rw-r--r--gdk/wayland/gdkdevice-wayland.c69
-rw-r--r--gdk/wayland/gdkdisplay-wayland.c2
-rw-r--r--gdk/wayland/gdkdnd-wayland.c134
-rw-r--r--gdk/wayland/gdkprivate-wayland.h4
-rw-r--r--gdk/wayland/gdkselection-wayland.c188
-rw-r--r--gtk/gtkdnd.c11
6 files changed, 294 insertions, 114 deletions
diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c
index 43a86906a9..fd2925c49f 100644
--- a/gdk/wayland/gdkdevice-wayland.c
+++ b/gdk/wayland/gdkdevice-wayland.c
@@ -883,16 +883,10 @@ data_device_drop (void *data,
struct wl_data_device *data_device)
{
GdkWaylandDeviceData *device = (GdkWaylandDeviceData *) data;
- GdkWindow *local_dnd_owner;
GDK_NOTE (EVENTS,
g_message ("data device drop, data device %p", data_device));
- local_dnd_owner = gdk_selection_owner_get_for_display (device->display, gdk_drag_get_selection (device->drop_context));
-
- if (local_dnd_owner)
- gdk_wayland_device_unset_grab (device->master_pointer);
-
_gdk_wayland_drag_context_emit_event (device->drop_context,
GDK_DROP_START, GDK_CURRENT_TIME);
}
@@ -3105,61 +3099,6 @@ gdk_wayland_device_set_selection (GdkDevice *gdk_device,
_gdk_wayland_display_get_serial (display_wayland));
}
-void
-gdk_wayland_device_unset_grab (GdkDevice *gdk_device)
-{
- GdkWaylandDeviceData *device;
- GdkEventSequence *sequence;
- GdkModifierType state;
- GdkEvent *event;
- guint button;
- gdouble x, y;
-
- device = GDK_WAYLAND_DEVICE (gdk_device)->device;
- _gdk_wayland_device_get_last_implicit_grab_serial (GDK_WAYLAND_DEVICE (gdk_device), &sequence);
- gdk_window_get_device_position_double (device->pointer_grab_window,
- gdk_device, &x, &y, &state);
-
- if (sequence)
- {
- event = gdk_event_new (GDK_TOUCH_END);
- event->touch.window = g_object_ref (device->pointer_grab_window);
- event->touch.send_event = TRUE;
- event->touch.sequence = sequence;
- event->touch.time = GDK_CURRENT_TIME;
- event->touch.x = event->touch.x_root = x;
- event->touch.y = event->touch.y_root = y;
- }
- else if (state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK))
- {
- if (state & GDK_BUTTON1_MASK)
- button = 1;
- else if (state & GDK_BUTTON2_MASK)
- button = 2;
- else if (state & GDK_BUTTON3_MASK)
- button = 3;
- else
- return;
-
- event = gdk_event_new (GDK_BUTTON_RELEASE);
- event->button.window = g_object_ref (device->pointer_grab_window);
- event->button.send_event = TRUE;
- event->button.button = button;
- event->button.time = GDK_CURRENT_TIME;
- event->button.x = event->button.x_root = x;
- event->button.y = event->button.y_root = y;
- }
- else
- return;
-
- device->button_modifiers = 0;
- gdk_event_set_device (event, gdk_device);
- gdk_event_set_source_device (event, gdk_device);
- gdk_event_set_seat (event, gdk_device_get_seat (gdk_device));
-
- _gdk_wayland_display_deliver_event (gdk_device_get_display (gdk_device), event);
-}
-
struct wl_seat *
gdk_wayland_seat_get_wl_seat (GdkSeat *seat)
{
@@ -3167,3 +3106,11 @@ gdk_wayland_seat_get_wl_seat (GdkSeat *seat)
return GDK_WAYLAND_SEAT (seat)->wl_seat;
}
+
+GdkDragContext *
+gdk_wayland_device_get_drop_context (GdkDevice *device)
+{
+ GdkSeat *seat = gdk_device_get_seat (device);
+
+ return GDK_WAYLAND_SEAT (seat)->drop_context;
+}
diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c
index 53e26aebbc..24a4ce229f 100644
--- a/gdk/wayland/gdkdisplay-wayland.c
+++ b/gdk/wayland/gdkdisplay-wayland.c
@@ -315,7 +315,7 @@ gdk_registry_handle_global (void *data,
else if (strcmp (interface, "wl_data_device_manager") == 0)
{
display_wayland->data_device_manager =
- wl_registry_bind (display_wayland->wl_registry, id, &wl_data_device_manager_interface, 1);
+ wl_registry_bind (display_wayland->wl_registry, id, &wl_data_device_manager_interface, 3);
}
else if (strcmp (interface, "wl_subcompositor") == 0)
{
diff --git a/gdk/wayland/gdkdnd-wayland.c b/gdk/wayland/gdkdnd-wayland.c
index 8eb8688e0d..8402b0d799 100644
--- a/gdk/wayland/gdkdnd-wayland.c
+++ b/gdk/wayland/gdkdnd-wayland.c
@@ -24,6 +24,7 @@
#include "gdkproperty.h"
#include "gdkprivate-wayland.h"
#include "gdkdisplay-wayland.h"
+#include "gdkseat-wayland.h"
#include "gdkdeviceprivate.h"
@@ -45,6 +46,7 @@ struct _GdkWaylandDragContext
GdkWindow *dnd_window;
struct wl_surface *dnd_surface;
struct wl_data_source *data_source;
+ GdkDragAction selected_action;
uint32_t serial;
gdouble x;
gdouble y;
@@ -82,6 +84,8 @@ gdk_wayland_drag_context_finalize (GObject *object)
selection_owner = gdk_selection_owner_get_for_display (display, selection);
if (selection_owner == context->source_window)
gdk_wayland_selection_unset_data_source (display, selection);
+
+ gdk_drag_context_set_cursor (context, NULL);
}
if (wayland_context->data_source)
@@ -157,6 +161,21 @@ gdk_wayland_drag_context_find_window (GdkDragContext *context,
return NULL;
}
+static inline uint32_t
+gdk_to_wl_actions (GdkDragAction action)
+{
+ uint32_t dnd_actions = 0;
+
+ if (action & (GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_PRIVATE))
+ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
+ if (action & GDK_ACTION_MOVE)
+ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
+ if (action & GDK_ACTION_ASK)
+ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
+
+ return dnd_actions;
+}
+
void
gdk_wayland_drag_context_set_action (GdkDragContext *context,
GdkDragAction action)
@@ -208,6 +227,9 @@ gdk_wayland_drop_context_set_status (GdkDragContext *context,
GdkDisplay *display;
struct wl_data_offer *wl_offer;
+ if (!context->dest_window)
+ return;
+
context_wayland = GDK_WAYLAND_DRAG_CONTEXT (context);
display = gdk_device_get_display (gdk_drag_context_get_device (context));
@@ -241,11 +263,32 @@ gdk_wayland_drop_context_set_status (GdkDragContext *context,
}
static void
+gdk_wayland_drag_context_commit_status (GdkDragContext *context)
+{
+ GdkWaylandDragContext *wayland_context;
+ GdkDisplay *display;
+ uint32_t dnd_actions;
+
+ wayland_context = GDK_WAYLAND_DRAG_CONTEXT (context);
+ display = gdk_device_get_display (gdk_drag_context_get_device (context));
+
+ dnd_actions = gdk_to_wl_actions (wayland_context->selected_action);
+ gdk_wayland_selection_set_current_offer_actions (display, dnd_actions);
+
+ gdk_wayland_drop_context_set_status (context, wayland_context->selected_action != 0);
+}
+
+static void
gdk_wayland_drag_context_drag_status (GdkDragContext *context,
GdkDragAction action,
guint32 time_)
{
- gdk_wayland_drop_context_set_status (context, action != 0);
+ GdkWaylandDragContext *wayland_context;
+
+ wayland_context = GDK_WAYLAND_DRAG_CONTEXT (context);
+ wayland_context->selected_action = action;
+
+ gdk_wayland_drag_context_commit_status (context);
}
static void
@@ -263,12 +306,20 @@ gdk_wayland_drag_context_drop_finish (GdkDragContext *context,
guint32 time)
{
GdkDisplay *display = gdk_device_get_display (gdk_drag_context_get_device (context));
+ GdkWaylandDragContext *wayland_context;
+ struct wl_data_offer *wl_offer;
GdkAtom selection;
+ wayland_context = GDK_WAYLAND_DRAG_CONTEXT (context);
selection = gdk_drag_get_selection (context);
+ wl_offer = gdk_wayland_selection_get_offer (display, selection);
- if (gdk_selection_owner_get_for_display (display, selection))
- gdk_wayland_selection_unset_data_source (display, selection);
+ if (success && wayland_context->selected_action &&
+ wayland_context->selected_action != GDK_ACTION_ASK)
+ {
+ gdk_wayland_drag_context_commit_status (context);
+ wl_data_offer_finish (wl_offer);
+ }
gdk_wayland_selection_set_offer (display, selection, NULL);
}
@@ -325,6 +376,67 @@ gdk_wayland_drag_context_set_hotspot (GdkDragContext *context,
gdk_window_invalidate_rect (context_wayland->dnd_window, &damage_rect, FALSE);
}
+static gboolean
+gdk_wayland_drag_context_manage_dnd (GdkDragContext *context,
+ GdkWindow *ipc_window,
+ GdkDragAction actions)
+{
+ GdkWaylandDragContext *context_wayland;
+ GdkWaylandDisplay *display_wayland;
+ GdkDevice *device;
+ GdkWindow *toplevel;
+
+ device = gdk_drag_context_get_device (context);
+ display_wayland = GDK_WAYLAND_DISPLAY (gdk_device_get_display (device));
+ toplevel = _gdk_device_window_at_position (device, NULL, NULL, NULL, TRUE);
+
+ context_wayland = GDK_WAYLAND_DRAG_CONTEXT (context);
+ wl_data_source_set_actions (context_wayland->data_source,
+ gdk_to_wl_actions (actions));
+
+ wl_data_device_start_drag (gdk_wayland_device_get_data_device (device),
+ context_wayland->data_source,
+ gdk_wayland_window_get_wl_surface (toplevel),
+ context_wayland->dnd_surface,
+ _gdk_wayland_display_get_serial (display_wayland));
+
+ gdk_seat_ungrab (gdk_device_get_seat (device));
+
+ return TRUE;
+}
+
+static void
+gdk_wayland_drag_context_set_cursor (GdkDragContext *context,
+ GdkCursor *cursor)
+{
+ GdkDevice *device = gdk_drag_context_get_device (context);
+
+ gdk_wayland_seat_set_global_cursor (gdk_device_get_seat (device), cursor);
+}
+
+static void
+gdk_wayland_drag_context_action_changed (GdkDragContext *context,
+ GdkDragAction action)
+{
+ GdkCursor *cursor;
+
+ cursor = gdk_drag_get_cursor (action);
+ gdk_drag_context_set_cursor (context, cursor);
+}
+
+static void
+gdk_wayland_drag_context_drop_performed (GdkDragContext *context,
+ guint32 time_)
+{
+ gdk_drag_context_set_cursor (context, NULL);
+}
+
+static void
+gdk_wayland_drag_context_cancel (GdkDragContext *context)
+{
+ gdk_drag_context_set_cursor (context, NULL);
+}
+
static void
gdk_wayland_drag_context_class_init (GdkWaylandDragContextClass *klass)
{
@@ -344,6 +456,11 @@ gdk_wayland_drag_context_class_init (GdkWaylandDragContextClass *klass)
context_class->get_selection = gdk_wayland_drag_context_get_selection;
context_class->get_drag_window = gdk_wayland_drag_context_get_drag_window;
context_class->set_hotspot = gdk_wayland_drag_context_set_hotspot;
+ context_class->manage_dnd = gdk_wayland_drag_context_manage_dnd;
+ context_class->set_cursor = gdk_wayland_drag_context_set_cursor;
+ context_class->action_changed = gdk_wayland_drag_context_action_changed;
+ context_class->drop_performed = gdk_wayland_drag_context_drop_performed;
+ context_class->cancel = gdk_wayland_drag_context_cancel;
}
GdkDragProtocol
@@ -383,13 +500,9 @@ _gdk_wayland_window_drag_begin (GdkWindow *window,
gint y_root)
{
GdkWaylandDragContext *context_wayland;
- GdkWaylandDisplay *display_wayland;
GdkDragContext *context;
- GdkWindow *toplevel;
GList *l;
- toplevel = _gdk_device_window_at_position (device, NULL, NULL, NULL, TRUE);
-
context_wayland = g_object_new (GDK_TYPE_WAYLAND_DRAG_CONTEXT, NULL);
context = GDK_DRAG_CONTEXT (context_wayland);
context->source_window = g_object_ref (window);
@@ -397,7 +510,6 @@ _gdk_wayland_window_drag_begin (GdkWindow *window,
context->targets = g_list_copy (targets);
gdk_drag_context_set_device (context, device);
- display_wayland = GDK_WAYLAND_DISPLAY (gdk_device_get_display (device));
context_wayland->dnd_window = create_dnd_window (gdk_window_get_screen (window));
context_wayland->dnd_surface = gdk_wayland_window_get_wl_surface (context_wayland->dnd_window);
@@ -413,12 +525,6 @@ _gdk_wayland_window_drag_begin (GdkWindow *window,
g_free (mimetype);
}
- wl_data_device_start_drag (gdk_wayland_device_get_data_device (device),
- context_wayland->data_source,
- gdk_wayland_window_get_wl_surface (toplevel),
- context_wayland->dnd_surface,
- _gdk_wayland_display_get_serial (display_wayland));
-
return context;
}
diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h
index 23125cbf05..9e5151702e 100644
--- a/gdk/wayland/gdkprivate-wayland.h
+++ b/gdk/wayland/gdkprivate-wayland.h
@@ -188,7 +188,7 @@ struct wl_data_device * gdk_wayland_device_get_data_device (GdkDevice *gdk_devic
void gdk_wayland_device_set_selection (GdkDevice *gdk_device,
struct wl_data_source *source);
-void gdk_wayland_device_unset_grab (GdkDevice *device);
+GdkDragContext * gdk_wayland_device_get_drop_context (GdkDevice *gdk_device);
void gdk_wayland_device_unset_touch_grab (GdkDevice *device,
GdkEventSequence *sequence);
@@ -258,6 +258,8 @@ void gdk_wayland_selection_store (GdkWindow *window,
struct wl_data_source * gdk_wayland_selection_get_data_source (GdkWindow *owner,
GdkAtom selection);
void gdk_wayland_selection_unset_data_source (GdkDisplay *display, GdkAtom selection);
+gboolean gdk_wayland_selection_set_current_offer_actions (GdkDisplay *display,
+ uint32_t actions);
EGLSurface gdk_wayland_window_get_egl_surface (GdkWindow *window,
EGLConfig config);
diff --git a/gdk/wayland/gdkselection-wayland.c b/gdk/wayland/gdkselection-wayland.c
index 1c83c8f6a4..24a4e374bb 100644
--- a/gdk/wayland/gdkselection-wayland.c
+++ b/gdk/wayland/gdkselection-wayland.c
@@ -350,8 +350,69 @@ data_offer_offer (void *data,
info->targets = g_list_prepend (info->targets, atom);
}
+static inline GdkDragAction
+_wl_to_gdk_actions (uint32_t dnd_actions)
+{
+ GdkDragAction actions = 0;
+
+ if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
+ actions |= GDK_ACTION_COPY;
+ if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
+ actions |= GDK_ACTION_MOVE;
+ if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
+ actions |= GDK_ACTION_ASK;
+
+ return actions;
+}
+
+static void
+data_offer_source_actions (void *data,
+ struct wl_data_offer *wl_data_offer,
+ uint32_t source_actions)
+{
+ GdkDragContext *drop_context;
+ GdkDisplay *display;
+ GdkDevice *device;
+ GdkSeat *seat;
+
+ display = gdk_display_get_default ();
+ seat = gdk_display_get_default_seat (display);
+ device = gdk_seat_get_pointer (seat);
+ drop_context = gdk_wayland_device_get_drop_context (device);
+
+ drop_context->actions = _wl_to_gdk_actions (source_actions);
+
+ if (gdk_drag_context_get_dest_window (drop_context))
+ _gdk_wayland_drag_context_emit_event (drop_context, GDK_DRAG_MOTION,
+ GDK_CURRENT_TIME);
+}
+
+static void
+data_offer_action (void *data,
+ struct wl_data_offer *wl_data_offer,
+ uint32_t action)
+{
+ GdkDragContext *drop_context;
+ GdkDisplay *display;
+ GdkDevice *device;
+ GdkSeat *seat;
+
+ display = gdk_display_get_default ();
+ seat = gdk_display_get_default_seat (display);
+ device = gdk_seat_get_pointer (seat);
+ drop_context = gdk_wayland_device_get_drop_context (device);
+
+ drop_context->action = _wl_to_gdk_actions (action);
+
+ if (gdk_drag_context_get_dest_window (drop_context))
+ _gdk_wayland_drag_context_emit_event (drop_context, GDK_DRAG_MOTION,
+ GDK_CURRENT_TIME);
+}
+
static const struct wl_data_offer_listener data_offer_listener = {
data_offer_offer,
+ data_offer_source_actions,
+ data_offer_action
};
DataOfferData *
@@ -569,6 +630,9 @@ gdk_wayland_selection_store (GdkWindow *window,
GdkWaylandSelection *selection = gdk_wayland_display_get_selection (display);
GArray *array;
+ if (type == gdk_atom_intern_static_string ("NULL"))
+ return;
+
array = g_array_new (TRUE, FALSE, sizeof (guchar));
g_array_append_vals (array, data, len);
@@ -701,32 +765,16 @@ data_source_target (void *data,
const char *mime_type)
{
GdkWaylandSelection *wayland_selection = data;
- GdkDragContext *context = NULL;
GdkWindow *window = NULL;
g_debug (G_STRLOC ": %s source = %p, mime_type = %s",
G_STRFUNC, source, mime_type);
- context = gdk_wayland_drag_context_lookup_by_data_source (source);
-
if (!mime_type)
- {
- if (context)
- {
- gdk_wayland_drag_context_set_action (context, 0);
- _gdk_wayland_drag_context_emit_event (context, GDK_DRAG_STATUS,
- GDK_CURRENT_TIME);
- }
- return;
- }
+ return;
if (source == wayland_selection->dnd_source)
- {
- window = wayland_selection->dnd_owner;
- gdk_wayland_drag_context_set_action (context, GDK_ACTION_COPY);
- _gdk_wayland_drag_context_emit_event (context, GDK_DRAG_STATUS,
- GDK_CURRENT_TIME);
- }
+ window = wayland_selection->dnd_owner;
else if (source == wayland_selection->clipboard_source)
window = wayland_selection->clipboard_owner;
@@ -745,7 +793,6 @@ data_source_send (void *data,
int32_t fd)
{
GdkWaylandSelection *wayland_selection = data;
- GdkDragContext *context;
GdkWindow *window;
g_debug (G_STRLOC ": %s source = %p, mime_type = %s, fd = %d",
@@ -757,8 +804,6 @@ data_source_send (void *data,
return;
}
- context = gdk_wayland_drag_context_lookup_by_data_source (source);
-
if (source == wayland_selection->dnd_source)
window = wayland_selection->dnd_owner;
else if (source == wayland_selection->clipboard_source)
@@ -776,13 +821,6 @@ data_source_send (void *data,
gdk_atom_intern (mime_type, FALSE),
fd))
gdk_wayland_selection_check_write (wayland_selection);
-
- if (context)
- {
- _gdk_wayland_drag_context_emit_event (context, GDK_DROP_FINISHED,
- GDK_CURRENT_TIME);
- gdk_wayland_device_unset_grab (gdk_drag_context_get_device (context));
- }
}
static void
@@ -806,22 +844,79 @@ data_source_cancelled (void *data,
else
return;
- gdk_wayland_selection_unset_data_source (display, atom);
+ context = gdk_wayland_drag_context_lookup_by_data_source (source);
+
+ if (context)
+ gdk_drag_context_cancel (context);
+
gdk_selection_owner_set (NULL, atom, GDK_CURRENT_TIME, TRUE);
+ gdk_wayland_selection_unset_data_source (display, atom);
+}
- if (source == wayland_selection->dnd_source)
- {
- context = gdk_wayland_drag_context_lookup_by_data_source (source);
+static void
+data_source_dnd_drop_performed (void *data,
+ struct wl_data_source *source)
+{
+ GdkDragContext *context;
+
+ context = gdk_wayland_drag_context_lookup_by_data_source (source);
+
+ if (!context)
+ return;
+
+ g_signal_emit_by_name (context, "drop-performed", GDK_CURRENT_TIME);
+}
+
+static void
+data_source_dnd_finished (void *data,
+ struct wl_data_source *source)
+{
+ GdkDisplay *display = gdk_display_get_default ();
+ GdkDragContext *context;
+
+ context = gdk_wayland_drag_context_lookup_by_data_source (source);
+
+ if (!context)
+ return;
- if (context)
- gdk_wayland_device_unset_grab (gdk_drag_context_get_device (context));
+ if (context->action == GDK_ACTION_MOVE)
+ {
+ gdk_wayland_selection_emit_request (context->source_window,
+ atoms[ATOM_DND],
+ gdk_atom_intern_static_string ("DELETE"));
}
+
+ g_signal_emit_by_name (context, "dnd-finished");
+ gdk_selection_owner_set (NULL, atoms[ATOM_DND], GDK_CURRENT_TIME, TRUE);
+ gdk_wayland_selection_unset_data_source (display, atoms[ATOM_DND]);
+}
+
+static void
+data_source_action (void *data,
+ struct wl_data_source *source,
+ uint32_t action)
+{
+ GdkDragContext *context;
+
+ g_debug (G_STRLOC ": %s source = %p action=%x",
+ G_STRFUNC, source, action);
+
+ context = gdk_wayland_drag_context_lookup_by_data_source (source);
+
+ if (!context)
+ return;
+
+ context->action = _wl_to_gdk_actions (action);
+ g_signal_emit_by_name (context, "action-changed", context->action);
}
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,
+ data_source_action,
};
struct wl_data_source *
@@ -1009,7 +1104,7 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display,
offer = gdk_wayland_selection_get_offer (display, selection);
target_list = gdk_wayland_selection_get_targets (display, selection);
- if (!offer)
+ if (!offer || target == gdk_atom_intern_static_string ("DELETE"))
{
GdkEvent *event;
@@ -1185,3 +1280,24 @@ gdk_wayland_selection_clear_targets (GdkDisplay *display,
g_array_set_size (wayland_selection->source_targets, 0);
gdk_wayland_selection_unset_data_source (display, selection);
}
+
+gboolean
+gdk_wayland_selection_set_current_offer_actions (GdkDisplay *display,
+ uint32_t action)
+{
+ struct wl_data_offer *offer;
+ uint32_t all_actions = 0;
+
+ offer = gdk_wayland_selection_get_offer (display, atoms[ATOM_DND]);
+
+ if (!offer)
+ return FALSE;
+
+ if (action != 0)
+ all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
+ WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE |
+ WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
+
+ wl_data_offer_set_actions (offer, all_actions, action);
+ return TRUE;
+}
diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c
index 3748112eb9..6c60fed6c7 100644
--- a/gtk/gtkdnd.c
+++ b/gtk/gtkdnd.c
@@ -42,6 +42,10 @@
#endif
#endif
+#ifdef GDK_WINDOWING_WAYLAND
+#include <gdk/wayland/gdkwayland.h>
+#endif
+
#include "gtkgesturedrag.h"
#include "gtkgesturesingle.h"
#include "gtkicontheme.h"
@@ -2174,9 +2178,14 @@ gtk_drag_begin_internal (GtkWidget *widget,
GdkAtom selection;
gboolean managed = FALSE;
+ managed =
#ifdef GDK_WINDOWING_X11
- managed = GDK_IS_X11_DISPLAY (gtk_widget_get_display (widget));
+ GDK_IS_X11_DISPLAY (gtk_widget_get_display (widget)) ||
+#endif
+#ifdef GDK_WINDOWING_WAYLAND
+ GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget)) ||
#endif
+ FALSE;
pointer = keyboard = NULL;
ipc_widget = gtk_drag_get_ipc_widget (widget);