diff options
Diffstat (limited to 'gtk/gtkdnd.c')
-rw-r--r-- | gtk/gtkdnd.c | 495 |
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, |