[gtk+/wayland-selections: 10/15] wayland: Implement drag sources
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wayland-selections: 10/15] wayland: Implement drag sources
- Date: Thu, 28 Aug 2014 15:02:15 +0000 (UTC)
commit b4baf8766245b248614b3ef506ff4f6a99575e54
Author: Carlos Garnacho <carlosg gnome org>
Date: Thu Aug 21 21:30:22 2014 +0200
wayland: Implement drag sources
The wl_data_source is retrieved from the selection object for the DnD
selection, and used to initiate a drag. When the drag is finished, a
button release or touch end event is synthesized to finish the DnD
operation after the compositor grab is gone.
gdk/wayland/gdkdnd-wayland.c | 137 +++++++++++++++++++++++++++++++++++++-
gdk/wayland/gdkprivate-wayland.h | 6 ++
2 files changed, 141 insertions(+), 2 deletions(-)
---
diff --git a/gdk/wayland/gdkdnd-wayland.c b/gdk/wayland/gdkdnd-wayland.c
index f1789c2..f40542b 100644
--- a/gdk/wayland/gdkdnd-wayland.c
+++ b/gdk/wayland/gdkdnd-wayland.c
@@ -40,6 +40,9 @@ typedef struct _GdkWaylandDragContextClass GdkWaylandDragContextClass;
struct _GdkWaylandDragContext
{
GdkDragContext context;
+ GdkWindow *dnd_window;
+ struct wl_surface *dnd_surface;
+ struct wl_data_source *data_source;
struct wl_data_offer *offer;
uint32_t serial;
gdouble x;
@@ -259,18 +262,59 @@ _gdk_wayland_window_register_dnd (GdkWindow *window)
{
}
+static GdkWindow *
+create_dnd_window (void)
+{
+ GdkWindowAttr attrs;
+ GdkScreen *screen;
+ guint mask;
+
+ screen = gdk_display_get_default_screen (gdk_display_get_default ());
+
+ attrs.x = attrs.y = 0;
+ attrs.width = attrs.height = 100;
+ attrs.wclass = GDK_INPUT_OUTPUT;
+ attrs.window_type = GDK_WINDOW_TEMP;
+ attrs.type_hint = GDK_WINDOW_TYPE_HINT_DND;
+ attrs.visual = gdk_screen_get_system_visual (screen);
+
+ mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
+
+ return gdk_window_new (gdk_screen_get_root_window (screen), &attrs, mask);
+}
+
GdkDragContext *
_gdk_wayland_window_drag_begin (GdkWindow *window,
GdkDevice *device,
GList *targets)
{
+ GdkWaylandDragContext *context_wayland;
+ GdkWaylandDisplay *display_wayland;
GdkDragContext *context;
+ GdkWindow *toplevel;
- context = (GdkDragContext *) g_object_new (GDK_TYPE_WAYLAND_DRAG_CONTEXT, NULL);
- context->source_window = window;
+ toplevel = gdk_device_get_window_at_position (device, NULL, NULL);
+
+ context_wayland = g_object_new (GDK_TYPE_WAYLAND_DRAG_CONTEXT, NULL);
+ context = GDK_DRAG_CONTEXT (context_wayland);
+ context->source_window = g_object_ref (window);
context->is_source = TRUE;
+ 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 ();
+ context_wayland->dnd_surface = gdk_wayland_window_get_wl_surface (context_wayland->dnd_window);
+ context_wayland->data_source =
+ gdk_wayland_selection_get_data_source (window,
+ gdk_wayland_drag_context_get_selection (context));
+
+ 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;
}
@@ -321,3 +365,92 @@ _gdk_wayland_drag_context_set_dest_window (GdkDragContext *context,
context->actions = GDK_ACTION_COPY | GDK_ACTION_MOVE;
gdk_wayland_drop_context_update_targets (context);
}
+
+GdkDragContext *
+gdk_wayland_drag_context_lookup_by_data_source (struct wl_data_source *source)
+{
+ GList *l;
+
+ for (l = contexts; l; l = l->next)
+ {
+ GdkWaylandDragContext *wayland_context = l->data;
+
+ if (wayland_context->data_source == source)
+ return l->data;
+ }
+
+ return NULL;
+}
+
+GdkDragContext *
+gdk_wayland_drag_context_lookup_by_source_window (GdkWindow *window)
+{
+ GList *l;
+
+ for (l = contexts; l; l = l->next)
+ {
+ if (window == gdk_drag_context_get_source_window (l->data))
+ return l->data;
+ }
+
+ return NULL;
+}
+
+struct wl_data_source *
+gdk_wayland_drag_context_get_data_source (GdkDragContext *context)
+{
+ return GDK_WAYLAND_DRAG_CONTEXT (context)->data_source;
+}
+
+void
+gdk_wayland_drag_context_undo_grab (GdkDragContext *context)
+{
+ GdkEventSequence *sequence;
+ GdkModifierType state;
+ GdkDevice *device;
+ GdkEvent *event;
+ guint button;
+ gdouble x, y;
+
+ device = gdk_drag_context_get_device (context);
+ _gdk_wayland_device_get_last_implicit_grab_serial (GDK_WAYLAND_DEVICE (device), &sequence);
+ gdk_window_get_device_position_double (gdk_drag_context_get_source_window (context),
+ device, &x, &y, &state);
+
+ if (sequence)
+ {
+ event = gdk_event_new (GDK_TOUCH_END);
+ event->touch.window = g_object_ref (gdk_drag_context_get_source_window (context));
+ 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 (gdk_drag_context_get_source_window (context));
+ 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.x_root = y;
+ }
+ else
+ return;
+
+ gdk_event_set_device (event, device);
+ gdk_event_set_source_device (event, device);
+
+ _gdk_wayland_display_deliver_event (gdk_device_get_display (device), event);
+}
diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h
index 55dc34c..cd8201d 100644
--- a/gdk/wayland/gdkprivate-wayland.h
+++ b/gdk/wayland/gdkprivate-wayland.h
@@ -104,6 +104,12 @@ void _gdk_wayland_drag_context_set_coords (GdkDragContext *context,
gdouble x,
gdouble y);
+GdkDragContext * gdk_wayland_drag_context_lookup_by_data_source (struct wl_data_source *source);
+GdkDragContext * gdk_wayland_drag_context_lookup_by_source_window (GdkWindow *window);
+struct wl_data_source * gdk_wayland_drag_context_get_data_source (GdkDragContext *context);
+
+void gdk_wayland_drag_context_undo_grab (GdkDragContext *context);
+
void gdk_wayland_drop_context_update_targets (GdkDragContext *context);
void _gdk_wayland_display_create_window_impl (GdkDisplay *display,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]