[gnome-software/1131-featured-carousel: 15/21] gs-app: Provide pixbufs at any requested size




commit b85a53a4d956513938fb9b423ea10ce8f82f8c4f
Author: Philip Withnall <pwithnall endlessos org>
Date:   Wed Feb 17 19:58:59 2021 +0000

    gs-app: Provide pixbufs at any requested size
    
    Rework the `gs_app_get_pixbuf()` API to return a pixbuf at a requested
    size, supporting multiple stored pixbufs per app, and resizing them in
    the `GsApp` code when needed, rather than making the caller do it every
    time.
    
    This allows more than one pixbuf for a `GsApp`, which allows the updated
    `GsFeatureTile` to use a different pixbuf size (128px) from the rest of
    the interface (64px).
    
    In future, it should be possible to fold the `gs-plugin-icons` code into
    `GsApp`, so that the metadata in `AsIcon` about *where* a pixbuf came
    from isn’t lost, which should allow pixbufs to be dropped out of memory
    and transparently reloaded when next needed, lowering runtime memory
    usage. However, that is future work.
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>
    
    Helps: #1131

 lib/gs-app.c                   | 110 ++++++++++++++++++++++++++++++++++-------
 lib/gs-app.h                   |   4 +-
 plugins/core/gs-plugin-icons.c |  13 +++--
 plugins/dummy/gs-self-test.c   |   8 ++-
 plugins/flatpak/gs-self-test.c |   4 +-
 plugins/snap/gs-plugin-snap.c  |   2 +-
 plugins/snap/gs-self-test.c    |  11 +++--
 src/gs-app-row.c               |   7 +--
 src/gs-details-page.c          |   6 +--
 src/gs-feature-tile.c          |  17 ++++---
 src/gs-popular-tile.c          |   6 ++-
 src/gs-popular-tile.ui         |   3 +-
 src/gs-shell-search-provider.c |   9 +++-
 src/gs-summary-tile.c          |   6 +--
 src/gs-summary-tile.ui         |   3 +-
 src/gs-update-dialog.c         |   6 +--
 16 files changed, 153 insertions(+), 62 deletions(-)
---
diff --git a/lib/gs-app.c b/lib/gs-app.c
index e1b24b750..5354f0920 100644
--- a/lib/gs-app.c
+++ b/lib/gs-app.c
@@ -121,7 +121,7 @@ typedef struct
        GsApp                   *runtime;
        GFile                   *local_file;
        AsContentRating         *content_rating;
-       GdkPixbuf               *pixbuf;  /* (nullable) (owned) */
+       GPtrArray               *pixbufs;  /* (nullable) (owned) (element-type GdkPixbuf), sorted by pixel 
size, smallest first */
        AsScreenshot            *action_screenshot;  /* (nullable) (owned) */
        GCancellable            *cancellable;
        GsPluginAction           pending_action;
@@ -525,8 +525,12 @@ gs_app_to_string_append (GsApp *app, GString *str)
                          gs_app_get_kudos_percentage (app));
        if (priv->name != NULL)
                gs_app_kv_lpad (str, "name", priv->name);
