Protect ensure_valid_themes() from recursion, which can happen for example
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 15 Mar 2007 18:40:16 +0000 (18:40 +0000)
committerChris Wilson <cpwilson@src.gnome.org>
Thu, 15 Mar 2007 18:40:16 +0000 (18:40 +0000)
2007-03-15  Chris Wilson  <chris@chris-wilson.co.uk>

* gtk/gtkicontheme.c (ensure_valid_themes), (rescan_themes),
(gtk_icon_theme_rescan_if_needed): Protect ensure_valid_themes()
from recursion, which can happen for example if the app tries to
reload an icon from within a theme-changed handler. (#418531)

svn path=/trunk/; revision=17523

ChangeLog
gtk/gtkicontheme.c

index 408758c79f88e1f446323e4dd1eea01e28f4c250..a049c13f5b74570e77444d3c4748cfd546bcf760 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2007-03-15  Chris Wilson  <chris@chris-wilson.co.uk>
+
+       * gtk/gtkicontheme.c (ensure_valid_themes), (rescan_themes),
+       (gtk_icon_theme_rescan_if_needed): Protect ensure_valid_themes()
+       from recursion, which can happen for example if the app tries to
+       reload an icon from within a theme-changed handler. (#418531)
+
 2007-03-15  Richard Hult  <richard@imendio.com>
 
        * gdk/quartz/gdkmain-quartz.c: Add stubs for
index ba9126f377858f31d8c33f6a1a4a8db9956cba2a..b981e228c2dbf9b2da15f4f21f7f0b31ae073419 100644 (file)
@@ -73,6 +73,7 @@ struct _GtkIconThemePrivate
   guint pixbuf_supports_svg : 1;
   guint themes_valid        : 1;
   guint check_reload        : 1;
+  guint loading_themes      : 1;
   
   char *current_theme;
   char *fallback_theme;
@@ -205,7 +206,8 @@ static void         theme_subdir_load (GtkIconTheme     *icon_theme,
                                       char             *subdir);
 static void         do_theme_change   (GtkIconTheme     *icon_theme);
 
-static void  blow_themes               (GtkIconTheme    *icon_themes);
+static void     blow_themes               (GtkIconTheme    *icon_themes);
+static gboolean rescan_themes             (GtkIconTheme    *icon_themes);
 
 static void  icon_data_free            (GtkIconData     *icon_data);
 static void load_icon_data             (IconThemeDir    *dir,
@@ -1176,37 +1178,49 @@ ensure_valid_themes (GtkIconTheme *icon_theme)
   GTimeVal tv;
   gboolean was_valid = priv->themes_valid;
 
+  if (priv->loading_themes)
+    return;
+  priv->loading_themes = TRUE;
+
   _gtk_icon_theme_ensure_builtin_cache ();
 
   if (priv->themes_valid)
     {
       g_get_current_time (&tv);
 
-      if (ABS (tv.tv_sec - priv->last_stat_time) > 5)
-       gtk_icon_theme_rescan_if_needed (icon_theme);
+      if (ABS (tv.tv_sec - priv->last_stat_time) > 5 &&
+         rescan_themes (icon_theme))
+       blow_themes (icon_theme);
     }
   
   if (!priv->themes_valid)
     {
       load_themes (icon_theme);
-      
-      if (!priv->check_reload && was_valid && priv->screen)
-       {         
-         static GdkAtom atom_iconthemes = GDK_NONE;
-         GdkEvent *event = gdk_event_new (GDK_CLIENT_EVENT);
-         int i;
 
-         if (!atom_iconthemes)
-           atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
+      if (was_valid)
+       {
+         g_signal_emit (icon_theme, signal_changed, 0);
+
+         if (!priv->check_reload && priv->screen)
+           {     
+             static GdkAtom atom_iconthemes = GDK_NONE;
+             GdkEvent *event = gdk_event_new (GDK_CLIENT_EVENT);
+             int i;
+
+             if (!atom_iconthemes)
+               atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
 
-         for (i = 0; i < 5; i++)
-           event->client.data.l[i] = 0;
-         event->client.data_format = 32;
-         event->client.message_type = atom_iconthemes;
+             for (i = 0; i < 5; i++)
+               event->client.data.l[i] = 0;
+             event->client.data_format = 32;
+             event->client.message_type = atom_iconthemes;
 
-         gdk_screen_broadcast_client_message (priv->screen, event);
+             gdk_screen_broadcast_client_message (priv->screen, event);
+           }
        }
     }
+
+  priv->loading_themes = FALSE;
 }
 
 /**
@@ -1673,21 +1687,9 @@ gtk_icon_theme_get_example_icon_name (GtkIconTheme *icon_theme)
   return NULL;
 }
 
-/**
- * gtk_icon_theme_rescan_if_needed:
- * @icon_theme: a #GtkIconTheme
- * 
- * Checks to see if the icon theme has changed; if it has, any
- * currently cached information is discarded and will be reloaded
- * next time @icon_theme is accessed.
- * 
- * Return value: %TRUE if the icon theme has changed and needed
- *   to be reloaded.
- *
- * Since: 2.4
- **/
-gboolean
-gtk_icon_theme_rescan_if_needed (GtkIconTheme *icon_theme)
+
+static gboolean
+rescan_themes (GtkIconTheme *icon_theme)
 {
   GtkIconThemePrivate *priv;
   IconThemeDirMtime *dir_mtime;
@@ -1696,10 +1698,8 @@ gtk_icon_theme_rescan_if_needed (GtkIconTheme *icon_theme)
   struct stat stat_buf;
   GTimeVal tv;
 
-  g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), FALSE);
-
   priv = icon_theme->priv;
-  
+
   for (d = priv->dir_mtimes; d != NULL; d = d->next)
     {
       dir_mtime = d->data;
@@ -1707,7 +1707,7 @@ gtk_icon_theme_rescan_if_needed (GtkIconTheme *icon_theme)
       stat_res = g_stat (dir_mtime->dir, &stat_buf);
 
       /* dir mtime didn't change */
-      if (stat_res == 0 && 
+      if (stat_res == 0 &&
          S_ISDIR (stat_buf.st_mode) &&
          dir_mtime->mtime == stat_buf.st_mtime)
        continue;
@@ -1715,17 +1715,43 @@ gtk_icon_theme_rescan_if_needed (GtkIconTheme *icon_theme)
       if (dir_mtime->mtime == 0 &&
          (stat_res != 0 || !S_ISDIR (stat_buf.st_mode)))
        continue;
-         
-      do_theme_change (icon_theme);
+
       return TRUE;
     }
-  
+
   g_get_current_time (&tv);
   priv->last_stat_time = tv.tv_sec;
 
   return FALSE;
 }
 
+/**
+ * gtk_icon_theme_rescan_if_needed:
+ * @icon_theme: a #GtkIconTheme
+ * 
+ * Checks to see if the icon theme has changed; if it has, any
+ * currently cached information is discarded and will be reloaded
+ * next time @icon_theme is accessed.
+ * 
+ * Return value: %TRUE if the icon theme has changed and needed
+ *   to be reloaded.
+ *
+ * Since: 2.4
+ **/
+gboolean
+gtk_icon_theme_rescan_if_needed (GtkIconTheme *icon_theme)
+{
+  gboolean retval;
+
+  g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), FALSE);
+
+  retval = rescan_themes (icon_theme);
+  if (retval)
+      do_theme_change (icon_theme);
+
+  return retval;
+}
+
 static void
 theme_destroy (IconTheme *theme)
 {