From 0b1c9b7cc26d293477a6823a40d3e1feebbd6df7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 15 Mar 2007 18:40:16 +0000 Subject: [PATCH] Protect ensure_valid_themes() from recursion, which can happen for example 2007-03-15 Chris Wilson * 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 | 7 ++++ gtk/gtkicontheme.c | 102 ++++++++++++++++++++++++++++----------------- 2 files changed, 71 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index 408758c79f..a049c13f5b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2007-03-15 Chris Wilson + + * 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 * gdk/quartz/gdkmain-quartz.c: Add stubs for diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c index ba9126f377..b981e228c2 100644 --- a/gtk/gtkicontheme.c +++ b/gtk/gtkicontheme.c @@ -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) { -- 2.30.2