-       if (priv->pixbuf != NULL)
-               gs_app_kv_printf (str, "pixbuf", "%p", priv->pixbuf);
+       for (i = 0; priv->pixbufs != NULL && i < priv->pixbufs->len; i++) {
+               GdkPixbuf *pixbuf = priv->pixbufs->pdata[i];
+               gs_app_kv_printf (str, "pixbuf", "%p, %dx%d", pixbuf,
+                                 gdk_pixbuf_get_width (pixbuf),
+                                 gdk_pixbuf_get_height (pixbuf));
+       }
        if (priv->action_screenshot != NULL)
                gs_app_kv_printf (str, "action-screenshot", "%p", priv->action_screenshot);
        for (i = 0; i < priv->icons->len; i++) {
@@ -1787,21 +1791,76 @@ gs_app_set_developer_name (GsApp *app, const gchar *developer_name)
 }
 
 /**
- * gs_app_get_pixbuf:
+ * gs_app_has_pixbufs:
  * @app: a #GsApp
  *
- * Gets a pixbuf to represent the application.
+ * Gets whether there are any pixbufs set for this app.
  *
- * Returns: (transfer none) (nullable): a #GdkPixbuf, or %NULL
+ * Returns: %TRUE if one or more pixbufs are set for the app, %FALSE otherwise
+ * Since: 40
+ */
+gboolean
+gs_app_has_pixbufs (GsApp *app)
+{
+       GsAppPrivate *priv = gs_app_get_instance_private (app);
+
+       g_return_val_if_fail (GS_IS_APP (app), FALSE);
+
+       return (priv->pixbufs != NULL && priv->pixbufs->len > 0);
+}
+
+/**
+ * gs_app_load_pixbuf:
+ * @app: a #GsApp
+ * @size: size (width or height, square) of the pixbuf to load, in device pixels
  *
- * Since: 3.22
+ * Loads a pixbuf to represent the application. This might be provided by the
+ * backend at the given @size, or downsized from a larger icon provided by the
+ * backend. The return value is guaranteed to be at @size, if it’s not %NULL.
+ *
+ * If an image at least @size pixels in width isn’t available, %NULL will be
+ * returned.
+ *
+ * This function may do disk I/O or image resizing, but it will not do network
+ * I/O to load a pixbuf. It should be acceptable to call this from a UI thread.
+ *
+ * Returns: (transfer full) (nullable): a #GdkPixbuf, or %NULL
+ *
+ * Since: 40
  **/
 GdkPixbuf *
-gs_app_get_pixbuf (GsApp *app)
+gs_app_load_pixbuf (GsApp *app,
+                    guint  size)
 {
        GsAppPrivate *priv = gs_app_get_instance_private (app);
+
        g_return_val_if_fail (GS_IS_APP (app), NULL);
-       return priv->pixbuf;
+       g_return_val_if_fail (size > 0, NULL);
+
+       /* FIXME: This algorithm currently relies on gs-plugin-icons to
+        * asynchronously load #AsIcons from #GsApp.icons and add them as
+        * pixbufs. Eventually, that plugin should be retired and its code
+        * folded in here. But for now, we can rely on everything being
+        * available as a pixbuf. */
+
+       /* See if there’s a pixbuf the right size. Note that the pixbufs array
+        * may be lazily created. */
+       for (guint i = 0; priv->pixbufs != NULL && i < priv->pixbufs->len; i++) {
+               GdkPixbuf *pixbuf = priv->pixbufs->pdata[i];
+               if ((guint) gdk_pixbuf_get_width (pixbuf) == size)
+                       return g_object_ref (pixbuf);
+               else if ((guint) gdk_pixbuf_get_width (pixbuf) > size)
+                       break;  /* array is sorted by size */
+       }
+
+       /* Now see if there’s a pixbuf which is too big, which could be resized. */
+       for (guint i = 0; priv->pixbufs != NULL && i < priv->pixbufs->len; i++) {
+               GdkPixbuf *pixbuf = priv->pixbufs->pdata[i];
+               if ((guint) gdk_pixbuf_get_width (pixbuf) > size)
+                       return gdk_pixbuf_scale_simple (pixbuf, size, size, GDK_INTERP_BILINEAR);
+       }
+
+       return NULL;
 }
 
 /**
@@ -2065,13 +2124,33 @@ gs_app_add_pixbuf (GsApp *app, GdkPixbuf *pixbuf)
 {
        GsAppPrivate *priv = gs_app_get_instance_private (app);
        g_autoptr(GMutexLocker) locker = NULL;
+       guint pixbuf_width;
 
        g_return_if_fail (GS_IS_APP (app));
        g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
 
-       /* TODO: For the moment, only one pixbuf is actually supported */
        locker = g_mutex_locker_new (&priv->mutex);
