[nautilus/wip/csoriano/dnd] dnd: use GtkPlacesSidebar drop targets hints



commit b751f14fcbc7dd2ec412c6b4f6c8208899e6320a
Author: Carlos Soriano <csoriano gnome org>
Date:   Sat Oct 3 23:41:04 2015 +0200

    dnd: use GtkPlacesSidebar drop targets hints
    
    Currently the dnd on the sidebar is only triggered when hovering
    above the sidebar itself. However we would like to give some
    feedback all along on the dnd operation.
    For that GtkPlacesSidebar has set_drop_targets_visible public API,
    which was implemented a few months ago and the GtkFileChooser is
    already using.
    
    I just forgot to implement the support for it on Nautilus... even if
    the original work was done for Nautilus, since users will probably
    use dnd more on nautilus than on the file chooser.

 libnautilus-private/nautilus-canvas-dnd.c          |   31 ++++++-
 libnautilus-private/nautilus-canvas-dnd.h          |    4 +
 libnautilus-private/nautilus-canvas-private.h      |    1 +
 libnautilus-private/nautilus-dnd.c                 |   53 ++++++++++-
 libnautilus-private/nautilus-dnd.h                 |    8 ++
 libnautilus-private/nautilus-tree-view-drag-dest.c |    1 +
 src/nautilus-list-view.c                           |   95 +++++++++++++++----
 src/nautilus-list-view.h                           |    5 +
 src/nautilus-window-slot-dnd.c                     |    1 +
 src/nautilus-window.c                              |   42 ++++++++-
 src/nautilus-window.h                              |    4 +
 11 files changed, 217 insertions(+), 28 deletions(-)
---
diff --git a/libnautilus-private/nautilus-canvas-dnd.c b/libnautilus-private/nautilus-canvas-dnd.c
index b4da369..720edf9 100644
--- a/libnautilus-private/nautilus-canvas-dnd.c
+++ b/libnautilus-private/nautilus-canvas-dnd.c
@@ -32,6 +32,8 @@
 
 #include <config.h>
 #include <math.h>
+#include <src/nautilus-window.h>
+
 #include "nautilus-canvas-dnd.h"
 
 #include "nautilus-file-dnd.h"
@@ -528,12 +530,18 @@ drag_end_callback (GtkWidget *widget,
 {
        NautilusCanvasContainer *container;
        NautilusCanvasDndInfo *dnd_info;
+        NautilusWindow *window;
 
        container = NAUTILUS_CANVAS_CONTAINER (widget);
+        window = NAUTILUS_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (container)));
        dnd_info = container->details->dnd_info;
 
        nautilus_drag_destroy_selection_list (dnd_info->drag_info.selection_list);
+       nautilus_drag_destroy_selection_list (container->details->dnd_source_info->selection_cache);
        dnd_info->drag_info.selection_list = NULL;
+        container->details->dnd_source_info->selection_cache = NULL;
+
+        nautilus_window_end_dnd (window, context);
 }
 
 static NautilusCanvasIcon *
@@ -1074,6 +1082,14 @@ nautilus_canvas_container_receive_dropped_icons (NautilusCanvasContainer *contai
        container->details->dnd_info->drag_info.selection_list = NULL;
 }
 
