aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fiv-browser.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/fiv-browser.c b/fiv-browser.c
index 1b01f77..df2b63d 100644
--- a/fiv-browser.c
+++ b/fiv-browser.c
@@ -72,6 +72,8 @@ struct _FivBrowser {
double drag_begin_x; ///< Viewport start X coordinate or -1
double drag_begin_y; ///< Viewport start Y coordinate or -1
+ GHashTable *thumbnail_cache; ///< [URI]cairo_surface_t, for item_size
+
Thumbnailer *thumbnailers; ///< Parallelized thumbnailers
size_t thumbnailers_len; ///< Thumbnailers array size
GList *thumbnailers_queue; ///< Queued up Entry pointers
@@ -431,9 +433,18 @@ entry_add_thumbnail(gpointer data, gpointer user_data)
g_clear_pointer(&self->thumbnail, cairo_surface_destroy);
FivBrowser *browser = FIV_BROWSER(user_data);
- self->thumbnail = rescale_thumbnail(
- fiv_thumbnail_lookup(self->uri, self->mtime_msec, browser->item_size),
- browser->item_height);
+ cairo_surface_t *cached =
+ g_hash_table_lookup(browser->thumbnail_cache, self->uri);
+ if (cached &&
+ (intptr_t) cairo_surface_get_user_data(
+ cached, &fiv_browser_key_mtime_msec) == self->mtime_msec) {
+ self->thumbnail = cairo_surface_reference(cached);
+ } else {
+ cairo_surface_t *found = fiv_thumbnail_lookup(
+ self->uri, self->mtime_msec, browser->item_size);
+ self->thumbnail = rescale_thumbnail(found, browser->item_height);
+ }
+
if (self->thumbnail) {
// This choice of mtime favours unnecessary thumbnail reloading.
cairo_surface_set_user_data(self->thumbnail,
@@ -515,8 +526,18 @@ reload_thumbnails(FivBrowser *self)
g_thread_pool_push(pool, &g_array_index(self->entries, Entry, i), NULL);
g_thread_pool_free(pool, FALSE, TRUE);
- for (guint i = 0; i < self->entries->len; i++)
- materialize_icon(self, &g_array_index(self->entries, Entry, i));
+ // Once a URI disappears from the model, its thumbnail is forgotten.
+ g_hash_table_remove_all(self->thumbnail_cache);
+
+ for (guint i = 0; i < self->entries->len; i++) {
+ Entry *entry = &g_array_index(self->entries, Entry, i);
+ if (entry->thumbnail) {
+ g_hash_table_insert(self->thumbnail_cache, g_strdup(entry->uri),
+ cairo_surface_reference(entry->thumbnail));
+ }
+
+ materialize_icon(self, entry);
+ }
gtk_widget_queue_resize(GTK_WIDGET(self));
}
@@ -928,6 +949,8 @@ fiv_browser_finalize(GObject *gobject)
g_clear_object(&self->model);
}
+ g_hash_table_destroy(self->thumbnail_cache);
+
cairo_surface_destroy(self->glow);
g_clear_object(&self->pointer);
@@ -972,6 +995,8 @@ set_item_size(FivBrowser *self, FivThumbnailSize size)
if (size != self->item_size) {
self->item_size = size;
self->item_height = fiv_thumbnail_sizes[self->item_size].size;
+
+ g_hash_table_remove_all(self->thumbnail_cache);
reload_thumbnails(self);
thumbnailers_start(self);
@@ -1688,6 +1713,9 @@ fiv_browser_init(FivBrowser *self)
g_array_set_clear_func(self->layouted_rows, (GDestroyNotify) row_free);
abort_button_tracking(self);
+ self->thumbnail_cache = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) cairo_surface_destroy);
+
self->thumbnailers_len = g_get_num_processors();
self->thumbnailers =
g_malloc0_n(self->thumbnailers_len, sizeof *self->thumbnailers);
@@ -1703,6 +1731,7 @@ fiv_browser_init(FivBrowser *self)
// --- Public interface --------------------------------------------------------
+// TODO(p): Later implement any arguments of this FivIoModel signal.
static void
on_model_files_changed(FivIoModel *model, FivBrowser *self)
{
@@ -1712,8 +1741,6 @@ on_model_files_changed(FivIoModel *model, FivBrowser *self)
if (self->selected)
selected_uri = g_strdup(self->selected->uri);
- // TODO(p): Later implement arguments of this FivIoModel signal.
- // Or ensure somehow else that thumbnails won't be reloaded unnecessarily.
thumbnailers_abort(self);
g_array_set_size(self->entries, 0);
g_array_set_size(self->layouted_rows, 0);