-       g_set_object (&priv->pixbuf, pixbuf);
+       pixbuf_width = gdk_pixbuf_get_width (pixbuf);
+
+       if (priv->pixbufs == NULL)
+               priv->pixbufs = g_ptr_array_new_with_free_func (g_object_unref);
+
+       /* Replace any existing pixbuf of the same size, or insert in order. */
+       for (guint i = 0; i < priv->pixbufs->len; i++) {
+               GdkPixbuf *p = priv->pixbufs->pdata[i];
+               guint p_width = gdk_pixbuf_get_width (p);
+
+               if (p_width == pixbuf_width) {
+                       g_set_object (&priv->pixbufs->pdata[i], pixbuf);
+                       return;
+               } else if (p_width > pixbuf_width) {
+                       g_ptr_array_insert (priv->pixbufs, i, g_object_ref (pixbuf));
+                       return;
+               }
+       }
+
+       /* Append if the array is empty. */
+       g_ptr_array_add (priv->pixbufs, g_object_ref (pixbuf));
 }
 
 /**
@@ -4125,7 +4204,6 @@ static void
 calculate_key_colors (GsApp *app)
 {
        GsAppPrivate *priv = gs_app_get_instance_private (app);
-       GdkPixbuf *pb;
        g_autoptr(GdkPixbuf) pb_small = NULL;
 
        /* Lazily create the array */
@@ -4133,14 +4211,13 @@ calculate_key_colors (GsApp *app)
                priv->key_colors = g_ptr_array_new_with_free_func ((GDestroyNotify) gdk_rgba_free);
 
        /* no pixbuf */
-       pb = gs_app_get_pixbuf (app);
-       if (pb == NULL) {
+       pb_small = gs_app_load_pixbuf (app, 32);
+       if (pb_small == NULL) {
                g_debug ("no pixbuf, so no key colors");
                return;
        }
 
        /* get a list of key colors */
-       pb_small = gdk_pixbuf_scale_simple (pb, 32, 32, GDK_INTERP_BILINEAR);
        key_colors_set_for_pixbuf (app, pb_small, 10);
 }
 
@@ -4800,8 +4877,7 @@ gs_app_finalize (GObject *object)
                g_object_unref (priv->local_file);
        if (priv->content_rating != NULL)
                g_object_unref (priv->content_rating);
-       if (priv->pixbuf != NULL)
-               g_object_unref (priv->pixbuf);
+       g_clear_pointer (&priv->pixbufs, g_ptr_array_unref);
        if (priv->action_screenshot != NULL)
                g_object_unref (priv->action_screenshot);
 
