diff --git a/src/nautilus-dnd.c b/src/nautilus-dnd.c index c35698652ceb4e1075d4c51cf877a227921a1cf0..eb25b5d4ed3e5dfabc28b01dbac402f0bd2d539e 100644 --- a/src/nautilus-dnd.c +++ b/src/nautilus-dnd.c @@ -1,354 +1,15 @@ -/* nautilus-dnd.c - Common Drag & drop handling code shared by the icon container - * and the list view. +/* nautilus-dnd.h - Common Drag & drop handling code * - * Copyright (C) 2000, 2001 Eazel, Inc. + * Authors: Pavel Cisler , + * Ettore Perazzoli + * Copyright (C) 2000, 2001 Eazel, Inc. + * Copyright (C) 2022 The GNOME project contributors * - * The Gnome Library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The Gnome Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with the Gnome Library; see the file COPYING.LIB. If not, - * see . - * - * Authors: Pavel Cisler , - * Ettore Perazzoli + * SPDX-License-Identifier: GPL-3.0-or-later */ -#include #include "nautilus-dnd.h" -#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION - -#include "nautilus-program-choosing.h" -#include -#include -#include -#include -#include -#include "nautilus-file-utilities.h" -#include -#include - -/* a set of defines stolen from the eel-icon-dnd.c file. - * These are in microseconds. - */ -#define AUTOSCROLL_TIMEOUT_INTERVAL 100 -#define AUTOSCROLL_INITIAL_DELAY 100000 - -/* drag this close to the view edge to start auto scroll*/ -#define AUTO_SCROLL_MARGIN 30 - -/* the smallest amount of auto scroll used when we just enter the autoscroll - * margin - */ -#define MIN_AUTOSCROLL_DELTA 5 - -/* the largest amount of auto scroll used when we are right over the view - * edge - */ -#define MAX_AUTOSCROLL_DELTA 50 - -void -nautilus_drag_init (NautilusDragInfo *drag_info, - const GtkTargetEntry *drag_types, - int drag_type_count, - gboolean add_text_targets) -{ - drag_info->target_list = gtk_target_list_new (drag_types, - drag_type_count); - - if (add_text_targets) - { - gtk_target_list_add_text_targets (drag_info->target_list, - NAUTILUS_ICON_DND_TEXT); - } - - drag_info->drop_occurred = FALSE; - drag_info->need_to_destroy = FALSE; -} - -void -nautilus_drag_finalize (NautilusDragInfo *drag_info) -{ - gtk_target_list_unref (drag_info->target_list); - nautilus_drag_destroy_selection_list (drag_info->selection_list); - nautilus_drag_destroy_selection_list (drag_info->selection_cache); - - g_free (drag_info); -} - - -/* Functions to deal with NautilusDragSelectionItems. */ - -NautilusDragSelectionItem * -nautilus_drag_selection_item_new (void) -{ - return g_new0 (NautilusDragSelectionItem, 1); -} - -static void -drag_selection_item_destroy (NautilusDragSelectionItem *item) -{ - g_clear_object (&item->file); - g_free (item->uri); - g_free (item); -} - -void -nautilus_drag_destroy_selection_list (GList *list) -{ - GList *p; - - if (list == NULL) - { - return; - } - - for (p = list; p != NULL; p = p->next) - { - drag_selection_item_destroy (p->data); - } - - g_list_free (list); -} - -GList * -nautilus_drag_uri_list_from_selection_list (const GList *selection_list) -{ - NautilusDragSelectionItem *selection_item; - GList *uri_list; - const GList *l; - - uri_list = NULL; - for (l = selection_list; l != NULL; l = l->next) - { - selection_item = (NautilusDragSelectionItem *) l->data; - if (selection_item->uri != NULL) - { - uri_list = g_list_prepend (uri_list, g_strdup (selection_item->uri)); - } - } - - return g_list_reverse (uri_list); -} - -/* - * Transfer: Full. Free with g_list_free_full (list, g_object_unref); - */ -GList * -nautilus_drag_file_list_from_selection_list (const GList *selection_list) -{ - NautilusDragSelectionItem *selection_item; - GList *file_list; - const GList *l; - - file_list = NULL; - for (l = selection_list; l != NULL; l = l->next) - { - selection_item = (NautilusDragSelectionItem *) l->data; - if (selection_item->file != NULL) - { - file_list = g_list_prepend (file_list, g_object_ref (selection_item->file)); - } - } - - return g_list_reverse (file_list); -} - -GList * -nautilus_drag_uri_list_from_array (const char **uris) -{ - GList *uri_list; - int i; - - if (uris == NULL) - { - return NULL; - } - - uri_list = NULL; - - for (i = 0; uris[i] != NULL; i++) - { - uri_list = g_list_prepend (uri_list, g_strdup (uris[i])); - } - - return g_list_reverse (uri_list); -} - -GList * -nautilus_drag_build_selection_list (GtkSelectionData *data) -{ - GList *result; - const guchar *p, *oldp; - int size; - - result = NULL; - oldp = gtk_selection_data_get_data (data); - size = gtk_selection_data_get_length (data); - - while (size > 0) - { - NautilusDragSelectionItem *item; - guint len; - - /* The list is in the form: - * - * name\rx:y:width:height\r\n - * - * The geometry information after the first \r is optional. */ - - /* 1: Decode name. */ - - p = memchr (oldp, '\r', size); - if (p == NULL) - { - break; - } - - item = nautilus_drag_selection_item_new (); - - len = p - oldp; - - item->uri = g_malloc (len + 1); - memcpy (item->uri, oldp, len); - item->uri[len] = 0; - item->file = nautilus_file_get_by_uri (item->uri); - - p++; - if (*p == '\n' || *p == '\0') - { - result = g_list_prepend (result, item); - if (p == 0) - { - g_warning ("Invalid x-special/gnome-icon-list data received: " - "missing newline character."); - break; - } - else - { - oldp = p + 1; - continue; - } - } - - size -= p - oldp; - oldp = p; - - /* 2: Decode geometry information. */ - - item->got_icon_position = sscanf ((const gchar *) p, "%d:%d:%d:%d%*s", - &item->icon_x, &item->icon_y, - &item->icon_width, &item->icon_height) == 4; - if (!item->got_icon_position) - { - g_warning ("Invalid x-special/gnome-icon-list data received: " - "invalid icon position specification."); - } - - result = g_list_prepend (result, item); - - p = memchr (p, '\r', size); - if (p == NULL || p[1] != '\n') - { - g_warning ("Invalid x-special/gnome-icon-list data received: " - "missing newline character."); - if (p == NULL) - { - break; - } - } - else - { - p += 2; - } - - size -= p - oldp; - oldp = p; - } - - return g_list_reverse (result); -} - -static gboolean -nautilus_drag_file_local_internal (const char *target_uri_string, - const char *first_source_uri) -{ - /* check if the first item on the list has target_uri_string as a parent - * FIXME: - * we should really test each item but that would be slow for large selections - * and currently dropped items can only be from the same container - */ - GFile *target, *item, *parent; - gboolean result; - - result = FALSE; - - target = g_file_new_for_uri (target_uri_string); - - /* get the parent URI of the first item in the selection */ - item = g_file_new_for_uri (first_source_uri); - parent = g_file_get_parent (item); - g_object_unref (item); - - if (parent != NULL) - { - result = g_file_equal (parent, target); - g_object_unref (parent); - } - - g_object_unref (target); - - return result; -} - -gboolean -nautilus_drag_uris_local (const char *target_uri, - const GList *source_uri_list) -{ - /* must have at least one item */ - g_assert (source_uri_list); - - return nautilus_drag_file_local_internal (target_uri, source_uri_list->data); -} - -gboolean -nautilus_drag_items_local (const char *target_uri_string, - const GList *selection_list) -{ - /* must have at least one item */ - g_assert (selection_list); - - return nautilus_drag_file_local_internal (target_uri_string, - ((NautilusDragSelectionItem *) selection_list->data)->uri); -} - -GdkDragAction -nautilus_drag_default_drop_action_for_netscape_url (GdkDragContext *context) -{ - /* Mozilla defaults to copy, but unless thats the - * only allowed thing (enforced by ctrl) we want to LINK */ - if (gdk_drag_context_get_suggested_action (context) == GDK_ACTION_COPY && - gdk_drag_context_get_actions (context) != GDK_ACTION_COPY) - { - return GDK_ACTION_LINK; - } - else if (gdk_drag_context_get_suggested_action (context) == GDK_ACTION_MOVE) - { - /* Don't support move */ - return GDK_ACTION_COPY; - } - - return gdk_drag_context_get_suggested_action (context); -} - static gboolean check_same_fs (NautilusFile *file1, NautilusFile *file2) @@ -394,360 +55,7 @@ source_is_deletable (GFile *file) return ret; } -NautilusDragInfo * -nautilus_drag_get_source_data (GdkDragContext *context) -{ - GtkWidget *source_widget; - NautilusDragInfo *source_data; - - source_widget = gtk_drag_get_source_widget (context); - if (source_widget == NULL) - { - return NULL; - } - - if (GTK_IS_TREE_VIEW (source_widget)) - { - NautilusWindow *window; - NautilusWindowSlot *active_slot; - NautilusView *view; - - window = NAUTILUS_WINDOW (gtk_widget_get_root (source_widget)); - active_slot = nautilus_window_get_active_slot (window); - view = nautilus_window_slot_get_current_view (active_slot); - if (NAUTILUS_IS_LIST_VIEW (view)) - { - source_data = nautilus_list_view_dnd_get_drag_source_data (NAUTILUS_LIST_VIEW (view), - context); - } - else - { - g_warning ("Got a drag context with a tree view source widget, but current view is not list view"); - source_data = NULL; - } - } - else - { - /* it's a slot or something else */ - g_warning ("Requested drag source data from a widget that doesn't support it"); - source_data = NULL; - } - - return source_data; -} - -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); -} - -GdkDragAction -nautilus_drag_default_drop_action_for_uri_list (GdkDragContext *context, - const char *target_uri_string) -{ - if (eel_uri_is_trash (target_uri_string) && (gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE)) - { - /* Only move to Trash */ - return GDK_ACTION_MOVE; - } - else - { - return gdk_drag_context_get_suggested_action (context); - } -} - -/* Encode a "x-special/gnome-icon-list" selection. - * Along with the URIs of the dragged files, this encodes - * the location and size of each icon relative to the cursor. - */ -static void -add_one_gnome_icon (const char *uri, - int x, - int y, - int w, - int h, - gpointer data) -{ - GString *result; - - result = (GString *) data; - - g_string_append_printf (result, "%s\r%d:%d:%hu:%hu\r\n", - uri, x, y, w, h); -} - -static void -add_one_uri (const char *uri, - int x, - int y, - int w, - int h, - gpointer data) -{ - GString *result; - - result = (GString *) data; - - g_string_append (result, uri); - g_string_append (result, "\r\n"); -} - -static void -cache_one_item (const char *uri, - int x, - int y, - int w, - int h, - gpointer data) -{ - GList **cache = data; - NautilusDragSelectionItem *item; - - item = nautilus_drag_selection_item_new (); - item->uri = nautilus_uri_to_native_uri (uri); - - if (item->uri == NULL) - { - item->uri = g_strdup (uri); - } - - item->file = nautilus_file_get_by_uri (uri); - item->icon_x = x; - item->icon_y = y; - item->icon_width = w; - item->icon_height = h; - *cache = g_list_prepend (*cache, item); -} - -GList * -nautilus_drag_create_selection_cache (gpointer container_context, - NautilusDragEachSelectedItemIterator each_selected_item_iterator) -{ - GList *cache = NULL; - - (*each_selected_item_iterator)(cache_one_item, container_context, &cache); - cache = g_list_reverse (cache); - - return cache; -} - -/* Common function for drag_data_get_callback calls. - * Returns FALSE if it doesn't handle drag data */ -gboolean -nautilus_drag_drag_data_get_from_cache (GList *cache, - GdkDragContext *context, - GtkSelectionData *selection_data, - guint info, - guint32 time) -{ - GList *l; - GString *result; - NautilusDragEachSelectedItemDataGet func; - - if (cache == NULL) - { - return FALSE; - } - - switch (info) - { - case NAUTILUS_ICON_DND_GNOME_ICON_LIST: - { - func = add_one_gnome_icon; - } - break; - - case NAUTILUS_ICON_DND_URI_LIST: - case NAUTILUS_ICON_DND_TEXT: - { - func = add_one_uri; - } - break; - - default: - { - return FALSE; - } - } - - result = g_string_new (NULL); - - for (l = cache; l != NULL; l = l->next) - { - NautilusDragSelectionItem *item = l->data; - (*func)(item->uri, item->icon_x, item->icon_y, item->icon_width, item->icon_height, result); - } - - gtk_selection_data_set (selection_data, - gtk_selection_data_get_target (selection_data), - 8, (guchar *) result->str, result->len); - g_string_free (result, TRUE); - - return TRUE; -} - -typedef struct -{ - GMainLoop *loop; - GdkDragAction chosen; -} DropActionMenuData; - -static void -menu_deactivate_callback (GtkWidget *menu, - gpointer data) -{ - DropActionMenuData *damd; - - damd = data; - - if (g_main_loop_is_running (damd->loop)) - { - g_main_loop_quit (damd->loop); - } -} - -static void -drop_action_activated_callback (GtkWidget *menu_item, - gpointer data) -{ - DropActionMenuData *damd; - - damd = data; - - damd->chosen = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), - "action")); - - if (g_main_loop_is_running (damd->loop)) - { - g_main_loop_quit (damd->loop); - } -} - +#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION static void append_drop_action_menu_item (GtkWidget *menu, const char *text, @@ -773,12 +81,13 @@ append_drop_action_menu_item (GtkWidget *menu, gtk_widget_show (menu_item); } - +#endif /* Pops up a menu of actions to perform on dropped files */ GdkDragAction nautilus_drag_drop_action_ask (GtkWidget *widget, GdkDragAction actions) { +#if 0 GtkWidget *popover; GtkWidget *menu; GtkWidget *menu_item; @@ -846,151 +155,66 @@ nautilus_drag_drop_action_ask (GtkWidget *widget, g_object_unref (popover); return damd.chosen; +#endif + return 0; } -gboolean -nautilus_drag_autoscroll_in_scroll_region (GtkWidget *widget) -{ - float x_scroll_delta, y_scroll_delta; - - nautilus_drag_autoscroll_calculate_delta (widget, &x_scroll_delta, &y_scroll_delta); - - return x_scroll_delta != 0 || y_scroll_delta != 0; -} - - -void -nautilus_drag_autoscroll_calculate_delta (GtkWidget *widget, - float *x_scroll_delta, - float *y_scroll_delta) +GdkDragAction +nautilus_dnd_get_prefered_action (NautilusFile *target_file, + GFile *dropped) { - GtkAllocation allocation; - GdkDisplay *display; - GdkSeat *seat; - GdkDevice *pointer; - int x, y; + g_return_val_if_fail (NAUTILUS_IS_FILE (target_file), 0); + g_return_val_if_fail (dropped == NULL || G_IS_FILE (dropped), 0); - g_assert (GTK_IS_WIDGET (widget)); + /* First check target imperatives */ - display = gtk_widget_get_display (widget); - seat = gdk_display_get_default_seat (display); - pointer = gdk_seat_get_pointer (seat); - gdk_window_get_device_position (gtk_widget_get_window (widget), pointer, - &x, &y, NULL); - - /* Find out if we are anywhere close to the tree view edges - * to see if we need to autoscroll. - */ - *x_scroll_delta = 0; - *y_scroll_delta = 0; - - if (x < AUTO_SCROLL_MARGIN) + if (nautilus_file_is_archive (target_file)) { - *x_scroll_delta = (float) (x - AUTO_SCROLL_MARGIN); + return GDK_ACTION_COPY; } - - gtk_widget_get_allocation (widget, &allocation); - if (x > allocation.width - AUTO_SCROLL_MARGIN) + else if (!nautilus_file_is_directory (target_file)) { - if (*x_scroll_delta != 0) - { - /* Already trying to scroll because of being too close to - * the top edge -- must be the window is really short, - * don't autoscroll. - */ - return; - } - *x_scroll_delta = (float) (x - (allocation.width - AUTO_SCROLL_MARGIN)); + /* No other file type other than archives and directories currently + * accepts drops */ + return 0; } - if (y < AUTO_SCROLL_MARGIN) + if (nautilus_file_is_in_trash (target_file)) { - *y_scroll_delta = (float) (y - AUTO_SCROLL_MARGIN); + return GDK_ACTION_MOVE; } - if (y > allocation.height - AUTO_SCROLL_MARGIN) + if (dropped != NULL) { - if (*y_scroll_delta != 0) + 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")) { - /* Already trying to scroll because of being too close to - * the top edge -- must be the window is really narrow, - * don't autoscroll. - */ - return; + return GDK_ACTION_MOVE; } - *y_scroll_delta = (float) (y - (allocation.height - AUTO_SCROLL_MARGIN)); - } - - if (*x_scroll_delta == 0 && *y_scroll_delta == 0) - { - /* no work */ - return; - } - - /* Adjust the scroll delta to the proper acceleration values depending on how far - * into the sroll margins we are. - * FIXME bugzilla.eazel.com 2486: - * we could use an exponential acceleration factor here for better feel - */ - if (*x_scroll_delta != 0) - { - *x_scroll_delta /= AUTO_SCROLL_MARGIN; - *x_scroll_delta *= (MAX_AUTOSCROLL_DELTA - MIN_AUTOSCROLL_DELTA); - *x_scroll_delta += MIN_AUTOSCROLL_DELTA; - } - - if (*y_scroll_delta != 0) - { - *y_scroll_delta /= AUTO_SCROLL_MARGIN; - *y_scroll_delta *= (MAX_AUTOSCROLL_DELTA - MIN_AUTOSCROLL_DELTA); - *y_scroll_delta += MIN_AUTOSCROLL_DELTA; - } -} - - -void -nautilus_drag_autoscroll_start (NautilusDragInfo *drag_info, - GtkWidget *widget, - GSourceFunc callback, - gpointer user_data) -{ - if (nautilus_drag_autoscroll_in_scroll_region (widget)) - { - if (drag_info->auto_scroll_timeout_id == 0) + target_location = nautilus_file_get_location (target_file); + if (g_file_equal (target_location, dropped) || + g_file_has_parent (dropped, target_location)) { - drag_info->waiting_to_autoscroll = TRUE; - drag_info->start_auto_scroll_in = g_get_monotonic_time () - + AUTOSCROLL_INITIAL_DELAY; - - drag_info->auto_scroll_timeout_id = g_timeout_add - (AUTOSCROLL_TIMEOUT_INTERVAL, - callback, - user_data); + return 0; } - } - else - { - if (drag_info->auto_scroll_timeout_id != 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) { - g_source_remove (drag_info->auto_scroll_timeout_id); - drag_info->auto_scroll_timeout_id = 0; + return GDK_ACTION_MOVE; } } -} -void -nautilus_drag_autoscroll_stop (NautilusDragInfo *drag_info) -{ - if (drag_info->auto_scroll_timeout_id != 0) - { - g_source_remove (drag_info->auto_scroll_timeout_id); - drag_info->auto_scroll_timeout_id = 0; - } + return GDK_ACTION_COPY; } -#endif - #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 a8fc416ff80ec5b20d2235936d39cceec83c5e9b..5fec2858b02aa5044020ff4e5021797b39f904e4 100644 --- a/src/nautilus-dnd.h +++ b/src/nautilus-dnd.h @@ -1,34 +1,18 @@ - -/* nautilus-dnd.h - Common Drag & drop handling code shared by the icon container - and the list view. - - Copyright (C) 2000 Eazel, Inc. - - The Gnome Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - see . - - Authors: Pavel Cisler , - Ettore Perazzoli -*/ +/* nautilus-dnd.h - Common Drag & drop handling code + * + * Authors: Pavel Cisler , + * Ettore Perazzoli + * Copyright (C) 2000 Eazel, Inc. + * Copyright (C) 2022 The GNOME project contributors + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ #pragma once #include #include "nautilus-file.h" -#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION - #define HOVER_TIMEOUT 500 /* Drag & Drop target names. */ @@ -39,110 +23,10 @@ #define NAUTILUS_ICON_DND_XDNDDIRECTSAVE_TYPE "XdndDirectSave0" /* XDS Protocol Type */ #define NAUTILUS_ICON_DND_RAW_TYPE "application/octet-stream" -/* drag&drop-related information. */ -typedef struct { - GtkTargetList *target_list; - - /* Stuff saved at "receive data" time needed later in the drag. */ - gboolean got_drop_data_type; - NautilusIconDndTargetType data_type; - GtkSelectionData *selection_data; - char *direct_save_uri; - - /* Start of the drag, in window coordinates. */ - int start_x, start_y; - - /* List of NautilusDragSelectionItems, representing items being dragged, or NULL - * if data about them has not been received from the source yet. - */ - GList *selection_list; - - /* cache of selected URIs, representing items being dragged */ - GList *selection_cache; - - /* File selection list information request handler, for the call for - * information (mostly the file system info, in order to know if we want - * co copy or move the files) about the files being dragged, that can - * come from another nautilus process, like the desktop. */ - NautilusFileListHandle *file_list_info_handler; - - /* has the drop occurred ? */ - gboolean drop_occurred; - - /* whether or not need to clean up the previous dnd data */ - gboolean need_to_destroy; - - /* autoscrolling during dragging */ - int auto_scroll_timeout_id; - gboolean waiting_to_autoscroll; - gint64 start_auto_scroll_in; - - /* source context actions. Used for peek the actions using a GdkDragContext - * source at drag-begin time when they are not available yet (they become - * available at drag-motion time) */ - guint32 source_actions; - -} NautilusDragInfo; - -typedef void (* NautilusDragEachSelectedItemDataGet) (const char *url, - int x, int y, int w, int h, - gpointer data); -typedef void (* NautilusDragEachSelectedItemIterator) (NautilusDragEachSelectedItemDataGet iteratee, - gpointer iterator_context, - gpointer data); - -void nautilus_drag_init (NautilusDragInfo *drag_info, - const GtkTargetEntry *drag_types, - int drag_type_count, - gboolean add_text_targets); -void nautilus_drag_finalize (NautilusDragInfo *drag_info); -NautilusDragSelectionItem *nautilus_drag_selection_item_new (void); -void nautilus_drag_destroy_selection_list (GList *selection_list); -GList *nautilus_drag_build_selection_list (GtkSelectionData *data); - -GList * nautilus_drag_uri_list_from_selection_list (const GList *selection_list); - -GList * nautilus_drag_uri_list_from_array (const char **uris); - -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); -GList *nautilus_drag_create_selection_cache (gpointer container_context, - NautilusDragEachSelectedItemIterator each_selected_item_iterator); -gboolean nautilus_drag_drag_data_get_from_cache (GList *cache, - GdkDragContext *context, - GtkSelectionData *selection_data, - guint info, - guint32 time); -int nautilus_drag_modifier_based_action (int default_action, - int non_default_action); - -GdkDragAction nautilus_drag_drop_action_ask (GtkWidget *widget, - GdkDragAction possible_actions); - -gboolean nautilus_drag_autoscroll_in_scroll_region (GtkWidget *widget); -void nautilus_drag_autoscroll_calculate_delta (GtkWidget *widget, - float *x_scroll_delta, - float *y_scroll_delta); -void nautilus_drag_autoscroll_start (NautilusDragInfo *drag_info, - GtkWidget *widget, - GSourceFunc callback, - gpointer user_data); -void nautilus_drag_autoscroll_stop (NautilusDragInfo *drag_info); - -NautilusDragInfo * nautilus_drag_get_source_data (GdkDragContext *context); - -GList * nautilus_drag_file_list_from_selection_list (const GList *selection_list); -#endif +GdkDragAction nautilus_drag_drop_action_ask (GtkWidget *widget, + GdkDragAction possible_actions); +GdkDragAction nautilus_dnd_get_prefered_action (NautilusFile *target_file, + GFile *dropped); GdkPaintable * get_paintable_for_drag_selection (GList *selection, int scale); diff --git a/src/nautilus-files-view-dnd.c b/src/nautilus-files-view-dnd.c index fbb0e2ee79d7dae01dabb53cb6741ec256fe6a8b..0f305c832aab1f28543492804b7b97f2249c55cb 100644 --- a/src/nautilus-files-view-dnd.c +++ b/src/nautilus-files-view-dnd.c @@ -23,7 +23,6 @@ * Pavel Cisler */ -#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION #include #include "nautilus-files-view-dnd.h" @@ -134,10 +133,12 @@ nautilus_files_view_handle_uri_list_drop (NautilusFilesView *view, if (action == GDK_ACTION_ASK) { +#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION action = nautilus_drag_drop_action_ask (GTK_WIDGET (view), GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK); if (action == 0) +#endif { g_free (container_uri); return; @@ -359,18 +360,21 @@ nautilus_files_view_drop_proxy_received_uris (NautilusFilesView *view, if (action == GDK_ACTION_ASK) { +#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION action = nautilus_drag_drop_action_ask (GTK_WIDGET (view), GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK); if (action == 0) +#endif { return; } } +#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION nautilus_clipboard_clear_if_colliding_uris (GTK_WIDGET (view), source_uri_list); - +#endif nautilus_files_view_move_copy_items (view, source_uri_list, target_uri != NULL ? target_uri : container_uri, action); @@ -408,4 +412,3 @@ nautilus_files_view_handle_hover (NautilusFilesView *view, g_object_unref (location); nautilus_file_unref (target_file); } -#endif diff --git a/src/nautilus-files-view-dnd.h b/src/nautilus-files-view-dnd.h index 7cfdb53b07b7292108bacf3e7d21fa78b5b78fdb..73b9263a76e22376e2297c1b5af55aa0d7aa9731 100644 --- a/src/nautilus-files-view-dnd.h +++ b/src/nautilus-files-view-dnd.h @@ -25,7 +25,7 @@ */ #pragma once -#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION + #include "nautilus-files-view.h" void nautilus_files_view_handle_uri_list_drop (NautilusFilesView *view, @@ -53,4 +53,3 @@ void nautilus_files_view_drop_proxy_received_uris (NautilusFilesView *view, const GList *uris, const char *target_location, GdkDragAction action); -#endif diff --git a/src/nautilus-grid-cell.c b/src/nautilus-grid-cell.c index 426a2c2a8459a88ed2fc4c626ee1bd2583138839..28fc43622b2307126b7ffa42e1c7bee85d47b6cd 100644 --- a/src/nautilus-grid-cell.c +++ b/src/nautilus-grid-cell.c @@ -31,6 +31,7 @@ update_icon (NautilusGridCell *self) { NautilusViewItem *item; NautilusFileIconFlags flags; + gboolean drag_accept; g_autoptr (GdkPaintable) icon_paintable = NULL; GtkStyleContext *style_context; NautilusFile *file; @@ -46,6 +47,12 @@ update_icon (NautilusGridCell *self) NAUTILUS_FILE_ICON_FLAGS_USE_EMBLEMS | NAUTILUS_FILE_ICON_FLAGS_USE_ONE_EMBLEM; + g_object_get (item, "drag-accept", &drag_accept, NULL); + if (drag_accept) + { + flags |= NAUTILUS_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT; + } + icon_paintable = nautilus_file_get_icon_paintable (file, icon_size, 1, flags); gtk_picture_set_paintable (GTK_PICTURE (self->icon), icon_paintable); @@ -127,6 +134,12 @@ on_item_size_changed (NautilusGridCell *self) update_captions (self); } +static void +on_item_drag_accept_changed (NautilusGridCell *self) +{ + update_icon (self); +} + static void on_item_is_cut_changed (NautilusGridCell *self) { @@ -181,6 +194,8 @@ nautilus_grid_cell_init (NautilusGridCell *self) self->item_signal_group = g_signal_group_new (NAUTILUS_TYPE_VIEW_ITEM); g_signal_group_connect_swapped (self->item_signal_group, "notify::icon-size", (GCallback) on_item_size_changed, self); + g_signal_group_connect_swapped (self->item_signal_group, "notify::drag-accept", + (GCallback) on_item_drag_accept_changed, self); g_signal_group_connect_swapped (self->item_signal_group, "notify::is-cut", (GCallback) on_item_is_cut_changed, self); g_signal_group_connect_swapped (self->item_signal_group, "file-changed", diff --git a/src/nautilus-list-base.c b/src/nautilus-list-base.c index e400196295e111093a78867d5c02086c4829f222..c6809c6a8a496a843e0ca6f2d587d891f045d5a8 100644 --- a/src/nautilus-list-base.c +++ b/src/nautilus-list-base.c @@ -12,7 +12,9 @@ #include "nautilus-view-item.h" #include "nautilus-view-model.h" #include "nautilus-files-view.h" +#include "nautilus-files-view-dnd.h" #include "nautilus-file.h" +#include "nautilus-file-operations.h" #include "nautilus-metadata.h" #include "nautilus-global-preferences.h" #include "nautilus-thumbnails.h" @@ -44,6 +46,10 @@ struct _NautilusListBasePrivate gboolean single_click_mode; gboolean activate_on_release; gboolean deny_background_click; + + GdkDragAction drag_item_action; + GdkDragAction drag_view_action; + guint hover_timer_id; }; G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (NautilusListBase, nautilus_list_base, NAUTILUS_TYPE_FILES_VIEW) @@ -529,11 +535,300 @@ on_item_drag_prepare (GtkDragSource *source, return gdk_content_provider_new_typed (GDK_TYPE_FILE_LIST, file_list); } +static gboolean +hover_timer (gpointer user_data) +{ + NautilusViewCell *cell = user_data; + NautilusListBase *self = nautilus_view_cell_get_view (cell); + NautilusListBasePrivate *priv = nautilus_list_base_get_instance_private (self); + NautilusViewItem *item = nautilus_view_cell_get_item (cell); + g_autofree gchar *uri = NULL; + + priv->hover_timer_id = 0; + + uri = nautilus_file_get_uri (nautilus_view_item_get_file (item)); + nautilus_files_view_handle_hover (NAUTILUS_FILES_VIEW (self), uri); + + return G_SOURCE_REMOVE; +} + +static void +on_item_drag_hover_enter (GtkDropControllerMotion *controller, + gdouble x, + gdouble y, + gpointer user_data) +{ + NautilusViewCell *cell = user_data; + NautilusListBase *self = nautilus_view_cell_get_view (cell); + NautilusListBasePrivate *priv = nautilus_list_base_get_instance_private (self); + + if (priv->hover_timer_id == 0) + { + priv->hover_timer_id = g_timeout_add (HOVER_TIMEOUT, hover_timer, cell); + } +} + +static void +on_item_drag_hover_leave (GtkDropControllerMotion *controller, + gpointer user_data) +{ + NautilusViewCell *cell = user_data; + NautilusListBase *self = nautilus_view_cell_get_view (cell); + NautilusListBasePrivate *priv = nautilus_list_base_get_instance_private (self); + + 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, + GdkDragAction action, + GFile *target_location) +{ + if (!gdk_drag_action_is_unique (action)) + { + /* TODO: Implement */ + } + else if (G_VALUE_HOLDS (value, G_TYPE_STRING)) + { + /* TODO: Implement */ + } + else if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST)) + { + GSList *source_file_list = g_value_get_boxed (value); + GList *source_uri_list = NULL; + g_autofree gchar *target_uri = NULL; + + for (GSList *l = source_file_list; l != NULL; l = l->next) + { + source_uri_list = g_list_prepend (source_uri_list, g_file_get_uri (l->data)); + } + source_uri_list = g_list_reverse (source_uri_list); + + target_uri = g_file_get_uri (target_location); + nautilus_files_view_drop_proxy_received_uris (NAUTILUS_FILES_VIEW (self), + source_uri_list, + target_uri, + action); + g_list_free_full (source_uri_list, g_free); + } +} + +static GdkDragAction +on_item_drag_enter (GtkDropTarget *target, + double x, + double y, + gpointer user_data) +{ + NautilusViewCell *cell = user_data; + NautilusListBase *self = nautilus_view_cell_get_view (cell); + NautilusListBasePrivate *priv = nautilus_list_base_get_instance_private (self); + NautilusViewItem *item; + const GValue *value; + g_autoptr (NautilusFile) dest_file = NULL; + + /* Reset action cache. */ + priv->drag_item_action = 0; + + item = nautilus_view_cell_get_item (cell); + if (item == NULL) + { + gtk_drop_target_reject (target); + return 0; + } + + dest_file = nautilus_file_ref (nautilus_view_item_get_file (item)); + + if (!nautilus_file_is_archive (dest_file) && !nautilus_file_is_directory (dest_file)) + { + gtk_drop_target_reject (target); + return 0; + } + + value = gtk_drop_target_get_value (target); + priv->drag_item_action = get_preferred_action (dest_file, value); + if (priv->drag_item_action == 0) + { + gtk_drop_target_reject (target); + return 0; + } + + nautilus_view_item_set_drag_accept (item, TRUE); + 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, + double y, + gpointer user_data) +{ + NautilusViewCell *cell = user_data; + NautilusListBase *self = nautilus_view_cell_get_view (cell); + NautilusListBasePrivate *priv = nautilus_list_base_get_instance_private (self); + + /* There's a bug in GtkDropTarget where motion overrides enter + * so until we fix that let's just return the action that we already + * received from enter*/ + + return priv->drag_item_action; +} + +static void +on_item_drag_leave (GtkDropTarget *dest, + gpointer user_data) +{ + NautilusViewCell *cell = user_data; + NautilusViewItem *item = nautilus_view_cell_get_item (cell); + + nautilus_view_item_set_drag_accept (item, FALSE); +} + +static gboolean +on_item_drop (GtkDropTarget *target, + const GValue *value, + double x, + double y, + gpointer user_data) +{ + NautilusViewCell *cell = user_data; + NautilusListBase *self = nautilus_view_cell_get_view (cell); + NautilusViewItem *item = nautilus_view_cell_get_item (cell); + GdkDragAction actions; + GFile *target_location; + + actions = gdk_drop_get_actions (gtk_drop_target_get_current_drop (target)); + target_location = nautilus_file_get_location (nautilus_view_item_get_file (item)); + + real_perform_drop (self, value, actions, target_location); + + return TRUE; +} + +static GdkDragAction +on_view_drag_enter (GtkDropTarget *target, + double x, + double y, + gpointer user_data) +{ + NautilusListBase *self = user_data; + NautilusListBasePrivate *priv = nautilus_list_base_get_instance_private (self); + NautilusFile *dest_file; + const GValue *value; + + dest_file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (self)); + value = gtk_drop_target_get_value (target); + priv->drag_view_action = get_preferred_action (dest_file, value); + if (priv->drag_view_action == 0) + { + gtk_drop_target_reject (target); + return 0; + } + + 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, + double y, + gpointer user_data) +{ + NautilusListBase *self = user_data; + NautilusListBasePrivate *priv = nautilus_list_base_get_instance_private (self); + + return priv->drag_view_action; +} + +static gboolean +on_view_drop (GtkDropTarget *target, + const GValue *value, + double x, + double y, + gpointer user_data) +{ + NautilusListBase *self = user_data; + GdkDragAction actions; + GFile *target_location; + + actions = gdk_drop_get_actions (gtk_drop_target_get_current_drop (target)); + target_location = nautilus_view_get_location (NAUTILUS_VIEW (self)); + + real_perform_drop (self, value, actions, target_location); + + return TRUE; +} + void setup_cell_common (GtkListItem *listitem, NautilusViewCell *cell) { GtkEventController *controller; + GtkDropTarget *drop_target; g_object_bind_property (listitem, "item", cell, "item", @@ -558,6 +853,23 @@ setup_cell_common (GtkListItem *listitem, gtk_widget_add_controller (GTK_WIDGET (cell), controller); gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE); g_signal_connect (controller, "prepare", G_CALLBACK (on_item_drag_prepare), cell); + + /* TODO: Implement GDK_ACTION_ASK */ + drop_target = gtk_drop_target_new (G_TYPE_INVALID, GDK_ACTION_COPY | GDK_ACTION_MOVE); + gtk_drop_target_set_preload (drop_target, TRUE); + /* 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); + gtk_widget_add_controller (GTK_WIDGET (cell), GTK_EVENT_CONTROLLER (drop_target)); + + controller = gtk_drop_controller_motion_new (); + gtk_widget_add_controller (GTK_WIDGET (cell), controller); + g_signal_connect (controller, "enter", G_CALLBACK (on_item_drag_hover_enter), cell); + g_signal_connect (controller, "leave", G_CALLBACK (on_item_drag_hover_leave), cell); } static void @@ -610,6 +922,11 @@ real_begin_loading (NautilusFilesView *files_view) /* When double clicking on an item this deny_background_click can persist * because the new view interrupts the gesture sequence, so lets reset it.*/ priv->deny_background_click = FALSE; + + /* When DnD is used to navigate between directories, the normal callbacks + * are ignored. Update DnD variables here upon navigating to a directory*/ + priv->drag_view_action = priv->drag_item_action; + priv->drag_item_action = 0; } static void @@ -1186,6 +1503,7 @@ nautilus_list_base_dispose (GObject *object) g_clear_handle_id (&priv->scroll_to_file_handle_id, g_source_remove); g_clear_handle_id (&priv->prioritize_thumbnailing_handle_id, g_source_remove); + g_clear_handle_id (&priv->hover_timer_id, g_source_remove); G_OBJECT_CLASS (nautilus_list_base_parent_class)->dispose (object); } @@ -1376,6 +1694,7 @@ nautilus_list_base_setup_gestures (NautilusListBase *self) { GtkWidget *view_ui = nautilus_list_base_get_view_ui (self); GtkEventController *controller; + GtkDropTarget *drop_target; controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ()); gtk_widget_add_controller (view_ui, controller); @@ -1388,4 +1707,15 @@ nautilus_list_base_setup_gestures (NautilusListBase *self) gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (controller), TRUE); g_signal_connect (controller, "pressed", G_CALLBACK (on_view_longpress_pressed), self); + + /* TODO: Implement GDK_ACTION_ASK */ + drop_target = gtk_drop_target_new (G_TYPE_INVALID, GDK_ACTION_COPY | GDK_ACTION_MOVE); + gtk_drop_target_set_preload (drop_target, TRUE); + /* 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)); } diff --git a/src/nautilus-name-cell.c b/src/nautilus-name-cell.c index daa6308a7deaf8df1e46412d29f9321c1ecdcebf..55574cb0a7f7b80f0d4c0235a68835b6a238e016 100644 --- a/src/nautilus-name-cell.c +++ b/src/nautilus-name-cell.c @@ -133,6 +133,7 @@ static void update_icon (NautilusNameCell *self) { NautilusFileIconFlags flags; + gboolean drag_accept; g_autoptr (GdkPaintable) icon_paintable = NULL; GtkStyleContext *style_context; NautilusViewItem *item; @@ -152,6 +153,12 @@ update_icon (NautilusNameCell *self) NAUTILUS_FILE_ICON_FLAGS_USE_EMBLEMS | NAUTILUS_FILE_ICON_FLAGS_USE_ONE_EMBLEM; + g_object_get (item, "drag-accept", &drag_accept, NULL); + if (drag_accept) + { + flags |= NAUTILUS_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT; + } + icon_paintable = nautilus_file_get_icon_paintable (file, icon_size, 1, flags); gtk_picture_set_paintable (GTK_PICTURE (self->icon), icon_paintable); @@ -198,6 +205,27 @@ on_item_size_changed (NautilusNameCell *self) update_icon (self); } +static void +on_item_drag_accept_changed (NautilusNameCell *self) +{ + gboolean drag_accept; + NautilusViewItem *item; + GtkWidget *list_row = gtk_widget_get_parent (gtk_widget_get_parent (GTK_WIDGET (self))); + + item = nautilus_view_cell_get_item (NAUTILUS_VIEW_CELL (self)); + g_object_get (item, "drag-accept", &drag_accept, NULL); + if (drag_accept) + { + gtk_widget_set_state_flags (list_row, GTK_STATE_FLAG_DROP_ACTIVE, FALSE); + } + else + { + gtk_widget_unset_state_flags (list_row, GTK_STATE_FLAG_DROP_ACTIVE); + } + + update_icon (self); +} + static void on_item_is_cut_changed (NautilusNameCell *self) { @@ -225,6 +253,8 @@ nautilus_name_cell_init (NautilusNameCell *self) self->item_signal_group = g_signal_group_new (NAUTILUS_TYPE_VIEW_ITEM); g_signal_group_connect_swapped (self->item_signal_group, "notify::icon-size", (GCallback) on_item_size_changed, self); + g_signal_group_connect_swapped (self->item_signal_group, "notify::drag-accept", + (GCallback) on_item_drag_accept_changed, self); g_signal_group_connect_swapped (self->item_signal_group, "notify::is-cut", (GCallback) on_item_is_cut_changed, self); g_signal_group_connect_swapped (self->item_signal_group, "file-changed", diff --git a/src/nautilus-notebook.c b/src/nautilus-notebook.c index 504ea5caabffc0365aff7ca5d495aed27b24066f..9713b545bc4938a5dd793e0f0686d5f068108430 100644 --- a/src/nautilus-notebook.c +++ b/src/nautilus-notebook.c @@ -289,9 +289,7 @@ build_tab_label (GtkNotebook *notebook, gtk_widget_show (close_button); g_object_set_data (G_OBJECT (tab_label), "nautilus-notebook-tab", GINT_TO_POINTER (1)); -#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION - nautilus_drag_slot_proxy_init (box, NULL, slot); -#endif + nautilus_drag_slot_proxy_init (tab_label, NULL, slot); g_object_set_data (G_OBJECT (tab_label), "label", label); g_object_set_data (G_OBJECT (tab_label), "spinner", spinner); diff --git a/src/nautilus-pathbar.c b/src/nautilus-pathbar.c index 1b5671b09039fa4e622ba3610183307af729bc5e..f43ccaf5ffe4b86fae7fd7bd73cdecfa0a79001c 100644 --- a/src/nautilus-pathbar.c +++ b/src/nautilus-pathbar.c @@ -1118,9 +1118,7 @@ make_button_data (NautilusPathBar *self, g_signal_connect (controller, "pressed", G_CALLBACK (on_click_gesture_pressed), button_data); -#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION nautilus_drag_slot_proxy_init (button_data->button, button_data->file, NULL); -#endif g_object_unref (path); diff --git a/src/nautilus-properties-window.c b/src/nautilus-properties-window.c index b3bfa1991dd5ab7aeddf0b4e7f9c9261fb822511..b1572ce9d31395fea0c628703d3ba10d24ef4429 100644 --- a/src/nautilus-properties-window.c +++ b/src/nautilus-properties-window.c @@ -254,22 +254,6 @@ typedef struct gboolean cancelled; } StartupData; -/* drag and drop definitions */ - -#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION -enum -{ - TARGET_URI_LIST, - TARGET_GNOME_URI_LIST, -}; - -static const GtkTargetEntry target_table[] = -{ - { "text/uri-list", 0, TARGET_URI_LIST }, - { "x-special/gnome-icon-list", 0, TARGET_GNOME_URI_LIST }, -}; -#endif - #define DIRECTORY_CONTENTS_UPDATE_INTERVAL 200 /* milliseconds */ #define FILES_UPDATE_INTERVAL 200 /* milliseconds */ @@ -474,7 +458,6 @@ update_properties_window_icon (NautilusPropertiesWindow *self) gtk_image_set_pixel_size (GTK_IMAGE (self->icon_button_image), pixel_size); } -#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION /* utility to test if a uri refers to a local image */ static gboolean uri_is_local_image (const char *uri) @@ -497,7 +480,6 @@ uri_is_local_image (const char *uri) return TRUE; } -#endif static void reset_icon (NautilusPropertiesWindow *self) @@ -516,27 +498,28 @@ reset_icon (NautilusPropertiesWindow *self) } } -#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION static void -nautilus_properties_window_drag_data_received (GtkWidget *widget, - GdkDragContext *context, - int x, - int y, - GtkSelectionData *selection_data, - guint info, - guint time) -{ - g_auto (GStrv) uris = NULL; +nautilus_properties_window_drag_drop_cb (GtkDropTarget *target, + const GValue *value, + gdouble x, + gdouble y, + gpointer user_data) +{ + GSList *file_list; gboolean exactly_one; GtkImage *image; GtkWindow *window; - image = GTK_IMAGE (widget); + image = GTK_IMAGE (user_data); window = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (image))); - uris = g_strsplit ((const gchar *) gtk_selection_data_get_data (selection_data), "\r\n", 0); - exactly_one = uris[0] != NULL && (uris[1] == NULL || uris[1][0] == '\0'); + if (!G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST)) + { + return; + } + file_list = g_value_get_boxed (value); + exactly_one = file_list != NULL && g_slist_next (file_list) == NULL; if (!exactly_one) { @@ -547,16 +530,15 @@ nautilus_properties_window_drag_data_received (GtkWidget *widget, } else { - if (uri_is_local_image (uris[0])) + g_autofree gchar *uri = g_file_get_uri (file_list->data); + + if (uri_is_local_image (uri)) { - set_icon (uris[0], NAUTILUS_PROPERTIES_WINDOW (window)); + set_icon (uri, NAUTILUS_PROPERTIES_WINDOW (window)); } else { - g_autoptr (GFile) f = NULL; - - f = g_file_new_for_uri (uris[0]); - if (!g_file_is_native (f)) + if (!g_file_is_native (file_list->data)) { show_dialog (_("The file that you dropped is not local."), _("You can only use local images as custom icons."), @@ -573,7 +555,6 @@ nautilus_properties_window_drag_data_received (GtkWidget *widget, } } } -#endif static void setup_image_widget (NautilusPropertiesWindow *self, @@ -583,16 +564,14 @@ setup_image_widget (NautilusPropertiesWindow *self, if (is_customizable) { -#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION + GtkDropTarget *target; + /* prepare the image to receive dropped objects to assign custom images */ - gtk_drag_dest_set (self->icon_button_image, - GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, - target_table, G_N_ELEMENTS (target_table), - GDK_ACTION_COPY | GDK_ACTION_MOVE); + target = gtk_drop_target_new (GDK_TYPE_FILE_LIST, GDK_ACTION_COPY); + gtk_widget_add_controller (self->icon_button, GTK_EVENT_CONTROLLER (target)); + g_signal_connect (target, "drop", + G_CALLBACK (nautilus_properties_window_drag_drop_cb), self->icon_button_image); - g_signal_connect (self->icon_button_image, "drag-data-received", - G_CALLBACK (nautilus_properties_window_drag_data_received), NULL); -#endif g_signal_connect (self->icon_button, "clicked", G_CALLBACK (select_image_button_callback), self); gtk_stack_set_visible_child (self->icon_stack, self->icon_button); diff --git a/src/nautilus-view-item.c b/src/nautilus-view-item.c index 560cfec42f73ee0b8eeb0b6e7217f84f5159ba98..84423fa2d6e8d802a0fde9f8d0cba2dec25d1a03 100644 --- a/src/nautilus-view-item.c +++ b/src/nautilus-view-item.c @@ -11,6 +11,7 @@ struct _NautilusViewItem GObject parent_instance; guint icon_size; gboolean is_cut; + gboolean drag_accept; NautilusFile *file; GtkWidget *item_ui; }; @@ -23,6 +24,7 @@ enum PROP_FILE, PROP_ICON_SIZE, PROP_IS_CUT, + PROP_DRAG_ACCEPT, PROP_ITEM_UI, N_PROPS }; @@ -85,6 +87,12 @@ nautilus_view_item_get_property (GObject *object, } break; + case PROP_DRAG_ACCEPT: + { + g_value_set_boolean (value, self->drag_accept); + } + break; + case PROP_ITEM_UI: { g_value_set_object (value, self->item_ui); @@ -126,6 +134,12 @@ nautilus_view_item_set_property (GObject *object, } break; + case PROP_DRAG_ACCEPT: + { + self->drag_accept = g_value_get_boolean (value); + } + break; + case PROP_ITEM_UI: { g_set_object (&self->item_ui, g_value_get_object (value)); @@ -164,6 +178,10 @@ nautilus_view_item_class_init (NautilusViewItemClass *klass) "", "", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + properties[PROP_DRAG_ACCEPT] = g_param_spec_boolean ("drag-accept", + "", "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); properties[PROP_FILE] = g_param_spec_object ("file", "", "", NAUTILUS_TYPE_FILE, @@ -219,6 +237,15 @@ nautilus_view_item_set_cut (NautilusViewItem *self, g_object_set (self, "is-cut", is_cut, NULL); } +void +nautilus_view_item_set_drag_accept (NautilusViewItem *self, + gboolean drag_accept) +{ + g_return_if_fail (NAUTILUS_IS_VIEW_ITEM (self)); + + g_object_set (self, "drag-accept", drag_accept, NULL); +} + NautilusFile * nautilus_view_item_get_file (NautilusViewItem *self) { diff --git a/src/nautilus-view-item.h b/src/nautilus-view-item.h index 5e620520aa042d546eac4e45d6abfa55b39ad207..9bdaff158bd0b051e17e074f3cc747d435c40cfc 100644 --- a/src/nautilus-view-item.h +++ b/src/nautilus-view-item.h @@ -26,6 +26,8 @@ void nautilus_view_item_set_icon_size (NautilusViewItem *self, guint nautilus_view_item_get_icon_size (NautilusViewItem *self); void nautilus_view_item_set_cut (NautilusViewItem *self, gboolean is_cut); +void nautilus_view_item_set_drag_accept (NautilusViewItem *self, + gboolean drag_accept); NautilusFile * nautilus_view_item_get_file (NautilusViewItem *self); diff --git a/src/nautilus-window-slot-dnd.c b/src/nautilus-window-slot-dnd.c index ccec73b6088c8b00116c569f197a360d279fc1a4..3d929a3f3c76a00a2b53c44600f2a9cb87e109ed 100644 --- a/src/nautilus-window-slot-dnd.c +++ b/src/nautilus-window-slot-dnd.c @@ -23,7 +23,6 @@ * Ettore Perazzoli */ -#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION #include #include "nautilus-notebook.h" @@ -33,19 +32,6 @@ typedef struct { - gboolean have_data; - gboolean have_valid_data; - - gboolean drop_occurred; - - unsigned int info; - union - { - GList *selection_list; - GList *uri_list; - GtkSelectionData *selection_data; - } data; - NautilusFile *target_file; NautilusWindowSlot *target_slot; GtkWidget *widget; @@ -120,8 +106,7 @@ slot_proxy_switch_location_timer (gpointer user_data) } static void -slot_proxy_check_switch_location_timer (NautilusDragSlotProxyInfo *drag_info, - GtkWidget *widget) +slot_proxy_check_switch_location_timer (NautilusDragSlotProxyInfo *drag_info) { if (drag_info->switch_location_timer) { @@ -143,50 +128,33 @@ slot_proxy_remove_switch_location_timer (NautilusDragSlotProxyInfo *drag_info) } } -static gboolean -slot_proxy_drag_motion (GtkWidget *widget, - GdkDragContext *context, - int x, - int y, - unsigned int time, - gpointer user_data) +static GdkDragAction +slot_proxy_drag_motion (GtkDropTarget *target, + gdouble x, + gdouble y, + gpointer user_data) { NautilusDragSlotProxyInfo *drag_info; NautilusWindowSlot *target_slot; GtkRoot *window; - GdkAtom target; - int action; + GdkDragAction action; char *target_uri; GFile *location; - gboolean valid_text_drag; - gboolean valid_xds_drag; + const GValue *value; drag_info = user_data; action = 0; - valid_text_drag = FALSE; - valid_xds_drag = FALSE; - if (gtk_drag_get_source_widget (context) == widget) + value = gtk_drop_target_get_value (target); + if (value == NULL) { - goto out; + return 0; } - window = gtk_widget_get_root (widget); + window = gtk_widget_get_root (drag_info->widget); g_assert (NAUTILUS_IS_WINDOW (window)); - if (!drag_info->have_data) - { - target = gtk_drag_dest_find_target (widget, context, NULL); - - if (target == GDK_NONE) - { - goto out; - } - - gtk_drag_get_data (widget, context, target, time); - } - target_uri = NULL; if (drag_info->target_file != NULL) { @@ -227,48 +195,18 @@ slot_proxy_drag_motion (GtkWidget *widget, } } - if (drag_info->have_data && - drag_info->have_valid_data) + if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST)) { - if (drag_info->info == NAUTILUS_ICON_DND_GNOME_ICON_LIST) - { - nautilus_drag_default_drop_action_for_icons (context, target_uri, - drag_info->data.selection_list, - 0, - &action); - } - else if (drag_info->info == NAUTILUS_ICON_DND_URI_LIST) - { - action = nautilus_drag_default_drop_action_for_uri_list (context, target_uri); - } - else if (drag_info->info == NAUTILUS_ICON_DND_TEXT) - { - valid_text_drag = TRUE; - } - else if (drag_info->info == NAUTILUS_ICON_DND_XDNDDIRECTSAVE || - drag_info->info == NAUTILUS_ICON_DND_RAW) - { - valid_xds_drag = TRUE; - } + GSList *items = g_value_get_boxed (value); + action = nautilus_dnd_get_prefered_action (drag_info->target_file, items->data); } g_free (target_uri); out: - if (action != 0 || valid_text_drag || valid_xds_drag) - { - gtk_drag_highlight (widget); - slot_proxy_check_switch_location_timer (drag_info, widget); - } - else - { - gtk_drag_unhighlight (widget); - slot_proxy_remove_switch_location_timer (drag_info); - } - - gdk_drag_status (context, action, time); + slot_proxy_check_switch_location_timer (drag_info); - return TRUE; + return action; } static void @@ -286,96 +224,37 @@ static void drag_info_clear (NautilusDragSlotProxyInfo *drag_info) { slot_proxy_remove_switch_location_timer (drag_info); - - if (!drag_info->have_data) - { - goto out; - } - - if (drag_info->info == NAUTILUS_ICON_DND_GNOME_ICON_LIST) - { - nautilus_drag_destroy_selection_list (drag_info->data.selection_list); - } - else if (drag_info->info == NAUTILUS_ICON_DND_URI_LIST) - { - g_list_free (drag_info->data.uri_list); - } - else if (drag_info->info == NAUTILUS_ICON_DND_TEXT || - drag_info->info == NAUTILUS_ICON_DND_XDNDDIRECTSAVE || - drag_info->info == NAUTILUS_ICON_DND_RAW) - { - if (drag_info->data.selection_data != NULL) - { - gtk_selection_data_free (drag_info->data.selection_data); - } - } - -out: - drag_info->have_data = FALSE; - drag_info->have_valid_data = FALSE; - - drag_info->drop_occurred = FALSE; } static void -slot_proxy_drag_leave (GtkWidget *widget, - GdkDragContext *context, - unsigned int time, - gpointer user_data) +slot_proxy_drag_leave (GtkDropTarget *target, + gpointer user_data) { NautilusDragSlotProxyInfo *drag_info; drag_info = user_data; - gtk_drag_unhighlight (widget); drag_info_clear (drag_info); } -static gboolean -slot_proxy_drag_drop (GtkWidget *widget, - GdkDragContext *context, - int x, - int y, - unsigned int time, - gpointer user_data) -{ - GdkAtom target; - NautilusDragSlotProxyInfo *drag_info; - - drag_info = user_data; - g_assert (!drag_info->have_data); - - drag_info->drop_occurred = TRUE; - - target = gtk_drag_dest_find_target (widget, context, NULL); - gtk_drag_get_data (widget, context, target, time); - - return TRUE; -} - - static void -slot_proxy_handle_drop (GtkWidget *widget, - GdkDragContext *context, - unsigned int time, - NautilusDragSlotProxyInfo *drag_info) +slot_proxy_handle_drop (GtkDropTarget *target, + const GValue *value, + gdouble x, + gdouble y, + gpointer user_data) { GtkRoot *window; NautilusWindowSlot *target_slot; NautilusFilesView *target_view; char *target_uri; - GList *uri_list; + GList *uri_list = NULL; GFile *location; + NautilusDragSlotProxyInfo *drag_info; - if (!drag_info->have_data || - !drag_info->have_valid_data) - { - gtk_drag_finish (context, FALSE, FALSE, time); - drag_info_clear (drag_info); - return; - } + drag_info = user_data; - window = gtk_widget_get_root (widget); + window = gtk_widget_get_root (drag_info->widget); g_assert (NAUTILUS_IS_WINDOW (window)); if (drag_info->target_slot != NULL) @@ -413,105 +292,33 @@ slot_proxy_handle_drop (GtkWidget *widget, if (target_slot != NULL && target_view != NULL) { - if (drag_info->info == NAUTILUS_ICON_DND_GNOME_ICON_LIST) + if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST)) { - uri_list = nautilus_drag_uri_list_from_selection_list (drag_info->data.selection_list); - g_assert (uri_list != NULL); + GSList *items = g_value_get_boxed (value); + for (GSList *l = items; l != NULL; l = l->next) + { + uri_list = g_list_prepend (uri_list, g_file_get_uri (l->data)); + } nautilus_files_view_drop_proxy_received_uris (target_view, uri_list, target_uri, - gdk_drag_context_get_selected_action (context)); + gdk_drop_get_actions (gtk_drop_target_get_current_drop (target))); g_list_free_full (uri_list, g_free); } - else if (drag_info->info == NAUTILUS_ICON_DND_URI_LIST) - { - nautilus_files_view_drop_proxy_received_uris (target_view, - drag_info->data.uri_list, - target_uri, - gdk_drag_context_get_selected_action (context)); - } - - gtk_drag_finish (context, TRUE, FALSE, time); - } - else - { - gtk_drag_finish (context, FALSE, FALSE, time); } - g_free (target_uri); drag_info_clear (drag_info); } -static void -slot_proxy_drag_data_received (GtkWidget *widget, - GdkDragContext *context, - int x, - int y, - GtkSelectionData *data, - unsigned int info, - unsigned int time, - gpointer user_data) -{ - NautilusDragSlotProxyInfo *drag_info; - char **uris; - - drag_info = user_data; - - g_assert (!drag_info->have_data); - - drag_info->have_data = TRUE; - drag_info->info = info; - - if (gtk_selection_data_get_length (data) < 0) - { - drag_info->have_valid_data = FALSE; - return; - } - - if (info == NAUTILUS_ICON_DND_GNOME_ICON_LIST) - { - drag_info->data.selection_list = nautilus_drag_build_selection_list (data); - - drag_info->have_valid_data = drag_info->data.selection_list != NULL; - } - else if (info == NAUTILUS_ICON_DND_URI_LIST) - { - uris = gtk_selection_data_get_uris (data); - drag_info->data.uri_list = nautilus_drag_uri_list_from_array ((const char **) uris); - g_strfreev (uris); - - drag_info->have_valid_data = drag_info->data.uri_list != NULL; - } - else if (info == NAUTILUS_ICON_DND_TEXT || - info == NAUTILUS_ICON_DND_XDNDDIRECTSAVE || - info == NAUTILUS_ICON_DND_RAW) - { - drag_info->data.selection_data = gtk_selection_data_copy (data); - drag_info->have_valid_data = drag_info->data.selection_data != NULL; - } - - if (drag_info->drop_occurred) - { - slot_proxy_handle_drop (widget, context, time, drag_info); - } -} - void nautilus_drag_slot_proxy_init (GtkWidget *widget, NautilusFile *target_file, NautilusWindowSlot *target_slot) { NautilusDragSlotProxyInfo *drag_info; - - const GtkTargetEntry targets[] = - { - { NAUTILUS_ICON_DND_GNOME_ICON_LIST_TYPE, 0, NAUTILUS_ICON_DND_GNOME_ICON_LIST }, - { NAUTILUS_ICON_DND_XDNDDIRECTSAVE_TYPE, 0, NAUTILUS_ICON_DND_XDNDDIRECTSAVE }, /* XDS Protocol Type */ - { NAUTILUS_ICON_DND_RAW_TYPE, 0, NAUTILUS_ICON_DND_RAW } - }; - GtkTargetList *target_list; + GtkDropTarget *target; g_assert (GTK_IS_WIDGET (widget)); @@ -533,31 +340,15 @@ nautilus_drag_slot_proxy_init (GtkWidget *widget, } drag_info->widget = widget; - - gtk_drag_dest_set (widget, 0, - NULL, 0, - GDK_ACTION_MOVE | - GDK_ACTION_COPY | - GDK_ACTION_LINK | - GDK_ACTION_ASK); - - target_list = gtk_target_list_new (targets, G_N_ELEMENTS (targets)); - gtk_target_list_add_uri_targets (target_list, NAUTILUS_ICON_DND_URI_LIST); - gtk_target_list_add_text_targets (target_list, NAUTILUS_ICON_DND_TEXT); - gtk_drag_dest_set_target_list (widget, target_list); - gtk_target_list_unref (target_list); - - g_signal_connect (widget, "drag-motion", - G_CALLBACK (slot_proxy_drag_motion), - drag_info); - g_signal_connect (widget, "drag-drop", - G_CALLBACK (slot_proxy_drag_drop), - drag_info); - g_signal_connect (widget, "drag-data-received", - G_CALLBACK (slot_proxy_drag_data_received), - drag_info); - g_signal_connect (widget, "drag-leave", - G_CALLBACK (slot_proxy_drag_leave), - drag_info); + /* TODO: Implement GDK_ACTION_ASK */ + target = gtk_drop_target_new (G_TYPE_INVALID, GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK); + + gtk_drop_target_set_preload (target, TRUE); + /* TODO: Implement GDK_TYPE_STRING */ + gtk_drop_target_set_gtypes (target, (GType[1]) { GDK_TYPE_FILE_LIST }, 1); + g_signal_connect (target, "enter", G_CALLBACK (slot_proxy_drag_motion), drag_info); + g_signal_connect (target, "motion", G_CALLBACK (slot_proxy_drag_motion), drag_info); + g_signal_connect (target, "drop", G_CALLBACK (slot_proxy_handle_drop), drag_info); + g_signal_connect (target, "leave", G_CALLBACK (slot_proxy_drag_leave), drag_info); + gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (target)); } -#endif diff --git a/src/nautilus-window-slot-dnd.h b/src/nautilus-window-slot-dnd.h index 0988dffb294291a67ebaae6aa333527a4cc9717e..bd77969a906c06024c2c929600aebd8d80d081a3 100644 --- a/src/nautilus-window-slot-dnd.h +++ b/src/nautilus-window-slot-dnd.h @@ -25,7 +25,6 @@ #pragma once -#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION #include #include @@ -36,4 +35,3 @@ void nautilus_drag_slot_proxy_init (GtkWidget *widget, NautilusFile *target_file, NautilusWindowSlot *target_slot); -#endif diff --git a/src/resources/css/Adwaita.css b/src/resources/css/Adwaita.css index 47110f38e22e093e27a0e677c65ac42a67dbdd59..af7e33ad77ef464e9490769efaa739def7a76f7b 100644 --- a/src/resources/css/Adwaita.css +++ b/src/resources/css/Adwaita.css @@ -155,7 +155,11 @@ } .nautilus-grid-view gridview > child { + padding: 0px; +} +.nautilus-grid-view #NautilusViewCell { padding: 6px; + border-radius: 6px; } /* Column view */ @@ -204,6 +208,11 @@ padding: 6px; } +/* We want drop feedback on the whole row. Disable per-cell feedback */ +.nautilus-list-view #NautilusViewCell:drop(active) { + box-shadow: none; +} + .nautilus-list-view.compact #NautilusViewCell { padding-top: 3px; padding-bottom: 3px; @@ -214,6 +223,11 @@ } /* Both views */ +.nautilus-list-view:drop(active), +.nautilus-grid-view:drop(active) { + box-shadow: none; +} + .view .thumbnail { background: url('/org/gnome/nautilus/Checkerboard.png') repeat; box-shadow: 0px 1px 2px 0px @shade_color,