From 21ac22598101c25f1705fa6dea263a16ffe49be1 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Sun, 26 Sep 2010 17:18:26 +0200 Subject: [PATCH] StIcon: add support for GIcon Add a "gicon" property so that a GIcon can be used instead of an icon name, while still getting icon recoloring from the theme. Also include a compatibility wrapper in libshell until GJS has support for interface static methods. https://bugzilla.gnome.org/show_bug.cgi?id=622451 --- js/ui/panelMenu.js | 19 ++-- js/ui/placeDisplay.js | 8 +- src/Makefile.am | 4 +- src/shell-app-system.c | 2 +- src/{shell-uri-util.c => shell-util.c} | 18 +++- src/{shell-uri-util.h => shell-util.h} | 7 +- src/shell-window-tracker.c | 2 +- src/st/st-icon.c | 121 +++++++++++++++++++++---- src/st/st-icon.h | 3 + src/st/st-texture-cache.c | 14 ++- src/st/st-texture-cache.h | 1 + 11 files changed, 157 insertions(+), 42 deletions(-) rename src/{shell-uri-util.c => shell-util.c} (95%) rename src/{shell-uri-util.h => shell-util.h} (60%) diff --git a/js/ui/panelMenu.js b/js/ui/panelMenu.js index 9888d2388..b0dad5eed 100644 --- a/js/ui/panelMenu.js +++ b/js/ui/panelMenu.js @@ -72,18 +72,19 @@ SystemStatusButton.prototype = { _init: function(iconName,tooltipText) { Button.prototype._init.call(this, St.Align.START); - this._iconActor = null; - this.setIcon(iconName); + this._iconActor = new St.Icon({ icon_name: iconName, + icon_type: St.IconType.SYMBOLIC, + style_class: 'system-status-icon' }); + this.actor.set_child(this._iconActor); this.setTooltip(tooltipText); }, setIcon: function(iconName) { - this._iconName = iconName; - if (this._iconActor) - this._iconActor.destroy(); - this._iconActor = new St.Icon({ icon_name: this._iconName, - style_class: 'system-status-icon' }); - this.actor.set_child(this._iconActor); + this._iconActor.icon_name = iconName; + }, + + setGIcon: function(gicon) { + this._iconActor.gicon = gicon; }, setTooltip: function(text) { @@ -96,4 +97,4 @@ SystemStatusButton.prototype = { this.tooltip = null; } } -}; \ No newline at end of file +}; diff --git a/js/ui/placeDisplay.js b/js/ui/placeDisplay.js index d22f422b7..88d25dabb 100644 --- a/js/ui/placeDisplay.js +++ b/js/ui/placeDisplay.js @@ -79,7 +79,7 @@ PlaceDeviceInfo.prototype = { iconFactory: function(size) { let icon = this._mount.get_icon(); - return St.TextureCache.get_default().load_gicon(icon, size); + return St.TextureCache.get_default().load_gicon(null, icon, size); }, launch: function() { @@ -137,7 +137,7 @@ PlacesManager.prototype = { let homeIcon = Shell.util_get_icon_for_uri (homeUri); this._home = new PlaceInfo('special:home', homeLabel, function(size) { - return St.TextureCache.get_default().load_gicon(homeIcon, size); + return St.TextureCache.get_default().load_gicon(null, homeIcon, size); }, function() { Gio.app_info_launch_default_for_uri(homeUri, global.create_app_launch_context()); @@ -150,7 +150,7 @@ PlacesManager.prototype = { let desktopIcon = Shell.util_get_icon_for_uri (desktopUri); this._desktopMenu = new PlaceInfo('special:desktop', desktopLabel, function(size) { - return St.TextureCache.get_default().load_gicon(desktopIcon, size); + return St.TextureCache.get_default().load_gicon(null, desktopIcon, size); }, function() { Gio.app_info_launch_default_for_uri(desktopUri, global.create_app_launch_context()); @@ -327,7 +327,7 @@ PlacesManager.prototype = { let item = new PlaceInfo('bookmark:' + bookmark, label, function(size) { - return St.TextureCache.get_default().load_gicon(icon, size); + return St.TextureCache.get_default().load_gicon(null, icon, size); }, function() { Gio.app_info_launch_default_for_uri(bookmark, global.create_app_launch_context()); diff --git a/src/Makefile.am b/src/Makefile.am index 013a884fb..05b1dedd1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,7 +77,7 @@ shell_public_headers_h = \ shell-stack.h \ shell-tray-icon.h \ shell-tray-manager.h \ - shell-uri-util.h \ + shell-util.h \ shell-window-tracker.h \ shell-wm.h \ shell-xfixes-cursor.h @@ -109,7 +109,7 @@ libgnome_shell_la_SOURCES = \ shell-stack.c \ shell-tray-icon.c \ shell-tray-manager.c \ - shell-uri-util.c \ + shell-util.c \ shell-window-tracker.c \ shell-wm.c \ shell-xfixes-cursor.c diff --git a/src/shell-app-system.c b/src/shell-app-system.c index 7df763f05..daf0f14cc 100644 --- a/src/shell-app-system.c +++ b/src/shell-app-system.c @@ -1274,7 +1274,7 @@ shell_app_info_create_icon_texture (ShellAppInfo *info, float size) } else { - ret = st_texture_cache_load_gicon (st_texture_cache_get_default (), icon, (int)size); + ret = st_texture_cache_load_gicon (st_texture_cache_get_default (), NULL, icon, (int)size); g_object_unref (icon); } diff --git a/src/shell-uri-util.c b/src/shell-util.c similarity index 95% rename from src/shell-uri-util.c rename to src/shell-util.c index dcbe58bb5..1a643c9f5 100644 --- a/src/shell-uri-util.c +++ b/src/shell-util.c @@ -2,7 +2,7 @@ #include "config.h" -#include "shell-uri-util.h" +#include "shell-util.h" #include #include #include @@ -383,3 +383,19 @@ shell_util_get_icon_for_uri (const char *text_uri) return g_themed_icon_new ("gtk-file"); } + +/** + * shell_util_icon_from_string: + * @string: a stringified #GIcon + * + * A static method equivalent to g_icon_new_for_string, workaround + * for GJS not being able to represent Gio.Icon (which is an interface, + * not a class). + * + * Returns: (transfer full): the icon which is represented by @string + */ +GIcon * +shell_util_icon_from_string (const char *string, GError **error) +{ + return g_icon_new_for_string (string, error); +} diff --git a/src/shell-uri-util.h b/src/shell-util.h similarity index 60% rename from src/shell-uri-util.h rename to src/shell-util.h index eef415a47..f523d446d 100644 --- a/src/shell-uri-util.h +++ b/src/shell-util.h @@ -1,7 +1,7 @@ /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -#ifndef __SHELL_URI_UTIL_H__ -#define __SHELL_URI_UTIL_H__ +#ifndef __SHELL_UTIL_H__ +#define __SHELL_UTIL_H__ #include @@ -9,7 +9,8 @@ G_BEGIN_DECLS char *shell_util_get_label_for_uri (const char *text_uri); GIcon *shell_util_get_icon_for_uri (const char *text_uri); +GIcon *shell_util_icon_from_string (const char *string, GError **error); G_END_DECLS -#endif /* __SHELL_URI_UTIL_H__ */ +#endif /* __SHELL_UTIL_H__ */ diff --git a/src/shell-window-tracker.c b/src/shell-window-tracker.c index ad8bc478d..1e61b7c6d 100644 --- a/src/shell-window-tracker.c +++ b/src/shell-window-tracker.c @@ -941,7 +941,7 @@ shell_startup_sequence_create_icon (ShellStartupSequence *sequence, guint size) themed = g_themed_icon_new (icon_name); texture = st_texture_cache_load_gicon (st_texture_cache_get_default (), - themed, size); + NULL, themed, size); g_object_unref (G_OBJECT (themed)); return texture; } diff --git a/src/st/st-icon.c b/src/st/st-icon.c index 94e6842df..4b6b14b76 100644 --- a/src/st/st-icon.c +++ b/src/st/st-icon.c @@ -35,6 +35,7 @@ enum { PROP_0, + PROP_GICON, PROP_ICON_NAME, PROP_ICON_TYPE, PROP_ICON_SIZE @@ -49,6 +50,7 @@ struct _StIconPrivate { ClutterActor *icon_texture; + GIcon *gicon; gchar *icon_name; StIconType icon_type; gint prop_icon_size; /* icon size set as property */ @@ -72,6 +74,10 @@ st_icon_set_property (GObject *gobject, switch (prop_id) { + case PROP_GICON: + st_icon_set_gicon (icon, g_value_get_object (value)); + break; + case PROP_ICON_NAME: st_icon_set_icon_name (icon, g_value_get_string (value)); break; @@ -100,6 +106,10 @@ st_icon_get_property (GObject *gobject, switch (prop_id) { + case PROP_GICON: + g_value_set_object (value, icon->priv->gicon); + break; + case PROP_ICON_NAME: g_value_set_string (value, st_icon_get_icon_name (icon)); break; @@ -129,6 +139,12 @@ st_icon_dispose (GObject *gobject) priv->icon_texture = NULL; } + if (priv->gicon) + { + g_object_unref (priv->gicon); + priv->gicon = NULL; + } + G_OBJECT_CLASS (st_icon_parent_class)->dispose (gobject); } @@ -272,6 +288,13 @@ st_icon_class_init (StIconClass *klass) widget_class->style_changed = st_icon_style_changed; + pspec = g_param_spec_object ("gicon", + "GIcon", + "A GIcon to override :icon-name", + G_TYPE_ICON, + ST_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_GICON, pspec); + pspec = g_param_spec_string ("icon-name", "Icon name", "An icon name", @@ -299,6 +322,7 @@ st_icon_init (StIcon *self) { self->priv = ST_ICON_GET_PRIVATE (self); + self->priv->gicon = NULL; self->priv->icon_size = DEFAULT_ICON_SIZE; self->priv->prop_icon_size = -1; self->priv->icon_type = DEFAULT_ICON_TYPE; @@ -308,6 +332,8 @@ static void st_icon_update (StIcon *icon) { StIconPrivate *priv = icon->priv; + StThemeNode *theme_node; + StTextureCache *cache; /* Get rid of the old one */ if (priv->icon_texture) @@ -317,23 +343,30 @@ st_icon_update (StIcon *icon) } /* Try to lookup the new one */ - if (priv->icon_name) + theme_node = st_widget_peek_theme_node (ST_WIDGET (icon)); + if (theme_node == NULL) + return; + + cache = st_texture_cache_get_default (); + if (priv->gicon) { - StThemeNode *theme_node = st_widget_peek_theme_node (ST_WIDGET (icon)); - - if (theme_node) - { - StTextureCache *cache = st_texture_cache_get_default (); - priv->icon_texture = st_texture_cache_load_icon_name (cache, - theme_node, - priv->icon_name, - priv->icon_type, - priv->icon_size); - - if (priv->icon_texture) - clutter_actor_set_parent (priv->icon_texture, CLUTTER_ACTOR (icon)); - } + priv->icon_texture = st_texture_cache_load_gicon (cache, + (priv->icon_type != ST_ICON_APPLICATION && + priv->icon_type != ST_ICON_DOCUMENT) ? + theme_node : NULL, + priv->gicon, + priv->icon_size); } + else if (priv->icon_name) + { + priv->icon_texture = st_texture_cache_load_icon_name (cache, + theme_node, + priv->icon_name, + priv->icon_type, + priv->icon_size); + } + if (priv->icon_texture) + clutter_actor_set_parent (priv->icon_texture, CLUTTER_ACTOR (icon)); } static gboolean @@ -397,9 +430,16 @@ st_icon_set_icon_name (StIcon *icon, g_free (priv->icon_name); priv->icon_name = g_strdup (icon_name); - st_icon_update (icon); + if (priv->gicon) + { + g_object_unref (priv->gicon); + priv->gicon = NULL; + g_object_notify (G_OBJECT (icon), "gicon"); + } g_object_notify (G_OBJECT (icon), "icon-name"); + + st_icon_update (icon); } /** @@ -448,6 +488,55 @@ st_icon_set_icon_type (StIcon *icon, g_object_notify (G_OBJECT (icon), "icon-type"); } +/** + * st_icon_get_gicon: + * @icon: an icon + * + * Return value: (transfer none): the override GIcon, if set, or NULL + */ +GIcon * +st_icon_get_gicon (StIcon *icon) +{ + g_return_val_if_fail (ST_IS_ICON (icon), NULL); + + return icon->priv->gicon; +} + +/** + * st_icon_set_gicon: + * @icon: an icon + * @gicon: (allow-none): a #GIcon to override :icon-name + */ +void +st_icon_set_gicon (StIcon *icon, GIcon *gicon) +{ + g_return_if_fail (ST_IS_ICON (icon)); + g_return_if_fail (G_IS_ICON (gicon)); + + if (icon->priv->gicon == gicon) /* do nothing */ + return; + + if (icon->priv->gicon) + { + g_object_unref (icon->priv->gicon); + icon->priv->gicon = NULL; + } + + if (gicon) + icon->priv->gicon = g_object_ref (gicon); + + if (icon->priv->icon_name) + { + g_free (icon->priv->icon_name); + icon->priv->icon_name = NULL; + g_object_notify (G_OBJECT (icon), "icon-name"); + } + + g_object_notify (G_OBJECT (icon), "gicon"); + + st_icon_update (icon); +} + /** * st_icon_get_icon_size: * @icon: an icon diff --git a/src/st/st-icon.h b/src/st/st-icon.h index bddb41d89..eac4a164f 100644 --- a/src/st/st-icon.h +++ b/src/st/st-icon.h @@ -29,6 +29,7 @@ #define _ST_ICON #include +#include #include #include @@ -93,6 +94,8 @@ StIconType st_icon_get_icon_type (StIcon *icon); gint st_icon_get_icon_size (StIcon *icon); void st_icon_set_icon_size (StIcon *icon, gint size); +void st_icon_set_gicon (StIcon *icon, GIcon *gicon); +GIcon *st_icon_get_gicon (StIcon *icon); G_END_DECLS diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c index cd84bdb10..35931da36 100644 --- a/src/st/st-texture-cache.c +++ b/src/st/st-texture-cache.c @@ -1118,6 +1118,8 @@ load_gicon_with_colors (StTextureCache *cache, /** * st_texture_cache_load_gicon: * @cache: The texture cache instance + * @theme_node: (allow-none): The #StThemeNode to use for colors, or NULL + * if the icon must not be recolored * @icon: the #GIcon to load * @size: Size of themed * @@ -1132,10 +1134,11 @@ load_gicon_with_colors (StTextureCache *cache, */ ClutterActor * st_texture_cache_load_gicon (StTextureCache *cache, + StThemeNode *theme_node, GIcon *icon, gint size) { - return load_gicon_with_colors (cache, icon, size, NULL); + return load_gicon_with_colors (cache, icon, size, theme_node ? st_theme_node_get_icon_colors (theme_node) : NULL); } typedef struct { @@ -1328,7 +1331,7 @@ st_texture_cache_load_icon_name (StTextureCache *cache, case ST_ICON_APPLICATION: case ST_ICON_DOCUMENT: themed = g_themed_icon_new (name); - texture = st_texture_cache_load_gicon (cache, themed, size); + texture = load_gicon_with_colors (cache, themed, size, NULL); g_object_unref (themed); return CLUTTER_ACTOR (texture); @@ -1345,7 +1348,8 @@ st_texture_cache_load_icon_name (StTextureCache *cache, break; case ST_ICON_FULLCOLOR: themed = g_themed_icon_new_with_default_fallbacks (name); - texture = st_texture_cache_load_gicon (cache, themed, size); + texture = load_gicon_with_colors (cache, themed, size, NULL); + g_object_unref (themed); return CLUTTER_ACTOR (texture); break; @@ -1693,7 +1697,7 @@ st_texture_cache_load_thumbnail (StTextureCache *cache, if (!g_str_has_prefix (uri, "file://")) { GIcon *icon = icon_for_mimetype (mimetype); - return st_texture_cache_load_gicon (cache, icon, size); + return st_texture_cache_load_gicon (cache, NULL, icon, size); } texture = create_default_texture (cache); @@ -1770,7 +1774,7 @@ st_texture_cache_load_recent_thumbnail (StTextureCache *cache, if (!g_str_has_prefix (uri, "file://")) { GIcon *icon = icon_for_recent (info); - return st_texture_cache_load_gicon (cache, icon, size); + return st_texture_cache_load_gicon (cache, NULL, icon, size); } texture = CLUTTER_TEXTURE (clutter_texture_new ()); diff --git a/src/st/st-texture-cache.h b/src/st/st-texture-cache.h index e8fc586c5..4f1a4820a 100644 --- a/src/st/st-texture-cache.h +++ b/src/st/st-texture-cache.h @@ -85,6 +85,7 @@ ClutterActor *st_texture_cache_load_icon_name (StTextureCache *cache, gint size); ClutterActor *st_texture_cache_load_gicon (StTextureCache *cache, + StThemeNode *theme_node, GIcon *icon, gint size);