diff --git a/lib/gs-app.h b/lib/gs-app.h
index 50b85e8e0..acace9ca0 100644
--- a/lib/gs-app.h
+++ b/lib/gs-app.h
@@ -353,7 +353,9 @@ void                 gs_app_set_update_urgency      (GsApp          *app,
 const gchar    *gs_app_get_management_plugin   (GsApp          *app);
 void            gs_app_set_management_plugin   (GsApp          *app,
                                                 const gchar    *management_plugin);
-GdkPixbuf      *gs_app_get_pixbuf              (GsApp          *app);
+gboolean        gs_app_has_pixbufs             (GsApp          *app);
+GdkPixbuf      *gs_app_load_pixbuf             (GsApp          *app,
+                                                guint           size);
 void            gs_app_add_pixbuf              (GsApp          *app,
                                                 GdkPixbuf      *pixbuf);
 GPtrArray      *gs_app_get_icons               (GsApp          *app);
diff --git a/plugins/core/gs-plugin-icons.c b/plugins/core/gs-plugin-icons.c
index 11c0af159..71133c227 100644
--- a/plugins/core/gs-plugin-icons.c
+++ b/plugins/core/gs-plugin-icons.c
@@ -314,7 +314,7 @@ refine_app (GsPlugin             *plugin,
                return TRUE;
 
        /* invalid */
-       if (gs_app_get_pixbuf (app) != NULL)
+       if (gs_app_has_pixbufs (app))
                return TRUE;
 
        /* process all icons */
@@ -348,13 +348,12 @@ refine_app (GsPlugin             *plugin,
                }
                if (pixbuf != NULL) {
                        gs_app_add_pixbuf (app, pixbuf);
-                       break;
+               } else {
+                       /* we failed, but keep going */
+                       g_debug ("failed to load icon for %s: %s",
+                                gs_app_get_id (app),
+                                error_local->message);
                }
-
-               /* we failed, but keep going */
-               g_debug ("failed to load icon for %s: %s",
-                        gs_app_get_id (app),
-                        error_local->message);
        }
 
        return TRUE;
diff --git a/plugins/dummy/gs-self-test.c b/plugins/dummy/gs-self-test.c
index 9ebaaea6b..cfe605ab8 100644
--- a/plugins/dummy/gs-self-test.c
+++ b/plugins/dummy/gs-self-test.c
@@ -348,6 +348,7 @@ gs_plugins_dummy_installed_func (GsPluginLoader *plugin_loader)
        g_autoptr(GError) error = NULL;
        g_autoptr(GsAppList) list = NULL;
        g_autoptr(GsPluginJob) plugin_job = NULL;
+       g_autoptr(GdkPixbuf) pixbuf = NULL;
 
        /* get installed packages */
        plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_GET_INSTALLED,
@@ -372,7 +373,9 @@ gs_plugins_dummy_installed_func (GsPluginLoader *plugin_loader)
        g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
        g_assert_cmpstr (gs_app_get_name (app), ==, "Zeus");
        g_assert_cmpstr (gs_app_get_source_default (app), ==, "zeus");
-       g_assert (gs_app_get_pixbuf (app) != NULL);
+       pixbuf = gs_app_load_pixbuf (app, 48);
+       g_assert_nonnull (pixbuf);
+       g_clear_object (&pixbuf);
 
        /* check various bitfields */
        g_assert (gs_app_has_quirk (app, GS_APP_QUIRK_PROVENANCE));
@@ -401,7 +404,8 @@ gs_plugins_dummy_installed_func (GsPluginLoader *plugin_loader)
        g_assert_cmpstr (gs_app_get_source_default (addon), ==, "zeus-spell");
        g_assert_cmpstr (gs_app_get_license (addon), ==,
                         "LicenseRef-free=https://www.debian.org/";);
-       g_assert (gs_app_get_pixbuf (addon) == NULL);
+       pixbuf = gs_app_load_pixbuf (addon, 48);
+       g_assert_null (pixbuf);
 }
 
 static void
diff --git a/plugins/flatpak/gs-self-test.c b/plugins/flatpak/gs-self-test.c
index 476d9883c..9408d14d8 100644
--- a/plugins/flatpak/gs-self-test.c
+++ b/plugins/flatpak/gs-self-test.c
@@ -115,6 +115,7 @@ gs_plugins_flatpak_repo_func (GsPluginLoader *plugin_loader)
        g_autoptr(GsApp) app2 = NULL;
        g_autoptr(GsApp) app = NULL;
        g_autoptr(GsPluginJob) plugin_job = NULL;
+       g_autoptr(GdkPixbuf) pixbuf = NULL;
 
        /* no flatpak, abort */
        if (!gs_plugin_loader_get_enabled (plugin_loader, "flatpak"))
@@ -150,7 +151,8 @@ gs_plugins_flatpak_repo_func (GsPluginLoader *plugin_loader)
        g_assert_cmpstr (gs_app_get_description (app), ==,
                         "Longer multiline comment that does into detail.");
        g_assert_true (gs_app_get_local_file (app) != NULL);
-       g_assert_true (gs_app_get_pixbuf (app) != NULL);
+       pixbuf = gs_app_load_pixbuf (app, 64);
+       g_assert_nonnull (pixbuf);
 
        /* now install the remote */
        g_object_unref (plugin_job);
