1998-10-30 03:47:54 +03:00
|
|
|
/* Desktop management for the Midnight Commander
|
|
|
|
*
|
|
|
|
* Copyright (C) 1998 The Free Software Foundation
|
1998-02-27 08:10:44 +03:00
|
|
|
*
|
1998-10-30 03:47:54 +03:00
|
|
|
* Authors: Federico Mena <federico@nuclecu.unam.mx>
|
|
|
|
* Miguel de Icaza <miguel@nuclecu.unam.mx>
|
1998-02-27 08:10:44 +03:00
|
|
|
*/
|
1998-11-07 04:19:53 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* TO-DO list for the desktop;
|
|
|
|
*
|
|
|
|
* - Put an InputOnly window over icons to be able to select them even if the user clicks on
|
|
|
|
* the transparent area.
|
|
|
|
*
|
|
|
|
* - DnD from file windows to icons.
|
|
|
|
*
|
|
|
|
* - DnD from icons to desktop (move icon).
|
|
|
|
*
|
|
|
|
* - DnD from icons to windows.
|
|
|
|
*
|
|
|
|
* - DnD from icons to icons (file->directory or file->executable).
|
|
|
|
*
|
|
|
|
* - Popup menus for icons.
|
|
|
|
*
|
|
|
|
* - Select icons with rubberband on the root window.
|
|
|
|
*
|
|
|
|
*/
|
1998-10-31 02:22:35 +03:00
|
|
|
#if 1
|
1998-10-30 03:47:54 +03:00
|
|
|
#include <config.h>
|
1998-11-02 10:26:19 +03:00
|
|
|
#include "fs.h"
|
1998-12-03 02:37:27 +03:00
|
|
|
#include <gdk/gdkx.h>
|
|
|
|
#include <gtk/gtkinvisible.h>
|
1998-10-30 03:47:54 +03:00
|
|
|
#include <gnome.h>
|
1998-10-31 02:22:35 +03:00
|
|
|
#include "dialog.h"
|
1998-10-30 03:47:54 +03:00
|
|
|
#include "gdesktop.h"
|
1998-10-31 02:22:35 +03:00
|
|
|
#include "gdesktop-icon.h"
|
1998-10-30 20:08:03 +03:00
|
|
|
#include "gmetadata.h"
|
1998-12-03 02:37:27 +03:00
|
|
|
#include "gdnd.h"
|
1998-11-25 06:29:23 +03:00
|
|
|
#include "gpopup.h"
|
1998-10-30 03:47:54 +03:00
|
|
|
#include "../vfs/vfs.h"
|
|
|
|
|
|
|
|
|
1998-11-07 04:19:53 +03:00
|
|
|
/* Name of the user's desktop directory (i.e. ~/desktop) */
|
1998-10-30 03:47:54 +03:00
|
|
|
#define DESKTOP_DIR_NAME "desktop"
|
|
|
|
|
|
|
|
|
1998-11-02 02:21:24 +03:00
|
|
|
/* Types of desktop icons */
|
|
|
|
enum icon_type {
|
|
|
|
ICON_FILE, /* Denotes a file (or symlink to a file) */
|
|
|
|
ICON_DIRECTORY /* Denotes a directory (or symlink to one) */
|
|
|
|
};
|
|
|
|
|
|
|
|
|
1998-10-30 03:47:54 +03:00
|
|
|
/* This structure defines the information carried by a desktop icon */
|
|
|
|
struct desktop_icon_info {
|
|
|
|
GtkWidget *dicon; /* The desktop icon widget */
|
|
|
|
int x, y; /* Position in the desktop */
|
1998-11-03 04:32:38 +03:00
|
|
|
int slot; /* Index of the slot the icon is in, or -1 for none */
|
1998-10-30 20:08:03 +03:00
|
|
|
char *filename; /* The file this icon refers to (relative to the desktop_directory) */
|
1998-11-02 02:21:24 +03:00
|
|
|
enum icon_type type; /* Type of icon, used to determine menu and DnD behavior */
|
1998-10-30 03:47:54 +03:00
|
|
|
int selected : 1; /* Is the icon selected? */
|
|
|
|
};
|
|
|
|
|
1998-11-03 04:32:38 +03:00
|
|
|
struct layout_slot {
|
|
|
|
int num_icons; /* Number of icons in this slot */
|
|
|
|
GList *icons; /* The list of icons in this slot */
|
|
|
|
};
|
|
|
|
|
1998-10-30 03:47:54 +03:00
|
|
|
|
1998-10-30 20:08:03 +03:00
|
|
|
/* Configuration options for the desktop */
|
|
|
|
|
1998-10-30 03:47:54 +03:00
|
|
|
int desktop_use_shaped_icons = TRUE;
|
1998-10-30 20:08:03 +03:00
|
|
|
int desktop_auto_placement = FALSE;
|
|
|
|
int desktop_snap_icons = FALSE;
|
1998-10-30 03:47:54 +03:00
|
|
|
|
|
|
|
/* The computed name of the user's desktop directory */
|
|
|
|
static char *desktop_directory;
|
|
|
|
|
1998-10-31 02:22:35 +03:00
|
|
|
/* Layout information: number of rows/columns for the layout slots, and the array of slots. Each
|
|
|
|
* slot is an integer that specifies the number of icons that belong to that slot.
|
|
|
|
*/
|
1998-10-30 03:47:54 +03:00
|
|
|
static int layout_cols;
|
|
|
|
static int layout_rows;
|
1998-11-03 04:32:38 +03:00
|
|
|
static struct layout_slot *layout_slots;
|
1998-10-30 03:47:54 +03:00
|
|
|
|
1998-11-03 19:29:47 +03:00
|
|
|
#define l_slots(u, v) (layout_slots[(u) * layout_rows + (v)])
|
1998-10-31 02:22:35 +03:00
|
|
|
|
1998-11-03 04:32:38 +03:00
|
|
|
/* The last icon to be selected */
|
|
|
|
static struct desktop_icon_info *last_selected_icon;
|
|
|
|
|
1998-12-03 02:37:27 +03:00
|
|
|
/* Drag and drop targets for the desktop */
|
|
|
|
static GtkTargetEntry dnd_targets[] = {
|
|
|
|
{ "text/uri-list", 0, TARGET_URI_LIST }
|
|
|
|
};
|
|
|
|
|
|
|
|
static int dnd_ntargets = sizeof (dnd_targets) / sizeof (dnd_targets[0]);
|
|
|
|
|
1998-12-04 05:08:06 +03:00
|
|
|
/* Proxy window for DnD on the root window */
|
1998-12-03 02:37:27 +03:00
|
|
|
static GtkWidget *dnd_proxy_window;
|
|
|
|
|
1998-10-31 02:22:35 +03:00
|
|
|
|
|
|
|
/* Looks for a free slot in the layout_slots array and returns the coordinates that coorespond to
|
|
|
|
* it. "Free" means it either has zero icons in it, or it has the minimum number of icons of all
|
|
|
|
* the slots.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
get_icon_auto_pos (int *x, int *y)
|
|
|
|
{
|
|
|
|
int min, min_x, min_y;
|
|
|
|
int u, v;
|
|
|
|
int val;
|
|
|
|
|
1998-11-03 04:32:38 +03:00
|
|
|
min = l_slots (0, 0).num_icons;
|
1998-10-31 02:22:35 +03:00
|
|
|
min_x = min_y = 0;
|
|
|
|
|
|
|
|
for (u = 0; u < layout_cols; u++)
|
|
|
|
for (v = 0; v < layout_rows; v++) {
|
1998-11-03 04:32:38 +03:00
|
|
|
val = l_slots (u, v).num_icons;
|
1998-10-31 02:22:35 +03:00
|
|
|
|
|
|
|
if (val == 0) {
|
|
|
|
/* Optimization: if it is zero, return immediately */
|
|
|
|
|
|
|
|
*x = u * DESKTOP_SNAP_X;
|
|
|
|
*y = v * DESKTOP_SNAP_Y;
|
|
|
|
return;
|
|
|
|
} else if (val < min) {
|
|
|
|
min = val;
|
|
|
|
min_x = u;
|
|
|
|
min_y = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*x = min_x * DESKTOP_SNAP_X;
|
|
|
|
*y = min_y * DESKTOP_SNAP_Y;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Snaps the specified position to the icon grid. It looks for the closest free spot on the grid,
|
|
|
|
* or the closest one that has the least number of icons in it.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
get_icon_snap_pos (int *x, int *y)
|
|
|
|
{
|
|
|
|
int min, min_x, min_y;
|
|
|
|
int min_dist;
|
|
|
|
int sx, sy;
|
|
|
|
int u, v;
|
|
|
|
int val, dist;
|
|
|
|
int dx, dy;
|
|
|
|
|
1998-11-03 04:32:38 +03:00
|
|
|
min = l_slots (0, 0).num_icons;
|
1998-10-31 02:22:35 +03:00
|
|
|
min_x = min_y = 0;
|
|
|
|
min_dist = INT_MAX;
|
|
|
|
|
1998-11-03 04:32:38 +03:00
|
|
|
sx = DESKTOP_SNAP_X * ((*x + DESKTOP_SNAP_X / 2) / DESKTOP_SNAP_X);
|
|
|
|
sy = DESKTOP_SNAP_Y * ((*y + DESKTOP_SNAP_Y / 2) / DESKTOP_SNAP_Y);
|
1998-10-31 02:22:35 +03:00
|
|
|
|
|
|
|
for (u = 0; u < layout_cols; u++)
|
|
|
|
for (v = 0; v < layout_rows; v++) {
|
1998-11-03 04:32:38 +03:00
|
|
|
val = l_slots (u, v).num_icons;
|
1998-10-31 02:22:35 +03:00
|
|
|
|
|
|
|
dx = sx - u;
|
|
|
|
dy = sy - v;
|
|
|
|
dist = dx * dx + dy * dy;
|
|
|
|
|
1998-11-03 19:29:47 +03:00
|
|
|
if ((val == min && dist < min_dist) || (val < min)) {
|
1998-10-31 02:22:35 +03:00
|
|
|
min_dist = dist;
|
|
|
|
min_x = u;
|
|
|
|
min_y = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*x = min_x * DESKTOP_SNAP_X;
|
|
|
|
*y = min_y * DESKTOP_SNAP_Y;
|
|
|
|
}
|
1998-10-30 03:47:54 +03:00
|
|
|
|
1998-11-03 04:32:38 +03:00
|
|
|
/* Removes an icon from the slot it is in, if any */
|
|
|
|
static void
|
|
|
|
remove_from_slot (struct desktop_icon_info *dii)
|
|
|
|
{
|
|
|
|
if (dii->slot == -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_assert (layout_slots[dii->slot].num_icons >= 1);
|
|
|
|
g_assert (layout_slots[dii->slot].icons != NULL);
|
|
|
|
|
|
|
|
layout_slots[dii->slot].num_icons--;
|
|
|
|
layout_slots[dii->slot].icons = g_list_remove (layout_slots[dii->slot].icons, dii);
|
|
|
|
}
|
|
|
|
|
1998-10-30 20:08:03 +03:00
|
|
|
/* Places a desktop icon. If auto_pos is true, then the function will look for a place to position
|
|
|
|
* the icon automatically, else it will use the specified coordinates, snapped to the grid if the
|
|
|
|
* global desktop_snap_icons flag is set.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
desktop_icon_info_place (struct desktop_icon_info *dii, int auto_pos, int xpos, int ypos)
|
|
|
|
{
|
1998-10-31 02:22:35 +03:00
|
|
|
int u, v;
|
1998-11-24 06:58:05 +03:00
|
|
|
char *filename;
|
1998-10-31 02:22:35 +03:00
|
|
|
|
|
|
|
if (auto_pos)
|
|
|
|
get_icon_auto_pos (&xpos, &ypos);
|
|
|
|
else if (desktop_snap_icons)
|
|
|
|
get_icon_snap_pos (&xpos, &ypos);
|
|
|
|
|
|
|
|
/* Increase the number of icons in the corresponding slot */
|
|
|
|
|
1998-11-03 04:32:38 +03:00
|
|
|
remove_from_slot (dii);
|
|
|
|
|
1998-10-31 02:22:35 +03:00
|
|
|
u = xpos / DESKTOP_SNAP_X;
|
|
|
|
v = ypos / DESKTOP_SNAP_Y;
|
1998-11-03 04:32:38 +03:00
|
|
|
|
|
|
|
dii->slot = u * layout_rows + v;
|
|
|
|
layout_slots[dii->slot].num_icons++;
|
|
|
|
layout_slots[dii->slot].icons = g_list_append (layout_slots[dii->slot].icons, dii);
|
1998-10-31 02:22:35 +03:00
|
|
|
|
|
|
|
/* Move the icon */
|
|
|
|
|
|
|
|
dii->x = xpos;
|
|
|
|
dii->y = ypos;
|
|
|
|
gtk_widget_set_uposition (dii->dicon, xpos, ypos);
|
1998-11-24 06:58:05 +03:00
|
|
|
|
|
|
|
/* Save the information */
|
|
|
|
|
|
|
|
filename = g_concat_dir_and_file (desktop_directory, dii->filename);
|
|
|
|
gmeta_set_icon_pos (filename, dii->x, dii->y);
|
|
|
|
g_free (filename);
|
1998-10-30 20:08:03 +03:00
|
|
|
}
|
|
|
|
|
1998-11-02 02:21:24 +03:00
|
|
|
/* Unselects all the desktop icons */
|
|
|
|
static void
|
|
|
|
unselect_all (void)
|
|
|
|
{
|
1998-11-03 04:32:38 +03:00
|
|
|
int i;
|
1998-11-02 02:21:24 +03:00
|
|
|
GList *l;
|
|
|
|
struct desktop_icon_info *dii;
|
|
|
|
|
1998-11-03 04:32:38 +03:00
|
|
|
for (i = 0; i < (layout_cols * layout_rows); i++)
|
|
|
|
for (l = layout_slots[i].icons; l; l = l->next) {
|
|
|
|
dii = l->data;
|
1998-11-02 02:21:24 +03:00
|
|
|
|
1998-11-03 04:32:38 +03:00
|
|
|
if (dii->selected) {
|
|
|
|
desktop_icon_select (DESKTOP_ICON (dii->dicon), FALSE);
|
|
|
|
dii->selected = FALSE;
|
|
|
|
}
|
1998-11-02 02:21:24 +03:00
|
|
|
}
|
1998-11-03 04:32:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Sets the selection state of a range to the specified value. The range starts at the
|
|
|
|
* last_selected_icon and ends at the specified icon.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
select_range (struct desktop_icon_info *dii, int sel)
|
|
|
|
{
|
1998-11-03 19:29:47 +03:00
|
|
|
int du, dv, lu, lv;
|
|
|
|
int min_u, min_v;
|
|
|
|
int max_u, max_v;
|
|
|
|
int u, v;
|
1998-11-03 04:32:38 +03:00
|
|
|
GList *l;
|
1998-11-03 19:29:47 +03:00
|
|
|
struct desktop_icon_info *ldii;
|
|
|
|
struct desktop_icon_info *min_udii, *min_vdii;
|
|
|
|
struct desktop_icon_info *max_udii, *max_vdii;
|
1998-11-03 04:32:38 +03:00
|
|
|
|
|
|
|
/* Find out the selection range */
|
|
|
|
|
|
|
|
if (!last_selected_icon)
|
|
|
|
last_selected_icon = dii;
|
|
|
|
|
1998-11-03 19:29:47 +03:00
|
|
|
du = dii->slot / layout_rows;
|
|
|
|
dv = dii->slot % layout_rows;
|
|
|
|
lu = last_selected_icon->slot / layout_rows;
|
|
|
|
lv = last_selected_icon->slot % layout_rows;
|
|
|
|
|
|
|
|
if (du < lu) {
|
|
|
|
min_u = du;
|
|
|
|
max_u = lu;
|
|
|
|
min_udii = dii;
|
|
|
|
max_udii = last_selected_icon;
|
1998-11-03 04:32:38 +03:00
|
|
|
} else {
|
1998-11-03 19:29:47 +03:00
|
|
|
min_u = lu;
|
|
|
|
max_u = du;
|
|
|
|
min_udii = last_selected_icon;
|
|
|
|
max_udii = dii;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dv < lv) {
|
|
|
|
min_v = dv;
|
|
|
|
max_v = lv;
|
|
|
|
min_vdii = dii;
|
|
|
|
max_vdii = last_selected_icon;
|
|
|
|
} else {
|
|
|
|
min_v = lv;
|
|
|
|
max_v = dv;
|
|
|
|
min_vdii = last_selected_icon;
|
|
|
|
max_vdii = dii;
|
1998-11-02 02:21:24 +03:00
|
|
|
}
|
1998-11-03 04:32:38 +03:00
|
|
|
|
1998-11-04 19:51:57 +03:00
|
|
|
/* Select all the icons in the rectangle */
|
1998-11-03 04:32:38 +03:00
|
|
|
|
1998-11-03 19:29:47 +03:00
|
|
|
for (u = min_u; u <= max_u; u++)
|
|
|
|
for (v = min_v; v <= max_v; v++)
|
|
|
|
for (l = l_slots (u, v).icons; l; l = l->next) {
|
|
|
|
ldii = l->data;
|
1998-11-03 04:32:38 +03:00
|
|
|
|
1998-11-03 19:29:47 +03:00
|
|
|
if ((u == min_u && ldii->x < min_udii->x)
|
|
|
|
|| (v == min_v && ldii->y < min_vdii->y)
|
|
|
|
|| (u == max_u && ldii->x > max_udii->x)
|
|
|
|
|| (v == max_v && ldii->y > max_vdii->y))
|
|
|
|
continue;
|
1998-11-03 04:32:38 +03:00
|
|
|
|
1998-11-03 19:29:47 +03:00
|
|
|
desktop_icon_select (DESKTOP_ICON (ldii->dicon), sel);
|
|
|
|
ldii->selected = sel;
|
|
|
|
}
|
1998-11-02 02:21:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Handles icon selection and unselection due to button presses */
|
|
|
|
static void
|
|
|
|
select_icon (struct desktop_icon_info *dii, GdkEventButton *event)
|
|
|
|
{
|
1998-11-03 04:32:38 +03:00
|
|
|
int range;
|
|
|
|
int additive;
|
|
|
|
|
|
|
|
range = ((event->state & GDK_SHIFT_MASK) != 0);
|
|
|
|
additive = ((event->state & GDK_CONTROL_MASK) != 0);
|
|
|
|
|
|
|
|
if (!additive)
|
1998-11-02 02:21:24 +03:00
|
|
|
unselect_all ();
|
1998-11-03 04:32:38 +03:00
|
|
|
|
|
|
|
if (!range) {
|
|
|
|
if (additive) {
|
|
|
|
desktop_icon_select (DESKTOP_ICON (dii->dicon), !dii->selected);
|
|
|
|
dii->selected = !dii->selected;
|
|
|
|
} else if (!dii->selected) {
|
|
|
|
desktop_icon_select (DESKTOP_ICON (dii->dicon), TRUE);
|
|
|
|
dii->selected = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
last_selected_icon = dii;
|
1998-11-04 19:51:57 +03:00
|
|
|
|
|
|
|
if (dii->selected)
|
|
|
|
gdk_window_raise (dii->dicon->window);
|
1998-11-03 04:32:38 +03:00
|
|
|
} else
|
|
|
|
select_range (dii, TRUE);
|
1998-11-02 02:21:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Handler for events on desktop icons. The on_text flag specifies whether the event ocurred on the
|
|
|
|
* text item in the icon or not.
|
|
|
|
*/
|
|
|
|
static gint
|
|
|
|
desktop_icon_info_event (struct desktop_icon_info *dii, GdkEvent *event, int on_text)
|
|
|
|
{
|
|
|
|
int retval;
|
1998-11-25 06:29:23 +03:00
|
|
|
char *filename;
|
1998-11-02 02:21:24 +03:00
|
|
|
|
|
|
|
retval = FALSE;
|
|
|
|
|
|
|
|
switch (event->type) {
|
|
|
|
case GDK_BUTTON_PRESS:
|
|
|
|
if ((event->button.button == 1) && !(on_text && dii->selected)) {
|
|
|
|
select_icon (dii, (GdkEventButton *) event);
|
|
|
|
retval = TRUE;
|
1998-11-25 06:29:23 +03:00
|
|
|
} else if (event->button.button == 3) {
|
|
|
|
filename = g_concat_dir_and_file (desktop_directory, dii->filename);
|
1998-12-02 09:33:07 +03:00
|
|
|
|
|
|
|
if (gpopup_do_popup ((GdkEventButton *) event, NULL, 0, filename) != -1)
|
|
|
|
; /* FIXME: reread the desktop if this returns something other than -1 */
|
|
|
|
|
1998-12-01 09:23:50 +03:00
|
|
|
g_free (filename);
|
1998-11-25 06:29:23 +03:00
|
|
|
retval = TRUE;
|
|
|
|
}
|
1998-11-02 02:21:24 +03:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GDK_2BUTTON_PRESS:
|
|
|
|
if (event->button.button != 1)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* FIXME: activate icon */
|
|
|
|
|
|
|
|
retval = TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we handled the event, do not pass it on to the icon text item */
|
|
|
|
|
|
|
|
if (on_text && retval)
|
|
|
|
gtk_signal_emit_stop_by_name (GTK_OBJECT (DESKTOP_ICON (dii->dicon)->text),
|
|
|
|
"event");
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handler for button presses on the images on desktop icons. The desktop icon info structure is
|
|
|
|
* passed in the user data.
|
|
|
|
*/
|
|
|
|
static gint
|
|
|
|
icon_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data)
|
|
|
|
{
|
|
|
|
return desktop_icon_info_event (data, event, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handler for button presses on the text on desktop icons. The desktop icon info structure is
|
|
|
|
* passed in the user data.
|
|
|
|
*/
|
|
|
|
static gint
|
|
|
|
text_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data)
|
|
|
|
{
|
|
|
|
return desktop_icon_info_event (data, event, TRUE);
|
|
|
|
}
|
|
|
|
|
1998-11-06 02:24:47 +03:00
|
|
|
/* Callback used when an icon's text changes. We must validate the rename and return the
|
|
|
|
* appropriate value. The desktop icon info structure is passed in the user data.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
text_changed (GnomeIconTextItem *iti, gpointer data)
|
|
|
|
{
|
|
|
|
struct desktop_icon_info *dii;
|
1998-11-07 04:19:53 +03:00
|
|
|
char *new_name;
|
1998-11-06 02:24:47 +03:00
|
|
|
char *source;
|
|
|
|
char *dest;
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
dii = data;
|
|
|
|
|
|
|
|
source = g_concat_dir_and_file (desktop_directory, dii->filename);
|
1998-11-07 04:19:53 +03:00
|
|
|
new_name = gnome_icon_text_item_get_text (iti);
|
|
|
|
dest = g_concat_dir_and_file (desktop_directory, new_name);
|
1998-11-06 02:24:47 +03:00
|
|
|
|
1998-11-07 04:19:53 +03:00
|
|
|
if (mc_rename (source, dest) == 0) {
|
|
|
|
g_free (dii->filename);
|
|
|
|
dii->filename = g_strdup (new_name);
|
1998-11-06 02:24:47 +03:00
|
|
|
retval = TRUE;
|
1998-11-07 04:19:53 +03:00
|
|
|
} else
|
1998-11-06 02:24:47 +03:00
|
|
|
retval = FALSE; /* FIXME: maybe pop up a warning/query dialog? */
|
|
|
|
|
|
|
|
g_free (source);
|
|
|
|
g_free (dest);
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
1998-11-05 02:01:24 +03:00
|
|
|
/* Callback used when the user begins editing the icon text item in a desktop icon. It installs the
|
|
|
|
* mouse and keyboard grabs that are required while an icon is being edited.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
editing_started (GnomeIconTextItem *iti, gpointer data)
|
|
|
|
{
|
|
|
|
struct desktop_icon_info *dii;
|
|
|
|
GdkCursor *ibeam;
|
|
|
|
|
|
|
|
dii = data;
|
|
|
|
|
|
|
|
ibeam = gdk_cursor_new (GDK_XTERM);
|
|
|
|
gdk_pointer_grab (GTK_LAYOUT (DESKTOP_ICON (dii->dicon)->canvas)->bin_window,
|
|
|
|
FALSE,
|
|
|
|
(GDK_BUTTON_PRESS_MASK
|
|
|
|
| GDK_BUTTON_RELEASE_MASK
|
|
|
|
| GDK_POINTER_MOTION_MASK
|
|
|
|
| GDK_ENTER_NOTIFY_MASK
|
|
|
|
| GDK_LEAVE_NOTIFY_MASK),
|
|
|
|
NULL,
|
|
|
|
ibeam,
|
|
|
|
GDK_CURRENT_TIME);
|
|
|
|
gdk_cursor_destroy (ibeam);
|
|
|
|
|
|
|
|
gdk_keyboard_grab (GTK_LAYOUT (DESKTOP_ICON (dii->dicon)->canvas)->bin_window, FALSE, GDK_CURRENT_TIME);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Callback used when the user finishes editing the icon text item in a desktop icon. It removes
|
|
|
|
* the mouse and keyboard grabs.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
editing_stopped (GnomeIconTextItem *iti, gpointer data)
|
|
|
|
{
|
|
|
|
gdk_pointer_ungrab (GDK_CURRENT_TIME);
|
|
|
|
gdk_keyboard_ungrab (GDK_CURRENT_TIME);
|
|
|
|
}
|
|
|
|
|
1998-10-30 03:47:54 +03:00
|
|
|
/* Creates a new desktop icon. The filename is the pruned filename inside the desktop directory.
|
|
|
|
* If auto_pos is true, then the function will look for a place to position the icon automatically,
|
1998-10-31 02:22:35 +03:00
|
|
|
* else it will use the specified coordinates. It does not show the icon.
|
1998-10-30 03:47:54 +03:00
|
|
|
*/
|
1998-10-31 02:22:35 +03:00
|
|
|
static struct desktop_icon_info *
|
1998-10-30 03:47:54 +03:00
|
|
|
desktop_icon_info_new (char *filename, int auto_pos, int xpos, int ypos)
|
|
|
|
{
|
1998-10-30 20:08:03 +03:00
|
|
|
struct desktop_icon_info *dii;
|
|
|
|
char *full_name;
|
|
|
|
char *icon_name;
|
1998-11-02 02:21:24 +03:00
|
|
|
struct stat s;
|
1998-10-30 20:08:03 +03:00
|
|
|
|
|
|
|
full_name = g_concat_dir_and_file (desktop_directory, filename);
|
1998-11-02 02:21:24 +03:00
|
|
|
|
1998-12-04 05:08:06 +03:00
|
|
|
if (mc_lstat (full_name, &s) != 0) {
|
1998-11-02 02:21:24 +03:00
|
|
|
g_warning ("Could not stat %s; will not use a desktop icon", full_name);
|
|
|
|
g_free (full_name);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create the icon structure */
|
|
|
|
|
1998-11-24 01:09:58 +03:00
|
|
|
icon_name = gmeta_get_icon_for_file (full_name);
|
1998-10-30 20:08:03 +03:00
|
|
|
|
|
|
|
dii = g_new (struct desktop_icon_info, 1);
|
1998-10-31 02:22:35 +03:00
|
|
|
dii->dicon = desktop_icon_new (icon_name, filename);
|
1998-11-03 04:32:38 +03:00
|
|
|
dii->x = 0;
|
|
|
|
dii->y = 0;
|
|
|
|
dii->slot = -1;
|
1998-10-30 20:08:03 +03:00
|
|
|
dii->filename = g_strdup (filename);
|
1998-11-02 02:21:24 +03:00
|
|
|
dii->type = S_ISDIR (s.st_mode) ? ICON_DIRECTORY : ICON_FILE;
|
1998-10-30 20:08:03 +03:00
|
|
|
dii->selected = FALSE;
|
|
|
|
|
|
|
|
g_free (full_name);
|
|
|
|
g_free (icon_name);
|
|
|
|
|
1998-11-02 02:21:24 +03:00
|
|
|
/* Connect to the icon's signals */
|
|
|
|
|
|
|
|
gtk_signal_connect (GTK_OBJECT (DESKTOP_ICON (dii->dicon)->icon), "event",
|
|
|
|
(GtkSignalFunc) icon_event,
|
|
|
|
dii);
|
|
|
|
gtk_signal_connect (GTK_OBJECT (DESKTOP_ICON (dii->dicon)->text), "event",
|
|
|
|
(GtkSignalFunc) text_event,
|
|
|
|
dii);
|
|
|
|
gtk_signal_connect (GTK_OBJECT (DESKTOP_ICON (dii->dicon)->stipple), "event",
|
|
|
|
(GtkSignalFunc) icon_event,
|
|
|
|
dii);
|
1998-10-31 02:22:35 +03:00
|
|
|
|
1998-11-05 02:01:24 +03:00
|
|
|
/* Connect to the text item's signals */
|
|
|
|
|
1998-11-06 02:24:47 +03:00
|
|
|
gtk_signal_connect (GTK_OBJECT (DESKTOP_ICON (dii->dicon)->text), "text_changed",
|
|
|
|
(GtkSignalFunc) text_changed,
|
|
|
|
dii);
|
1998-11-05 02:01:24 +03:00
|
|
|
gtk_signal_connect (GTK_OBJECT (DESKTOP_ICON (dii->dicon)->text), "editing_started",
|
|
|
|
(GtkSignalFunc) editing_started,
|
|
|
|
dii);
|
|
|
|
gtk_signal_connect (GTK_OBJECT (DESKTOP_ICON (dii->dicon)->text), "editing_stopped",
|
|
|
|
(GtkSignalFunc) editing_stopped,
|
|
|
|
dii);
|
|
|
|
|
1998-11-02 02:21:24 +03:00
|
|
|
/* Place the icon and append it to the list */
|
|
|
|
|
|
|
|
desktop_icon_info_place (dii, auto_pos, xpos, ypos);
|
1998-10-31 02:22:35 +03:00
|
|
|
return dii;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Frees a desktop icon information structure, and destroy the icon widget. Does not remove the
|
|
|
|
* structure from the desktop_icons list!
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
desktop_icon_info_free (struct desktop_icon_info *dii)
|
|
|
|
{
|
|
|
|
gtk_widget_destroy (dii->dicon);
|
1998-11-03 04:32:38 +03:00
|
|
|
remove_from_slot (dii);
|
1998-10-31 02:22:35 +03:00
|
|
|
|
|
|
|
g_free (dii->filename);
|
|
|
|
g_free (dii);
|
1998-10-30 03:47:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Creates the layout information array */
|
|
|
|
static void
|
|
|
|
create_layout_info (void)
|
|
|
|
{
|
1998-10-31 02:22:35 +03:00
|
|
|
layout_cols = (gdk_screen_width () + DESKTOP_SNAP_X - 1) / DESKTOP_SNAP_X;
|
|
|
|
layout_rows = (gdk_screen_height () + DESKTOP_SNAP_Y - 1) / DESKTOP_SNAP_Y;
|
1998-11-03 04:32:38 +03:00
|
|
|
layout_slots = g_new0 (struct layout_slot, layout_cols * layout_rows);
|
1998-10-30 03:47:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check that the user's desktop directory exists, and if not, create it with a symlink to the
|
|
|
|
* user's home directory so that an icon will be displayed.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
create_desktop_dir (void)
|
|
|
|
{
|
|
|
|
char *home_link_name;
|
|
|
|
|
|
|
|
desktop_directory = g_concat_dir_and_file (gnome_user_home_dir, DESKTOP_DIR_NAME);
|
|
|
|
|
|
|
|
if (!g_file_exists (desktop_directory)) {
|
|
|
|
/* Create the directory */
|
|
|
|
|
|
|
|
mkdir (desktop_directory, 0777);
|
|
|
|
|
|
|
|
/* Create the link to the user's home directory so that he will have an icon */
|
|
|
|
|
|
|
|
home_link_name = g_concat_dir_and_file (desktop_directory, _("Home directory"));
|
|
|
|
|
|
|
|
if (mc_symlink (gnome_user_home_dir, home_link_name) != 0) {
|
|
|
|
message (FALSE,
|
|
|
|
_("Warning"),
|
|
|
|
_("Could not symlink %s to %s; will not have initial desktop icons."),
|
|
|
|
gnome_user_home_dir, home_link_name);
|
|
|
|
g_free (home_link_name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (home_link_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-12-04 05:08:06 +03:00
|
|
|
/* Returns TRUE if there is already an icon in the desktop for the specified filename, FALSE otherwise. */
|
|
|
|
static int
|
|
|
|
icon_exists (char *filename)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
GList *l;
|
|
|
|
struct desktop_icon_info *dii;
|
|
|
|
|
|
|
|
for (i = 0; i < (layout_cols * layout_rows); i++)
|
|
|
|
for (l = layout_slots[i].icons; l; l = l->next) {
|
|
|
|
dii = l->data;
|
|
|
|
if (strcmp (filename, dii->filename) == 0)
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Reads the ~/Desktop directory and creates the desktop icons. If incremental is TRUE, then an
|
|
|
|
* icon will not be created for a file if there is already an icon for it, and icons will be created
|
|
|
|
* starting at the specified position.
|
|
|
|
*/
|
1998-10-30 03:47:54 +03:00
|
|
|
static void
|
1998-12-04 05:08:06 +03:00
|
|
|
load_desktop_icons (int incremental, int xpos, int ypos)
|
1998-10-30 03:47:54 +03:00
|
|
|
{
|
|
|
|
struct dirent *dirent;
|
|
|
|
DIR *dir;
|
1998-10-30 20:08:03 +03:00
|
|
|
char *full_name;
|
1998-10-30 03:47:54 +03:00
|
|
|
int have_pos, x, y;
|
1998-10-31 02:22:35 +03:00
|
|
|
struct desktop_icon_info *dii;
|
1998-12-04 05:08:06 +03:00
|
|
|
GSList *need_position_list, *l;
|
1998-10-30 03:47:54 +03:00
|
|
|
|
|
|
|
dir = mc_opendir (desktop_directory);
|
|
|
|
if (!dir) {
|
|
|
|
message (FALSE,
|
|
|
|
_("Warning"),
|
|
|
|
_("Could not open %s; will not have initial desktop icons"),
|
|
|
|
desktop_directory);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1998-12-04 05:08:06 +03:00
|
|
|
/* First create the icons for all the files that do have their icon position set. Build a
|
|
|
|
* list of the icons that do not have their position set.
|
|
|
|
*/
|
|
|
|
|
|
|
|
need_position_list = NULL;
|
|
|
|
|
1998-10-30 03:47:54 +03:00
|
|
|
while ((dirent = mc_readdir (dir)) != NULL) {
|
|
|
|
if (((dirent->d_name[0] == '.') && (dirent->d_name[1] == 0))
|
|
|
|
|| ((dirent->d_name[0] == '.') && (dirent->d_name[1] == '.') && (dirent->d_name[2] == 0)))
|
|
|
|
continue;
|
|
|
|
|
1998-12-04 05:08:06 +03:00
|
|
|
if (incremental && icon_exists (dirent->d_name))
|
|
|
|
continue;
|
|
|
|
|
1998-10-30 20:08:03 +03:00
|
|
|
full_name = g_concat_dir_and_file (desktop_directory, dirent->d_name);
|
|
|
|
|
1998-11-24 01:09:58 +03:00
|
|
|
have_pos = gmeta_get_icon_pos (full_name, &x, &y);
|
1998-10-30 20:08:03 +03:00
|
|
|
|
1998-12-04 05:08:06 +03:00
|
|
|
if (have_pos) {
|
|
|
|
dii = desktop_icon_info_new (dirent->d_name, FALSE, x, y);
|
|
|
|
gtk_widget_show (dii->dicon);
|
|
|
|
|
|
|
|
g_free (full_name);
|
|
|
|
} else
|
|
|
|
need_position_list = g_slist_prepend (need_position_list, g_strdup (dirent->d_name));
|
1998-10-30 03:47:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
mc_closedir (dir);
|
1998-10-31 02:22:35 +03:00
|
|
|
|
1998-12-04 05:08:06 +03:00
|
|
|
/* Now create the icons for all the files that did not have their position set. This makes
|
|
|
|
* auto-placement work correctly without overlapping icons.
|
|
|
|
*/
|
1998-10-31 02:22:35 +03:00
|
|
|
|
1998-12-04 05:08:06 +03:00
|
|
|
need_position_list = g_slist_reverse (need_position_list);
|
|
|
|
|
|
|
|
for (l = need_position_list; l; l = l->next) {
|
|
|
|
dii = desktop_icon_info_new (l->data, FALSE, xpos, ypos);
|
|
|
|
gtk_widget_show (dii->dicon);
|
|
|
|
g_free (l->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_slist_free (need_position_list);
|
1998-10-30 03:47:54 +03:00
|
|
|
}
|
|
|
|
|
1998-12-03 02:37:27 +03:00
|
|
|
/* Destroys all the current desktop icons */
|
|
|
|
static void
|
|
|
|
destroy_desktop_icons (void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
GList *l;
|
|
|
|
struct desktop_icon_info *dii;
|
|
|
|
|
|
|
|
for (i = 0; i < (layout_cols * layout_rows); i++) {
|
|
|
|
l = layout_slots[i].icons;
|
|
|
|
|
|
|
|
while (l) {
|
|
|
|
dii = l->data;
|
|
|
|
l = l->next;
|
|
|
|
|
|
|
|
desktop_icon_info_free (dii);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-12-04 05:08:06 +03:00
|
|
|
/* Reloads the desktop icons. If incremental is TRUE, then the existing icons will not be destroyed
|
|
|
|
* first, and the new icons will be put at the specified position.
|
|
|
|
*/
|
1998-12-03 02:37:27 +03:00
|
|
|
static void
|
1998-12-04 05:08:06 +03:00
|
|
|
reload_desktop_icons (int incremental, int x, int y)
|
1998-12-03 02:37:27 +03:00
|
|
|
{
|
1998-12-04 05:08:06 +03:00
|
|
|
if (!incremental)
|
|
|
|
destroy_desktop_icons ();
|
|
|
|
|
|
|
|
load_desktop_icons (incremental, x, y);
|
1998-12-03 02:37:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Sets up a proxy window for DnD on the specified X window. Courtesy of Owen Taylor */
|
|
|
|
static gboolean
|
|
|
|
setup_xdnd_proxy (guint32 xid, GdkWindow *proxy_window)
|
|
|
|
{
|
|
|
|
GdkAtom xdnd_proxy_atom;
|
|
|
|
guint32 proxy_xid;
|
|
|
|
Atom type;
|
|
|
|
int format;
|
|
|
|
unsigned long nitems, after;
|
|
|
|
Window *proxy_data;
|
|
|
|
Window proxy;
|
|
|
|
guint32 old_warnings;
|
|
|
|
|
|
|
|
XGrabServer (GDK_DISPLAY ());
|
|
|
|
|
|
|
|
xdnd_proxy_atom = gdk_atom_intern ("XdndProxy", FALSE);
|
|
|
|
proxy_xid = GDK_WINDOW_XWINDOW (proxy_window);
|
|
|
|
type = None;
|
|
|
|
proxy = None;
|
|
|
|
|
|
|
|
old_warnings = gdk_error_warnings;
|
|
|
|
|
|
|
|
gdk_error_code = 0;
|
|
|
|
gdk_error_warnings = 0;
|
|
|
|
|
|
|
|
/* Check if somebody else already owns drops on the root window */
|
|
|
|
|
|
|
|
XGetWindowProperty (GDK_DISPLAY (), xid,
|
|
|
|
xdnd_proxy_atom, 0,
|
|
|
|
1, False, AnyPropertyType,
|
|
|
|
&type, &format, &nitems, &after,
|
|
|
|
(guchar **) &proxy_data);
|
|
|
|
|
|
|
|
if (type != None) {
|
|
|
|
if ((format == 32) && (nitems == 1))
|
|
|
|
proxy = *proxy_data;
|
|
|
|
|
|
|
|
XFree (proxy_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The property was set, now check if the window it points to exists and has a XdndProxy
|
|
|
|
* property pointing to itself.
|
|
|
|
*/
|
|
|
|
if (proxy) {
|
|
|
|
XGetWindowProperty (GDK_DISPLAY (), proxy,
|
|
|
|
xdnd_proxy_atom, 0,
|
|
|
|
1, False, AnyPropertyType,
|
|
|
|
&type, &format, &nitems, &after,
|
|
|
|
(guchar **) &proxy_data);
|
|
|
|
|
|
|
|
if (!gdk_error_code && type != None) {
|
|
|
|
if ((format == 32) && (nitems == 1))
|
|
|
|
if (*proxy_data != proxy)
|
|
|
|
proxy = GDK_NONE;
|
|
|
|
|
|
|
|
XFree (proxy_data);
|
|
|
|
} else
|
|
|
|
proxy = GDK_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!proxy) {
|
|
|
|
/* OK, we can set the property to point to us */
|
|
|
|
|
|
|
|
XChangeProperty (GDK_DISPLAY (), xid,
|
|
|
|
xdnd_proxy_atom, gdk_atom_intern ("WINDOW", FALSE),
|
|
|
|
32, PropModeReplace,
|
|
|
|
(guchar *) &proxy_xid, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
gdk_error_code = 0;
|
|
|
|
gdk_error_warnings = old_warnings;
|
|
|
|
|
|
|
|
XUngrabServer (GDK_DISPLAY ());
|
|
|
|
|
|
|
|
if (!proxy) {
|
|
|
|
/* Mark our window as a valid proxy window with a XdndProxy
|
|
|
|
* property pointing recursively;
|
|
|
|
*/
|
|
|
|
XChangeProperty (GDK_DISPLAY (), proxy_xid,
|
|
|
|
xdnd_proxy_atom, gdk_atom_intern ("WINDOW", FALSE),
|
|
|
|
32, PropModeReplace,
|
|
|
|
(guchar *) &proxy_xid, 1);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
} else
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Callback used when the root window receives a drop */
|
1998-12-03 19:11:01 +03:00
|
|
|
static void
|
1998-12-03 02:37:27 +03:00
|
|
|
drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x, gint y,
|
|
|
|
GtkSelectionData *data, guint info, guint time, gpointer user_data)
|
|
|
|
{
|
1998-12-04 05:08:06 +03:00
|
|
|
int retval;
|
|
|
|
gint dx, dy;
|
|
|
|
|
1998-12-03 02:37:27 +03:00
|
|
|
switch (info) {
|
|
|
|
case TARGET_URI_LIST:
|
1998-12-04 05:08:06 +03:00
|
|
|
/* Fix the proxy window offsets */
|
|
|
|
gdk_window_get_position (widget->window, &dx, &dy);
|
|
|
|
x += dx;
|
|
|
|
y += dy;
|
|
|
|
|
|
|
|
/* Drop! */
|
|
|
|
|
|
|
|
retval = gdnd_drop_on_directory (context, data, desktop_directory);
|
|
|
|
|
|
|
|
if (retval)
|
|
|
|
reload_desktop_icons (TRUE, x, y);
|
1998-12-03 02:37:27 +03:00
|
|
|
|
|
|
|
/* FIXME: return TRUE for delete if appropriate */
|
1998-12-04 05:08:06 +03:00
|
|
|
gtk_drag_finish (context, retval, FALSE, time);
|
1998-12-03 02:37:27 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_drag_finish (context, FALSE, FALSE, time);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sets up drag and drop to the desktop root window */
|
|
|
|
static void
|
|
|
|
setup_desktop_dnd (void)
|
|
|
|
{
|
|
|
|
dnd_proxy_window = gtk_invisible_new ();
|
|
|
|
gtk_widget_show (dnd_proxy_window);
|
|
|
|
|
|
|
|
if (!setup_xdnd_proxy (GDK_ROOT_WINDOW (), dnd_proxy_window->window))
|
|
|
|
g_warning ("Eeeeek, some moron is already taking drops on the root window!");
|
|
|
|
|
|
|
|
gtk_drag_dest_set (dnd_proxy_window,
|
1998-12-04 05:08:06 +03:00
|
|
|
GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
|
1998-12-03 02:37:27 +03:00
|
|
|
dnd_targets, dnd_ntargets,
|
1998-12-04 05:08:06 +03:00
|
|
|
GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK);
|
1998-12-03 02:37:27 +03:00
|
|
|
|
|
|
|
gtk_signal_connect (GTK_OBJECT (dnd_proxy_window), "drag_data_received",
|
|
|
|
GTK_SIGNAL_FUNC (drag_data_received), NULL);
|
|
|
|
}
|
|
|
|
|
1998-10-30 03:47:54 +03:00
|
|
|
/**
|
|
|
|
* desktop_init
|
|
|
|
*
|
|
|
|
* Initializes the desktop by setting up the default icons (if necessary), setting up drag and drop,
|
|
|
|
* and other miscellaneous tasks.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
desktop_init (void)
|
|
|
|
{
|
|
|
|
create_layout_info ();
|
|
|
|
create_desktop_dir ();
|
1998-12-04 05:08:06 +03:00
|
|
|
load_desktop_icons (FALSE, 0, 0);
|
1998-12-03 02:37:27 +03:00
|
|
|
setup_desktop_dnd ();
|
1998-10-30 03:47:54 +03:00
|
|
|
}
|
|
|
|
|
1998-11-03 04:32:38 +03:00
|
|
|
/**
|
|
|
|
* desktop_destroy
|
1998-10-30 03:47:54 +03:00
|
|
|
*
|
|
|
|
* Shuts the desktop down by destroying the desktop icons.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
desktop_destroy (void)
|
|
|
|
{
|
|
|
|
/* Destroy the desktop icons */
|
|
|
|
|
1998-12-03 02:37:27 +03:00
|
|
|
destroy_desktop_icons ();
|
1998-10-30 03:47:54 +03:00
|
|
|
|
|
|
|
/* Cleanup */
|
|
|
|
|
|
|
|
g_free (layout_slots);
|
|
|
|
layout_slots = NULL;
|
|
|
|
layout_cols = 0;
|
|
|
|
layout_rows = 0;
|
|
|
|
|
|
|
|
g_free (desktop_directory);
|
|
|
|
desktop_directory = NULL;
|
1998-12-03 02:37:27 +03:00
|
|
|
|
|
|
|
/* Remove DnD crap */
|
|
|
|
|
|
|
|
gtk_widget_destroy (dnd_proxy_window);
|
|
|
|
XDeleteProperty (GDK_DISPLAY (), GDK_ROOT_WINDOW (), gdk_atom_intern ("XdndProxy", FALSE));
|
1998-10-30 03:47:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1998-11-28 06:12:13 +03:00
|
|
|
#if 0
|
1998-11-24 01:09:58 +03:00
|
|
|
/* Stubs for filegui.h */
|
|
|
|
|
|
|
|
#include "file.h"
|
|
|
|
#include "panel.h"
|
|
|
|
|
|
|
|
FileProgressStatus
|
|
|
|
file_progress_show_source (char *path)
|
|
|
|
{
|
1998-11-28 06:12:13 +03:00
|
|
|
g_warning ("file_progres_show_source: Implement this function!\n");
|
1998-11-24 01:09:58 +03:00
|
|
|
return FILE_CONT;
|
|
|
|
}
|
|
|
|
|
|
|
|
FileProgressStatus
|
|
|
|
file_progress_show_target (char *path)
|
|
|
|
{
|
1998-11-28 06:12:13 +03:00
|
|
|
g_warning ("file_progres_show_target: Implement this function!\n");
|
1998-11-24 01:09:58 +03:00
|
|
|
return FILE_CONT;
|
|
|
|
}
|
|
|
|
|
|
|
|
FileProgressStatus
|
|
|
|
file_progress_show_deleting (char *path)
|
|
|
|
{
|
1998-11-28 06:12:13 +03:00
|
|
|
g_warning ("file_progress_show_deleting: Implement this function!\n");
|
1998-11-24 01:09:58 +03:00
|
|
|
return FILE_CONT;
|
|
|
|
}
|
|
|
|
|
|
|
|
FileProgressStatus
|
|
|
|
file_progress_show (long done, long total)
|
|
|
|
{
|
1998-11-28 06:12:13 +03:00
|
|
|
g_warning ("file-progress_show; Implement this function!\n");
|
1998-11-24 01:09:58 +03:00
|
|
|
return FILE_CONT;
|
|
|
|
}
|
|
|
|
|
|
|
|
FileProgressStatus
|
|
|
|
file_progress_show_count (long done, long total)
|
|
|
|
{
|
1998-11-28 06:12:13 +03:00
|
|
|
g_warning ("file_progress_show_count: Implement this function!\n");
|
1998-11-24 01:09:58 +03:00
|
|
|
return FILE_CONT;
|
|
|
|
}
|
|
|
|
|
|
|
|
FileProgressStatus
|
|
|
|
file_progress_show_bytes (long done, long total)
|
|
|
|
{
|
1998-11-28 06:12:13 +03:00
|
|
|
g_warning ("file_progress_show_bytes: Implement this function!\n");
|
1998-11-24 01:09:58 +03:00
|
|
|
return FILE_CONT;
|
|
|
|
}
|
|
|
|
|
|
|
|
FileProgressStatus
|
|
|
|
file_progress_real_query_replace (enum OperationMode mode, char *destname, struct stat *_s_stat, struct stat *_d_stat)
|
|
|
|
{
|
1998-11-28 06:12:13 +03:00
|
|
|
g_warning ("file_progress_real_query_replace: Implement this function!\n");
|
1998-11-24 01:09:58 +03:00
|
|
|
return FILE_CONT;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
file_progress_set_stalled_label (char *stalled_msg)
|
|
|
|
{
|
1998-11-28 06:12:13 +03:00
|
|
|
g_warning ("file_progress_set_stalled_label: Implement this function!\n");
|
1998-11-24 01:09:58 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
panel_operate_generate_prompt (char* cmd_buf, WPanel* panel, int operation, int only_one, struct stat* src_stat)
|
|
|
|
{
|
1998-11-28 06:12:13 +03:00
|
|
|
g_warning ("panel_opreate_create_prompt: Implement this function!\n");
|
1998-11-24 01:09:58 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
file_mask_dialog (FileOperation operation, char *text, char *def_text, int only_one, int *do_background)
|
|
|
|
{
|
1998-11-28 06:12:13 +03:00
|
|
|
g_warning ("file_mask_dialog: Implement this function!\n");
|
1998-11-24 01:09:58 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
create_op_win (FileOperation op, int with_eta)
|
|
|
|
{
|
1998-11-28 06:12:13 +03:00
|
|
|
g_warning ("create_op_win: Implement this function!\n");
|
1998-11-24 01:09:58 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
destroy_op_win (void)
|
|
|
|
{
|
1998-11-28 06:12:13 +03:00
|
|
|
g_warning ("destory_op_win: Implement this function!\n");
|
1998-11-24 01:09:58 +03:00
|
|
|
}
|
1998-10-30 03:47:54 +03:00
|
|
|
|
1998-11-24 01:09:58 +03:00
|
|
|
#endif
|
1998-10-30 03:47:54 +03:00
|
|
|
|
|
|
|
|
1998-12-02 09:33:07 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
1998-10-30 03:47:54 +03:00
|
|
|
#else
|
|
|
|
|
1998-02-27 08:10:44 +03:00
|
|
|
#include <config.h>
|
1998-10-30 20:51:28 +03:00
|
|
|
#include "fs.h"
|
1998-02-27 08:10:44 +03:00
|
|
|
#include <gnome.h>
|
1998-10-28 22:31:04 +03:00
|
|
|
#include "gdesktop-icon.h"
|
1998-02-27 08:10:44 +03:00
|
|
|
#include "gdesktop.h"
|
|
|
|
#include "../vfs/vfs.h"
|
|
|
|
#include <string.h>
|
1998-08-21 02:04:52 +04:00
|
|
|
#include "mad.h"
|
1998-02-27 08:10:44 +03:00
|
|
|
#include "main.h"
|
|
|
|
#include "file.h"
|
|
|
|
#include "global.h"
|
1998-03-04 09:28:35 +03:00
|
|
|
#include "panel.h"
|
|
|
|
#include "gscreen.h"
|
1998-03-16 22:09:24 +03:00
|
|
|
#include "ext.h"
|
1998-03-20 05:00:09 +03:00
|
|
|
#include "dialog.h"
|
|
|
|
#include "gpageprop.h"
|
1998-03-04 09:28:35 +03:00
|
|
|
#include <gdk/gdkx.h>
|
1998-03-19 05:57:01 +03:00
|
|
|
#include <gdk/gdkprivate.h>
|
1998-04-17 04:59:58 +04:00
|
|
|
#include "gcache.h"
|
|
|
|
#include "gmain.h"
|
1998-02-27 08:10:44 +03:00
|
|
|
|
1998-04-15 07:16:29 +04:00
|
|
|
/* places used in the grid */
|
|
|
|
static char *spot_array;
|
|
|
|
|
|
|
|
/* number of icons that fit along the x and y axis */
|
|
|
|
static int x_spots, y_spots;
|
|
|
|
|
1998-03-04 03:56:14 +03:00
|
|
|
/* operations on drops */
|
|
|
|
enum {
|
|
|
|
OPER_COPY,
|
|
|
|
OPER_MOVE,
|
|
|
|
OPER_LINK
|
|
|
|
};
|
|
|
|
|
1998-03-17 11:27:10 +03:00
|
|
|
/* The X11 root window */
|
|
|
|
static GnomeRootWin *root_window;
|
|
|
|
|
1998-04-15 07:16:29 +04:00
|
|
|
|
1998-03-18 09:24:20 +03:00
|
|
|
/* The full name of the desktop directory ~/desktop */
|
|
|
|
char *desktop_directory;
|
|
|
|
|
1998-06-03 18:08:47 +04:00
|
|
|
static void desktop_reload (char *desktop_dir, GdkPoint *drop_position);
|
1998-03-20 05:00:09 +03:00
|
|
|
static void desktop_icon_context_popup (GdkEventButton *event, desktop_icon_t *di);
|
1998-03-18 09:24:20 +03:00
|
|
|
|
|
|
|
/* The list with the filenames we have actually loaded */
|
|
|
|
static GList *desktop_icons;
|
|
|
|
|
1998-03-19 05:57:01 +03:00
|
|
|
#define ELEMENTS(x) (sizeof (x) / sizeof (x[0]))
|
|
|
|
|
1998-04-15 07:16:29 +04:00
|
|
|
static void
|
|
|
|
init_spot_list (void)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
|
|
|
|
x_spots = gdk_screen_width () / SNAP_X;
|
|
|
|
y_spots = gdk_screen_height () / SNAP_Y;
|
|
|
|
size = (x_spots * y_spots) / 8;
|
|
|
|
spot_array = xmalloc (size+1, "spot_array");
|
|
|
|
memset (spot_array, 0, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
is_spot_set (int x, int y)
|
|
|
|
{
|
|
|
|
int o = (x * x_spots + y);
|
|
|
|
int idx = o / 8;
|
|
|
|
int bit = o % 8;
|
|
|
|
|
|
|
|
return spot_array [idx] & (1 << bit);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_spot_val (int x, int y, int set)
|
|
|
|
{
|
|
|
|
int o = (x * x_spots + y);
|
|
|
|
int idx = o / 8;
|
|
|
|
int bit = o % 8;
|
|
|
|
|
|
|
|
if (set)
|
|
|
|
spot_array [idx] |= (1 << bit);
|
|
|
|
else
|
|
|
|
spot_array [idx] &= ~(1 << bit);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
allocate_free_spot (int *rx, int *ry)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
for (x = 0; x < x_spots; x++)
|
|
|
|
for (y = 0; y < y_spots; y++)
|
|
|
|
if (!is_spot_set (x, y)){
|
|
|
|
*rx = x;
|
|
|
|
*ry = y;
|
|
|
|
set_spot_val (x, y, 1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
snap_to (desktop_icon_t *di, int absolute, int x, int y)
|
|
|
|
{
|
|
|
|
int nx = x/SNAP_X;
|
|
|
|
int ny = y/SNAP_Y;
|
|
|
|
|
|
|
|
if (!absolute && is_spot_set (nx, ny))
|
|
|
|
allocate_free_spot (&di->grid_x, &di->grid_y);
|
|
|
|
else {
|
|
|
|
set_spot_val (nx, ny, 1);
|
|
|
|
di->grid_x = nx;
|
|
|
|
di->grid_y = ny;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get snapped position for an icon */
|
|
|
|
static void
|
|
|
|
get_icon_screen_x_y (desktop_icon_t *di, int *x, int *y)
|
|
|
|
{
|
1998-10-22 04:32:21 +04:00
|
|
|
int w, h;
|
|
|
|
|
|
|
|
w = DESKTOP_ICON (di->widget)->width;
|
|
|
|
h = DESKTOP_ICON (di->widget)->height;
|
|
|
|
|
1998-04-15 07:16:29 +04:00
|
|
|
if (di->grid_x != -1){
|
|
|
|
*x = di->grid_x * SNAP_X;
|
|
|
|
*y = di->grid_y * SNAP_Y;
|
|
|
|
|
1998-10-22 04:32:21 +04:00
|
|
|
*x = *x + (SNAP_X - w) / 2;
|
1998-04-15 07:16:29 +04:00
|
|
|
if (*x < 0)
|
|
|
|
*x = 0;
|
|
|
|
|
1998-10-22 04:32:21 +04:00
|
|
|
if (h > SNAP_Y)
|
|
|
|
*y = *y + (SNAP_Y - h) / 2;
|
1998-04-15 07:16:29 +04:00
|
|
|
else
|
1998-10-22 04:32:21 +04:00
|
|
|
*y = *y + (SNAP_Y - h);
|
1998-04-15 07:16:29 +04:00
|
|
|
} else {
|
|
|
|
*x = di->x;
|
|
|
|
*y = di->y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-02-27 08:10:44 +03:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
1998-04-15 07:16:29 +04:00
|
|
|
static int current_x, current_y;
|
|
|
|
|
1998-02-27 08:10:44 +03:00
|
|
|
static void
|
1998-03-19 05:57:01 +03:00
|
|
|
desktop_icon_set_position (desktop_icon_t *di)
|
1998-02-27 08:10:44 +03:00
|
|
|
{
|
|
|
|
static int x, y = 10;
|
1998-04-15 07:16:29 +04:00
|
|
|
|
1998-02-27 08:10:44 +03:00
|
|
|
x = -1;
|
|
|
|
if (di->dentry && di->dentry->geometry){
|
|
|
|
char *comma = strchr (di->dentry->geometry, ',');
|
|
|
|
|
|
|
|
if (comma){
|
|
|
|
x = atoi (di->dentry->geometry);
|
|
|
|
comma++;
|
|
|
|
y = atoi (comma);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-04-15 07:16:29 +04:00
|
|
|
if (icons_snap_to_grid){
|
|
|
|
if (x == -1){
|
|
|
|
x = current_x;
|
|
|
|
y = current_y;
|
|
|
|
|
|
|
|
current_y += SNAP_Y;
|
|
|
|
if (current_y > gdk_screen_height ())
|
|
|
|
current_x += SNAP_X;
|
|
|
|
|
|
|
|
snap_to (di, 1, x, y);
|
|
|
|
} else
|
|
|
|
snap_to (di, 0, x, y);
|
|
|
|
|
|
|
|
get_icon_screen_x_y (di, &x, &y);
|
|
|
|
} else {
|
|
|
|
/* This find-spot routine can obviously be improved, left as an excercise
|
|
|
|
* to the hacker
|
|
|
|
*/
|
|
|
|
if (x == -1){
|
|
|
|
x = current_x;
|
|
|
|
y = current_y;
|
|
|
|
|
1998-10-23 18:31:02 +04:00
|
|
|
current_y += DESKTOP_ICON (di)->height + 8;
|
1998-04-15 07:16:29 +04:00
|
|
|
if (current_y > gdk_screen_height ()){
|
|
|
|
current_x += SNAP_X;
|
|
|
|
current_y = 0;
|
|
|
|
}
|
1998-02-27 08:10:44 +03:00
|
|
|
}
|
1998-04-15 07:16:29 +04:00
|
|
|
x += 6;
|
|
|
|
di->grid_x = di->grid_y = -1;
|
1998-02-27 08:10:44 +03:00
|
|
|
}
|
1998-04-15 07:16:29 +04:00
|
|
|
|
1998-02-27 08:10:44 +03:00
|
|
|
di->x = x;
|
|
|
|
di->y = y;
|
1998-04-15 07:16:29 +04:00
|
|
|
|
|
|
|
gtk_widget_set_uposition (di->widget, x, y);
|
1998-03-19 05:57:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 */
|
1998-03-24 08:25:56 +03:00
|
|
|
if (fname){
|
|
|
|
full_fname = gnome_unconditional_pixmap_file (fname);
|
1998-05-19 22:37:03 +04:00
|
|
|
free (fname);
|
1998-03-24 08:25:56 +03:00
|
|
|
if (exist_file (full_fname))
|
|
|
|
return full_fname;
|
|
|
|
g_free (full_fname);
|
|
|
|
}
|
1998-04-08 03:45:27 +04:00
|
|
|
|
1998-03-19 05:57:01 +03:00
|
|
|
/* Try a mc icon */
|
1998-04-08 03:45:27 +04:00
|
|
|
if (fname){
|
|
|
|
full_fname = concat_dir_and_file (ICONDIR, fname);
|
|
|
|
if (exist_file (full_fname))
|
|
|
|
return full_fname;
|
1998-03-19 05:57:01 +03:00
|
|
|
|
1998-04-08 03:45:27 +04:00
|
|
|
free (full_fname);
|
|
|
|
}
|
1998-03-19 05:57:01 +03:00
|
|
|
|
1998-09-17 09:42:05 +04:00
|
|
|
return gnome_unconditional_pixmap_file ("launcher-program.png");
|
1998-03-19 05:57:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Hackisigh routine taken from GDK
|
|
|
|
*/
|
1998-10-20 05:52:16 +04:00
|
|
|
#ifdef OLD_DND
|
1998-03-19 05:57:01 +03:00
|
|
|
static void
|
|
|
|
gdk_dnd_drag_begin (GdkWindow *initial_window)
|
|
|
|
{
|
1998-04-08 03:45:27 +04:00
|
|
|
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);
|
1998-03-19 05:57:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
artificial_drag_start (GdkWindow *window, int x, int y)
|
|
|
|
{
|
|
|
|
GdkWindowPrivate *wp = (GdkWindowPrivate *) window;
|
|
|
|
|
|
|
|
if (!wp->dnd_drag_enabled)
|
|
|
|
return;
|
1998-04-15 07:16:29 +04:00
|
|
|
#if 1
|
1998-03-19 05:57:01 +03:00
|
|
|
if (!gdk_dnd.drag_perhaps)
|
|
|
|
return;
|
|
|
|
if (gdk_dnd.dnd_grabbed)
|
|
|
|
return;
|
|
|
|
if (gdk_dnd.drag_really)
|
|
|
|
return;
|
|
|
|
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_really = 1;
|
|
|
|
gdk_dnd_display_drag_cursor (x, y, FALSE, TRUE);
|
1998-04-15 07:16:29 +04:00
|
|
|
#else
|
1998-04-10 01:59:32 +04:00
|
|
|
gdk_dnd.real_sw = wp;
|
|
|
|
gdk_dnd.dnd_drag_start.x = x;
|
|
|
|
gdk_dnd.dnd_drag_start.y = y;
|
|
|
|
gdk_dnd.drag_perhaps = 1;
|
|
|
|
if(gdk_dnd.drag_startwindows)
|
|
|
|
{
|
|
|
|
g_free(gdk_dnd.drag_startwindows);
|
|
|
|
gdk_dnd.drag_startwindows = NULL;
|
|
|
|
}
|
|
|
|
gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
|
|
|
|
gdk_dnd.dnd_grabbed = FALSE;
|
|
|
|
{
|
|
|
|
/* Set motion mask for first DnD'd window, since it
|
|
|
|
will be the one that is actually dragged */
|
|
|
|
XWindowAttributes dnd_winattr;
|
|
|
|
XSetWindowAttributes dnd_setwinattr;
|
|
|
|
|
|
|
|
/* We need to get motion events while the button is down, so
|
|
|
|
we can know whether to really start dragging or not... */
|
|
|
|
XGetWindowAttributes(gdk_display, (Window)wp->xwindow,
|
|
|
|
&dnd_winattr);
|
|
|
|
|
|
|
|
wp->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
|
|
|
|
dnd_setwinattr.event_mask =
|
|
|
|
wp->dnd_drag_eventmask = ButtonMotionMask | ButtonPressMask | ButtonReleaseMask |
|
|
|
|
EnterWindowMask | LeaveWindowMask;
|
|
|
|
XChangeWindowAttributes(gdk_display, wp->xwindow,
|
|
|
|
CWEventMask, &dnd_setwinattr);
|
|
|
|
}
|
1998-04-15 07:16:29 +04:00
|
|
|
#endif
|
1998-02-27 08:10:44 +03:00
|
|
|
}
|
1998-10-20 05:52:16 +04:00
|
|
|
#endif /* OLD_DND */
|
1998-02-27 08:10:44 +03:00
|
|
|
|
1998-10-21 22:05:08 +04:00
|
|
|
static GdkDragAction operation_value;
|
1998-03-04 03:56:14 +03:00
|
|
|
|
|
|
|
static void
|
1998-10-21 22:05:08 +04:00
|
|
|
set_option (GtkWidget *widget, GdkDragAction value)
|
1998-03-04 03:56:14 +03:00
|
|
|
{
|
|
|
|
operation_value = value;
|
|
|
|
gtk_main_quit ();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
option_menu_gone ()
|
|
|
|
{
|
1998-10-21 22:05:08 +04:00
|
|
|
operation_value = GDK_ACTION_ASK;
|
1998-03-04 03:56:14 +03:00
|
|
|
gtk_main_quit ();
|
|
|
|
}
|
|
|
|
|
1998-10-21 22:05:08 +04:00
|
|
|
static GdkDragAction
|
1998-03-18 09:24:20 +03:00
|
|
|
get_operation (guint32 timestamp, int x, int y)
|
1998-03-04 03:56:14 +03:00
|
|
|
{
|
|
|
|
static GtkWidget *menu;
|
1998-10-21 22:05:08 +04:00
|
|
|
|
1998-03-04 03:56:14 +03:00
|
|
|
if (!menu){
|
|
|
|
GtkWidget *item;
|
|
|
|
|
|
|
|
menu = gtk_menu_new ();
|
|
|
|
|
|
|
|
item = gtk_menu_item_new_with_label (_("Copy"));
|
1998-10-21 22:05:08 +04:00
|
|
|
gtk_signal_connect (GTK_OBJECT (item), "activate",
|
|
|
|
GTK_SIGNAL_FUNC(set_option), (void *) GDK_ACTION_COPY);
|
1998-03-04 03:56:14 +03:00
|
|
|
gtk_menu_append (GTK_MENU (menu), item);
|
|
|
|
gtk_widget_show (item);
|
|
|
|
|
|
|
|
item = gtk_menu_item_new_with_label (_("Move"));
|
1998-10-21 22:05:08 +04:00
|
|
|
gtk_signal_connect (GTK_OBJECT (item), "activate",
|
|
|
|
GTK_SIGNAL_FUNC(set_option), (void *) GDK_ACTION_MOVE);
|
1998-03-04 03:56:14 +03:00
|
|
|
gtk_menu_append (GTK_MENU (menu), item);
|
|
|
|
gtk_widget_show (item);
|
|
|
|
|
1998-03-06 09:03:30 +03:00
|
|
|
/* Not yet implemented the Link bits, so better to not show what we dont have */
|
1998-03-04 03:56:14 +03:00
|
|
|
item = gtk_menu_item_new_with_label (_("Link"));
|
1998-10-21 22:05:08 +04:00
|
|
|
gtk_signal_connect (GTK_OBJECT (item), "activate",
|
|
|
|
GTK_SIGNAL_FUNC(set_option), (void *) GDK_ACTION_LINK);
|
1998-03-04 03:56:14 +03:00
|
|
|
gtk_menu_append (GTK_MENU (menu), item);
|
|
|
|
gtk_widget_show (item);
|
1998-03-18 09:24:20 +03:00
|
|
|
|
1998-03-04 03:56:14 +03:00
|
|
|
gtk_signal_connect (GTK_OBJECT (menu), "hide", GTK_SIGNAL_FUNC(option_menu_gone), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_widget_set_uposition (menu, x, y);
|
|
|
|
|
|
|
|
/* FIXME: We should catch any events that escape this menu and cancel it */
|
1998-10-21 22:05:08 +04:00
|
|
|
operation_value = GDK_ACTION_ASK;
|
1998-03-18 09:24:20 +03:00
|
|
|
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, 0, NULL, 1, timestamp);
|
1998-03-04 03:56:14 +03:00
|
|
|
gtk_grab_add (menu);
|
|
|
|
gtk_main ();
|
|
|
|
gtk_grab_remove (menu);
|
|
|
|
gtk_widget_hide (menu);
|
|
|
|
|
|
|
|
return operation_value;
|
|
|
|
}
|
|
|
|
|
1998-10-21 22:05:08 +04:00
|
|
|
/*
|
|
|
|
* Used by check_window_id_in_one_panel and find_panel_owning_window_id for finding
|
1998-03-04 09:28:35 +03:00
|
|
|
* the panel that contains the specified window id (used to figure where the drag
|
|
|
|
* started)
|
|
|
|
*/
|
|
|
|
static WPanel *temp_panel;
|
|
|
|
|
|
|
|
static void
|
1998-10-21 22:05:08 +04:00
|
|
|
check_window_in_one_panel (gpointer data, gpointer user_data)
|
1998-03-04 09:28:35 +03:00
|
|
|
{
|
|
|
|
PanelContainer *pc = (PanelContainer *) data;
|
1998-10-28 04:47:57 +03:00
|
|
|
GdkWindowPrivate *w = (GdkWindowPrivate *) user_data;
|
1998-03-04 09:28:35 +03:00
|
|
|
WPanel *panel = pc->panel;
|
|
|
|
|
1998-05-25 02:21:56 +04:00
|
|
|
if (panel->list_type == list_icons){
|
|
|
|
GnomeIconList *icon_list = GNOME_ICON_LIST (panel->icons);
|
1998-10-28 04:47:57 +03:00
|
|
|
GdkWindowPrivate *wp = (GdkWindowPrivate *) GTK_WIDGET (icon_list)->window;
|
|
|
|
|
|
|
|
if (w->xwindow == wp->xwindow){
|
1998-05-25 02:21:56 +04:00
|
|
|
temp_panel = panel;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
GtkCList *clist = GTK_CLIST (panel->list);
|
1998-10-28 04:47:57 +03:00
|
|
|
GdkWindowPrivate *wp = (GdkWindowPrivate *) clist->clist_window;
|
|
|
|
|
|
|
|
if (w->xwindow == wp->xwindow){
|
1998-05-25 02:21:56 +04:00
|
|
|
temp_panel = panel;
|
|
|
|
return;
|
|
|
|
}
|
1998-03-04 09:28:35 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static WPanel *
|
1998-10-21 22:05:08 +04:00
|
|
|
find_panel_owning_window (GdkWindow *window)
|
1998-03-04 09:28:35 +03:00
|
|
|
{
|
|
|
|
temp_panel = NULL;
|
1998-10-28 04:47:57 +03:00
|
|
|
|
|
|
|
printf ("Looking for window %x\n", window);
|
|
|
|
|
1998-10-21 22:05:08 +04:00
|
|
|
g_list_foreach (containers, check_window_in_one_panel, window);
|
|
|
|
|
1998-03-04 09:28:35 +03:00
|
|
|
return temp_panel;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-10-21 22:05:08 +04:00
|
|
|
perform_drop_on_directory (WPanel *source_panel, GdkDragAction action, char *dest)
|
1998-03-04 09:28:35 +03:00
|
|
|
{
|
1998-10-21 22:05:08 +04:00
|
|
|
switch (action){
|
|
|
|
case GDK_ACTION_COPY:
|
1998-03-04 09:28:35 +03:00
|
|
|
panel_operate (source_panel, OP_COPY, dest);
|
|
|
|
break;
|
|
|
|
|
1998-10-21 22:05:08 +04:00
|
|
|
case GDK_ACTION_MOVE:
|
1998-03-04 09:28:35 +03:00
|
|
|
panel_operate (source_panel, OP_MOVE, dest);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-10-21 22:05:08 +04:00
|
|
|
perform_drop_manually (GList *names, GdkDragAction action, char *dest)
|
1998-03-04 09:28:35 +03:00
|
|
|
{
|
1998-04-17 04:21:53 +04:00
|
|
|
struct stat buf;
|
1998-03-04 09:28:35 +03:00
|
|
|
|
1998-10-21 22:05:08 +04:00
|
|
|
switch (action){
|
|
|
|
case GDK_ACTION_COPY:
|
1998-03-06 09:03:30 +03:00
|
|
|
create_op_win (OP_COPY, 0);
|
|
|
|
break;
|
|
|
|
|
1998-10-21 22:05:08 +04:00
|
|
|
case GDK_ACTION_MOVE:
|
1998-03-06 09:03:30 +03:00
|
|
|
create_op_win (OP_MOVE, 0);
|
|
|
|
break;
|
1998-10-21 22:05:08 +04:00
|
|
|
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
1998-03-06 09:03:30 +03:00
|
|
|
}
|
1998-10-21 22:05:08 +04:00
|
|
|
|
1998-03-06 09:03:30 +03:00
|
|
|
file_mask_defaults ();
|
1998-10-21 22:05:08 +04:00
|
|
|
|
|
|
|
for (; names; names = names->next){
|
|
|
|
char *p = names->data;
|
1998-03-04 09:28:35 +03:00
|
|
|
char *tmpf;
|
1998-04-17 04:21:53 +04:00
|
|
|
int res, v;
|
1998-03-04 09:28:35 +03:00
|
|
|
|
1998-10-21 22:05:08 +04:00
|
|
|
if (strncmp (p, "file:", 5) == 0)
|
|
|
|
p += 5;
|
|
|
|
|
|
|
|
switch (action){
|
|
|
|
case GDK_ACTION_COPY:
|
1998-03-04 09:28:35 +03:00
|
|
|
tmpf = concat_dir_and_file (dest, x_basename (p));
|
1998-04-17 04:21:53 +04:00
|
|
|
do {
|
|
|
|
res = mc_stat (p, &buf);
|
|
|
|
if (res != 0){
|
|
|
|
v = file_error (" Could not stat %s \n %s ", tmpf);
|
|
|
|
if (v != FILE_RETRY)
|
|
|
|
res = 0;
|
|
|
|
} else {
|
|
|
|
if (S_ISDIR (buf.st_mode))
|
|
|
|
copy_dir_dir (p, tmpf, 1, 0, 0, 0);
|
|
|
|
else
|
|
|
|
copy_file_file (p, tmpf, 1);
|
|
|
|
}
|
|
|
|
} while (res != 0);
|
1998-03-04 09:28:35 +03:00
|
|
|
free (tmpf);
|
|
|
|
break;
|
|
|
|
|
1998-10-21 22:05:08 +04:00
|
|
|
case GDK_ACTION_MOVE:
|
1998-03-04 09:28:35 +03:00
|
|
|
tmpf = concat_dir_and_file (dest, x_basename (p));
|
1998-04-17 04:21:53 +04:00
|
|
|
do {
|
|
|
|
res = mc_stat (p, &buf);
|
|
|
|
if (res != 0){
|
|
|
|
v = file_error (" Could not stat %s \n %s ", tmpf);
|
|
|
|
if (v != FILE_RETRY)
|
|
|
|
res = 0;
|
|
|
|
} else {
|
|
|
|
if (S_ISDIR (buf.st_mode))
|
|
|
|
move_dir_dir (p, tmpf);
|
|
|
|
else
|
|
|
|
move_file_file (p, tmpf);
|
|
|
|
}
|
|
|
|
} while (res != 0);
|
1998-03-04 09:28:35 +03:00
|
|
|
free (tmpf);
|
|
|
|
break;
|
1998-10-21 22:05:08 +04:00
|
|
|
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
1998-03-04 09:28:35 +03:00
|
|
|
}
|
1998-10-21 22:05:08 +04:00
|
|
|
}
|
|
|
|
|
1998-03-06 09:03:30 +03:00
|
|
|
destroy_op_win ();
|
|
|
|
}
|
|
|
|
|
1998-03-18 09:24:20 +03:00
|
|
|
static void
|
1998-10-21 22:05:08 +04:00
|
|
|
do_symlinks (GList *names, char *dest)
|
1998-03-18 09:24:20 +03:00
|
|
|
{
|
1998-10-21 22:05:08 +04:00
|
|
|
for (; names; names = names->next){
|
1998-03-18 09:24:20 +03:00
|
|
|
char *full_dest_name;
|
1998-10-21 22:05:08 +04:00
|
|
|
char *name = names->data;
|
1998-03-18 09:24:20 +03:00
|
|
|
|
1998-10-21 22:05:08 +04:00
|
|
|
full_dest_name = concat_dir_and_file (dest, x_basename (name));
|
|
|
|
if (strncmp (name, "file:", 5) == 0)
|
|
|
|
mc_symlink (name+5, full_dest_name);
|
|
|
|
else
|
|
|
|
mc_symlink (name, full_dest_name);
|
1998-03-10 09:31:01 +03:00
|
|
|
|
1998-10-21 22:05:08 +04:00
|
|
|
free (full_dest_name);
|
|
|
|
}
|
1998-03-04 09:28:35 +03:00
|
|
|
}
|
|
|
|
|
1998-10-21 22:05:08 +04:00
|
|
|
#if OLD_DND
|
1998-05-20 06:12:06 +04:00
|
|
|
static char **
|
|
|
|
drops_from_event (GdkEventDropDataAvailable *event, int *argc)
|
|
|
|
{
|
|
|
|
int count, i, len;
|
|
|
|
int arguments;
|
|
|
|
char *p, **argv;
|
|
|
|
|
|
|
|
/* Count the number of file names received */
|
|
|
|
count = event->data_numbytes;
|
|
|
|
p = event->data;
|
|
|
|
arguments = 0;
|
|
|
|
while (count){
|
|
|
|
arguments++;
|
|
|
|
len = strlen (p) + 1;
|
|
|
|
count -= len;
|
|
|
|
p += len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create the exec vector with all of the filenames */
|
|
|
|
argv = (char **) xmalloc (sizeof (char *) * arguments + 1, "arguments");
|
|
|
|
count = event->data_numbytes;
|
|
|
|
p = event->data;
|
|
|
|
i = 0;
|
|
|
|
do {
|
|
|
|
len = 1 + strlen (p);
|
|
|
|
count -= len;
|
|
|
|
argv [i++] = p;
|
|
|
|
p += len;
|
|
|
|
} while (count);
|
|
|
|
argv [i] = 0;
|
|
|
|
*argc = i;
|
|
|
|
|
|
|
|
return argv;
|
|
|
|
}
|
1998-10-20 05:52:16 +04:00
|
|
|
#endif /* OLD_DND */
|
1998-05-20 06:12:06 +04:00
|
|
|
|
1998-10-21 22:05:08 +04:00
|
|
|
void
|
|
|
|
drop_on_directory (GtkSelectionData *sel_data, GdkDragContext *context,
|
|
|
|
GdkDragAction action, char *dest, int force_manually)
|
|
|
|
{
|
|
|
|
WPanel *source_panel;
|
|
|
|
GList *names;
|
|
|
|
|
1998-10-28 04:47:57 +03:00
|
|
|
gdk_flush ();
|
1998-10-21 22:05:08 +04:00
|
|
|
g_warning ("Figure out the data type\n");
|
|
|
|
if (sel_data->data == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
printf ("action=%d\n", action);
|
|
|
|
if (action == GDK_ACTION_ASK){
|
|
|
|
g_warning ("I need the event here\n");
|
|
|
|
#if 0
|
|
|
|
action = get_operation (event->timestamp, event->coords.x, event->coords.y);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
printf ("action=%d\n", action);
|
|
|
|
if (action == GDK_ACTION_ASK)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Optimization: if we are dragging from the same process, we can
|
|
|
|
* display a nicer status bar.
|
|
|
|
*/
|
|
|
|
source_panel = find_panel_owning_window (context->source_window);
|
|
|
|
|
|
|
|
printf ("SOurce_Panel=%p\n", source_panel);
|
|
|
|
|
|
|
|
names = gnome_uri_list_extract_uris ((char *)sel_data->data);
|
|
|
|
|
|
|
|
/* Symlinks do not use any panel/file.c optimization */
|
|
|
|
if (action == GDK_ACTION_LINK){
|
|
|
|
do_symlinks (names, dest);
|
|
|
|
gnome_uri_list_free_strings (names);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source_panel && !force_manually){
|
|
|
|
perform_drop_on_directory (source_panel, action, dest);
|
|
|
|
update_one_panel_widget (source_panel, 0, UP_KEEPSEL);
|
|
|
|
panel_update_contents (source_panel);
|
|
|
|
} else
|
|
|
|
perform_drop_manually (names, action, dest);
|
|
|
|
|
|
|
|
gnome_uri_list_free_strings (names);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1998-05-20 06:12:06 +04:00
|
|
|
/*
|
|
|
|
* destroys a desktop_icon_t structure and anything that was held there,
|
|
|
|
* including the desktop widget.
|
|
|
|
*/
|
|
|
|
static void
|
1998-06-03 18:08:47 +04:00
|
|
|
desktop_release_desktop_icon_t (desktop_icon_t *di, int destroy_dentry)
|
1998-05-20 06:12:06 +04:00
|
|
|
{
|
|
|
|
if (di->dentry){
|
1998-06-03 18:08:47 +04:00
|
|
|
if (destroy_dentry)
|
|
|
|
gnome_desktop_entry_destroy (di->dentry);
|
|
|
|
else
|
|
|
|
gnome_desktop_entry_free (di->dentry);
|
1998-05-20 06:12:06 +04:00
|
|
|
} else {
|
|
|
|
free (di->pathname);
|
|
|
|
di->pathname = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (di->widget){
|
|
|
|
gtk_widget_destroy (di->widget);
|
|
|
|
di->widget = 0;
|
|
|
|
}
|
|
|
|
free (di);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
remove_directory (char *path)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (confirm_delete){
|
|
|
|
char *buffer;
|
|
|
|
|
|
|
|
if (know_not_what_am_i_doing)
|
|
|
|
query_set_sel (1);
|
|
|
|
buffer = copy_strings (_("Do you want to delete "), path, "?", NULL);
|
|
|
|
i = query_dialog (_("Delete"), buffer,
|
|
|
|
D_ERROR, 2, _("&Yes"), _("&No"));
|
|
|
|
free (buffer);
|
|
|
|
if (i != 0)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
create_op_win (OP_DELETE, 0);
|
|
|
|
erase_dir (path);
|
|
|
|
destroy_op_win ();
|
|
|
|
update_panels (UP_OPTIMIZE, UP_KEEPSEL);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
|
|
|
|
if (di->dentry == NULL){
|
|
|
|
/* launch entry */
|
|
|
|
mc_unlink (di->pathname);
|
|
|
|
} else {
|
|
|
|
/* a .destop file or a directory */
|
|
|
|
/* Remove the .desktop */
|
|
|
|
mc_unlink (di->dentry->location);
|
1998-05-23 04:55:03 +04:00
|
|
|
|
1998-05-20 06:12:06 +04:00
|
|
|
if (strcmp (di->dentry->type, "Directory") == 0){
|
|
|
|
struct stat s;
|
|
|
|
|
|
|
|
if (mc_lstat (di->dentry->exec[0], &s) == 0){
|
|
|
|
if (S_ISLNK (s.st_mode))
|
|
|
|
mc_unlink (di->dentry->exec[0]);
|
|
|
|
else
|
|
|
|
if (!remove_directory (di->dentry->exec[0]))
|
|
|
|
return;
|
|
|
|
}
|
1998-05-23 04:55:03 +04:00
|
|
|
} else {
|
|
|
|
if (strncmp (di->dentry->exec [0], desktop_directory, strlen (desktop_directory)) == 0)
|
|
|
|
mc_unlink (di->dentry->exec [0]);
|
1998-05-20 06:12:06 +04:00
|
|
|
}
|
|
|
|
}
|
1998-06-03 18:08:47 +04:00
|
|
|
desktop_release_desktop_icon_t (di, 1);
|
1998-05-20 06:12:06 +04:00
|
|
|
}
|
|
|
|
|
1998-10-20 05:52:16 +04:00
|
|
|
#ifdef OLD_DN
|
1998-05-20 06:12:06 +04:00
|
|
|
static void
|
|
|
|
drop_on_launch_entry (GtkWidget *widget, GdkEventDropDataAvailable *event, desktop_icon_t *di)
|
|
|
|
{
|
|
|
|
struct stat s;
|
|
|
|
char *r;
|
|
|
|
char **drops;
|
|
|
|
int drop_count;
|
|
|
|
|
|
|
|
/* try to stat it, if it fails, remove it from desktop */
|
|
|
|
if (!mc_stat (di->dentry->exec [0], &s) == 0){
|
|
|
|
desktop_icon_remove (di);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
drops = drops_from_event (event, &drop_count);
|
|
|
|
|
|
|
|
r = regex_command (di->pathname, "Drop", drops, 0);
|
|
|
|
if (r && strcmp (r, "Success") == 0){
|
|
|
|
free (drops);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_exe (s.st_mode))
|
|
|
|
gnome_desktop_entry_launch_with_args (di->dentry, drop_count, drops);
|
|
|
|
|
|
|
|
free (drops);
|
|
|
|
}
|
|
|
|
|
1998-02-27 08:10:44 +03:00
|
|
|
static void
|
1998-03-19 05:57:01 +03:00
|
|
|
url_dropped (GtkWidget *widget, GdkEventDropDataAvailable *event, desktop_icon_t *di)
|
1998-02-27 08:10:44 +03:00
|
|
|
{
|
1998-02-28 05:23:00 +03:00
|
|
|
char *p;
|
|
|
|
int count;
|
|
|
|
int len;
|
1998-03-18 09:24:20 +03:00
|
|
|
int is_directory = 0;
|
1998-03-03 08:20:20 +03:00
|
|
|
|
1998-03-18 09:24:20 +03:00
|
|
|
/* if DI is set to zero, then it is a drop on the root window */
|
|
|
|
if (di)
|
|
|
|
is_directory = strcasecmp (di->dentry->type, "directory") == 0;
|
|
|
|
else {
|
1998-06-03 18:08:47 +04:00
|
|
|
char *drop_location;
|
|
|
|
|
1998-03-18 09:24:20 +03:00
|
|
|
drop_on_directory (event, desktop_directory, 1);
|
1998-06-03 18:08:47 +04:00
|
|
|
desktop_reload (desktop_directory, &event->coords);
|
1998-03-18 09:24:20 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1998-03-04 03:56:14 +03:00
|
|
|
if (is_directory){
|
1998-05-17 00:54:28 +04:00
|
|
|
drop_on_directory (event, di->dentry->exec[0], 0);
|
1998-03-04 09:28:35 +03:00
|
|
|
return;
|
1998-03-04 03:56:14 +03:00
|
|
|
}
|
1998-03-18 09:24:20 +03:00
|
|
|
|
1998-05-20 06:12:06 +04:00
|
|
|
/* Last case: regular desktop stuff */
|
|
|
|
drop_on_launch_entry (widget, event, di);
|
1998-02-27 08:10:44 +03:00
|
|
|
}
|
|
|
|
|
1998-06-03 18:08:47 +04:00
|
|
|
static int
|
1998-03-19 05:57:01 +03:00
|
|
|
drop_cb (GtkWidget *widget, GdkEventDropDataAvailable *event, desktop_icon_t *di)
|
|
|
|
{
|
|
|
|
if (strcmp (event->data_type, "icon/root") == 0){
|
|
|
|
printf ("ICON DROPPED ON ROOT!\n");
|
1998-06-03 18:08:47 +04:00
|
|
|
} if (strcmp (event->data_type, "url:ALL") == 0 ||
|
|
|
|
(strcmp (event->data_type, "file:ALL") == 0) ||
|
|
|
|
(strcmp (event->data_type, "text/plain") == 0)){
|
1998-03-19 05:57:01 +03:00
|
|
|
url_dropped (widget, event, di);
|
1998-05-27 04:21:32 +04:00
|
|
|
} else
|
|
|
|
return FALSE;
|
|
|
|
return TRUE;
|
1998-03-19 05:57:01 +03:00
|
|
|
}
|
|
|
|
|
1998-04-15 07:16:29 +04:00
|
|
|
static void
|
|
|
|
drop_enter_leave ()
|
|
|
|
{
|
|
|
|
/* printf ("Enter/Leave\n"); */
|
|
|
|
}
|
|
|
|
|
1998-02-27 08:10:44 +03:00
|
|
|
static void
|
|
|
|
connect_drop_signals (GtkWidget *widget, desktop_icon_t *di)
|
|
|
|
{
|
|
|
|
GtkObject *o = GTK_OBJECT (widget);
|
|
|
|
|
1998-04-15 07:16:29 +04:00
|
|
|
gtk_signal_connect (o, "drop_enter_event", GTK_SIGNAL_FUNC (drop_enter_leave), di);
|
|
|
|
gtk_signal_connect (o, "drop_leave_event", GTK_SIGNAL_FUNC (drop_enter_leave), di);
|
1998-02-27 08:10:44 +03:00
|
|
|
gtk_signal_connect (o, "drop_data_available_event", GTK_SIGNAL_FUNC (drop_cb), di);
|
|
|
|
}
|
1998-10-20 05:52:16 +04:00
|
|
|
#endif /* OLD DND */
|
1998-02-27 08:10:44 +03:00
|
|
|
|
1998-05-23 04:55:03 +04:00
|
|
|
void
|
|
|
|
desktop_icon_execute (GtkWidget *ignored, desktop_icon_t *di)
|
1998-02-27 08:10:44 +03:00
|
|
|
{
|
|
|
|
/* Ultra lame-o execute. This should be replaced by the fixed regexp_command
|
|
|
|
* invocation
|
|
|
|
*/
|
|
|
|
|
1998-05-23 04:55:03 +04:00
|
|
|
if (strcmp (di->dentry->type, "Directory") == 0)
|
1998-05-17 00:54:28 +04:00
|
|
|
new_panel_at (di->dentry->exec[0]);
|
1998-05-23 04:55:03 +04:00
|
|
|
else
|
|
|
|
gnome_desktop_entry_launch (di->dentry);
|
1998-02-27 08:10:44 +03:00
|
|
|
}
|
|
|
|
|
1998-03-19 05:57:01 +03:00
|
|
|
static void
|
|
|
|
start_icon_drag (GtkWidget *wi, GdkEventMotion *event)
|
|
|
|
{
|
|
|
|
printf ("MOTION NOTIF!\n");
|
1998-10-20 09:37:45 +04:00
|
|
|
#ifdef OLD_DND
|
1998-03-19 05:57:01 +03:00
|
|
|
artificial_drag_start (wi->window, event->x, event->y);
|
1998-10-20 09:37:45 +04:00
|
|
|
#endif
|
1998-03-19 05:57:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
GdkPoint root_icon_drag_hotspot = { 15, 15 };
|
|
|
|
|
1998-04-15 07:16:29 +04:00
|
|
|
static void
|
|
|
|
desktop_icon_configure_position (desktop_icon_t *di, int x, int y)
|
|
|
|
{
|
|
|
|
gtk_widget_set_uposition (di->widget, x, y);
|
|
|
|
|
|
|
|
if (di->dentry){
|
|
|
|
char buffer [40];
|
|
|
|
|
|
|
|
sprintf (buffer, "%d,%d", x, y);
|
|
|
|
if (di->dentry->geometry)
|
|
|
|
g_free (di->dentry->geometry);
|
|
|
|
di->dentry->geometry = g_strdup (buffer);
|
|
|
|
gnome_desktop_entry_save (di->dentry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-10-20 05:52:16 +04:00
|
|
|
#ifdef OLD_DND
|
1998-03-19 05:57:01 +03:00
|
|
|
static void
|
|
|
|
desktop_icon_drag_request (GtkWidget *widget, GdkEventDragRequest *event, desktop_icon_t *di)
|
|
|
|
{
|
|
|
|
printf ("Drag type: %s\n", event->data_type);
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
drop_x = event->drop_coords.x - root_icon_drag_hotspot.x;
|
|
|
|
drop_y = event->drop_coords.y - root_icon_drag_hotspot.y;
|
|
|
|
|
1998-05-19 22:37:03 +04:00
|
|
|
/* Icon dropped on root. We take care of it */
|
1998-03-19 05:57:01 +03:00
|
|
|
printf ("Dropped at %d %d\n", drop_x, drop_y);
|
1998-04-15 07:16:29 +04:00
|
|
|
|
|
|
|
if (di->grid_x != -1)
|
|
|
|
set_spot_val (di->grid_x, di->grid_y, 0);
|
|
|
|
|
|
|
|
if (icons_snap_to_grid){
|
|
|
|
snap_to (di, 0, drop_x, drop_y);
|
|
|
|
get_icon_screen_x_y (di, &drop_x, &drop_y);
|
1998-03-19 05:57:01 +03:00
|
|
|
}
|
1998-04-15 07:16:29 +04:00
|
|
|
|
|
|
|
desktop_icon_configure_position (di, drop_x, drop_y);
|
1998-03-19 05:57:01 +03:00
|
|
|
}
|
|
|
|
}
|
1998-10-20 05:52:16 +04:00
|
|
|
#endif
|
1998-03-19 05:57:01 +03:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-04-15 07:16:29 +04:00
|
|
|
void
|
|
|
|
gnome_arrange_icons (void)
|
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
current_x = current_y = 0;
|
|
|
|
memset (spot_array, 0, (x_spots * y_spots)/8);
|
|
|
|
|
|
|
|
for (l = desktop_icons; l; l = l->next){
|
|
|
|
desktop_icon_t *di = l->data;
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
snap_to (di, 1, current_x, current_y);
|
|
|
|
get_icon_screen_x_y (di, &x, &y);
|
|
|
|
desktop_icon_configure_position (di, x, y);
|
|
|
|
|
|
|
|
current_y += SNAP_Y;
|
|
|
|
if (current_y == gdk_screen_height ()){
|
|
|
|
current_y = 0;
|
|
|
|
current_x += SNAP_X;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-03-31 11:35:38 +04:00
|
|
|
/* As Elliot can not be bothered to fix his DnD code in Gdk and it is an absolute mess */
|
1998-04-15 07:16:29 +04:00
|
|
|
static int in_desktop_dnd;
|
1998-03-31 11:35:38 +04:00
|
|
|
|
1998-03-19 05:57:01 +03:00
|
|
|
static void
|
|
|
|
desktop_icon_drag_start (GtkWidget *widget, GdkEvent *event, desktop_icon_t *di)
|
|
|
|
{
|
|
|
|
char *fname;
|
|
|
|
|
1998-03-31 11:35:38 +04:00
|
|
|
if (in_desktop_dnd)
|
|
|
|
return;
|
1998-04-10 01:59:32 +04:00
|
|
|
|
1998-03-31 11:35:38 +04:00
|
|
|
in_desktop_dnd = 1;
|
1998-04-10 01:59:32 +04:00
|
|
|
|
1998-03-19 05:57:01 +03:00
|
|
|
/* This should not happen, as the drag end routine should destroy those widgets */
|
|
|
|
destroy_shaped_dnd_windows ();
|
1998-03-20 05:00:09 +03:00
|
|
|
|
1998-03-19 05:57:01 +03:00
|
|
|
if (di->dentry)
|
|
|
|
fname = strdup (di->dentry->icon);
|
|
|
|
else
|
|
|
|
fname = get_desktop_icon (di->pathname);
|
1998-03-20 05:00:09 +03:00
|
|
|
|
1998-03-19 05:57:01 +03:00
|
|
|
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);
|
1998-05-05 12:08:56 +04:00
|
|
|
if (root_drag_not_ok_window && root_drag_ok_window){
|
1998-10-20 05:52:16 +04:00
|
|
|
#ifdef OLD_DND
|
1998-05-05 12:08:56 +04:00
|
|
|
gdk_dnd_set_drag_shape (root_drag_ok_window->window, &root_icon_drag_hotspot,
|
|
|
|
root_drag_not_ok_window->window, &root_icon_drag_hotspot);
|
1998-10-20 05:52:16 +04:00
|
|
|
#endif
|
1998-05-05 12:08:56 +04:00
|
|
|
gtk_widget_show (root_drag_not_ok_window);
|
|
|
|
gtk_widget_show (root_drag_ok_window);
|
|
|
|
}
|
1998-03-19 05:57:01 +03:00
|
|
|
free (fname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
desktop_icon_drag_end (GtkWidget *widget, GdkEvent *event, desktop_icon_t *di)
|
|
|
|
{
|
1998-03-31 11:35:38 +04:00
|
|
|
in_desktop_dnd = 0;
|
1998-03-19 05:57:01 +03:00
|
|
|
destroy_shaped_dnd_windows ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Bind the signals so that we can make this icon draggable
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
desktop_icon_make_draggable (desktop_icon_t *di)
|
|
|
|
{
|
1998-08-20 03:39:57 +04:00
|
|
|
GtkObject *obj;
|
|
|
|
GList *child;
|
1998-03-19 05:57:01 +03:00
|
|
|
char *drag_types [] = { "icon/root", "url:ALL" };
|
|
|
|
|
1998-08-20 03:39:57 +04:00
|
|
|
child = gtk_container_children(GTK_CONTAINER(di->widget));
|
|
|
|
obj = GTK_OBJECT (child->data);
|
|
|
|
/* To artificially start up drag and drop */
|
1998-10-20 05:52:16 +04:00
|
|
|
|
|
|
|
#ifdef OLD_DND
|
1998-03-23 20:49:04 +03:00
|
|
|
/* gtk_signal_connect (obj, "motion_notify_event", GTK_SIGNAL_FUNC (start_icon_drag), di); */
|
1998-08-20 03:39:57 +04:00
|
|
|
gtk_widget_dnd_drag_set (GTK_WIDGET(child->data), TRUE, drag_types, ELEMENTS (drag_types));
|
1998-03-19 05:57:01 +03:00
|
|
|
|
|
|
|
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);
|
1998-10-20 05:52:16 +04:00
|
|
|
#endif
|
1998-03-19 05:57:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Called by the pop up menu: removes the icon from the desktop */
|
1998-05-23 04:55:03 +04:00
|
|
|
void
|
|
|
|
desktop_icon_delete (GtkWidget *widget, desktop_icon_t *di)
|
1998-03-19 05:57:01 +03:00
|
|
|
{
|
|
|
|
desktop_icon_remove (di);
|
|
|
|
}
|
|
|
|
|
1998-03-18 09:24:20 +03:00
|
|
|
GtkWidget *
|
1998-10-22 04:32:21 +04:00
|
|
|
create_desktop_icon (char *file, char *text)
|
1998-03-18 09:24:20 +03:00
|
|
|
{
|
|
|
|
GtkWidget *w;
|
|
|
|
|
1998-10-22 04:32:21 +04:00
|
|
|
if (g_file_exists (file))
|
|
|
|
w = desktop_icon_new (file, text);
|
|
|
|
else {
|
|
|
|
static char *default_image;
|
|
|
|
|
|
|
|
if (!default_image)
|
|
|
|
default_image = gnome_unconditional_pixmap_file ("launcher-program.png");
|
|
|
|
|
|
|
|
if (g_file_exists (default_image))
|
|
|
|
w = desktop_icon_new (default_image, text);
|
|
|
|
else
|
|
|
|
w = NULL;
|
1998-03-18 09:24:20 +03:00
|
|
|
}
|
1998-10-22 04:32:21 +04:00
|
|
|
|
1998-03-18 09:24:20 +03:00
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
1998-03-20 05:00:09 +03:00
|
|
|
static GtkWidget *
|
1998-10-22 04:32:21 +04:00
|
|
|
get_desktop_icon_for_dentry (GnomeDesktopEntry *dentry)
|
1998-02-27 08:10:44 +03:00
|
|
|
{
|
1998-10-22 04:32:21 +04:00
|
|
|
GtkWidget *dicon;
|
1998-03-20 05:00:09 +03:00
|
|
|
char *icon_label;
|
1998-02-27 08:10:44 +03:00
|
|
|
|
1998-05-17 00:54:28 +04:00
|
|
|
icon_label = dentry->name ? dentry->name : x_basename (dentry->exec[0]);
|
1998-03-20 05:00:09 +03:00
|
|
|
|
1998-02-28 05:23:00 +03:00
|
|
|
if (dentry->icon)
|
1998-10-22 04:32:21 +04:00
|
|
|
dicon = create_desktop_icon (dentry->icon, icon_label);
|
1998-02-28 05:23:00 +03:00
|
|
|
else {
|
1998-03-01 04:29:42 +03:00
|
|
|
static char *default_icon_path;
|
|
|
|
static char exists;
|
|
|
|
|
1998-03-20 05:00:09 +03:00
|
|
|
if (!default_icon_path) {
|
1998-09-17 09:42:05 +04:00
|
|
|
default_icon_path = gnome_unconditional_pixmap_file ("launcher-program.png");
|
1998-03-01 04:29:42 +03:00
|
|
|
if (g_file_exists (default_icon_path))
|
|
|
|
exists = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (exists)
|
1998-10-22 04:32:21 +04:00
|
|
|
dicon = create_desktop_icon (default_icon_path, icon_label);
|
1998-03-01 04:29:42 +03:00
|
|
|
else {
|
1998-10-22 04:32:21 +04:00
|
|
|
dicon = gtk_window_new (GTK_WINDOW_POPUP);
|
|
|
|
gtk_widget_set_usize (dicon, 20, 20);
|
1998-03-01 04:29:42 +03:00
|
|
|
}
|
1998-02-28 05:23:00 +03:00
|
|
|
}
|
1998-03-20 05:00:09 +03:00
|
|
|
|
1998-10-22 04:32:21 +04:00
|
|
|
return dicon;
|
1998-03-20 05:00:09 +03:00
|
|
|
}
|
|
|
|
|
1998-04-17 06:23:29 +04:00
|
|
|
static GtkWidget *
|
1998-10-22 04:32:21 +04:00
|
|
|
get_desktop_icon_for_di (desktop_icon_t *di)
|
1998-04-17 06:23:29 +04:00
|
|
|
{
|
|
|
|
GtkWidget *window;
|
|
|
|
char *icon_label, *icon;
|
|
|
|
|
|
|
|
icon_label = x_basename (di->pathname);
|
|
|
|
|
|
|
|
icon = get_desktop_icon (di->pathname);
|
1998-10-22 04:32:21 +04:00
|
|
|
window = create_desktop_icon (icon, icon_label);
|
1998-04-17 06:23:29 +04:00
|
|
|
g_free (icon);
|
|
|
|
return window;
|
|
|
|
}
|
|
|
|
|
1998-03-20 05:00:09 +03:00
|
|
|
static int
|
|
|
|
dentry_button_click (GtkWidget *widget, GdkEventButton *event, desktop_icon_t *di)
|
|
|
|
{
|
1998-03-23 20:49:04 +03:00
|
|
|
if (event->button == 1){
|
|
|
|
if (event->type == GDK_2BUTTON_PRESS)
|
1998-05-23 04:55:03 +04:00
|
|
|
desktop_icon_execute (widget, di);
|
1998-03-23 20:49:04 +03:00
|
|
|
|
1998-03-20 05:00:09 +03:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (event->type == GDK_BUTTON_PRESS && event->button == 3){
|
|
|
|
desktop_icon_context_popup (event, di);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
1998-03-18 09:24:20 +03:00
|
|
|
|
1998-03-20 05:00:09 +03:00
|
|
|
char *drop_types [] = {
|
|
|
|
"text/plain",
|
|
|
|
"url:ALL",
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
1998-04-15 07:16:29 +04:00
|
|
|
post_setup_desktop_icon (desktop_icon_t *di, int show)
|
1998-03-20 05:00:09 +03:00
|
|
|
{
|
1998-08-20 03:39:57 +04:00
|
|
|
GList *child;
|
1998-03-19 05:57:01 +03:00
|
|
|
desktop_icon_make_draggable (di);
|
1998-03-20 05:00:09 +03:00
|
|
|
|
1998-02-27 08:10:44 +03:00
|
|
|
/* Setup the widget to make it useful: */
|
|
|
|
|
1998-10-20 09:37:45 +04:00
|
|
|
#ifdef OLD_DND
|
1998-02-27 08:10:44 +03:00
|
|
|
/* 1. Drag and drop functionality */
|
1998-08-20 03:39:57 +04:00
|
|
|
|
|
|
|
child = gtk_container_children(GTK_CONTAINER(di->widget));
|
|
|
|
connect_drop_signals (GTK_WIDGET(child->data), di);
|
|
|
|
gtk_widget_dnd_drop_set (GTK_WIDGET(child->data), TRUE, drop_types, ELEMENTS (drop_types), FALSE);
|
1998-04-23 22:23:32 +04:00
|
|
|
|
1998-02-27 08:10:44 +03:00
|
|
|
/* 2. Double clicking executes the command */
|
1998-08-20 03:39:57 +04:00
|
|
|
gtk_signal_connect (GTK_OBJECT (child->data), "button_press_event", GTK_SIGNAL_FUNC (dentry_button_click), di);
|
1998-03-18 09:24:20 +03:00
|
|
|
|
1998-10-23 18:31:02 +04:00
|
|
|
#endif
|
1998-04-15 07:16:29 +04:00
|
|
|
if (show)
|
|
|
|
gtk_widget_show (di->widget);
|
1998-03-20 05:00:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Pops up the icon properties pages */
|
1998-05-23 04:55:03 +04:00
|
|
|
void
|
|
|
|
desktop_icon_properties (GtkWidget *widget, desktop_icon_t *di)
|
1998-03-20 05:00:09 +03:00
|
|
|
{
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
retval = item_properties (di->widget, di->pathname, di);
|
|
|
|
|
1998-04-17 06:23:29 +04:00
|
|
|
if (retval & (GPROP_TITLE | GPROP_ICON | GPROP_FILENAME)) {
|
1998-03-20 05:00:09 +03:00
|
|
|
gtk_widget_destroy (di->widget);
|
|
|
|
|
1998-04-17 06:23:29 +04:00
|
|
|
if (di->dentry)
|
1998-10-22 04:32:21 +04:00
|
|
|
di->widget = get_desktop_icon_for_dentry (di->dentry);
|
1998-04-17 06:23:29 +04:00
|
|
|
else
|
1998-10-22 04:32:21 +04:00
|
|
|
di->widget = get_desktop_icon_for_di (di);
|
1998-03-20 05:00:09 +03:00
|
|
|
|
1998-10-22 04:32:21 +04:00
|
|
|
if (icons_snap_to_grid && di->grid_x != -1)
|
1998-04-17 06:23:29 +04:00
|
|
|
get_icon_screen_x_y (di, &di->x, &di->y);
|
1998-10-22 04:32:21 +04:00
|
|
|
|
1998-04-17 06:23:29 +04:00
|
|
|
gtk_widget_set_uposition (di->widget, di->x, di->y);
|
1998-10-22 04:32:21 +04:00
|
|
|
|
1998-04-15 07:16:29 +04:00
|
|
|
post_setup_desktop_icon (di, 1);
|
1998-10-22 04:32:21 +04:00
|
|
|
|
1998-04-17 06:23:29 +04:00
|
|
|
if (di->dentry)
|
|
|
|
gnome_desktop_entry_save (di->dentry);
|
1998-03-20 05:00:09 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Activates the context sensitive menu for this icon
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
desktop_icon_context_popup (GdkEventButton *event, desktop_icon_t *di)
|
|
|
|
{
|
1998-05-23 04:55:03 +04:00
|
|
|
file_popup (event, NULL, di, 0, di->dentry->exec [0]);
|
1998-03-20 05:00:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
char *root_drop_types [] = {
|
|
|
|
"icon/root",
|
|
|
|
"url:ALL"
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
desktop_load_from_dentry (GnomeDesktopEntry *dentry)
|
|
|
|
{
|
1998-10-22 04:32:21 +04:00
|
|
|
GtkWidget *dicon;
|
1998-03-20 05:00:09 +03:00
|
|
|
desktop_icon_t *di;
|
|
|
|
|
1998-10-22 04:32:21 +04:00
|
|
|
dicon = get_desktop_icon_for_dentry (dentry);
|
1998-03-20 05:00:09 +03:00
|
|
|
|
1998-10-22 04:32:21 +04:00
|
|
|
if (!dicon)
|
1998-03-20 05:00:09 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
di = xmalloc (sizeof (desktop_icon_t), "desktop_load_entry");
|
|
|
|
di->dentry = dentry;
|
1998-10-22 04:32:21 +04:00
|
|
|
di->widget = dicon;
|
1998-03-20 05:00:09 +03:00
|
|
|
di->pathname = dentry->location;
|
|
|
|
|
|
|
|
desktop_icons = g_list_prepend (desktop_icons, di);
|
|
|
|
|
1998-04-15 07:16:29 +04:00
|
|
|
post_setup_desktop_icon (di, 0);
|
1998-03-20 09:00:20 +03:00
|
|
|
desktop_icon_set_position (di);
|
1998-02-27 08:10:44 +03:00
|
|
|
}
|
|
|
|
|
1998-03-19 05:57:01 +03:00
|
|
|
/*
|
|
|
|
* Loads a .desktop file from FILENAME for the desktop.
|
|
|
|
*/
|
1998-03-18 09:24:20 +03:00
|
|
|
static void
|
|
|
|
desktop_load_dentry (char *filename)
|
|
|
|
{
|
|
|
|
GnomeDesktopEntry *dentry;
|
|
|
|
|
|
|
|
dentry = gnome_desktop_entry_load (filename);
|
|
|
|
|
|
|
|
if (!dentry)
|
|
|
|
return;
|
|
|
|
|
|
|
|
desktop_load_from_dentry (dentry);
|
|
|
|
}
|
|
|
|
|
1998-06-03 18:08:47 +04:00
|
|
|
/* Set the drop position to NULL, we only drop the
|
|
|
|
* first icon on the spot it was dropped, th rest
|
|
|
|
* get auto-layouted. Perhaps this should be an option.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
desktop_setup_geometry_from_point (GnomeDesktopEntry *dentry, GdkPoint **point)
|
|
|
|
{
|
|
|
|
char buffer [40];
|
|
|
|
|
|
|
|
sprintf (buffer, "%d,%d", (*point)->x, (*point)->y);
|
|
|
|
dentry->geometry = g_strdup (buffer);
|
|
|
|
*point = NULL;
|
|
|
|
}
|
|
|
|
|
1998-03-19 05:57:01 +03:00
|
|
|
/*
|
|
|
|
* Creates a new DIRECTORY/.directory file which is just a .dekstop
|
|
|
|
* on directories. And then loads it into the desktop
|
|
|
|
*/
|
1998-02-27 08:10:44 +03:00
|
|
|
static void
|
1998-06-03 18:08:47 +04:00
|
|
|
desktop_create_directory_entry (char *dentry_path, char *pathname, char *short_name, GdkPoint **pos)
|
1998-02-27 08:10:44 +03:00
|
|
|
{
|
|
|
|
GnomeDesktopEntry *dentry;
|
|
|
|
|
|
|
|
dentry = xmalloc (sizeof (GnomeDesktopEntry), "dcde");
|
1998-05-20 06:12:06 +04:00
|
|
|
memset (dentry, 0, sizeof (GnomeDesktopEntry));
|
1998-03-25 22:29:12 +03:00
|
|
|
dentry->name = g_strdup (short_name);
|
1998-05-17 00:54:28 +04:00
|
|
|
dentry->exec = (char **) malloc (2 * sizeof (char *));
|
|
|
|
dentry->exec[0] = g_strdup (pathname);
|
|
|
|
dentry->exec[1] = NULL;
|
1998-05-20 06:12:06 +04:00
|
|
|
dentry->exec_length = 1;
|
1998-03-25 22:29:12 +03:00
|
|
|
dentry->icon = gnome_unconditional_pixmap_file ("gnome-folder.png");
|
|
|
|
dentry->type = g_strdup ("Directory");
|
1998-02-27 08:10:44 +03:00
|
|
|
dentry->location = g_strdup (dentry_path);
|
1998-06-03 18:08:47 +04:00
|
|
|
if (pos && *pos)
|
|
|
|
desktop_setup_geometry_from_point (dentry, pos);
|
1998-03-25 22:29:12 +03:00
|
|
|
|
1998-02-27 08:10:44 +03:00
|
|
|
gnome_desktop_entry_save (dentry);
|
1998-03-18 09:24:20 +03:00
|
|
|
desktop_load_from_dentry (dentry);
|
1998-02-27 08:10:44 +03:00
|
|
|
}
|
|
|
|
|
1998-03-18 09:24:20 +03:00
|
|
|
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
|
1998-02-27 08:10:44 +03:00
|
|
|
desktop_file_exec (GtkWidget *widget, GdkEventButton *event, desktop_icon_t *di)
|
|
|
|
{
|
1998-03-18 09:24:20 +03:00
|
|
|
if (event->type == GDK_2BUTTON_PRESS && event->button == 1){
|
|
|
|
if (di->dentry){
|
|
|
|
printf ("FIXME: No support for dentry loaded stuff yet\n");
|
|
|
|
} else {
|
|
|
|
if (file_is_executable (di->pathname)){
|
|
|
|
char *tmp = name_quote (di->pathname, 0);
|
|
|
|
|
1998-03-25 08:16:00 +03:00
|
|
|
if (!confirm_execute || (query_dialog (_(" The Midnight Commander "),
|
|
|
|
_(" Do you really want to execute? "),
|
|
|
|
0, 2, _("&Yes"), _("&No")) == 0))
|
1998-03-18 09:24:20 +03:00
|
|
|
execute (tmp);
|
|
|
|
free (tmp);
|
|
|
|
} else {
|
1998-04-09 08:58:24 +04:00
|
|
|
char *result, *command;
|
|
|
|
|
|
|
|
result = regex_command (di->pathname, "Open", NULL, 0);
|
|
|
|
if (result && (strcmp (result, "Success") == 0))
|
|
|
|
return TRUE;
|
|
|
|
command = input_expand_dialog (_("Open with..."),
|
|
|
|
_("Enter extra arguments:"),
|
|
|
|
di->pathname);
|
|
|
|
if (command){
|
|
|
|
execute (command);
|
|
|
|
free (command);
|
|
|
|
}
|
1998-03-18 09:24:20 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
1998-03-03 08:20:20 +03:00
|
|
|
|
1998-03-18 09:24:20 +03:00
|
|
|
if (event->type == GDK_BUTTON_PRESS && event->button == 3){
|
|
|
|
desktop_icon_context_popup (event, di);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
1998-03-03 08:20:20 +03:00
|
|
|
static void
|
1998-06-03 18:08:47 +04:00
|
|
|
desktop_create_launch_entry (char *desktop_file, char *pathname, char *short_name, GdkPoint **pos)
|
1998-02-27 08:10:44 +03:00
|
|
|
{
|
1998-05-20 06:12:06 +04:00
|
|
|
GnomeDesktopEntry *dentry;
|
1998-10-22 04:32:21 +04:00
|
|
|
GtkWidget *dicon;
|
1998-02-27 08:10:44 +03:00
|
|
|
desktop_icon_t *di;
|
|
|
|
char *icon;
|
1998-05-20 06:12:06 +04:00
|
|
|
struct stat s;
|
1998-02-27 08:10:44 +03:00
|
|
|
|
1998-05-20 06:12:06 +04:00
|
|
|
stat (pathname, &s);
|
|
|
|
dentry = xmalloc (sizeof (GnomeDesktopEntry), "launch_entry");
|
|
|
|
memset (dentry, 0, sizeof (GnomeDesktopEntry));
|
|
|
|
|
1998-05-26 02:16:11 +04:00
|
|
|
dentry->name = g_strdup (short_name);
|
1998-05-20 06:12:06 +04:00
|
|
|
dentry->exec = (char **) malloc (2 * sizeof (char *));
|
|
|
|
dentry->exec[0] = g_strdup (pathname);
|
|
|
|
dentry->exec[1] = NULL;
|
|
|
|
dentry->exec_length = 1;
|
|
|
|
dentry->icon = get_desktop_icon (short_name);
|
|
|
|
dentry->type = g_strdup ("File");
|
|
|
|
dentry->location = g_strdup (desktop_file);
|
|
|
|
dentry->terminal = 1;
|
1998-06-03 18:08:47 +04:00
|
|
|
if (pos && *pos)
|
|
|
|
desktop_setup_geometry_from_point (dentry, pos);
|
|
|
|
|
1998-05-20 06:12:06 +04:00
|
|
|
gnome_desktop_entry_save (dentry);
|
|
|
|
desktop_load_from_dentry (dentry);
|
|
|
|
#if 0
|
1998-10-22 04:32:21 +04:00
|
|
|
dicon = create_desktop_icon (icon, x_basename (pathname));
|
1998-02-27 08:10:44 +03:00
|
|
|
g_free (icon);
|
1998-10-22 04:32:21 +04:00
|
|
|
if (!dicon)
|
1998-03-18 09:24:20 +03:00
|
|
|
return;
|
|
|
|
|
1998-02-27 08:10:44 +03:00
|
|
|
di = xmalloc (sizeof (desktop_icon_t), "dcle");
|
|
|
|
di->dentry = NULL;
|
1998-10-22 04:32:21 +04:00
|
|
|
di->widget = dicon;
|
1998-03-03 08:20:20 +03:00
|
|
|
di->pathname = strdup (pathname);
|
1998-03-18 09:24:20 +03:00
|
|
|
|
1998-03-19 05:57:01 +03:00
|
|
|
desktop_icon_set_position (di);
|
|
|
|
desktop_icon_make_draggable (di);
|
|
|
|
|
1998-02-27 08:10:44 +03:00
|
|
|
desktop_icons = g_list_prepend (desktop_icons, (gpointer) di);
|
|
|
|
|
1998-03-18 09:24:20 +03:00
|
|
|
/* Double clicking executes the command, single clicking brings up context menu */
|
1998-10-22 04:32:21 +04:00
|
|
|
gtk_signal_connect (GTK_OBJECT (dicon), "button_press_event", GTK_SIGNAL_FUNC (desktop_file_exec), di);
|
|
|
|
gtk_widget_realize (dicon);
|
1998-03-03 08:20:20 +03:00
|
|
|
|
1998-10-22 04:32:21 +04:00
|
|
|
gtk_signal_connect (GTK_OBJECT (dicon), "drop_data_available_event",
|
1998-03-03 08:20:20 +03:00
|
|
|
GTK_SIGNAL_FUNC (drop_on_launch_entry), di);
|
|
|
|
|
1998-10-22 04:32:21 +04:00
|
|
|
gtk_widget_dnd_drop_set (dicon, TRUE, drop_types, ELEMENTS (drop_types), FALSE);
|
1998-05-20 06:12:06 +04:00
|
|
|
#endif
|
1998-02-27 08:10:44 +03:00
|
|
|
}
|
|
|
|
|
1998-03-18 09:24:20 +03:00
|
|
|
static int
|
|
|
|
desktop_pathname_loaded (char *pathname)
|
|
|
|
{
|
|
|
|
GList *p = desktop_icons;
|
|
|
|
|
|
|
|
for (; p; p = p->next){
|
|
|
|
desktop_icon_t *di = p->data;
|
|
|
|
|
|
|
|
if (strcmp (di->pathname, pathname) == 0)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-06-03 18:08:47 +04:00
|
|
|
desktop_setup_icon (char *filename, char *full_pathname, GdkPoint **desired_position)
|
1998-03-18 09:24:20 +03:00
|
|
|
{
|
|
|
|
struct stat s;
|
|
|
|
|
|
|
|
if (mc_stat (full_pathname, &s) == -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (S_ISDIR (s.st_mode)){
|
|
|
|
char *dir_full = concat_dir_and_file (full_pathname, ".directory");
|
|
|
|
|
|
|
|
if (!desktop_pathname_loaded (dir_full)){
|
|
|
|
if (exist_file (dir_full))
|
|
|
|
desktop_load_dentry (dir_full);
|
|
|
|
else
|
1998-06-03 18:08:47 +04:00
|
|
|
desktop_create_directory_entry (dir_full, full_pathname, filename, desired_position);
|
1998-03-18 09:24:20 +03:00
|
|
|
}
|
1998-05-19 22:37:03 +04:00
|
|
|
free (dir_full);
|
1998-03-18 09:24:20 +03:00
|
|
|
} else {
|
|
|
|
if (strstr (filename, ".desktop")){
|
|
|
|
if (!desktop_pathname_loaded (full_pathname))
|
|
|
|
desktop_load_dentry (full_pathname);
|
|
|
|
} else {
|
|
|
|
char *desktop_version;
|
|
|
|
|
|
|
|
desktop_version = copy_strings (full_pathname, ".desktop", NULL);
|
|
|
|
if (!exist_file (desktop_version) && !desktop_pathname_loaded (full_pathname))
|
1998-06-03 18:08:47 +04:00
|
|
|
desktop_create_launch_entry (desktop_version, full_pathname, filename, desired_position);
|
1998-03-18 09:24:20 +03:00
|
|
|
free (desktop_version);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-02-27 08:10:44 +03:00
|
|
|
/*
|
1998-03-18 09:24:20 +03:00
|
|
|
* Load all of the entries available on the ~/desktop directory
|
|
|
|
* So far, we support: .desktop files; directories (they get a .directory file);
|
|
|
|
* sylinks to directories; other programs.
|
1998-02-27 08:10:44 +03:00
|
|
|
*/
|
|
|
|
static void
|
1998-06-03 18:08:47 +04:00
|
|
|
desktop_reload (char *desktop_dir, GdkPoint *drop_position)
|
1998-02-27 08:10:44 +03:00
|
|
|
{
|
|
|
|
struct dirent *dent;
|
1998-04-17 06:23:29 +04:00
|
|
|
GList *l;
|
1998-02-27 08:10:44 +03:00
|
|
|
DIR *dir;
|
|
|
|
|
|
|
|
dir = mc_opendir (desktop_dir);
|
|
|
|
if (dir == NULL){
|
1998-03-25 08:16:00 +03:00
|
|
|
message (1, _(" Warning "), _(" Could not open %s directory"), desktop_dir, NULL);
|
1998-02-27 08:10:44 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((dent = mc_readdir (dir)) != NULL){
|
|
|
|
char *full;
|
|
|
|
|
|
|
|
/* ignore '.' */
|
|
|
|
if (dent->d_name [0] == '.' && dent->d_name [1] == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* ignore `..' */
|
|
|
|
if (dent->d_name [0] == '.' && dent->d_name [1] == '.' && dent->d_name [2] == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
full = concat_dir_and_file (desktop_dir, dent->d_name);
|
1998-06-03 18:08:47 +04:00
|
|
|
desktop_setup_icon (dent->d_name, full, &drop_position);
|
|
|
|
|
1998-02-27 08:10:44 +03:00
|
|
|
free (full);
|
|
|
|
}
|
1998-05-19 22:37:03 +04:00
|
|
|
mc_closedir (dir);
|
|
|
|
|
1998-04-17 06:23:29 +04:00
|
|
|
/* Show all of the widgets */
|
1998-04-15 07:16:29 +04:00
|
|
|
for (l = desktop_icons; l; l = l->next){
|
|
|
|
desktop_icon_t *di = l->data;
|
|
|
|
|
|
|
|
gtk_widget_show (di->widget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-04-17 06:23:29 +04:00
|
|
|
static void
|
|
|
|
desktop_load (char *desktop_dir)
|
|
|
|
{
|
1998-06-03 18:08:47 +04:00
|
|
|
desktop_reload (desktop_dir, NULL);
|
1998-04-17 06:23:29 +04:00
|
|
|
}
|
|
|
|
|
1998-03-18 09:24:20 +03:00
|
|
|
/*
|
|
|
|
* Copy the system defaults to the user ~/desktop directory and setup a
|
|
|
|
* Home directory link
|
|
|
|
*/
|
1998-02-27 08:10:44 +03:00
|
|
|
static void
|
|
|
|
desktop_setup_default (char *desktop_dir)
|
|
|
|
{
|
|
|
|
char *mc_desktop_dir;
|
1998-03-18 09:24:20 +03:00
|
|
|
char *desktop_dir_home_link;
|
|
|
|
|
|
|
|
desktop_dir_home_link = concat_dir_and_file (desktop_dir, "Home directory.desktop");
|
1998-02-27 08:10:44 +03:00
|
|
|
|
|
|
|
mc_desktop_dir = concat_dir_and_file (mc_home, MC_LIB_DESKTOP);
|
|
|
|
|
1998-03-10 09:31:01 +03:00
|
|
|
if (exist_file (mc_desktop_dir)){
|
|
|
|
create_op_win (OP_COPY, 0);
|
|
|
|
file_mask_defaults ();
|
1998-04-17 04:21:53 +04:00
|
|
|
copy_dir_dir (mc_desktop_dir, desktop_dir, 1, 0, 0, 0);
|
1998-03-10 09:31:01 +03:00
|
|
|
destroy_op_win ();
|
1998-03-18 09:24:20 +03:00
|
|
|
} else
|
1998-03-17 11:27:10 +03:00
|
|
|
mkdir (desktop_dir, 0777);
|
1998-03-18 09:24:20 +03:00
|
|
|
|
1998-06-03 18:08:47 +04:00
|
|
|
desktop_create_directory_entry (desktop_dir_home_link, "~", "Home directory", NULL);
|
1998-03-18 09:24:20 +03:00
|
|
|
free (desktop_dir_home_link);
|
1998-03-10 09:31:01 +03:00
|
|
|
free (mc_desktop_dir);
|
1998-02-27 08:10:44 +03:00
|
|
|
}
|
|
|
|
|
1998-03-18 09:24:20 +03:00
|
|
|
/*
|
|
|
|
* configures the root window dropability
|
|
|
|
*/
|
1998-03-17 11:27:10 +03:00
|
|
|
void
|
|
|
|
desktop_root (void)
|
|
|
|
{
|
|
|
|
GtkWidget *rw;
|
|
|
|
|
|
|
|
rw = gnome_rootwin_new ();
|
1998-10-20 09:37:45 +04:00
|
|
|
#ifdef OLD_DND
|
1998-03-18 09:24:20 +03:00
|
|
|
connect_drop_signals (rw, NULL);
|
1998-03-19 05:57:01 +03:00
|
|
|
gtk_widget_dnd_drop_set (rw, TRUE, root_drop_types, ELEMENTS (root_drop_types), FALSE);
|
1998-10-21 05:09:50 +04:00
|
|
|
gtk_widget_realize (rw);
|
1998-03-17 11:27:10 +03:00
|
|
|
gtk_widget_show (rw);
|
|
|
|
root_window = GNOME_ROOTWIN (rw);
|
1998-10-21 05:09:50 +04:00
|
|
|
#endif
|
1998-03-17 11:27:10 +03:00
|
|
|
}
|
|
|
|
|
1998-03-18 09:24:20 +03:00
|
|
|
/*
|
|
|
|
* entry point to start up the gnome desktop
|
|
|
|
*/
|
1998-02-27 08:10:44 +03:00
|
|
|
void
|
|
|
|
start_desktop (void)
|
|
|
|
{
|
1998-04-15 07:16:29 +04:00
|
|
|
init_spot_list ();
|
1998-03-18 09:24:20 +03:00
|
|
|
desktop_directory = concat_dir_and_file (home_dir, "desktop");
|
1998-02-27 08:10:44 +03:00
|
|
|
|
1998-03-18 09:24:20 +03:00
|
|
|
if (!exist_file (desktop_directory))
|
|
|
|
desktop_setup_default (desktop_directory);
|
1998-03-17 11:27:10 +03:00
|
|
|
|
|
|
|
desktop_root ();
|
1998-04-15 07:16:29 +04:00
|
|
|
desktop_load (desktop_directory);
|
1998-02-27 08:10:44 +03:00
|
|
|
}
|
1998-03-19 05:57:01 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* shutdown the desktop
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
stop_desktop (void)
|
|
|
|
{
|
|
|
|
GList *p;
|
|
|
|
|
|
|
|
for (p = desktop_icons; p; p = p->next){
|
|
|
|
desktop_icon_t *di = p->data;
|
|
|
|
|
1998-06-03 18:08:47 +04:00
|
|
|
desktop_release_desktop_icon_t (di, 0);
|
1998-03-19 05:57:01 +03:00
|
|
|
}
|
1998-04-01 04:52:33 +04:00
|
|
|
image_cache_destroy ();
|
1998-03-19 05:57:01 +03:00
|
|
|
}
|
1998-10-30 03:47:54 +03:00
|
|
|
|
|
|
|
#endif
|