b=621962 rearrange nsIconChannel::Init to make what is happening clearer r=roc
authorKarl Tomlinson <karlt+@karlt.net>
Thu, 03 Feb 2011 12:22:33 -0500
changeset 61853 57536671a3637d216f06e1f28b0ddf8b8c5250d3
parent 61852 9a9f6f3eec6ba9acb0249e3d8e4310770c40d59d
child 61854 29df2b0fa77bb689e9984499c5f604b8507da8b3
push idunknown
push userunknown
push dateunknown
reviewersroc
bugs621962
milestone2.0b12pre
b=621962 rearrange nsIconChannel::Init to make what is happening clearer r=roc
modules/libpr0n/decoders/icon/gtk/nsIconChannel.cpp
--- a/modules/libpr0n/decoders/icon/gtk/nsIconChannel.cpp
+++ b/modules/libpr0n/decoders/icon/gtk/nsIconChannel.cpp
@@ -163,16 +163,18 @@ static GtkWidget *gStockImageWidget = ns
 static GnomeIconTheme *gIconTheme = nsnull;
 #endif
 
 static GtkIconFactory *gIconFactory = nsnull;
 
 static void
 ensure_stock_image_widget()
 {
+  // Only the style of the GtkImage needs to be used, but the widget is kept
+  // to track dynamic style changes.
   if (!gProtoWindow) {
     gProtoWindow = gtk_window_new(GTK_WINDOW_POPUP);
     GtkWidget* protoLayout = gtk_fixed_new();
     gtk_container_add(GTK_CONTAINER(gProtoWindow), protoLayout);
 
     gStockImageWidget = gtk_image_new();
     gtk_container_add(GTK_CONTAINER(protoLayout), gStockImageWidget);
 
@@ -459,40 +461,57 @@ nsIconChannel::Init(nsIURI* aURI)
 
   nsCAutoString iconSizeString;
   iconURI->GetIconSize(iconSizeString);
 
   nsCAutoString iconStateString;
   iconURI->GetIconState(iconStateString);
 
   GtkIconSize icon_size = moz_gtk_icon_size(iconSizeString.get());
-   
+  GtkStateType state = iconStateString.EqualsLiteral("disabled") ?
+    GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL;
+
+  // First lookup the icon by stock id.
   ensure_stock_image_widget();
+  GtkStyle *style = gtk_widget_get_style(gStockImageWidget);
+  GtkIconSet *icon_set =
+    gtk_style_lookup_icon_set(style, stockIcon.get());
 
-  gboolean sensitive = strcmp(iconStateString.get(), "disabled");
-  gtk_widget_set_sensitive (gStockImageWidget, sensitive);
+  if (icon_set) {
+    gtk_icon_set_ref(icon_set);
+  } else {
+    // stockIcon is not a stock id, so assume it is an icon name.
+    //
+    // Creating a GtkIconSet is a convenient way to allow the style to
+    // render the icon, possibly with variations suitable for insensitive
+    // states.
+    //
+    // The GtkIconSet is also used to add a new stock id in such a way that
+    // the look up above will succeed next time.  Maybe this is to take
+    // advantage of the cache of stock icon GdkPixbufs.
 
-  GdkPixbuf *icon = gtk_widget_render_icon(gStockImageWidget, stockIcon.get(),
-                                           icon_size, NULL);
-  if (!icon) {
     ensure_icon_factory();
       
-    GtkIconSet *icon_set = gtk_icon_set_new();
+    icon_set = gtk_icon_set_new();
     GtkIconSource *icon_source = gtk_icon_source_new();
     
     gtk_icon_source_set_icon_name(icon_source, stockIcon.get());
     gtk_icon_set_add_source(icon_set, icon_source);
     gtk_icon_factory_add(gIconFactory, stockIcon.get(), icon_set);
-    gtk_icon_set_unref(icon_set);
     gtk_icon_source_free(icon_source);
-
-    icon = gtk_widget_render_icon(gStockImageWidget, stockIcon.get(),
-                                  icon_size, NULL);
   }
 
+  GdkPixbuf *icon =
+    gtk_icon_set_render_icon (icon_set, style,
+                              gtk_widget_get_default_direction(), state,
+                              icon_size, gStockImageWidget, NULL);
+  gtk_icon_set_unref(icon_set);
+
+  // gtk_icon_set_render_icon() never returns NULL, except when we have
+  // https://bugzilla.gnome.org/show_bug.cgi?id=629878#c13
   if (!icon)
     return NS_ERROR_NOT_AVAILABLE;
   
   nsresult rv = moz_gdk_pixbuf_to_channel(icon, iconURI,
                                           getter_AddRefs(mRealChannel));
 
   g_object_unref(icon);