diff options
author | Carlos Soriano <csoriano@gnome.org> | 2015-10-03 23:41:04 +0200 |
---|---|---|
committer | Carlos Soriano <csoriano@gnome.org> | 2015-10-06 23:36:30 +0200 |
commit | 749a86440541b6fe622084c2e553784b34cbe51c (patch) | |
tree | 880d3be531794cb2a2127d567341899a7956199a /src | |
parent | 02af0763c53a77c23f7dac6ca8e9121ed4f293dd (diff) | |
download | nautilus-749a86440541b6fe622084c2e553784b34cbe51c.tar.gz |
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.
I'm not entirely happy with the implementation, since it uses custom
functions to access the drag data, given that we need them at drag-begin
time and in random places on the code, since nautilus is doing all the dnd
work manually and on different places.
The final result is that drag and drop is still managed mostly on its own
widgets, in this case list-view and canvas-view, and nautilus-dnd manages
a central accessor for dnd in nautilus, in this case requesting depending
on the widget that is the owner of the data, its data through the custom
functions of that particula widget. All other ways I tried to do it entirely
with only gtk_drag_* or gdk_drag_* functions were in vanish if no a complete
refactoring is done, and probably it doesn't worth the effort. Also I
actually separated the list view dnd code as well, so now at least the
pattern to handling dnd on nautilus is more or less consistent.
Diffstat (limited to 'src')
-rw-r--r-- | src/nautilus-list-view-dnd.c | 92 | ||||
-rw-r--r-- | src/nautilus-list-view-dnd.h | 5 | ||||
-rw-r--r-- | src/nautilus-list-view-private.h | 2 | ||||
-rw-r--r-- | src/nautilus-list-view.c | 2 | ||||
-rw-r--r-- | src/nautilus-window-slot-dnd.c | 1 | ||||
-rw-r--r-- | src/nautilus-window.c | 37 | ||||
-rw-r--r-- | src/nautilus-window.h | 4 |
7 files changed, 123 insertions, 20 deletions
diff --git a/src/nautilus-list-view-dnd.c b/src/nautilus-list-view-dnd.c index d682b3a02..1706b2679 100644 --- a/src/nautilus-list-view-dnd.c +++ b/src/nautilus-list-view-dnd.c @@ -21,33 +21,37 @@ #include "nautilus-list-view-dnd.h" #include "nautilus-list-view-private.h" -#include "nautilus-dnd.h" - static GtkTargetList * source_target_list = NULL; static void +drag_info_data_free (NautilusListView *list_view); + +static void drag_data_get_callback (GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, guint info, - guint time) + guint time, + gpointer user_data) { GtkTreeView *tree_view; GtkTreeModel *model; - GList *selection_cache; + 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 cairo_surface_t * @@ -159,9 +163,10 @@ drag_begin_callback (GtkWidget *widget, GdkDragContext *context, NautilusListView *view) { - GList *selection_cache; cairo_surface_t *surface; + NautilusWindow *window; + window = nautilus_files_view_get_window (NAUTILUS_FILES_VIEW (view)); surface = get_drag_surface (view); if (surface) { @@ -176,20 +181,73 @@ drag_begin_callback (GtkWidget *widget, view->details->drag_button = 0; view->details->drag_started = TRUE; - selection_cache = nautilus_drag_create_selection_cache (view, - each_item_get_data_binder); + 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 void +drag_end_callback (GtkWidget *widget, + GdkDragContext *context, + NautilusListView *list_view) +{ + NautilusWindow *window; + + window = nautilus_files_view_get_window (NAUTILUS_FILES_VIEW (list_view)); + + nautilus_window_end_dnd (window, context); + + drag_info_data_free (list_view); +} + +static void +drag_info_data_free (NautilusListView *list_view) +{ + 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); + list_view->details->drag_source_info = NULL; - g_object_set_data_full (G_OBJECT (context), - "drag-info", - selection_cache, - (GDestroyNotify)nautilus_drag_destroy_selection_list); + g_signal_handlers_disconnect_by_func (list_view->details->tree_view, drag_begin_callback, list_view); + g_signal_handlers_disconnect_by_func (list_view->details->tree_view, drag_data_get_callback, list_view); + g_signal_handlers_disconnect_by_func (list_view->details->tree_view, drag_end_callback, list_view); +} + +NautilusDragInfo * +nautilus_list_view_dnd_get_drag_source_data (NautilusListView *list_view, + GdkDragContext *context) +{ + GtkTreeView *tree_view; + GtkTreeModel *model; + + 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; } void nautilus_list_view_dnd_init (NautilusListView *list_view) { + if (list_view->details->drag_source_info != NULL) + return; + + list_view->details->drag_source_info = g_new0 (NautilusDragInfo, 1); + g_signal_connect_object (list_view->details->tree_view, "drag-begin", G_CALLBACK (drag_begin_callback), list_view, 0); + g_signal_connect_object (list_view->details->tree_view, "drag-end", + G_CALLBACK (drag_end_callback), list_view, 0); g_signal_connect_object (list_view->details->tree_view, "drag-data-get", G_CALLBACK (drag_data_get_callback), list_view, 0); } @@ -209,9 +267,13 @@ nautilus_list_view_dnd_drag_begin (NautilusListView *list_view, event->x, event->y)) { + guint32 actions; + + actions = GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK; + list_view->details->drag_source_info->source_actions = actions; gtk_drag_begin_with_coordinates (GTK_WIDGET (list_view->details->tree_view), source_target_list, - GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK, + actions, list_view->details->drag_button, (GdkEvent*)event, -1, diff --git a/src/nautilus-list-view-dnd.h b/src/nautilus-list-view-dnd.h index 24500eb31..0022daf8a 100644 --- a/src/nautilus-list-view-dnd.h +++ b/src/nautilus-list-view-dnd.h @@ -22,8 +22,13 @@ #include "nautilus-list-view.h" +#include "nautilus-dnd.h" + void nautilus_list_view_dnd_init (NautilusListView *list_view); gboolean nautilus_list_view_dnd_drag_begin (NautilusListView *list_view, GdkEventMotion *event); +NautilusDragInfo * +nautilus_list_view_dnd_get_drag_source_data (NautilusListView *list_view, + GdkDragContext *context); #endif /* NAUTILUS_LIST_VIEW_DND_H */ diff --git a/src/nautilus-list-view-private.h b/src/nautilus-list-view-private.h index 8a24f2dde..7fbe00b89 100644 --- a/src/nautilus-list-view-private.h +++ b/src/nautilus-list-view-private.h @@ -20,6 +20,7 @@ #include "nautilus-list-model.h" #include "nautilus-tree-view-drag-dest.h" +#include "nautilus-dnd.h" struct NautilusListViewDetails { GtkTreeView *tree_view; @@ -53,6 +54,7 @@ struct NautilusListViewDetails { gboolean ignore_button_release; gboolean row_selected_on_button_down; gboolean active; + NautilusDragInfo *drag_source_info; GHashTable *columns; GtkWidget *column_editor; diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index 0fa519f3c..a0377dadc 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -333,6 +333,7 @@ motion_notify_callback (GtkWidget *widget, } } + nautilus_list_view_dnd_init (view); handled = nautilus_list_view_dnd_drag_begin (view, event); return handled; @@ -1621,7 +1622,6 @@ create_and_set_up_tree_view (NautilusListView *view) "changed", G_CALLBACK (list_selection_changed_callback), view, 0); - nautilus_list_view_dnd_init (view); g_signal_connect_object (view->details->tree_view, "motion-notify-event", G_CALLBACK (motion_notify_callback), view, 0); g_signal_connect_object (view->details->tree_view, "enter-notify-event", diff --git a/src/nautilus-window-slot-dnd.c b/src/nautilus-window-slot-dnd.c index 6c9fea571..0cf25ef7a 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 84d9f6129..04b929c19 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,17 +1006,28 @@ places_sidebar_drag_action_requested_cb (GtkPlacesSidebar *sidebar, GList *items; char *uri; int action = 0; - - items = build_selection_list_from_gfile_list (source_file_list); + NautilusDragInfo *info; + guint32 source_actions; + + info = nautilus_drag_get_source_data (context); + if (info != NULL) { + items = info->selection_cache; + source_actions = info->source_actions; + } else { + items = build_selection_list_from_gfile_list (source_file_list); + source_actions = 0; + } uri = g_file_get_uri (dest_file); if (g_list_length (items) < 1) goto out; - nautilus_drag_default_drop_action_for_icons (context, uri, items, &action); + nautilus_drag_default_drop_action_for_icons (context, uri, items, source_actions, &action); out: - nautilus_drag_destroy_selection_list (items); + if (info == NULL) + nautilus_drag_destroy_selection_list (items); + g_free (uri); return action; diff --git a/src/nautilus-window.h b/src/nautilus-window.h index d9b0b2409..8ba877b40 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 |