mc/gnome/gdesktop-icon.c

462 lines
12 KiB
C
Raw Normal View History

1998-10-21 07:41:56 +04:00
/* Desktop icon widget for the Midnight Commander
*
* Copyright (C) 1998 The Free Software Foundation
*
* Author: Federico Mena <federico@nuclecu.unam.mx>
1998-10-21 07:41:56 +04:00
*/
#include <config.h>
#include <gnome.h>
1999-01-19 01:37:39 +03:00
#include <sys/stat.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <gdk/gdkx.h>
#include "gdesktop-icon.h"
1999-01-19 01:37:39 +03:00
#include "dir.h"
1998-10-21 07:41:56 +04:00
#include "gdesktop.h"
/* Spacing between icon and text */
#define SPACING 2
/* The 50% gray stipple for selected icons */
#define gray50_width 2
#define gray50_height 2
static char gray50_bits[] = {
0x02, 0x01, };
1998-10-21 07:41:56 +04:00
static void desktop_icon_class_init (DesktopIconClass *class);
static void desktop_icon_init (DesktopIcon *dicon);
1998-10-23 18:31:02 +04:00
static void desktop_icon_realize (GtkWidget *widget);
1998-10-21 07:41:56 +04:00
static GtkWindowClass *parent_class;
/**
* desktop_icon_get_type
*
* Returns the Gtk type assigned to the DesktopIcon class.
*/
1998-10-21 07:41:56 +04:00
GtkType
desktop_icon_get_type (void)
{
static GtkType desktop_icon_type = 0;
if (!desktop_icon_type) {
GtkTypeInfo desktop_icon_info = {
"DesktopIcon",
sizeof (DesktopIcon),
sizeof (DesktopIconClass),
(GtkClassInitFunc) desktop_icon_class_init,
(GtkObjectInitFunc) desktop_icon_init,
NULL, /* reserved_1 */
NULL, /* reserved_2 */
(GtkClassInitFunc) NULL
};
desktop_icon_type = gtk_type_unique (gtk_window_get_type (), &desktop_icon_info);
}
return desktop_icon_type;
}
static void
desktop_icon_class_init (DesktopIconClass *class)
{
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
object_class = (GtkObjectClass *) class;
1998-10-21 07:41:56 +04:00
widget_class = (GtkWidgetClass *) class;
parent_class = gtk_type_class (gtk_window_get_type ());
1998-10-23 18:31:02 +04:00
widget_class->realize = desktop_icon_realize;
1998-10-21 07:41:56 +04:00
}
/* Callback used when the size of the icon text item changes */
static void
size_changed (GnomeIconTextItem *text, gpointer data)
{
DesktopIcon *dicon;
dicon = DESKTOP_ICON (data);
desktop_icon_reshape (dicon);
}
1998-10-30 20:08:03 +03:00
/* Callback used when the desktop icon's canvas is size_allocated. We reset the canvas scrolling
* region here, instead of doing it when the window shape changes, to avoid flicker.
*/
static void
canvas_size_allocated (GtkWidget *widget, GtkAllocation *allocation, gpointer data)
{
gnome_canvas_set_scroll_region (GNOME_CANVAS (widget),
0, 0,
allocation->width, allocation->height);
1998-10-30 20:08:03 +03:00
}
1998-10-21 07:41:56 +04:00
static void
desktop_icon_init (DesktopIcon *dicon)
{
GdkBitmap *stipple;
1998-10-30 20:08:03 +03:00
/* Set the window policy */
gtk_window_set_policy (GTK_WINDOW (dicon), TRUE, TRUE, TRUE);
1998-10-21 07:41:56 +04:00
/* Create the canvas */
dicon->canvas = gnome_canvas_new ();
1998-10-30 20:08:03 +03:00
gtk_signal_connect (GTK_OBJECT (dicon->canvas), "size_allocate",
(GtkSignalFunc) canvas_size_allocated,
NULL);
1998-10-21 07:41:56 +04:00
gtk_container_add (GTK_CONTAINER (dicon), dicon->canvas);
gtk_widget_show (dicon->canvas);
/* Create the icon and the text items */
dicon->icon = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (dicon->canvas)),
1998-10-21 07:41:56 +04:00
gnome_canvas_image_get_type (),
"anchor", GTK_ANCHOR_NW,
NULL);
dicon->text = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (dicon->canvas)),
1998-10-21 07:41:56 +04:00
gnome_icon_text_item_get_type (),
NULL);
stipple = gdk_bitmap_create_from_data (NULL, gray50_bits, gray50_width, gray50_height);
dicon->stipple = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (dicon->canvas)),
gnome_canvas_rect_get_type (),
"fill_stipple", stipple,
NULL);
gnome_canvas_item_hide (dicon->stipple);
gdk_bitmap_unref (stipple);
dicon->w_changed_id = gtk_signal_connect (GTK_OBJECT (dicon->text), "width_changed",
(GtkSignalFunc) size_changed,
dicon);
dicon->h_changed_id = gtk_signal_connect (GTK_OBJECT (dicon->text), "height_changed",
(GtkSignalFunc) size_changed,
dicon);
1998-10-21 07:41:56 +04:00
}
1998-10-23 18:31:02 +04:00
static void
desktop_icon_realize (GtkWidget *widget)
{
DesktopIcon *dicon;
1998-10-23 18:31:02 +04:00
g_return_if_fail (widget != NULL);
g_return_if_fail (IS_DESKTOP_ICON (widget));
dicon = DESKTOP_ICON (widget);
1998-10-23 18:31:02 +04:00
if (GTK_WIDGET_CLASS (parent_class)->realize)
(* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
/* Set the window decorations to none and hints to the appropriate combination */
gdk_window_set_decorations (widget->window, 0);
gdk_window_set_functions (widget->window, 0);
These are a bunch of changes to fix CORBA and session management. They are almost complete (i.e. to handle all nitty gritty cases), but they seem to be working OK right now. SM should be much more stable now. Please tell me if you find any weird behavior - Federico 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdesktop-icon.c (desktop_icon_realize): Remove the WM_CLIENT_LEADER property from icon windows so that window managers will not store SM information for them. * gnome-open-dialog.c: Added missing #includes. * gdesktop-init.c (desktop_init_at): Removed an unused variable. * gdesktop.h: Added some missing prototypes. * gmain.h: Added some missing prototypes. * Makefile.in: Added gsession.[ch] to the list of sources. * gmain.c (create_panels): Consider whether we have a CORBA server and session management. * gdesktop.c: #include "gdesktop-init.h" * gdesktop.c: Added a missing cast to GNOME_DIALOG. * gmain.c (create_panels): Removed the run_desktop global variable. * glayout.c (create_container): Set the wmclass of the panel to include its unique ID. * gsession.[ch]: New file with the functions that deal with session management. * glayout.c (gnome_exit): Use session_set_restart(). * gcorba.c (corba_init): Now returns an int with an error value. (corba_init_server): Initialize the server properly. Fixed all the object implementation code. (corba_create_window): New function used to create a window with the CORBA server. * gmain.c (gnome_check_super_user): Now the check for running as root is done here. There should be no GUI code in src/. 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * dlg.c (dlg_run_done): Do not call the callback of a NULL current widget. * setup.h: Added missing prototype for setup_init(). * filegui.c (check_progress_buttons): Added a missing return value. * dlg.c (remove_widget): Added a missing return value. * main.c: Removed the global directory_list variable. Removed the main_corba_register_server() function. * main.h: Removed the global run_desktop variable. * panel.h: Now the panel structure has a unique numerical ID used for session management. * screen.c (panel_new): Maintain a unique ID for each panel. * main.c (maybe_display_linksdir): Handle display of the desktop init dir here. (main): Call gnome_check_super_user(). (init_corba_with_args): Call corba_init_server(). * main.c (init_corba_with_args): Do CORBA initialization here. Also removed the global force_activation option. 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * vfs.c (vfs_add_current_stamps): Only do stamping of the panels if they exist. * mcserv.c: #include <sys/wait.h> (get_client): Put `#ifdef __EMX__' around an otherwise-unused variable. * utilvfs.c (vfs_split_url): Fix NULL <-> 0 confusion when comparing characters. * ftpfs.c (retrieve_dir): Removed unused variable dot_dot_found. * extfs.c (extfs_init): Assign `key' to c, not `&key'.
1999-03-30 10:09:56 +04:00
/* Set the proper GNOME hints */
gnome_win_hints_init ();
if (gnome_win_hints_wm_exists ()) {
gnome_win_hints_set_layer (widget, WIN_LAYER_DESKTOP);
gnome_win_hints_set_state (widget,
WIN_STATE_FIXED_POSITION
| WIN_STATE_ARRANGE_IGNORE
| WIN_STATE_STICKY);
gnome_win_hints_set_hints (widget,
WIN_HINTS_SKIP_FOCUS
| WIN_HINTS_SKIP_WINLIST
| WIN_HINTS_SKIP_TASKBAR);
}
/* Set the stipple color now that we have a style */
gnome_canvas_item_set (dicon->stipple,
"fill_color_gdk", &widget->style->bg[GTK_STATE_SELECTED],
NULL);
1998-10-23 18:31:02 +04:00
}
/* Sets the icon from the specified image. Does not re-create the window shape for the desktop
* icon.
*/
static void
set_icon (DesktopIcon *dicon, GdkImlibImage *im)
1998-10-21 07:41:56 +04:00
{
gnome_canvas_item_set (dicon->icon,
"image", im,
"width", (double) im->rgb_width,
"height", (double) im->rgb_height,
1998-10-21 07:41:56 +04:00
NULL);
}
/* Sets the text in the desktop icon, but does not re-create its window shape. */
static void
set_text (DesktopIcon *dicon, char *text)
1998-10-21 07:41:56 +04:00
{
int text_height;
double x1, y1, x2, y2;
gnome_canvas_item_get_bounds (dicon->text, &x1, &y1, &x2, &y2);
text_height = y2 = y1;
gtk_signal_handler_block (GTK_OBJECT (dicon->text), dicon->w_changed_id);
gtk_signal_handler_block (GTK_OBJECT (dicon->text), dicon->h_changed_id);
gnome_icon_text_item_configure (GNOME_ICON_TEXT_ITEM (dicon->text),
0, dicon->height - text_height,
DESKTOP_SNAP_X,
DESKTOP_ICON_FONT,
text,
TRUE,
FALSE);
gtk_signal_handler_unblock (GTK_OBJECT (dicon->text), dicon->w_changed_id);
gtk_signal_handler_unblock (GTK_OBJECT (dicon->text), dicon->h_changed_id);
}
/**
* desktop_icon_new
* @image: Imlib image with the icon.
* @text: Text to use for the icon.
*
* Creates a new desktop icon widget with the specified icon image and text. The icon has to be
* positioned at the desired place.
*
* Returns the newly-created desktop icon widget.
*/
GtkWidget *
desktop_icon_new (GdkImlibImage *image, char *text)
{
DesktopIcon *dicon;
g_return_val_if_fail (image != NULL, NULL);
g_return_val_if_fail (text != NULL, NULL);
dicon = gtk_type_new (desktop_icon_get_type ());
set_icon (dicon, image);
set_text (dicon, text);
desktop_icon_reshape (dicon);
return GTK_WIDGET (dicon);
}
/**
* desktop_icon_set_icon
* @dicon: The desktop icon to set the icon for
* @image: Imlib image with the icon.
*
* Sets a new icon for an existing desktop icon.
*/
void
desktop_icon_set_icon (DesktopIcon *dicon, GdkImlibImage *image)
{
g_return_if_fail (dicon != NULL);
g_return_if_fail (IS_DESKTOP_ICON (dicon));
g_return_if_fail (image != NULL);
set_icon (dicon, image);
desktop_icon_reshape (dicon);
}
/**
* desktop_icon_set_text
* @dicon: The desktop icon to set the text for
* @text: The new text to use for the icon's title
*
* Sets a new title for an existing desktop icon.
*/
void
desktop_icon_set_text (DesktopIcon *dicon, char *text)
{
g_return_if_fail (dicon != NULL);
g_return_if_fail (IS_DESKTOP_ICON (dicon));
g_return_if_fail (text != NULL);
set_text (dicon, text);
desktop_icon_reshape (dicon);
}
1998-10-30 20:08:03 +03:00
/* Computes and sets a new window shape for the desktop icon */
static void
create_window_shape (DesktopIcon *dicon, int icon_width, int icon_height, int text_width, int text_height)
{
GdkImlibImage *im;
GdkBitmap *mask;
GdkBitmap *im_mask;
GdkGC *mgc;
GdkColor c;
GnomeIconTextItem *i;
1998-10-30 20:08:03 +03:00
/* Create the initial mask and clear it */
mask = gdk_pixmap_new (GTK_WIDGET (dicon)->window, dicon->width, dicon->height, 1);
mgc = gdk_gc_new (mask);
c.pixel = 0;
gdk_gc_set_foreground (mgc, &c);
gdk_draw_rectangle (mask, mgc, TRUE, 0, 0, dicon->width, dicon->height);
c.pixel = 1;
gdk_gc_set_foreground (mgc, &c);
/* Paint the mask of the image */
im = GNOME_CANVAS_IMAGE (dicon->icon)->im;
gdk_imlib_render (im, icon_width, icon_height);
im_mask = gdk_imlib_move_mask (im);
1998-10-30 20:08:03 +03:00
if (im_mask && desktop_use_shaped_icons) {
gdk_draw_pixmap (mask,
mgc,
im_mask,
0, 0,
dicon->icon_x, dicon->icon_y,
1998-10-30 20:08:03 +03:00
icon_width, icon_height);
gdk_imlib_free_bitmap (im_mask);
} else
gdk_draw_rectangle (mask, mgc, TRUE,
dicon->icon_x, dicon->icon_y,
1998-10-30 20:08:03 +03:00
icon_width, icon_height);
/* Fill the area for the text */
i = GNOME_ICON_TEXT_ITEM (dicon->text);
if (desktop_use_shaped_text && !i->editing && !i->selected)
gnome_icon_paint_text (i->ti,
mask, mgc,
dicon->text_x + 2,
dicon->text_y + 2,
GTK_JUSTIFY_CENTER);
else
gdk_draw_rectangle (mask, mgc, TRUE,
dicon->text_x,
dicon->text_y,
text_width, text_height);
1998-10-30 20:08:03 +03:00
if (!GTK_WIDGET_REALIZED (dicon))
gtk_widget_realize (GTK_WIDGET (dicon));
gtk_widget_shape_combine_mask (GTK_WIDGET (dicon), mask, 0, 0);
gdk_bitmap_unref (mask);
gdk_gc_unref (mgc);
}
/**
* desktop_icon_reshape
* @dicon: The desktop icon whose shape will be recalculated
*
* Recomputes the window shape for the specified desktop icon. This needs to be called only when
* the global desktop_use_shaped_icons flag changes.
*/
void
desktop_icon_reshape (DesktopIcon *dicon)
{
GtkArg args[2];
int icon_width, icon_height;
int text_width, text_height;
int total_height;
double x1, y1, x2, y2;
g_return_if_fail (dicon != NULL);
g_return_if_fail (IS_DESKTOP_ICON (dicon));
/* Get size of icon image */
args[0].name = "width";
args[1].name = "height";
gtk_object_getv (GTK_OBJECT (dicon->icon), 2, args);
icon_width = GTK_VALUE_DOUBLE (args[0]);
icon_height = GTK_VALUE_DOUBLE (args[1]);
/* Get size of icon text */
gnome_canvas_item_get_bounds (dicon->text, &x1, &y1, &x2, &y2);
text_width = x2 - x1;
text_height = y2 - y1;
total_height = icon_height + SPACING + text_height;
/* Calculate new size of widget */
dicon->width = MAX (icon_width, DESKTOP_SNAP_X);
dicon->height = MAX (total_height, DESKTOP_SNAP_Y);
/* Set new position of children */
gnome_canvas_item_set (dicon->icon,
"x", (dicon->width - icon_width) / 2.0,
"y", (dicon->height - total_height) / 2.0,
NULL);
gnome_canvas_item_set (dicon->stipple,
"x1", 0.0,
"y1", 0.0,
"x2", (double) dicon->width,
"y2", (double) dicon->height - text_height - SPACING,
NULL);
if (dicon->width <= DESKTOP_SNAP_X)
gnome_icon_text_item_setxy (GNOME_ICON_TEXT_ITEM (dicon->text),
0,
dicon->height - text_height);
else
gnome_icon_text_item_setxy (GNOME_ICON_TEXT_ITEM (dicon->text),
(dicon->width - DESKTOP_SNAP_X) / 2,
dicon->height - text_height);
gtk_widget_set_usize (GTK_WIDGET (dicon), dicon->width, dicon->height);
dicon->icon_x = (int) ((dicon->width - icon_width) / 2.0 + 0.5);
dicon->icon_y = (int) ((dicon->height - total_height) / 2.0 + 0.5);
dicon->icon_w = icon_width;
dicon->icon_h = icon_height;
gnome_canvas_item_get_bounds (dicon->text, &x1, &y1, &x2, &y2);
dicon->text_x = x1;
dicon->text_y = y1;
dicon->text_w = text_width;
dicon->text_h = text_height;
/* Create and set the window shape */
create_window_shape (dicon, icon_width, icon_height, text_width, text_height);
1998-10-21 07:41:56 +04:00
}
/**
* desktop_icon_select
* @dicon: The desktop icon which will be selected/unselected
* @sel: TRUE if icon should be selected, FALSE if it should be unselected
*
* Selects or unselects the icon. This means setting the selection flag of the icon text item as
* appropriate, and displaying the icon image as selected or not.
*/
void
desktop_icon_select (DesktopIcon *dicon, int sel)
{
g_return_if_fail (dicon != NULL);
g_return_if_fail (IS_DESKTOP_ICON (dicon));
gnome_icon_text_item_select (GNOME_ICON_TEXT_ITEM (dicon->text), sel);
if (desktop_use_shaped_text)
desktop_icon_reshape (dicon);
if (sel)
gnome_canvas_item_show (dicon->stipple);
else
gnome_canvas_item_hide (dicon->stipple);
}