summaryrefslogtreecommitdiff
path: root/gtk/gtkdnd.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/gtkdnd.c')
-rw-r--r--gtk/gtkdnd.c495
1 files changed, 3 insertions, 492 deletions
diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c
index 48be48c355..71913b03d9 100644
--- a/gtk/gtkdnd.c
+++ b/gtk/gtkdnd.c
@@ -46,6 +46,7 @@
#include <gdk/wayland/gdkwayland.h>
#endif
+#include "gtkdragdest.h"
#include "gtkgesturedrag.h"
#include "gtkgesturesingle.h"
#include "gtkicontheme.h"
@@ -79,7 +80,6 @@
static GSList *source_widgets = NULL;
typedef struct _GtkDragSourceInfo GtkDragSourceInfo;
-typedef struct _GtkDragDestSite GtkDragDestSite;
typedef struct _GtkDragDestInfo GtkDragDestInfo;
@@ -121,19 +121,6 @@ struct _GtkDragSourceInfo
guint have_grab : 1; /* Do we still have the pointer grab */
};
-struct _GtkDragDestSite
-{
- GtkDestDefaults flags;
- GtkTargetList *target_list;
- GdkDragAction actions;
- GdkWindow *proxy_window;
- GdkDragProtocol proxy_protocol;
- guint do_proxy : 1;
- guint proxy_coords : 1;
- guint have_drag : 1;
- guint track_motion : 1;
-};
-
struct _GtkDragDestInfo
{
GtkWidget *widget; /* Widget in which drag is in */
@@ -192,10 +179,6 @@ static gboolean gtk_drag_find_widget (GtkWidget *widget,
static void gtk_drag_proxy_begin (GtkWidget *widget,
GtkDragDestInfo *dest_info,
guint32 time);
-static void gtk_drag_dest_realized (GtkWidget *widget);
-static void gtk_drag_dest_hierarchy_changed (GtkWidget *widget,
- GtkWidget *previous_toplevel);
-static void gtk_drag_dest_site_destroy (gpointer data);
static void gtk_drag_dest_leave (GtkWidget *widget,
GdkDragContext *context,
guint time);
@@ -1025,381 +1008,6 @@ gtk_drag_unhighlight (GtkWidget *widget)
gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_DROP_ACTIVE);
}
-static void
-gtk_drag_dest_set_internal (GtkWidget *widget,
- GtkDragDestSite *site)
-{
- GtkDragDestSite *old_site;
-
- g_return_if_fail (widget != NULL);
-
- /* HACK, do this in the destroy */
- old_site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
- if (old_site)
- {
- g_signal_handlers_disconnect_by_func (widget,
- gtk_drag_dest_realized,
- old_site);
- g_signal_handlers_disconnect_by_func (widget,
- gtk_drag_dest_hierarchy_changed,
- old_site);
-
- site->track_motion = old_site->track_motion;
- }
-
- if (gtk_widget_get_realized (widget))
- gtk_drag_dest_realized (widget);
-
- g_signal_connect (widget, "realize",
- G_CALLBACK (gtk_drag_dest_realized), site);
- g_signal_connect (widget, "hierarchy-changed",
- G_CALLBACK (gtk_drag_dest_hierarchy_changed), site);
-
- g_object_set_data_full (G_OBJECT (widget), I_("gtk-drag-dest"),
- site, gtk_drag_dest_site_destroy);
-}
-
-/**
- * gtk_drag_dest_set: (method)
- * @widget: a #GtkWidget
- * @flags: which types of default drag behavior to use
- * @targets: (allow-none) (array length=n_targets): a pointer to an array of
- * #GtkTargetEntrys indicating the drop types that this @widget will
- * accept, or %NULL. Later you can access the list with
- * gtk_drag_dest_get_target_list() and gtk_drag_dest_find_target().
- * @n_targets: the number of entries in @targets
- * @actions: a bitmask of possible actions for a drop onto this @widget.
- *
- * Sets a widget as a potential drop destination, and adds default behaviors.
- *
- * The default behaviors listed in @flags have an effect similar
- * to installing default handlers for the widget’s drag-and-drop signals
- * (#GtkWidget::drag-motion, #GtkWidget::drag-drop, ...). They all exist
- * for convenience. When passing #GTK_DEST_DEFAULT_ALL for instance it is
- * sufficient to connect to the widget’s #GtkWidget::drag-data-received
- * signal to get primitive, but consistent drag-and-drop support.
- *
- * Things become more complicated when you try to preview the dragged data,
- * as described in the documentation for #GtkWidget::drag-motion. The default
- * behaviors described by @flags make some assumptions, that can conflict
- * with your own signal handlers. For instance #GTK_DEST_DEFAULT_DROP causes
- * invokations of gdk_drag_status() in the context of #GtkWidget::drag-motion,
- * and invokations of gtk_drag_finish() in #GtkWidget::drag-data-received.
- * Especially the later is dramatic, when your own #GtkWidget::drag-motion
- * handler calls gtk_drag_get_data() to inspect the dragged data.
- *
- * There’s no way to set a default action here, you can use the
- * #GtkWidget::drag-motion callback for that. Here’s an example which selects
- * the action to use depending on whether the control key is pressed or not:
- * |[<!-- language="C" -->
- * static void
- * drag_motion (GtkWidget *widget,
- * GdkDragContext *context,
- * gint x,
- * gint y,
- * guint time)
- * {
- * GdkModifierType mask;
- *
- * gdk_window_get_pointer (gtk_widget_get_window (widget),
- * NULL, NULL, &mask);
- * if (mask & GDK_CONTROL_MASK)
- * gdk_drag_status (context, GDK_ACTION_COPY, time);
- * else
- * gdk_drag_status (context, GDK_ACTION_MOVE, time);
- * }
- * ]|
- */
-void
-gtk_drag_dest_set (GtkWidget *widget,
- GtkDestDefaults flags,
- const GtkTargetEntry *targets,
- gint n_targets,
- GdkDragAction actions)
-{
- GtkDragDestSite *site;
-
- g_return_if_fail (GTK_IS_WIDGET (widget));
-
- site = g_slice_new0 (GtkDragDestSite);
-
- site->flags = flags;
- site->have_drag = FALSE;
- if (targets)
- site->target_list = gtk_target_list_new (targets, n_targets);
- else
- site->target_list = NULL;
- site->actions = actions;
- site->do_proxy = FALSE;
- site->proxy_window = NULL;
- site->track_motion = FALSE;
-
- gtk_drag_dest_set_internal (widget, site);
-}
-
-/**
- * gtk_drag_dest_set_proxy: (method)
- * @widget: a #GtkWidget
- * @proxy_window: the window to which to forward drag events
- * @protocol: the drag protocol which the @proxy_window accepts
- * (You can use gdk_drag_get_protocol() to determine this)
- * @use_coordinates: If %TRUE, send the same coordinates to the
- * destination, because it is an embedded
- * subwindow.
- *
- * Sets this widget as a proxy for drops to another window.
- */
-void
-gtk_drag_dest_set_proxy (GtkWidget *widget,
- GdkWindow *proxy_window,
- GdkDragProtocol protocol,
- gboolean use_coordinates)
-{
- GtkDragDestSite *site;
-
- g_return_if_fail (GTK_IS_WIDGET (widget));
- g_return_if_fail (!proxy_window || GDK_IS_WINDOW (proxy_window));
-
- site = g_slice_new (GtkDragDestSite);
-
- site->flags = 0;
- site->have_drag = FALSE;
- site->target_list = NULL;
- site->actions = 0;
- site->proxy_window = proxy_window;
- if (proxy_window)
- g_object_ref (proxy_window);
- site->do_proxy = TRUE;
- site->proxy_protocol = protocol;
- site->proxy_coords = use_coordinates;
- site->track_motion = FALSE;
-
- gtk_drag_dest_set_internal (widget, site);
-}
-
-/**
- * gtk_drag_dest_unset: (method)
- * @widget: a #GtkWidget
- *
- * Clears information about a drop destination set with
- * gtk_drag_dest_set(). The widget will no longer receive
- * notification of drags.
- */
-void
-gtk_drag_dest_unset (GtkWidget *widget)
-{
- GtkDragDestSite *old_site;
-
- g_return_if_fail (GTK_IS_WIDGET (widget));
-
- old_site = g_object_get_data (G_OBJECT (widget),
- "gtk-drag-dest");
- if (old_site)
- {
- g_signal_handlers_disconnect_by_func (widget,
- gtk_drag_dest_realized,
- old_site);
- g_signal_handlers_disconnect_by_func (widget,
- gtk_drag_dest_hierarchy_changed,
- old_site);
- }
-
- g_object_set_data (G_OBJECT (widget), I_("gtk-drag-dest"), NULL);
-}
-
-/**
- * gtk_drag_dest_get_target_list: (method)
- * @widget: a #GtkWidget
- *
- * Returns the list of targets this widget can accept from
- * drag-and-drop.
- *
- * Returns: (nullable) (transfer none): the #GtkTargetList, or %NULL if none
- */
-GtkTargetList*
-gtk_drag_dest_get_target_list (GtkWidget *widget)
-{
- GtkDragDestSite *site;
-
- g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
-
- site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
-
- return site ? site->target_list : NULL;
-}
-
-/**
- * gtk_drag_dest_set_target_list: (method)
- * @widget: a #GtkWidget that’s a drag destination
- * @target_list: (allow-none): list of droppable targets, or %NULL for none
- *
- * Sets the target types that this widget can accept from drag-and-drop.
- * The widget must first be made into a drag destination with
- * gtk_drag_dest_set().
- */
-void
-gtk_drag_dest_set_target_list (GtkWidget *widget,
- GtkTargetList *target_list)
-{
- GtkDragDestSite *site;
-
- g_return_if_fail (GTK_IS_WIDGET (widget));
-
- site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
-
- if (!site)
- {
- g_warning ("Can't set a target list on a widget until you've called gtk_drag_dest_set() "
- "to make the widget into a drag destination");
- return;
- }
-
- if (target_list)
- gtk_target_list_ref (target_list);
-
- if (site->target_list)
- gtk_target_list_unref (site->target_list);
-
- site->target_list = target_list;
-}
-
-/**
- * gtk_drag_dest_add_text_targets: (method)
- * @widget: a #GtkWidget that’s a drag destination
- *
- * Add the text targets supported by #GtkSelectionData to
- * the target list of the drag destination. The targets
- * are added with @info = 0. If you need another value,
- * use gtk_target_list_add_text_targets() and
- * gtk_drag_dest_set_target_list().
- *
- * Since: 2.6
- */
-void
-gtk_drag_dest_add_text_targets (GtkWidget *widget)
-{
- GtkTargetList *target_list;
-
- target_list = gtk_drag_dest_get_target_list (widget);
- if (target_list)
- gtk_target_list_ref (target_list);
- else
- target_list = gtk_target_list_new (NULL, 0);
- gtk_target_list_add_text_targets (target_list, 0);
- gtk_drag_dest_set_target_list (widget, target_list);
- gtk_target_list_unref (target_list);
-}
-
-/**
- * gtk_drag_dest_add_image_targets: (method)
- * @widget: a #GtkWidget that’s a drag destination
- *
- * Add the image targets supported by #GtkSelectionData to
- * the target list of the drag destination. The targets
- * are added with @info = 0. If you need another value,
- * use gtk_target_list_add_image_targets() and
- * gtk_drag_dest_set_target_list().
- *
- * Since: 2.6
- */
-void
-gtk_drag_dest_add_image_targets (GtkWidget *widget)
-{
- GtkTargetList *target_list;
-
- target_list = gtk_drag_dest_get_target_list (widget);
- if (target_list)
- gtk_target_list_ref (target_list);
- else
- target_list = gtk_target_list_new (NULL, 0);
- gtk_target_list_add_image_targets (target_list, 0, FALSE);
- gtk_drag_dest_set_target_list (widget, target_list);
- gtk_target_list_unref (target_list);
-}
-
-/**
- * gtk_drag_dest_add_uri_targets: (method)
- * @widget: a #GtkWidget that’s a drag destination
- *
- * Add the URI targets supported by #GtkSelectionData to
- * the target list of the drag destination. The targets
- * are added with @info = 0. If you need another value,
- * use gtk_target_list_add_uri_targets() and
- * gtk_drag_dest_set_target_list().
- *
- * Since: 2.6
- */
-void
-gtk_drag_dest_add_uri_targets (GtkWidget *widget)
-{
- GtkTargetList *target_list;
-
- target_list = gtk_drag_dest_get_target_list (widget);
- if (target_list)
- gtk_target_list_ref (target_list);
- else
- target_list = gtk_target_list_new (NULL, 0);
- gtk_target_list_add_uri_targets (target_list, 0);
- gtk_drag_dest_set_target_list (widget, target_list);
- gtk_target_list_unref (target_list);
-}
-
-/**
- * gtk_drag_dest_set_track_motion: (method)
- * @widget: a #GtkWidget that’s a drag destination
- * @track_motion: whether to accept all targets
- *
- * Tells the widget to emit #GtkWidget::drag-motion and
- * #GtkWidget::drag-leave events regardless of the targets and the
- * %GTK_DEST_DEFAULT_MOTION flag.
- *
- * This may be used when a widget wants to do generic
- * actions regardless of the targets that the source offers.
- *
- * Since: 2.10
- */
-void
-gtk_drag_dest_set_track_motion (GtkWidget *widget,
- gboolean track_motion)
-{
- GtkDragDestSite *site;
-
- g_return_if_fail (GTK_IS_WIDGET (widget));
-
- site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
-
- g_return_if_fail (site != NULL);
-
- site->track_motion = track_motion != FALSE;
-}
-
-/**
- * gtk_drag_dest_get_track_motion: (method)
- * @widget: a #GtkWidget that’s a drag destination
- *
- * Returns whether the widget has been configured to always
- * emit #GtkWidget::drag-motion signals.
- *
- * Returns: %TRUE if the widget always emits
- * #GtkWidget::drag-motion events
- *
- * Since: 2.10
- */
-gboolean
-gtk_drag_dest_get_track_motion (GtkWidget *widget)
-{
- GtkDragDestSite *site;
-
- g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
-
- site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
-
- if (site)
- return site->track_motion;
-
- return FALSE;
-}
-
/*
* _gtk_drag_dest_handle_event:
* @toplevel: Toplevel widget that received the event
@@ -1506,70 +1114,6 @@ _gtk_drag_dest_handle_event (GtkWidget *toplevel,
}
}
-/**
- * gtk_drag_dest_find_target: (method)
- * @widget: drag destination widget
- * @context: drag context
- * @target_list: (allow-none): list of droppable targets, or %NULL to use
- * gtk_drag_dest_get_target_list (@widget).
- *
- * Looks for a match between the supported targets of @context and the
- * @dest_target_list, returning the first matching target, otherwise
- * returning %GDK_NONE. @dest_target_list should usually be the return
- * value from gtk_drag_dest_get_target_list(), but some widgets may
- * have different valid targets for different parts of the widget; in
- * that case, they will have to implement a drag_motion handler that
- * passes the correct target list to this function.
- *
- * Returns: (transfer none): first target that the source offers
- * and the dest can accept, or %GDK_NONE
- */
-GdkAtom
-gtk_drag_dest_find_target (GtkWidget *widget,
- GdkDragContext *context,
- GtkTargetList *target_list)
-{
- GList *tmp_target;
- GList *tmp_source = NULL;
- GtkWidget *source_widget;
-
- g_return_val_if_fail (GTK_IS_WIDGET (widget), GDK_NONE);
- g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), GDK_NONE);
-
-
- source_widget = gtk_drag_get_source_widget (context);
-
- if (target_list == NULL)
- target_list = gtk_drag_dest_get_target_list (widget);
-
- if (target_list == NULL)
- return GDK_NONE;
-
- tmp_target = target_list->list;
- while (tmp_target)
- {
- GtkTargetPair *pair = tmp_target->data;
- tmp_source = gdk_drag_context_list_targets (context);
- while (tmp_source)
- {
- if (tmp_source->data == GUINT_TO_POINTER (pair->target))
- {
- if ((!(pair->flags & GTK_TARGET_SAME_APP) || source_widget) &&
- (!(pair->flags & GTK_TARGET_SAME_WIDGET) || (source_widget == widget)) &&
- (!(pair->flags & GTK_TARGET_OTHER_APP) || !source_widget) &&
- (!(pair->flags & GTK_TARGET_OTHER_WIDGET) || (source_widget != widget)))
- return pair->target;
- else
- break;
- }
- tmp_source = tmp_source->next;
- }
- tmp_target = tmp_target->next;
- }
-
- return GDK_NONE;
-}
-
static void
gtk_drag_selection_received (GtkWidget *widget,
GtkSelectionData *selection_data,
@@ -1875,39 +1419,6 @@ gtk_drag_clear_source_info (GdkDragContext *context)
g_object_set_qdata (G_OBJECT (context), dest_info_quark, NULL);
}
-static void
-gtk_drag_dest_realized (GtkWidget *widget)
-{
- GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
-
- if (gtk_widget_is_toplevel (toplevel))
- gdk_window_register_dnd (gtk_widget_get_window (toplevel));
-}
-
-static void
-gtk_drag_dest_hierarchy_changed (GtkWidget *widget,
- GtkWidget *previous_toplevel)
-{
- GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
-
- if (gtk_widget_is_toplevel (toplevel) && gtk_widget_get_realized (toplevel))
- gdk_window_register_dnd (gtk_widget_get_window (toplevel));
-}
-
-static void
-gtk_drag_dest_site_destroy (gpointer data)
-{
- GtkDragDestSite *site = data;
-
- if (site->proxy_window)
- g_object_unref (site->proxy_window);
-
- if (site->target_list)
- gtk_target_list_unref (site->target_list);
-
- g_slice_free (GtkDragDestSite, site);
-}
-
/*
* Default drag handlers
*/
@@ -2765,7 +2276,6 @@ gtk_drag_set_icon_surface (GdkDragContext *context,
rgba_visual != NULL &&
gdk_screen_is_composited (screen);
-
gtk_window_set_screen (GTK_WINDOW (window), screen);
if (has_rgba)
@@ -2793,7 +2303,8 @@ gtk_drag_set_icon_surface (GdkDragContext *context,
cairo_region_destroy (region);
/* Need to saturate the colors, so it doesn't look like semi-transparent
- * pixels were painted on black. */
+ * pixels were painted on black.
+ */
saturated = gdk_window_create_similar_surface (gtk_widget_get_window (window),
CAIRO_CONTENT_COLOR,
extents.width,