From fff8297a50e23481d2df72d123f2a84e34a866be Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 1 Dec 2015 23:33:53 -0500 Subject: [PATCH] Add gdk_drag_context_get_drag_window This makes gdk_wayland_drag_context_get_dnd_window backend-independent API and adds an implementation for X11. --- docs/reference/gdk/gdk3-sections.txt | 1 + gdk/gdkdnd.c | 26 +++++++++++++++++++ gdk/gdkdnd.h | 3 +++ gdk/gdkdndprivate.h | 2 ++ gdk/wayland/gdkdnd-wayland.c | 7 ++++++ gdk/x11/gdkdnd-x11.c | 37 ++++++++++++++++++++++++++++ 6 files changed, 76 insertions(+) diff --git a/docs/reference/gdk/gdk3-sections.txt b/docs/reference/gdk/gdk3-sections.txt index 8309d1d977..b26ede0ae2 100644 --- a/docs/reference/gdk/gdk3-sections.txt +++ b/docs/reference/gdk/gdk3-sections.txt @@ -967,6 +967,7 @@ gdk_drag_context_set_device gdk_drag_context_get_source_window gdk_drag_context_get_dest_window gdk_drag_context_get_protocol +gdk_drag_context_get_drag_window GDK_DRAG_CONTEXT diff --git a/gdk/gdkdnd.c b/gdk/gdkdnd.c index 2957fe2663..691b52bff5 100644 --- a/gdk/gdkdnd.c +++ b/gdk/gdkdnd.c @@ -454,3 +454,29 @@ gdk_drag_get_selection (GdkDragContext *context) return GDK_DRAG_CONTEXT_GET_CLASS (context)->get_selection (context); } + +/** + * gdk_drag_context_get_drag_window: + * @context: a #GdkDragContext + * + * Returns the window on which the drag icon should be rendered + * during the drag operation. Note that the window may not be + * available until the drag operation has begun. GDK will move + * the window in accordance with the ongoing drag operation. + * The window is owned by @context and will be destroyed when + * the drag operation is over. + * + * Returns: (transfer none): the drag window, or %NULL + * + * Since: 3.20 + */ +GdkWindow * +gdk_drag_context_get_drag_window (GdkDragContext *context) +{ + g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL); + + if (GDK_DRAG_CONTEXT_GET_CLASS (context)->get_drag_window) + return GDK_DRAG_CONTEXT_GET_CLASS (context)->get_drag_window (context); + + return NULL; +} diff --git a/gdk/gdkdnd.h b/gdk/gdkdnd.h index 8871b2a6b8..4d2cd65a7d 100644 --- a/gdk/gdkdnd.h +++ b/gdk/gdkdnd.h @@ -171,6 +171,9 @@ void gdk_drag_abort (GdkDragContext *context, GDK_AVAILABLE_IN_ALL gboolean gdk_drag_drop_succeeded (GdkDragContext *context); +GDK_AVAILABLE_IN_3_20 +GdkWindow *gdk_drag_context_get_drag_window (GdkDragContext *context); + G_END_DECLS #endif /* __GDK_DND_H__ */ diff --git a/gdk/gdkdndprivate.h b/gdk/gdkdndprivate.h index 90c3a20d4a..be1626fcbd 100644 --- a/gdk/gdkdndprivate.h +++ b/gdk/gdkdndprivate.h @@ -62,6 +62,7 @@ struct _GdkDragContextClass { gboolean success, guint32 time_); gboolean (*drop_status) (GdkDragContext *context); + GdkWindow* (*get_drag_window) (GdkDragContext *context); }; struct _GdkDragContext { @@ -73,6 +74,7 @@ struct _GdkDragContext { gboolean is_source; GdkWindow *source_window; GdkWindow *dest_window; + GdkWindow *drag_window; GList *targets; GdkDragAction actions; diff --git a/gdk/wayland/gdkdnd-wayland.c b/gdk/wayland/gdkdnd-wayland.c index 70956868aa..7a07078bd5 100644 --- a/gdk/wayland/gdkdnd-wayland.c +++ b/gdk/wayland/gdkdnd-wayland.c @@ -293,6 +293,12 @@ gdk_wayland_drag_context_init (GdkWaylandDragContext *context_wayland) context->actions = GDK_ACTION_COPY | GDK_ACTION_MOVE; } +static GdkWindow * +gdk_wayland_drag_context_get_drag_window (GdkDragContext *context) +{ + return GDK_WAYLAND_DRAG_CONTEXT (context)->dnd_window; +} + static void gdk_wayland_drag_context_class_init (GdkWaylandDragContextClass *klass) { @@ -310,6 +316,7 @@ gdk_wayland_drag_context_class_init (GdkWaylandDragContextClass *klass) context_class->drop_finish = gdk_wayland_drag_context_drop_finish; context_class->drop_status = gdk_wayland_drag_context_drop_status; context_class->get_selection = gdk_wayland_drag_context_get_selection; + context_class->get_drag_window = gdk_wayland_drag_context_get_drag_window; } GdkDragProtocol diff --git a/gdk/x11/gdkdnd-x11.c b/gdk/x11/gdkdnd-x11.c index e38e1f35fb..4c818301d3 100644 --- a/gdk/x11/gdkdnd-x11.c +++ b/gdk/x11/gdkdnd-x11.c @@ -85,6 +85,8 @@ struct _GdkX11DragContext GSList *window_caches; + GdkWindow *drag_window; + Window dest_xid; /* The last window we looked up */ Window drop_xid; /* The (non-proxied) window that is receiving drops */ guint xdnd_targets_set : 1; /* Whether we've already set XdndTypeList */ @@ -183,6 +185,12 @@ static void gdk_x11_drag_context_drop_finish (GdkDragContext *context, static gboolean gdk_x11_drag_context_drop_status (GdkDragContext *context); static GdkAtom gdk_x11_drag_context_get_selection (GdkDragContext *context); +static GdkWindow * +gdk_x11_drag_context_get_drag_window (GdkDragContext *context) +{ + return GDK_X11_DRAG_CONTEXT (context)->drag_window; +} + static void gdk_x11_drag_context_class_init (GdkX11DragContextClass *klass) { @@ -200,6 +208,7 @@ gdk_x11_drag_context_class_init (GdkX11DragContextClass *klass) context_class->drop_finish = gdk_x11_drag_context_drop_finish; context_class->drop_status = gdk_x11_drag_context_drop_status; context_class->get_selection = gdk_x11_drag_context_get_selection; + context_class->get_drag_window = gdk_x11_drag_context_get_drag_window; } static void @@ -1914,6 +1923,26 @@ gdk_drag_do_leave (GdkX11DragContext *context_x11, } } +static GdkWindow * +create_drag_window (GdkScreen *screen) +{ + GdkWindowAttr attrs; + guint mask; + + 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_rgba_visual (screen); + if (!attrs.visual) + 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_x11_window_drag_begin (GdkWindow *window, GdkDevice *device, @@ -1934,6 +1963,8 @@ _gdk_x11_window_drag_begin (GdkWindow *window, gdk_drag_context_set_device (context, device); + GDK_X11_DRAG_CONTEXT (context)->drag_window = create_drag_window (gdk_window_get_screen (window)); + return context; } @@ -2088,6 +2119,12 @@ gdk_x11_drag_context_drag_motion (GdkDragContext *context, GdkX11DragContext *context_x11 = GDK_X11_DRAG_CONTEXT (context); GdkWindowImplX11 *impl; + if (context_x11->drag_window) + { + gdk_window_move (context_x11->drag_window, x_root, y_root); + gdk_window_raise (context_x11->drag_window); + } + context_x11->old_actions = context->actions; context->actions = possible_actions;