filethumbnail: Set filechooser::queried after querying
authorGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>
Tue, 28 Feb 2023 16:54:11 +0000 (13:54 -0300)
committerGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>
Tue, 28 Feb 2023 17:18:30 +0000 (14:18 -0300)
Setting this attribute after querying, but before receiving the
results, can lead to inappropriate behaviour. This can be reproduced
by dragging the scrollbar very quickly in a large directory; after
going up and down a few times, some thumbnails will be wrong.

Without this branch, "wrong" means they'll show the completely wrong
icon or thumbnail, e.g. a folder icon in a video file. With previous
commit, "wrong" means they'll be empty even when there is a thumbnail
available.

The sequence of events that triggers this is as follows:

 1. GtkListItem receives a GFileInfo object and passes it to
    GtkFileThumbnail via expressions

 2. `get_thumbnail()` is called, doesn't find a thumbnail

 3. `filechooser::queried` is not set yet, so it is set to TRUE
      and we call `g_file_query_info_async()`

 4. **Before `thumbnail_queried_cb` is called**, a new GFileInfo
    is set, and we cancel the query initiated in the previous
    step

 5. We now have a GFileInfo with `filechooser::queried` set to
    TRUE, and no thumbnail!

This commit fixes that by only setting the `filechooser::queried`
attribute after the icon is queried. We need to set it in two
situations: when the query is successful, or when the error is
not G_IO_ERROR_CANCELLED. That's because the query was cancelled,
we didn't really perform it!

gtk/gtkfilethumbnail.c

index 3e01484158609a82e52f3efb9f846094cd5308d7..84df7dcc07d73f41223e9fd3d3613f887bc3f80f 100644 (file)
@@ -104,10 +104,19 @@ thumbnail_queried_cb (GObject      *object,
   GtkFileThumbnail *self = user_data; /* might be unreffed if operation was cancelled */
   GFile *file = G_FILE (object);
   GFileInfo *queried;
+  GError *error = NULL;
 
-  queried = g_file_query_info_finish (file, result, NULL);
-  if (queried == NULL)
-    return;
+  queried = g_file_query_info_finish (file, result, &error);
+
+  if (error)
+    {
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        g_file_info_set_attribute_boolean (self->info, "filechooser::queried", TRUE);
+      g_clear_error (&error);
+      return;
+    }
+
+  g_file_info_set_attribute_boolean (self->info, "filechooser::queried", TRUE);
 
   copy_attribute (self->info, queried, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
   copy_attribute (self->info, queried, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED);
@@ -147,7 +156,6 @@ get_thumbnail (GtkFileThumbnail *self)
       self->cancellable = g_cancellable_new ();
 
       file = _gtk_file_info_get_file (self->info);
-      g_file_info_set_attribute_boolean (self->info, "filechooser::queried", TRUE);
       g_file_query_info_async (file,
                                G_FILE_ATTRIBUTE_THUMBNAIL_PATH ","
                                G_FILE_ATTRIBUTE_THUMBNAILING_FAILED ","