[gnome-shell] st-texture-cache: Add texture-file-changed signal



commit 9c8b75206c086b90558a3ba751203d9cd4757f3f
Author: Florian MÃllner <fmuellner gnome org>
Date:   Thu Sep 20 21:42:52 2012 +0200

    st-texture-cache: Add texture-file-changed signal
    
    For textures loaded from files, the cache might hide image changes
    by keeping the data of a previous version around indefinitely. For
    instance AccountsService will notify of avatar changes, but as new
    image is copied over the old one, we will continue to use the old
    image data.
    Install a file monitor for each file resource we load and clear
    the corresponding data from the cache on changes, emitting the
    new StTextureCache::texture-file-changed signal.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=679268

 src/st/st-texture-cache.c |   77 ++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 70 insertions(+), 7 deletions(-)
---
diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c
index 0508006..2ba0f8e 100644
--- a/src/st/st-texture-cache.c
+++ b/src/st/st-texture-cache.c
@@ -42,6 +42,9 @@ struct _StTextureCachePrivate
 
   /* Presently this is used to de-duplicate requests for GIcons and async URIs. */
   GHashTable *outstanding_requests; /* char * -> AsyncTextureLoadData * */
+
+  /* File monitors to evict cache data on changes */
+  GHashTable *file_monitors; /* char * -> GFileMonitor * */
 };
 
 static void st_texture_cache_dispose (GObject *object);
@@ -50,6 +53,7 @@ static void st_texture_cache_finalize (GObject *object);
 enum
 {
   ICON_THEME_CHANGED,
+  TEXTURE_FILE_CHANGED,
 
   LAST_SIGNAL
 };
@@ -92,6 +96,14 @@ st_texture_cache_class_init (StTextureCacheClass *klass)
                   0, /* no default handler slot */
                   NULL, NULL, NULL,
                   G_TYPE_NONE, 0);
+
+  signals[TEXTURE_FILE_CHANGED] =
+    g_signal_new ("texture-file-changed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  0, /* no default handler slot */
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 1, G_TYPE_STRING);
 }
 
 /**
@@ -164,6 +176,9 @@ st_texture_cache_init (StTextureCache *self)
                                                    g_free, cogl_handle_unref);
   self->priv->outstanding_requests = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                             g_free, NULL);
+  self->priv->file_monitors = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                     g_object_unref, g_object_unref);
+
 }
 
 static void
@@ -179,13 +194,9 @@ st_texture_cache_dispose (GObject *object)
       self->priv->icon_theme = NULL;
     }
 
-  if (self->priv->keyed_cache)
-    g_hash_table_destroy (self->priv->keyed_cache);
-  self->priv->keyed_cache = NULL;
-
-  if (self->priv->outstanding_requests)
-    g_hash_table_destroy (self->priv->outstanding_requests);
-  self->priv->outstanding_requests = NULL;
+  g_clear_pointer (&self->priv->keyed_cache, g_hash_table_destroy);
+  g_clear_pointer (&self->priv->outstanding_requests, g_hash_table_destroy);
+  g_clear_pointer (&self->priv->file_monitors, g_hash_table_destroy);
 
   G_OBJECT_CLASS (st_texture_cache_parent_class)->dispose (object);
 }
@@ -1039,6 +1050,52 @@ load_from_pixbuf (GdkPixbuf *pixbuf)
   return CLUTTER_ACTOR (texture);
 }
 
+static void
+file_changed_cb (GFileMonitor      *monitor,
+                 GFile             *file,
+                 GFile             *other,
+                 GFileMonitorEvent  event_type,
+                 gpointer           user_data)
+{
+  StTextureCache *cache = user_data;
+  char *uri, *key;
+
+  if (event_type != G_FILE_MONITOR_EVENT_CHANGED)
+    return;
+
+  uri = g_file_get_uri (file);
+
+  key = g_strconcat (CACHE_PREFIX_URI, uri, NULL);
+  g_hash_table_remove (cache->priv->keyed_cache, key);
+  g_free (key);
+
+  key = g_strconcat (CACHE_PREFIX_URI_FOR_CAIRO, uri, NULL);
+  g_hash_table_remove (cache->priv->keyed_cache, key);
+  g_free (key);
+
+  g_signal_emit (cache, signals[TEXTURE_FILE_CHANGED], 0, uri);
+
+  g_free (uri);
+}
+
+static void
+ensure_monitor_for_uri (StTextureCache *cache,
+                        const gchar    *uri)
+{
+  StTextureCachePrivate *priv = cache->priv;
+  GFile *file = g_file_new_for_uri (uri);
+
+  if (g_hash_table_lookup (priv->file_monitors, uri) == NULL)
+    {
+      GFileMonitor *monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE,
+                                                   NULL, NULL);
+      g_signal_connect (monitor, "changed",
+                        G_CALLBACK (file_changed_cb), cache);
+      g_hash_table_insert (priv->file_monitors, g_strdup (uri), monitor);
+    }
+  g_object_unref (file);
+}
+
 typedef struct {
   gchar *path;
   gint   grid_width, grid_height;
@@ -1211,6 +1268,8 @@ st_texture_cache_load_uri_async (StTextureCache *cache,
       load_texture_async (cache, request);
     }
 
+  ensure_monitor_for_uri (cache, uri);
+
   return CLUTTER_ACTOR (texture);
 }
 
@@ -1248,6 +1307,8 @@ st_texture_cache_load_uri_sync_to_cogl_texture (StTextureCache *cache,
   else
     cogl_handle_ref (texdata);
 
+  ensure_monitor_for_uri (cache, uri);
+
 out:
   g_free (key);
   return texdata;
@@ -1287,6 +1348,8 @@ st_texture_cache_load_uri_sync_to_cairo_surface (StTextureCache        *cache,
   else
     cairo_surface_reference (surface);
 
+  ensure_monitor_for_uri (cache, uri);
+
 out:
   g_free (key);
   return surface;



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