Wed Mar 18 20:35:45 1998 Miguel de Icaza <miguel@nuclecu.unam.mx>
* 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.
Этот коммит содержится в:
родитель
9ab2e34656
Коммит
84013cb8d5
@ -1,3 +1,22 @@
|
|||||||
|
Wed Mar 18 20:35:45 1998 Miguel de Icaza <miguel@nuclecu.unam.mx>
|
||||||
|
|
||||||
|
* 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 <federico@nuclecu.unam.mx>
|
1998-03-18 Federico Mena Quintero <federico@nuclecu.unam.mx>
|
||||||
|
|
||||||
* gscreen.c: Removed tests for the gprop stuff.
|
* gscreen.c: Removed tests for the gprop stuff.
|
||||||
|
545
gnome/gdesktop.c
545
gnome/gdesktop.c
@ -18,6 +18,7 @@
|
|||||||
#include "gscreen.h"
|
#include "gscreen.h"
|
||||||
#include "ext.h"
|
#include "ext.h"
|
||||||
#include <gdk/gdkx.h>
|
#include <gdk/gdkx.h>
|
||||||
|
#include <gdk/gdkprivate.h>
|
||||||
|
|
||||||
/* Types of desktop icons:
|
/* Types of desktop icons:
|
||||||
*
|
*
|
||||||
@ -64,13 +65,15 @@ static void desktop_reload (char *desktop_dir);
|
|||||||
/* The list with the filenames we have actually loaded */
|
/* The list with the filenames we have actually loaded */
|
||||||
static GList *desktop_icons;
|
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
|
* 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
|
* In this case, we probably will have to store the geometry for a file somewhere
|
||||||
* else.
|
* else.
|
||||||
*/
|
*/
|
||||||
static void
|
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 x, y = 10;
|
||||||
static int current_x, current_y;
|
static int current_x, current_y;
|
||||||
@ -93,8 +96,8 @@ desktop_icon_set_position (desktop_icon_t *di, GtkWidget *widget)
|
|||||||
x = current_x;
|
x = current_x;
|
||||||
y = current_y;
|
y = current_y;
|
||||||
|
|
||||||
gtk_widget_size_request (widget, &widget->requisition);
|
gtk_widget_size_request (di->widget, &di->widget->requisition);
|
||||||
current_y += widget->requisition.height + 8;
|
current_y += di->widget->requisition.height + 8;
|
||||||
if (current_y > gdk_screen_height ()){
|
if (current_y > gdk_screen_height ()){
|
||||||
current_x += 0;
|
current_x += 0;
|
||||||
current_y = 0;
|
current_y = 0;
|
||||||
@ -102,7 +105,76 @@ desktop_icon_set_position (desktop_icon_t *di, GtkWidget *widget)
|
|||||||
}
|
}
|
||||||
di->x = x;
|
di->x = x;
|
||||||
di->y = y;
|
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;
|
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);
|
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
|
/* Optimization: if we are dragging from the same process, we can
|
||||||
* display a nicer status bar.
|
* display a nicer status bar.
|
||||||
*/
|
*/
|
||||||
@ -311,7 +386,7 @@ drop_on_directory (GdkEventDropDataAvailable *event, char *dest, int force_manua
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
drop_cb (GtkWidget *widget, GdkEventDropDataAvailable *event, desktop_icon_t *di)
|
url_dropped (GtkWidget *widget, GdkEventDropDataAvailable *event, desktop_icon_t *di)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
int count;
|
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
|
static void
|
||||||
connect_drop_signals (GtkWidget *widget, desktop_icon_t *di)
|
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");
|
printf ("Edit this widget properties\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
/* Pops up the icon properties pages */
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
desktop_load_from_dentry (GnomeDesktopEntry *dentry)
|
icon_properties (GtkWidget *widget, desktop_icon_t *di)
|
||||||
{
|
{
|
||||||
desktop_icon_t *di;
|
printf ("Sorry, no property pages yet\n");
|
||||||
GtkWidget *window;
|
gtk_main_quit ();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* destroys a desktop_icon_t structure and anything that was held there,
|
||||||
|
* including the desktop widget.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
desktop_release_desktop_icon_t (desktop_icon_t *di)
|
desktop_release_desktop_icon_t (desktop_icon_t *di)
|
||||||
{
|
{
|
||||||
@ -486,97 +490,124 @@ desktop_release_desktop_icon_t (desktop_icon_t *di)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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)
|
drop_x = event->drop_coords.x - root_icon_drag_hotspot.x;
|
||||||
return;
|
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
|
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");
|
/* This should not happen, as the drag end routine should destroy those widgets */
|
||||||
dentry->name = g_strdup (short_name);
|
destroy_shaped_dnd_windows ();
|
||||||
dentry->comment = NULL;
|
|
||||||
dentry->tryexec = NULL;
|
if (di->dentry)
|
||||||
dentry->exec = g_strdup (pathname);
|
fname = strdup (di->dentry->icon);
|
||||||
dentry->icon = gnome_unconditional_pixmap_file ("gnome-folder.png");
|
else
|
||||||
dentry->docpath = NULL;
|
fname = get_desktop_icon (di->pathname);
|
||||||
dentry->type = g_strdup ("Directory");
|
|
||||||
dentry->location = g_strdup (dentry_path);
|
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);
|
free (fname);
|
||||||
desktop_load_from_dentry (dentry);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
* Bind the signals so that we can make this icon draggable
|
||||||
* 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
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");
|
GtkObject *obj = GTK_OBJECT (di->widget);
|
||||||
gtk_main_quit ();
|
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
|
static void
|
||||||
desktop_icon_remove (desktop_icon_t *di)
|
desktop_icon_remove (desktop_icon_t *di)
|
||||||
{
|
{
|
||||||
desktop_icons = g_list_remove (desktop_icons, di);
|
desktop_icons = g_list_remove (desktop_icons, di);
|
||||||
|
|
||||||
mc_unlink (di->pathname);
|
mc_unlink (di->pathname);
|
||||||
gtk_widget_destroy (di->widget);
|
|
||||||
desktop_release_desktop_icon_t (di);
|
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
|
static void
|
||||||
icon_delete (GtkWidget *widget, desktop_icon_t *di)
|
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);
|
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
|
static int
|
||||||
desktop_file_exec (GtkWidget *widget, GdkEventButton *event, desktop_icon_t *di)
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static char **
|
||||||
drop_on_executable (desktop_icon_t *di, GdkEventDropDataAvailable *event)
|
drops_from_event (GdkEventDropDataAvailable *event)
|
||||||
{
|
{
|
||||||
int count, i, len;
|
int count, i, len;
|
||||||
int arguments;
|
int arguments;
|
||||||
@ -675,25 +856,34 @@ drop_on_executable (desktop_icon_t *di, GdkEventDropDataAvailable *event)
|
|||||||
} while (count);
|
} while (count);
|
||||||
argv [i] = 0;
|
argv [i] = 0;
|
||||||
|
|
||||||
/* invoke */
|
return argv;
|
||||||
exec_direct (di->pathname, argv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
drop_on_launch_entry (GtkWidget *widget, GdkEventDropDataAvailable *event, desktop_icon_t *di)
|
drop_on_launch_entry (GtkWidget *widget, GdkEventDropDataAvailable *event, desktop_icon_t *di)
|
||||||
{
|
{
|
||||||
struct stat s;
|
struct stat s;
|
||||||
|
char *r;
|
||||||
|
char **drops;
|
||||||
|
|
||||||
/* try to stat it, if it fails, remove it from desktop */
|
/* try to stat it, if it fails, remove it from desktop */
|
||||||
if (!mc_stat (di->pathname, &s) == 0){
|
if (!mc_stat (di->pathname, &s) == 0){
|
||||||
desktop_icon_remove (di);
|
desktop_icon_remove (di);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drops = drops_from_event (event);
|
||||||
|
|
||||||
if (is_exe (s.st_mode)){
|
r = regex_command (di->pathname, "Drop", drops, 0);
|
||||||
drop_on_executable (di, event);
|
if (strcmp (r, "Success") == 0){
|
||||||
|
free (drops);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_exe (s.st_mode))
|
||||||
|
exec_direct (di->pathname, drops);
|
||||||
|
|
||||||
|
free (drops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -704,7 +894,7 @@ desktop_create_launch_entry (char *pathname, char *short_name)
|
|||||||
char *icon;
|
char *icon;
|
||||||
|
|
||||||
icon = get_desktop_icon (pathname);
|
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);
|
g_free (icon);
|
||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
@ -714,8 +904,9 @@ desktop_create_launch_entry (char *pathname, char *short_name)
|
|||||||
di->widget = window;
|
di->widget = window;
|
||||||
di->pathname = strdup (pathname);
|
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);
|
desktop_icons = g_list_prepend (desktop_icons, (gpointer) di);
|
||||||
|
|
||||||
/* Double clicking executes the command, single clicking brings up context menu */
|
/* 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_SIGNAL_FUNC (drop_on_launch_entry), di);
|
||||||
|
|
||||||
gtk_widget_dnd_drop_set (window, TRUE, drop_types, ELEMENTS (drop_types), FALSE);
|
gtk_widget_dnd_drop_set (window, TRUE, drop_types, ELEMENTS (drop_types), FALSE);
|
||||||
|
|
||||||
gtk_widget_show (window);
|
gtk_widget_show (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -851,7 +1042,7 @@ desktop_root (void)
|
|||||||
rw = gnome_rootwin_new ();
|
rw = gnome_rootwin_new ();
|
||||||
connect_drop_signals (rw, NULL);
|
connect_drop_signals (rw, NULL);
|
||||||
gtk_widget_realize (rw);
|
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);
|
gtk_widget_show (rw);
|
||||||
root_window = GNOME_ROOTWIN (rw);
|
root_window = GNOME_ROOTWIN (rw);
|
||||||
}
|
}
|
||||||
@ -870,4 +1061,18 @@ start_desktop (void)
|
|||||||
desktop_root ();
|
desktop_root ();
|
||||||
desktop_reload (desktop_directory);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,3 +6,4 @@ GtkWidget *make_transparent_window (char *file);
|
|||||||
|
|
||||||
/* gdesktop.c */
|
/* gdesktop.c */
|
||||||
void drop_on_directory (GdkEventDropDataAvailable *event, char *dest, int force_manually);
|
void drop_on_directory (GdkEventDropDataAvailable *event, char *dest, int force_manually);
|
||||||
|
void artificial_drag_start (GdkWindow *source_window, int x, int y);
|
||||||
|
@ -358,5 +358,8 @@ create_panels (void)
|
|||||||
|
|
||||||
set_current_panel (0);
|
set_current_panel (0);
|
||||||
run_dlg (h);
|
run_dlg (h);
|
||||||
|
|
||||||
|
/* shutdown gnome specific bits of midnight commander */
|
||||||
|
stop_desktop ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
#include <stdlib.h> /* atoi */
|
#include <stdlib.h> /* atoi */
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "x.h"
|
#include "x.h"
|
||||||
#include <gdk/gdkprivate.h>
|
|
||||||
#include <gdk/gdkx.h>
|
|
||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
#include "panel.h"
|
#include "panel.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
@ -690,14 +688,11 @@ panel_drag_request (GtkWidget *widget, GdkEventDragRequest *event, WPanel *panel
|
|||||||
int len;
|
int len;
|
||||||
GdkWindowPrivate *clist_window = (GdkWindowPrivate *) (GTK_WIDGET (widget)->window);
|
GdkWindowPrivate *clist_window = (GdkWindowPrivate *) (GTK_WIDGET (widget)->window);
|
||||||
GdkWindowPrivate *clist_areaw = (GdkWindowPrivate *) (GTK_CLIST (widget)->clist_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) ||
|
if ((strcmp (event->data_type, "text/plain") == 0) ||
|
||||||
(strcmp (event->data_type, "url:ALL") == 0)){
|
(strcmp (event->data_type, "url:ALL") == 0)){
|
||||||
data = panel_build_selected_file_list (panel, &len);
|
data = panel_build_selected_file_list (panel, &len);
|
||||||
printf ("Data: %s\n", (char *) data);
|
|
||||||
|
|
||||||
if (clist_window->dnd_drag_accepted)
|
if (clist_window->dnd_drag_accepted)
|
||||||
gdk_window_dnd_data_set ((GdkWindow *)clist_window, (GdkEvent *) event, data, len);
|
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 };
|
GdkPoint hotspot = { 15, 15 };
|
||||||
|
|
||||||
printf ("Drag starting\n");
|
|
||||||
if (panel->marked){
|
if (panel->marked){
|
||||||
if (drag_multiple && drag_multiple_ok){
|
if (drag_multiple && drag_multiple_ok){
|
||||||
gdk_dnd_set_drag_shape (drag_multiple->window, &hotspot,
|
gdk_dnd_set_drag_shape (drag_multiple->window, &hotspot,
|
||||||
@ -785,37 +779,9 @@ panel_drag_begin (GtkWidget *widget, GdkEvent *event, WPanel *panel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gdk_dnd_drag_begin (GdkWindow *initial_window)
|
panel_artificial_drag_start (GtkCList *window, GdkEventMotion *event)
|
||||||
{
|
{
|
||||||
GdkEventDragBegin tev;
|
artificial_drag_start (window->clist_window, event->x, event->y);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GtkWidget *
|
static GtkWidget *
|
||||||
|
@ -468,7 +468,7 @@ type/PDF
|
|||||||
type/executable
|
type/executable
|
||||||
Open=./%f
|
Open=./%f
|
||||||
View=%view
|
View=%view
|
||||||
Drop=./%f %q
|
Drop=%f %q
|
||||||
Execute in XTerm=xterm -e ./%f &
|
Execute in XTerm=xterm -e ./%f &
|
||||||
View Required Libraries=%view{ascii} ldd %f
|
View Required Libraries=%view{ascii} ldd %f
|
||||||
Strip binary=strip %f
|
Strip binary=strip %f
|
||||||
|
37
src/ext.c
37
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
|
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;
|
char *file_name;
|
||||||
FILE *cmd_file;
|
FILE *cmd_file;
|
||||||
@ -92,7 +120,7 @@ exec_extension (char *filename, char *data, char *drops, int *move_dir, int star
|
|||||||
time_t localmtime = 0;
|
time_t localmtime = 0;
|
||||||
struct stat mystat;
|
struct stat mystat;
|
||||||
int do_local_copy;
|
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 */
|
/* Avoid making a local copy if we are doing a cd */
|
||||||
if (!vfs_file_is_local(filename))
|
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);
|
text = (*quote_func) (filename, 0);
|
||||||
}
|
}
|
||||||
} else if (*data == 'q') {
|
} else if (*data == 'q') {
|
||||||
/* FIXME: currently broken */
|
text = quote_block (quote_func, drops);
|
||||||
/* text = (*quote_func) (drops, 0); */
|
|
||||||
} else
|
} else
|
||||||
text = expand_format (*data, !is_cd);
|
text = expand_format (*data, !is_cd);
|
||||||
if (!is_cd)
|
if (!is_cd)
|
||||||
@ -618,8 +645,6 @@ match_file_output:
|
|||||||
if (p < q) {
|
if (p < q) {
|
||||||
char *filename_copy = strdup (filename);
|
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);
|
exec_extension (filename_copy, r + 1, drops, move_dir, view_at_line_number);
|
||||||
free (filename_copy);
|
free (filename_copy);
|
||||||
|
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user