diff --git a/demos/gtk-demo/images.c b/demos/gtk-demo/images.c index 9eaac39c0f..eb3f1d9484 100644 --- a/demos/gtk-demo/images.c +++ b/demos/gtk-demo/images.c @@ -317,6 +317,7 @@ do_images (GtkWidget *do_widget) GtkWidget *align; GtkWidget *button; GdkPixbuf *pixbuf; + GIcon *gicon; GError *error = NULL; char *filename; @@ -415,6 +416,26 @@ do_images (GtkWidget *do_widget) gtk_container_add (GTK_CONTAINER (frame), image); + /* Symbolic icon */ + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), + "Symbolic themed icon"); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + /* The alignment keeps the frame from growing when users resize + * the window + */ + align = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_container_add (GTK_CONTAINER (align), frame); + gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0); + + gicon = g_themed_icon_new_with_default_fallbacks ("battery-critical-charging-symbolic"); + image = gtk_image_new_from_gicon (gicon, GTK_ICON_SIZE_DIALOG); + + gtk_container_add (GTK_CONTAINER (frame), image); /* Progressive */ diff --git a/demos/gtk-demo/list_store.c b/demos/gtk-demo/list_store.c index 009cd97993..e5c72bab67 100644 --- a/demos/gtk-demo/list_store.c +++ b/demos/gtk-demo/list_store.c @@ -29,7 +29,9 @@ enum COLUMN_SEVERITY, COLUMN_DESCRIPTION, COLUMN_PULSE, + COLUMN_ICON, COLUMN_ACTIVE, + COLUMN_SENSITIVE, NUM_COLUMNS }; @@ -92,11 +94,24 @@ create_model (void) G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, + G_TYPE_STRING, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); /* add data to the list store */ for (i = 0; i < G_N_ELEMENTS (data); i++) { + gchar *icon_name; + gboolean sensitive; + + if (i == 1 || i == 3) + icon_name = "battery-critical-charging-symbolic"; + else + icon_name = NULL; + if (i == 3) + sensitive = FALSE; + else + sensitive = TRUE; gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, COLUMN_FIXED, data[i].fixed, @@ -104,7 +119,9 @@ create_model (void) COLUMN_SEVERITY, data[i].severity, COLUMN_DESCRIPTION, data[i].description, COLUMN_PULSE, 0, + COLUMN_ICON, icon_name, COLUMN_ACTIVE, FALSE, + COLUMN_SENSITIVE, sensitive, -1); } @@ -199,6 +216,19 @@ add_columns (GtkTreeView *treeview) NULL); gtk_tree_view_column_set_sort_column_id (column, COLUMN_PULSE); gtk_tree_view_append_column (treeview, column); + + /* column for symbolic icon */ + renderer = gtk_cell_renderer_pixbuf_new (); + g_object_set (G_OBJECT (renderer), "follow-state", TRUE, NULL); + column = gtk_tree_view_column_new_with_attributes ("Symbolic icon", + renderer, + "icon-name", + COLUMN_ICON, + "sensitive", + COLUMN_SENSITIVE, + NULL); + gtk_tree_view_column_set_sort_column_id (column, COLUMN_ICON); + gtk_tree_view_append_column (treeview, column); } static gboolean diff --git a/docs/reference/gtk/gtk-sections.txt b/docs/reference/gtk/gtk-sections.txt index 1961891820..bf9c664b75 100644 --- a/docs/reference/gtk/gtk-sections.txt +++ b/docs/reference/gtk/gtk-sections.txt @@ -6684,6 +6684,7 @@ gtk_icon_info_get_base_size gtk_icon_info_get_filename gtk_icon_info_get_builtin_pixbuf gtk_icon_info_load_icon +gtk_icon_info_load_symbolic gtk_icon_info_set_raw_coordinates gtk_icon_info_get_embedded_rect gtk_icon_info_get_attach_points diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index af6ada455d..ff85c8c4dc 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -1965,6 +1965,7 @@ gtk_icon_info_get_filename_utf8 #endif gtk_icon_info_get_type G_GNUC_CONST gtk_icon_info_load_icon +gtk_icon_info_load_symbolic gtk_icon_info_set_raw_coordinates gtk_icon_theme_add_builtin_icon #ifndef _WIN64 diff --git a/gtk/gtkcellrendererpixbuf.c b/gtk/gtkcellrendererpixbuf.c index f689784bcc..bde1d809e3 100644 --- a/gtk/gtkcellrendererpixbuf.c +++ b/gtk/gtkcellrendererpixbuf.c @@ -497,6 +497,7 @@ gtk_cell_renderer_pixbuf_create_themed_pixbuf (GtkCellRendererPixbuf *cellpixbuf GtkIconTheme *icon_theme; GtkSettings *settings; gint width, height; + GtkIconInfo *info; priv = GTK_CELL_RENDERER_PIXBUF_GET_PRIVATE (cellpixbuf); @@ -519,29 +520,140 @@ gtk_cell_renderer_pixbuf_create_themed_pixbuf (GtkCellRendererPixbuf *cellpixbuf } if (priv->icon_name) - cellpixbuf->pixbuf = gtk_icon_theme_load_icon (icon_theme, - priv->icon_name, - MIN (width, height), - GTK_ICON_LOOKUP_USE_BUILTIN, - NULL); + info = gtk_icon_theme_lookup_icon (icon_theme, + priv->icon_name, + MIN (width, height), + GTK_ICON_LOOKUP_USE_BUILTIN); else if (priv->gicon) - { - GtkIconInfo *info; + info = gtk_icon_theme_lookup_by_gicon (icon_theme, + priv->gicon, + MIN (width, height), + GTK_ICON_LOOKUP_USE_BUILTIN); + else + info = NULL; - info = gtk_icon_theme_lookup_by_gicon (icon_theme, - priv->gicon, - MIN (width, height), - GTK_ICON_LOOKUP_USE_BUILTIN); - if (info) - { - cellpixbuf->pixbuf = gtk_icon_info_load_icon (info, NULL); - gtk_icon_info_free (info); - } + if (info) + { + GdkColor error_color, warning_color, success_color; + GdkColor *error_ptr, *warning_ptr, *success_ptr; + GtkStyle *style; + + style = gtk_widget_get_style (GTK_WIDGET (widget)); + if (!gtk_style_lookup_color (style, "error_color", &error_color)) + error_ptr = NULL; + else + error_ptr = &error_color; + if (!gtk_style_lookup_color (style, "warning_color", &warning_color)) + warning_ptr = NULL; + else + warning_ptr = &warning_color; + if (!gtk_style_lookup_color (style, "success_color", &success_color)) + success_ptr = NULL; + else + success_ptr = &success_color; + + cellpixbuf->pixbuf = gtk_icon_info_load_symbolic (info, + &style->fg[GTK_STATE_NORMAL], + success_ptr, + warning_ptr, + error_ptr, + NULL, + NULL); + gtk_icon_info_free (info); } g_object_notify (G_OBJECT (cellpixbuf), "pixbuf"); } +static GdkPixbuf * +create_symbolic_pixbuf (GtkCellRendererPixbuf *cellpixbuf, + GtkWidget *widget, + GdkColor *fg) +{ + GtkCellRendererPixbufPrivate *priv; + GdkScreen *screen; + GtkIconTheme *icon_theme; + GtkSettings *settings; + gint width, height; + GtkIconInfo *info; + GdkPixbuf *pixbuf; + + priv = GTK_CELL_RENDERER_PIXBUF_GET_PRIVATE (cellpixbuf); + + /* Not a named symbolic icon? */ + if (priv->icon_name) { + if (!g_str_has_suffix (priv->icon_name, "-symbolic")) + return NULL; + } else if (priv->gicon) { + const gchar * const *names; + if (!G_IS_THEMED_ICON (priv->gicon)) + return NULL; + names = g_themed_icon_get_names (G_THEMED_ICON (priv->gicon)); + if (names == NULL || !g_str_has_suffix (names[0], "-symbolic")) + return NULL; + } else { + return NULL; + } + + screen = gtk_widget_get_screen (GTK_WIDGET (widget)); + icon_theme = gtk_icon_theme_get_for_screen (screen); + settings = gtk_settings_get_for_screen (screen); + + if (!gtk_icon_size_lookup_for_settings (settings, + priv->stock_size, + &width, &height)) + { + g_warning ("Invalid icon size %u\n", priv->stock_size); + width = height = 24; + } + + + if (priv->icon_name) + info = gtk_icon_theme_lookup_icon (icon_theme, + priv->icon_name, + MIN (width, height), + GTK_ICON_LOOKUP_USE_BUILTIN); + else if (priv->gicon) + info = gtk_icon_theme_lookup_by_gicon (icon_theme, + priv->gicon, + MIN (width, height), + GTK_ICON_LOOKUP_USE_BUILTIN); + else + return NULL; + + if (info) + { + GdkColor error_color, warning_color, success_color; + GdkColor *error_ptr, *warning_ptr, *success_ptr; + GtkStyle *style; + + style = gtk_widget_get_style (GTK_WIDGET (widget)); + if (!gtk_style_lookup_color (style, "error_color", &error_color)) + error_ptr = NULL; + else + error_ptr = &error_color; + if (!gtk_style_lookup_color (style, "warning_color", &warning_color)) + warning_ptr = NULL; + else + warning_ptr = &warning_color; + if (!gtk_style_lookup_color (style, "success_color", &success_color)) + success_ptr = NULL; + else + success_ptr = &success_color; + + pixbuf = gtk_icon_info_load_symbolic (info, + fg, + success_ptr, + warning_ptr, + error_ptr, + NULL, + NULL); + gtk_icon_info_free (info); + return pixbuf; + } + return NULL; +} + static GdkPixbuf * create_colorized_pixbuf (GdkPixbuf *src, GdkColor *new_color) @@ -678,6 +790,7 @@ gtk_cell_renderer_pixbuf_render (GtkCellRenderer *cell, GdkPixbuf *pixbuf; GdkPixbuf *invisible = NULL; GdkPixbuf *colorized = NULL; + GdkPixbuf *symbolic = NULL; GdkRectangle pix_rect; GdkRectangle draw_rect; cairo_t *cr; @@ -755,10 +868,15 @@ gtk_cell_renderer_pixbuf_render (GtkCellRenderer *cell, else state = GTK_STATE_PRELIGHT; - colorized = create_colorized_pixbuf (pixbuf, - &widget->style->base[state]); + symbolic = create_symbolic_pixbuf (cellpixbuf, widget, &widget->style->fg[state]); + if (!symbolic) { + colorized = create_colorized_pixbuf (pixbuf, + &widget->style->base[state]); - pixbuf = colorized; + pixbuf = colorized; + } else { + pixbuf = symbolic; + } } cr = gdk_cairo_create (window); @@ -774,6 +892,9 @@ gtk_cell_renderer_pixbuf_render (GtkCellRenderer *cell, if (colorized) g_object_unref (colorized); + + if (symbolic) + g_object_unref (symbolic); } #define __GTK_CELL_RENDERER_PIXBUF_C__ diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c index 67ed420332..0084343fbf 100644 --- a/gtk/gtkicontheme.c +++ b/gtk/gtkicontheme.c @@ -3079,6 +3079,142 @@ gtk_icon_info_load_icon (GtkIconInfo *icon_info, return g_object_ref (icon_info->pixbuf); } +static gchar * +gdk_color_to_css (GdkColor *color) +{ + return g_strdup_printf ("rgb(%d,%d,%d)", + color->red >> 8, + color->green >> 8, + color->blue >> 8); +} + +/** + * gtk_icon_info_load_symbolic: + * @info: a #GtkIconInfo + * @fg: a #GdkColor representing the foreground color of the icon + * @success_color: (allow-none): a #GdkColor representing the warning color of the icon + * or %NULL to use the default color + * @warning_color: (allow-none): a #GdkColor representing the warning color of the icon + * or %NULL to use the default color + * @error_color: (allow-none): a #GdkColor representing the error color of the icon + * or %NULL to use the default color (allow-none) + * @was_symbolic: (allow-none): a #gboolean, returns whether the loaded icon was a symbolic + * one and whether the @fg color was applied to it. + * @error: (allow-none): location to store error information on failure, or %NULL. + * + * Loads an icon, modifying it to match the system colours for the foreground, + * success, warning and error colors provided. If the icon is not a symbolic one, + * the function will return the result from gtk_icon_info_load_icon(). + * + * This allows loading symbolic icons that will match the system theme. + * + * Unless you are implementing a widget, you will want to use + * g_themed_icon_new_with_default_fallbacks() to load the icon. + * + * As implementation details, the icon loaded needs to be of SVG type, + * contain the "symbolic" term as the last chunk of the icon name, + * and use the fg, success, warning and error styles in the SVG file itself. + * See the Symbolic Icons spec + * for more information about symbolic icons. + * + * Return value: a #GdkPixbuf representing the loaded icon + * + * Since: 2.22 + **/ +GdkPixbuf * +gtk_icon_info_load_symbolic (GtkIconInfo *info, + GdkColor *fg, + GdkColor *success_color, + GdkColor *warning_color, + GdkColor *error_color, + gboolean *was_symbolic, + GError **error) +{ + GdkPixbuf *pixbuf; + GInputStream *stream; + gchar *data; + gchar *css_fg; + gchar *css_success; + gchar *css_warning; + gchar *css_error; + + g_return_val_if_fail (fg != NULL, NULL); + + if (!info->filename || !g_str_has_suffix (info->filename, "-symbolic.svg")) + { + if (was_symbolic) + *was_symbolic = FALSE; + return gtk_icon_info_load_icon (info, error); + } + + if (was_symbolic) + *was_symbolic = TRUE; + + css_fg = gdk_color_to_css (fg); + if (!warning_color) + { + GdkColor warning_default_color = { 0, 0xf500, 0x7900, 0x3e00 }; + css_warning = gdk_color_to_css (&warning_default_color); + } + else + css_warning = gdk_color_to_css (warning_color); + if (!error_color) + { + GdkColor error_default_color = { 0, 0xcc00, 0x0000, 0x0000 }; + css_error = gdk_color_to_css (&error_default_color); + } + else + css_error = gdk_color_to_css (error_color); + if (!success_color) + { + GdkColor success_default_color = { 0, 0x4e00, 0x9a00, 0x0600 }; + css_success = gdk_color_to_css (&success_default_color); + } + else + css_success = gdk_color_to_css (success_color); + + data = g_strconcat ( +"\n" +"\n" +" \n" +" filename, "\"/>\n" +"", + NULL); + g_free (css_fg); + g_free (css_warning); + g_free (css_success); + g_free (css_error); + + stream = g_memory_input_stream_new_from_data (data, -1, g_free); + + pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream, + info->desired_size, + info->desired_size, + TRUE, + NULL, + error); + g_object_unref (stream); + + return pixbuf; +} + /** * gtk_icon_info_set_raw_coordinates: * @icon_info: a #GtkIconInfo diff --git a/gtk/gtkicontheme.h b/gtk/gtkicontheme.h index b6d7d31fe2..f8609cbc0b 100644 --- a/gtk/gtkicontheme.h +++ b/gtk/gtkicontheme.h @@ -179,6 +179,13 @@ G_CONST_RETURN gchar *gtk_icon_info_get_filename (GtkIconInfo *icon_info GdkPixbuf * gtk_icon_info_get_builtin_pixbuf (GtkIconInfo *icon_info); GdkPixbuf * gtk_icon_info_load_icon (GtkIconInfo *icon_info, GError **error); +GdkPixbuf * gtk_icon_info_load_symbolic (GtkIconInfo *icon_info, + GdkColor *fg, + GdkColor *success_color, + GdkColor *warning_color, + GdkColor *error_color, + gboolean *was_symbolic, + GError **error); void gtk_icon_info_set_raw_coordinates (GtkIconInfo *icon_info, gboolean raw_coordinates); diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c index 6654f0db62..87e0b08245 100644 --- a/gtk/gtkimage.c +++ b/gtk/gtkimage.c @@ -134,6 +134,11 @@ struct _GtkImagePrivate /* Only used with GTK_IMAGE_ANIMATION, GTK_IMAGE_PIXBUF */ gchar *filename; + /* a GtkStateType, with -1 meaning an invalid state, + * only used with GTK_IMAGE_GICON, GTK_IMAGE_ICON_NAME */ + gint last_rendered_state; + gboolean was_symbolic; + gint pixel_size; guint need_calc_size : 1; }; @@ -1628,6 +1633,10 @@ animation_timeout (gpointer data) static void icon_theme_changed (GtkImage *image) { + GtkImagePrivate *priv; + + priv = GTK_IMAGE_GET_PRIVATE (image); + if (image->storage_type == GTK_IMAGE_ICON_NAME) { if (image->data.name.pixbuf) @@ -1647,7 +1656,8 @@ icon_theme_changed (GtkImage *image) } static void -ensure_pixbuf_for_icon_name (GtkImage *image) +ensure_pixbuf_for_icon_name (GtkImage *image, + GtkStateType state) { GtkImagePrivate *priv; GdkScreen *screen; @@ -1655,8 +1665,8 @@ ensure_pixbuf_for_icon_name (GtkImage *image) GtkSettings *settings; gint width, height; gint *sizes, *s, dist; + GtkIconInfo *info; GtkIconLookupFlags flags; - GError *error = NULL; g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_NAME); @@ -1665,8 +1675,15 @@ ensure_pixbuf_for_icon_name (GtkImage *image) icon_theme = gtk_icon_theme_get_for_screen (screen); settings = gtk_settings_get_for_screen (screen); flags = GTK_ICON_LOOKUP_USE_BUILTIN; - if (image->data.name.pixbuf == NULL) + if (image->data.name.pixbuf == NULL || + (priv->was_symbolic && priv->last_rendered_state != state)) { + priv->last_rendered_state = state; + if (image->data.name.pixbuf) + { + g_object_unref (image->data.name.pixbuf); + image->data.name.pixbuf = NULL; + } if (priv->pixel_size != -1) { width = height = priv->pixel_size; @@ -1714,24 +1731,57 @@ ensure_pixbuf_for_icon_name (GtkImage *image) width = height = 24; } } - image->data.name.pixbuf = - gtk_icon_theme_load_icon (icon_theme, - image->data.name.icon_name, - MIN (width, height), flags, &error); + + info = gtk_icon_theme_lookup_icon (icon_theme, + image->data.name.icon_name, + MIN (width, height), flags); + if (info) + { + GdkColor error_color, warning_color, success_color; + GdkColor *error_ptr, *warning_ptr, *success_ptr; + GtkStyle *style; + gboolean was_symbolic; + + style = gtk_widget_get_style (GTK_WIDGET (image)); + if (!gtk_style_lookup_color (style, "error_color", &error_color)) + error_ptr = NULL; + else + error_ptr = &error_color; + if (!gtk_style_lookup_color (style, "warning_color", &warning_color)) + warning_ptr = NULL; + else + warning_ptr = &warning_color; + if (!gtk_style_lookup_color (style, "success_color", &success_color)) + success_ptr = NULL; + else + success_ptr = &success_color; + + image->data.name.pixbuf = gtk_icon_info_load_symbolic (info, + &style->fg[state], + success_ptr, + warning_ptr, + error_ptr, + &was_symbolic, + NULL); + priv->was_symbolic = was_symbolic; + gtk_icon_info_free (info); + } + if (image->data.name.pixbuf == NULL) { - g_error_free (error); image->data.name.pixbuf = gtk_widget_render_icon (GTK_WIDGET (image), GTK_STOCK_MISSING_IMAGE, image->icon_size, NULL); + priv->was_symbolic = FALSE; } } } static void -ensure_pixbuf_for_gicon (GtkImage *image) +ensure_pixbuf_for_gicon (GtkImage *image, + GtkStateType state) { GtkImagePrivate *priv; GdkScreen *screen; @@ -1748,8 +1798,15 @@ ensure_pixbuf_for_gicon (GtkImage *image) icon_theme = gtk_icon_theme_get_for_screen (screen); settings = gtk_settings_get_for_screen (screen); flags = GTK_ICON_LOOKUP_USE_BUILTIN; - if (image->data.gicon.pixbuf == NULL) + if (image->data.gicon.pixbuf == NULL || + (priv->was_symbolic && priv->last_rendered_state != state)) { + priv->last_rendered_state = state; + if (image->data.gicon.pixbuf) + { + g_object_unref (image->data.gicon.pixbuf); + image->data.gicon.pixbuf = NULL; + } if (priv->pixel_size != -1) { width = height = priv->pixel_size; @@ -1773,7 +1830,33 @@ ensure_pixbuf_for_gicon (GtkImage *image) MIN (width, height), flags); if (info) { - image->data.gicon.pixbuf = gtk_icon_info_load_icon (info, NULL); + GdkColor error_color, warning_color, success_color; + GdkColor *error_ptr, *warning_ptr, *success_ptr; + GtkStyle *style; + gboolean was_symbolic; + + style = gtk_widget_get_style (GTK_WIDGET (image)); + if (!gtk_style_lookup_color (style, "error_color", &error_color)) + error_ptr = NULL; + else + error_ptr = &error_color; + if (!gtk_style_lookup_color (style, "warning_color", &warning_color)) + warning_ptr = NULL; + else + warning_ptr = &warning_color; + if (!gtk_style_lookup_color (style, "success_color", &success_color)) + success_ptr = NULL; + else + success_ptr = &success_color; + + image->data.gicon.pixbuf = gtk_icon_info_load_symbolic (info, + &style->fg[state], + success_ptr, + warning_ptr, + error_ptr, + &was_symbolic, + NULL); + priv->was_symbolic = was_symbolic; gtk_icon_info_free (info); } @@ -1784,6 +1867,7 @@ ensure_pixbuf_for_gicon (GtkImage *image) GTK_STOCK_MISSING_IMAGE, image->icon_size, NULL); + priv->was_symbolic = FALSE; } } } @@ -1845,6 +1929,7 @@ gtk_image_expose (GtkWidget *widget, gint x, y, mask_x, mask_y; GdkBitmap *mask; GdkPixbuf *pixbuf; + GtkStateType state; gboolean needs_state_transform; image = GTK_IMAGE (widget); @@ -2012,7 +2097,18 @@ gtk_image_expose (GtkWidget *widget, break; case GTK_IMAGE_ICON_NAME: - ensure_pixbuf_for_icon_name (image); + state = gtk_widget_get_state (widget); + if (state == GTK_STATE_INSENSITIVE) + { + ensure_pixbuf_for_icon_name (image, GTK_STATE_NORMAL); + } + else + { + ensure_pixbuf_for_icon_name (image, state); + /* Already done by the loading function? */ + if (priv->was_symbolic) + needs_state_transform = FALSE; + } pixbuf = image->data.name.pixbuf; if (pixbuf) { @@ -2023,7 +2119,18 @@ gtk_image_expose (GtkWidget *widget, break; case GTK_IMAGE_GICON: - ensure_pixbuf_for_gicon (image); + state = gtk_widget_get_state (widget); + if (state == GTK_STATE_INSENSITIVE) + { + ensure_pixbuf_for_gicon (image, GTK_STATE_NORMAL); + } + else + { + ensure_pixbuf_for_gicon (image, state); + /* Already done by the loading function? */ + if (priv->was_symbolic) + needs_state_transform = FALSE; + } pixbuf = image->data.gicon.pixbuf; if (pixbuf) { @@ -2325,12 +2432,12 @@ gtk_image_calc_size (GtkImage *image) NULL); break; case GTK_IMAGE_ICON_NAME: - ensure_pixbuf_for_icon_name (image); + ensure_pixbuf_for_icon_name (image, GTK_STATE_NORMAL); pixbuf = image->data.name.pixbuf; if (pixbuf) g_object_ref (pixbuf); break; case GTK_IMAGE_GICON: - ensure_pixbuf_for_gicon (image); + ensure_pixbuf_for_gicon (image, GTK_STATE_NORMAL); pixbuf = image->data.gicon.pixbuf; if (pixbuf) g_object_ref (pixbuf);