static cairo_surface_t *
get_content_loading_icon (BgSource *source)
{
  GtkIconTheme *theme;
  GtkIconInfo *icon_info;
  GdkPixbuf *pixbuf, *ret;
  GError *error = NULL;
  int scale_factor;
  cairo_surface_t *surface;
  int thumbnail_height;
  int thumbnail_width;

  theme = gtk_icon_theme_get_default ();
  icon_info = gtk_icon_theme_lookup_icon (theme,
                                          "content-loading-symbolic",
                                          16,
                                          GTK_ICON_LOOKUP_FORCE_SIZE | GTK_ICON_LOOKUP_GENERIC_FALLBACK);
  if (icon_info == NULL)
    {
      g_warning ("Failed to find placeholder icon");
      return NULL;
    }

  pixbuf = gtk_icon_info_load_icon (icon_info, &error);
  if (pixbuf == NULL)
    {
      g_warning ("Failed to load placeholder icon: %s", error->message);
      g_clear_error (&error);
      g_clear_object (&icon_info);
      return NULL;
    }

  thumbnail_height = bg_source_get_thumbnail_height (source);
  thumbnail_width = bg_source_get_thumbnail_width (source);
  ret = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
                        TRUE,
                        8, thumbnail_width, thumbnail_height);
  gdk_pixbuf_fill (ret, 0x00000000);

  /* Put the icon in the middle */
  gdk_pixbuf_copy_area (pixbuf, 0, 0,
			gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf),
			ret,
			(thumbnail_width - gdk_pixbuf_get_width (pixbuf)) / 2,
			(thumbnail_height - gdk_pixbuf_get_height (pixbuf)) / 2);
  g_object_unref (pixbuf);

  scale_factor = bg_source_get_scale_factor (source);
  surface = gdk_cairo_surface_create_from_pixbuf (ret, scale_factor, NULL);
  g_object_unref (ret);
  g_clear_object (&icon_info);

  return surface;
}
static void
picture_scaled (GObject *source_object,
                GAsyncResult *res,
                gpointer user_data)
{
  BgPicturesSource *bg_source;
  CcBackgroundItem *item;
  GError *error = NULL;
  GdkPixbuf *pixbuf = NULL;
  const char *software;
  const char *uri;
  GtkTreeIter iter;
  GtkTreePath *path;
  GtkTreeRowReference *row_ref;
  GtkListStore *store;
  cairo_surface_t *surface = NULL;
  int scale_factor;

  item = g_object_get_data (source_object, "item");
  pixbuf = gdk_pixbuf_new_from_stream_finish (res, &error);
  if (pixbuf == NULL)
    {
      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
        {
          g_warning ("Failed to load image: %s", error->message);
          remove_placeholder (BG_PICTURES_SOURCE (user_data), item);
        }

      g_error_free (error);
      goto out;
    }

  /* since we were not cancelled, we can now cast user_data
   * back to BgPicturesSource.
   */
  bg_source = BG_PICTURES_SOURCE (user_data);
  store = bg_source_get_liststore (BG_SOURCE (bg_source));
  uri = cc_background_item_get_uri (item);
  if (uri == NULL)
    uri = cc_background_item_get_source_url (item);

  /* Ignore screenshots */
  software = gdk_pixbuf_get_option (pixbuf, "tEXt::Software");
  if (software != NULL &&
      g_str_equal (software, "gnome-screenshot"))
    {
      g_debug ("Ignored URL '%s' as it's a screenshot from gnome-screenshot", uri);
      remove_placeholder (BG_PICTURES_SOURCE (user_data), item);
      goto out;
    }

  scale_factor = bg_source_get_scale_factor (BG_SOURCE (bg_source));
  surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL);
  cc_background_item_load (item, NULL);

  row_ref = g_object_get_data (G_OBJECT (item), "row-ref");
  if (row_ref == NULL)
    {
      /* insert the item into the liststore if it did not exist */
      gtk_list_store_insert_with_values (store, NULL, -1,
                                         0, surface,
                                         1, item,
                                         -1);
    }
  else
    {
      path = gtk_tree_row_reference_get_path (row_ref);
      if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
        {
          /* otherwise update the thumbnail */
          gtk_list_store_set (store, &iter,
                              0, surface,
                              -1);
        }
    }

  g_hash_table_insert (bg_source->priv->known_items,
                       bg_pictures_source_get_unique_filename (uri),
                       GINT_TO_POINTER (TRUE));


 out:
  g_clear_pointer (&surface, (GDestroyNotify) cairo_surface_destroy);
  g_clear_object (&pixbuf);
}
static void
bg_colors_source_add_color (BgColorsSource               *self,
                            GnomeDesktopThumbnailFactory *thumb_factory,
                            GtkListStore                 *store,
                            const char                   *color,
                            GtkTreeRowReference         **ret_row_ref)
{
  CcBackgroundItemFlags flags;
  CcBackgroundItem *item;
  GdkPixbuf *pixbuf;
  cairo_surface_t *surface;
  int scale_factor;
  int thumbnail_height, thumbnail_width;
  GtkTreeIter iter;

  thumbnail_height = bg_source_get_thumbnail_height (BG_SOURCE (self));
  thumbnail_width = bg_source_get_thumbnail_width (BG_SOURCE (self));

  item = cc_background_item_new (NULL);
  flags = CC_BACKGROUND_ITEM_HAS_PCOLOR |
          CC_BACKGROUND_ITEM_HAS_SCOLOR |
          CC_BACKGROUND_ITEM_HAS_SHADING |
          CC_BACKGROUND_ITEM_HAS_PLACEMENT |
          CC_BACKGROUND_ITEM_HAS_URI;
  /* It does have a URI, it's "none" */

  g_object_set (G_OBJECT (item),
                "uri", "file:///" DATADIR "/gnome-control-center/pixmaps/noise-texture-light.png",
                "primary-color", color,
                "secondary-color", color,
                "shading", G_DESKTOP_BACKGROUND_SHADING_SOLID,
                "placement", G_DESKTOP_BACKGROUND_STYLE_WALLPAPER,
                "flags", flags,
                NULL);
  cc_background_item_load (item, NULL);

  /* insert the item into the liststore */
  scale_factor = bg_source_get_scale_factor (BG_SOURCE (self));
  pixbuf = cc_background_item_get_thumbnail (item,
                                             thumb_factory,
                                             thumbnail_width, thumbnail_height,
                                             scale_factor);
  surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL);
  gtk_list_store_insert_with_values (store, &iter, 0,
                                     0, surface,
                                     1, item,
                                     -1);

  if (ret_row_ref)
    {
      GtkTreePath *path;

      path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
      *ret_row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), path);
      gtk_tree_path_free (path);
    }

  cairo_surface_destroy (surface);
  g_object_unref (pixbuf);
  g_object_unref (item);
}