From 84013cb8d5dad5a5c754b9897a754e132f9d3345 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Thu, 19 Mar 1998 02:57:01 +0000 Subject: [PATCH] Wed Mar 18 20:35:45 1998 Miguel de Icaza * gdesktop.c (desktop_create_launch_entry): Support for the "Drop" target in mc.ext now. * Add support for dragging the icons on the desktop. (desktop_icon_make_draggable): new function. (drop_from_event): simplify. (my_create_transparent_text_window): Get the motion notify event. (drops_from_event): create a vector based on thge drop event. (drop_cb): splitted, call url_drop for regular drops, otherwise it is a icon drop. (artificial_drag_start): new routine, used now by gscreen.c and gdesktop.c (drop_on_directory): Check result value of operation. (desktop_icon_set_position): sane interface. (stop_desktop): Flush all of our state to disk. --- gnome/ChangeLog | 19 ++ gnome/gdesktop.c | 545 ++++++++++++++++++++++++++++++++--------------- gnome/gdesktop.h | 1 + gnome/gmain.c | 3 + gnome/gscreen.c | 40 +--- lib/mc.ext.in | 2 +- src/ext.c | 37 +++- 7 files changed, 433 insertions(+), 214 deletions(-) diff --git a/gnome/ChangeLog b/gnome/ChangeLog index 3b45eb381..f9abaf4e1 100644 --- a/gnome/ChangeLog +++ b/gnome/ChangeLog @@ -1,3 +1,22 @@ +Wed Mar 18 20:35:45 1998 Miguel de Icaza + + * gdesktop.c (desktop_create_launch_entry): Support for the "Drop" + target in mc.ext now. + + * Add support for dragging the icons on the desktop. + + (desktop_icon_make_draggable): new function. + (drop_from_event): simplify. + (my_create_transparent_text_window): Get the motion notify event. + (drops_from_event): create a vector based on thge drop event. + (drop_cb): splitted, call url_drop for regular drops, otherwise it + is a icon drop. + (artificial_drag_start): new routine, used now by gscreen.c and + gdesktop.c + (drop_on_directory): Check result value of operation. + (desktop_icon_set_position): sane interface. + (stop_desktop): Flush all of our state to disk. + 1998-03-18 Federico Mena Quintero * gscreen.c: Removed tests for the gprop stuff. diff --git a/gnome/gdesktop.c b/gnome/gdesktop.c index edca2e52e..46b4264ac 100644 --- a/gnome/gdesktop.c +++ b/gnome/gdesktop.c @@ -18,6 +18,7 @@ #include "gscreen.h" #include "ext.h" #include +#include /* Types of desktop icons: * @@ -64,13 +65,15 @@ static void desktop_reload (char *desktop_dir); /* The list with the filenames we have actually loaded */ static GList *desktop_icons; +#define ELEMENTS(x) (sizeof (x) / sizeof (x[0])) + /* * If the dentry is zero, then no information from the on-disk .desktop file is used * In this case, we probably will have to store the geometry for a file somewhere * else. */ static void -desktop_icon_set_position (desktop_icon_t *di, GtkWidget *widget) +desktop_icon_set_position (desktop_icon_t *di) { static int x, y = 10; static int current_x, current_y; @@ -93,8 +96,8 @@ desktop_icon_set_position (desktop_icon_t *di, GtkWidget *widget) x = current_x; y = current_y; - gtk_widget_size_request (widget, &widget->requisition); - current_y += widget->requisition.height + 8; + gtk_widget_size_request (di->widget, &di->widget->requisition); + current_y += di->widget->requisition.height + 8; if (current_y > gdk_screen_height ()){ current_x += 0; current_y = 0; @@ -102,7 +105,76 @@ desktop_icon_set_position (desktop_icon_t *di, GtkWidget *widget) } di->x = x; di->y = y; - gtk_widget_set_uposition (widget, 6 + x, y); + gtk_widget_set_uposition (di->widget, 6 + x, y); +} + +/* + * Returns the icon associated with the given file name, or app.xpm + * if no icon is defined for this application + */ +static char * +get_desktop_icon (char *pathname) +{ + char *fname, *full_fname; + + fname = regex_command (x_basename (pathname), "Icon", 0, 0); + + /* Try the GNOME icon */ + full_fname = gnome_unconditional_pixmap_file (fname); + if (exist_file (full_fname)) + return full_fname; + g_free (full_fname); + + /* Try a mc icon */ + full_fname = concat_dir_and_file (ICONDIR, fname); + if (exist_file (full_fname)) + return full_fname; + + free (full_fname); + + return gnome_unconditional_pixmap_file ("launcher-program.xpm"); +} + +/* + * Hackisigh routine taken from GDK + */ +static void +gdk_dnd_drag_begin (GdkWindow *initial_window) +{ + GdkEventDragBegin tev; + tev.type = GDK_DRAG_BEGIN; + tev.window = initial_window; + tev.u.allflags = 0; + tev.u.flags.protocol_version = DND_PROTOCOL_VERSION; + + gdk_event_put ((GdkEvent *) &tev); +} + +void +artificial_drag_start (GdkWindow *window, int x, int y) +{ + GdkWindowPrivate *wp = (GdkWindowPrivate *) window; + + if (!wp->dnd_drag_enabled) + return; + if (!gdk_dnd.drag_perhaps) + return; + if (gdk_dnd.dnd_grabbed) + return; + if (gdk_dnd.drag_really) + return; + + printf ("Pushing artificial drag\n"); + gdk_dnd_drag_addwindow (window); + gdk_dnd_drag_begin (window); + XGrabPointer (gdk_display, wp->xwindow, False, + ButtonMotionMask | ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, gdk_root_window, + None, CurrentTime); + gdk_dnd.dnd_grabbed = TRUE; + gdk_dnd.drag_perhaps = 1; + gdk_dnd.drag_really = 1; + gdk_dnd_display_drag_cursor (x, y, FALSE, TRUE); } static int operation_value; @@ -292,6 +364,9 @@ drop_on_directory (GdkEventDropDataAvailable *event, char *dest, int force_manua operation = get_operation (event->timestamp, event->coords.x, event->coords.y); + if (operation == -1) + return; + /* Optimization: if we are dragging from the same process, we can * display a nicer status bar. */ @@ -311,7 +386,7 @@ drop_on_directory (GdkEventDropDataAvailable *event, char *dest, int force_manua } static void -drop_cb (GtkWidget *widget, GdkEventDropDataAvailable *event, desktop_icon_t *di) +url_dropped (GtkWidget *widget, GdkEventDropDataAvailable *event, desktop_icon_t *di) { char *p; int count; @@ -345,6 +420,15 @@ drop_cb (GtkWidget *widget, GdkEventDropDataAvailable *event, desktop_icon_t *di } +static void +drop_cb (GtkWidget *widget, GdkEventDropDataAvailable *event, desktop_icon_t *di) +{ + if (strcmp (event->data_type, "icon/root") == 0){ + printf ("ICON DROPPED ON ROOT!\n"); + } else + url_dropped (widget, event, di); +} + static void connect_drop_signals (GtkWidget *widget, desktop_icon_t *di) { @@ -376,98 +460,18 @@ dentry_properties (desktop_icon_t *di) printf ("Edit this widget properties\n"); } -static int -dentry_button_click (GtkWidget *widget, GdkEventButton *event, desktop_icon_t *di) -{ - if (event->type == GDK_2BUTTON_PRESS && event->button == 1){ - dentry_execute (di); - return TRUE; - } - - if (event->type == GDK_BUTTON_PRESS && event->button == 3){ - desktop_icon_context_popup (event, di); - return TRUE; - } - return FALSE; -} - -char *drop_types [] = { - "text/plain", - "url:ALL", -}; - -#define ELEMENTS(x) (sizeof (x) / sizeof (x[0])) - -GtkWidget * -my_create_transparent_text_window (char *file, char *text, int extra_events) -{ - GtkWidget *w; - - w = create_transparent_text_window (file, text, extra_events); - if (!w){ - static char *default_pix; - - if (!default_pix){ - default_pix = gnome_unconditional_pixmap_file ("launcher-program.xpm"); - } - w = create_transparent_text_window (default_pix, text, extra_events); - if (!w) - return NULL; - } - return w; -} - +/* Pops up the icon properties pages */ static void -desktop_load_from_dentry (GnomeDesktopEntry *dentry) +icon_properties (GtkWidget *widget, desktop_icon_t *di) { - desktop_icon_t *di; - GtkWidget *window; - char *icon_label; - - icon_label = dentry->name ? dentry->name : x_basename (dentry->exec); - if (dentry->icon) - window = my_create_transparent_text_window (dentry->icon, icon_label, GDK_BUTTON_PRESS_MASK); - else { - static char *default_icon_path; - static char exists; - - if (!default_icon_path){ - default_icon_path = gnome_unconditional_pixmap_file ("launcher-program.xpm"); - if (g_file_exists (default_icon_path)) - exists = 1; - } - - if (exists) - window = my_create_transparent_text_window (default_icon_path, icon_label, GDK_BUTTON_PRESS_MASK); - else { - window = gtk_window_new (GTK_WINDOW_POPUP); - gtk_widget_set_usize (window, 20, 20); - } - } - if (!window) - return; - - di = xmalloc (sizeof (desktop_icon_t), "desktop_load_entry"); - di->dentry = dentry; - di->widget = window; - di->pathname = dentry->location; - - desktop_icon_set_position (di, window); - - desktop_icons = g_list_prepend (desktop_icons, (gpointer) di); - - /* Setup the widget to make it useful: */ - - /* 1. Drag and drop functionality */ - connect_drop_signals (window, di); - gtk_widget_dnd_drop_set (window, TRUE, drop_types, ELEMENTS (drop_types), FALSE); - - /* 2. Double clicking executes the command */ - gtk_signal_connect (GTK_OBJECT (window), "button_press_event", GTK_SIGNAL_FUNC (dentry_button_click), di); - - gtk_widget_show (window); + printf ("Sorry, no property pages yet\n"); + gtk_main_quit (); } +/* + * destroys a desktop_icon_t structure and anything that was held there, + * including the desktop widget. + */ static void desktop_release_desktop_icon_t (desktop_icon_t *di) { @@ -486,97 +490,124 @@ desktop_release_desktop_icon_t (desktop_icon_t *di) } static void -desktop_load_dentry (char *filename) +start_icon_drag (GtkWidget *wi, GdkEventMotion *event) { - GnomeDesktopEntry *dentry; + printf ("MOTION NOTIF!\n"); + artificial_drag_start (wi->window, event->x, event->y); +} + +GdkPoint root_icon_drag_hotspot = { 15, 15 }; + +static void +desktop_icon_drag_request (GtkWidget *widget, GdkEventDragRequest *event, desktop_icon_t *di) +{ + printf ("Drag type: %s\n", event->data_type); - dentry = gnome_desktop_entry_load (filename); + if (strcmp (event->data_type, "url:ALL") == 0){ + gdk_window_dnd_data_set (widget->window, (GdkEvent *)event, di->pathname, strlen (di->pathname) + 1); + } else { + int drop_x, drop_y; - if (!dentry) - return; + drop_x = event->drop_coords.x - root_icon_drag_hotspot.x; + drop_y = event->drop_coords.y - root_icon_drag_hotspot.y; + + /* Icon dropped on root. We take care of it */ + printf ("Dropped at %d %d\n", drop_x, drop_y); + gtk_widget_set_uposition (di->widget, drop_x, drop_y); + if (di->dentry){ + char buffer [40]; - desktop_load_from_dentry (dentry); + sprintf (buffer, "%d,%d", drop_x, drop_y); + if (di->dentry->geometry) + g_free (di->dentry->geometry); + di->dentry->geometry = g_strdup (buffer); + gnome_desktop_entry_save (di->dentry); + } + } +} + +static GtkWidget *root_drag_ok_window; +static GtkWidget *root_drag_not_ok_window; + +static void +destroy_shaped_dnd_windows (void) +{ + if (root_drag_not_ok_window){ + gtk_widget_destroy (root_drag_not_ok_window); + root_drag_not_ok_window = 0; + } + + if (root_drag_ok_window){ + gtk_widget_destroy (root_drag_ok_window); + root_drag_ok_window = 0; + } } static void -desktop_create_directory_entry (char *dentry_path, char *pathname, char *short_name) +desktop_icon_drag_start (GtkWidget *widget, GdkEvent *event, desktop_icon_t *di) { - GnomeDesktopEntry *dentry; + char *fname; - dentry = xmalloc (sizeof (GnomeDesktopEntry), "dcde"); - dentry->name = g_strdup (short_name); - dentry->comment = NULL; - dentry->tryexec = NULL; - dentry->exec = g_strdup (pathname); - dentry->icon = gnome_unconditional_pixmap_file ("gnome-folder.png"); - dentry->docpath = NULL; - dentry->type = g_strdup ("Directory"); - dentry->location = g_strdup (dentry_path); + /* This should not happen, as the drag end routine should destroy those widgets */ + destroy_shaped_dnd_windows (); + + if (di->dentry) + fname = strdup (di->dentry->icon); + else + fname = get_desktop_icon (di->pathname); + + if (fname){ + /* FIXME: we are using the same icon for ok and not ok drags */ + root_drag_ok_window = make_transparent_window (fname); + root_drag_not_ok_window = make_transparent_window (fname); + + gdk_dnd_set_drag_shape (root_drag_ok_window->window, &root_icon_drag_hotspot, + root_drag_not_ok_window->window, &root_icon_drag_hotspot); + gtk_widget_show (root_drag_not_ok_window); + gtk_widget_show (root_drag_ok_window); - gnome_desktop_entry_save (dentry); - desktop_load_from_dentry (dentry); + free (fname); + } +} + +static void +desktop_icon_drag_end (GtkWidget *widget, GdkEvent *event, desktop_icon_t *di) +{ + printf ("drag end!\n"); + destroy_shaped_dnd_windows (); } /* - * Returns the icon associated with the given file name, or app.xpm - * if no icon is defined for this application + * Bind the signals so that we can make this icon draggable */ -static char * -get_desktop_icon (char *pathname) -{ - char *fname, *full_fname; - - fname = regex_command (x_basename (pathname), "Icon", 0, 0); - - /* Try the GNOME icon */ - full_fname = gnome_unconditional_pixmap_file (fname); - if (exist_file (full_fname)) - return full_fname; - g_free (full_fname); - - /* Try a mc icon */ - full_fname = concat_dir_and_file (ICONDIR, fname); - if (exist_file (full_fname)) - return full_fname; - - free (full_fname); - - return gnome_unconditional_pixmap_file ("launcher-program.xpm"); -} - -static int -file_is_executable (char *path) -{ - struct stat s; - - if (mc_stat (path, &s) == -1) - return 0; - - if (is_exe (s.st_mode)) - return 1; - return 0; - -} - -/* Pops up the icon properties pages */ static void -icon_properties (GtkWidget *widget, desktop_icon_t *di) +desktop_icon_make_draggable (desktop_icon_t *di) { - printf ("Sorry, no property pages yet\n"); - gtk_main_quit (); + GtkObject *obj = GTK_OBJECT (di->widget); + char *drag_types [] = { "icon/root", "url:ALL" }; + + /* To artificially start up drag and drop */ + gtk_signal_connect (obj, "motion_notify_event", GTK_SIGNAL_FUNC (start_icon_drag), di); + gtk_widget_dnd_drag_set (di->widget, TRUE, drag_types, ELEMENTS (drag_types)); + + gtk_signal_connect (obj, "drag_request_event", GTK_SIGNAL_FUNC (desktop_icon_drag_request), di); + gtk_signal_connect (obj, "drag_begin_event", GTK_SIGNAL_FUNC (desktop_icon_drag_start), di); + gtk_signal_connect (obj, "drag_end_event", GTK_SIGNAL_FUNC (desktop_icon_drag_end), di); } +/* + * Removes an icon from the desktop and kills the ~/desktop file associated with it + */ static void desktop_icon_remove (desktop_icon_t *di) { desktop_icons = g_list_remove (desktop_icons, di); mc_unlink (di->pathname); - gtk_widget_destroy (di->widget); desktop_release_desktop_icon_t (di); } -/* Removes the icon from the desktop */ +/* Called by the pop up menu: removes the icon from the desktop */ static void icon_delete (GtkWidget *widget, desktop_icon_t *di) { @@ -614,6 +645,156 @@ desktop_icon_context_popup (GdkEventButton *event, desktop_icon_t *di) gtk_widget_destroy (menu); } +static int +dentry_button_click (GtkWidget *widget, GdkEventButton *event, desktop_icon_t *di) +{ + if (event->type == GDK_2BUTTON_PRESS && event->button == 1){ + dentry_execute (di); + return TRUE; + } + + if (event->type == GDK_BUTTON_PRESS && event->button == 3){ + desktop_icon_context_popup (event, di); + return TRUE; + } + return FALSE; +} + +char *drop_types [] = { + "text/plain", + "url:ALL", +}; + +char *root_drop_types [] = { + "icon/root", + "url:ALL" +}; + +GtkWidget * +my_create_transparent_text_window (char *file, char *text) +{ + GtkWidget *w; + int events = GDK_BUTTON_PRESS_MASK | GDK_BUTTON1_MOTION_MASK; + + w = create_transparent_text_window (file, text, events); + if (!w){ + static char *default_pix; + + if (!default_pix){ + default_pix = gnome_unconditional_pixmap_file ("launcher-program.xpm"); + } + w = create_transparent_text_window (default_pix, text, events); + if (!w) + return NULL; + } + return w; +} + +static void +desktop_load_from_dentry (GnomeDesktopEntry *dentry) +{ + desktop_icon_t *di; + GtkWidget *window; + char *icon_label; + + icon_label = dentry->name ? dentry->name : x_basename (dentry->exec); + if (dentry->icon) + window = my_create_transparent_text_window (dentry->icon, icon_label); + else { + static char *default_icon_path; + static char exists; + + if (!default_icon_path){ + default_icon_path = gnome_unconditional_pixmap_file ("launcher-program.xpm"); + if (g_file_exists (default_icon_path)) + exists = 1; + } + + if (exists) + window = my_create_transparent_text_window (default_icon_path, icon_label); + else { + window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_widget_set_usize (window, 20, 20); + } + } + if (!window) + return; + + di = xmalloc (sizeof (desktop_icon_t), "desktop_load_entry"); + di->dentry = dentry; + di->widget = window; + di->pathname = dentry->location; + + desktop_icon_set_position (di); + desktop_icon_make_draggable (di); + + desktop_icons = g_list_prepend (desktop_icons, (gpointer) di); + + /* Setup the widget to make it useful: */ + + /* 1. Drag and drop functionality */ + connect_drop_signals (window, di); + gtk_widget_dnd_drop_set (window, TRUE, drop_types, ELEMENTS (drop_types), FALSE); + + /* 2. Double clicking executes the command */ + gtk_signal_connect (GTK_OBJECT (window), "button_press_event", GTK_SIGNAL_FUNC (dentry_button_click), di); + + gtk_widget_show (window); +} + +/* + * Loads a .desktop file from FILENAME for the desktop. + */ +static void +desktop_load_dentry (char *filename) +{ + GnomeDesktopEntry *dentry; + + dentry = gnome_desktop_entry_load (filename); + + if (!dentry) + return; + + desktop_load_from_dentry (dentry); +} + +/* + * Creates a new DIRECTORY/.directory file which is just a .dekstop + * on directories. And then loads it into the desktop + */ +static void +desktop_create_directory_entry (char *dentry_path, char *pathname, char *short_name) +{ + GnomeDesktopEntry *dentry; + + dentry = xmalloc (sizeof (GnomeDesktopEntry), "dcde"); + dentry->name = g_strdup (short_name); + dentry->comment = NULL; + dentry->tryexec = NULL; + dentry->exec = g_strdup (pathname); + dentry->icon = gnome_unconditional_pixmap_file ("gnome-folder.png"); + dentry->docpath = NULL; + dentry->type = g_strdup ("Directory"); + dentry->location = g_strdup (dentry_path); + + gnome_desktop_entry_save (dentry); + desktop_load_from_dentry (dentry); +} + +static int +file_is_executable (char *path) +{ + struct stat s; + + if (mc_stat (path, &s) == -1) + return 0; + + if (is_exe (s.st_mode)) + return 1; + return 0; + +} + static int desktop_file_exec (GtkWidget *widget, GdkEventButton *event, desktop_icon_t *di) { @@ -644,8 +825,8 @@ desktop_file_exec (GtkWidget *widget, GdkEventButton *event, desktop_icon_t *di) return FALSE; } -static void -drop_on_executable (desktop_icon_t *di, GdkEventDropDataAvailable *event) +static char ** +drops_from_event (GdkEventDropDataAvailable *event) { int count, i, len; int arguments; @@ -675,25 +856,34 @@ drop_on_executable (desktop_icon_t *di, GdkEventDropDataAvailable *event) } while (count); argv [i] = 0; - /* invoke */ - exec_direct (di->pathname, argv); + return argv; } static void drop_on_launch_entry (GtkWidget *widget, GdkEventDropDataAvailable *event, desktop_icon_t *di) { struct stat s; - + char *r; + char **drops; + /* try to stat it, if it fails, remove it from desktop */ if (!mc_stat (di->pathname, &s) == 0){ desktop_icon_remove (di); return; } + + drops = drops_from_event (event); - if (is_exe (s.st_mode)){ - drop_on_executable (di, event); + r = regex_command (di->pathname, "Drop", drops, 0); + if (strcmp (r, "Success") == 0){ + free (drops); return; } + + if (is_exe (s.st_mode)) + exec_direct (di->pathname, drops); + + free (drops); } static void @@ -704,7 +894,7 @@ desktop_create_launch_entry (char *pathname, char *short_name) char *icon; icon = get_desktop_icon (pathname); - window = my_create_transparent_text_window (icon, x_basename (pathname), GDK_BUTTON_PRESS_MASK); + window = my_create_transparent_text_window (icon, x_basename (pathname)); g_free (icon); if (!window) return; @@ -714,8 +904,9 @@ desktop_create_launch_entry (char *pathname, char *short_name) di->widget = window; di->pathname = strdup (pathname); - desktop_icon_set_position (di, window); - + desktop_icon_set_position (di); + desktop_icon_make_draggable (di); + desktop_icons = g_list_prepend (desktop_icons, (gpointer) di); /* Double clicking executes the command, single clicking brings up context menu */ @@ -726,7 +917,7 @@ desktop_create_launch_entry (char *pathname, char *short_name) GTK_SIGNAL_FUNC (drop_on_launch_entry), di); gtk_widget_dnd_drop_set (window, TRUE, drop_types, ELEMENTS (drop_types), FALSE); - + gtk_widget_show (window); } @@ -851,7 +1042,7 @@ desktop_root (void) rw = gnome_rootwin_new (); connect_drop_signals (rw, NULL); gtk_widget_realize (rw); - gtk_widget_dnd_drop_set (rw, TRUE, drop_types, ELEMENTS (drop_types), FALSE); + gtk_widget_dnd_drop_set (rw, TRUE, root_drop_types, ELEMENTS (root_drop_types), FALSE); gtk_widget_show (rw); root_window = GNOME_ROOTWIN (rw); } @@ -870,4 +1061,18 @@ start_desktop (void) desktop_root (); desktop_reload (desktop_directory); } - + +/* + * shutdown the desktop + */ +void +stop_desktop (void) +{ + GList *p; + + for (p = desktop_icons; p; p = p->next){ + desktop_icon_t *di = p->data; + + desktop_release_desktop_icon_t (di); + } +} diff --git a/gnome/gdesktop.h b/gnome/gdesktop.h index 6bc655e4f..2a53fa369 100644 --- a/gnome/gdesktop.h +++ b/gnome/gdesktop.h @@ -6,3 +6,4 @@ GtkWidget *make_transparent_window (char *file); /* gdesktop.c */ void drop_on_directory (GdkEventDropDataAvailable *event, char *dest, int force_manually); +void artificial_drag_start (GdkWindow *source_window, int x, int y); diff --git a/gnome/gmain.c b/gnome/gmain.c index 7958349ae..6b2db0d37 100644 --- a/gnome/gmain.c +++ b/gnome/gmain.c @@ -358,5 +358,8 @@ create_panels (void) set_current_panel (0); run_dlg (h); + + /* shutdown gnome specific bits of midnight commander */ + stop_desktop (); } diff --git a/gnome/gscreen.c b/gnome/gscreen.c index 054827ac3..29428fec7 100644 --- a/gnome/gscreen.c +++ b/gnome/gscreen.c @@ -13,8 +13,6 @@ #include /* atoi */ #include "fs.h" #include "x.h" -#include -#include #include "dir.h" #include "panel.h" #include "command.h" @@ -690,14 +688,11 @@ panel_drag_request (GtkWidget *widget, GdkEventDragRequest *event, WPanel *panel int len; GdkWindowPrivate *clist_window = (GdkWindowPrivate *) (GTK_WIDGET (widget)->window); GdkWindowPrivate *clist_areaw = (GdkWindowPrivate *) (GTK_CLIST (widget)->clist_window); - - printf ("Drag request!\n"); - printf ("Drag [%s] request!\n", event->data_type); + if ((strcmp (event->data_type, "text/plain") == 0) || (strcmp (event->data_type, "url:ALL") == 0)){ data = panel_build_selected_file_list (panel, &len); - printf ("Data: %s\n", (char *) data); if (clist_window->dnd_drag_accepted) gdk_window_dnd_data_set ((GdkWindow *)clist_window, (GdkEvent *) event, data, len); @@ -765,7 +760,6 @@ panel_drag_begin (GtkWidget *widget, GdkEvent *event, WPanel *panel) { GdkPoint hotspot = { 15, 15 }; - printf ("Drag starting\n"); if (panel->marked){ if (drag_multiple && drag_multiple_ok){ gdk_dnd_set_drag_shape (drag_multiple->window, &hotspot, @@ -785,37 +779,9 @@ panel_drag_begin (GtkWidget *widget, GdkEvent *event, WPanel *panel) } static void -gdk_dnd_drag_begin (GdkWindow *initial_window) +panel_artificial_drag_start (GtkCList *window, GdkEventMotion *event) { - GdkEventDragBegin tev; - tev.type = GDK_DRAG_BEGIN; - tev.window = initial_window; - tev.u.allflags = 0; - tev.u.flags.protocol_version = DND_PROTOCOL_VERSION; - - gdk_event_put ((GdkEvent *) &tev); -} - -static void -panel_artificial_drag_start (GtkCList *window, GdkEventMotion *event, WPanel *panel) -{ - GdkWindowPrivate *wp = (GdkWindowPrivate *) window->clist_window; - - if (!wp->dnd_drag_enabled) - return; - if (!(gdk_dnd.drag_perhaps || gdk_dnd.drag_really)) - return; - - gdk_dnd_drag_addwindow (window->clist_window); - gdk_dnd_drag_begin (window->clist_window); - XGrabPointer (gdk_display, wp->xwindow, False, - ButtonMotionMask | ButtonPressMask | ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, gdk_root_window, - None, CurrentTime); - gdk_dnd.dnd_grabbed = TRUE; - gdk_dnd.drag_perhaps = 1; - gdk_dnd.drag_really = 1; - gdk_dnd_display_drag_cursor (event->x, event->y, FALSE, TRUE); + artificial_drag_start (window->clist_window, event->x, event->y); } static GtkWidget * diff --git a/lib/mc.ext.in b/lib/mc.ext.in index 1df7ab9ce..3ef6b9a32 100644 --- a/lib/mc.ext.in +++ b/lib/mc.ext.in @@ -468,7 +468,7 @@ type/PDF type/executable Open=./%f View=%view - Drop=./%f %q + Drop=%f %q Execute in XTerm=xterm -e ./%f & View Required Libraries=%view{ascii} ldd %f Strip binary=strip %f diff --git a/src/ext.c b/src/ext.c index ad08a9bdc..1409cfd5d 100644 --- a/src/ext.c +++ b/src/ext.c @@ -73,8 +73,36 @@ flush_extension_file (void) } +typedef char *(*quote_func_t)(const char *name, int i); + +static char * +quote_block (quote_func_t quote_func, char **quoting_block) +{ + char **p = quoting_block; + char *result = 0; + char *tail = 0; + int current_len = 0; + + for (p = quoting_block; *p; p++){ + int temp_len; + char *temp = quote_func (*p, 0); + + temp_len = strlen (temp); + current_len += temp_len + 2; + result = realloc (result, current_len); + if (!tail) + tail = result; + strcpy (tail, temp); + strcat (tail, " "); + tail += temp_len + 1; + free (temp); + } + + return result; +} + static void -exec_extension (char *filename, char *data, char *drops, int *move_dir, int start_line) +exec_extension (char *filename, char *data, char **drops, int *move_dir, int start_line) { char *file_name; FILE *cmd_file; @@ -92,7 +120,7 @@ exec_extension (char *filename, char *data, char *drops, int *move_dir, int star time_t localmtime = 0; struct stat mystat; int do_local_copy; - char * (*quote_func)(const char *name, int i) = name_quote; + quote_func_t quote_func = name_quote; /* Avoid making a local copy if we are doing a cd */ if (!vfs_file_is_local(filename)) @@ -178,8 +206,7 @@ exec_extension (char *filename, char *data, char *drops, int *move_dir, int star text = (*quote_func) (filename, 0); } } else if (*data == 'q') { - /* FIXME: currently broken */ -/* text = (*quote_func) (drops, 0); */ + text = quote_block (quote_func, drops); } else text = expand_format (*data, !is_cd); if (!is_cd) @@ -618,8 +645,6 @@ match_file_output: if (p < q) { char *filename_copy = strdup (filename); - /* FIXME: drops is passed from an incompatible pointer type */ - exec_extension (filename_copy, r + 1, drops, move_dir, view_at_line_number); free (filename_copy);