[gtk+/gtk-3-8] IconCache: Keep a ref on the GtkIconData
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/gtk-3-8] IconCache: Keep a ref on the GtkIconData
- Date: Wed, 19 Jun 2013 08:15:30 +0000 (UTC)
commit b489d20ac4e7157f76b964d9ca604283fc52cb8a
Author: Alexander Larsson <alexl redhat com>
Date: Wed Jun 19 09:32:38 2013 +0200
IconCache: Keep a ref on the GtkIconData
The icon data in GttkIconInfo->data is currently owned by the
IconThemeDir->icon_data hashtable. However, on e.g. a theme change
blow_themes() destroys the dirs and thus the data, meaning any
outstanding GtkIconInfo points to stale data.
We solve this by adding a refcount to GtkIconData and reffing it
from GtkIconInfo.
https://bugzilla.gnome.org/show_bug.cgi?id=702598
(cherry picked from commit 280d606cd41c5d607e56d48e57bcba5b654cfa2e)
gtk/gtkiconcache.c | 1 +
gtk/gtkiconcache.h | 1 +
gtk/gtkicontheme.c | 47 +++++++++++++++++++++++++++++++++--------------
3 files changed, 35 insertions(+), 14 deletions(-)
---
diff --git a/gtk/gtkiconcache.c b/gtk/gtkiconcache.c
index 7d8b3fc..09aaa1b 100644
--- a/gtk/gtkiconcache.c
+++ b/gtk/gtkiconcache.c
@@ -520,6 +520,7 @@ _gtk_icon_cache_get_icon_data (GtkIconCache *cache,
return NULL;
data = g_slice_new0 (GtkIconData);
+ data->ref = 1;
offset = GET_UINT32 (cache->buffer, meta_data_offset);
if (offset)
diff --git a/gtk/gtkiconcache.h b/gtk/gtkiconcache.h
index 07e909d..767e2b6 100644
--- a/gtk/gtkiconcache.h
+++ b/gtk/gtkiconcache.h
@@ -25,6 +25,7 @@ typedef struct _GtkIconData GtkIconData;
struct _GtkIconData
{
+ gint ref;
gboolean has_embedded_rect;
gint x0, y0, x1, y1;
diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c
index c79826c..e1e6746 100644
--- a/gtk/gtkicontheme.c
+++ b/gtk/gtkicontheme.c
@@ -351,7 +351,8 @@ static void blow_themes (GtkIconTheme *icon_themes);
static gboolean rescan_themes (GtkIconTheme *icon_themes);
static GtkIconData *icon_data_dup (GtkIconData *icon_data);
-static void icon_data_free (GtkIconData *icon_data);
+static GtkIconData *icon_data_ref (GtkIconData *icon_data);
+static void icon_data_unref (GtkIconData *icon_data);
static void load_icon_data (IconThemeDir *dir,
const char *path,
const char *name);
@@ -2607,9 +2608,9 @@ theme_lookup_icon (IconTheme *theme,
icon_info->filename = NULL;
icon_info->icon_file = NULL;
}
-
+
if (min_dir->icon_data != NULL)
- icon_info->data = g_hash_table_lookup (min_dir->icon_data, icon_name);
+ icon_info->data = icon_data_ref (g_hash_table_lookup (min_dir->icon_data, icon_name));
if (icon_info->data == NULL && min_dir->cache != NULL)
{
@@ -2618,9 +2619,9 @@ theme_lookup_icon (IconTheme *theme,
{
if (min_dir->icon_data == NULL)
min_dir->icon_data = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify)icon_data_free);
+ g_free, (GDestroyNotify)icon_data_unref);
- g_hash_table_replace (min_dir->icon_data, g_strdup (icon_name), icon_info->data);
+ g_hash_table_replace (min_dir->icon_data, g_strdup (icon_name), icon_data_ref
(icon_info->data));
}
}
@@ -2635,10 +2636,10 @@ theme_lookup_icon (IconTheme *theme,
{
if (min_dir->icon_data == NULL)
min_dir->icon_data = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify)icon_data_free);
+ g_free, (GDestroyNotify)icon_data_unref);
load_icon_data (min_dir, icon_file_path, icon_file_name);
- icon_info->data = g_hash_table_lookup (min_dir->icon_data, icon_name);
+ icon_info->data = icon_data_ref (g_hash_table_lookup (min_dir->icon_data, icon_name));
}
g_free (icon_file_name);
g_free (icon_file_path);
@@ -2727,7 +2728,6 @@ load_icon_data (IconThemeDir *dir, const char *path, const char *name)
int i;
gint *ivalues;
GError *error = NULL;
-
GtkIconData *data;
icon_file = g_key_file_new ();
@@ -2742,8 +2742,10 @@ load_icon_data (IconThemeDir *dir, const char *path, const char *name)
else
{
base_name = strip_suffix (name);
-
+
data = g_slice_new0 (GtkIconData);
+ data->ref = 1;
+
/* takes ownership of base_name */
g_hash_table_replace (dir->icon_data, base_name, data);
@@ -2824,7 +2826,7 @@ scan_directory (GtkIconThemePrivate *icon_theme,
{
if (dir->icon_data == NULL)
dir->icon_data = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify)icon_data_free);
+ g_free, (GDestroyNotify)icon_data_unref);
path = g_build_filename (full_dir, name, NULL);
if (g_file_test (path, G_FILE_TEST_IS_REGULAR))
@@ -2963,12 +2965,27 @@ theme_subdir_load (GtkIconTheme *icon_theme,
}
}
+static GtkIconData *
+icon_data_ref (GtkIconData *icon_data)
+{
+ if (icon_data)
+ icon_data->ref++;
+ return icon_data;
+}
+
static void
-icon_data_free (GtkIconData *icon_data)
+icon_data_unref (GtkIconData *icon_data)
{
- g_free (icon_data->attach_points);
- g_free (icon_data->display_name);
- g_slice_free (GtkIconData, icon_data);
+ if (icon_data)
+ {
+ icon_data->ref--;
+ if (icon_data->ref == 0)
+ {
+ g_free (icon_data->attach_points);
+ g_free (icon_data->display_name);
+ g_slice_free (GtkIconData, icon_data);
+ }
+ }
}
static GtkIconData *
@@ -2978,6 +2995,7 @@ icon_data_dup (GtkIconData *icon_data)
if (icon_data)
{
dup = g_slice_new0 (GtkIconData);
+ dup->ref = 1;
*dup = *icon_data;
if (dup->n_attach_points > 0)
{
@@ -3126,6 +3144,7 @@ gtk_icon_info_finalize (GObject *object)
g_object_unref (icon_info->cache_pixbuf);
if (icon_info->symbolic_pixbuf_size)
gtk_requisition_free (icon_info->symbolic_pixbuf_size);
+ icon_data_unref (icon_info->data);
symbolic_pixbuf_cache_free (icon_info->symbolic_pixbuf_cache);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]