1
1

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.
Этот коммит содержится в:
Miguel de Icaza 1999-01-26 06:53:48 +00:00
родитель 83ab2a7f65
Коммит f97cb04b55
5 изменённых файлов: 239 добавлений и 88 удалений

Просмотреть файл

@ -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))

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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 (