From ceb258ff1cb4cd39d7b6aa76dc40565f93a703f4 Mon Sep 17 00:00:00 2001 From: Eric Koegel Date: Sat, 17 Dec 2011 19:23:38 +0300 Subject: [PATCH] Right click drag and drop. Bug 4004 --- src/xfdesktop-file-icon-manager.c | 8 ++- src/xfdesktop-icon-view-manager.c | 98 ++++++++++++++++++++++++++++++++++++- src/xfdesktop-icon-view.c | 20 +++++--- 3 files changed, 116 insertions(+), 10 deletions(-) diff --git a/src/xfdesktop-file-icon-manager.c b/src/xfdesktop-file-icon-manager.c index d3ca2eb..1a11dff 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..0bdcc19 100644 --- a/src/xfdesktop-icon-view-manager.c +++ b/src/xfdesktop-icon-view-manager.c @@ -23,10 +23,11 @@ #endif #include - +#include #include "xfdesktop-icon-view-manager.h" #include "xfdesktop-icon-view.h" + GType xfdesktop_icon_view_manager_get_type(void) { @@ -82,6 +83,91 @@ xfdesktop_icon_view_manager_fini(XfdesktopIconViewManager *manager) iface->manager_fini(manager); } +static void xfdesktop_dnd_item(GtkWidget *item, GdkDragAction *action) +{ + *action = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(item), "action")); +} + +static void xfdesktop_dnd_item_cancel(GtkWidget *item, GdkDragAction *action) +{ + *action = 0; +} + +/** + * 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. Sets context->action to + * the new action the user selected or 0 on cancel. + * 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; + guint menu_item, signal_id; + GMainLoop *loop; + gint response; + menu = gtk_menu_new(); + + 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), &response); + g_object_set_data(G_OBJECT(item), "action", GUINT_TO_POINTER(actions[menu_item])); + /* 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), &response); + gtk_widget_show(item); + + gtk_widget_show(menu); + g_object_ref_sink (G_OBJECT (menu)); + gtk_menu_set_screen(GTK_MENU(menu), gdk_display_get_default_screen(gdk_display_get_default())); + + loop = g_main_loop_new (NULL, FALSE); + signal_id = g_signal_connect_swapped (G_OBJECT (menu), "deactivate", G_CALLBACK (g_main_loop_quit), loop); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, time_); + g_main_loop_run (loop); + g_signal_handler_disconnect (G_OBJECT (menu), signal_id); + g_main_loop_unref (loop); + + context->action = response; + + g_object_unref (G_OBJECT (menu)); +} + gboolean xfdesktop_icon_view_manager_drag_drop(XfdesktopIconViewManager *manager, XfdesktopIcon *drop_icon, @@ -94,6 +180,16 @@ 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_); + + if(context->action == 0) { + gtk_drag_finish(context, FALSE, FALSE, 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..1919694 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; @@ -809,8 +806,11 @@ xfdesktop_icon_view_button_release(GtkWidget *widget, XfdesktopIconView *icon_view = XFDESKTOP_ICON_VIEW(user_data); 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