summaryrefslogtreecommitdiff
path: root/libnautilus-private/nautilus-icon-dnd.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnautilus-private/nautilus-icon-dnd.c')
-rw-r--r--libnautilus-private/nautilus-icon-dnd.c101
1 files changed, 83 insertions, 18 deletions
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
}