+NautilusDragInfo *
+nautilus_canvas_container_get_drag_source_data (NautilusCanvasContainer *container,
+                                                GdkDragContext          *context,
+                                                guint32                  time)
+{
+        return container->details->dnd_source_info;
+}
+
 static void
 nautilus_canvas_container_get_drop_action (NautilusCanvasContainer *container,
                                         GdkDragContext *context,
@@ -1104,8 +1120,9 @@ nautilus_canvas_container_get_drop_action (NautilusCanvasContainer *container,
        switch (container->details->dnd_info->drag_info.data_type) {
        case NAUTILUS_ICON_DND_GNOME_ICON_LIST:
                if (container->details->dnd_info->drag_info.selection_list != NULL) {
-                       nautilus_drag_default_drop_action_for_icons (context, drop_target, 
-                                                                    
container->details->dnd_info->drag_info.selection_list, 
+                       nautilus_drag_default_drop_action_for_icons (context, drop_target,
+                                                                    
container->details->dnd_info->drag_info.selection_list,
+                                                                     0,
                                                                     action);
                }
                break;
@@ -1258,12 +1275,14 @@ drag_begin_callback (GtkWidget      *widget,
 {
        NautilusCanvasContainer *container;
        NautilusDragInfo *drag_info;
+        NautilusWindow *window;
        cairo_surface_t *surface;
        double x1, y1, x2, y2, winx, winy;
        int x_offset, y_offset;
        int start_x, start_y;
 
        container = NAUTILUS_CANVAS_CONTAINER (widget);
+        window = NAUTILUS_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (container)));
 
        start_x = container->details->dnd_info->drag_info.start_x +
                gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)));
@@ -1290,6 +1309,10 @@ drag_begin_callback (GtkWidget      *widget,
        drag_info->selection_cache = nautilus_drag_create_selection_cache (widget,
                                                                           each_icon_get_data_binder);
 
+        container->details->dnd_source_info->selection_cache = nautilus_drag_create_selection_cache (widget,
+                                                                                                     
each_icon_get_data_binder);
+
+        nautilus_window_start_dnd (window, context);
 }
 
 void
@@ -1301,11 +1324,14 @@ nautilus_canvas_dnd_begin_drag (NautilusCanvasContainer *container,
                              int                    start_y)
 {
        NautilusCanvasDndInfo *dnd_info;
+       NautilusDragInfo *dnd_source_info;
        
        g_return_if_fail (NAUTILUS_IS_CANVAS_CONTAINER (container));
        g_return_if_fail (event != NULL);
 
        dnd_info = container->details->dnd_info;
+       container->details->dnd_source_info = g_new0 (NautilusDragInfo, 1);
+       dnd_source_info = container->details->dnd_source_info;
        g_return_if_fail (dnd_info != NULL);
        
        /* Notice that the event is in bin_window coordinates, because of
@@ -1316,6 +1342,7 @@ nautilus_canvas_dnd_begin_drag (NautilusCanvasContainer *container,
        dnd_info->drag_info.start_y = start_y -
                gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container))); 
 
+        dnd_source_info->overrided_actions = actions;
        /* start the drag */
        gtk_drag_begin_with_coordinates (GTK_WIDGET (container),
                                         dnd_info->drag_info.target_list,
diff --git a/libnautilus-private/nautilus-canvas-dnd.h b/libnautilus-private/nautilus-canvas-dnd.h
index f780848..aecf49d 100644
--- a/libnautilus-private/nautilus-canvas-dnd.h
+++ b/libnautilus-private/nautilus-canvas-dnd.h
@@ -54,4 +54,8 @@ void   nautilus_canvas_dnd_begin_drag            (NautilusCanvasContainer *conta
                                                  int                    start_y);
 void   nautilus_canvas_dnd_end_drag              (NautilusCanvasContainer *container);
 
+NautilusDragInfo* nautilus_canvas_container_get_drag_source_data (NautilusCanvasContainer *container,
+                                                       GdkDragContext          *context,
+                                                       guint32                  time);
+
 #endif /* NAUTILUS_CANVAS_DND_H */
diff --git a/libnautilus-private/nautilus-canvas-private.h b/libnautilus-private/nautilus-canvas-private.h
index 6cdd7a6..2e693aa 100644
--- a/libnautilus-private/nautilus-canvas-private.h
+++ b/libnautilus-private/nautilus-canvas-private.h
@@ -182,6 +182,7 @@ struct NautilusCanvasContainerDetails {
 
        /* DnD info. */
        NautilusCanvasDndInfo *dnd_info;
+       NautilusDragInfo *dnd_source_info;
 
        /* zoom level */
        int zoom_level;
diff --git a/libnautilus-private/nautilus-dnd.c b/libnautilus-private/nautilus-dnd.c
index 694f295..bfa27c7 100644
--- a/libnautilus-private/nautilus-dnd.c
+++ b/libnautilus-private/nautilus-dnd.c
@@ -35,6 +35,8 @@
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
 #include <libnautilus-private/nautilus-file-utilities.h>
+#include <libnautilus-private/nautilus-canvas-dnd.h>
+#include <src/nautilus-list-view.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -381,10 +383,52 @@ source_is_deletable (GFile *file)
        return ret;
 }
 
+NautilusDragInfo *
+nautilus_drag_get_source_data (GdkDragContext *context,
+                               guint32         time)
+{
+        GtkWidget *source_widget;
+        NautilusDragInfo *source_data;
+
+        source_widget = gtk_drag_get_source_widget (context);
+        if (source_widget == NULL)
+                return NULL;
+
+        if (NAUTILUS_IS_CANVAS_CONTAINER (source_widget)) {
+               source_data = nautilus_canvas_container_get_drag_source_data (NAUTILUS_CANVAS_CONTAINER 
(source_widget),
+                                                                             context,
+                                                                             time);
+        } else if (GTK_IS_TREE_VIEW (source_widget)) {
+                NautilusWindow *window;
+                NautilusWindowSlot *active_slot;
+                NautilusView *view;
+
+                window = NAUTILUS_WINDOW (gtk_widget_get_toplevel (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_get_drag_source_data (NAUTILUS_LIST_VIEW (view),
+                                                                               context,
+                                                                               time);
+                } 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,
-                                            int *action)
+                                             const char     *target_uri_string,
+                                             const GList    *items,
+                                             guint32         overrided_actions,
+                                             int            *action)
 {
        gboolean same_fs;
        gboolean target_is_source_parent;
@@ -399,7 +443,10 @@ nautilus_drag_default_drop_action_for_icons (GdkDragContext *context,
                return;
        }
 
-       actions = gdk_drag_context_get_actions (context) & (GDK_ACTION_MOVE | GDK_ACTION_COPY);
+        if (overrided_actions)
+                actions = overrided_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);
diff --git a/libnautilus-private/nautilus-dnd.h b/libnautilus-private/nautilus-dnd.h
index 2b343ce..fe16574 100644
--- a/libnautilus-private/nautilus-dnd.h
+++ b/libnautilus-private/nautilus-dnd.h
@@ -90,6 +90,10 @@ typedef struct {
        gboolean waiting_to_autoscroll;
        gint64 start_auto_scroll_in;
 
+        /* overrided actions. Used for knowing the actions using a GdkDragContext
+         * source instead of destination */
+        guint32 overrided_actions;
+
 } NautilusDragInfo;
 
 typedef void           (* NautilusDragEachSelectedItemDataGet) (const char *url, 
@@ -120,6 +124,7 @@ gboolean                nautilus_drag_items_on_desktop              (const GList          
                *selection_li
 void                       nautilus_drag_default_drop_action_for_icons (GdkDragContext                       
*context,
                                                                         const char                           
*target_uri,
                                                                         const GList                          
*items,
+                                                                         guint32                             
  overrided_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,
@@ -149,4 +154,7 @@ void                            nautilus_drag_autoscroll_stop               
(NautilusDragInfo                     *drag_info);
 
 gboolean                   nautilus_drag_selection_includes_special_link (GList                              
*selection_list);
 
+NautilusDragInfo *                     nautilus_drag_get_source_data               (GdkDragContext *context,
+                                                                         guint32         time);
+
 #endif
diff --git a/libnautilus-private/nautilus-tree-view-drag-dest.c 
b/libnautilus-private/nautilus-tree-view-drag-dest.c
index ee57881..dd63851 100644
--- a/libnautilus-private/nautilus-tree-view-drag-dest.c
+++ b/libnautilus-private/nautilus-tree-view-drag-dest.c
@@ -513,6 +513,7 @@ get_drop_action (NautilusTreeViewDragDest *dest,
                        (context,
                         drop_target,
                         dest->details->drag_list,
+                         0,
                         &action);
                break;
        case NAUTILUS_ICON_DND_NETSCAPE_URL:
diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c
index 50e76a4..ca1c7fd 100644
--- a/src/nautilus-list-view.c
+++ b/src/nautilus-list-view.c
@@ -97,6 +97,7 @@ struct NautilusListViewDetails {
        gboolean ignore_button_release;
        gboolean row_selected_on_button_down;
        gboolean active;
+        NautilusDragInfo *drag_source_info;
        
        GHashTable *columns;
        GtkWidget *column_editor;
@@ -342,31 +343,58 @@ nautilus_list_view_did_not_drag (NautilusListView *view,
        
 }
 
-static void 
-drag_data_get_callback (GtkWidget *widget,
-                       GdkDragContext *context,
-                       GtkSelectionData *selection_data,
-                       guint info,
-                       guint time)
+NautilusDragInfo *
+nautilus_list_view_get_drag_source_data (NautilusListView *list_view,
+                                         GdkDragContext   *context,
+                                         guint32           time)
 {
        GtkTreeView *tree_view;
        GtkTreeModel *model;
-       GList *selection_cache;
+
+       tree_view = GTK_TREE_VIEW (list_view->details->tree_view);
+
+       model = gtk_tree_view_get_model (tree_view);
+
+       if (model == NULL) {
+               return NULL;
+       }
+
+       if (list_view->details->drag_source_info == NULL ||
+            list_view->details->drag_source_info->selection_cache == NULL) {
+               return NULL;
+       }
+
+        return list_view->details->drag_source_info;
+}
+
+static void
+drag_data_get_callback (GtkWidget        *widget,
+                        GdkDragContext   *context,
+                        GtkSelectionData *selection_data,
+                        guint             info,
+                        guint             time,
+                        gpointer          user_data)
+{
+       GtkTreeView *tree_view;
+       GtkTreeModel *model;
+        NautilusListView *list_view;
 
        tree_view = GTK_TREE_VIEW (widget);
-  
+        list_view = NAUTILUS_LIST_VIEW (user_data);
+
        model = gtk_tree_view_get_model (tree_view);
   
        if (model == NULL) {
                return;
        }
 
-       selection_cache = g_object_get_data (G_OBJECT (context), "drag-info");
-       if (selection_cache == NULL) {
+       if (list_view->details->drag_source_info == NULL ||
+            list_view->details->drag_source_info->selection_cache == NULL) {
                return;
        }
 
-       nautilus_drag_drag_data_get_from_cache (selection_cache, context, selection_data, info, time);
+       nautilus_drag_drag_data_get_from_cache (list_view->details->drag_source_info->selection_cache,
+                                                context, selection_data, info, time);
 }
 
 static void
@@ -479,14 +507,31 @@ each_item_get_data_binder (NautilusDragEachSelectedItemDataGet iteratee,
        gtk_tree_selection_selected_foreach (selection, item_get_data_binder, &context);
 }
 
+static void
+drag_end_callback (GtkWidget        *widget,
+                   GdkDragContext   *context,
+                   NautilusListView *view)
+{
+        NautilusWindow *window;
+
+        window = nautilus_files_view_get_window (NAUTILUS_FILES_VIEW (view));
+
+        nautilus_window_end_dnd (window, context);
+
+       nautilus_drag_destroy_selection_list (view->details->drag_source_info->selection_cache);
+       view->details->drag_source_info->selection_cache = NULL;
+}
 
 static void
 drag_begin_callback (GtkWidget *widget,
                     GdkDragContext *context,
                     NautilusListView *view)
 {
-       GList *selection_cache;
        cairo_surface_t *surface;
+        GdkDragAction actions;
+        NautilusWindow *window;
+
+        window = nautilus_files_view_get_window (NAUTILUS_FILES_VIEW (view));
 
        surface = get_drag_surface (view);
        if (surface) {
@@ -499,13 +544,10 @@ drag_begin_callback (GtkWidget *widget,
        stop_drag_check (view);
        view->details->drag_started = TRUE;
 
-       selection_cache = nautilus_drag_create_selection_cache (view,
-                                                               each_item_get_data_binder);
-
-       g_object_set_data_full (G_OBJECT (context),
-                               "drag-info",
-                               selection_cache,
-                               (GDestroyNotify)nautilus_drag_destroy_selection_list);
+        /* Source selection */
+        view->details->drag_source_info->selection_cache = nautilus_drag_create_selection_cache (view,
+                                                                                                 
each_item_get_data_binder);
+        nautilus_window_start_dnd (window, context);
 }
 
 static gboolean
@@ -553,10 +595,14 @@ motion_notify_callback (GtkWidget *widget,
                                              view->details->drag_y,
                                              event->x, 
                                              event->y)) {
+                        guint32 actions;
+
+                        actions = GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK;
+                        view->details->drag_source_info->overrided_actions = actions;
                        gtk_drag_begin
                                (widget,
                                 source_target_list,
-                                GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK,
+                                actions,
                                 view->details->drag_button,
                                 (GdkEvent*)event);
                }                     
@@ -1851,6 +1897,8 @@ create_and_set_up_tree_view (NautilusListView *view)
 
        g_signal_connect_object (view->details->tree_view, "drag-begin",
                                 G_CALLBACK (drag_begin_callback), view, 0);
+       g_signal_connect_object (view->details->tree_view, "drag-end",
+                                G_CALLBACK (drag_end_callback), view, 0);
        g_signal_connect_object (view->details->tree_view, "drag-data-get",
                                 G_CALLBACK (drag_data_get_callback), view, 0);
        g_signal_connect_object (view->details->tree_view, "motion-notify-event",
@@ -3174,6 +3222,11 @@ nautilus_list_view_finalize (GObject *object)
 
        g_free (list_view->details);
 
+       nautilus_drag_destroy_selection_list (list_view->details->drag_source_info->selection_cache);
+       list_view->details->drag_source_info->selection_cache = NULL;
+        g_free (list_view->details->drag_source_info);
+
+
        g_signal_handlers_disconnect_by_func (nautilus_preferences,
                                              default_sort_order_changed_callback,
                                              list_view);
@@ -3427,6 +3480,8 @@ nautilus_list_view_init (NautilusListView *list_view)
                                  "clipboard-info",
                                  G_CALLBACK (list_view_notify_clipboard_info), list_view);
 
+       list_view->details->drag_source_info = g_new0 (NautilusDragInfo, 1);
+
        view_action_group = nautilus_files_view_get_action_group (NAUTILUS_FILES_VIEW (list_view));
        g_action_map_add_action_entries (G_ACTION_MAP (view_action_group),
                                        list_view_entries,
diff --git a/src/nautilus-list-view.h b/src/nautilus-list-view.h
index 03f027e..8f388d0 100644
--- a/src/nautilus-list-view.h
+++ b/src/nautilus-list-view.h
@@ -54,4 +54,9 @@ typedef struct {
 GType nautilus_list_view_get_type (void);
 NautilusFilesView * nautilus_list_view_new (NautilusWindowSlot *slot);
 
+NautilusDragInfo *
+nautilus_list_view_get_drag_source_data (NautilusListView *list_view,
+                                         GdkDragContext   *context,
+                                         guint32           time);
+
 #endif /* NAUTILUS_LIST_VIEW_H */
diff --git a/src/nautilus-window-slot-dnd.c b/src/nautilus-window-slot-dnd.c
index 6c9fea5..0cf25ef 100644
--- a/src/nautilus-window-slot-dnd.c
+++ b/src/nautilus-window-slot-dnd.c
@@ -214,6 +214,7 @@ slot_proxy_drag_motion (GtkWidget          *widget,
     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);
diff --git a/src/nautilus-window.c b/src/nautilus-window.c
index da28b52..c52b244 100644
--- a/src/nautilus-window.c
+++ b/src/nautilus-window.c
@@ -977,6 +977,24 @@ build_selection_list_from_gfile_list (GList *gfile_list)
        return g_list_reverse (result);
 }
 
+void
+nautilus_window_start_dnd (NautilusWindow *window,
+                           GdkDragContext *context)
+{
+        gtk_places_sidebar_set_drop_targets_visible (GTK_PLACES_SIDEBAR (window->priv->places_sidebar),
+                                                     TRUE,
+                                                     context);
+}
+
+void
+nautilus_window_end_dnd (NautilusWindow *window,
+                         GdkDragContext *context)
+{
+        gtk_places_sidebar_set_drop_targets_visible (GTK_PLACES_SIDEBAR (window->priv->places_sidebar),
+                                                     FALSE,
+                                                     context);
+}
+
 /* Callback used when the places sidebar needs to know the drag action to suggest */
 static GdkDragAction
 places_sidebar_drag_action_requested_cb (GtkPlacesSidebar *sidebar,
@@ -988,13 +1006,31 @@ places_sidebar_drag_action_requested_cb (GtkPlacesSidebar *sidebar,
        GList *items;
        char *uri;
        int action = 0;
+        GtkWidget *source_widget;
+        NautilusDragInfo *info;
+        guint32 overrided_actions;
+
+
+        source_widget = gtk_drag_get_source_widget (context);
 
-       items = build_selection_list_from_gfile_list (source_file_list);
+        info = nautilus_drag_get_source_data (context, GDK_CURRENT_TIME);
+        if (info != NULL) {
+                items = info->selection_cache;
+                overrided_actions = info->overrided_actions;
+        } else {
+                items = build_selection_list_from_gfile_list (source_file_list);
+                overrided_actions = 0;
+        }
        uri = g_file_get_uri (dest_file);
 
-       nautilus_drag_default_drop_action_for_icons (context, uri, items, &action);
+        if (g_list_length (items) < 1)
+                return 0;
+
+       nautilus_drag_default_drop_action_for_icons (context, uri, items, overrided_actions, &action);
+
+        if (info == NULL)
+               nautilus_drag_destroy_selection_list (items);
 
-       nautilus_drag_destroy_selection_list (items);
        g_free (uri);
 
        return action;
diff --git a/src/nautilus-window.h b/src/nautilus-window.h
index d9b0b24..8ba877b 100644
--- a/src/nautilus-window.h
+++ b/src/nautilus-window.h
@@ -145,4 +145,8 @@ void nautilus_window_sync_title            (NautilusWindow *window,
 void nautilus_window_show_operation_notification (NautilusWindow *window,
                                                   gchar          *main_label,
                                                   GFile          *folder_to_open);
+void nautilus_window_start_dnd (NautilusWindow *window,
+                                GdkDragContext *context);
+void nautilus_window_end_dnd (NautilusWindow *window,
+                              GdkDragContext *context);
 #endif


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