revised image prop, icon patch



Hi,

Revised patches for GtkImage properties and setting window icons.

Havoc

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.2216
diff -u -p -u -r1.2216 ChangeLog
--- ChangeLog	2001/08/27 01:05:05	1.2216
+++ ChangeLog	2001/08/28 05:52:21
@@ -1,3 +1,35 @@
+2001-08-28  Havoc Pennington  <hp pobox com>
+
+	* demos/gtk-demo/main.c (setup_default_icon): add default icon
+
+	* gtk/gtkradiobutton.c (gtk_radio_button_new_with_mnemonic):
+	warning fix
+	(gtk_radio_button_new_with_label): warning fix
+
+	* gtk/gtkdnd.c: used some random GtkImage private structs, 
+	update to reflect GtkImage changes
+
+	* gdk/x11/gdkwindow-x11.c (gdk_window_set_icon_list): don't check
+	whether the hint is supported, just always set the icon. A task
+	list might want to use it even if the WM doesn't, and the WM may
+	change over time. Also, XDeleteProperty() if list == NULL.
+
+	* gtk/gtkwindow.c (gtk_window_set_icon_list)
+	(gtk_window_get_icon_list)
+	(gtk_window_set_icon)
+	(gtk_window_get_icon)
+	(gtk_window_set_default_icon_list)
+	(gtk_window_get_default_icon_list):
+	new functions
+
+	* gtk/gtk-boxed.defs (GtkIconSet): add GtkIconSet
+
+	* gtk/gtkimage.c: Implement property support, bug #59408
+
+	* gtk/gtkcontainer.c (gtk_container_add): make the warning message
+	on reparent-without-removing-first a bit more helpful.
+	Let's just destroy this FAQ.
+
 2001-08-26  Alexander Larsson  <alla lysator liu se>
 
 	* gtk/gtkbutton.[ch]:
Index: demos/gtk-demo/main.c
===================================================================
RCS file: /cvs/gnome/gtk+/demos/gtk-demo/main.c,v
retrieving revision 1.28
diff -u -p -u -r1.28 main.c
--- demos/gtk-demo/main.c	2001/08/10 03:45:44	1.28
+++ demos/gtk-demo/main.c	2001/08/28 05:52:21
@@ -722,6 +722,58 @@ create_tree (void)
   return tree_view;
 }
 
