summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntónio Fernandes <antoniof@gnome.org>2022-06-30 01:49:37 +0100
committerAntónio Fernandes <antoniof@gnome.org>2022-06-30 01:49:55 +0100
commitc2157d4b53c52a01c292c1caa8cb04caff93354d (patch)
tree475a47c44c3bbfe0c17b4b86a915704dee094b33
parentb4d45b3876718dd43d1cc74f5c06fb28d54f9be7 (diff)
downloadnautilus-c2157d4b53c52a01c292c1caa8cb04caff93354d.tar.gz
dnd: Introduce helper to compute preferred drop action
Based on the logic from nautilus_drag_default_drop_action_for_icons(), but tailored for GTK4 paradigm. Also add some cases that weren't handled well previously. Heavily inspired by more conservative patch by Corey Berla.
-rw-r--r--src/nautilus-dnd.c193
-rw-r--r--src/nautilus-dnd.h7
2 files changed, 65 insertions, 135 deletions
diff --git a/src/nautilus-dnd.c b/src/nautilus-dnd.c
index c35698652..e57be8a27 100644
--- a/src/nautilus-dnd.c
+++ b/src/nautilus-dnd.c
@@ -24,12 +24,13 @@
#include <config.h>
#include "nautilus-dnd.h"
+#include <eel/eel-vfs-extensions.h>
+
#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION
#include "nautilus-program-choosing.h"
#include <eel/eel-glib-extensions.h>
#include <eel/eel-string.h>
-#include <eel/eel-vfs-extensions.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include "nautilus-file-utilities.h"
@@ -348,6 +349,7 @@ nautilus_drag_default_drop_action_for_netscape_url (GdkDragContext *context)
return gdk_drag_context_get_suggested_action (context);
}
+#endif
static gboolean
check_same_fs (NautilusFile *file1,
@@ -394,6 +396,8 @@ source_is_deletable (GFile *file)
return ret;
}
+#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION
+
NautilusDragInfo *
nautilus_drag_get_source_data (GdkDragContext *context)
{
@@ -435,136 +439,9 @@ nautilus_drag_get_source_data (GdkDragContext *context)
return source_data;
}
+#endif
-void
-nautilus_drag_default_drop_action_for_icons (GdkDragContext *context,
- const char *target_uri_string,
- const GList *items,
- guint32 source_actions,
- int *action)
-{
- gboolean same_fs;
- gboolean target_is_source_parent;
- gboolean source_deletable;
- const char *dropped_uri;
- GFile *target, *dropped, *dropped_directory;
- GdkDragAction actions;
- NautilusFile *dropped_file, *target_file;
-
- if (target_uri_string == NULL)
- {
- *action = 0;
- return;
- }
-
- /* this is needed because of how dnd works. The actions at the time drag-begin
- * is done are not set, because they are first set on drag-motion. However,
- * for our use case, which is validation with the sidebar for dnd feedback
- * when the dnd doesn't have as a destination the sidebar itself, we need
- * a way to know the actions at drag-begin time. Either canvas view or
- * list view know them when starting the drag, but asking for them here
- * would be breaking the current model too much. So instead we rely on the
- * caller, which will ask if appropiate to those objects about the actions
- * available, instead of relying solely on the context here. */
- if (source_actions)
- {
- actions = source_actions & (GDK_ACTION_MOVE | GDK_ACTION_COPY);
- }
- else
- {
- actions = gdk_drag_context_get_actions (context) & (GDK_ACTION_MOVE | GDK_ACTION_COPY);
- }
- if (actions == 0)
- {
- /* We can't use copy or move, just go with the suggested action. */
- *action = gdk_drag_context_get_suggested_action (context);
- return;
- }
-
- if (gdk_drag_context_get_suggested_action (context) == GDK_ACTION_ASK)
- {
- /* Don't override ask */
- *action = gdk_drag_context_get_suggested_action (context);
- return;
- }
-
- dropped_uri = ((NautilusDragSelectionItem *) items->data)->uri;
- dropped_file = ((NautilusDragSelectionItem *) items->data)->file;
- target_file = nautilus_file_get_by_uri (target_uri_string);
-
- /*
- * Check for trash URI. We do a find_directory for any Trash directory.
- * Passing 0 permissions as gnome-vfs would override the permissions
- * passed with 700 while creating .Trash directory
- */
- if (eel_uri_is_trash (target_uri_string))
- {
- /* Only move to Trash */
- if (actions & GDK_ACTION_MOVE)
- {
- *action = GDK_ACTION_MOVE;
- }
- nautilus_file_unref (target_file);
- return;
- }
- else if (target_file != NULL && nautilus_file_is_archive (target_file))
- {
- *action = GDK_ACTION_COPY;
-
- nautilus_file_unref (target_file);
- return;
- }
- else
- {
- target = g_file_new_for_uri (target_uri_string);
- }
-
- same_fs = check_same_fs (target_file, dropped_file);
-
- nautilus_file_unref (target_file);
-
- /* Compare the first dropped uri with the target uri for same fs match. */
- dropped = g_file_new_for_uri (dropped_uri);
- dropped_directory = g_file_get_parent (dropped);
- target_is_source_parent = FALSE;
- if (dropped_directory != NULL)
- {
- /* If the dropped file is already in the same directory but
- * is in another filesystem we still want to move, not copy
- * as this is then just a move of a mountpoint to another
- * position in the dir */
- target_is_source_parent = g_file_equal (dropped_directory, target);
- g_object_unref (dropped_directory);
- }
- source_deletable = source_is_deletable (dropped);
-
- if ((same_fs && source_deletable) || target_is_source_parent ||
- g_file_has_uri_scheme (dropped, "trash"))
- {
- if (actions & GDK_ACTION_MOVE)
- {
- *action = GDK_ACTION_MOVE;
- }
- else
- {
- *action = gdk_drag_context_get_suggested_action (context);
- }
- }
- else
- {
- if (actions & GDK_ACTION_COPY)
- {
- *action = GDK_ACTION_COPY;
- }
- else
- {
- *action = gdk_drag_context_get_suggested_action (context);
- }
- }
-
- g_object_unref (target);
- g_object_unref (dropped);
-}
+#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION
GdkDragAction
nautilus_drag_default_drop_action_for_uri_list (GdkDragContext *context,
@@ -991,6 +868,62 @@ nautilus_drag_autoscroll_stop (NautilusDragInfo *drag_info)
#endif
+GdkDragAction
+nautilus_dnd_get_prefered_action (NautilusFile *target_file,
+ GFile *dropped)
+{
+ g_return_val_if_fail (NAUTILUS_IS_FILE (target_file), 0);
+ g_return_val_if_fail (dropped == NULL || G_IS_FILE (dropped), 0);
+
+ /* First check target imperatives */
+
+ if (nautilus_file_is_archive (target_file))
+ {
+ return GDK_ACTION_COPY;
+ }
+ else if (!nautilus_file_is_directory (target_file))
+ {
+ /* No other file type other than archives and directories currently
+ * accepts drops */
+ return 0;
+ }
+
+ if (nautilus_file_is_in_trash (target_file))
+ {
+ return GDK_ACTION_MOVE;
+ }
+
+ if (dropped != NULL)
+ {
+ g_autoptr (GFile) target_location = NULL;
+ g_autoptr (NautilusFile) dropped_file = NULL;
+ gboolean same_fs;
+ gboolean source_deletable;
+
+ if (g_file_has_uri_scheme (dropped, "trash"))
+ {
+ return GDK_ACTION_MOVE;
+ }
+
+ target_location = nautilus_file_get_location (target_file);
+ if (g_file_equal (target_location, dropped) ||
+ g_file_has_parent (dropped, target_location))
+ {
+ return 0;
+ }
+
+ dropped_file = nautilus_file_get (dropped);
+ same_fs = check_same_fs (target_file, dropped_file);
+ source_deletable = source_is_deletable (dropped);
+ if (same_fs && source_deletable)
+ {
+ return GDK_ACTION_MOVE;
+ }
+ }
+
+ return GDK_ACTION_COPY;
+}
+
#define MAX_DRAWN_DRAG_ICONS 10
#define NAUTILUS_DRAG_SURFACE_ICON_SIZE 64
diff --git a/src/nautilus-dnd.h b/src/nautilus-dnd.h
index a8fc416ff..069256cfb 100644
--- a/src/nautilus-dnd.h
+++ b/src/nautilus-dnd.h
@@ -108,11 +108,6 @@ gboolean nautilus_drag_items_local (const char *target_uri,
const GList *selection_list);
gboolean nautilus_drag_uris_local (const char *target_uri,
const GList *source_uri_list);
-void nautilus_drag_default_drop_action_for_icons (GdkDragContext *context,
- const char *target_uri,
- const GList *items,
- guint32 source_actions,
- int *action);
GdkDragAction nautilus_drag_default_drop_action_for_netscape_url (GdkDragContext *context);
GdkDragAction nautilus_drag_default_drop_action_for_uri_list (GdkDragContext *context,
const char *target_uri_string);
@@ -144,5 +139,7 @@ NautilusDragInfo * nautilus_drag_get_source_data (GdkDr
GList * nautilus_drag_file_list_from_selection_list (const GList *selection_list);
#endif
+GdkDragAction nautilus_dnd_get_prefered_action (NautilusFile *target_file,
+ GFile *dropped);
GdkPaintable * get_paintable_for_drag_selection (GList *selection,
int scale);