diff --git a/plugins/snap/gs-plugin-snap.c b/plugins/snap/gs-plugin-snap.c
index 87b1820ea..8a82e9630 100644
--- a/plugins/snap/gs-plugin-snap.c
+++ b/plugins/snap/gs-plugin-snap.c
@@ -1071,7 +1071,7 @@ refine_app_with_client (GsPlugin             *plugin,
        }
 
        /* load icon if requested */
-       if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON && gs_app_get_pixbuf (app) == NULL)
+       if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON && !gs_app_has_pixbufs (app))
                load_icon (plugin, client, app, snap_name, local_snap, store_snap, cancellable);
 
        return TRUE;
diff --git a/plugins/snap/gs-self-test.c b/plugins/snap/gs-self-test.c
index d3aa69e1e..41696c114 100644
--- a/plugins/snap/gs-self-test.c
+++ b/plugins/snap/gs-self-test.c
@@ -261,7 +261,7 @@ gs_plugins_snap_test_func (GsPluginLoader *plugin_loader)
        GPtrArray *screenshots, *images;
        AsScreenshot *screenshot;
        AsImage *image;
-       GdkPixbuf *pixbuf;
+       g_autoptr(GdkPixbuf) pixbuf = NULL;
        g_autoptr(GError) error = NULL;
 
        /* no snap, abort */
@@ -300,7 +300,7 @@ gs_plugins_snap_test_func (GsPluginLoader *plugin_loader)
        g_assert_cmpstr (as_image_get_url (image), ==, "http://example.com/screenshot2.jpg";);
        g_assert_cmpint (as_image_get_width (image), ==, 1024);
        g_assert_cmpint (as_image_get_height (image), ==, 768);
-       pixbuf = gs_app_get_pixbuf (app);
+       pixbuf = gs_app_load_pixbuf (app, 64);
        g_assert_null (pixbuf);
        g_assert_cmpint (gs_app_get_size_installed (app), ==, 0);
        g_assert_cmpint (gs_app_get_size_download (app), ==, 500);
@@ -319,9 +319,10 @@ gs_plugins_snap_test_func (GsPluginLoader *plugin_loader)
        g_assert_cmpint (gs_app_get_size_installed (app), ==, 1000);
        g_assert_cmpint (gs_app_get_install_date (app), ==, g_date_time_to_unix (g_date_time_new_utc (2017, 
1, 2, 11, 23, 58)));
 
-       pixbuf = gs_app_get_pixbuf (app);
-       g_assert_cmpint (gdk_pixbuf_get_width (pixbuf), ==, 64);
-       g_assert_cmpint (gdk_pixbuf_get_height (pixbuf), ==, 64);
+       pixbuf = gs_app_load_pixbuf (app, 128);
+       g_assert_nonnull (pixbuf);
+       g_assert_cmpint (gdk_pixbuf_get_width (pixbuf), ==, 128);
+       g_assert_cmpint (gdk_pixbuf_get_height (pixbuf), ==, 128);
 
        g_object_unref (plugin_job);
        plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
diff --git a/src/gs-app-row.c b/src/gs-app-row.c
index c2d4e629b..bfd8f28c7 100644
--- a/src/gs-app-row.c
+++ b/src/gs-app-row.c
@@ -246,6 +246,7 @@ gs_app_row_actually_refresh (GsAppRow *app_row)
        const gchar *tmp;
        gboolean missing_search_result;
        guint64 size = 0;
+       g_autoptr(GdkPixbuf) pixbuf = NULL;
 
        if (priv->app == NULL)
                return;
@@ -388,13 +389,13 @@ gs_app_row_actually_refresh (GsAppRow *app_row)
        }
 
        /* pixbuf */
