[nautilus/wip/antoniof/drag-source-changes] foo




commit 8229f42b6a713f201426d90a48c683ff43d1ae94
Author: António Fernandes <antoniof gnome org>
Date:   Sat Jun 4 19:03:08 2022 +0100

    foo

 src/nautilus-files-view.c           |  46 ---------------
 src/nautilus-view-icon-controller.c | 111 ++++++++++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+), 46 deletions(-)
---
diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c
index 2b4ff4dfd..109d991c2 100644
--- a/src/nautilus-files-view.c
+++ b/src/nautilus-files-view.c
@@ -4198,47 +4198,6 @@ on_end_file_changes (NautilusFilesView *view)
     }
 }
 
-static GdkContentProvider *
-on_drag_prepare (GtkDragSource     *source,
-                 double             x,
-                 double             y,
-                 NautilusFilesView *self)
-{
-    g_autolist (NautilusFile) selection = NULL;
-    g_autoslist (GFile) file_list = NULL;
-    g_autoptr (GdkPaintable) paintable = NULL;
-    g_autoptr (GtkSnapshot) snapshot = NULL;
-    GdkDragAction actions;
-
-    selection = nautilus_files_view_get_selection (NAUTILUS_VIEW (self));
-    if (selection != NULL)
-    {
-        file_list = convert_file_list_to_gdk_file_list (selection);
-        actions = GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK | GDK_ACTION_MOVE;
-        gtk_drag_source_set_actions (source, actions);
-        paintable = nautilus_file_get_icon_paintable (selection->data, NAUTILUS_GRID_ICON_SIZE_LARGE, 1, 0);
-        for (GList *cur_file = selection->next; cur_file != NULL; cur_file = cur_file->next)
-        {
-            g_autoptr (GdkPaintable) paintable2 = NULL;
-            paintable2 = nautilus_file_get_icon_paintable (cur_file->data, NAUTILUS_GRID_ICON_SIZE_LARGE, 1, 
0);
-            if (paintable2 != paintable || cur_file->next == NULL)
-            {
-                snapshot = gtk_snapshot_new ();
-                gdk_paintable_snapshot (paintable, snapshot, NAUTILUS_GRID_ICON_SIZE_LARGE, 
NAUTILUS_GRID_ICON_SIZE_LARGE);
-                gdk_paintable_snapshot (paintable2, snapshot, NAUTILUS_GRID_ICON_SIZE_LARGE * 0.5, 
NAUTILUS_GRID_ICON_SIZE_LARGE * 0.5);
-                g_object_unref (paintable);
-                paintable = gtk_snapshot_to_paintable (snapshot, NULL);
-                break;
-            }
-        }
-
-        gtk_drag_source_set_icon (source, paintable, 0, 0);
-        return gdk_content_provider_new_typed (GDK_TYPE_FILE_LIST, file_list);
-    }
-
-    return NULL;
-}
-
 static int
 compare_pointers (gconstpointer pointer_1,
                   gconstpointer pointer_2)
@@ -9389,7 +9348,6 @@ nautilus_files_view_init (NautilusFilesView *view)
 #endif
     NautilusDirectory *scripts_directory;
     NautilusDirectory *templates_directory;
-    GtkDragSource *drag_source;
     GtkEventController *controller;
     gchar *templates_uri;
     GdkClipboard *clipboard;
@@ -9594,10 +9552,6 @@ nautilus_files_view_init (NautilusFilesView *view)
 
     priv->in_destruction = FALSE;
 
-    drag_source = gtk_drag_source_new ();
-    g_signal_connect (drag_source, "prepare", G_CALLBACK (on_drag_prepare), view);
-    gtk_widget_add_controller (GTK_WIDGET (view), GTK_EVENT_CONTROLLER (drag_source));
-
 #if 0 && NAUTILUS_A11Y_NEEDS_GTK4_REIMPLEMENTATION
     /* Accessibility */
     atk_object = gtk_widget_get_accessible (GTK_WIDGET (view));
diff --git a/src/nautilus-view-icon-controller.c b/src/nautilus-view-icon-controller.c
index 43c710ece..c6885003c 100644
--- a/src/nautilus-view-icon-controller.c
+++ b/src/nautilus-view-icon-controller.c
@@ -4,6 +4,7 @@
 #include "nautilus-view-model.h"
 #include "nautilus-files-view.h"
 #include "nautilus-file.h"
+#include "nautilus-file-utilities.h"
 #include "nautilus-metadata.h"
 #include "nautilus-window-slot.h"
 #include "nautilus-directory.h"
@@ -27,6 +28,7 @@ struct _NautilusViewIconController
     gboolean single_click_mode;
     gboolean activate_on_release;
     gboolean deny_background_click;
+    NautilusViewItemModel *clicked_item;
 
     guint scroll_to_file_handle_id;
     guint prioritize_thumbnailing_handle_id;
