diff options
Diffstat (limited to 'gtk/gtkiconview.c')
-rw-r--r-- | gtk/gtkiconview.c | 358 |
1 files changed, 167 insertions, 191 deletions
diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c index 8c5962d1fa..c662156488 100644 --- a/gtk/gtkiconview.c +++ b/gtk/gtkiconview.c @@ -30,7 +30,6 @@ #include "gtkcellrenderertext.h" #include "gtkcombobox.h" #include "gtkcssnodeprivate.h" -#include "gtkdnd.h" #include "gtkdragdest.h" #include "gtkdragsource.h" #include "gtkentry.h" @@ -48,6 +47,11 @@ #include "gtkwidgetprivate.h" #include "gtkwindow.h" #include "gtkeventcontrollerkey.h" +#include "gtkdragsource.h" +#include "gtkdragdest.h" +#include "gtkdragicon.h" +#include "gtkselectionprivate.h" +#include "gtknative.h" #include "a11y/gtkiconviewaccessibleprivate.h" @@ -279,30 +283,28 @@ static void update_text_cell (GtkIco static void update_pixbuf_cell (GtkIconView *icon_view); /* Source side drag signals */ -static void gtk_icon_view_drag_begin (GtkWidget *widget, - GdkDrag *drag); -static void gtk_icon_view_drag_end (GtkWidget *widget, - GdkDrag *drag); -static void gtk_icon_view_drag_data_get (GtkWidget *widget, - GdkDrag *drag, - GtkSelectionData *selection_data); -static void gtk_icon_view_drag_data_delete (GtkWidget *widget, - GdkDrag *drag); +static void gtk_icon_view_dnd_finished_cb (GdkDrag *drag, + GtkWidget *widget); +static GBytes * gtk_icon_view_drag_data_get (const char *mime_type, + gpointer data); /* Target side drag signals */ -static void gtk_icon_view_drag_leave (GtkWidget *widget, - GdkDrop *drop); -static gboolean gtk_icon_view_drag_motion (GtkWidget *widget, +static void gtk_icon_view_drag_leave (GtkDropTarget *dest, GdkDrop *drop, - gint x, - gint y); -static gboolean gtk_icon_view_drag_drop (GtkWidget *widget, + GtkIconView *icon_view); +static void gtk_icon_view_drag_motion (GtkDropTarget *dest, GdkDrop *drop, - gint x, - gint y); -static void gtk_icon_view_drag_data_received (GtkWidget *widget, + int x, + int y, + GtkIconView *icon_view); +static gboolean gtk_icon_view_drag_drop (GtkDropTarget *dest, GdkDrop *drop, - GtkSelectionData *selection_data); + int x, + int y, + GtkIconView *icon_view); +static void gtk_icon_view_drag_data_received (GObject *source, + GAsyncResult *result, + gpointer data); static gboolean gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view, double x, double y, @@ -360,14 +362,6 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) widget_class->measure = gtk_icon_view_measure; widget_class->size_allocate = gtk_icon_view_size_allocate; widget_class->snapshot = gtk_icon_view_snapshot; - widget_class->drag_begin = gtk_icon_view_drag_begin; - widget_class->drag_end = gtk_icon_view_drag_end; - widget_class->drag_data_get = gtk_icon_view_drag_data_get; - widget_class->drag_data_delete = gtk_icon_view_drag_data_delete; - widget_class->drag_leave = gtk_icon_view_drag_leave; - widget_class->drag_motion = gtk_icon_view_drag_motion; - widget_class->drag_drop = gtk_icon_view_drag_drop; - widget_class->drag_data_received = gtk_icon_view_drag_data_received; container_class->remove = gtk_icon_view_remove; container_class->forall = gtk_icon_view_forall; @@ -1033,6 +1027,8 @@ gtk_icon_view_dispose (GObject *object) g_clear_object (&priv->key_controller); + g_clear_pointer (&priv->source_formats, gdk_content_formats_unref); + G_OBJECT_CLASS (gtk_icon_view_parent_class)->dispose (object); } @@ -1761,9 +1757,14 @@ gtk_icon_view_snapshot (GtkWidget *widget, break; } - gtk_snapshot_render_focus (snapshot, context, + gtk_style_context_save_to_node (context, icon_view->priv->dndnode); + gtk_style_context_set_state (context, gtk_style_context_get_state (context) | GTK_STATE_FLAG_DROP_ACTIVE); + + gtk_snapshot_render_frame (snapshot, context, rect.x, rect.y, rect.width, rect.height); + + gtk_style_context_restore (context); } if (icon_view->priv->doing_rubberband) @@ -5712,35 +5713,6 @@ unset_reorderable (GtkIconView *icon_view) } } -static void -set_source_row (GdkDrag *drag, - GtkTreeModel *model, - GtkTreePath *source_row) -{ - if (source_row) - g_object_set_data_full (G_OBJECT (drag), - I_("gtk-icon-view-source-row"), - gtk_tree_row_reference_new (model, source_row), - (GDestroyNotify) gtk_tree_row_reference_free); - else - g_object_set_data_full (G_OBJECT (drag), - I_("gtk-icon-view-source-row"), - NULL, NULL); -} - -static GtkTreePath* -get_source_row (GdkDrag *drag) -{ - GtkTreeRowReference *ref; - - ref = g_object_get_data (G_OBJECT (drag), "gtk-icon-view-source-row"); - - if (ref) - return gtk_tree_row_reference_get_path (ref); - else - return NULL; -} - typedef struct { GtkTreeRowReference *dest_row; @@ -5886,7 +5858,7 @@ drag_scroll_timeout (gpointer data) static gboolean set_destination (GtkIconView *icon_view, - GdkDrop *drop, + GtkDropTarget *dest, gint x, gint y, GdkDragAction *suggested_action, @@ -5919,8 +5891,7 @@ set_destination (GtkIconView *icon_view, return FALSE; /* no longer a drop site */ } - *target = gtk_drag_dest_find_target (widget, drop, - gtk_drag_dest_get_target_list (widget)); + *target = gtk_drop_target_find_mimetype (dest); if (*target == NULL) return FALSE; @@ -6030,11 +6001,14 @@ gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view, double y, GdkDevice *device) { - GtkWidget *widget = GTK_WIDGET (icon_view); - GdkDrag *drag; GtkTreePath *path = NULL; GtkTreeModel *model; gboolean retval = FALSE; + GdkContentProvider *content; + GdkPaintable *icon; + GtkIconViewItem *item; + GdkSurface *surface; + GdkDrag *drag; if (!icon_view->priv->source_set) goto out; @@ -6055,16 +6029,19 @@ gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view, icon_view->priv->pressed_button = -1; - path = gtk_icon_view_get_path_at_pos (icon_view, - icon_view->priv->press_start_x, - icon_view->priv->press_start_y); + item = _gtk_icon_view_get_item_at_coords (icon_view, + icon_view->priv->press_start_x, + icon_view->priv->press_start_y, + TRUE, + NULL); - if (path == NULL) + if (item == NULL) goto out; + path = gtk_tree_path_new_from_indices (item->index, -1); + if (!GTK_IS_TREE_DRAG_SOURCE (model) || - !gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (model), - path)) + !gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (model), path)) goto out; /* FIXME Check whether we're a start button, if not return FALSE and @@ -6075,88 +6052,66 @@ gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view, retval = TRUE; - drag = gtk_drag_begin (widget, + surface = gtk_native_get_surface (gtk_widget_get_native (GTK_WIDGET (icon_view))); + + content = gdk_content_provider_new_with_formats (icon_view->priv->source_formats, + gtk_icon_view_drag_data_get, + icon_view); + + drag = gdk_drag_begin (surface, device, - gtk_drag_source_get_target_list (widget), - icon_view->priv->source_actions, + content, + icon_view->priv->source_actions, icon_view->priv->press_start_x, icon_view->priv->press_start_y); - set_source_row (drag, model, path); - - out: - if (path) - gtk_tree_path_free (path); - - return retval; -} - -/* Source side drag signals */ -static void -gtk_icon_view_drag_begin (GtkWidget *widget, - GdkDrag *drag) -{ - GtkIconView *icon_view; - GtkIconViewItem *item; - GdkPaintable *icon; - gint x, y; - GtkTreePath *path; - - icon_view = GTK_ICON_VIEW (widget); + g_object_unref (content); - /* if the user uses a custom DnD impl, we don't set the icon here */ - if (!icon_view->priv->dest_set && !icon_view->priv->source_set) - return; + g_signal_connect (drag, "dnd-finished", G_CALLBACK (gtk_icon_view_dnd_finished_cb), icon_view); - item = _gtk_icon_view_get_item_at_coords (icon_view, - icon_view->priv->press_start_x, - icon_view->priv->press_start_y, - TRUE, - NULL); - - g_return_if_fail (item != NULL); + icon_view->priv->source_item = gtk_tree_row_reference_new (model, path); x = icon_view->priv->press_start_x - item->cell_area.x + icon_view->priv->item_padding; y = icon_view->priv->press_start_y - item->cell_area.y + icon_view->priv->item_padding; - path = gtk_tree_path_new_from_indices (item->index, -1); icon = gtk_icon_view_create_drag_icon (icon_view, path); - gtk_tree_path_free (path); + gtk_drag_icon_set_from_paintable (drag, icon, x, y); + g_object_unref (icon); - gtk_drag_set_icon_paintable (drag, icon, x, y); + icon_view->priv->drag = drag; - g_object_unref (icon); -} + g_object_unref (drag); -static void -gtk_icon_view_drag_end (GtkWidget *widget, - GdkDrag *drag) -{ - /* do nothing */ + out: + if (path) + gtk_tree_path_free (path); + + return retval; } -static void -gtk_icon_view_drag_data_get (GtkWidget *widget, - GdkDrag *drag, - GtkSelectionData *selection_data) +/* Source side drag signals */ +static GBytes * +gtk_icon_view_drag_data_get (const char *mime_type, + gpointer data) { - GtkIconView *icon_view; + GtkIconView *icon_view = data; GtkTreeModel *model; GtkTreePath *source_row; + GtkSelectionData sdata = { 0, }; + + sdata.target = g_intern_string (mime_type); - icon_view = GTK_ICON_VIEW (widget); model = gtk_icon_view_get_model (icon_view); if (model == NULL) - return; + return NULL; if (!icon_view->priv->source_set) - return; - - source_row = get_source_row (drag); + return NULL; + source_row = gtk_tree_row_reference_get_path (icon_view->priv->source_item); if (source_row == NULL) - return; + return NULL; /* We can implement the GTK_TREE_MODEL_ROW target generically for * any model; for DragSource models there are some other formats @@ -6164,29 +6119,31 @@ gtk_icon_view_drag_data_get (GtkWidget *widget, */ if (GTK_IS_TREE_DRAG_SOURCE (model) && - gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model), - source_row, - selection_data)) + gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model), source_row, &sdata)) goto done; /* If drag_data_get does nothing, try providing row data. */ - if (gtk_selection_data_get_target (selection_data) == g_intern_static_string ("GTK_TREE_MODEL_ROW")) - gtk_tree_set_row_drag_data (selection_data, - model, - source_row); + if (gtk_selection_data_get_target (&sdata) == g_intern_static_string ("GTK_TREE_MODEL_ROW")) + gtk_tree_set_row_drag_data (&sdata, model, source_row); done: gtk_tree_path_free (source_row); + + return g_bytes_new_take ((gpointer)gtk_selection_data_get_data (&sdata), + gtk_selection_data_get_length (&sdata)); } static void -gtk_icon_view_drag_data_delete (GtkWidget *widget, - GdkDrag *drag) +gtk_icon_view_dnd_finished_cb (GdkDrag *drag, + GtkWidget *widget) { GtkTreeModel *model; GtkIconView *icon_view; GtkTreePath *source_row; + if (gdk_drag_get_selected_action (drag) != GDK_ACTION_MOVE) + return; + icon_view = GTK_ICON_VIEW (widget); model = gtk_icon_view_get_model (icon_view); @@ -6196,28 +6153,24 @@ gtk_icon_view_drag_data_delete (GtkWidget *widget, if (!icon_view->priv->source_set) return; - source_row = get_source_row (drag); - + source_row = gtk_tree_row_reference_get_path (icon_view->priv->source_item); if (source_row == NULL) return; - gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model), - source_row); + gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model), source_row); gtk_tree_path_free (source_row); - set_source_row (drag, NULL, NULL); + g_clear_pointer (&icon_view->priv->source_item, gtk_tree_row_reference_free); + icon_view->priv->drag = NULL; } /* Target side drag signals */ static void -gtk_icon_view_drag_leave (GtkWidget *widget, - GdkDrop *drop) +gtk_icon_view_drag_leave (GtkDropTarget *dest, + GdkDrop *drop, + GtkIconView *icon_view) { - GtkIconView *icon_view; - - icon_view = GTK_ICON_VIEW (widget); - /* unset any highlight row */ gtk_icon_view_set_drag_dest_item (icon_view, NULL, @@ -6226,26 +6179,24 @@ gtk_icon_view_drag_leave (GtkWidget *widget, remove_scroll_timeout (icon_view); } -static gboolean -gtk_icon_view_drag_motion (GtkWidget *widget, - GdkDrop *drop, - gint x, - gint y) +static void +gtk_icon_view_drag_motion (GtkDropTarget *dest, + GdkDrop *drop, + int x, + int y, + GtkIconView *icon_view) { GtkTreePath *path = NULL; GtkIconViewDropPosition pos; - GtkIconView *icon_view; GdkDragAction suggested_action = 0; GdkAtom target; gboolean empty; - icon_view = GTK_ICON_VIEW (widget); - - if (!set_destination (icon_view, drop, x, y, &suggested_action, &target)) - return FALSE; - - icon_view->priv->event_last_x = x; - icon_view->priv->event_last_y = y; + if (!set_destination (icon_view, dest, x, y, &suggested_action, &target)) + { + gdk_drop_status (drop, 0); + return; + } gtk_icon_view_get_drag_dest_item (icon_view, &path, &pos); @@ -6271,7 +6222,7 @@ gtk_icon_view_drag_motion (GtkWidget *widget, * determining whether to accept the drop */ set_status_pending (drop, suggested_action); - gtk_drag_get_data (widget, drop, target); + gtk_drop_target_read_selection (dest, target, NULL, gtk_icon_view_drag_data_received, icon_view); } else { @@ -6282,27 +6233,24 @@ gtk_icon_view_drag_motion (GtkWidget *widget, if (path) gtk_tree_path_free (path); - - return TRUE; } static gboolean -gtk_icon_view_drag_drop (GtkWidget *widget, - GdkDrop *drop, - gint x, - gint y) +gtk_icon_view_drag_drop (GtkDropTarget *dest, + GdkDrop *drop, + int x, + int y, + GtkIconView *icon_view) { - GtkIconView *icon_view; GtkTreePath *path; GdkDragAction suggested_action = 0; GdkAtom target = NULL; GtkTreeModel *model; gboolean drop_append_mode; - icon_view = GTK_ICON_VIEW (widget); model = gtk_icon_view_get_model (icon_view); - remove_scroll_timeout (GTK_ICON_VIEW (widget)); + remove_scroll_timeout (icon_view); if (!icon_view->priv->dest_set) return FALSE; @@ -6310,7 +6258,7 @@ gtk_icon_view_drag_drop (GtkWidget *widget, if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag-drop")) return FALSE; - if (!set_destination (icon_view, drop, x, y, &suggested_action, &target)) + if (!set_destination (icon_view, dest, x, y, &suggested_action, &target)) return FALSE; path = get_logical_destination (icon_view, &drop_append_mode); @@ -6333,7 +6281,7 @@ gtk_icon_view_drag_drop (GtkWidget *widget, if (target != NULL) { - gtk_drag_get_data (widget, drop, target); + gtk_drop_target_read_selection (dest, target, NULL, gtk_icon_view_drag_data_received, icon_view); return TRUE; } else @@ -6341,16 +6289,16 @@ gtk_icon_view_drag_drop (GtkWidget *widget, } static GdkDragAction -gtk_icon_view_get_action (GtkWidget *treeview, +gtk_icon_view_get_action (GtkWidget *widget, GdkDrop *drop) { + GtkIconView *iconview = GTK_ICON_VIEW (widget); GdkDrag *drag = gdk_drop_get_drag (drop); - GtkWidget *source_widget = gtk_drag_get_source_widget (drag); GdkDragAction actions; actions = gdk_drop_get_actions (drop); - if (source_widget == treeview && + if (drag == iconview->priv->drag && actions & GDK_ACTION_MOVE) return GDK_ACTION_MOVE; @@ -6367,25 +6315,31 @@ gtk_icon_view_get_action (GtkWidget *treeview, } static void -gtk_icon_view_drag_data_received (GtkWidget *widget, - GdkDrop *drop, - GtkSelectionData *selection_data) +gtk_icon_view_drag_data_received (GObject *source, + GAsyncResult *result, + gpointer data) { + GtkDropTarget *dest = GTK_DROP_TARGET (source); + GtkIconView *icon_view = data; + GdkDrop *drop = gtk_drop_target_get_drop (dest); GtkTreePath *path; GtkTreeModel *model; - GtkIconView *icon_view; GtkTreePath *dest_row; GdkDragAction suggested_action; gboolean drop_append_mode; - - icon_view = GTK_ICON_VIEW (widget); + GtkSelectionData *selection_data; + + selection_data = gtk_drop_target_read_selection_finish (dest, result, NULL); + if (!selection_data) + return; + model = gtk_icon_view_get_model (icon_view); if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag-data-received")) - return; + goto out; if (!icon_view->priv->dest_set) - return; + goto out; suggested_action = get_status_pending (drop); @@ -6419,18 +6373,18 @@ gtk_icon_view_drag_data_received (GtkWidget *widget, gtk_icon_view_set_drag_dest_item (icon_view, NULL, GTK_ICON_VIEW_DROP_LEFT); - return; + goto out; } dest_row = get_dest_row (drop); if (dest_row == NULL) - return; + goto out; if (gtk_selection_data_get_length (selection_data) >= 0) { - suggested_action = gtk_icon_view_get_action (widget, drop); + suggested_action = gtk_icon_view_get_action (GTK_WIDGET (icon_view), drop); if (suggested_action && !gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model), @@ -6445,9 +6399,13 @@ gtk_icon_view_drag_data_received (GtkWidget *widget, /* drop dest_row */ set_dest_row (drop, NULL, NULL, FALSE, FALSE); + +out: + gtk_selection_data_free (selection_data); } /* Drag-and-Drop support */ + /** * gtk_icon_view_enable_model_drag_source: * @icon_view: a #GtkIconView @@ -6467,9 +6425,7 @@ gtk_icon_view_enable_model_drag_source (GtkIconView *icon_view, { g_return_if_fail (GTK_IS_ICON_VIEW (icon_view)); - gtk_drag_source_set (GTK_WIDGET (icon_view), 0, formats, actions); - - icon_view->priv->start_button_mask = start_button_mask; + icon_view->priv->source_formats = gdk_content_formats_ref (formats); icon_view->priv->source_actions = actions; icon_view->priv->source_set = TRUE; @@ -6486,21 +6442,37 @@ gtk_icon_view_enable_model_drag_source (GtkIconView *icon_view, * * Turns @icon_view into a drop destination for automatic DND. Calling this * method sets #GtkIconView:reorderable to %FALSE. + * + * Returns: (transfer none): the drop target that was attached **/ -void +GtkDropTarget * gtk_icon_view_enable_model_drag_dest (GtkIconView *icon_view, GdkContentFormats *formats, GdkDragAction actions) { - g_return_if_fail (GTK_IS_ICON_VIEW (icon_view)); + g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL); + GtkCssNode *widget_node; - gtk_drag_dest_set (GTK_WIDGET (icon_view), 0, formats, actions); + icon_view->priv->dest = gtk_drop_target_new (formats, actions); + g_signal_connect (icon_view->priv->dest, "drag-leave", G_CALLBACK (gtk_icon_view_drag_leave), icon_view); + g_signal_connect (icon_view->priv->dest, "drag-motion", G_CALLBACK (gtk_icon_view_drag_motion), icon_view); + g_signal_connect (icon_view->priv->dest, "drag-drop", G_CALLBACK (gtk_icon_view_drag_drop), icon_view); + gtk_widget_add_controller (GTK_WIDGET (icon_view), GTK_EVENT_CONTROLLER (icon_view->priv->dest)); icon_view->priv->dest_actions = actions; icon_view->priv->dest_set = TRUE; unset_reorderable (icon_view); + + widget_node = gtk_widget_get_css_node (GTK_WIDGET (icon_view)); + icon_view->priv->dndnode = gtk_css_node_new (); + gtk_css_node_set_name (icon_view->priv->dndnode, I_("dndtarget")); + gtk_css_node_set_parent (icon_view->priv->dndnode, widget_node); + gtk_css_node_set_state (icon_view->priv->dndnode, gtk_css_node_get_state (widget_node)); + g_object_unref (icon_view->priv->dndnode); + + return icon_view->priv->dest; } /** @@ -6517,7 +6489,7 @@ gtk_icon_view_unset_model_drag_source (GtkIconView *icon_view) if (icon_view->priv->source_set) { - gtk_drag_source_unset (GTK_WIDGET (icon_view)); + g_clear_pointer (&icon_view->priv->source_formats, gdk_content_formats_unref); icon_view->priv->source_set = FALSE; } @@ -6538,8 +6510,12 @@ gtk_icon_view_unset_model_drag_dest (GtkIconView *icon_view) if (icon_view->priv->dest_set) { - gtk_drag_dest_unset (GTK_WIDGET (icon_view)); + gtk_widget_remove_controller (GTK_WIDGET (icon_view), GTK_EVENT_CONTROLLER (icon_view->priv->dest)); + icon_view->priv->dest = NULL; icon_view->priv->dest_set = FALSE; + + gtk_css_node_set_parent (icon_view->priv->dndnode, NULL); + icon_view->priv->dndnode = NULL; } unset_reorderable (icon_view); |