-       if (gs_app_get_pixbuf (priv->app) == NULL) {
+       pixbuf = gs_app_load_pixbuf (priv->app, gtk_image_get_pixel_size (GTK_IMAGE (priv->image)) * 
gtk_widget_get_scale_factor (priv->image));
+       if (pixbuf == NULL) {
                gtk_image_set_from_icon_name (GTK_IMAGE (priv->image),
                                              "application-x-executable",
                                              GTK_ICON_SIZE_DIALOG);
        } else {
-               gs_image_set_from_pixbuf (GTK_IMAGE (priv->image),
-                                         gs_app_get_pixbuf (priv->app));
+               gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), pixbuf);
        }
 
        context = gtk_widget_get_style_context (priv->image);
diff --git a/src/gs-details-page.c b/src/gs-details-page.c
index 099ff06d0..d9bf92802 100644
--- a/src/gs-details-page.c
+++ b/src/gs-details-page.c
@@ -1101,7 +1101,7 @@ static void
 gs_details_page_refresh_all (GsDetailsPage *self)
 {
        GsAppList *history;
-       GdkPixbuf *pixbuf = NULL;
+       g_autoptr(GdkPixbuf) pixbuf = NULL;
        GList *addons;
        const gchar *tmp;
        gboolean ret;
@@ -1138,9 +1138,9 @@ gs_details_page_refresh_all (GsDetailsPage *self)
        gs_details_page_set_description (self, tmp);
 
        /* set the icon */
-       pixbuf = gs_app_get_pixbuf (self->app);
+       pixbuf = gs_app_load_pixbuf (self->app, gtk_image_get_pixel_size (GTK_IMAGE 
(self->application_details_icon)) * gtk_widget_get_scale_factor (self->application_details_icon));
        if (pixbuf != NULL) {
-               gs_image_set_from_pixbuf (GTK_IMAGE (self->application_details_icon), pixbuf);
+               gtk_image_set_from_pixbuf (GTK_IMAGE (self->application_details_icon), pixbuf);
        } else {
                gtk_image_set_from_icon_name (GTK_IMAGE (self->application_details_icon),
                                              "application-x-executable",
diff --git a/src/gs-feature-tile.c b/src/gs-feature-tile.c
index 5ffd9074a..a5a975083 100644
--- a/src/gs-feature-tile.c
+++ b/src/gs-feature-tile.c
@@ -54,6 +54,7 @@ gs_feature_tile_refresh (GsAppTile *self)
        const gchar *markup = NULL;
        g_autofree gchar *name = NULL;
        GtkStyleContext *context;
+       g_autoptr(GdkPixbuf) pixbuf = NULL;
 
        if (app == NULL)
                return;
@@ -67,14 +68,14 @@ gs_feature_tile_refresh (GsAppTile *self)
        else
                gtk_style_context_remove_class (context, "narrow");
 
-       /* Update the icon. */
-       if (gs_app_get_pixbuf (app) != NULL) {
-               guint desired_width = tile->narrow_mode ? 128 : 160;
-               GdkPixbuf *pixbuf = gs_app_get_pixbuf (app);
-               guint pixbuf_width = (guint) gdk_pixbuf_get_width (pixbuf);
-               guint scale = (desired_width <= pixbuf_width) ? pixbuf_width / desired_width : 1;
-
-               gs_image_set_from_pixbuf_with_scale (GTK_IMAGE (tile->image), pixbuf, scale);
+       /* Update the icon. Try a 160px version if not in narrow mode, and it’s
+        * available; otherwise use 128px. */
+       if (!tile->narrow_mode)
+               pixbuf = gs_app_load_pixbuf (app, 160 * gtk_widget_get_scale_factor (tile->image));
+       if (pixbuf == NULL)
+               pixbuf = gs_app_load_pixbuf (app, 128 * gtk_widget_get_scale_factor (tile->image));
+       if (pixbuf != NULL) {
+               gtk_image_set_from_pixbuf (GTK_IMAGE (tile->image), pixbuf);
                gtk_widget_show (tile->image);
        } else {
                gtk_widget_hide (tile->image);
diff --git a/src/gs-popular-tile.c b/src/gs-popular-tile.c
index 4ed0f9d49..75f8dbb6a 100644
--- a/src/gs-popular-tile.c
+++ b/src/gs-popular-tile.c
@@ -48,6 +48,7 @@ gs_popular_tile_refresh (GsAppTile *self)
        gboolean installed;
        g_autofree gchar *name = NULL;
        const gchar *css;
+       g_autoptr(GdkPixbuf) pixbuf = NULL;
 
        if (app == NULL)
                return;
@@ -88,8 +89,9 @@ gs_popular_tile_refresh (GsAppTile *self)
        css = gs_app_get_metadata_item (app, "GnomeSoftware::PopularTile-css");
        gs_utils_widget_set_css (GTK_WIDGET (tile), &tile->tile_provider, "popular-tile", css);
 
-       if (gs_app_get_pixbuf (app) != NULL) {
-               gs_image_set_from_pixbuf (GTK_IMAGE (tile->image), gs_app_get_pixbuf (app));
+       pixbuf = gs_app_load_pixbuf (app, gtk_image_get_pixel_size (GTK_IMAGE (tile->image)) * 
gtk_widget_get_scale_factor (tile->image));
+       if (pixbuf != NULL) {
+               gtk_image_set_from_pixbuf (GTK_IMAGE (tile->image), pixbuf);
        } else {
                gtk_image_set_from_icon_name (GTK_IMAGE (tile->image),
                                              "application-x-executable",
diff --git a/src/gs-popular-tile.ui b/src/gs-popular-tile.ui
index 17e4eecd6..e48e913d1 100644
--- a/src/gs-popular-tile.ui
+++ b/src/gs-popular-tile.ui
@@ -68,8 +68,7 @@
                     <property name="margin-bottom">16</property>
                     <child>
                       <object class="GtkImage" id="image">
-                        <property name="width-request">64</property>
-                        <property name="height-request">64</property>
+                        <property name="pixel-size">64</property>
                         <property name="visible">True</property>
                         <property name="valign">center</property>
                         <property name="vexpand">True</property>
diff --git a/src/gs-shell-search-provider.c b/src/gs-shell-search-provider.c
index 98ddc9215..35c3913cf 100644
--- a/src/gs-shell-search-provider.c
+++ b/src/gs-shell-search-provider.c
@@ -224,7 +224,6 @@ handle_get_result_metas (GsShellSearchProvider2     *skeleton,
        GsShellSearchProvider *self = user_data;
        GVariantBuilder meta;
        GVariant *meta_variant;
-       GdkPixbuf *pixbuf;
        gint i;
        GVariantBuilder builder;
 
@@ -232,6 +231,7 @@ handle_get_result_metas (GsShellSearchProvider2     *skeleton,
 
        for (i = 0; results[i]; i++) {
                GsApp *app;
+               g_autoptr(GdkPixbuf) pixbuf = NULL;
                g_autofree gchar *description = NULL;
 
                /* already built */
@@ -248,9 +248,14 @@ handle_get_result_metas (GsShellSearchProvider2    *skeleton,
                g_variant_builder_init (&meta, G_VARIANT_TYPE ("a{sv}"));
                g_variant_builder_add (&meta, "{sv}", "id", g_variant_new_string (gs_app_get_unique_id 
(app)));
                g_variant_builder_add (&meta, "{sv}", "name", g_variant_new_string (gs_app_get_name (app)));
-               pixbuf = gs_app_get_pixbuf (app);
+               /* ICON_SIZE is defined as 24px in js/ui/search.js in gnome-shell */
+               pixbuf = gs_app_load_pixbuf (app, 24);
                if (pixbuf != NULL)
                        g_variant_builder_add (&meta, "{sv}", "icon", g_icon_serialize (G_ICON (pixbuf)));
+               /* FIXME: Ideally we’d provide a `gicon` field here with the results of g_icon_to_string(),
+                * if possible, which would allow gnome-shell to load the app’s
+                * icon from the icon theme (if available) and potentially save
+                * time and memory */
 
                if (gs_utils_list_has_component_fuzzy (self->search_results, app) &&
                    gs_app_get_origin_hostname (app) != NULL) {
diff --git a/src/gs-summary-tile.c b/src/gs-summary-tile.c
index 187f8871e..e80022838 100644
--- a/src/gs-summary-tile.c
+++ b/src/gs-summary-tile.c
@@ -40,7 +40,7 @@ gs_summary_tile_refresh (GsAppTile *self)
        GsApp *app = gs_app_tile_get_app (self);
        AtkObject *accessible;
        GtkStyleContext *context;
-       const GdkPixbuf *pixbuf;
+       g_autoptr(GdkPixbuf) pixbuf = NULL;
        gboolean installed;
        g_autofree gchar *name = NULL;
        const gchar *summary;
@@ -60,9 +60,9 @@ gs_summary_tile_refresh (GsAppTile *self)
        gtk_label_set_label (GTK_LABEL (tile->summary), summary);
        gtk_widget_set_visible (tile->summary, summary && summary[0]);
 
-       pixbuf = gs_app_get_pixbuf (app);
+       pixbuf = gs_app_load_pixbuf (app, gtk_image_get_pixel_size (GTK_IMAGE (tile->image)) * 
gtk_widget_get_scale_factor (tile->image));
        if (pixbuf != NULL) {
-               gs_image_set_from_pixbuf (GTK_IMAGE (tile->image), pixbuf);
+               gtk_image_set_from_pixbuf (GTK_IMAGE (tile->image), pixbuf);
        } else {
                gtk_image_set_from_icon_name (GTK_IMAGE (tile->image),
                                              "application-x-executable",
diff --git a/src/gs-summary-tile.ui b/src/gs-summary-tile.ui
index a63bbd6fd..6f1b39c0c 100644
--- a/src/gs-summary-tile.ui
+++ b/src/gs-summary-tile.ui
@@ -68,8 +68,7 @@
                 <child>
                   <object class="GtkImage" id="image">
                     <property name="visible">True</property>
-                    <property name="width-request">64</property>
-                    <property name="height-request">64</property>
+                    <property name="pixel-size">64</property>
                   </object>
                   <packing>
                     <property name="left-attach">0</property>
diff --git a/src/gs-update-dialog.c b/src/gs-update-dialog.c
index 059188b13..cd8487236 100644
--- a/src/gs-update-dialog.c
+++ b/src/gs-update-dialog.c
@@ -157,7 +157,7 @@ static void
 set_updates_description_ui (GsUpdateDialog *dialog, GsApp *app)
 {
        AsComponentKind kind;
-       const GdkPixbuf *pixbuf;
+       g_autoptr(GdkPixbuf) pixbuf = NULL;
        const gchar *update_details;
 
        /* set window title */
@@ -192,9 +192,9 @@ set_updates_description_ui (GsUpdateDialog *dialog, GsApp *app)
        gtk_label_set_label (GTK_LABEL (dialog->label_name), gs_app_get_name (app));
        gtk_label_set_label (GTK_LABEL (dialog->label_summary), gs_app_get_summary (app));
 
-       pixbuf = gs_app_get_pixbuf (app);
+       pixbuf = gs_app_load_pixbuf (app, gtk_image_get_pixel_size (GTK_IMAGE (dialog->image_icon)) * 
gtk_widget_get_scale_factor (dialog->image_icon));
        if (pixbuf != NULL)
-               gs_image_set_from_pixbuf (GTK_IMAGE (dialog->image_icon), pixbuf);
+               gtk_image_set_from_pixbuf (GTK_IMAGE (dialog->image_icon), pixbuf);
 
        /* show the back button if needed */
        gtk_widget_set_visible (dialog->button_back, !g_queue_is_empty (dialog->back_entry_stack));


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