[Xfce4-commits] <xfdesktop:eric/bugzilla-patches> Right-click Drag and Drop

Eric Koegel noreply at xfce.org
Sun Feb 12 14:32:02 CET 2012


Updating branch refs/heads/eric/bugzilla-patches
         to cf1ba8ecefacca369c4f83ece0b6d03b718fce06 (commit)
       from 82e69c54b00a07e6ffd52b0c2f475dd9ba76dfa7 (commit)

commit cf1ba8ecefacca369c4f83ece0b6d03b718fce06
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Mon Feb 6 08:45:06 2012 +0300

    Right-click Drag and Drop
    
    Drag and drop right-click to and from the desktop will cause a
    menu pop-up. Additionally, this patch also fixes the issue where
    files that were dropped onto the desktop were always copied by
    default instead of doing a move when they were on the same
    filesystem. They were combined because the move/copy bug requires
    code implemented in this right click drag and drop patch.

 src/xfdesktop-file-icon-manager.c |  146 ++++++++++++++++++++++++++++++++++++-
 src/xfdesktop-icon-view.c         |   20 +++--
 2 files changed, 156 insertions(+), 10 deletions(-)

diff --git a/src/xfdesktop-file-icon-manager.c b/src/xfdesktop-file-icon-manager.c
index d3ca2eb..8b82fdc 100644
--- a/src/xfdesktop-file-icon-manager.c
+++ b/src/xfdesktop-file-icon-manager.c
@@ -2778,6 +2778,92 @@ xfdesktop_file_icon_manager_drag_drop(XfdesktopIconViewManager *manager,
     return TRUE;
 }
 
+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 <benny at xfce.org>
+ * Copyright (c) 2009-2011 Jannis Pohlmann <jannis at xfce.org>
+ **/
+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();
+
+    /* This adds the Copy, Move, & Link options */
+    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);
+    }
+
+    /* Add a seperator */
+    item = gtk_separator_menu_item_new();
+    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+    gtk_widget_show(item);
+
+    /* Cancel option */
+    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));
+
+    /* Loop until we get a user response */
+    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));
+}
+
 static void
 xfdesktop_file_icon_manager_drag_data_received(XfdesktopIconViewManager *manager,
                                                XfdesktopIcon *drop_icon,
@@ -2794,6 +2880,20 @@ xfdesktop_file_icon_manager_drag_data_received(XfdesktopIconViewManager *manager
     GFile *tfile = NULL;
     gboolean copy_only = TRUE, drop_ok = FALSE;
     GList *file_list;
+    gboolean user_selected_action = FALSE;
+
+    TRACE("entering");
+
+    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;
+        }
+        /* The user picked whether to move or copy the files */
+        user_selected_action = TRUE;
+    }
 
     if(info == TARGET_XDND_DIRECT_SAVE0) {
         /* we don't suppose XdndDirectSave stage 3, result F, i.e., the app
@@ -2866,7 +2966,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_);
@@ -2907,12 +3007,48 @@ xfdesktop_file_icon_manager_drag_data_received(XfdesktopIconViewManager *manager
                     base_dest_file = g_object_ref(fmanager->priv->folder);
                 }
 
+                /* If the user didn't pick whether to copy or move via
+                 * a GDK_ACTION_ASK then determine if we should move/copy
+                 * by checking if the files are on the same file system.
+                 */
+                if(user_selected_action == FALSE) {
+                    GFileInfo *src_info, *dest_info;
+                    const gchar *src_name, *dest_name;
+                    dest_info = g_file_query_info(base_dest_file,
+                                                  G_FILE_ATTRIBUTE_ID_FILESYSTEM,
+                                                  G_FILE_QUERY_INFO_NONE,
+                                                  NULL,
+                                                  NULL);
+                    src_info = g_file_query_info(file_list->data,
+                                                 G_FILE_ATTRIBUTE_ID_FILESYSTEM,
+                                                 G_FILE_QUERY_INFO_NONE,
+                                                 NULL,
+                                                 NULL);
+
+                    if(dest_info != NULL && src_info != NULL) {
+                        dest_name = g_file_info_get_attribute_string(dest_info,
+                                                G_FILE_ATTRIBUTE_ID_FILESYSTEM);
+                        src_name = g_file_info_get_attribute_string(src_info,
+                                                G_FILE_ATTRIBUTE_ID_FILESYSTEM);
+
+                        if(g_strcmp0(src_name, dest_name) == 0) {
+                            copy_only = FALSE;
+                            context->action = GDK_ACTION_MOVE;
+                        }
+                    }
+
+                    if(dest_info != NULL)
+                        g_object_unref(dest_info);
+                    if(src_info != NULL)
+                        g_object_unref(src_info);
+                }
+
                 for (l = file_list; l; l = l->next) {
                     gchar *dest_basename = g_file_get_basename(l->data);
 
                     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 +3072,11 @@ xfdesktop_file_icon_manager_drag_data_received(XfdesktopIconViewManager *manager
                                                                   fmanager->priv->gscreen);
                 }
 
-                xfdesktop_file_utils_file_list_free(dest_file_list);
+                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.c b/src/xfdesktop-icon-view.c
index 0736006..e1c918a 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 <libwnck/libwnck.h>
 #include <libxfce4ui/libxfce4ui.h>
@@ -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!");
     


More information about the Xfce4-commits mailing list