[gnome-shell] Handle icon theme changes



commit 8734a59cd7d930019b4187399646d97bce57465a
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Fri Nov 12 19:15:09 2010 -0500

    Handle icon theme changes
    
    Connect to the "changed" signal on the default icon theme, and
    when it triggers:
    
     - Evict all cached looked up icons from the StTextureCache
     - Fake a style change on all StThemeContext; this will result
       in StIcon looking up icons again.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=633866

 src/st/st-texture-cache.c |   64 ++++++++++++++++++++++++++++++++++++++++++++-
 src/st/st-theme-context.c |   24 +++++++++++++++++
 2 files changed, 87 insertions(+), 1 deletions(-)
---
diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c
index cdea848..cd84bdb 100644
--- a/src/st/st-texture-cache.c
+++ b/src/st/st-texture-cache.c
@@ -36,6 +36,8 @@
 
 struct _StTextureCachePrivate
 {
+  GtkIconTheme *icon_theme;
+
   /* Things that were loaded with a cache policy != NONE */
   GHashTable *keyed_cache; /* char * -> CoglTexture* */
   /* Presently this is used to de-duplicate requests for GIcons,
@@ -49,6 +51,14 @@ struct _StTextureCachePrivate
 static void st_texture_cache_dispose (GObject *object);
 static void st_texture_cache_finalize (GObject *object);
 
+enum
+{
+  ICON_THEME_CHANGED,
+
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
 G_DEFINE_TYPE(StTextureCache, st_texture_cache, G_TYPE_OBJECT);
 
 /* We want to preserve the aspect ratio by default, also the default
@@ -78,12 +88,56 @@ st_texture_cache_class_init (StTextureCacheClass *klass)
 
   gobject_class->dispose = st_texture_cache_dispose;
   gobject_class->finalize = st_texture_cache_finalize;
+
+  signals[ICON_THEME_CHANGED] =
+    g_signal_new ("icon-theme-changed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  0, /* no default handler slot */
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+}
+
+/* Evicts all cached textures for named icons */
+static void
+st_texture_cache_evict_icons (StTextureCache *cache)
+{
+  GHashTableIter iter;
+  gpointer key;
+  gpointer value;
+
+  g_hash_table_iter_init (&iter, cache->priv->keyed_cache);
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      const char *cache_key = key;
+
+      /* This is too conservative - it takes out all cached textures
+       * for GIcons even when they aren't named icons, but it's not
+       * worth the complexity of parsing the key and calling
+       * g_icon_new_for_string(); icon theme changes aren't normal */
+      if (g_str_has_prefix (cache_key, "gicon:"))
+        g_hash_table_iter_remove (&iter);
+    }
+}
+
+static void
+on_icon_theme_changed (GtkIconTheme   *icon_theme,
+                       StTextureCache *cache)
+{
+  st_texture_cache_evict_icons (cache);
+  g_signal_emit (cache, signals[ICON_THEME_CHANGED], 0);
 }
 
 static void
 st_texture_cache_init (StTextureCache *self)
 {
   self->priv = g_new0 (StTextureCachePrivate, 1);
+
+  self->priv->icon_theme = gtk_icon_theme_get_default ();
+  g_signal_connect (self->priv->icon_theme, "changed",
+                    G_CALLBACK (on_icon_theme_changed), self);
+
   self->priv->keyed_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                    g_free, cogl_handle_unref);
   self->priv->outstanding_requests = g_hash_table_new_full (g_str_hash, g_str_equal,
@@ -96,6 +150,14 @@ st_texture_cache_dispose (GObject *object)
 {
   StTextureCache *self = (StTextureCache*)object;
 
+  if (self->priv->icon_theme)
+    {
+      g_signal_handlers_disconnect_by_func (self->priv->icon_theme,
+                                            (gpointer) on_icon_theme_changed,
+                                            self);
+      self->priv->icon_theme = NULL;
+    }
+
   if (self->priv->keyed_cache)
     g_hash_table_destroy (self->priv->keyed_cache);
   self->priv->keyed_cache = NULL;
@@ -1023,7 +1085,7 @@ load_gicon_with_colors (StTextureCache    *cache,
     }
 
   /* Do theme lookups in the main thread to avoid thread-unsafety */
-  theme = gtk_icon_theme_get_default ();
+  theme = cache->priv->icon_theme;
 
   info = gtk_icon_theme_lookup_by_gicon (theme, icon, size, GTK_ICON_LOOKUP_USE_BUILTIN);
   if (info != NULL)
diff --git a/src/st/st-theme-context.c b/src/st/st-theme-context.c
index 378db30..80a00e5 100644
--- a/src/st/st-theme-context.c
+++ b/src/st/st-theme-context.c
@@ -21,6 +21,7 @@
 
 #include <config.h>
 
+#include "st-texture-cache.h"
 #include "st-theme.h"
 #include "st-theme-context.h"
 
@@ -51,11 +52,18 @@ static guint signals[LAST_SIGNAL] = { 0, };
 
 G_DEFINE_TYPE (StThemeContext, st_theme_context, G_TYPE_OBJECT)
 
+static void on_icon_theme_changed (StTextureCache *cache,
+                                   StThemeContext *context);
+
 static void
 st_theme_context_finalize (GObject *object)
 {
   StThemeContext *context = ST_THEME_CONTEXT (object);
 
+  g_signal_handlers_disconnect_by_func (st_texture_cache_get_default (),
+                                       (gpointer) on_icon_theme_changed,
+                                       context);
+
   if (context->root_node)
     g_object_unref (context->root_node);
   if (context->theme)
@@ -88,6 +96,11 @@ st_theme_context_init (StThemeContext *context)
 {
   context->resolution = DEFAULT_RESOLUTION;
   context->font = pango_font_description_from_string (DEFAULT_FONT);
+
+  g_signal_connect (st_texture_cache_get_default (),
+                    "icon-theme-changed",
+                    G_CALLBACK (on_icon_theme_changed),
+                    context);
 }
 
 /**
@@ -129,6 +142,17 @@ st_theme_context_changed (StThemeContext *context)
     g_object_unref (old_root);
 }
 
+static void
+on_icon_theme_changed (StTextureCache *cache,
+                       StThemeContext *context)
+{
+  /* Note that an icon theme change isn't really a change of the StThemeContext;
+   * the style information has changed. But since the style factors into the
+   * icon_name => icon lookup, faking a theme context change is a good way
+   * to force users such as StIcon to look up icons again */
+  st_theme_context_changed (context);
+}
+
 /**
  * st_theme_context_get_for_stage:
  * @stage: a #ClutterStage



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]