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: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3141>
This commit is contained in:
Florian Müllner 2024-01-23 21:20:51 +01:00 committed by Marge Bot
parent e97175d2bf
commit 671c242958

View File

@ -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)