summaryrefslogtreecommitdiff
path: root/libnautilus-private/nautilus-dnd.c
diff options
context:
space:
mode:
authorChristian Neumair <cneumair@gnome.org>2008-07-13 12:07:53 +0000
committerChristian Neumair <cneumair@src.gnome.org>2008-07-13 12:07:53 +0000
commitd4f08bc033176b37124695263928999a63748beb (patch)
treee4fe3ae554af62079b2fd50b7178d664d5b88ec0 /libnautilus-private/nautilus-dnd.c
parent88d90c73c4c0a74edd2f13ca00ab31e7755568cf (diff)
downloadnautilus-d4f08bc033176b37124695263928999a63748beb.tar.gz
Add simple slot drop proxy API to libnautilus-private, centered around
2008-07-13 Christian Neumair <cneumair@gnome.org> * libnautilus-private/nautilus-dnd.c (nautilus_drag_uri_array_from_selection_list), (nautilus_drag_uri_list_from_selection_list), (nautilus_drag_uri_array_from_list), (nautilus_drag_uri_list_from_array), (slot_proxy_drag_motion), (drag_info_clear), (slot_proxy_drag_leave), (slot_proxy_drag_drop), (slot_proxy_handle_drop), (slot_proxy_drag_data_received), (nautilus_drag_slot_proxy_init): * libnautilus-private/nautilus-dnd.h: Add simple slot drop proxy API to libnautilus-private, centered around nautilus_drag_slot_proxy_init(). The notebook tab label drop targets will later be ported to this API. Add API for converting URI lists to URI arrays, and for constructing URI lists and arrays from selection lists. * src/nautilus-notebook.c (notebook_tab_drag_data_received): Use nautilus_drag_uri_array_from_selection_list(). * src/nautilus-pathbar.c (slider_timeout), (nautilus_path_bar_slider_drag_motion), (nautilus_path_bar_slider_drag_leave), (nautilus_path_bar_init), (nautilus_path_bar_finalize), (button_data_free), (button_drag_data_get_cb), (setup_button_drag_source), (make_directory_button): * src/nautilus-pathbar.h: Add path bar drop targets, use nautilus_drag_slot_proxy_init() for setup. Also offer GNOME icon lists as drag target. Reveal hidden paths when hovering over the up/down sliders for some time. Fixes #309842. svn path=/trunk/; revision=14356
Diffstat (limited to 'libnautilus-private/nautilus-dnd.c')
-rw-r--r--libnautilus-private/nautilus-dnd.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/libnautilus-private/nautilus-dnd.c b/libnautilus-private/nautilus-dnd.c
index bda64dc9c..744f9986a 100644
--- a/libnautilus-private/nautilus-dnd.c
+++ b/libnautilus-private/nautilus-dnd.c
@@ -31,6 +31,9 @@
#include "nautilus-program-choosing.h"
#include "nautilus-link.h"
+#include "nautilus-window-slot-info.h"
+#include "nautilus-window-info.h"
+#include "nautilus-view.h"
#include <eel/eel-glib-extensions.h>
#include <eel/eel-gtk-extensions.h>
#include <eel/eel-string.h>
@@ -118,6 +121,76 @@ nautilus_drag_destroy_selection_list (GList *list)
g_list_free (list);
}
+char **
+nautilus_drag_uri_array_from_selection_list (const GList *selection_list)
+{
+ GList *uri_list;
+ char **uris;
+
+ uri_list = nautilus_drag_uri_list_from_selection_list (selection_list);
+ uris = nautilus_drag_uri_array_from_list (uri_list);
+ eel_g_list_free_deep (uri_list);
+
+ return uris;
+}
+
+GList *
+nautilus_drag_uri_list_from_selection_list (const GList *selection_list)
+{
+ NautilusDragSelectionItem *selection_item;
+ GList *uri_list;
+ const GList *l;
+
+ uri_list = NULL;
+ for (l = selection_list; l != NULL; l = l->next) {
+ selection_item = (NautilusDragSelectionItem *) l->data;
+ if (selection_item->uri != NULL) {
+ uri_list = g_list_prepend (uri_list, g_strdup (selection_item->uri));
+ }
+ }
+
+ return g_list_reverse (uri_list);
+}
+
+char **
+nautilus_drag_uri_array_from_list (const GList *uri_list)
+{
+ const GList *l;
+ char **uris;
+ int i;
+
+ if (uri_list == NULL) {
+ return NULL;
+ }
+
+ uris = g_new0 (char *, g_list_length ((GList *) uri_list));
+ for (i = 0, l = uri_list; l != NULL; l = l->next) {
+ uris[i++] = g_strdup ((char *) l->data);
+ }
+ uris[i] = NULL;
+
+ return uris;
+}
+
+GList *
+nautilus_drag_uri_list_from_array (const char **uris)
+{
+ GList *uri_list;
+ int i;
+
+ if (uris == NULL) {
+ return NULL;
+ }
+
+ uri_list = NULL;
+
+ for (i = 0; uris[i] != NULL; i++) {
+ uri_list = g_list_prepend (uri_list, g_strdup (uris[i]));
+ }
+
+ return g_list_reverse (uri_list);
+}
+
GList *
nautilus_drag_build_selection_list (GtkSelectionData *data)
{
@@ -921,3 +994,284 @@ nautilus_drag_selection_includes_special_link (GList *selection_list)
return FALSE;
}
+
+static void
+slot_proxy_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ int x,
+ int y,
+ unsigned int time,
+ gpointer user_data)
+{
+ GdkAtom target;
+ int action;
+ char *target_uri;
+ NautilusDragSlotProxyInfo *drag_info;
+
+ drag_info = user_data;
+
+ action = 0;
+
+ if (gtk_drag_get_source_widget (context) == widget) {
+ goto out;
+ }
+
+ if (!drag_info->have_data) {
+ target = gtk_drag_dest_find_target (widget, context, NULL);
+ gtk_drag_get_data (widget, context, target, time);
+ }
+
+ target_uri = NULL;
+ if (drag_info->target_location != NULL) {
+ target_uri = g_file_get_uri (drag_info->target_location);
+ }
+
+ if (drag_info->have_data &&
+ drag_info->have_valid_data) {
+ 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,
+ &action);
+ } else if (drag_info->info == NAUTILUS_ICON_DND_URI_LIST) {
+ action = nautilus_drag_default_drop_action_for_uri_list (context, target_uri);
+ } else if (drag_info->info == NAUTILUS_ICON_DND_NETSCAPE_URL) {
+ action = nautilus_drag_default_drop_action_for_netscape_url (context);
+ }
+ }
+
+ g_free (target_uri);
+
+out:
+ if (action != 0) {
+ gtk_drag_highlight (widget);
+ } else {
+ gtk_drag_unhighlight (widget);
+ }
+
+ gdk_drag_status (context, action, time);
+}
+
+static void
+drag_info_clear (NautilusDragSlotProxyInfo *drag_info)
+{
+ if (!drag_info->have_data) {
+ goto out;
+ }
+
+ if (drag_info->info == NAUTILUS_ICON_DND_GNOME_ICON_LIST) {
+ nautilus_drag_destroy_selection_list (drag_info->data.selection_list);
+ } else if (drag_info->info == NAUTILUS_ICON_DND_URI_LIST) {
+ g_list_free (drag_info->data.uri_list);
+ } else if (drag_info->info == NAUTILUS_ICON_DND_NETSCAPE_URL) {
+ g_free (drag_info->data.netscape_url);
+ }
+
+out:
+ drag_info->have_data = FALSE;
+ drag_info->have_valid_data = FALSE;
+
+ drag_info->drop_occured = FALSE;
+}
+
+static void
+slot_proxy_drag_leave (GtkWidget *widget,
+ GdkDragContext *context,
+ unsigned int time,
+ gpointer user_data)
+{
+ NautilusDragSlotProxyInfo *drag_info;
+
+ drag_info = user_data;
+
+ gtk_drag_unhighlight (widget);
+ drag_info_clear (drag_info);
+}
+
+static gboolean
+slot_proxy_drag_drop (GtkWidget *widget,
+ GdkDragContext *context,
+ int x,
+ int y,
+ unsigned int time,
+ gpointer user_data)
+{
+ GdkAtom target;
+ NautilusDragSlotProxyInfo *drag_info;
+
+ drag_info = user_data;
+ g_assert (!drag_info->have_data);
+
+ drag_info->drop_occured = TRUE;
+
+ target = gtk_drag_dest_find_target (widget, context, NULL);
+ gtk_drag_get_data (widget, context, target, time);
+
+ return TRUE;
+}
+
+
+static void
+slot_proxy_handle_drop (GtkWidget *widget,
+ GdkDragContext *context,
+ unsigned int time,
+ NautilusDragSlotProxyInfo *drag_info)
+{
+ GtkWidget *window;
+ NautilusWindowSlotInfo *target_slot;
+ NautilusView *target_view;
+ char *target_uri;
+ GList *uri_list;
+
+ if (!drag_info->have_data ||
+ !drag_info->have_valid_data) {
+ gtk_drag_finish (context, FALSE, FALSE, time);
+ drag_info_clear (drag_info);
+ return;
+ }
+
+ window = gtk_widget_get_toplevel (widget);
+ g_assert (NAUTILUS_IS_WINDOW_INFO (window));
+
+ if (drag_info->target_slot != NULL) {
+ target_slot = drag_info->target_slot;
+ } else {
+ target_slot = nautilus_window_info_get_active_slot (NAUTILUS_WINDOW_INFO (window));
+ }
+
+ target_uri = NULL;
+ if (drag_info->target_location != NULL) {
+ target_uri = g_file_get_uri (drag_info->target_location);
+ } else if (target_slot != NULL) {
+ target_uri = nautilus_window_slot_info_get_current_location (target_slot);
+ }
+
+ target_view = NULL;
+ if (target_slot != NULL) {
+ target_view = nautilus_window_slot_info_get_current_view (target_slot);
+ }
+
+ if (target_slot != NULL && target_view != NULL) {
+ if (drag_info->info == NAUTILUS_ICON_DND_GNOME_ICON_LIST) {
+ uri_list = nautilus_drag_uri_list_from_selection_list (drag_info->data.selection_list);
+ g_assert (uri_list != NULL);
+
+ nautilus_view_drop_proxy_received_uris (target_view,
+ uri_list,
+ target_uri,
+ context->action);
+ eel_g_list_free_deep (uri_list);
+ } else if (drag_info->info == NAUTILUS_ICON_DND_URI_LIST) {
+ nautilus_view_drop_proxy_received_uris (target_view,
+ drag_info->data.uri_list,
+ target_uri,
+ context->action);
+ } if (drag_info->info == NAUTILUS_ICON_DND_NETSCAPE_URL) {
+ nautilus_view_drop_proxy_received_netscape_url (target_view,
+ drag_info->data.netscape_url,
+ target_uri,
+ context->action);
+ }
+
+
+ gtk_drag_finish (context, TRUE, FALSE, time);
+ } else {
+ gtk_drag_finish (context, FALSE, FALSE, time);
+ }
+
+ if (target_view != NULL) {
+ g_object_unref (target_view);
+ }
+
+ g_free (target_uri);
+
+ drag_info_clear (drag_info);
+}
+
+static void
+slot_proxy_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ int x,
+ int y,
+ GtkSelectionData *data,
+ unsigned int info,
+ unsigned int time,
+ gpointer user_data)
+{
+ NautilusDragSlotProxyInfo *drag_info;
+ char **uris;
+
+ drag_info = user_data;
+
+ g_assert (!drag_info->have_data);
+
+ drag_info->have_data = TRUE;
+ drag_info->info = info;
+
+ if (data->length < 0) {
+ drag_info->have_valid_data = FALSE;
+ return;
+ }
+
+ if (info == NAUTILUS_ICON_DND_GNOME_ICON_LIST) {
+ drag_info->data.selection_list = nautilus_drag_build_selection_list (data);
+
+ drag_info->have_valid_data = drag_info->data.selection_list != NULL;
+ } else if (info == NAUTILUS_ICON_DND_URI_LIST) {
+ uris = gtk_selection_data_get_uris (data);
+ drag_info->data.uri_list = nautilus_drag_uri_list_from_array ((const char **) uris);
+ g_strfreev (uris);
+
+ drag_info->have_valid_data = drag_info->data.uri_list != NULL;
+ } else if (info == NAUTILUS_ICON_DND_NETSCAPE_URL) {
+ drag_info->data.netscape_url = g_strdup ((char *) data->data);
+
+ drag_info->have_valid_data = drag_info->data.netscape_url != NULL;
+ }
+
+ if (drag_info->drop_occured) {
+ slot_proxy_handle_drop (widget, context, time, drag_info);
+ }
+}
+
+void
+nautilus_drag_slot_proxy_init (GtkWidget *widget,
+ NautilusDragSlotProxyInfo *drag_info)
+{
+ const GtkTargetEntry targets[] = {
+ { NAUTILUS_ICON_DND_GNOME_ICON_LIST_TYPE, 0, NAUTILUS_ICON_DND_GNOME_ICON_LIST },
+ { NAUTILUS_ICON_DND_NETSCAPE_URL_TYPE, 0, NAUTILUS_ICON_DND_NETSCAPE_URL }
+ };
+ GtkTargetList *target_list;
+
+ g_assert (GTK_IS_WIDGET (widget));
+ g_assert (drag_info != NULL);
+
+ gtk_drag_dest_set (widget, 0,
+ NULL, 0,
+ GDK_ACTION_MOVE |
+ GDK_ACTION_COPY |
+ GDK_ACTION_LINK |
+ GDK_ACTION_ASK);
+
+ gtk_drag_source_add_uri_targets (widget);
+
+ target_list = gtk_target_list_new (targets, G_N_ELEMENTS (targets));
+ gtk_target_list_add_uri_targets (target_list, NAUTILUS_ICON_DND_URI_LIST);
+ gtk_drag_dest_set_target_list (widget, target_list);
+ gtk_target_list_unref (target_list);
+
+ g_signal_connect (widget, "drag-motion",
+ G_CALLBACK (slot_proxy_drag_motion),
+ drag_info);
+ g_signal_connect (widget, "drag-drop",
+ G_CALLBACK (slot_proxy_drag_drop),
+ drag_info);
+ g_signal_connect (widget, "drag-data-received",
+ G_CALLBACK (slot_proxy_drag_data_received),
+ drag_info);
+ g_signal_connect (widget, "drag-leave",
+ G_CALLBACK (slot_proxy_drag_leave),
+ drag_info);
+}
+
+