From de28b13567398509867e296a681a455e7d048621 Mon Sep 17 00:00:00 2001 From: Eric Koegel Date: Sat, 3 Dec 2011 11:45:26 +0300 Subject: [PATCH] Adds support for the right click drag and drop when moving files to and from the desktop. Fixes bug 4004 --- src/xfdesktop-file-icon-manager.c | 8 ++- src/xfdesktop-icon-view-manager.c | 132 ++++++++++++++++++++++++++++++++++++- src/xfdesktop-icon-view.c | 18 ++++-- 3 files changed, 149 insertions(+), 9 deletions(-) diff --git a/src/xfdesktop-file-icon-manager.c b/src/xfdesktop-file-icon-manager.c index d3ca2eb..4817c10 100644 --- a/src/xfdesktop-file-icon-manager.c +++ b/src/xfdesktop-file-icon-manager.c @@ -2866,7 +2866,7 @@ xfdesktop_file_icon_manager_drag_data_received(XfdesktopIconViewManager *manager tinfo = xfdesktop_file_icon_peek_file_info(file_icon); } - copy_only = (context->action != GDK_ACTION_MOVE); + copy_only = (context->action == GDK_ACTION_COPY); if(tfile && g_file_has_uri_scheme(tfile, "trash") && copy_only) { gtk_drag_finish(context, FALSE, FALSE, time_); @@ -2912,7 +2912,7 @@ xfdesktop_file_icon_manager_drag_data_received(XfdesktopIconViewManager *manager if(dest_basename && *dest_basename != '\0') { /* If we copy a file, we need to use the new absolute filename - * as the destination. If we move, we need to use the destination + * as the destination. If we move or link, we need to use the destination * directory. */ if(copy_only) { GFile *dest_file = g_file_get_child(base_dest_file, dest_basename); @@ -2936,7 +2936,11 @@ xfdesktop_file_icon_manager_drag_data_received(XfdesktopIconViewManager *manager fmanager->priv->gscreen); } + if(copy_only) { xfdesktop_file_utils_file_list_free(dest_file_list); + } else { + g_list_free(dest_file_list); + } } } } diff --git a/src/xfdesktop-icon-view-manager.c b/src/xfdesktop-icon-view-manager.c index efab2ec..313d502 100644 --- a/src/xfdesktop-icon-view-manager.c +++ b/src/xfdesktop-icon-view-manager.c @@ -23,7 +23,7 @@ #endif #include - +#include #include "xfdesktop-icon-view-manager.h" #include "xfdesktop-icon-view.h" @@ -82,6 +82,130 @@ xfdesktop_icon_view_manager_fini(XfdesktopIconViewManager *manager) iface->manager_fini(manager); } +static void xfdesktop_dnd_item(GtkWidget *item, GdkDragAction *action) +{ + XfdesktopIconViewManager *manager; + XfdesktopIcon *drop_icon; + GdkDragContext *context; + guint16 *row; + guint16 *col; + guint *time_; + + manager = g_object_get_data(G_OBJECT(item), "manager"); + drop_icon = g_object_get_data(G_OBJECT(item), "drop_icon"); + context = g_object_get_data(G_OBJECT(item), "context"); + row = g_object_get_data(G_OBJECT(item), "row"); + col = g_object_get_data(G_OBJECT(item), "col"); + time_ = g_object_get_data(G_OBJECT(item), "time"); + + context->action = *action; + xfdesktop_icon_view_manager_drag_drop(manager, drop_icon, context, *row, *col, *time_); + + g_free(row); + g_free(col); + g_free(time_); +} + +/* Cancel selected from the xfdesktop_dnd_menu. + * This frees up memory allocated during the xfdesktop_dnd_menu setup. */ +static void xfdesktop_dnd_item_cancel(GtkWidget *item, GdkDragAction *action) +{ + guint16 *row; + guint16 *col; + guint *time_; + row = g_object_get_data(G_OBJECT(item), "row"); + col = g_object_get_data(G_OBJECT(item), "col"); + time_ = g_object_get_data(G_OBJECT(item), "time"); + g_free(row); + g_free(col); + g_free(time_); +} + +/** + * xfdesktop_dnd_menu: + * @manager : the #XfdesktopIconViewManager instance + * @drop_icon : the #XfdesktopIcon to which is being dropped. + * @context : the #GdkDragContext of the icons being dropped. + * @row : the row on the desktop to drop to. + * @col : the col on the desktop to drop to. + * @ time_ : the starting time of the drag event. + * Pops up a menu that asks the user to choose one of the + * actions or to cancel the drop. If the user chooses an action other + * than cancel, it will then call xfdesktop_icon_view_manager_drag_drop + * with the selected action. + * Portions of this code was copied from thunar-dnd.c + * Copyright (c) 2005-2006 Benedikt Meurer + * Copyright (c) 2009-2011 Jannis Pohlmann + **/ +static void xfdesktop_dnd_menu (XfdesktopIconViewManager *manager, + XfdesktopIcon *drop_icon, + GdkDragContext *context, + guint16 row, + guint16 col, + guint time_) +{ + static GdkDragAction actions[] = { GDK_ACTION_COPY, GDK_ACTION_MOVE, GDK_ACTION_LINK }; + static const gchar *action_names[] = { N_ ("Copy _Here") , N_ ("_Move Here") , N_ ("_Link Here") }; + static const gchar *action_icons[] = { "stock_folder-copy", "stock_folder-move", NULL }; + GtkWidget *menu; + GtkWidget *item; + GtkWidget *image; + guint16 *temp_row, *temp_col; + guint *temp_time, menu_item; + menu = gtk_menu_new(); + + /* Allocate these variables so they don't go out of scope */ + temp_row = g_try_malloc(sizeof(guint16)); + temp_col = g_try_malloc(sizeof(guint16)); + temp_time = g_try_malloc(sizeof(guint)); + + g_return_if_fail(temp_row != NULL); + g_return_if_fail(temp_col != NULL); + g_return_if_fail(temp_time != NULL); + + *temp_row = row; + *temp_col = col; + *temp_time = time_; + for(menu_item = 0; menu_item < G_N_ELEMENTS(actions); menu_item++) + { + item = gtk_image_menu_item_new_with_mnemonic(action_names[menu_item]); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(xfdesktop_dnd_item), &actions[menu_item]); + + g_object_set_data(G_OBJECT(item), "manager", manager); + g_object_set_data(G_OBJECT(item), "drop_icon", drop_icon); + g_object_set_data(G_OBJECT(item), "context", context); + g_object_set_data(G_OBJECT(item), "row", temp_row); + g_object_set_data(G_OBJECT(item), "col", temp_col); + g_object_set_data(G_OBJECT(item), "time", temp_time); + + /* add image to the menu item */ + if (G_LIKELY (action_icons[menu_item] != NULL)) + { + image = gtk_image_new_from_icon_name (action_icons[menu_item], GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); + gtk_widget_show (image); + } + + gtk_widget_show (item); + } + + item = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_widget_show (item); + + item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CANCEL, NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(xfdesktop_dnd_item_cancel), NULL); + g_object_set_data(G_OBJECT(item), "row", temp_row); + g_object_set_data(G_OBJECT(item), "col", temp_col); + g_object_set_data(G_OBJECT(item), "time", temp_time); + gtk_widget_show (item); + + gtk_widget_show(menu); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, time_); +} + gboolean xfdesktop_icon_view_manager_drag_drop(XfdesktopIconViewManager *manager, XfdesktopIcon *drop_icon, @@ -94,6 +218,12 @@ xfdesktop_icon_view_manager_drag_drop(XfdesktopIconViewManager *manager, g_return_val_if_fail(XFDESKTOP_IS_ICON_VIEW_MANAGER(manager), FALSE); + if(context->action == GDK_ACTION_ASK) + { + xfdesktop_dnd_menu(manager, drop_icon, context, row, col, time_); + return TRUE; + } + iface = XFDESKTOP_ICON_VIEW_MANAGER_GET_IFACE(manager); g_return_val_if_fail(iface->drag_drop, FALSE); diff --git a/src/xfdesktop-icon-view.c b/src/xfdesktop-icon-view.c index 0736006..4c39b0c 100644 --- a/src/xfdesktop-icon-view.c +++ b/src/xfdesktop-icon-view.c @@ -48,6 +48,7 @@ #include "xfdesktop-icon-view.h" #include "xfdesktop-marshal.h" +#include "xfce-desktop.h" #include #include @@ -744,7 +745,7 @@ xfdesktop_icon_view_button_press(GtkWidget *widget, xfdesktop_icon_view_select_item(icon_view, icon); } - if(evt->button == 1) { + if(evt->button == 1 || evt->button == 3) { /* we might be the start of a drag */ DBG("setting stuff"); icon_view->priv->maybe_begin_drag = TRUE; @@ -752,10 +753,6 @@ xfdesktop_icon_view_button_press(GtkWidget *widget, icon_view->priv->definitely_rubber_banding = FALSE; icon_view->priv->press_start_x = evt->x; icon_view->priv->press_start_y = evt->y; - } else if(evt->button == 3) { - /* XfceDesktop will handle signalling the icon view manager - * to show the context menu */ - return FALSE; } return TRUE; @@ -810,7 +807,10 @@ xfdesktop_icon_view_button_release(GtkWidget *widget, TRACE("entering btn=%d", evt->button); - if(evt->button == 1) { + if(evt->button == 3 && !icon_view->priv->definitely_dragging && !icon_view->priv->definitely_rubber_banding) + xfce_desktop_popup_root_menu(XFCE_DESKTOP(widget), evt->button, evt->time); + + if(evt->button == 1 || evt->button == 3) { DBG("unsetting stuff"); icon_view->priv->definitely_dragging = FALSE; icon_view->priv->maybe_begin_drag = FALSE; @@ -897,9 +897,15 @@ xfdesktop_icon_view_maybe_begin_drag(XfdesktopIconView *icon_view, actions = GDK_ACTION_MOVE | (icon_view->priv->drag_source_set ? icon_view->priv->foreign_source_actions : 0); + if(evt->state != GDK_BUTTON3_MASK) { gtk_drag_begin(GTK_WIDGET(icon_view), icon_view->priv->source_targets, actions, 1, (GdkEvent *)evt); + } else { + gtk_drag_begin(GTK_WIDGET(icon_view), + icon_view->priv->source_targets, + actions| GDK_ACTION_ASK, 3, (GdkEvent *)evt); + } DBG("DRAG BEGIN!"); -- 1.7.5.4