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.
Этот коммит содержится в:
родитель
83ab2a7f65
Коммит
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 (
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user