summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libnautilus-private/nautilus-canvas-dnd.c30
-rw-r--r--libnautilus-private/nautilus-canvas-dnd.h3
-rw-r--r--libnautilus-private/nautilus-canvas-private.h1
-rw-r--r--libnautilus-private/nautilus-dnd.c59
-rw-r--r--libnautilus-private/nautilus-dnd.h8
-rw-r--r--libnautilus-private/nautilus-tree-view-drag-dest.c1
-rw-r--r--src/nautilus-list-view-dnd.c90
-rw-r--r--src/nautilus-list-view-dnd.h5
-rw-r--r--src/nautilus-list-view-private.h2
-rw-r--r--src/nautilus-list-view.c2
-rw-r--r--src/nautilus-window-slot-dnd.c1
-rw-r--r--src/nautilus-window.c37
-rw-r--r--src/nautilus-window.h4
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