[nautilus/wip/antoniof/drag-source-changes] foo
- From: António Fernandes <antoniof src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus/wip/antoniof/drag-source-changes] foo
- Date: Sun, 5 Jun 2022 15:12:38 +0000 (UTC)
commit 30a6a51a34d1d23db0e1ccb054c70cc613b3836b
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 | 129 ++++++++++++++++++++++++++++++++++++
2 files changed, 129 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..3e8a71ee3 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,125 @@ on_view_click_pressed (GtkGestureClick *gesture,
}
}
+#define MAX_DRAWN_DRAG_ICONS 10
+
+static GdkPaintable *
+get_paintable_for_drag_selection (GList *selection)
+{
+ g_autoqueue (GdkPaintable) icons = g_queue_new ();
+ g_autoptr (GtkSnapshot) snapshot = gtk_snapshot_new ();
+ guint n_icons;
+ float dy;
+ /* A wide shadow for the pile of icons gives a sense of floating. */
+ GskShadow stack_shadow = {.color = {0, 0, 0, .alpha = 0.15}, .dx = 0, .dy = 2, .radius = 10 };
+ /* A slight shadow swhich makes each icon in the stack look separate. */
+ GskShadow icon_shadow = {.color = {0, 0, 0, .alpha = 0.20}, .dx = 0, .dy = 1, .radius = 1 };
+ GskRoundedRect rounded_rect;
+
+ g_return_val_if_fail (NAUTILUS_IS_FILE (selection->data), NULL);
+
+ /* 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 (icons) <= MAX_DRAWN_DRAG_ICONS;
+ l = l->prev)
+ {
+ g_queue_push_tail (icons,
+ nautilus_file_get_icon_paintable (l->data,
+ NAUTILUS_GRID_ICON_SIZE_LARGE,
+ 1,
+ NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS |
NAUTILUS_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE));
+ }
+
+ /* 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 (icons);
+ dy = (n_icons == 2) ? 10 : (n_icons == 3) ? 6 : (n_icons >= 4) ? 4 : 0;
+
+ /* We want the first icon on top of every other. So we need to start drawing
+ * the stack from the bottom, that is, from the last icon. This requires us
+ * to jump to the last position and then move upwards one step at a time.
+ * Also, add 10px horizontal offset, for shadow, to workaround this GTK bug:
+ * https://gitlab.gnome.org/GNOME/gtk/-/issues/2341
+ */
+ gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (10, dy * n_icons));
+ gtk_snapshot_push_shadow (snapshot, &stack_shadow, 1);
+ for (GList *l = g_queue_peek_tail_link (icons); l != NULL; l = l->prev)
+ {
+ double w = gdk_paintable_get_intrinsic_width (l->data);
+ double h = gdk_paintable_get_intrinsic_height (l->data);
+ /* Offsets needed to center thumbnails. Floored to keep images sharp. */
+ float x = floor ((NAUTILUS_GRID_ICON_SIZE_LARGE - w) / 2);
+ float y = floor ((NAUTILUS_GRID_ICON_SIZE_LARGE - h) / 2);
+ gsk_rounded_rect_init_from_rect (&rounded_rect, &GRAPHENE_RECT_INIT (0, 0, w, h), 6);
+
+ gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (0, -dy));
+
+ gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
+ gtk_snapshot_push_shadow (snapshot, &icon_shadow, 1);
+ gtk_snapshot_push_rounded_clip (snapshot, &rounded_rect);
+
+ gdk_paintable_snapshot (l->data, snapshot, w, h);
+
+ gtk_snapshot_pop (snapshot); /* Pop rounded clip */
+ gtk_snapshot_pop (snapshot); /* Pop icon shadow */
+ gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (-x, -y));
+ }
+ gtk_snapshot_pop (snapshot); /* Pop stack shadow */
+
+ 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 +1424,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 +1666,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]