[Xfce4-commits] <xfdesktop:master> Right-click Drag and Drop
Eric Koegel
noreply at xfce.org
Mon Mar 5 19:30:01 CET 2012
Updating branch refs/heads/master
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