diff --git a/gnome/ChangeLog b/gnome/ChangeLog index 26448280b..150a8b1fb 100644 --- a/gnome/ChangeLog +++ b/gnome/ChangeLog @@ -1,3 +1,12 @@ +1998-04-14 Miguel de Icaza + + * gview.c (x_init_view): Initialize view->sadj. + + * gdesktop.c (start_desktop): use destkop_load instead of + desktop_reload. + (desktop_load): This reloads + shows every widget on the + desktop_icons list. + 1998-04-14 Federico Mena Quintero * gdesktop.h: Added extern declarations for the diff --git a/gnome/gdesktop.c b/gnome/gdesktop.c index fb42ec011..0454e4b83 100644 --- a/gnome/gdesktop.c +++ b/gnome/gdesktop.c @@ -22,6 +22,12 @@ #include #include +/* 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; + /* operations on drops */ enum { OPER_COPY, @@ -32,6 +38,9 @@ enum { /* The X11 root window */ static GnomeRootWin *root_window; +/* use grid? */ +int icons_snap_to_grid = 1; + /* The full name of the desktop directory ~/desktop */ char *desktop_directory; @@ -43,17 +52,106 @@ static GList *desktop_icons; #define ELEMENTS(x) (sizeof (x) / sizeof (x[0])) +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) +{ + if (di->grid_x != -1){ + *x = di->grid_x * SNAP_X; + *y = di->grid_y * SNAP_Y; + + *x = *x + (SNAP_X - di->widget->requisition.width)/2; + if (*x < 0) + *x = 0; + + if (di->widget->requisition.height > SNAP_Y) + *y = *y + (SNAP_Y - di->widget->requisition.height)/2; + else + *y = *y + (SNAP_Y - di->widget->requisition.height); + } else { + *x = di->x; + *y = di->y; + } +} + /* * If the dentry is zero, then no information from the on-disk .desktop file is used * In this case, we probably will have to store the geometry for a file somewhere * else. */ +static int current_x, current_y; + static void desktop_icon_set_position (desktop_icon_t *di) { static int x, y = 10; - static int current_x, current_y; - + x = -1; if (di->dentry && di->dentry->geometry){ char *comma = strchr (di->dentry->geometry, ','); @@ -65,23 +163,45 @@ desktop_icon_set_position (desktop_icon_t *di) } } - /* This find-spot routine can obviously be improved, left as an excercise - * to the hacker - */ - if (x == -1){ - x = current_x; - y = current_y; + gtk_widget_size_request (di->widget, &di->widget->requisition); + + if (icons_snap_to_grid){ + if (x == -1){ + x = current_x; + y = current_y; - gtk_widget_size_request (di->widget, &di->widget->requisition); - current_y += di->widget->requisition.height + 8; - if (current_y > gdk_screen_height ()){ - current_x += 0; - current_y = 0; + 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; + + current_y += di->widget->requisition.height + 8; + if (current_y > gdk_screen_height ()){ + current_x += SNAP_X; + current_y = 0; + } } + x += 6; + di->grid_x = di->grid_y = -1; } + di->x = x; di->y = y; - gtk_widget_set_uposition (di->widget, 6 + x, y); + + gdk_window_lower (di->widget->window); + gtk_widget_set_uposition (di->widget, x, y); } /* @@ -137,7 +257,7 @@ artificial_drag_start (GdkWindow *window, int x, int y) if (!wp->dnd_drag_enabled) return; -#if 0 +#if 1 if (!gdk_dnd.drag_perhaps) return; if (gdk_dnd.dnd_grabbed) @@ -153,7 +273,7 @@ artificial_drag_start (GdkWindow *window, int x, int y) gdk_dnd.dnd_grabbed = TRUE; gdk_dnd.drag_really = 1; gdk_dnd_display_drag_cursor (x, y, FALSE, TRUE); -#endif +#else gdk_dnd.real_sw = wp; gdk_dnd.dnd_drag_start.x = x; gdk_dnd.dnd_drag_start.y = y; @@ -183,7 +303,7 @@ artificial_drag_start (GdkWindow *window, int x, int y) XChangeWindowAttributes(gdk_display, wp->xwindow, CWEventMask, &dnd_setwinattr); } - +#endif } static int operation_value; @@ -403,6 +523,7 @@ url_dropped (GtkWidget *widget, GdkEventDropDataAvailable *event, desktop_icon_t int len; int is_directory = 0; + printf ("URL dropped\n"); /* 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; @@ -438,13 +559,19 @@ drop_cb (GtkWidget *widget, GdkEventDropDataAvailable *event, desktop_icon_t *di url_dropped (widget, event, di); } +static void +drop_enter_leave () +{ +/* printf ("Enter/Leave\n"); */ +} + static void connect_drop_signals (GtkWidget *widget, desktop_icon_t *di) { GtkObject *o = GTK_OBJECT (widget); - gtk_signal_connect (o, "drop_enter_event", GTK_SIGNAL_FUNC (gtk_true), di); - gtk_signal_connect (o, "drop_leave_event", GTK_SIGNAL_FUNC (gtk_true), di); + 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); gtk_signal_connect (o, "drop_data_available_event", GTK_SIGNAL_FUNC (drop_cb), di); } @@ -472,6 +599,22 @@ start_icon_drag (GtkWidget *wi, GdkEventMotion *event) GdkPoint root_icon_drag_hotspot = { 15, 15 }; +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); + } +} + static void desktop_icon_drag_request (GtkWidget *widget, GdkEventDragRequest *event, desktop_icon_t *di) { @@ -487,16 +630,19 @@ desktop_icon_drag_request (GtkWidget *widget, GdkEventDragRequest *event, deskto /* Icon dropped on root. We take care of it */ printf ("Dropped at %d %d\n", drop_x, drop_y); - gtk_widget_set_uposition (di->widget, drop_x, drop_y); - if (di->dentry){ - char buffer [40]; + + if (di->grid_x != -1) + set_spot_val (di->grid_x, di->grid_y, 0); - sprintf (buffer, "%d,%d", drop_x, drop_y); - if (di->dentry->geometry) - g_free (di->dentry->geometry); - di->dentry->geometry = g_strdup (buffer); - gnome_desktop_entry_save (di->dentry); + if (icons_snap_to_grid){ + int px, py; + + snap_to (di, 0, drop_x, drop_y); + + get_icon_screen_x_y (di, &drop_x, &drop_y); } + + desktop_icon_configure_position (di, drop_x, drop_y); } } @@ -517,21 +663,42 @@ destroy_shaped_dnd_windows (void) } } +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; + } + } +} + /* As Elliot can not be bothered to fix his DnD code in Gdk and it is an absolute mess */ -/* static int in_desktop_dnd; */ +static int in_desktop_dnd; static void desktop_icon_drag_start (GtkWidget *widget, GdkEvent *event, desktop_icon_t *di) { char *fname; - g_print("!!!!! desktop_icon_drag_start"); -#if 0 if (in_desktop_dnd) return; in_desktop_dnd = 1; -#endif /* This should not happen, as the drag end routine should destroy those widgets */ destroy_shaped_dnd_windows (); @@ -545,7 +712,6 @@ desktop_icon_drag_start (GtkWidget *widget, GdkEvent *event, desktop_icon_t *di) /* FIXME: we are using the same icon for ok and not ok drags */ root_drag_ok_window = make_transparent_window (fname); root_drag_not_ok_window = make_transparent_window (fname); - gdk_dnd_set_drag_shape (root_drag_ok_window->window, &root_icon_drag_hotspot, root_drag_not_ok_window->window, &root_icon_drag_hotspot); gtk_widget_show (root_drag_not_ok_window); @@ -557,9 +723,7 @@ desktop_icon_drag_start (GtkWidget *widget, GdkEvent *event, desktop_icon_t *di) static void desktop_icon_drag_end (GtkWidget *widget, GdkEvent *event, desktop_icon_t *di) { -#if 0 in_desktop_dnd = 0; -#endif printf ("!!!!!!!! drag end!\n"); destroy_shaped_dnd_windows (); } @@ -696,7 +860,7 @@ char *drop_types [] = { }; static void -post_setup_desktop_icon (desktop_icon_t *di) +post_setup_desktop_icon (desktop_icon_t *di, int show) { desktop_icon_make_draggable (di); @@ -709,7 +873,8 @@ post_setup_desktop_icon (desktop_icon_t *di) /* 2. Double clicking executes the command */ gtk_signal_connect (GTK_OBJECT (di->widget), "button_press_event", GTK_SIGNAL_FUNC (dentry_button_click), di); - gtk_widget_show (di->widget); + if (show) + gtk_widget_show (di->widget); } /* Pops up the icon properties pages */ @@ -725,7 +890,7 @@ icon_properties (GtkWidget *widget, desktop_icon_t *di) di->widget = get_transparent_window_for_dentry (di->dentry); - post_setup_desktop_icon (di); + post_setup_desktop_icon (di, 1); gnome_desktop_entry_save (di->dentry); } } @@ -785,7 +950,7 @@ desktop_load_from_dentry (GnomeDesktopEntry *dentry) desktop_icons = g_list_prepend (desktop_icons, di); - post_setup_desktop_icon (di); + post_setup_desktop_icon (di, 0); desktop_icon_set_position (di); } @@ -976,8 +1141,6 @@ desktop_create_launch_entry (char *pathname, char *short_name) GTK_SIGNAL_FUNC (drop_on_launch_entry), di); gtk_widget_dnd_drop_set (window, TRUE, drop_types, ELEMENTS (drop_types), FALSE); - - gtk_widget_show (window); } static int @@ -1062,6 +1225,19 @@ desktop_reload (char *desktop_dir) } } +static void +desktop_load (char *desktop_dir) +{ + GList *l; + + desktop_reload (desktop_dir); + for (l = desktop_icons; l; l = l->next){ + desktop_icon_t *di = l->data; + + gtk_widget_show (di->widget); + } +} + /* * Copy the system defaults to the user ~/desktop directory and setup a * Home directory link @@ -1111,13 +1287,14 @@ desktop_root (void) void start_desktop (void) { + init_spot_list (); desktop_directory = concat_dir_and_file (home_dir, "desktop"); if (!exist_file (desktop_directory)) desktop_setup_default (desktop_directory); desktop_root (); - desktop_reload (desktop_directory); + desktop_load (desktop_directory); } /* diff --git a/gnome/gdesktop.h b/gnome/gdesktop.h index a14ccb6b9..e3b08f3e0 100644 --- a/gnome/gdesktop.h +++ b/gnome/gdesktop.h @@ -27,10 +27,14 @@ typedef struct { GtkWidget *widget; icon_t type; int x, y; + int grid_x, grid_y; char *title; char *pathname; } desktop_icon_t; +/* size of the snap to grid size */ +#define SNAP_X 80 +#define SNAP_Y 80 /* gtrans.c */ @@ -42,6 +46,8 @@ GtkWidget *make_transparent_window (char *file); /* gdesktop.c */ void drop_on_directory (GdkEventDropDataAvailable *event, char *dest, int force_manually); +void gnome_arrange_icons (void); void artificial_drag_start (GdkWindow *source_window, int x, int y); +extern int icons_snap_to_grid; #endif diff --git a/gnome/glayout.c b/gnome/glayout.c index a9fe75383..b3e840d0b 100644 --- a/gnome/glayout.c +++ b/gnome/glayout.c @@ -18,6 +18,7 @@ #include "panelize.h" #include "gcmd.h" #include "gcliplabel.h" +#include "gdesktop.h" #define UNDEFINED_INDEX -1 @@ -184,6 +185,7 @@ void save_panel_types (void) } void configure_box (void); +GtkCheckMenuItem *gnome_toggle_snap (void); GnomeUIInfo gnome_panel_file_menu [] = { { GNOME_APP_UI_ITEM, N_("New panel"), N_("Opens a new panel"), gnome_open_panel }, @@ -248,6 +250,12 @@ GnomeUIInfo gnome_panel_commands_menu [] = { { GNOME_APP_UI_ENDOFINFO, 0, 0 } }; +GnomeUIInfo gnome_panel_desktop_menu [] = { + { GNOME_APP_UI_ITEM, N_("Arrange icons"), N_("Arranges the icons on the desktop"), gnome_arrange_icons }, +/* { GNOME_APP_UI_TOGGLEITEM, N_("Desktop grid"), N_("Use a grid for laying out icons"), gnome_toggle_snap }, */ + { GNOME_APP_UI_ENDOFINFO, 0, 0 } +}; + GnomeUIInfo gnome_panel_about_menu [] = { { GNOME_APP_UI_ITEM, N_("About"), N_("Information on this program"), gnome_about_cmd, NULL, NULL, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_ABOUT }, @@ -260,10 +268,17 @@ GnomeUIInfo gnome_panel_menu [] = { { GNOME_APP_UI_SUBTREE, N_("Panel"), NULL, &gnome_panel_panel_menu }, { GNOME_APP_UI_SUBTREE, N_("Commands"), NULL, &gnome_panel_commands_menu }, { GNOME_APP_UI_SUBTREE, N_("Options"), NULL, &gnome_panel_options_menu }, + { GNOME_APP_UI_SUBTREE, N_("Desktop"), NULL, &gnome_panel_desktop_menu }, { GNOME_APP_UI_SUBTREE, N_("Help"), NULL, &gnome_panel_about_menu }, { GNOME_APP_UI_ENDOFINFO, 0, 0 } }; +GtkCheckMenuItem * +gnome_toggle_snap (void) +{ + return GTK_CHECK_MENU_ITEM (gnome_panel_desktop_menu [1].widget); +} + void gnome_init_panels () { @@ -293,7 +308,7 @@ create_container (Dlg_head *h, char *name) container->splitted = 0; app = gnome_app_new ("gmc", name); - gtk_widget_set_usize (GTK_WIDGET (app), 400, 300); + gtk_widget_set_usize (GTK_WIDGET (app), 500, 360); panel = panel_new (name); vbox = gtk_vbox_new (0, 0); diff --git a/gnome/gtrans.c b/gnome/gtrans.c index 408ea8f60..e043ef946 100644 --- a/gnome/gtrans.c +++ b/gnome/gtrans.c @@ -14,7 +14,6 @@ /* The spacing between the cute little icon and the text */ #define SPACING 2 - int want_transparent_icons = 1; int want_transparent_text = 0; @@ -86,8 +85,8 @@ layout_text (GtkWidget *widget, char *text) if (!window_width) { /* make an initial guess at window's width */ - if (row_width > (gdk_screen_width () / 12)) - window_width = gdk_screen_width () / 12; + if (row_width > SNAP_X) + window_width = SNAP_X; else window_width = row_width; } diff --git a/gnome/gview.c b/gnome/gview.c index cb38c6687..34cb7191d 100644 --- a/gnome/gview.c +++ b/gnome/gview.c @@ -23,6 +23,7 @@ void x_init_view (WView *view) { view->current_x = view->current_y = 0; + view->sadj = 0; } void diff --git a/src/setup.c b/src/setup.c index 2abe20506..2a25fdf95 100644 --- a/src/setup.c +++ b/src/setup.c @@ -45,6 +45,10 @@ #include "cmd.h" #include "x.h" +#ifdef HAVE_GNOME +# include "gdesktop.h" +#endif + #include "../vfs/vfs.h" #ifdef USE_NETCODE # include "../vfs/ftpfs.h" @@ -220,7 +224,11 @@ static struct { { "editor_edit_confirm_save", &edit_confirm_save }, #endif -#ifndef HAVE_GNOME +#ifdef HAVE_GNOME + { "want_transparent_text", &want_transparent_text }, + { "want_transparent_icons", &want_transparent_icons }, + { "icons_snap_to_grid", &icons_snap_to_grid }, +#else { "nice_rotating_dash", &nice_rotating_dash }, { "horizontal_split", &horizontal_split }, #endif