From 13831c6939b0ae3a4b1c06fd2c113541d82a6a8a Mon Sep 17 00:00:00 2001 From: Lars Mueller Date: Sun, 3 Nov 2019 15:45:01 +0100 Subject: [PATCH] Fix: Handle GFileIcon file changes This monitors file changes for GFileIcon and updates the StIcon accordingly --- src/st/st-icon.c | 47 ++++++++++++++++++++++++++++++++++++++- src/st/st-texture-cache.c | 47 +++++++++++++++++++++++++++++++++------ 2 files changed, 86 insertions(+), 8 deletions(-) diff --git a/src/st/st-icon.c b/src/st/st-icon.c index 2c658beec9..b6fda8475d 100644 --- a/src/st/st-icon.c +++ b/src/st/st-icon.c @@ -47,8 +47,10 @@ struct _StIconPrivate ClutterActor *icon_texture; ClutterActor *pending_texture; guint opacity_handler_id; + guint texture_file_changed_id; GIcon *gicon; + gchar *file_uri; gchar *icon_name; StIconType icon_type; gint prop_icon_size; /* icon size set as property */ @@ -141,6 +143,12 @@ st_icon_dispose (GObject *gobject) { StIconPrivate *priv = ST_ICON (gobject)->priv; + if (priv->texture_file_changed_id > 0) + { + g_signal_handler_disconnect(st_texture_cache_get_default(), priv->texture_file_changed_id); + priv->texture_file_changed_id = 0; + } + if (priv->icon_texture) { clutter_actor_destroy (priv->icon_texture); @@ -154,6 +162,9 @@ st_icon_dispose (GObject *gobject) priv->pending_texture = NULL; } + g_free (priv->file_uri); + priv->file_uri = NULL; + g_clear_object (&priv->gicon); g_clear_pointer (&priv->shadow_pipeline, cogl_object_unref); @@ -295,6 +306,8 @@ st_icon_init (StIcon *self) self->priv->shadow_pipeline = NULL; self->priv->icon_scale = 1; + + self->priv->file_uri = NULL; } static void @@ -343,6 +356,15 @@ on_pixbuf_changed (ClutterTexture *texture, clutter_actor_queue_redraw (CLUTTER_ACTOR (icon)); } +static void +on_texture_file_cb (StTextureCache *cache, + char *uri, + StIcon *icon) +{ + if (g_strcmp0 (uri, icon->priv->file_uri) == 0) + st_icon_update (icon); +} + static void st_icon_finish_update (StIcon *icon) { @@ -531,7 +553,14 @@ st_icon_set_icon_name (StIcon *icon, if (priv->gicon) { + if (icon->priv->texture_file_changed_id > 0) + { + g_signal_handler_disconnect(st_texture_cache_get_default(), icon->priv->texture_file_changed_id); + icon->priv->texture_file_changed_id = 0; + } g_object_unref (priv->gicon); + g_free (icon->priv->file_uri); + icon->priv->file_uri = NULL; priv->gicon = NULL; g_object_notify (G_OBJECT (icon), "gicon"); } @@ -609,20 +638,36 @@ st_icon_get_gicon (StIcon *icon) void st_icon_set_gicon (StIcon *icon, GIcon *gicon) { + StTextureCache *cache = st_texture_cache_get_default(); g_return_if_fail (ST_IS_ICON (icon)); g_return_if_fail (G_IS_ICON (gicon)); if (icon->priv->gicon == gicon) /* do nothing */ return; + if (icon->priv->texture_file_changed_id > 0) + { + g_signal_handler_disconnect(cache, icon->priv->texture_file_changed_id); + icon->priv->texture_file_changed_id = 0; + } + if (icon->priv->gicon) { g_object_unref (icon->priv->gicon); icon->priv->gicon = NULL; + g_free (icon->priv->file_uri); + icon->priv->file_uri = NULL; } - if (gicon) + if (gicon) { icon->priv->gicon = g_object_ref (gicon); + if (G_IS_FILE_ICON (gicon)) + { + GFile *file = g_file_icon_get_file (G_FILE_ICON(gicon)); + icon->priv->file_uri = g_file_get_uri (file); + } + icon->priv->texture_file_changed_id = g_signal_connect (cache, "texture-file-changed", G_CALLBACK (on_texture_file_cb), icon); + } if (icon->priv->icon_name) { diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c index 24b82ff9fd..2f637d1d58 100644 --- a/src/st/st-texture-cache.c +++ b/src/st/st-texture-cache.c @@ -57,6 +57,7 @@ struct _StTextureCachePrivate static void st_texture_cache_dispose (GObject *object); static void st_texture_cache_finalize (GObject *object); +static void ensure_monitor_for_uri (StTextureCache *cache, const gchar *uri); enum { @@ -831,6 +832,13 @@ load_gicon_with_colors (StTextureCache *cache, load_texture_async (cache, request); } + if (G_IS_FILE_ICON (icon)) + { + GFile *file = g_file_icon_get_file (G_FILE_ICON (icon)); + char *uri = g_file_get_uri (file); + ensure_monitor_for_uri (cache, uri); + } + return CLUTTER_ACTOR (texture); } @@ -897,24 +905,49 @@ file_changed_cb (GFileMonitor *monitor, gpointer user_data) { StTextureCache *cache = user_data; - char *uri, *key; + char *uri, *path; + + GHashTableIter iter; + gpointer key; + gpointer value; + + gchar *path_prefixed; + gchar *uri_prefixed; + gchar *uri_for_cairo_prefixed; if (event_type != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) return; uri = g_file_get_uri (file); + path = g_file_get_path (file); - key = g_strconcat (CACHE_PREFIX_URI, uri, NULL); - g_hash_table_remove (cache->priv->keyed_cache, key); - g_free (key); + path_prefixed = g_strconcat (CACHE_PREFIX_ICON, path, NULL); + uri_prefixed = g_strconcat (CACHE_PREFIX_URI, uri, NULL); + uri_for_cairo_prefixed = g_strconcat (CACHE_PREFIX_URI_FOR_CAIRO, uri, NULL); - key = g_strconcat (CACHE_PREFIX_URI_FOR_CAIRO, uri, NULL); - g_hash_table_remove (cache->priv->keyed_surface_cache, key); - g_free (key); + g_hash_table_iter_init (&iter, cache->priv->keyed_cache); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + const char *tmp = key; + if (g_str_has_prefix (tmp, path_prefixed)) + { + g_hash_table_iter_remove (&iter); + } + if (g_strcmp0 (tmp, uri_prefixed) == 0) + { + g_hash_table_iter_remove (&iter); + } + } + + g_hash_table_remove (cache->priv->keyed_surface_cache, uri_for_cairo_prefixed); g_signal_emit (cache, signals[TEXTURE_FILE_CHANGED], 0, uri); + g_free (path_prefixed); + g_free (uri_prefixed); + g_free (uri_for_cairo_prefixed); g_free (uri); + g_free (path); } static void