forked from AuroraMiddleware/gtk
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.
This commit is contained in:
parent
0747a60129
commit
1045dda035
@ -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;
|
||||
}
|
||||
|
@ -314,8 +314,10 @@ gdk_registry_handle_global (void *data,
|
||||
}
|
||||
else if (strcmp (interface, "wl_data_device_manager") == 0)
|
||||
{
|
||||
display_wayland->data_device_manager_version = MIN (version, 3);
|
||||
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,
|
||||
display_wayland->data_device_manager_version);
|
||||
}
|
||||
else if (strcmp (interface, "wl_subcompositor") == 0)
|
||||
{
|
||||
|
@ -93,6 +93,7 @@ struct _GdkWaylandDisplay
|
||||
|
||||
int compositor_version;
|
||||
int seat_version;
|
||||
int data_device_manager_version;
|
||||
|
||||
struct xkb_context *xkb_context;
|
||||
|
||||
|
@ -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));
|
||||
@ -240,12 +262,33 @@ gdk_wayland_drop_context_set_status (GdkDragContext *context,
|
||||
wl_data_offer_accept (wl_offer, context_wayland->serial, NULL);
|
||||
}
|
||||
|
||||
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,24 @@ gdk_wayland_drag_context_drop_finish (GdkDragContext *context,
|
||||
guint32 time)
|
||||
{
|
||||
GdkDisplay *display = gdk_device_get_display (gdk_drag_context_get_device (context));
|
||||
GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (display);
|
||||
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);
|
||||
|
||||
if (wayland_display->data_device_manager_version >=
|
||||
WL_DATA_OFFER_FINISH_SINCE_VERSION)
|
||||
wl_data_offer_finish (wl_offer);
|
||||
}
|
||||
|
||||
gdk_wayland_selection_set_offer (display, selection, NULL);
|
||||
}
|
||||
@ -325,6 +380,72 @@ 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);
|
||||
|
||||
if (display_wayland->data_device_manager_version >=
|
||||
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION)
|
||||
{
|
||||
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 +465,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 +509,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 +519,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 +534,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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
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->action == GDK_ACTION_MOVE)
|
||||
{
|
||||
context = gdk_wayland_drag_context_lookup_by_data_source (source);
|
||||
|
||||
if (context)
|
||||
gdk_wayland_device_unset_grab (gdk_drag_context_get_device (context));
|
||||
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,27 @@ 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)
|
||||
{
|
||||
GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (display);
|
||||
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;
|
||||
|
||||
if (wayland_display->data_device_manager_version >=
|
||||
WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION)
|
||||
wl_data_offer_set_actions (offer, all_actions, action);
|
||||
return TRUE;
|
||||
}
|
||||
|
11
gtk/gtkdnd.c
11
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);
|
||||
|
Loading…
Reference in New Issue
Block a user