summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog-2000041450
-rw-r--r--libnautilus-extensions/nautilus-file.c28
-rw-r--r--libnautilus-extensions/nautilus-file.h4
-rw-r--r--libnautilus-extensions/nautilus-gtk-extensions.c14
-rw-r--r--libnautilus-extensions/nautilus-gtk-extensions.h5
-rw-r--r--libnautilus-extensions/nautilus-icon-canvas-item.c8
-rw-r--r--libnautilus-extensions/nautilus-icon-container.c24
-rw-r--r--libnautilus-extensions/nautilus-icon-container.h3
-rw-r--r--libnautilus-extensions/nautilus-icon-dnd.c101
-rw-r--r--libnautilus-extensions/nautilus-icon-dnd.h3
-rw-r--r--libnautilus-private/nautilus-file.c28
-rw-r--r--libnautilus-private/nautilus-file.h4
-rw-r--r--libnautilus-private/nautilus-gtk-extensions.c14
-rw-r--r--libnautilus-private/nautilus-gtk-extensions.h5
-rw-r--r--libnautilus-private/nautilus-icon-canvas-item.c8
-rw-r--r--libnautilus-private/nautilus-icon-container.c24
-rw-r--r--libnautilus-private/nautilus-icon-container.h3
-rw-r--r--libnautilus-private/nautilus-icon-dnd.c101
-rw-r--r--libnautilus-private/nautilus-icon-dnd.h3
-rw-r--r--libnautilus/nautilus-file.c28
-rw-r--r--libnautilus/nautilus-file.h4
-rw-r--r--libnautilus/nautilus-gtk-extensions.c14
-rw-r--r--libnautilus/nautilus-gtk-extensions.h5
-rw-r--r--libnautilus/nautilus-icon-canvas-item.c8
-rw-r--r--libnautilus/nautilus-icon-container.c24
-rw-r--r--libnautilus/nautilus-icon-container.h3
-rw-r--r--libnautilus/nautilus-icon-dnd.c101
-rw-r--r--libnautilus/nautilus-icon-dnd.h3
-rw-r--r--src/file-manager/fm-directory-view.c24
-rw-r--r--src/file-manager/fm-directory-view.h4
-rw-r--r--src/file-manager/fm-icon-view.c4
31 files changed, 595 insertions, 57 deletions
diff --git a/ChangeLog-20000414 b/ChangeLog-20000414
index 48f63618f..9c3ee9e60 100644
--- a/ChangeLog-20000414
+++ b/ChangeLog-20000414
@@ -1,3 +1,53 @@
+2000-04-11 Pavel Cisler <pavel@eazel.com>
+
+ * libnautilus/nautilus-icon-dnd.c:
+ * libnautilus/nautilus-icon-dnd.h:
+ (nautilus_icon_dnd_update_drop_target):
+ Determine if a drop target can accept drop, update highlight for
+ drop accordingly.
+ (nautilus_icon_dnd_update_drop_target):
+ Add drop highlighting for dragged items that can be accepted by a
+ drop target.
+ (nautilus_icon_canvas_item_can_accept_item):
+ Implement the call.
+ (nautilus_icon_canvas_item_can_accept_items):
+ Put a cap on the number of items checked as accepted by drop target
+ to not lock up the machine when dragging lots of items.
+ (nautilus_icon_dnd_modifier_based_action):
+ Tweak the modifier keys -- use Alt to force copy.
+
+ * libnautilus/nautilus-icon-container.c:
+ * libnautilus/nautilus-icon-container.h:
+ * src/file-manager/fm-directory-view.c:
+ * src/file-manager/fm-directory-view.h:
+ * src/file-manager/fm-icon-view.c:
+ (can_accept_item), (fm_directory_view_can_accept_item):
+ New signal -- helps figuring out if potential drop target can
+ accept dropped URIs. For now returns TRUE for any directory that
+ doesn't match the dragged item.
+
+ * libnautilus/nautilus-icon-container.c:
+ (item_event_callback):
+ Support for turning the "highlight for drop" state of an icon on/off --
+ during drag&drop don't let the "enter notify" signal reach the canvas item
+ so that the item won't get prelit.
+
+ * libnautilus/nautilus-icon-canvas-item.c:
+ (nautilus_icon_canvas_item_event):
+ Turn off highlight for drop as well as prelight on leave event.
+ This is a fallback in case the drag&drop for some reason leaves
+ the target icon highlighted for drop after a drag ends.
+
+ * libnautilus/nautilus-gtk-extensions.c:
+ * libnautilus/nautilus-gtk-extensions.h:
+ (nautilus_gtk_marshal_INT__POINTER_POINTER):
+ Added another binder function.
+
+ * libnautilus/nautilus-file.c:
+ * libnautilus/nautilus-file.h:
+ (nautilus_file_matches_uri): Added a utility call used to detect
+ a drop on self.
+
2000-04-10 Andy Hertzfeld <andy@eazel.com>
* components/rpmview/nautilus-rpmview.c:
diff --git a/libnautilus-extensions/nautilus-file.c b/libnautilus-extensions/nautilus-file.c
index 0ed7bf771..d98a2e06e 100644
--- a/libnautilus-extensions/nautilus-file.c
+++ b/libnautilus-extensions/nautilus-file.c
@@ -360,6 +360,34 @@ nautilus_file_rename (NautilusFile *file, const char *new_name)
return result;
}
+gboolean
+nautilus_file_matches_uri (NautilusFile *file, const char *uri_string)
+{
+ GnomeVFSURI *match_uri;
+ GnomeVFSURI *file_uri;
+ gboolean result;
+
+ g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
+ g_return_val_if_fail (uri_string != NULL, FALSE);
+
+ match_uri = gnome_vfs_uri_new (uri_string);
+ if (match_uri == NULL)
+ return FALSE;
+
+ result = FALSE;
+ file_uri = gnome_vfs_uri_append_path (file->details->directory->details->uri,
+ file->details->info->name);
+
+ if (match_uri != NULL) {
+ result = gnome_vfs_uri_equal (file_uri, match_uri);
+ }
+
+ gnome_vfs_uri_unref (file_uri);
+ gnome_vfs_uri_unref (match_uri);
+
+ return result;
+}
+
static int
nautilus_file_compare_by_size_with_directories (NautilusFile *file_1, NautilusFile *file_2)
{
diff --git a/libnautilus-extensions/nautilus-file.h b/libnautilus-extensions/nautilus-file.h
index 6cc0c79be..27bb41b76 100644
--- a/libnautilus-extensions/nautilus-file.h
+++ b/libnautilus-extensions/nautilus-file.h
@@ -122,6 +122,10 @@ void nautilus_file_set_metadata (NautilusFile *
char * nautilus_file_get_string_attribute (NautilusFile *file,
const char *attribute_name);
+/* Matching with another URI*/
+gboolean nautilus_file_matches_uri (NautilusFile *file,
+ const char *uri);
+
/* Comparing two file objects for sorting */
int nautilus_file_compare_for_sort (NautilusFile *file_1,
NautilusFile *file_2,
diff --git a/libnautilus-extensions/nautilus-gtk-extensions.c b/libnautilus-extensions/nautilus-gtk-extensions.c
index 99d8d1523..b89404644 100644
--- a/libnautilus-extensions/nautilus-gtk-extensions.c
+++ b/libnautilus-extensions/nautilus-gtk-extensions.c
@@ -320,6 +320,20 @@ nautilus_gtk_marshal_POINTER__POINTER (GtkObject *object,
}
void
+nautilus_gtk_marshal_INT__POINTER_POINTER (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ * GTK_RETLOC_INT (args[2]) =
+ (* (int (*)(GtkObject *, gpointer, gpointer, gpointer)) func)
+ (object,
+ GTK_VALUE_POINTER (args[0]),
+ GTK_VALUE_POINTER (args[1]),
+ func_data);
+}
+
+void
nautilus_gtk_marshal_POINTER__POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
diff --git a/libnautilus-extensions/nautilus-gtk-extensions.h b/libnautilus-extensions/nautilus-gtk-extensions.h
index 88f0684f1..61f1f5187 100644
--- a/libnautilus-extensions/nautilus-gtk-extensions.h
+++ b/libnautilus-extensions/nautilus-gtk-extensions.h
@@ -38,6 +38,7 @@
#define nautilus_gtk_marshal_STRING__POINTER_STRING nautilus_gtk_marshal_POINTER__POINTER_POINTER
#define nautilus_gtk_marshal_STRING__POINTER_POINTER_POINTER nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER
#define nautilus_gtk_marshal_STRING__POINTER_POINTER_STRING nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER
+#define nautilus_gtk_marshal_INT__POINTER_STRING nautilus_gtk_marshal_INT__POINTER_POINTER
#define NAUTILUS_DEFAULT_POPUP_MENU_DISPLACEMENT 2
@@ -101,6 +102,10 @@ void nautilus_gtk_marshal_POINTER__POINTER
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
+void nautilus_gtk_marshal_INT__POINTER_POINTER (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
diff --git a/libnautilus-extensions/nautilus-icon-canvas-item.c b/libnautilus-extensions/nautilus-icon-canvas-item.c
index 268a58459..bc5be35e9 100644
--- a/libnautilus-extensions/nautilus-icon-canvas-item.c
+++ b/libnautilus-extensions/nautilus-icon-canvas-item.c
@@ -1018,8 +1018,14 @@ nautilus_icon_canvas_item_event (GnomeCanvasItem *item, GdkEvent *event)
return TRUE;
case GDK_LEAVE_NOTIFY:
- if (icon_item->details->is_prelit) {
+ if (icon_item->details->is_prelit
+ || icon_item->details->is_highlighted_for_drop) {
+ /* When leaving, turn of the prelight state and the
+ * higlighted for drop. The latter gets turned on
+ * by the drag&drop motion callback.
+ */
icon_item->details->is_prelit = FALSE;
+ icon_item->details->is_highlighted_for_drop = FALSE;
gnome_canvas_item_request_update (item);
}
return TRUE;
diff --git a/libnautilus-extensions/nautilus-icon-container.c b/libnautilus-extensions/nautilus-icon-container.c
index a656ebd10..1d656703f 100644
--- a/libnautilus-extensions/nautilus-icon-container.c
+++ b/libnautilus-extensions/nautilus-icon-container.c
@@ -106,6 +106,7 @@ enum {
SELECTION_CHANGED,
MOVE_COPY_ITEMS,
GET_CONTAINER_URI,
+ CAN_ACCEPT_ITEM,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
@@ -1868,6 +1869,16 @@ nautilus_icon_container_initialize_class (NautilusIconContainerClass *class)
get_container_uri),
nautilus_gtk_marshal_STRING__NONE,
GTK_TYPE_STRING, 0);
+ signals[CAN_ACCEPT_ITEM]
+ = gtk_signal_new ("can_accept_item",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (NautilusIconContainerClass,
+ can_accept_item),
+ nautilus_gtk_marshal_INT__POINTER_STRING,
+ GTK_TYPE_INT, 2,
+ GTK_TYPE_POINTER,
+ GTK_TYPE_STRING);
@@ -2041,6 +2052,19 @@ item_event_callback (GnomeCanvasItem *item,
g_return_val_if_fail (icon != NULL, FALSE);
switch (event->type) {
+ case GDK_ENTER_NOTIFY:
+ if (details->drag_button != 0) {
+ /* Drag motion callback will take care of the
+ * necessary update -- don't let the signal reach
+ * the canvas item and cause a prelight.
+ * We let the GDK_LEAVE_NOTIFY fly through here to
+ * cause the "can_accept_drop" state to get turned off
+ */
+ gtk_signal_emit_stop_by_name (GTK_OBJECT (item), "event");
+ return TRUE;
+ }
+ return FALSE;
+
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
if (handle_icon_button_press (container, icon, &event->button)) {
diff --git a/libnautilus-extensions/nautilus-icon-container.h b/libnautilus-extensions/nautilus-icon-container.h
index f910052f2..0d3d49d24 100644
--- a/libnautilus-extensions/nautilus-icon-container.h
+++ b/libnautilus-extensions/nautilus-icon-container.h
@@ -68,6 +68,9 @@ struct NautilusIconContainerClass {
double scale_x, double scale_y);
char * (* get_container_uri) (NautilusIconContainer *container);
+ gboolean (* can_accept_item) (NautilusIconContainer *container,
+ const NautilusIconData *target_uri,
+ const char *item_uri);
/* Connect to these signals to supply information about icons.
* They are called as needed after the icons are inserted.
diff --git a/libnautilus-extensions/nautilus-icon-dnd.c b/libnautilus-extensions/nautilus-icon-dnd.c
index 05a041dd3..f3cd41f97 100644
--- a/libnautilus-extensions/nautilus-icon-dnd.c
+++ b/libnautilus-extensions/nautilus-icon-dnd.c
@@ -45,10 +45,16 @@
#include <libgnomeui/gnome-canvas-rect-ellipse.h>
#include "nautilus-icon-private.h"
-static int nautilus_icon_drag_key_callback (GtkWidget *widget, GdkEventKey *event,
- gpointer data);
-static gboolean drag_drop_callback (GtkWidget *widget, GdkDragContext *context,
- int x, int y, guint32 time, gpointer data);
+static int nautilus_icon_drag_key_callback (GtkWidget *widget, GdkEventKey *event,
+ gpointer data);
+static gboolean drag_drop_callback (GtkWidget *widget,
+ GdkDragContext *context,
+ int x, int y,
+ guint32 time, gpointer data);
+static void nautilus_icon_dnd_update_drop_target (NautilusIconContainer *container,
+ GdkDragContext *context,
+ int x, int y);
+
typedef struct {
char *uri;
@@ -510,9 +516,9 @@ drag_motion_callback (GtkWidget *widget,
guint32 time)
{
nautilus_icon_dnd_update_drop_action (widget);
-
nautilus_icon_container_ensure_drag_data (NAUTILUS_ICON_CONTAINER (widget), context, time);
nautilus_icon_container_position_shadow (NAUTILUS_ICON_CONTAINER (widget), x, y);
+ nautilus_icon_dnd_update_drop_target (NAUTILUS_ICON_CONTAINER (widget), context, x, y);
gdk_drag_status (context, context->suggested_action, time);
@@ -628,16 +634,18 @@ nautilus_icon_container_selection_items_local (const NautilusIconContainer *cont
}
static gboolean
-nautilus_icon_canvas_item_can_accept_item (const NautilusIcon *drop_target_item,
+nautilus_icon_canvas_item_can_accept_item (NautilusIconContainer *container,
+ const NautilusIcon *drop_target_item,
const char *item_uri)
{
- /* FIXME:
- *
- * should have NautilusFile answer whether it can handle icon URI
- *
- * For now:
- */
- return TRUE;
+ gboolean result;
+
+ gtk_signal_emit_by_name (GTK_OBJECT (container),
+ "can_accept_item",
+ drop_target_item->data,
+ item_uri,
+ &result);
+ return result;
}
static gboolean
@@ -645,10 +653,17 @@ nautilus_icon_canvas_item_can_accept_items (NautilusIconContainer *container,
const NautilusIcon *drop_target_item,
const GList *items)
{
- for (; items != NULL; items = items->next) {
- if (!nautilus_icon_canvas_item_can_accept_item (drop_target_item,
- ((DndSelectionItem *)items->data)->uri))
+ int max;
+
+ /* Iterate through selection checking if item will get accepted by the
+ * drop target. If more than 100 items selected, return an over-optimisic
+ * result
+ */
+ for (max = 100; items != NULL && max >=0 ; items = items->next, max--) {
+ if (!nautilus_icon_canvas_item_can_accept_item (container, drop_target_item,
+ ((DndSelectionItem *)items->data)->uri)) {
return FALSE;
+ }
}
return TRUE;
@@ -808,6 +823,53 @@ nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container,
}
static void
+nautilus_icon_dnd_update_drop_target (NautilusIconContainer *container,
+ GdkDragContext *context,
+ int x, int y)
+{
+ NautilusIcon *drop_target_icon;
+ double world_x, world_y;
+
+ g_assert (NAUTILUS_IS_ICON_CONTAINER (container));
+ if (container->details->dnd_info->selection_list == NULL) {
+ return;
+ }
+
+ gnome_canvas_window_to_world (GNOME_CANVAS (container),
+ x, y, &world_x, &world_y);
+
+
+ /* Find the item we hit with our drop, if any. */
+ drop_target_icon = nautilus_icon_container_item_at (container, world_x, world_y);
+
+
+ /* Find if target icon accepts our drop. */
+ if (drop_target_icon != NULL
+ && !nautilus_icon_canvas_item_can_accept_items
+ (container, drop_target_icon, container->details->dnd_info->selection_list)) {
+ drop_target_icon = NULL;
+ }
+
+ /* Check if current drop target changed, update icon drop higlight if needed. */
+ if (drop_target_icon != container->details->dnd_info->current_drop_target_icon) {
+ /* Turn on new target, if any. */
+ if (drop_target_icon != NULL) {
+ gnome_canvas_item_set (GNOME_CANVAS_ITEM (drop_target_icon->item),
+ "highlighted_for_drop", TRUE,
+ NULL);
+ }
+ /* Turn off old target, if any. */
+ if (container->details->dnd_info->current_drop_target_icon != NULL) {
+ gnome_canvas_item_set (GNOME_CANVAS_ITEM (((NautilusIcon *)container->details->
+ dnd_info->current_drop_target_icon)->item),
+ "highlighted_for_drop", FALSE, NULL);
+ }
+ /* Remember the new drop target for the next round. */
+ container->details->dnd_info->current_drop_target_icon = drop_target_icon;
+ }
+}
+
+static void
nautilus_icon_container_free_drag_data (NautilusIconContainer *container)
{
NautilusIconDndInfo *dnd_info;
@@ -1013,6 +1075,8 @@ nautilus_icon_dnd_begin_drag (NautilusIconContainer *container,
GTK_SIGNAL_FUNC (nautilus_icon_drag_key_callback), info);
+ container->details->dnd_info->current_drop_target_icon = NULL;
+
/* create a pixmap and mask to drag with */
pixbuf = nautilus_icon_canvas_item_get_image (container->details->drag_icon->item, NULL);
@@ -1095,6 +1159,7 @@ drag_drop_callback (GtkWidget *widget,
}
NAUTILUS_ICON_CONTAINER (widget)->details->dnd_info->saved_drag_source_info = NULL;
+ NAUTILUS_ICON_CONTAINER (widget)->details->dnd_info->current_drop_target_icon = NULL;
return FALSE;
}
@@ -1120,13 +1185,13 @@ nautilus_icon_dnd_modifier_based_action ()
GdkModifierType modifiers;
gdk_window_get_pointer (NULL, NULL, NULL, &modifiers);
- if ((modifiers & GDK_CONTROL_MASK) != 0) {
+ if ((modifiers & GDK_MOD1_MASK) != 0) {
return GDK_ACTION_COPY;
#if 0
/* FIXME:
* don't know how to do links yet
*/
- } else if ((modifiers & GDK_MOD1_MASK) != 0) {
+ } else if ((modifiers & GDK_CONTROL_MASK) != 0) {
return GDK_ACTION_LINK;
#endif
}
diff --git a/libnautilus-extensions/nautilus-icon-dnd.h b/libnautilus-extensions/nautilus-icon-dnd.h
index f75b9aed8..821dd3d9b 100644
--- a/libnautilus-extensions/nautilus-icon-dnd.h
+++ b/libnautilus-extensions/nautilus-icon-dnd.h
@@ -79,6 +79,9 @@ struct NautilusIconDndInfo {
* interface gets added to gtkdnd to do this in a clean way
*/
gpointer saved_drag_source_info;
+
+ /* last highlighted drop target*/
+ gpointer current_drop_target_icon;
};
void nautilus_icon_dnd_init (NautilusIconContainer *container,
diff --git a/libnautilus-private/nautilus-file.c b/libnautilus-private/nautilus-file.c
index 0ed7bf771..d98a2e06e 100644
--- a/libnautilus-private/nautilus-file.c
+++ b/libnautilus-private/nautilus-file.c
@@ -360,6 +360,34 @@ nautilus_file_rename (NautilusFile *file, const char *new_name)
return result;
}
+gboolean
+nautilus_file_matches_uri (NautilusFile *file, const char *uri_string)
+{
+ GnomeVFSURI *match_uri;
+ GnomeVFSURI *file_uri;
+ gboolean result;
+
+ g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
+ g_return_val_if_fail (uri_string != NULL, FALSE);
+
+ match_uri = gnome_vfs_uri_new (uri_string);
+ if (match_uri == NULL)
+ return FALSE;
+
+ result = FALSE;
+ file_uri = gnome_vfs_uri_append_path (file->details->directory->details->uri,
+ file->details->info->name);
+
+ if (match_uri != NULL) {
+ result = gnome_vfs_uri_equal (file_uri, match_uri);
+ }
+
+ gnome_vfs_uri_unref (file_uri);
+ gnome_vfs_uri_unref (match_uri);
+
+ return result;
+}
+
static int
nautilus_file_compare_by_size_with_directories (NautilusFile *file_1, NautilusFile *file_2)
{
diff --git a/libnautilus-private/nautilus-file.h b/libnautilus-private/nautilus-file.h
index 6cc0c79be..27bb41b76 100644
--- a/libnautilus-private/nautilus-file.h
+++ b/libnautilus-private/nautilus-file.h
@@ -122,6 +122,10 @@ void nautilus_file_set_metadata (NautilusFile *
char * nautilus_file_get_string_attribute (NautilusFile *file,
const char *attribute_name);
+/* Matching with another URI*/
+gboolean nautilus_file_matches_uri (NautilusFile *file,
+ const char *uri);
+
/* Comparing two file objects for sorting */
int nautilus_file_compare_for_sort (NautilusFile *file_1,
NautilusFile *file_2,
diff --git a/libnautilus-private/nautilus-gtk-extensions.c b/libnautilus-private/nautilus-gtk-extensions.c
index 99d8d1523..b89404644 100644
--- a/libnautilus-private/nautilus-gtk-extensions.c
+++ b/libnautilus-private/nautilus-gtk-extensions.c
@@ -320,6 +320,20 @@ nautilus_gtk_marshal_POINTER__POINTER (GtkObject *object,
}
void
+nautilus_gtk_marshal_INT__POINTER_POINTER (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ * GTK_RETLOC_INT (args[2]) =
+ (* (int (*)(GtkObject *, gpointer, gpointer, gpointer)) func)
+ (object,
+ GTK_VALUE_POINTER (args[0]),
+ GTK_VALUE_POINTER (args[1]),
+ func_data);
+}
+
+void
nautilus_gtk_marshal_POINTER__POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
diff --git a/libnautilus-private/nautilus-gtk-extensions.h b/libnautilus-private/nautilus-gtk-extensions.h
index 88f0684f1..61f1f5187 100644
--- a/libnautilus-private/nautilus-gtk-extensions.h
+++ b/libnautilus-private/nautilus-gtk-extensions.h
@@ -38,6 +38,7 @@
#define nautilus_gtk_marshal_STRING__POINTER_STRING nautilus_gtk_marshal_POINTER__POINTER_POINTER
#define nautilus_gtk_marshal_STRING__POINTER_POINTER_POINTER nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER
#define nautilus_gtk_marshal_STRING__POINTER_POINTER_STRING nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER
+#define nautilus_gtk_marshal_INT__POINTER_STRING nautilus_gtk_marshal_INT__POINTER_POINTER
#define NAUTILUS_DEFAULT_POPUP_MENU_DISPLACEMENT 2
@@ -101,6 +102,10 @@ void nautilus_gtk_marshal_POINTER__POINTER
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
+void nautilus_gtk_marshal_INT__POINTER_POINTER (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
diff --git a/libnautilus-private/nautilus-icon-canvas-item.c b/libnautilus-private/nautilus-icon-canvas-item.c
index 268a58459..bc5be35e9 100644
--- a/libnautilus-private/nautilus-icon-canvas-item.c
+++ b/libnautilus-private/nautilus-icon-canvas-item.c
@@ -1018,8 +1018,14 @@ nautilus_icon_canvas_item_event (GnomeCanvasItem *item, GdkEvent *event)
return TRUE;
case GDK_LEAVE_NOTIFY:
- if (icon_item->details->is_prelit) {
+ if (icon_item->details->is_prelit
+ || icon_item->details->is_highlighted_for_drop) {
+ /* When leaving, turn of the prelight state and the
+ * higlighted for drop. The latter gets turned on
+ * by the drag&drop motion callback.
+ */
icon_item->details->is_prelit = FALSE;
+ icon_item->details->is_highlighted_for_drop = FALSE;
gnome_canvas_item_request_update (item);
}
return TRUE;
diff --git a/libnautilus-private/nautilus-icon-container.c b/libnautilus-private/nautilus-icon-container.c
index a656ebd10..1d656703f 100644
--- a/libnautilus-private/nautilus-icon-container.c
+++ b/libnautilus-private/nautilus-icon-container.c
@@ -106,6 +106,7 @@ enum {
SELECTION_CHANGED,
MOVE_COPY_ITEMS,
GET_CONTAINER_URI,
+ CAN_ACCEPT_ITEM,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
@@ -1868,6 +1869,16 @@ nautilus_icon_container_initialize_class (NautilusIconContainerClass *class)
get_container_uri),
nautilus_gtk_marshal_STRING__NONE,
GTK_TYPE_STRING, 0);
+ signals[CAN_ACCEPT_ITEM]
+ = gtk_signal_new ("can_accept_item",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (NautilusIconContainerClass,
+ can_accept_item),
+ nautilus_gtk_marshal_INT__POINTER_STRING,
+ GTK_TYPE_INT, 2,
+ GTK_TYPE_POINTER,
+ GTK_TYPE_STRING);
@@ -2041,6 +2052,19 @@ item_event_callback (GnomeCanvasItem *item,
g_return_val_if_fail (icon != NULL, FALSE);
switch (event->type) {
+ case GDK_ENTER_NOTIFY:
+ if (details->drag_button != 0) {
+ /* Drag motion callback will take care of the
+ * necessary update -- don't let the signal reach
+ * the canvas item and cause a prelight.
+ * We let the GDK_LEAVE_NOTIFY fly through here to
+ * cause the "can_accept_drop" state to get turned off
+ */
+ gtk_signal_emit_stop_by_name (GTK_OBJECT (item), "event");
+ return TRUE;
+ }
+ return FALSE;
+
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
if (handle_icon_button_press (container, icon, &event->button)) {
diff --git a/libnautilus-private/nautilus-icon-container.h b/libnautilus-private/nautilus-icon-container.h
index f910052f2..0d3d49d24 100644
--- a/libnautilus-private/nautilus-icon-container.h
+++ b/libnautilus-private/nautilus-icon-container.h
@@ -68,6 +68,9 @@ struct NautilusIconContainerClass {
double scale_x, double scale_y);
char * (* get_container_uri) (NautilusIconContainer *container);
+ gboolean (* can_accept_item) (NautilusIconContainer *container,
+ const NautilusIconData *target_uri,
+ const char *item_uri);
/* Connect to these signals to supply information about icons.
* They are called as needed after the icons are inserted.
diff --git a/libnautilus-private/nautilus-icon-dnd.c b/libnautilus-private/nautilus-icon-dnd.c
index 05a041dd3..f3cd41f97 100644
--- a/libnautilus-private/nautilus-icon-dnd.c
+++ b/libnautilus-private/nautilus-icon-dnd.c
@@ -45,10 +45,16 @@
#include <libgnomeui/gnome-canvas-rect-ellipse.h>
#include "nautilus-icon-private.h"
-static int nautilus_icon_drag_key_callback (GtkWidget *widget, GdkEventKey *event,
- gpointer data);
-static gboolean drag_drop_callback (GtkWidget *widget, GdkDragContext *context,
- int x, int y, guint32 time, gpointer data);
+static int nautilus_icon_drag_key_callback (GtkWidget *widget, GdkEventKey *event,
+ gpointer data);
+static gboolean drag_drop_callback (GtkWidget *widget,
+ GdkDragContext *context,
+ int x, int y,
+ guint32 time, gpointer data);
+static void nautilus_icon_dnd_update_drop_target (NautilusIconContainer *container,
+ GdkDragContext *context,
+ int x, int y);
+
typedef struct {
char *uri;
@@ -510,9 +516,9 @@ drag_motion_callback (GtkWidget *widget,
guint32 time)
{
nautilus_icon_dnd_update_drop_action (widget);
-
nautilus_icon_container_ensure_drag_data (NAUTILUS_ICON_CONTAINER (widget), context, time);
nautilus_icon_container_position_shadow (NAUTILUS_ICON_CONTAINER (widget), x, y);
+ nautilus_icon_dnd_update_drop_target (NAUTILUS_ICON_CONTAINER (widget), context, x, y);
gdk_drag_status (context, context->suggested_action, time);
@@ -628,16 +634,18 @@ nautilus_icon_container_selection_items_local (const NautilusIconContainer *cont
}
static gboolean
-nautilus_icon_canvas_item_can_accept_item (const NautilusIcon *drop_target_item,
+nautilus_icon_canvas_item_can_accept_item (NautilusIconContainer *container,
+ const NautilusIcon *drop_target_item,
const char *item_uri)
{
- /* FIXME:
- *
- * should have NautilusFile answer whether it can handle icon URI
- *
- * For now:
- */
- return TRUE;
+ gboolean result;
+
+ gtk_signal_emit_by_name (GTK_OBJECT (container),
+ "can_accept_item",
+ drop_target_item->data,
+ item_uri,
+ &result);
+ return result;
}
static gboolean
@@ -645,10 +653,17 @@ nautilus_icon_canvas_item_can_accept_items (NautilusIconContainer *container,
const NautilusIcon *drop_target_item,
const GList *items)
{
- for (; items != NULL; items = items->next) {
- if (!nautilus_icon_canvas_item_can_accept_item (drop_target_item,
- ((DndSelectionItem *)items->data)->uri))
+ int max;
+
+ /* Iterate through selection checking if item will get accepted by the
+ * drop target. If more than 100 items selected, return an over-optimisic
+ * result
+ */
+ for (max = 100; items != NULL && max >=0 ; items = items->next, max--) {
+ if (!nautilus_icon_canvas_item_can_accept_item (container, drop_target_item,
+ ((DndSelectionItem *)items->data)->uri)) {
return FALSE;
+ }
}
return TRUE;
@@ -808,6 +823,53 @@ nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container,
}
static void
+nautilus_icon_dnd_update_drop_target (NautilusIconContainer *container,
+ GdkDragContext *context,
+ int x, int y)
+{
+ NautilusIcon *drop_target_icon;
+ double world_x, world_y;
+
+ g_assert (NAUTILUS_IS_ICON_CONTAINER (container));
+ if (container->details->dnd_info->selection_list == NULL) {
+ return;
+ }
+
+ gnome_canvas_window_to_world (GNOME_CANVAS (container),
+ x, y, &world_x, &world_y);
+
+
+ /* Find the item we hit with our drop, if any. */
+ drop_target_icon = nautilus_icon_container_item_at (container, world_x, world_y);
+
+
+ /* Find if target icon accepts our drop. */
+ if (drop_target_icon != NULL
+ && !nautilus_icon_canvas_item_can_accept_items
+ (container, drop_target_icon, container->details->dnd_info->selection_list)) {
+ drop_target_icon = NULL;
+ }
+
+ /* Check if current drop target changed, update icon drop higlight if needed. */
+ if (drop_target_icon != container->details->dnd_info->current_drop_target_icon) {
+ /* Turn on new target, if any. */
+ if (drop_target_icon != NULL) {
+ gnome_canvas_item_set (GNOME_CANVAS_ITEM (drop_target_icon->item),
+ "highlighted_for_drop", TRUE,
+ NULL);
+ }
+ /* Turn off old target, if any. */
+ if (container->details->dnd_info->current_drop_target_icon != NULL) {
+ gnome_canvas_item_set (GNOME_CANVAS_ITEM (((NautilusIcon *)container->details->
+ dnd_info->current_drop_target_icon)->item),
+ "highlighted_for_drop", FALSE, NULL);
+ }
+ /* Remember the new drop target for the next round. */
+ container->details->dnd_info->current_drop_target_icon = drop_target_icon;
+ }
+}
+
+static void
nautilus_icon_container_free_drag_data (NautilusIconContainer *container)
{
NautilusIconDndInfo *dnd_info;
@@ -1013,6 +1075,8 @@ nautilus_icon_dnd_begin_drag (NautilusIconContainer *container,
GTK_SIGNAL_FUNC (nautilus_icon_drag_key_callback), info);
+ container->details->dnd_info->current_drop_target_icon = NULL;
+
/* create a pixmap and mask to drag with */
pixbuf = nautilus_icon_canvas_item_get_image (container->details->drag_icon->item, NULL);
@@ -1095,6 +1159,7 @@ drag_drop_callback (GtkWidget *widget,
}
NAUTILUS_ICON_CONTAINER (widget)->details->dnd_info->saved_drag_source_info = NULL;
+ NAUTILUS_ICON_CONTAINER (widget)->details->dnd_info->current_drop_target_icon = NULL;
return FALSE;
}
@@ -1120,13 +1185,13 @@ nautilus_icon_dnd_modifier_based_action ()
GdkModifierType modifiers;
gdk_window_get_pointer (NULL, NULL, NULL, &modifiers);
- if ((modifiers & GDK_CONTROL_MASK) != 0) {
+ if ((modifiers & GDK_MOD1_MASK) != 0) {
return GDK_ACTION_COPY;
#if 0
/* FIXME:
* don't know how to do links yet
*/
- } else if ((modifiers & GDK_MOD1_MASK) != 0) {
+ } else if ((modifiers & GDK_CONTROL_MASK) != 0) {
return GDK_ACTION_LINK;
#endif
}
diff --git a/libnautilus-private/nautilus-icon-dnd.h b/libnautilus-private/nautilus-icon-dnd.h
index f75b9aed8..821dd3d9b 100644
--- a/libnautilus-private/nautilus-icon-dnd.h
+++ b/libnautilus-private/nautilus-icon-dnd.h
@@ -79,6 +79,9 @@ struct NautilusIconDndInfo {
* interface gets added to gtkdnd to do this in a clean way
*/
gpointer saved_drag_source_info;
+
+ /* last highlighted drop target*/
+ gpointer current_drop_target_icon;
};
void nautilus_icon_dnd_init (NautilusIconContainer *container,
diff --git a/libnautilus/nautilus-file.c b/libnautilus/nautilus-file.c
index 0ed7bf771..d98a2e06e 100644
--- a/libnautilus/nautilus-file.c
+++ b/libnautilus/nautilus-file.c
@@ -360,6 +360,34 @@ nautilus_file_rename (NautilusFile *file, const char *new_name)
return result;
}
+gboolean
+nautilus_file_matches_uri (NautilusFile *file, const char *uri_string)
+{
+ GnomeVFSURI *match_uri;
+ GnomeVFSURI *file_uri;
+ gboolean result;
+
+ g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
+ g_return_val_if_fail (uri_string != NULL, FALSE);
+
+ match_uri = gnome_vfs_uri_new (uri_string);
+ if (match_uri == NULL)
+ return FALSE;
+
+ result = FALSE;
+ file_uri = gnome_vfs_uri_append_path (file->details->directory->details->uri,
+ file->details->info->name);
+
+ if (match_uri != NULL) {
+ result = gnome_vfs_uri_equal (file_uri, match_uri);
+ }
+
+ gnome_vfs_uri_unref (file_uri);
+ gnome_vfs_uri_unref (match_uri);
+
+ return result;
+}
+
static int
nautilus_file_compare_by_size_with_directories (NautilusFile *file_1, NautilusFile *file_2)
{
diff --git a/libnautilus/nautilus-file.h b/libnautilus/nautilus-file.h
index 6cc0c79be..27bb41b76 100644
--- a/libnautilus/nautilus-file.h
+++ b/libnautilus/nautilus-file.h
@@ -122,6 +122,10 @@ void nautilus_file_set_metadata (NautilusFile *
char * nautilus_file_get_string_attribute (NautilusFile *file,
const char *attribute_name);
+/* Matching with another URI*/
+gboolean nautilus_file_matches_uri (NautilusFile *file,
+ const char *uri);
+
/* Comparing two file objects for sorting */
int nautilus_file_compare_for_sort (NautilusFile *file_1,
NautilusFile *file_2,
diff --git a/libnautilus/nautilus-gtk-extensions.c b/libnautilus/nautilus-gtk-extensions.c
index 99d8d1523..b89404644 100644
--- a/libnautilus/nautilus-gtk-extensions.c
+++ b/libnautilus/nautilus-gtk-extensions.c
@@ -320,6 +320,20 @@ nautilus_gtk_marshal_POINTER__POINTER (GtkObject *object,
}
void
+nautilus_gtk_marshal_INT__POINTER_POINTER (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ * GTK_RETLOC_INT (args[2]) =
+ (* (int (*)(GtkObject *, gpointer, gpointer, gpointer)) func)
+ (object,
+ GTK_VALUE_POINTER (args[0]),
+ GTK_VALUE_POINTER (args[1]),
+ func_data);
+}
+
+void
nautilus_gtk_marshal_POINTER__POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
diff --git a/libnautilus/nautilus-gtk-extensions.h b/libnautilus/nautilus-gtk-extensions.h
index 88f0684f1..61f1f5187 100644
--- a/libnautilus/nautilus-gtk-extensions.h
+++ b/libnautilus/nautilus-gtk-extensions.h
@@ -38,6 +38,7 @@
#define nautilus_gtk_marshal_STRING__POINTER_STRING nautilus_gtk_marshal_POINTER__POINTER_POINTER
#define nautilus_gtk_marshal_STRING__POINTER_POINTER_POINTER nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER
#define nautilus_gtk_marshal_STRING__POINTER_POINTER_STRING nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER
+#define nautilus_gtk_marshal_INT__POINTER_STRING nautilus_gtk_marshal_INT__POINTER_POINTER
#define NAUTILUS_DEFAULT_POPUP_MENU_DISPLACEMENT 2
@@ -101,6 +102,10 @@ void nautilus_gtk_marshal_POINTER__POINTER
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
+void nautilus_gtk_marshal_INT__POINTER_POINTER (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
diff --git a/libnautilus/nautilus-icon-canvas-item.c b/libnautilus/nautilus-icon-canvas-item.c
index 268a58459..bc5be35e9 100644
--- a/libnautilus/nautilus-icon-canvas-item.c
+++ b/libnautilus/nautilus-icon-canvas-item.c
@@ -1018,8 +1018,14 @@ nautilus_icon_canvas_item_event (GnomeCanvasItem *item, GdkEvent *event)
return TRUE;
case GDK_LEAVE_NOTIFY:
- if (icon_item->details->is_prelit) {
+ if (icon_item->details->is_prelit
+ || icon_item->details->is_highlighted_for_drop) {
+ /* When leaving, turn of the prelight state and the
+ * higlighted for drop. The latter gets turned on
+ * by the drag&drop motion callback.
+ */
icon_item->details->is_prelit = FALSE;
+ icon_item->details->is_highlighted_for_drop = FALSE;
gnome_canvas_item_request_update (item);
}
return TRUE;
diff --git a/libnautilus/nautilus-icon-container.c b/libnautilus/nautilus-icon-container.c
index a656ebd10..1d656703f 100644
--- a/libnautilus/nautilus-icon-container.c
+++ b/libnautilus/nautilus-icon-container.c
@@ -106,6 +106,7 @@ enum {
SELECTION_CHANGED,
MOVE_COPY_ITEMS,
GET_CONTAINER_URI,
+ CAN_ACCEPT_ITEM,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
@@ -1868,6 +1869,16 @@ nautilus_icon_container_initialize_class (NautilusIconContainerClass *class)
get_container_uri),
nautilus_gtk_marshal_STRING__NONE,
GTK_TYPE_STRING, 0);
+ signals[CAN_ACCEPT_ITEM]
+ = gtk_signal_new ("can_accept_item",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (NautilusIconContainerClass,
+ can_accept_item),
+ nautilus_gtk_marshal_INT__POINTER_STRING,
+ GTK_TYPE_INT, 2,
+ GTK_TYPE_POINTER,
+ GTK_TYPE_STRING);
@@ -2041,6 +2052,19 @@ item_event_callback (GnomeCanvasItem *item,
g_return_val_if_fail (icon != NULL, FALSE);
switch (event->type) {
+ case GDK_ENTER_NOTIFY:
+ if (details->drag_button != 0) {
+ /* Drag motion callback will take care of the
+ * necessary update -- don't let the signal reach
+ * the canvas item and cause a prelight.
+ * We let the GDK_LEAVE_NOTIFY fly through here to
+ * cause the "can_accept_drop" state to get turned off
+ */
+ gtk_signal_emit_stop_by_name (GTK_OBJECT (item), "event");
+ return TRUE;
+ }
+ return FALSE;
+
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
if (handle_icon_button_press (container, icon, &event->button)) {
diff --git a/libnautilus/nautilus-icon-container.h b/libnautilus/nautilus-icon-container.h
index f910052f2..0d3d49d24 100644
--- a/libnautilus/nautilus-icon-container.h
+++ b/libnautilus/nautilus-icon-container.h
@@ -68,6 +68,9 @@ struct NautilusIconContainerClass {
double scale_x, double scale_y);
char * (* get_container_uri) (NautilusIconContainer *container);
+ gboolean (* can_accept_item) (NautilusIconContainer *container,
+ const NautilusIconData *target_uri,
+ const char *item_uri);
/* Connect to these signals to supply information about icons.
* They are called as needed after the icons are inserted.
diff --git a/libnautilus/nautilus-icon-dnd.c b/libnautilus/nautilus-icon-dnd.c
index 05a041dd3..f3cd41f97 100644
--- a/libnautilus/nautilus-icon-dnd.c
+++ b/libnautilus/nautilus-icon-dnd.c
@@ -45,10 +45,16 @@
#include <libgnomeui/gnome-canvas-rect-ellipse.h>
#include "nautilus-icon-private.h"
-static int nautilus_icon_drag_key_callback (GtkWidget *widget, GdkEventKey *event,
- gpointer data);
-static gboolean drag_drop_callback (GtkWidget *widget, GdkDragContext *context,
- int x, int y, guint32 time, gpointer data);
+static int nautilus_icon_drag_key_callback (GtkWidget *widget, GdkEventKey *event,
+ gpointer data);
+static gboolean drag_drop_callback (GtkWidget *widget,
+ GdkDragContext *context,
+ int x, int y,
+ guint32 time, gpointer data);
+static void nautilus_icon_dnd_update_drop_target (NautilusIconContainer *container,
+ GdkDragContext *context,
+ int x, int y);
+
typedef struct {
char *uri;
@@ -510,9 +516,9 @@ drag_motion_callback (GtkWidget *widget,
guint32 time)
{
nautilus_icon_dnd_update_drop_action (widget);
-
nautilus_icon_container_ensure_drag_data (NAUTILUS_ICON_CONTAINER (widget), context, time);
nautilus_icon_container_position_shadow (NAUTILUS_ICON_CONTAINER (widget), x, y);
+ nautilus_icon_dnd_update_drop_target (NAUTILUS_ICON_CONTAINER (widget), context, x, y);
gdk_drag_status (context, context->suggested_action, time);
@@ -628,16 +634,18 @@ nautilus_icon_container_selection_items_local (const NautilusIconContainer *cont
}
static gboolean
-nautilus_icon_canvas_item_can_accept_item (const NautilusIcon *drop_target_item,
+nautilus_icon_canvas_item_can_accept_item (NautilusIconContainer *container,
+ const NautilusIcon *drop_target_item,
const char *item_uri)
{
- /* FIXME:
- *
- * should have NautilusFile answer whether it can handle icon URI
- *
- * For now:
- */
- return TRUE;
+ gboolean result;
+
+ gtk_signal_emit_by_name (GTK_OBJECT (container),
+ "can_accept_item",
+ drop_target_item->data,
+ item_uri,
+ &result);
+ return result;
}
static gboolean
@@ -645,10 +653,17 @@ nautilus_icon_canvas_item_can_accept_items (NautilusIconContainer *container,
const NautilusIcon *drop_target_item,
const GList *items)
{
- for (; items != NULL; items = items->next) {
- if (!nautilus_icon_canvas_item_can_accept_item (drop_target_item,
- ((DndSelectionItem *)items->data)->uri))
+ int max;
+
+ /* Iterate through selection checking if item will get accepted by the
+ * drop target. If more than 100 items selected, return an over-optimisic
+ * result
+ */
+ for (max = 100; items != NULL && max >=0 ; items = items->next, max--) {
+ if (!nautilus_icon_canvas_item_can_accept_item (container, drop_target_item,
+ ((DndSelectionItem *)items->data)->uri)) {
return FALSE;
+ }
}
return TRUE;
@@ -808,6 +823,53 @@ nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container,
}
static void
+nautilus_icon_dnd_update_drop_target (NautilusIconContainer *container,
+ GdkDragContext *context,
+ int x, int y)
+{
+ NautilusIcon *drop_target_icon;
+ double world_x, world_y;
+
+ g_assert (NAUTILUS_IS_ICON_CONTAINER (container));
+ if (container->details->dnd_info->selection_list == NULL) {
+ return;
+ }
+
+ gnome_canvas_window_to_world (GNOME_CANVAS (container),
+ x, y, &world_x, &world_y);
+
+
+ /* Find the item we hit with our drop, if any. */
+ drop_target_icon = nautilus_icon_container_item_at (container, world_x, world_y);
+
+
+ /* Find if target icon accepts our drop. */
+ if (drop_target_icon != NULL
+ && !nautilus_icon_canvas_item_can_accept_items
+ (container, drop_target_icon, container->details->dnd_info->selection_list)) {
+ drop_target_icon = NULL;
+ }
+
+ /* Check if current drop target changed, update icon drop higlight if needed. */
+ if (drop_target_icon != container->details->dnd_info->current_drop_target_icon) {
+ /* Turn on new target, if any. */
+ if (drop_target_icon != NULL) {
+ gnome_canvas_item_set (GNOME_CANVAS_ITEM (drop_target_icon->item),
+ "highlighted_for_drop", TRUE,
+ NULL);
+ }
+ /* Turn off old target, if any. */
+ if (container->details->dnd_info->current_drop_target_icon != NULL) {
+ gnome_canvas_item_set (GNOME_CANVAS_ITEM (((NautilusIcon *)container->details->
+ dnd_info->current_drop_target_icon)->item),
+ "highlighted_for_drop", FALSE, NULL);
+ }
+ /* Remember the new drop target for the next round. */
+ container->details->dnd_info->current_drop_target_icon = drop_target_icon;
+ }
+}
+
+static void
nautilus_icon_container_free_drag_data (NautilusIconContainer *container)
{
NautilusIconDndInfo *dnd_info;
@@ -1013,6 +1075,8 @@ nautilus_icon_dnd_begin_drag (NautilusIconContainer *container,
GTK_SIGNAL_FUNC (nautilus_icon_drag_key_callback), info);
+ container->details->dnd_info->current_drop_target_icon = NULL;
+
/* create a pixmap and mask to drag with */
pixbuf = nautilus_icon_canvas_item_get_image (container->details->drag_icon->item, NULL);
@@ -1095,6 +1159,7 @@ drag_drop_callback (GtkWidget *widget,
}
NAUTILUS_ICON_CONTAINER (widget)->details->dnd_info->saved_drag_source_info = NULL;
+ NAUTILUS_ICON_CONTAINER (widget)->details->dnd_info->current_drop_target_icon = NULL;
return FALSE;
}
@@ -1120,13 +1185,13 @@ nautilus_icon_dnd_modifier_based_action ()
GdkModifierType modifiers;
gdk_window_get_pointer (NULL, NULL, NULL, &modifiers);
- if ((modifiers & GDK_CONTROL_MASK) != 0) {
+ if ((modifiers & GDK_MOD1_MASK) != 0) {
return GDK_ACTION_COPY;
#if 0
/* FIXME:
* don't know how to do links yet
*/
- } else if ((modifiers & GDK_MOD1_MASK) != 0) {
+ } else if ((modifiers & GDK_CONTROL_MASK) != 0) {
return GDK_ACTION_LINK;
#endif
}
diff --git a/libnautilus/nautilus-icon-dnd.h b/libnautilus/nautilus-icon-dnd.h
index f75b9aed8..821dd3d9b 100644
--- a/libnautilus/nautilus-icon-dnd.h
+++ b/libnautilus/nautilus-icon-dnd.h
@@ -79,6 +79,9 @@ struct NautilusIconDndInfo {
* interface gets added to gtkdnd to do this in a clean way
*/
gpointer saved_drag_source_info;
+
+ /* last highlighted drop target*/
+ gpointer current_drop_target_icon;
};
void nautilus_icon_dnd_init (NautilusIconContainer *container,
diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c
index 5ec74760e..4eb053ec6 100644
--- a/src/file-manager/fm-directory-view.c
+++ b/src/file-manager/fm-directory-view.c
@@ -2115,6 +2115,30 @@ fm_directory_view_move_copy_items (NautilusIconContainer *container,
GTK_WIDGET (view));
}
+gboolean
+fm_directory_view_can_accept_item (NautilusIconContainer *container,
+ NautilusFile *target_item,
+ const char *item_uri,
+ FMDirectoryView *view)
+{
+ g_assert (NAUTILUS_IS_ICON_CONTAINER (container));
+ g_assert (NAUTILUS_IS_FILE (target_item));
+ g_assert (FM_IS_DIRECTORY_VIEW (view));
+
+ /* FIXME:
+ * elaborate here some more
+ * should consider permissions, handle symlinks to directories, etc.
+ *
+ * for now just allways return true if dropping into a directory
+ */
+ if (nautilus_file_get_file_type (target_item) != GNOME_VFS_FILE_TYPE_DIRECTORY) {
+ return FALSE;
+ }
+
+ /* target is a directory, find out if it matches the item */
+ return !nautilus_file_matches_uri (target_item, item_uri);
+}
+
static void
add_nautilus_file_to_uri_map (FMDirectoryView *view,
diff --git a/src/file-manager/fm-directory-view.h b/src/file-manager/fm-directory-view.h
index b15140418..84e34a488 100644
--- a/src/file-manager/fm-directory-view.h
+++ b/src/file-manager/fm-directory-view.h
@@ -181,6 +181,10 @@ void fm_directory_view_load_uri (FMDi
/* Functions callable from the user interface and elsewhere. */
char * fm_directory_view_get_container_uri (NautilusIconContainer *container,
FMDirectoryView *view);
+gboolean fm_directory_view_can_accept_item (NautilusIconContainer *container,
+ NautilusFile *target_item,
+ const char *item_uri,
+ FMDirectoryView *view);
GList * fm_directory_view_get_selection (FMDirectoryView *view);
void fm_directory_view_stop (FMDirectoryView *view);
gboolean fm_directory_view_can_zoom_in (FMDirectoryView *view);
diff --git a/src/file-manager/fm-icon-view.c b/src/file-manager/fm-icon-view.c
index 07e69ec41..7dd2c27e2 100644
--- a/src/file-manager/fm-icon-view.c
+++ b/src/file-manager/fm-icon-view.c
@@ -282,6 +282,10 @@ create_icon_container (FMIconView *icon_view)
"get_container_uri",
GTK_SIGNAL_FUNC (fm_directory_view_get_container_uri),
directory_view);
+ gtk_signal_connect (GTK_OBJECT (icon_container),
+ "can_accept_item",
+ GTK_SIGNAL_FUNC (fm_directory_view_can_accept_item),
+ directory_view);
gtk_container_add (GTK_CONTAINER (icon_view), GTK_WIDGET (icon_container));