mirror of https://github.com/MidnightCommander/mc
1999-01-26 Federico Mena Quintero <federico@nuclecu.unam.mx>
* gscreen.c (panel_setup_drag_scroll): Renamed from panel_setup_drag_motion(). (panel_clist_drag_motion): Use gdnd_validate_action(). (panel_clist_motion): Return immediately if the event window is not the clist_window. Otherwise, forward the event to panel_widget_motion(). * gdnd.c (gdnd_find_panel_by_drag_context): New public function to find a panel based on a drag context. This is basically the old find_panel_owning_window() made public. (gdnd_drop_on_directory): Test for the source widget being a tree, and if so, do not use the default behavior for panels. (gdnd_validate_action): New function to compute the final drag action given some conditions. This is now used to make dragging behavior consistent across the desktop and the file panels.
This commit is contained in:
parent
83ab2a7f65
commit
f97cb04b55
|
@ -1,3 +1,21 @@
|
|||
1999-01-26 Federico Mena Quintero <federico@nuclecu.unam.mx>
|
||||
|
||||
* gscreen.c (panel_setup_drag_scroll): Renamed from
|
||||
panel_setup_drag_motion().
|
||||
(panel_clist_drag_motion): Use gdnd_validate_action().
|
||||
(panel_clist_motion): Return immediately if the event window is
|
||||
not the clist_window. Otherwise, forward the event to
|
||||
panel_widget_motion().
|
||||
|
||||
* gdnd.c (gdnd_find_panel_by_drag_context): New public function to
|
||||
find a panel based on a drag context. This is basically the old
|
||||
find_panel_owning_window() made public.
|
||||
(gdnd_drop_on_directory): Test for the source widget being a tree,
|
||||
and if so, do not use the default behavior for panels.
|
||||
(gdnd_validate_action): New function to compute the final drag
|
||||
action given some conditions. This is now used to make dragging
|
||||
behavior consistent across the desktop and the file panels.
|
||||
|
||||
1999-01-26 Jonathan Blandford <jrb@redhat.com>
|
||||
|
||||
* gnome-file-property-dialog.c: Many Many Many changes. Now it's
|
||||
|
@ -11,6 +29,15 @@
|
|||
|
||||
1999-01-25 Federico Mena Quintero <federico@nuclecu.unam.mx>
|
||||
|
||||
* gscreen.c (panel_create_icon_display): Only use
|
||||
GTK_DEST_DEFAULT_DROP since we want to do exotic stuff in the
|
||||
drag_motion handler to validate drops.
|
||||
(panel_icon_list_drag_motion): Use gdnd_validate_action().
|
||||
|
||||
* gdnd.c (gdnd_drop_on_directory): Removed hack that prevented the
|
||||
user from dropping files on the same panel as the source one.
|
||||
This should not be done here.
|
||||
|
||||
* gdnd.c (get_action): Sensitize the menu items based on the
|
||||
allowed actions in the drag context.
|
||||
(actions): Add some underlined accelerators for the action menu.
|
||||
|
|
|
@ -1645,6 +1645,12 @@ desktop_drag_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y,
|
|||
/* If it comes from ourselves, make move the default unless the
|
||||
* user is explicitly asking for ASK.
|
||||
*/
|
||||
printf ("%s\t%s\t%s\t%s\n",
|
||||
(context->actions & GDK_ACTION_COPY) ? "copy" : "",
|
||||
(context->actions & GDK_ACTION_MOVE) ? "move" : "",
|
||||
(context->actions & GDK_ACTION_LINK) ? "link" : "",
|
||||
(context->actions & GDK_ACTION_ASK) ? "ask" : "");
|
||||
|
||||
if (source_widget
|
||||
&& context->suggested_action != GDK_ACTION_ASK
|
||||
&& (context->actions & GDK_ACTION_MOVE))
|
||||
|
|
160
gnome/gdnd.c
160
gnome/gdnd.c
|
@ -96,56 +96,6 @@ get_action (GdkDragContext *context)
|
|||
return action;
|
||||
}
|
||||
|
||||
/*
|
||||
* Looks for a panel that has the specified window for its list
|
||||
* display. It is used to figure out if we are receiving a drop from
|
||||
* a panel on this MC process. If no panel is found, it returns NULL.
|
||||
*/
|
||||
static WPanel *
|
||||
find_panel_owning_window (GdkDragContext *context)
|
||||
{
|
||||
GList *list;
|
||||
WPanel *panel;
|
||||
GtkWidget *source_widget, *toplevel_widget;
|
||||
|
||||
source_widget = gtk_drag_get_source_widget (context);
|
||||
if (!source_widget)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* We will scan the list of existing WPanels. We
|
||||
* uniformize the thing by pulling the toplevel
|
||||
* widget for each WPanel and compare this to the
|
||||
* toplevel source_widget
|
||||
*/
|
||||
toplevel_widget = gtk_widget_get_toplevel (source_widget);
|
||||
|
||||
for (list = containers; list; list = list->next) {
|
||||
GtkWidget *panel_toplevel_widget;
|
||||
|
||||
panel = ((PanelContainer *) list->data)->panel;
|
||||
|
||||
panel_toplevel_widget = panel->xwindow;
|
||||
|
||||
if (panel->xwindow == toplevel_widget){
|
||||
|
||||
/*
|
||||
* Now a WPanel actually contains a number of
|
||||
* drag sources. If the drag source is the
|
||||
* Tree, we must report that it was not the
|
||||
* contents of the WPanel
|
||||
*/
|
||||
|
||||
if (source_widget == panel->tree)
|
||||
return NULL;
|
||||
|
||||
return panel;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a drop action on the specified panel. Only supports copy
|
||||
* and move operations. The files are moved or copied to the
|
||||
|
@ -292,6 +242,7 @@ gdnd_drop_on_directory (GdkDragContext *context, GtkSelectionData *selection_dat
|
|||
{
|
||||
GdkDragAction action;
|
||||
WPanel *source_panel;
|
||||
GtkWidget *source_widget;
|
||||
GList *names;
|
||||
|
||||
if (context->action == GDK_ACTION_ASK) {
|
||||
|
@ -303,14 +254,12 @@ gdnd_drop_on_directory (GdkDragContext *context, GtkSelectionData *selection_dat
|
|||
} else
|
||||
action = context->action;
|
||||
|
||||
/* If we are dragging from a file panel, we can display a nicer status display */
|
||||
source_panel = find_panel_owning_window (context);
|
||||
|
||||
/* Check if the user did not drag the information to the same directory */
|
||||
if (source_panel) {
|
||||
if (strcmp (source_panel->cwd, destdir) == 0)
|
||||
return FALSE;
|
||||
}
|
||||
/* If we are dragging from a file panel, we can display a nicer status
|
||||
* display. But if the drag was from the tree, we cannot do this.
|
||||
*/
|
||||
source_panel = gdnd_find_panel_by_drag_context (context, &source_widget);
|
||||
if (source_widget == source_panel->tree)
|
||||
source_panel = NULL;
|
||||
|
||||
/* Symlinks do not use file.c */
|
||||
|
||||
|
@ -355,3 +304,98 @@ gdnd_drag_context_has_target (GdkDragContext *context, TargetType type)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdnd_find_panel_by_drag_context:
|
||||
* @context: The context by which to find a panel.
|
||||
* @source_widget: The source widget is returned here.
|
||||
*
|
||||
* Looks in the list of panels for the one that corresponds to the specified
|
||||
* drag context.
|
||||
*
|
||||
* Return value: The sought panel, or NULL if no panel corresponds to the
|
||||
* context.
|
||||
**/
|
||||
WPanel *
|
||||
gdnd_find_panel_by_drag_context (GdkDragContext *context, GtkWidget **source_widget)
|
||||
{
|
||||
GtkWidget *source;
|
||||
GtkWidget *toplevel;
|
||||
GList *l;
|
||||
WPanel *panel;
|
||||
|
||||
g_return_val_if_fail (context != NULL, NULL);
|
||||
|
||||
source = gtk_drag_get_source_widget (context);
|
||||
|
||||
if (source_widget)
|
||||
*source_widget = source;
|
||||
|
||||
if (!source)
|
||||
return NULL; /* different process */
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (source);
|
||||
|
||||
for (l = containers; l; l = l->next) {
|
||||
panel = ((PanelContainer *) l->data)->panel;
|
||||
|
||||
if (panel->xwindow == toplevel)
|
||||
return panel;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdnd_validate_action:
|
||||
* @context: The drag context for this drag operation.
|
||||
* @same_process: Whether the drag comes from the same process or not.
|
||||
* @same_source: If same_process, then whether the source and dest widgets are the same.
|
||||
* @dest: The destination file entry, or NULL if dropping on empty space.
|
||||
* @dest_selected: If dest is non-NULL, whether it is selected or not.
|
||||
*
|
||||
* Computes the final drag action based on the suggested action of the specified
|
||||
* context and conditions.
|
||||
*
|
||||
* Return value: The computed action, meant to be passed to gdk_drag_action().
|
||||
**/
|
||||
GdkDragAction
|
||||
gdnd_validate_action (GdkDragContext *context, int same_process, int same_source,
|
||||
file_entry *dest_fe, int dest_selected)
|
||||
{
|
||||
int on_directory;
|
||||
int on_exe;
|
||||
|
||||
if (dest_fe) {
|
||||
on_directory = dest_fe->f.link_to_dir || S_ISDIR (dest_fe->buf.st_mode);
|
||||
on_exe = is_exe (dest_fe->buf.st_mode) && if_link_is_exe (dest_fe);
|
||||
}
|
||||
|
||||
if (dest_fe) {
|
||||
if (same_source && dest_selected)
|
||||
return 0;
|
||||
|
||||
if (on_directory) {
|
||||
if ((same_source || same_process) && (context->actions & GDK_ACTION_MOVE))
|
||||
return GDK_ACTION_MOVE;
|
||||
else
|
||||
return context->suggested_action;
|
||||
} else if (on_exe) {
|
||||
if (context->actions & GDK_ACTION_COPY)
|
||||
return GDK_ACTION_COPY;
|
||||
} else if (same_source)
|
||||
return 0;
|
||||
else if (same_process && (context->actions & GDK_ACTION_MOVE))
|
||||
return GDK_ACTION_MOVE;
|
||||
else
|
||||
return context->suggested_action;
|
||||
} else {
|
||||
if (same_source)
|
||||
return 0;
|
||||
else if (same_process && (context->actions & GDK_ACTION_MOVE))
|
||||
return GDK_ACTION_MOVE;
|
||||
else
|
||||
return context->suggested_action;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
11
gnome/gdnd.h
11
gnome/gdnd.h
|
@ -10,6 +10,7 @@
|
|||
#define GDND_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "panel.h"
|
||||
|
||||
|
||||
/* Standard DnD types */
|
||||
|
@ -40,4 +41,14 @@ int gdnd_drop_on_directory (GdkDragContext *context, GtkSelectionData *selection
|
|||
/* Test whether the specified context has a certain target type */
|
||||
int gdnd_drag_context_has_target (GdkDragContext *context, TargetType type);
|
||||
|
||||
/* Look for a panel that corresponds to the specified drag context */
|
||||
WPanel *gdnd_find_panel_by_drag_context (GdkDragContext *context, GtkWidget **source_widget);
|
||||
|
||||
/* Computes the final drag action based on the suggested actions and the
|
||||
* specified conditions.
|
||||
*/
|
||||
GdkDragAction gdnd_validate_action (GdkDragContext *context, int same_process, int same_source,
|
||||
file_entry *dest_fe, int dest_selected);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
123
gnome/gscreen.c
123
gnome/gscreen.c
|
@ -601,7 +601,7 @@ typedef gboolean (*desirable_fn)(WPanel *p, int x, int y);
|
|||
typedef gboolean (*scroll_fn)(gpointer data);
|
||||
|
||||
static gboolean
|
||||
panel_setup_drag_motion (WPanel *panel, int x, int y, desirable_fn desirable, scroll_fn scroll)
|
||||
panel_setup_drag_scroll (WPanel *panel, int x, int y, desirable_fn desirable, scroll_fn scroll)
|
||||
{
|
||||
if (panel->timer_id != -1){
|
||||
gtk_timeout_remove (panel->timer_id);
|
||||
|
@ -911,7 +911,7 @@ panel_widget_motion (GtkWidget *widget, GdkEventMotion *event, WPanel *panel)
|
|||
{
|
||||
GtkTargetList *list;
|
||||
GdkDragContext *context;
|
||||
|
||||
|
||||
if (!panel->maybe_start_drag)
|
||||
return FALSE;
|
||||
|
||||
|
@ -952,6 +952,18 @@ panel_drag_end (GtkWidget *widget, GdkDragContext *context, WPanel *panel)
|
|||
panel->dragging = 0;
|
||||
}
|
||||
|
||||
/* Wrapper for the motion_notify callback; it ignores motion events from the
|
||||
* clist if they do not come from the clist_window.
|
||||
*/
|
||||
static int
|
||||
panel_clist_motion (GtkWidget *widget, GdkEventMotion *event, gpointer data)
|
||||
{
|
||||
if (event->window != GTK_CLIST (widget)->clist_window)
|
||||
return FALSE;
|
||||
|
||||
return panel_widget_motion (widget, event, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* panel_clist_scrolling_is_desirable:
|
||||
*
|
||||
|
@ -1011,25 +1023,50 @@ panel_clist_scroll (gpointer data)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* panel_clist_drag_motion:
|
||||
*
|
||||
* Invoked when an application dragging over us has the the cursor moved.
|
||||
* If we are close to the top or bottom, we scroll the window
|
||||
/* Callback used for drag motion events over the clist. We set up
|
||||
* auto-scrolling and validate the drop to present the user with the correct
|
||||
* feedback.
|
||||
*/
|
||||
static gboolean
|
||||
panel_clist_drag_motion (GtkWidget *widget, GdkDragContext *ctx, int x, int y, guint time, void *data)
|
||||
panel_clist_drag_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time,
|
||||
gpointer data)
|
||||
{
|
||||
WPanel *panel = data;
|
||||
WPanel *panel;
|
||||
GdkDragAction action;
|
||||
GtkWidget *source_widget;
|
||||
gint idx;
|
||||
file_entry *fe;
|
||||
|
||||
if (ctx->dest_window != GTK_CLIST (widget)->clist_window)
|
||||
gdk_drag_status (ctx, 0, time);
|
||||
else {
|
||||
panel_setup_drag_motion (panel, x, y,
|
||||
panel_clist_scrolling_is_desirable, panel_clist_scroll);
|
||||
gdk_drag_status (ctx, ctx->suggested_action, time);
|
||||
panel = data;
|
||||
|
||||
if (context->dest_window != GTK_CLIST (widget)->clist_window) {
|
||||
printf ("squick\n");
|
||||
gdk_drag_status (context, 0, time);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Set up auto-scrolling */
|
||||
|
||||
panel_setup_drag_scroll (panel, x, y,
|
||||
panel_clist_scrolling_is_desirable,
|
||||
panel_clist_scroll);
|
||||
|
||||
/* Validate the drop */
|
||||
|
||||
gdnd_find_panel_by_drag_context (context, &source_widget);
|
||||
|
||||
if (!gtk_clist_get_selection_info (GTK_CLIST (widget), x, y, &idx, NULL))
|
||||
fe = NULL;
|
||||
else
|
||||
fe = &panel->dir.list[idx];
|
||||
|
||||
action = gdnd_validate_action (context,
|
||||
source_widget != NULL,
|
||||
source_widget == widget,
|
||||
fe,
|
||||
fe ? fe->f.marked : FALSE);
|
||||
|
||||
gdk_drag_status (context, action, time);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1108,18 +1145,42 @@ panel_icon_list_scroll (gpointer data)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* panel_icon_list_drag_motion:
|
||||
*
|
||||
* Invoked when an application dragging over us has the the cursor moved.
|
||||
* If we are close to the top or bottom, we scroll the window
|
||||
/* Callback used for drag motion events in the icon list. We need to set up
|
||||
* auto-scrolling and validate the drop to present the user with the correct
|
||||
* feedback.
|
||||
*/
|
||||
static gboolean
|
||||
panel_icon_list_drag_motion (GtkWidget *widget, GdkDragContext *ctx, int x, int y, guint time, void *data)
|
||||
panel_icon_list_drag_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time,
|
||||
gpointer data)
|
||||
{
|
||||
WPanel *panel = data;
|
||||
|
||||
panel_setup_drag_motion (panel, x, y, panel_icon_list_scrolling_is_desirable, panel_icon_list_scroll);
|
||||
WPanel *panel;
|
||||
GdkDragAction action;
|
||||
GtkWidget *source_widget;
|
||||
int idx;
|
||||
file_entry *fe;
|
||||
|
||||
panel = data;
|
||||
|
||||
/* Set up auto-scrolling */
|
||||
|
||||
panel_setup_drag_scroll (panel, x, y,
|
||||
panel_icon_list_scrolling_is_desirable,
|
||||
panel_icon_list_scroll);
|
||||
|
||||
/* Validate the drop */
|
||||
|
||||
gdnd_find_panel_by_drag_context (context, &source_widget);
|
||||
|
||||
idx = gnome_icon_list_get_icon_at (GNOME_ICON_LIST (widget), x, y);
|
||||
fe = (idx == -1) ? NULL : &panel->dir.list[idx];
|
||||
|
||||
action = gdnd_validate_action (context,
|
||||
source_widget != NULL,
|
||||
source_widget == widget,
|
||||
fe,
|
||||
fe ? fe->f.marked : FALSE);
|
||||
|
||||
gdk_drag_status (context, action, time);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1189,15 +1250,16 @@ panel_create_file_list (WPanel *panel)
|
|||
|
||||
load_dnd_icons ();
|
||||
|
||||
gtk_drag_dest_set (GTK_WIDGET (file_list), GTK_DEST_DEFAULT_DROP,
|
||||
gtk_drag_dest_set (GTK_WIDGET (file_list),
|
||||
GTK_DEST_DEFAULT_DROP,
|
||||
drop_types, ELEMENTS (drop_types),
|
||||
GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK);
|
||||
|
||||
#if 0
|
||||
/* Make directories draggable */
|
||||
gtk_drag_source_set (GTK_WIDGET (file_list), GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
|
||||
drag_types, ELEMENTS (drag_types),
|
||||
GDK_ACTION_LINK | GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_ASK);
|
||||
|
||||
#endif
|
||||
gtk_signal_connect (GTK_OBJECT (file_list), "drag_data_get",
|
||||
GTK_SIGNAL_FUNC (panel_drag_data_get), panel);
|
||||
gtk_signal_connect (GTK_OBJECT (file_list), "drag_data_delete",
|
||||
|
@ -1226,7 +1288,7 @@ panel_create_file_list (WPanel *panel)
|
|||
GTK_SIGNAL_FUNC (panel_clist_button_release), panel);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (file_list), "motion_notify_event",
|
||||
GTK_SIGNAL_FUNC (panel_widget_motion), panel);
|
||||
GTK_SIGNAL_FUNC (panel_clist_motion), panel);
|
||||
gtk_signal_connect (GTK_OBJECT (file_list), "drag_begin",
|
||||
GTK_SIGNAL_FUNC (panel_drag_begin), panel);
|
||||
gtk_signal_connect (GTK_OBJECT (file_list), "drag_end",
|
||||
|
@ -1385,7 +1447,8 @@ panel_create_icon_display (WPanel *panel)
|
|||
load_imlib_icons ();
|
||||
load_dnd_icons ();
|
||||
|
||||
gtk_drag_dest_set (GTK_WIDGET (ilist), GTK_DEST_DEFAULT_ALL,
|
||||
gtk_drag_dest_set (GTK_WIDGET (ilist),
|
||||
GTK_DEST_DEFAULT_DROP,
|
||||
drop_types, ELEMENTS (drop_types),
|
||||
GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK);
|
||||
|
||||
|
@ -1918,7 +1981,7 @@ panel_tree_drag_motion (GtkWidget *widget, GdkDragContext *ctx, int x, int y, gu
|
|||
WPanel *panel = data;
|
||||
int r, row, col;
|
||||
|
||||
if (panel_setup_drag_motion (panel, x, y, panel_tree_scrolling_is_desirable, panel_tree_scroll))
|
||||
if (panel_setup_drag_scroll (panel, x, y, panel_tree_scrolling_is_desirable, panel_tree_scroll))
|
||||
return TRUE;
|
||||
|
||||
r = gtk_clist_get_selection_info (
|
||||
|
|
Loading…
Reference in New Issue