diff options
-rw-r--r-- | libnautilus-private/nautilus-canvas-dnd.c | 30 | ||||
-rw-r--r-- | libnautilus-private/nautilus-canvas-dnd.h | 3 | ||||
-rw-r--r-- | libnautilus-private/nautilus-canvas-private.h | 1 | ||||
-rw-r--r-- | libnautilus-private/nautilus-dnd.c | 59 | ||||
-rw-r--r-- | libnautilus-private/nautilus-dnd.h | 8 | ||||
-rw-r--r-- | libnautilus-private/nautilus-tree-view-drag-dest.c | 1 | ||||
-rw-r--r-- | src/nautilus-list-view-dnd.c | 90 | ||||
-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 |
13 files changed, 218 insertions, 25 deletions
diff --git a/libnautilus-private/nautilus-canvas-dnd.c b/libnautilus-private/nautilus-canvas-dnd.c index b4da369f3..2b6d2a39c 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,13 @@ nautilus_canvas_container_receive_dropped_icons (NautilusCanvasContainer *contai container->details->dnd_info->drag_info.selection_list = NULL; } +NautilusDragInfo * +nautilus_canvas_dnd_get_drag_source_data (NautilusCanvasContainer *container, + GdkDragContext *context) +{ + return container->details->dnd_source_info; +} + static void nautilus_canvas_container_get_drop_action (NautilusCanvasContainer *container, GdkDragContext *context, @@ -1104,8 +1119,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 +1274,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 +1308,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 +1323,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 +1341,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->source_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 f780848e8..c015f7632 100644 --- a/libnautilus-private/nautilus-canvas-dnd.h +++ b/libnautilus-private/nautilus-canvas-dnd.h @@ -54,4 +54,7 @@ void nautilus_canvas_dnd_begin_drag (NautilusCanvasContainer *conta int start_y); void nautilus_canvas_dnd_end_drag (NautilusCanvasContainer *container); +NautilusDragInfo* nautilus_canvas_dnd_get_drag_source_data (NautilusCanvasContainer *container, + GdkDragContext *context); + #endif /* NAUTILUS_CANVAS_DND_H */ diff --git a/libnautilus-private/nautilus-canvas-private.h b/libnautilus-private/nautilus-canvas-private.h index 6cdd7a6de..2e693aa09 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 694f295da..dce90cce0 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-dnd.h> #include <stdio.h> #include <string.h> @@ -381,10 +383,49 @@ 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 (NAUTILUS_IS_CANVAS_CONTAINER (source_widget)) { + source_data = nautilus_canvas_dnd_get_drag_source_data (NAUTILUS_CANVAS_CONTAINER (source_widget), + context); + } 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_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, - int *action) + const char *target_uri_string, + const GList *items, + guint32 source_actions, + int *action) { gboolean same_fs; gboolean target_is_source_parent; @@ -399,7 +440,19 @@ nautilus_drag_default_drop_action_for_icons (GdkDragContext *context, return; } - actions = gdk_drag_context_get_actions (context) & (GDK_ACTION_MOVE | GDK_ACTION_COPY); + /* 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); diff --git a/libnautilus-private/nautilus-dnd.h b/libnautilus-private/nautilus-dnd.h index 2b343ce44..ee62052ad 100644 --- a/libnautilus-private/nautilus-dnd.h +++ b/libnautilus-private/nautilus-dnd.h @@ -90,6 +90,11 @@ typedef struct { 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, @@ -120,6 +125,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 +155,6 @@ 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); + #endif diff --git a/libnautilus-private/nautilus-tree-view-drag-dest.c b/libnautilus-private/nautilus-tree-view-drag-dest.c index ee578818c..dd638513f 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-dnd.c b/src/nautilus-list-view-dnd.c index d682b3a02..d286f2f83 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,71 @@ 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_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); - g_object_set_data_full (G_OBJECT (context), - "drag-info", - selection_cache, - (GDestroyNotify)nautilus_drag_destroy_selection_list); + 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 +265,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 |