+static void
+setup_default_icon (void)
+{
+  GdkPixbuf *pixbuf;
+  
+  /* Try in current directory, in case we haven't yet been installed
+   * (would be wrong in a real app)
+   */
+  pixbuf = gdk_pixbuf_new_from_file ("./gtk-logo-rgb.gif", NULL);
+
+  if (pixbuf == NULL)
+    {
+      GError *err;
+
+      err = NULL;
+      pixbuf = gdk_pixbuf_new_from_file (DEMOCODEDIR"/gtk-logo-rgb.gif",
+                                         &err);
+
+      /* Ignoring this error (passing NULL instead of &err above)
+       * would probably be reasonable for most apps.  We're just
+       * showing off.
+       */
+      if (err)
+        {
+          GtkWidget *dialog;
+          
+          dialog = gtk_message_dialog_new (NULL, 0,
+                                           GTK_MESSAGE_ERROR,
+                                           GTK_BUTTONS_CLOSE,
+                                           "Failed to read icon file "DEMOCODEDIR"/gtk-logo-rgb.gif: %s",
+                                           err->message);
+          g_error_free (err);
+
+          gtk_signal_connect (GTK_OBJECT (dialog),
+                              "response",
+                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
+                              NULL);
+        }
+    }
+
+  if (pixbuf)
+    {
+      GList *list;      
+
+      list = NULL;
+      list = g_list_append (list, pixbuf);
+      gtk_window_set_default_icon_list (list);
+      g_list_free (list);
+      g_object_unref (G_OBJECT (pixbuf));
+    }
+}
+
 int
 main (int argc, char **argv)
 {
@@ -744,6 +796,8 @@ main (int argc, char **argv)
   /* -- End of hack -- */
   
   gtk_init (&argc, &argv);
+
+  setup_default_icon ();
   
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   gtk_window_set_title (GTK_WINDOW (window), "GTK+ Code Demos");
Index: docs/reference/gdk/tmpl/windows.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gdk/tmpl/windows.sgml,v
retrieving revision 1.14
diff -u -p -u -r1.14 windows.sgml
--- docs/reference/gdk/tmpl/windows.sgml	2001/08/10 03:45:45	1.14
+++ docs/reference/gdk/tmpl/windows.sgml	2001/08/28 05:52:21
@@ -793,6 +793,7 @@ Windows
 
 @window: 
 @pixbufs: 
+<!-- # Unused Parameters # -->
 @Returns: 
 
 
Index: docs/reference/gtk/tmpl/gtkbutton.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtkbutton.sgml,v
retrieving revision 1.7
diff -u -p -u -r1.7 gtkbutton.sgml
--- docs/reference/gtk/tmpl/gtkbutton.sgml	2001/03/23 22:21:05	1.7
+++ docs/reference/gtk/tmpl/gtkbutton.sgml	2001/08/28 05:52:21
@@ -181,3 +181,13 @@ there is actually a #GtkLabel inside of 
 The #GtkReliefStyle as outlined in gtk_button_set_relief().
 </para>
 
+<!-- ##### ARG GtkButton:use-underline ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkButton:use-stock ##### -->
+<para>
+
+</para>
+
Index: docs/reference/gtk/tmpl/gtkimage.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtkimage.sgml,v
retrieving revision 1.8
diff -u -p -u -r1.8 gtkimage.sgml
--- docs/reference/gtk/tmpl/gtkimage.sgml	2001/08/26 02:03:09	1.8
+++ docs/reference/gtk/tmpl/gtkimage.sgml	2001/08/28 05:52:21
@@ -278,3 +278,53 @@ Gets the GtkImage
 @mask: a GDKBitmap that indicates which parts of the image should be transparent.
 
 
+<!-- ##### ARG GtkImage:pixbuf ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkImage:pixmap ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkImage:image ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkImage:mask ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkImage:file ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkImage:stock ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkImage:icon-set ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkImage:icon-size ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkImage:pixbuf-animation ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkImage:storage-type ##### -->
+<para>
+
+</para>
+
Index: docs/reference/gtk/tmpl/gtkwindow.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtkwindow.sgml,v
retrieving revision 1.20
diff -u -p -u -r1.20 gtkwindow.sgml
--- docs/reference/gtk/tmpl/gtkwindow.sgml	2001/08/10 03:46:05	1.20
+++ docs/reference/gtk/tmpl/gtkwindow.sgml	2001/08/28 05:52:21
@@ -549,3 +549,13 @@ The position of the window.
 
 </para>
 
+<!-- ##### ARG GtkWindow:icon-list ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkWindow:icon ##### -->
+<para>
+
+</para>
+
Index: gdk/gdkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkwindow.h,v
retrieving revision 1.29
diff -u -p -u -r1.29 gdkwindow.h
--- gdk/gdkwindow.h	2001/08/23 15:26:46	1.29
+++ gdk/gdkwindow.h	2001/08/28 05:52:21
@@ -444,7 +444,7 @@ GdkEventMask  gdk_window_get_events	 (Gd
 void	      gdk_window_set_events	 (GdkWindow	  *window,
 					  GdkEventMask	   event_mask);
 
-gboolean      gdk_window_set_icon_list   (GdkWindow       *window,
+void          gdk_window_set_icon_list   (GdkWindow       *window,
 					  GList           *pixbufs);
 void	      gdk_window_set_icon	 (GdkWindow	  *window, 
 					  GdkWindow	  *icon_window,
Index: gdk/x11/gdkwindow-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkwindow-x11.c,v
retrieving revision 1.123
diff -u -p -u -r1.123 gdkwindow-x11.c
--- gdk/x11/gdkwindow-x11.c	2001/08/10 03:46:07	1.123
+++ gdk/x11/gdkwindow-x11.c	2001/08/28 05:52:22
@@ -2325,7 +2325,6 @@ gdk_window_set_override_redirect (GdkWin
  * gdk_window_set_icon_list:
  * @window: The #GdkWindow toplevel window to set the icon of.
  * @pixbufs: A list of pixbufs, of different sizes.
- * @Returns: %TRUE if the icons were set, false otherwise
  *
  * Sets a list of icons for the window. One of these will be used
  * to represent the window when it has been iconified. The icon is
@@ -2335,12 +2334,8 @@ gdk_window_set_override_redirect (GdkWin
  * image quality since the window manager may only need to scale the
  * icon by a small amount or not at all.
  *
- * On the X11 backend this call might fail if the window manager
- * doesn't support the Extended Window Manager Hints. Then this
- * function returns FALSE, and the application should fall back
- * to #gdk_window_set_icon().
  **/
-gboolean
+void
 gdk_window_set_icon_list (GdkWindow *window,
 			  GList     *pixbufs)
 {
@@ -2354,14 +2349,10 @@ gdk_window_set_icon_list (GdkWindow *win
   gint x, y;
   gint n_channels;
   
-  g_return_val_if_fail (window != NULL, FALSE);
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
-    return FALSE;
-
-  if (!gdk_net_wm_supports (gdk_atom_intern ("_NET_WM_ICON", FALSE)))
-    return FALSE;
+    return;
   
   l = pixbufs;
   size = 0;
@@ -2417,15 +2408,22 @@ gdk_window_set_icon_list (GdkWindow *win
 
       l = g_list_next (l);
     }
-
-  XChangeProperty (GDK_WINDOW_XDISPLAY (window),
-		   GDK_WINDOW_XID (window),
-		   gdk_atom_intern ("_NET_WM_ICON", FALSE),
-		   XA_CARDINAL, 32,
-		   PropModeReplace,
-		   (guchar*) data, size);
 
-  return TRUE;
+  if (size > 0)
+    {
+      XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+                       GDK_WINDOW_XID (window),
+                       gdk_atom_intern ("_NET_WM_ICON", FALSE),
+                       XA_CARDINAL, 32,
+                       PropModeReplace,
+                       (guchar*) data, size);
+    }
+  else
+    {
+      XDeleteProperty (GDK_WINDOW_XDISPLAY (window),
+                       GDK_WINDOW_XID (window),
+                       gdk_atom_intern ("_NET_WM_ICON", FALSE));
+    }
 }
 
 void          
Index: gtk/gtk-boxed.defs
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtk-boxed.defs,v
retrieving revision 1.16
diff -u -p -u -r1.16 gtk-boxed.defs
--- gtk/gtk-boxed.defs	2001/07/25 13:36:02	1.16
+++ gtk/gtk-boxed.defs	2001/08/28 05:52:22
@@ -23,6 +23,11 @@
   gtk_requisition_free
   "sizeof(GtkRequisition)")
 
+(define-boxed GtkIconSet
+  gtk_icon_set_ref
+  gtk_icon_set_unref
+  "sizeof(GtkIconSet)")
+
 ;; TextView
 
 (define-boxed GtkTextIter
Index: gtk/gtkcontainer.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcontainer.c,v
retrieving revision 1.86
diff -u -p -u -r1.86 gtkcontainer.c
--- gtk/gtkcontainer.c	2001/08/23 23:38:32	1.86
+++ gtk/gtkcontainer.c	2001/08/28 05:52:22
@@ -858,7 +858,8 @@ gtk_container_add (GtkContainer *contain
   if (widget->parent != NULL)
     {
       g_warning ("Attempting to add a widget with type %s to a container of "
-                 "type %s, but the widget is already inside a container of type %s",
+                 "type %s, but the widget is already inside a container of type %s, "
+                 "the GTK+ FAQ at http://www.gtk.org/faq/ explains how to reparent a widget.",
                  g_type_name (G_OBJECT_TYPE (widget)),
                  g_type_name (G_OBJECT_TYPE (container)),
                  g_type_name (G_OBJECT_TYPE (widget->parent)));
Index: gtk/gtkdnd.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkdnd.c,v
retrieving revision 1.66
diff -u -p -u -r1.66 gtkdnd.c
--- gtk/gtkdnd.c	2001/07/05 03:21:52	1.66
+++ gtk/gtkdnd.c	2001/08/28 05:52:23
@@ -78,6 +78,7 @@ struct _GtkDragSourceSite 
     GtkImagePixbufData pixbuf;
     GtkImageStockData stock;
   } icon_data;
+  GdkBitmap *icon_mask;
 
   GdkColormap       *colormap;	         /* Colormap for drag icon */
 
@@ -1941,8 +1942,8 @@ gtk_drag_source_unset_icon (GtkDragSourc
     case GTK_IMAGE_PIXMAP:
       if (site->icon_data.pixmap.pixmap)
 	gdk_pixmap_unref (site->icon_data.pixmap.pixmap);
-      if (site->icon_data.pixmap.mask)
-	gdk_pixmap_unref (site->icon_data.pixmap.mask);
+      if (site->icon_mask)
+	gdk_pixmap_unref (site->icon_mask);
       break;
     case GTK_IMAGE_PIXBUF:
       g_object_unref (G_OBJECT (site->icon_data.pixbuf.pixbuf));
@@ -1999,7 +2000,7 @@ gtk_drag_source_set_icon (GtkWidget     
   site->icon_type = GTK_IMAGE_PIXMAP;
   
   site->icon_data.pixmap.pixmap = pixmap;
-  site->icon_data.pixmap.mask = mask;
+  site->icon_mask = mask;
   site->colormap = colormap;
 }
 
@@ -2683,7 +2684,7 @@ gtk_drag_source_event_cb (GtkWidget     
 		      gtk_drag_set_icon_pixmap (context,
 						site->colormap,
 						site->icon_data.pixmap.pixmap,
-						site->icon_data.pixmap.mask,
+						site->icon_mask,
 						-2, -2);
 		      break;
 		    case GTK_IMAGE_PIXBUF:
Index: gtk/gtkimage.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkimage.c,v
retrieving revision 1.28
diff -u -p -u -r1.28 gtkimage.c
--- gtk/gtkimage.c	2001/08/25 03:15:26	1.28
+++ gtk/gtkimage.c	2001/08/28 05:52:23
@@ -28,8 +28,11 @@
 #include "gtkimage.h"
 #include "gtkiconfactory.h"
 #include "gtkstock.h"
+#include "gtkintl.h"
 #include <string.h>
 
+#define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON
+
 static void gtk_image_class_init   (GtkImageClass  *klass);
 static void gtk_image_init         (GtkImage       *image);
 static gint gtk_image_expose       (GtkWidget      *widget,
@@ -44,8 +47,32 @@ static void gtk_image_update_size  (GtkI
                                     gint            image_width,
                                     gint            image_height);
 
+static void gtk_image_set_property      (GObject          *object,
+					 guint             prop_id,
+					 const GValue     *value,
+					 GParamSpec       *pspec);
+static void gtk_image_get_property      (GObject          *object,
+					 guint             prop_id,
+					 GValue           *value,
+					 GParamSpec       *pspec);
+
 static gpointer parent_class;
 
+enum
+{
+  PROP_0,
+  PROP_PIXBUF,
+  PROP_PIXMAP,
+  PROP_IMAGE,
+  PROP_MASK,
+  PROP_FILE,
+  PROP_STOCK,
+  PROP_ICON_SET,
+  PROP_ICON_SIZE,
+  PROP_PIXBUF_ANIMATION,
+  PROP_STORAGE_TYPE
+};
+
 GtkType
 gtk_image_get_type (void)
 {
@@ -74,20 +101,109 @@ gtk_image_get_type (void)
 static void
 gtk_image_class_init (GtkImageClass *class)
 {
+  GObjectClass *gobject_class;
   GtkObjectClass *object_class;
   GtkWidgetClass *widget_class;
 
   parent_class = g_type_class_peek_parent (class);
 
-  object_class = (GtkObjectClass *) class;
+  gobject_class = G_OBJECT_CLASS (class);
   
+  gobject_class->set_property = gtk_image_set_property;
+  gobject_class->get_property = gtk_image_get_property;
+  
+  object_class = GTK_OBJECT_CLASS (class);
+  
   object_class->destroy = gtk_image_destroy;
-
-  widget_class = (GtkWidgetClass*) class;
 
+  widget_class = GTK_WIDGET_CLASS (class);
+  
   widget_class->expose_event = gtk_image_expose;
   widget_class->size_request = gtk_image_size_request;
   widget_class->unmap = gtk_image_unmap;
+  
+  g_object_class_install_property (gobject_class,
+                                   PROP_PIXBUF,
+                                   g_param_spec_object ("pixbuf",
+                                                        _("Pixbuf"),
+                                                        _("A GdkPixbuf to display."),
+                                                        GDK_TYPE_PIXBUF,
+                                                        G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_PIXMAP,
+                                   g_param_spec_object ("pixmap",
+                                                        _("Pixmap"),
+                                                        _("A GdkPixmap to display."),
+                                                        GDK_TYPE_PIXMAP,
+                                                        G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_IMAGE,
+                                   g_param_spec_object ("image",
+                                                        _("Image"),
+                                                        _("A GdkImage to display."),
+                                                        GDK_TYPE_IMAGE,
+                                                        G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_MASK,
+                                   g_param_spec_object ("mask",
+                                                        _("Mask"),
+                                                        _("Mask bitmap to use with GdkImage or GdkPixmap"),
+                                                        GDK_TYPE_PIXMAP,
+                                                        G_PARAM_READWRITE));
+  
+  g_object_class_install_property (gobject_class,
+                                   PROP_FILE,
+                                   g_param_spec_string ("file",
+                                                        _("Filename"),
+                                                        _("Filename to load and siplay."),
+                                                        NULL,
+                                                        G_PARAM_WRITABLE));
+  
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_STOCK,
+                                   g_param_spec_string ("stock",
+                                                        _("Stock ID"),
+                                                        _("Stock ID for a stock image to display."),
+                                                        NULL,
+                                                        G_PARAM_READWRITE));
+  
+  g_object_class_install_property (gobject_class,
+                                   PROP_ICON_SET,
+                                   g_param_spec_boxed ("icon_set",
+                                                       _("Icon set"),
+                                                       _("Icon set to display."),
+                                                       GTK_TYPE_ICON_SET,
+                                                       G_PARAM_READWRITE));
+  
+  g_object_class_install_property (gobject_class,
+                                   PROP_ICON_SIZE,
+                                   g_param_spec_int ("icon_size",
+                                                     _("Icon size"),
+                                                     _("Size to use for stock icon or icon set."),
+                                                     0, G_MAXINT,
+                                                     DEFAULT_ICON_SIZE,
+                                                     G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_PIXBUF_ANIMATION,
+                                   g_param_spec_object ("pixbuf_animation",
+                                                        _("Animation"),
+                                                        _("GdkPixbufAnimation to display."),
+                                                        GDK_TYPE_PIXBUF_ANIMATION,
+                                                        G_PARAM_READWRITE));
+  
+  g_object_class_install_property (gobject_class,
+                                   PROP_STORAGE_TYPE,
+                                   g_param_spec_enum ("storage_type",
+                                                      _("Storage type"),
+                                                      _("The representation being used for image data."),
+                                                      GTK_TYPE_IMAGE_TYPE,
+                                                      GTK_IMAGE_EMPTY,
+                                                      G_PARAM_READABLE));
 }
 
 static void
@@ -96,6 +212,8 @@ gtk_image_init (GtkImage *image)
   GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW);
 
   image->storage_type = GTK_IMAGE_EMPTY;
+  image->icon_size = DEFAULT_ICON_SIZE;
+  image->mask = NULL;
 }
 
 static void
@@ -108,6 +226,167 @@ gtk_image_destroy (GtkObject *object)
   GTK_OBJECT_CLASS (parent_class)->destroy (object);
 }
 
+static void 
+gtk_image_set_property (GObject      *object,
+			guint         prop_id,
+			const GValue *value,
+			GParamSpec   *pspec)
+{
+  GtkImage *image;
+
+  image = GTK_IMAGE (object);
+  
+  switch (prop_id)
+    {
+    case PROP_PIXBUF:
+      gtk_image_set_from_pixbuf (image,
+                                 g_value_get_object (value));
+      break;
+    case PROP_PIXMAP:
+      gtk_image_set_from_pixmap (image,
+                                 g_value_get_object (value),
+                                 image->mask);
+      break;
+    case PROP_IMAGE:
+      gtk_image_set_from_image (image,
+                                g_value_get_object (value),
+                                image->mask);
+      break;
+    case PROP_MASK:
+      /* If current storage type doesn't support a mask,
+       * we switch to one that does. This allows setting
+       * mask first then the pixmap or image.
+       */
+      if (image->storage_type == GTK_IMAGE_PIXMAP)
+        gtk_image_set_from_pixmap (image,
+                                   image->data.pixmap.pixmap,
+                                   g_value_get_object (value));
+      else if (image->storage_type == GTK_IMAGE_IMAGE)
+        gtk_image_set_from_image (image,
+                                  image->data.image.image,
+                                  g_value_get_object (value));
+      else
+        gtk_image_set_from_pixmap (image,
+                                   NULL,
+                                   g_value_get_object (value));
+      break;
+    case PROP_FILE:
+      gtk_image_set_from_file (image,
+                               g_value_get_string (value));
+      break;
+    case PROP_STOCK:
+      gtk_image_set_from_stock (image, g_value_get_string (value),
+                                image->icon_size);
+      break;
+    case PROP_ICON_SET:
+      gtk_image_set_from_icon_set (image, g_value_get_boxed (value),
+                                   image->icon_size);
+      break;
+    case PROP_ICON_SIZE:
+      /* If current storage type doesn't support icon size,
+       * we switch to one that does. This allows setting
+       * size first then the stock ID or icon set
+       */
+      if (image->storage_type == GTK_IMAGE_STOCK)
+        gtk_image_set_from_stock (image,
+                                  image->data.stock.stock_id,
+                                  g_value_get_int (value));
+      else if (image->storage_type == GTK_IMAGE_ICON_SET)
+        gtk_image_set_from_icon_set (image,
+                                     image->data.icon_set.icon_set,
+                                     g_value_get_int (value));
+      else
+        gtk_image_set_from_stock (image,
+                                  GTK_STOCK_MISSING_IMAGE,
+                                  g_value_get_int (value));
+      break;
+    case PROP_PIXBUF_ANIMATION:
+      gtk_image_set_from_animation (image,
+                                    g_value_get_object (value));
+      break;
+      
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void 
+gtk_image_get_property (GObject     *object,
+			guint        prop_id,
+			GValue      *value,
+			GParamSpec  *pspec)
+{
+  GtkImage *image;
+
+  image = GTK_IMAGE (object);
+
+  /* The "getter" functions whine if you try to get the wrong
+   * storage type. This function is instead robust against that,
+   * so that GUI builders don't have to jump through hoops
+   * to avoid g_warning
+   */
+  
+  switch (prop_id)
+    {
+    case PROP_PIXBUF:
+      if (image->storage_type != GTK_IMAGE_PIXBUF)
+        g_value_set_object (value, NULL);
+      else
+        g_value_set_object (value,
+                            gtk_image_get_pixbuf (image));
+      break;
+    case PROP_PIXMAP:
+      if (image->storage_type != GTK_IMAGE_PIXMAP)
+        g_value_set_object (value, NULL);
+      else
+        g_value_set_object (value,
+                            image->data.pixmap.pixmap);
+      break;
+    case PROP_MASK:
+      g_value_set_object (value, image->mask);
+      break;
+    case PROP_IMAGE:
+      if (image->storage_type != GTK_IMAGE_IMAGE)
+        g_value_set_object (value, NULL);
+      else
+        g_value_set_object (value,
+                            image->data.image.image);
+      break;
+    case PROP_STOCK:
+      if (image->storage_type != GTK_IMAGE_STOCK)
+        g_value_set_string (value, NULL);
+      else
+        g_value_set_string (value,
+                            image->data.stock.stock_id);
+      break;
+    case PROP_ICON_SET:
+      if (image->storage_type != GTK_IMAGE_ICON_SET)
+        g_value_set_boxed (value, NULL);
+      else
+        g_value_set_boxed (value,
+                           image->data.icon_set.icon_set);
+      break;      
+    case PROP_ICON_SIZE:
+        g_value_set_int (value, image->icon_size);
+      break;
+    case PROP_PIXBUF_ANIMATION:
+      if (image->storage_type != GTK_IMAGE_ANIMATION)
+        g_value_set_object (value, NULL);
+      else
+        g_value_set_object (value,
+                            image->data.anim.anim);
+      break;
+    case PROP_STORAGE_TYPE:
+      g_value_set_enum (value, image->storage_type);
+      break;
+      
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
 
 /**
  * gtk_image_new_from_pixmap:
@@ -328,6 +607,8 @@ gtk_image_set_from_pixmap (GtkImage  *im
                     GDK_IS_PIXMAP (pixmap));
   g_return_if_fail (mask == NULL ||
                     GDK_IS_PIXMAP (mask));
+
+  g_object_freeze_notify (G_OBJECT (image));
   
   if (pixmap)
     g_object_ref (G_OBJECT (pixmap));
@@ -345,7 +626,7 @@ gtk_image_set_from_pixmap (GtkImage  *im
       image->storage_type = GTK_IMAGE_PIXMAP;
 
       image->data.pixmap.pixmap = pixmap;
-      image->data.pixmap.mask = mask;
+      image->mask = mask;
 
       gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height);
 
@@ -357,6 +638,11 @@ gtk_image_set_from_pixmap (GtkImage  *im
       if (mask)
         g_object_unref (G_OBJECT (mask));
     }
+
+  g_object_notify (G_OBJECT (image), "pixmap");
+  g_object_notify (G_OBJECT (image), "mask");
+  
+  g_object_thaw_notify (G_OBJECT (image));
 }
 
 /**
@@ -379,6 +665,7 @@ gtk_image_set_from_image  (GtkImage  *im
   g_return_if_fail (mask == NULL ||
                     GDK_IS_PIXMAP (mask));
 
+  g_object_freeze_notify (G_OBJECT (image));
   
   if (gdk_image)
     g_object_ref (G_OBJECT (gdk_image));
@@ -393,7 +680,7 @@ gtk_image_set_from_image  (GtkImage  *im
       image->storage_type = GTK_IMAGE_IMAGE;
 
       image->data.image.image = gdk_image;
-      image->data.image.mask = mask;
+      image->mask = mask;
 
       gtk_image_update_size (image, gdk_image->width, gdk_image->height);
     }
@@ -403,6 +690,11 @@ gtk_image_set_from_image  (GtkImage  *im
       if (mask)
         g_object_unref (G_OBJECT (mask));
     }
+
+  g_object_notify (G_OBJECT (image), "image");
+  g_object_notify (G_OBJECT (image), "mask");
+  
+  g_object_thaw_notify (G_OBJECT (image));
 }
 
 /**
@@ -421,11 +713,16 @@ gtk_image_set_from_file   (GtkImage    *
   
   g_return_if_fail (GTK_IS_IMAGE (image));
   g_return_if_fail (filename != NULL);
+
+  g_object_freeze_notify (G_OBJECT (image));
   
   gtk_image_reset (image);
 
   if (filename == NULL)
-    return;
+    {
+      g_object_thaw_notify (G_OBJECT (image));
+      return;
+    }
   
   anim = gdk_pixbuf_animation_new_from_file (filename, NULL);
 
@@ -434,6 +731,7 @@ gtk_image_set_from_file   (GtkImage    *
       gtk_image_set_from_stock (image,
                                 GTK_STOCK_MISSING_IMAGE,
                                 GTK_ICON_SIZE_BUTTON);
+      g_object_thaw_notify (G_OBJECT (image));
       return;
     }
 
@@ -453,6 +751,8 @@ gtk_image_set_from_file   (GtkImage    *
     }
 
   g_object_unref (G_OBJECT (anim));
+
+  g_object_thaw_notify (G_OBJECT (image));
 }
 
 /**
@@ -470,6 +770,8 @@ gtk_image_set_from_pixbuf (GtkImage  *im
   g_return_if_fail (GTK_IS_IMAGE (image));
   g_return_if_fail (pixbuf == NULL ||
                     GDK_IS_PIXBUF (pixbuf));
+
+  g_object_freeze_notify (G_OBJECT (image));
   
   if (pixbuf)
     g_object_ref (G_OBJECT (pixbuf));
@@ -486,6 +788,10 @@ gtk_image_set_from_pixbuf (GtkImage  *im
                              gdk_pixbuf_get_width (pixbuf),
                              gdk_pixbuf_get_height (pixbuf));
     }
+
+  g_object_notify (G_OBJECT (image), "pixbuf");
+  
+  g_object_thaw_notify (G_OBJECT (image));
 }
 
 /**
@@ -502,22 +808,34 @@ gtk_image_set_from_stock  (GtkImage     
                            const gchar    *stock_id,
                            GtkIconSize     size)
 {
+  gchar *new_id;
+  
   g_return_if_fail (GTK_IS_IMAGE (image));
+
+  g_object_freeze_notify (G_OBJECT (image));
+
+  /* in case stock_id == image->data.stock.stock_id */
+  new_id = g_strdup (stock_id);
   
   gtk_image_reset (image);
 
-  if (stock_id)
-    {      
+  if (new_id)
+    {
       image->storage_type = GTK_IMAGE_STOCK;
       
-      image->data.stock.stock_id = g_strdup (stock_id);
-      image->data.stock.size = size;
+      image->data.stock.stock_id = new_id;
+      image->icon_size = size;
 
       /* Size is demand-computed in size request method
        * if we're a stock image, since changing the
        * style impacts the size request
        */
     }
+
+  g_object_notify (G_OBJECT (image), "stock");
+  g_object_notify (G_OBJECT (image), "icon_size");
+  
+  g_object_thaw_notify (G_OBJECT (image));
 }
 
 /**
@@ -536,6 +854,8 @@ gtk_image_set_from_icon_set  (GtkImage  
 {
   g_return_if_fail (GTK_IS_IMAGE (image));
 
+  g_object_freeze_notify (G_OBJECT (image));
+  
   if (icon_set)
     gtk_icon_set_ref (icon_set);
   
@@ -546,12 +866,17 @@ gtk_image_set_from_icon_set  (GtkImage  
       image->storage_type = GTK_IMAGE_ICON_SET;
       
       image->data.icon_set.icon_set = icon_set;
-      image->data.icon_set.size = size;
+      image->icon_size = size;
 
       /* Size is demand-computed in size request method
        * if we're an icon set
        */
     }
+  
+  g_object_notify (G_OBJECT (image), "icon_set");
+  g_object_notify (G_OBJECT (image), "icon_size");
+  
+  g_object_thaw_notify (G_OBJECT (image));
 }
 
 /**
@@ -569,6 +894,8 @@ gtk_image_set_from_animation (GtkImage  
   g_return_if_fail (GTK_IS_IMAGE (image));
   g_return_if_fail (animation == NULL ||
                     GDK_IS_PIXBUF_ANIMATION (animation));
+
+  g_object_freeze_notify (G_OBJECT (image));
   
   if (animation)
     g_object_ref (G_OBJECT (animation));
@@ -587,6 +914,10 @@ gtk_image_set_from_animation (GtkImage  
                              gdk_pixbuf_animation_get_width (animation),
                              gdk_pixbuf_animation_get_height (animation));
     }
+
+  g_object_notify (G_OBJECT (image), "pixbuf_animation");
+  
+  g_object_thaw_notify (G_OBJECT (image));
 }
 
 /**
@@ -633,7 +964,7 @@ gtk_image_get_pixmap (GtkImage   *image,
     *pixmap = image->data.pixmap.pixmap;
   
   if (mask)
-    *mask = image->data.pixmap.mask;
+    *mask = image->mask;
 }
 
 /**
@@ -661,7 +992,7 @@ gtk_image_get_image  (GtkImage   *image,
     *gdk_image = image->data.image.image;
   
   if (mask)
-    *mask = image->data.image.mask;
+    *mask = image->mask;
 }
 
 /**
@@ -719,7 +1050,7 @@ gtk_image_get_stock  (GtkImage        *i
     *stock_id = image->data.stock.stock_id;
 
   if (size)
-    *size = image->data.stock.size;
+    *size = image->icon_size;
 }
 
 /**
@@ -746,7 +1077,7 @@ gtk_image_get_icon_set  (GtkImage       
     *icon_set = image->data.icon_set.icon_set;
 
   if (size)
-    *size = image->data.icon_set.size;
+    *size = image->icon_size;
 }
 
 /**
@@ -899,14 +1230,14 @@ gtk_image_expose (GtkWidget      *widget
       switch (image->storage_type)
         {
         case GTK_IMAGE_PIXMAP:
-          mask = image->data.pixmap.mask;
+          mask = image->mask;
           gdk_drawable_get_size (image->data.pixmap.pixmap,
                                  &image_bound.width,
                                  &image_bound.height);
           break;
 
         case GTK_IMAGE_IMAGE:
-          mask = image->data.image.mask;
+          mask = image->mask;
           image_bound.width = image->data.image.image->width;
           image_bound.height = image->data.image.image->height;
           break;
@@ -919,7 +1250,7 @@ gtk_image_expose (GtkWidget      *widget
         case GTK_IMAGE_STOCK:
           stock_pixbuf = gtk_widget_render_icon (widget,
                                                  image->data.stock.stock_id,
-                                                 image->data.stock.size,
+                                                 image->icon_size,
                                                  NULL);
           if (stock_pixbuf)
             {              
@@ -934,7 +1265,7 @@ gtk_image_expose (GtkWidget      *widget
                                       widget->style,
                                       gtk_widget_get_direction (widget),
                                       GTK_WIDGET_STATE (widget),
-                                      image->data.icon_set.size,
+                                      image->icon_size,
                                       widget,
                                       NULL);
 
@@ -1070,26 +1401,41 @@ gtk_image_expose (GtkWidget      *widget
 static void
 gtk_image_clear (GtkImage *image)
 {
+  g_object_freeze_notify (G_OBJECT (image));
+  
+  if (image->storage_type != GTK_IMAGE_EMPTY)
+    g_object_notify (G_OBJECT (image), "storage_type");
+  
   switch (image->storage_type)
     {
     case GTK_IMAGE_PIXMAP:
 
       if (image->data.pixmap.pixmap)
         g_object_unref (G_OBJECT (image->data.pixmap.pixmap));
-
-      if (image->data.pixmap.mask)
-        g_object_unref (G_OBJECT (image->data.pixmap.mask));
-
+      image->data.pixmap.pixmap = NULL;
+      
+      if (image->mask)
+        g_object_unref (G_OBJECT (image->mask));
+      image->mask = NULL;
+      
+      g_object_notify (G_OBJECT (image), "pixmap");
+      g_object_notify (G_OBJECT (image), "mask");
+      
       break;
 
     case GTK_IMAGE_IMAGE:
 
       if (image->data.image.image)
         g_object_unref (G_OBJECT (image->data.image.image));
-
-      if (image->data.image.mask)
-        g_object_unref (G_OBJECT (image->data.image.mask));
-
+      image->data.image.image = NULL;
+      
+      if (image->mask)
+        g_object_unref (G_OBJECT (image->mask));
+      image->mask = NULL;
+      
+      g_object_notify (G_OBJECT (image), "image");
+      g_object_notify (G_OBJECT (image), "mask");
+      
       break;
 
     case GTK_IMAGE_PIXBUF:
@@ -1097,26 +1443,46 @@ gtk_image_clear (GtkImage *image)
       if (image->data.pixbuf.pixbuf)
         g_object_unref (G_OBJECT (image->data.pixbuf.pixbuf));
 
+      g_object_notify (G_OBJECT (image), "pixbuf");
+      
       break;
 
     case GTK_IMAGE_STOCK:
 
       g_free (image->data.stock.stock_id);
+
+      image->icon_size = DEFAULT_ICON_SIZE;
+      image->data.stock.stock_id = NULL;
+      
+      g_object_notify (G_OBJECT (image), "stock");
+      g_object_notify (G_OBJECT (image), "icon_size");
       
       break;
 
     case GTK_IMAGE_ICON_SET:
       if (image->data.icon_set.icon_set)
         gtk_icon_set_unref (image->data.icon_set.icon_set);
+      image->data.icon_set.icon_set = NULL;
       
+      image->icon_size = DEFAULT_ICON_SIZE;
+      
+      g_object_notify (G_OBJECT (image), "icon_set");
+      g_object_notify (G_OBJECT (image), "icon_size");
+      
       break;
 
     case GTK_IMAGE_ANIMATION:
       if (image->data.anim.frame_timeout)
         g_source_remove (image->data.anim.frame_timeout);
-
+      
       if (image->data.anim.anim)
-        g_object_unref (G_OBJECT (image->data.anim.anim));      
+        g_object_unref (G_OBJECT (image->data.anim.anim));
+
+      image->data.anim.frame_timeout = 0;
+      image->data.anim.anim = NULL;
+      
+      g_object_notify (G_OBJECT (image), "pixbuf_animation");
+      
       break;
       
     case GTK_IMAGE_EMPTY:
@@ -1128,6 +1494,8 @@ gtk_image_clear (GtkImage *image)
   image->storage_type = GTK_IMAGE_EMPTY;
 
   memset (&image->data, '\0', sizeof (image->data));
+
+  g_object_thaw_notify (G_OBJECT (image));
 }
 
 static void
@@ -1158,7 +1526,7 @@ gtk_image_size_request (GtkWidget      *
     case GTK_IMAGE_STOCK:
       pixbuf = gtk_widget_render_icon (GTK_WIDGET (image),
                                        image->data.stock.stock_id,
-                                       image->data.stock.size,
+                                       image->icon_size,
                                        NULL);
       break;
 
@@ -1167,7 +1535,7 @@ gtk_image_size_request (GtkWidget      *
                                          widget->style,
                                          gtk_widget_get_direction (widget),
                                          GTK_WIDGET_STATE (widget),
-                                         image->data.icon_set.size,
+                                         image->icon_size,
                                          widget,
                                          NULL);
       break;
Index: gtk/gtkimage.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkimage.h,v
retrieving revision 1.12
diff -u -p -u -r1.12 gtkimage.h
--- gtk/gtkimage.h	2001/08/25 03:15:26	1.12
+++ gtk/gtkimage.h	2001/08/28 05:52:23
@@ -57,13 +57,11 @@ typedef struct _GtkImageAnimationData Gt
 struct _GtkImagePixmapData
 {
   GdkPixmap *pixmap;
-  GdkBitmap *mask;
 };
 
 struct _GtkImageImageData
 {
   GdkImage *image;
-  GdkBitmap *mask;
 };
 
 struct _GtkImagePixbufData
@@ -74,13 +72,11 @@ struct _GtkImagePixbufData
 struct _GtkImageStockData
 {
   gchar *stock_id;
-  GtkIconSize size;
 };
 
 struct _GtkImageIconSetData
 {
   GtkIconSet *icon_set;
-  GtkIconSize size;
 };
 
 struct _GtkImageAnimationData
@@ -116,6 +112,12 @@ struct _GtkImage
     GtkImageIconSetData icon_set;
     GtkImageAnimationData anim;
   } data;
+
+  /* Only used with GTK_IMAGE_PIXMAP, GTK_IMAGE_IMAGE */
+  GdkBitmap *mask;
+
+  /* Only used with GTK_IMAGE_STOCK, GTK_IMAGE_ICON_SET */
+  GtkIconSize icon_size;
 };
 
 struct _GtkImageClass
Index: gtk/gtkradiobutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkradiobutton.c,v
retrieving revision 1.29
diff -u -p -u -r1.29 gtkradiobutton.c
--- gtk/gtkradiobutton.c	2001/08/27 01:05:07	1.29
+++ gtk/gtkradiobutton.c	2001/08/28 05:52:23
@@ -220,7 +220,7 @@ gtk_radio_button_new_with_label (GSList 
   radio_button = g_object_new (GTK_TYPE_CHECK_BUTTON, "label", label, NULL) ;
 
   if (group)
-    gtk_radio_button_set_group (radio_button, group);
+    gtk_radio_button_set_group (GTK_RADIO_BUTTON (radio_button), group);
 
   return radio_button;
 }
@@ -246,7 +246,7 @@ gtk_radio_button_new_with_mnemonic (GSLi
   radio_button = g_object_new (GTK_TYPE_CHECK_BUTTON, "label", label, "use_underline", TRUE, NULL);
 
   if (group)
-    gtk_radio_button_set_group (radio_button, group);
+    gtk_radio_button_set_group (GTK_RADIO_BUTTON (radio_button), group);
 
   return radio_button;
 }
Index: gtk/gtkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
retrieving revision 1.143
diff -u -p -u -r1.143 gtkwindow.c
--- gtk/gtkwindow.c	2001/08/26 02:03:10	1.143
+++ gtk/gtkwindow.c	2001/08/28 05:52:24
@@ -64,7 +64,7 @@ enum {
   /* Construct */
   PROP_TYPE,
 
-  /* Style Props */
+  /* Normal Props */
   PROP_TITLE,
   PROP_ALLOW_SHRINK,
   PROP_ALLOW_GROW,
@@ -74,10 +74,22 @@ enum {
   PROP_DEFAULT_WIDTH,
   PROP_DEFAULT_HEIGHT,
   PROP_DESTROY_WITH_PARENT,
-
+  PROP_ICON_LIST,
+  PROP_ICON,
+  
   LAST_ARG
 };
 
+typedef struct
+{
+  GList     *icon_list;
+  GdkPixmap *icon_pixmap;
+  GdkPixmap *icon_mask;
+  guint      realized : 1;
+  guint      using_default_icon : 1;
+  guint      using_parent_icon : 1;
+} GtkWindowIconInfo;
+
 typedef struct {
   GdkGeometry    geometry; /* Last set of geometry hints we set */
   GdkWindowHints flags;
@@ -217,11 +229,17 @@ static void     gtk_window_set_default_s
                                                       gboolean      change_height,
                                                       gint          height);
 
+static void     gtk_window_realize_icon               (GtkWindow    *window);
+static void     gtk_window_unrealize_icon             (GtkWindow    *window);
 
 static GSList      *toplevel_list = NULL;
 static GHashTable  *mnemonic_hash_table = NULL;
 static GtkBinClass *parent_class = NULL;
 static guint        window_signals[LAST_SIGNAL] = { 0 };
+static GList       *default_icon_list = NULL;
+/* FIXME need to be per-screen */
+static GdkPixmap   *default_icon_pixmap = NULL;
+static GdkPixmap   *default_icon_mask = NULL;
 
 static void gtk_window_set_property (GObject         *object,
 				     guint            prop_id,
@@ -349,7 +367,7 @@ gtk_window_class_init (GtkWindowClass *k
 						      GTK_WINDOW_TOPLEVEL,
 						      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
-  /* Style Props */
+  /* Regular Props */
   g_object_class_install_property (gobject_class,
                                    PROP_TITLE,
                                    g_param_spec_string ("title",
@@ -427,8 +445,21 @@ gtk_window_class_init (GtkWindowClass *k
                                                          FALSE,
 							 G_PARAM_READWRITE));
 
-  /* Style props are set or not */
+  g_object_class_install_property (gobject_class,
+                                   PROP_ICON_LIST,
+                                   g_param_spec_pointer ("icon_list",
+							 _("Icon list"),
+							 _("List of icons to represent the window"),
+							 G_PARAM_READWRITE));
 
+  g_object_class_install_property (gobject_class,
+                                   PROP_ICON,
+                                   g_param_spec_object ("icon",
+                                                        _("Icon"),
+                                                        _("Icon for this window"),
+                                                        GDK_TYPE_PIXBUF,
+                                                        G_PARAM_READWRITE));
+  
   window_signals[SET_FOCUS] =
     g_signal_new ("set_focus",
                   G_TYPE_FROM_CLASS (object_class),
@@ -651,6 +682,20 @@ gtk_window_set_property (GObject      *o
     case PROP_DESTROY_WITH_PARENT:
       gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
       break;
+    case PROP_ICON_LIST:
+      gtk_window_set_icon_list (window, g_value_get_pointer (value));
+      break;
+    case PROP_ICON:
+      {
+        GdkPixbuf *pixbuf;
+        pixbuf = g_value_get_object (value);
+        if (pixbuf)
+          gtk_window_set_icon (window, GDK_PIXBUF (pixbuf));
+        else
+          gtk_window_set_icon (window, NULL);
+      }
+      break;
+
     default:
       break;
     }
@@ -707,6 +752,17 @@ gtk_window_get_property (GObject      *o
     case PROP_DESTROY_WITH_PARENT:
       g_value_set_boolean (value, window->destroy_with_parent);
       break;
+    case PROP_ICON_LIST:
+      /* Returns a copy of the list, owned by the caller
+       * not the gvalue.
+       */
+      g_value_set_pointer (value,
+                           gtk_window_get_icon_list (window));
+      break;
+    case PROP_ICON:
+      g_value_set_object (value,
+                          G_OBJECT (gtk_window_get_icon (window)));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1706,6 +1762,503 @@ gtk_window_get_decorated (GtkWindow *win
 }
 
 static void
+gdk_pixbuf_render_pixmap_and_mask_with_colormap (GdkPixbuf   *pixbuf,
+                                                 GdkPixmap  **pixmap_return,
+                                                 GdkBitmap  **mask_return,
+                                                 int          alpha_threshold,
+                                                 GdkColormap *cmap)
+{
+  g_return_if_fail (pixbuf != NULL);
+  
+  if (pixmap_return)
+    {
+      GdkGC *gc;
+      
+      *pixmap_return = gdk_pixmap_new (NULL, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf),
+				       gdk_colormap_get_visual (cmap)->depth);
+      gdk_drawable_set_colormap (GDK_DRAWABLE (*pixmap_return),
+                                 cmap);
+      gc = gdk_gc_new (*pixmap_return);
+      gdk_pixbuf_render_to_drawable (pixbuf, *pixmap_return, gc,
+				     0, 0, 0, 0,
+				     gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf),
+				     GDK_RGB_DITHER_NORMAL,
+				     0, 0);
+      gdk_gc_unref (gc);
+    }
+  
+  if (mask_return)
+    {
+      if (gdk_pixbuf_get_has_alpha (pixbuf))
+	{
+	  *mask_return = gdk_pixmap_new (NULL, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf), 1);
+          
+	  gdk_pixbuf_render_threshold_alpha (pixbuf, *mask_return,
+					     0, 0, 0, 0,
+					     gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf),
+					     alpha_threshold);
+	}
+      else
+	*mask_return = NULL;
+    }
+}
+
+static GtkWindowIconInfo*
+get_icon_info (GtkWindow *window)
+{
+  return g_object_get_data (G_OBJECT (window),
+                            "gtk-window-icon-info");
+}
+     
+static GtkWindowIconInfo*
+ensure_icon_info (GtkWindow *window)
+{
+  GtkWindowIconInfo *info;
+
+  info = get_icon_info (window);
+  
+  if (info == NULL)
+    {
+      info = g_new0 (GtkWindowIconInfo, 1);
+      g_object_set_data_full (G_OBJECT (window),
+                              "gtk-window-icon-info",
+                              info,
+                              g_free);
+    }
+
+  return info;
+}
+
+static void
+get_pixmap_and_mask (GtkWindowIconInfo  *parent_info,
+                     gboolean            is_default_list,
+                     GList              *icon_list,
+                     GdkPixmap         **pmap_return,
+                     GdkBitmap         **mask_return)
+{
+  GdkPixbuf *best_icon;
+  GList *tmp_list;
+  int best_size;
+
+  *pmap_return = NULL;
+  *mask_return = NULL;
+  
+  if (is_default_list &&
+      default_icon_pixmap != NULL)
+    {
+      /* Use shared icon pixmap (eventually will be stored on the
+       * GdkScreen)
+       */
+      if (default_icon_pixmap)
+        g_object_ref (G_OBJECT (default_icon_pixmap));
+      if (default_icon_mask)
+        g_object_ref (G_OBJECT (default_icon_mask));
+      
+      *pmap_return = default_icon_pixmap;
+      *mask_return = default_icon_mask;
+    }
+  else if (parent_info && parent_info->icon_pixmap)
+    {
+      if (parent_info->icon_pixmap)
+        g_object_ref (G_OBJECT (parent_info->icon_pixmap));
+      if (parent_info->icon_mask)
+        g_object_ref (G_OBJECT (parent_info->icon_mask));
+      
+      *pmap_return = parent_info->icon_pixmap;
+      *mask_return = parent_info->icon_mask;
+    }
+  else
+    {
+#define IDEAL_SIZE 48
+  
+      best_size = G_MAXINT;
+      best_icon = NULL;
+      tmp_list = icon_list;
+      while (tmp_list != NULL)
+        {
+          GdkPixbuf *pixbuf = tmp_list->data;
+          int this;
+      
+          /* average width and height - if someone passes in a rectangular
+           * icon they deserve what they get.
+           */
+          this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
+          this /= 2;
+      
+          if (best_icon == NULL)
+            {
+              best_icon = pixbuf;
+              best_size = this;
+            }
+          else
+            {
+              /* icon is better if it's 32 pixels or larger, and closer to
+               * the ideal size than the current best.
+               */
+              if (this >= 32 &&
+                  (ABS (best_size - IDEAL_SIZE) <
+                   ABS (this - IDEAL_SIZE)))
+                {
+                  best_icon = pixbuf;
+                  best_size = this;
+                }
+            }
+
+          tmp_list = tmp_list->next;
+        }
+
+      if (best_icon)
+        gdk_pixbuf_render_pixmap_and_mask_with_colormap (best_icon,
+                                                         pmap_return,
+                                                         mask_return,
+                                                         128,
+                                                         gdk_colormap_get_system ());
+
+      /* Save pmap/mask for others to use if appropriate */
+      if (parent_info)
+        {
+          parent_info->icon_pixmap = *pmap_return;
+          parent_info->icon_mask = *mask_return;
+
+          if (parent_info->icon_pixmap)
+            g_object_ref (G_OBJECT (parent_info->icon_pixmap));
+          if (parent_info->icon_mask)
+            g_object_ref (G_OBJECT (parent_info->icon_mask));
+        }
+      else if (is_default_list)
+        {
+          default_icon_pixmap = *pmap_return;
+          default_icon_mask = *mask_return;
+
+          if (default_icon_pixmap)
+            g_object_add_weak_pointer (G_OBJECT (default_icon_pixmap),
+                                       (gpointer*)&default_icon_pixmap);
+          if (default_icon_mask)
+            g_object_add_weak_pointer (G_OBJECT (default_icon_mask),
+                                       (gpointer*)&default_icon_mask);
+        }
+    }
+}
+
+static void
+gtk_window_realize_icon (GtkWindow *window)
+{
+  GtkWidget *widget;
+  GtkWindowIconInfo *info;
+  GList *icon_list;
+  
+  widget = GTK_WIDGET (window);
+
+  g_return_if_fail (widget->window != NULL);
+
+  /* no point setting an icon on override-redirect */
+  if (window->type == GTK_WINDOW_POPUP)
+    return;
+
+  icon_list = NULL;
+  
+  info = ensure_icon_info (window);
+
+  if (info->realized)
+    return;
+
+  g_return_if_fail (info->icon_pixmap == NULL);
+  g_return_if_fail (info->icon_mask == NULL);
+  
+  info->using_default_icon = FALSE;
+  info->using_parent_icon = FALSE;
+  
+  icon_list = info->icon_list;
+  
+  /* Inherit from transient parent */
+  if (icon_list == NULL && window->transient_parent)
+    {
+      icon_list = ensure_icon_info (window->transient_parent)->icon_list;
+      if (icon_list)
+        info->using_parent_icon = TRUE;
+    }      
+
+  /* Inherit from default */
+  if (icon_list == NULL)
+    {
+      icon_list = default_icon_list;
+      if (icon_list)
+        info->using_default_icon = TRUE;
+    }
+  
+  gdk_window_set_icon_list (widget->window, icon_list);
+
+  get_pixmap_and_mask (info->using_parent_icon ?
+                       ensure_icon_info (window->transient_parent) : NULL,
+                       info->using_default_icon,
+                       icon_list,
+                       &info->icon_pixmap,
+                       &info->icon_mask);
+  
+  /* This is a slight ICCCM violation since it's a color pixmap not
+   * a bitmap, but everyone does it.
+   */
+  gdk_window_set_icon (widget->window,
+                       NULL,
+                       info->icon_pixmap,
+                       info->icon_mask);
+
+  info->realized = TRUE;
+}
+
+static void
+gtk_window_unrealize_icon (GtkWindow *window)
+{
+  GtkWindowIconInfo *info;
+  GtkWidget *widget;
+
+  widget = GTK_WIDGET (window);
+  
+  info = get_icon_info (window);
+
+  if (info == NULL)
+    return;
+  
+  if (info->icon_pixmap)
+    g_object_unref (G_OBJECT (info->icon_pixmap));
+
+  if (info->icon_mask)
+    g_object_unref (G_OBJECT (info->icon_mask));
+
+  info->icon_pixmap = NULL;
+  info->icon_mask = NULL;
+
+  /* We don't clear the properties on the window, just figure the
+   * window is going away.
+   */
+}
+
+/**
+ * gtk_window_set_icon_list:
+ * @window: a #GtkWindow
+ * @list: list of #GdkPixbuf
+ *
+ * Sets up the icon representing a #GtkWindow. The icon is used when
+ * the window is minimized (also known as iconified).  Some window
+ * managers or desktop environments may also place it in the window
+ * frame, or display it in other contexts.
+ *
+ * gtk_window_set_icon_list() allows you to pass in the same icon in
+ * several hand-drawn sizes. The list should contain the natural sizes
+ * your icon is available in; that is, don't scale the image before
+ * passing it to GTK+. Scaling is postponed until the last minute,
+ * when the desired final size is known, to allow best quality.
+ *
+ * By passing several sizes, you may improve the final image quality
+ * of the icon, by reducing or eliminating automatic image scaling.
+ *
+ * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
+ * larger images (64x64, 128x128) if you have them.
+ *
+ * See also gtk_window_set_default_icon_list() to set the icon
+ * for all windows in your application in one go.
+ *
+ * Note that transient windows (those who have been set transient for another
+ * window using gtk_window_set_transient_for()) will inherit their
+ * icon from their transient parent. So there's no need to explicitly
+ * set the icon on transient windows.
+ **/
+void
+gtk_window_set_icon_list (GtkWindow  *window,
+                          GList      *list)
+{
+  GtkWindowIconInfo *info;
+
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  info = ensure_icon_info (window);
+
+  if (info->icon_list == list) /* check for NULL mostly */
+    return;
+
+  g_list_foreach (info->icon_list,
+                  (GFunc) g_object_unref, NULL);
+
+  g_list_free (info->icon_list);
+
+  info->icon_list = g_list_copy (list);
+  g_list_foreach (info->icon_list,
+                  (GFunc) g_object_ref, NULL);
+  
+  g_object_notify (G_OBJECT (window), "icon_list");
+
+  gtk_window_unrealize_icon (window);
+  
+  if (GTK_WIDGET_REALIZED (window))
+    gtk_window_realize_icon (window);
+
+  /* We could try to update our transient children, but I don't think
+   * it's really worth it. If we did it, the best way would probably
+   * be to have children connect to notify::icon_list
+   */
+}
+
+/**
+ * gtk_window_get_icon_list:
+ * @window: a #GtkWindow
+ * 
+ * Retrieves the list of icons set by gtk_window_set_icon_list().
+ * The list is copied, but the reference count on each
+ * member won't be incremented.
+ * 
+ * Return value: a list of icons
+ **/
+GList*
+gtk_window_get_icon_list (GtkWindow  *window)
+{
+  GtkWindowIconInfo *info;
+  
+  g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
+
+  info = get_icon_info (window);
+
+  if (info)
+    return g_list_copy (info->icon_list);
+  else
+    return NULL;  
+}
+
+/**
+ * gtk_window_set_icon:
+ * @window: a #GtkWindow
+ * @icon: icon image, or %NULL
+ * 
+ * Sets up the icon representing a #GtkWindow. This icon is used when
+ * the window is minimized (also known as iconified).  Some window
+ * managers or desktop environments may also place it in the window
+ * frame, or display it in other contexts.
+ *
+ * The icon should be provided in whatever size it was naturally
+ * drawn; that is, don't scale the image before passing it to
+ * GTK+. Scaling is postponed until the last minute, when the desired
+ * final size is known, to allow best quality.
+ *
+ * If you have your icon hand-drawn in multiple sizes, use
+ * gtk_window_set_icon_list(). Then the best size will be used.
+ *
+ * This function is equivalent to calling gtk_window_set_icon_list()
+ * with a 1-element list.
+ *
+ * See also gtk_window_set_default_icon_list() to set the icon
+ * for all windows in your application in one go.
+ **/
+void
+gtk_window_set_icon (GtkWindow  *window,
+                     GdkPixbuf  *icon)
+{
+  GList *list;
+  
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
+
+  list = NULL;
+  list = g_list_append (list, icon);
+  gtk_window_set_icon_list (window, list);
+  g_list_free (list);  
+}
+
+/**
+ * gtk_window_get_icon:
+ * @window: a #GtkWindow
+ * 
+ * Gets the value set by gtk_window_set_icon() (or if you've
+ * called gtk_window_set_icon_list(), gets the first icon in
+ * the icon list).
+ * 
+ * Return value: icon for window
+ **/
+GdkPixbuf*
+gtk_window_get_icon (GtkWindow  *window)
+{
+  GtkWindowIconInfo *info;
+
+  info = get_icon_info (window);
+  if (info && info->icon_list)
+    return GDK_PIXBUF (info->icon_list->data);
+  else
+    return NULL;
+}
+
+/**
+ * gtk_window_set_default_icon_list:
+ * @list: a list of #GdkPixbuf
+ *
+ * Sets an icon list to be used as fallback for windows that haven't
+ * had gtk_window_set_icon_list() called on them to set up a
+ * window-specific icon list. This function allows you to set up the
+ * icon for all windows in your app at once.
+ *
+ * See gtk_window_set_icon_list() for more details.
+ * 
+ **/
+void
+gtk_window_set_default_icon_list (GList *list)
+{
+  GList *toplevels;
+  GList *tmp_list;
+  if (list == default_icon_list)
+    return;
+
+  if (default_icon_pixmap)
+    g_object_unref (G_OBJECT (default_icon_pixmap));
+  if (default_icon_mask)
+    g_object_unref (G_OBJECT (default_icon_mask));
+
+  default_icon_pixmap = NULL;
+  default_icon_mask = NULL;
+  
+  g_list_foreach (default_icon_list,
+                  (GFunc) g_object_unref, NULL);
+
+  g_list_free (default_icon_list);
+
+  default_icon_list = g_list_copy (list);
+  g_list_foreach (default_icon_list,
+                  (GFunc) g_object_ref, NULL);
+  
+  /* Update all toplevels */
+  toplevels = gtk_window_list_toplevels ();
+  tmp_list = toplevels;
+  while (tmp_list != NULL)
+    {
+      GtkWindowIconInfo *info;
+      GtkWindow *w = tmp_list->data;
+      
+      info = get_icon_info (w);
+      if (info && info->using_default_icon)
+        {
+          gtk_window_unrealize_icon (w);
+          if (GTK_WIDGET_REALIZED (w))
+            gtk_window_realize_icon (w);
+        }
+
+      tmp_list = tmp_list->next;
+    }
+  g_list_free (toplevels);
+}
+
+/**
+ * gtk_window_get_default_icon_list:
+ * 
+ * Gets the value set by gtk_window_set_default_icon_list().
+ * The list is a copy and should be freed with g_list_free(),
+ * but the pixbufs in the list have not had their reference count
+ * incremented.
+ * 
+ * Return value: default icon list 
+ **/
+GList*
+gtk_window_get_default_icon_list (void)
+{
+  return g_list_copy (default_icon_list);
+}
+
+static void
 gtk_window_set_default_size_internal (GtkWindow    *window,
                                       gboolean      change_width,
                                       gint          width,
@@ -2256,10 +2809,13 @@ gtk_window_destroy (GtkObject *object)
   g_return_if_fail (GTK_IS_WINDOW (object));
 
   window = GTK_WINDOW (object);
-
+  
   if (window->transient_parent)
     gtk_window_set_transient_for (window, NULL);
 
+  /* frees the icons */
+  gtk_window_set_icon_list (window, NULL);
+  
   if (window->has_user_ref_count)
     {
       window->has_user_ref_count = FALSE;
@@ -2632,6 +3188,9 @@ gtk_window_realize (GtkWidget *widget)
     gdk_window_set_modal_hint (widget->window, TRUE);
   else
     gdk_window_set_modal_hint (widget->window, FALSE);
+
+  /* Icons */
+  gtk_window_realize_icon (window);
 }
 
 static void
@@ -2668,6 +3227,9 @@ gtk_window_unrealize (GtkWidget *widget)
       gdk_window_destroy (window->frame);
       window->frame = NULL;
     }
+
+  /* Icons */
+  gtk_window_unrealize_icon (window);
   
   (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
 }
Index: gtk/gtkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.h,v
retrieving revision 1.47
diff -u -p -u -r1.47 gtkwindow.h
--- gtk/gtkwindow.h	2001/08/23 15:26:48	1.47
+++ gtk/gtkwindow.h	2001/08/28 05:52:24
@@ -206,6 +206,15 @@ void       gtk_window_set_decorated     
                                                 gboolean   setting);
 gboolean   gtk_window_get_decorated            (GtkWindow *window);
 
+void       gtk_window_set_icon_list                (GtkWindow  *window,
+                                                    GList      *list);
+GList*     gtk_window_get_icon_list                (GtkWindow  *window);
+void       gtk_window_set_icon                     (GtkWindow  *window,
+                                                    GdkPixbuf  *icon);
+GdkPixbuf* gtk_window_get_icon                     (GtkWindow  *window);
+void       gtk_window_set_default_icon_list        (GList      *list);
+GList*     gtk_window_get_default_icon_list        (void);
+
 /* If window is set modal, input will be grabbed when show and released when hide */
 void       gtk_window_set_modal      (GtkWindow *window,
 				      gboolean   modal);




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]