From 671c242958772f22de287d9bf6e13ad01f3e44b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Tue, 23 Jan 2024 21:20:51 +0100 Subject: [PATCH] st/icon: Automatically update on icon theme changes St.Icon is very commonly used for displaying themed icons, yet so far updating the icon on icon theme changes is left to the caller. Unsurprisingly, very few actually do that, with the result that for most icons, icon theme changes only take effect after a delay (say, a color change on hover) or not at all. This is also inconsistent with GTK, where Gtk.Image will automatically pick up icon theme changes. Address this by tracking whether the current icon corresponds to a themed icon, and update it automatically on theme changes if it does. Part-of: --- src/st/st-icon.c | 85 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 18 deletions(-) diff --git a/src/st/st-icon.c b/src/st/st-icon.c index 6a32df5b3..c9e29ee3f 100644 --- a/src/st/st-icon.c +++ b/src/st/st-icon.c @@ -53,6 +53,7 @@ struct _StIconPrivate ClutterActor *icon_texture; ClutterActor *pending_texture; gulong opacity_handler_id; + gulong icon_theme_changed_id; GIcon *gicon; gint prop_icon_size; /* icon size set as property */ @@ -60,6 +61,7 @@ struct _StIconPrivate gint icon_size; /* icon size we are using */ GIcon *fallback_gicon; gboolean needs_update; + gboolean is_themed; StIconColors *colors; @@ -80,6 +82,13 @@ static GIcon *default_gicon = NULL; #define IMAGE_MISSING_ICON_NAME "image-missing" #define DEFAULT_ICON_SIZE 48 +static void +on_icon_theme_changed (StIcon *icon) +{ + if (icon->priv->is_themed) + st_icon_update (icon); +} + static void st_icon_set_property (GObject *gobject, guint prop_id, @@ -170,6 +179,9 @@ st_icon_dispose (GObject *gobject) priv->pending_texture = NULL; } + g_clear_signal_handler (&priv->icon_theme_changed_id, + st_texture_cache_get_default ()); + g_clear_object (&priv->gicon); g_clear_object (&priv->fallback_gicon); g_clear_pointer (&priv->colors, st_icon_colors_unref); @@ -354,6 +366,7 @@ static void st_icon_init (StIcon *self) { ClutterLayoutManager *layout_manager; + StTextureCache *texture_cache; if (G_UNLIKELY (default_gicon == NULL)) default_gicon = g_themed_icon_new (IMAGE_MISSING_ICON_NAME); @@ -363,6 +376,11 @@ st_icon_init (StIcon *self) layout_manager = clutter_bin_layout_new (); clutter_actor_set_layout_manager (CLUTTER_ACTOR (self), layout_manager); + texture_cache = st_texture_cache_get_default (); + self->priv->icon_theme_changed_id = + g_signal_connect_swapped (texture_cache, "icon-theme-changed", + G_CALLBACK (on_icon_theme_changed), self); + /* Set the icon size to -1 here to make sure we apply the scale to the * default size on the first "style-changed" signal. */ self->priv->icon_size = -1; @@ -462,6 +480,32 @@ opacity_changed_cb (GObject *object, st_icon_finish_update (icon); } +static ClutterActor * +load_gicon (StTextureCache *cache, + StThemeNode *theme_node, + GIcon *gicon, + int size, + int paint_scale, + float resource_scale, + gboolean *is_themed) +{ + ClutterActor *texture; + + g_assert (is_themed != NULL); + + texture = st_texture_cache_load_gicon (cache, + theme_node, + gicon, + size, + paint_scale, + resource_scale); + + + if (texture) + *is_themed = G_IS_THEMED_ICON (gicon); + return texture; +} + static void st_icon_update (StIcon *icon) { @@ -504,29 +548,34 @@ st_icon_update (StIcon *icon) cache = st_texture_cache_get_default (); + priv->is_themed = FALSE; + if (priv->gicon != NULL) - priv->pending_texture = st_texture_cache_load_gicon (cache, - theme_node, - priv->gicon, - priv->icon_size / paint_scale, - paint_scale, - resource_scale); + priv->pending_texture = load_gicon (cache, + theme_node, + priv->gicon, + priv->icon_size / paint_scale, + paint_scale, + resource_scale, + &priv->is_themed); if (priv->pending_texture == NULL && priv->fallback_gicon != NULL) - priv->pending_texture = st_texture_cache_load_gicon (cache, - theme_node, - priv->fallback_gicon, - priv->icon_size / paint_scale, - paint_scale, - resource_scale); + priv->pending_texture = load_gicon (cache, + theme_node, + priv->fallback_gicon, + priv->icon_size / paint_scale, + paint_scale, + resource_scale, + &priv->is_themed); if (priv->pending_texture == NULL) - priv->pending_texture = st_texture_cache_load_gicon (cache, - theme_node, - default_gicon, - priv->icon_size / paint_scale, - paint_scale, - resource_scale); + priv->pending_texture = load_gicon (cache, + theme_node, + default_gicon, + priv->icon_size / paint_scale, + paint_scale, + resource_scale, + &priv->is_themed); priv->needs_update = FALSE; if (priv->pending_texture)