@@ -807,6 +809,7 @@ on_item_click_pressed (GtkGestureClick *gesture,
     selection_mode = (modifiers & (GDK_CONTROL_MASK | GDK_SHIFT_MASK));
 
     /* Before anything else, store event state to be read by other handlers. */
+    g_set_weak_pointer (&self->clicked_item, item_model);
     self->deny_background_click = TRUE;
     self->activate_on_release = (self->single_click_mode &&
                                  button == GDK_BUTTON_PRIMARY &&
@@ -901,6 +904,7 @@ on_view_click_pressed (GtkGestureClick *gesture,
         return;
     }
 
+    g_clear_weak_pointer (&self->clicked_item);
     /* Don't interfere with GtkGridView default selection handling when
      * holding Ctrl and Shift. */
     modifiers = gtk_event_controller_get_current_event_state (GTK_EVENT_CONTROLLER (gesture));
@@ -926,6 +930,107 @@ on_view_click_pressed (GtkGestureClick *gesture,
     }
 }
 
+#define MAX_DRAWN_DRAG_ICONS 10
+
+static GdkPaintable *
+get_paintable_for_drag_selection (GList *selection)
+{
+    g_autoqueue (GdkPaintable) paintables = NULL;
+    g_autoptr (GtkSnapshot) snapshot = NULL;
+    guint n_icons;
+    float dy;
+
+    g_return_val_if_fail (NAUTILUS_IS_FILE (selection->data), NULL);
+
+    paintables = g_queue_new ();
+    snapshot = gtk_snapshot_new ();
+
+    /* The selection list is reversed compared to what the user sees. Get the
+     * first items by starting from the end of the list. */
+    for (GList *l = g_list_last (selection);
+         l != NULL && g_queue_get_length (paintables) <= MAX_DRAWN_DRAG_ICONS;
+         l = l->prev)
+    {
+        g_queue_push_tail (paintables,
+                           nautilus_file_get_icon_paintable (l->data, NAUTILUS_GRID_ICON_SIZE_LARGE, 1, 0));
+    }
+
+    /* When there are 2 or 3 identical icons, we need to space them more,
+     * otherwise it would be hard to tell there is more than one icon at all.
+     * The more icons we have, the easier it is to notice multiple icons are
+     * stacked, and the more compact we want to be.
+     *
+     *  1 icon          2 icons         3 icons         4+ icons
+     *  .--------.      .--------.      .--------.      .--------.
+     *  |        |      |        |      |        |      |        |
+     *  |        |      |        |      |        |      |        |
+     *  |        |      |        |      |        |      |        |
+     *  |        |      |        |      |        |      |        |
+     *  |        |      |        |      |        |      |        |
+     *  '--------'      |--------|      |--------|      |--------|
+     *                  |        |      |        |      |--------|
+     *                  |        |      |--------|      |--------|
+     *                  '--------'      |        |      |--------|
+     *                                  '--------'      '--------'
+     *
+     */
+    n_icons = g_queue_get_length (paintables);
+    dy = ((n_icons == 2) ? 10 :
+          (n_icons == 3) ? 6 :
+          (n_icons >= 4) ? 4 :
+          0);
+
+    /* We want to draw the first icon on top of every other. So we need to start
+     * drawing from the last icon. This requires us to jump to the last position
+     * and then walk back one step at a time. */
+    gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (0, dy * n_icons));
+    for (GList *l = g_queue_peek_tail_link (paintables); l != NULL; l = l->prev)
+    {
+        gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (0, -dy));
+
+        gtk_snapshot_push_shadow (snapshot, (GskShadow[]){{{0,0,0,0.2},0,0,1}}, 1);
+        gdk_paintable_snapshot (l->data, snapshot, NAUTILUS_GRID_ICON_SIZE_LARGE, 
NAUTILUS_GRID_ICON_SIZE_LARGE);
+        gtk_snapshot_pop (snapshot);
+    }
+
+    return gtk_snapshot_to_paintable (snapshot, NULL);
+}
+
+static GdkContentProvider *
+on_drag_prepare (GtkDragSource              *source,
+                 double                      x,
+                 double                      y,
+                 NautilusViewIconController *self)
+{
+    g_autolist (NautilusFile) selection = NULL;
+    g_autoslist (GFile) file_list = NULL;
+    g_autoptr (GdkPaintable) paintable = NULL;
+    GdkDragAction actions;
+
+    /* Antecipate selection, if necessary, for dragging the clicked item. */
+    if (self->clicked_item != NULL)
+    {
+        select_single_item_if_not_selected (self, self->clicked_item);
+    }
+
+    selection = nautilus_view_get_selection (NAUTILUS_VIEW (self));
+    if (selection == NULL)
+    {
+        return NULL;
+    }
+
+    gtk_gesture_set_state (GTK_GESTURE (source), GTK_EVENT_SEQUENCE_CLAIMED);
+
+    file_list = convert_file_list_to_gdk_file_list (selection);
+    actions = GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK | GDK_ACTION_MOVE;
+    gtk_drag_source_set_actions (source, actions);
+
+    paintable = get_paintable_for_drag_selection (selection);
+    gtk_drag_source_set_icon (source, paintable, 0, 0);
+
+    return gdk_content_provider_new_typed (GDK_TYPE_FILE_LIST, file_list);
+}
+
 static void
 on_longpress_gesture_pressed_callback (GtkGestureLongPress *gesture,
                                        gdouble              x,
@@ -1301,6 +1406,7 @@ dispose (GObject *object)
 
     self = NAUTILUS_VIEW_ICON_CONTROLLER (object);
 
+    g_clear_weak_pointer (&self->clicked_item);
     g_clear_handle_id (&self->scroll_to_file_handle_id, g_source_remove);
     g_clear_handle_id (&self->prioritize_thumbnailing_handle_id, g_source_remove);
 
@@ -1542,6 +1648,11 @@ constructed (GObject *object)
     g_signal_connect (controller, "pressed",
                       G_CALLBACK (on_view_click_pressed), self);
 
+    controller = GTK_EVENT_CONTROLLER (gtk_drag_source_new ());
+    g_signal_connect (controller, "prepare", G_CALLBACK (on_drag_prepare), self);
+    gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
+    gtk_widget_add_controller (GTK_WIDGET (self), controller);
+
     controller = GTK_EVENT_CONTROLLER (gtk_gesture_long_press_new ());
     gtk_widget_add_controller (GTK_WIDGET (self->view_ui), controller);
     gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_BUBBLE);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]