[nautilus] list-base: Support non-local drops
- From: António Fernandes <antoniof src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus] list-base: Support non-local drops
- Date: Thu, 30 Jun 2022 17:41:23 +0000 (UTC)
commit c21904c53fc7ce53d3ecc3b9cb6a500f506ca6db
Author: António Fernandes <antoniof gnome org>
Date: Thu Jun 30 18:06:09 2022 +0100
list-base: Support non-local drops
We reject drops on GtkDropTarget::enter if no drop action is supported.
But this assumes the drop value is already available, which holds only
for local (in-process) dnd opertaions. When dragging from other apps,
we need to preload the value first, which may happen at any point in
the future after ::enter.
So, as per GTK documentation's advice, listen to changes to the
GtkDropTarget:value property and update the cached preferred action
when a new non-NULL value is loaded.
src/nautilus-list-base.c | 92 ++++++++++++++++++++++++++++++++++++------------
1 file changed, 70 insertions(+), 22 deletions(-)
---
diff --git a/src/nautilus-list-base.c b/src/nautilus-list-base.c
index ce4f27641..c6809c6a8 100644
--- a/src/nautilus-list-base.c
+++ b/src/nautilus-list-base.c
@@ -579,6 +579,25 @@ on_item_drag_hover_leave (GtkDropControllerMotion *controller,
g_clear_handle_id (&priv->hover_timer_id, g_source_remove);
}
+static GdkDragAction
+get_preferred_action (NautilusFile *target_file,
+ const GValue *value)
+{
+ GdkDragAction action = 0;
+
+ if (value == NULL)
+ {
+ action = nautilus_dnd_get_prefered_action (target_file, NULL);
+ }
+ if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST))
+ {
+ GSList *source_file_list = g_value_get_boxed (value);
+ action = nautilus_dnd_get_prefered_action (target_file, source_file_list->data);
+ }
+
+ return action;
+}
+
static void
real_perform_drop (NautilusListBase *self,
const GValue *value,
@@ -646,15 +665,7 @@ on_item_drag_enter (GtkDropTarget *target,
}
value = gtk_drop_target_get_value (target);
- if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST))
- {
- GSList *source_file_list;
-
- source_file_list = g_value_get_boxed (value);
- priv->drag_item_action = nautilus_dnd_get_prefered_action (dest_file,
- source_file_list->data);
- }
-
+ priv->drag_item_action = get_preferred_action (dest_file, value);
if (priv->drag_item_action == 0)
{
gtk_drop_target_reject (target);
@@ -665,6 +676,30 @@ on_item_drag_enter (GtkDropTarget *target,
return priv->drag_item_action;
}
+static void
+on_item_drag_value_notify (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GtkDropTarget *target = GTK_DROP_TARGET (object);
+ NautilusViewCell *cell = user_data;
+ NautilusListBase *self = nautilus_view_cell_get_view (cell);
+ NautilusListBasePrivate *priv = nautilus_list_base_get_instance_private (self);
+ const GValue *value;
+ NautilusViewItem *item;
+
+ value = gtk_drop_target_get_value (target);
+ if (value == NULL)
+ {
+ return;
+ }
+
+ item = nautilus_view_cell_get_item (cell);
+ g_return_if_fail (NAUTILUS_IS_VIEW_ITEM (item));
+
+ priv->drag_item_action = get_preferred_action (nautilus_view_item_get_file (item), value);
+}
+
static GdkDragAction
on_item_drag_motion (GtkDropTarget *target,
double x,
@@ -721,22 +756,12 @@ on_view_drag_enter (GtkDropTarget *target,
{
NautilusListBase *self = user_data;
NautilusListBasePrivate *priv = nautilus_list_base_get_instance_private (self);
- g_autoptr (NautilusFile) dest_file = NULL;
+ NautilusFile *dest_file;
const GValue *value;
- GList *source_file_list;
-
- /* Reset action cache */
- priv->drag_view_action = 0;
+ dest_file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (self));
value = gtk_drop_target_get_value (target);
- if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST))
- {
- source_file_list = g_value_get_boxed (value);
- dest_file = nautilus_file_get (nautilus_view_get_location (NAUTILUS_VIEW (self)));
- priv->drag_view_action = nautilus_dnd_get_prefered_action (dest_file,
- source_file_list->data);
- }
-
+ priv->drag_view_action = get_preferred_action (dest_file, value);
if (priv->drag_view_action == 0)
{
gtk_drop_target_reject (target);
@@ -746,6 +771,27 @@ on_view_drag_enter (GtkDropTarget *target,
return priv->drag_view_action;
}
+static void
+on_view_drag_value_notify (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GtkDropTarget *target = GTK_DROP_TARGET (object);
+ NautilusListBase *self = user_data;
+ NautilusListBasePrivate *priv = nautilus_list_base_get_instance_private (self);
+ const GValue *value;
+ NautilusFile *dest_file;
+
+ value = gtk_drop_target_get_value (target);
+ if (value == NULL)
+ {
+ return;
+ }
+
+ dest_file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (self));
+ priv->drag_item_action = get_preferred_action (dest_file, value);
+}
+
static GdkDragAction
on_view_drag_motion (GtkDropTarget *target,
double x,
@@ -814,6 +860,7 @@ setup_cell_common (GtkListItem *listitem,
/* TODO: Implement GDK_TYPE_STRING */
gtk_drop_target_set_gtypes (drop_target, (GType[1]) { GDK_TYPE_FILE_LIST }, 1);
g_signal_connect (drop_target, "enter", G_CALLBACK (on_item_drag_enter), cell);
+ g_signal_connect (drop_target, "notify::value", G_CALLBACK (on_item_drag_value_notify), cell);
g_signal_connect (drop_target, "leave", G_CALLBACK (on_item_drag_leave), cell);
g_signal_connect (drop_target, "motion", G_CALLBACK (on_item_drag_motion), cell);
g_signal_connect (drop_target, "drop", G_CALLBACK (on_item_drop), cell);
@@ -1667,6 +1714,7 @@ nautilus_list_base_setup_gestures (NautilusListBase *self)
/* TODO: Implement GDK_TYPE_STRING */
gtk_drop_target_set_gtypes (drop_target, (GType[1]) { GDK_TYPE_FILE_LIST }, 1);
g_signal_connect (drop_target, "enter", G_CALLBACK (on_view_drag_enter), self);
+ g_signal_connect (drop_target, "notify::value", G_CALLBACK (on_view_drag_value_notify), self);
g_signal_connect (drop_target, "motion", G_CALLBACK (on_view_drag_motion), self);
g_signal_connect (drop_target, "drop", G_CALLBACK (on_view_drop), self);
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (drop_target));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]