Commit 7f606870 authored by Debarshi Ray's avatar Debarshi Ray

background: Composite the emblems ourselves

We were assuming that setting stock-size would affect the emblems in
GEmblemedIcons, but not the icons themselves. This is a bit weird.
GtkCellRendererPixbuf:gicon is meant to work with
GtkCellRendererPixbuf:stock-size, and this was only working so far
because GTK_ICON_LOOKUP_FORCE_SIZE was not being used when loading
the icon.

Let's composite the emblems ourselves so that we don't have to depend
on this quirky interpretation of stock-size.

Unfortunately, we can not directly use the pixbufs because they are
unaware of the scale factor and GTK+ will scale them on HiDpi
displays. Since our pixbufs already have enough pixels to work well
with such devices, scaling them further will lead to giant, fuzzy
thumbnails. Hence, we use GtkCellRendererPixbuf:surface with the
scale factor codified in it.

https://bugzilla.gnome.org/show_bug.cgi?id=732375
parent b37d6ffd
......@@ -119,7 +119,7 @@ LIBGD_INIT([_view-common notification static])
PKG_CHECK_MODULES(LIBLANGUAGE, $COMMON_MODULES gnome-desktop-3.0 fontconfig)
PKG_CHECK_MODULES(LIBSHORTCUTS, $COMMON_MODULES x11)
PKG_CHECK_MODULES(SHELL, $COMMON_MODULES x11 polkit-gobject-1 >= $POLKIT_REQUIRED_VERSION)
PKG_CHECK_MODULES(BACKGROUND_PANEL, $COMMON_MODULES libxml-2.0 gnome-desktop-3.0
PKG_CHECK_MODULES(BACKGROUND_PANEL, $COMMON_MODULES cairo-gobject libxml-2.0 gnome-desktop-3.0
gdk-pixbuf-2.0 >= $GDKPIXBUF_REQUIRED_VERSION
goa-1.0 >= $GOA_REQUIRED_VERSION
grilo-0.2 >= $GRILO_REQUIRED_VERSION)
......
......@@ -24,6 +24,7 @@
#include "cc-background-item.h"
#include <cairo-gobject.h>
#include <glib/gi18n-lib.h>
#include <gdesktop-enums.h>
......@@ -76,6 +77,8 @@ bg_colors_source_constructed (GObject *object)
CcBackgroundItemFlags flags;
CcBackgroundItem *item;
GIcon *pixbuf;
cairo_surface_t *surface;
int scale_factor;
item = cc_background_item_new (NULL);
flags = CC_BACKGROUND_ITEM_HAS_PCOLOR |
......@@ -96,14 +99,18 @@ bg_colors_source_constructed (GObject *object)
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);
thumbnail_width, thumbnail_height,
scale_factor);
surface = gdk_cairo_surface_create_from_pixbuf (GDK_PIXBUF (pixbuf), scale_factor, NULL);
gtk_list_store_insert_with_values (store, NULL, 0,
0, pixbuf,
0, surface,
1, item,
-1);
cairo_surface_destroy (surface);
g_object_unref (pixbuf);
g_object_unref (item);
}
......
......@@ -27,6 +27,7 @@
#include "cc-background-item.h"
#include <string.h>
#include <cairo-gobject.h>
#include <gio/gio.h>
#include <grilo.h>
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
......@@ -150,6 +151,8 @@ picture_scaled (GObject *source_object,
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);
......@@ -183,6 +186,8 @@ picture_scaled (GObject *source_object,
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");
......@@ -190,7 +195,7 @@ picture_scaled (GObject *source_object,
{
/* insert the item into the liststore if it did not exist */
gtk_list_store_insert_with_values (store, NULL, -1,
0, pixbuf,
0, surface,
1, item,
-1);
}
......@@ -201,7 +206,7 @@ picture_scaled (GObject *source_object,
{
/* otherwise update the thumbnail */
gtk_list_store_set (store, &iter,
0, pixbuf,
0, surface,
-1);
}
}
......@@ -212,6 +217,7 @@ picture_scaled (GObject *source_object,
out:
g_clear_pointer (&surface, (GDestroyNotify) cairo_surface_destroy);
g_clear_object (&pixbuf);
}
......@@ -336,10 +342,12 @@ add_single_file (BgPicturesSource *bg_source,
GtkTreeIter iter;
GtkTreePath *path = NULL;
GtkTreeRowReference *row_ref;
cairo_surface_t *surface = NULL;
char *source_uri = NULL;
char *uri = NULL;
gboolean is_native;
gboolean retval = FALSE;
int scale_factor;
/* find png and jpeg files */
if (!content_type)
......@@ -395,11 +403,13 @@ add_single_file (BgPicturesSource *bg_source,
goto read_file;
}
scale_factor = bg_source_get_scale_factor (BG_SOURCE (bg_source));
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL);
store = bg_source_get_liststore (BG_SOURCE (bg_source));
/* insert the item into the liststore */
gtk_list_store_insert_with_values (store, &iter, -1,
0, pixbuf,
0, surface,
1, item,
-1);
......@@ -470,6 +480,7 @@ add_single_file (BgPicturesSource *bg_source,
out:
gtk_tree_path_free (path);
g_clear_pointer (&surface, (GDestroyNotify) cairo_surface_destroy);
g_clear_object (&pixbuf);
g_clear_object (&icon_info);
g_clear_object (&item);
......
......@@ -21,6 +21,8 @@
#include "bg-source.h"
#include "cc-background-item.h"
#include <cairo-gobject.h>
#define THUMBNAIL_WIDTH 256
#define THUMBNAIL_HEIGHT (THUMBNAIL_WIDTH * 3 / 4)
......@@ -155,7 +157,7 @@ bg_source_init (BgSource *self)
priv = self->priv = SOURCE_PRIVATE (self);
priv->store = gtk_list_store_new (3, G_TYPE_ICON, G_TYPE_OBJECT, G_TYPE_STRING);
priv->store = gtk_list_store_new (3, CAIRO_GOBJECT_TYPE_SURFACE, G_TYPE_OBJECT, G_TYPE_STRING);
}
GtkListStore*
......@@ -166,6 +168,14 @@ bg_source_get_liststore (BgSource *source)
return source->priv->store;
}
gint
bg_source_get_scale_factor (BgSource *source)
{
g_return_val_if_fail (BG_IS_SOURCE (source), 1);
return gtk_widget_get_scale_factor (source->priv->window);
}
gint
bg_source_get_thumbnail_height (BgSource *source)
{
......
......@@ -67,6 +67,8 @@ GType bg_source_get_type (void) G_GNUC_CONST;
GtkListStore* bg_source_get_liststore (BgSource *source);
gint bg_source_get_scale_factor (BgSource *source);
gint bg_source_get_thumbnail_height (BgSource *source);
gint bg_source_get_thumbnail_width (BgSource *source);
......
......@@ -25,6 +25,7 @@
#include "cc-background-item.h"
#include "cc-background-xml.h"
#include <cairo-gobject.h>
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
#include <gio/gio.h>
......@@ -49,7 +50,9 @@ load_wallpapers (gchar *key,
GtkTreeIter iter;
GIcon *pixbuf;
GtkListStore *store = bg_source_get_liststore (BG_SOURCE (source));
cairo_surface_t *surface = NULL;
gboolean deleted;
gint scale_factor;
gint thumbnail_height;
gint thumbnail_width;
......@@ -60,17 +63,24 @@ load_wallpapers (gchar *key,
gtk_list_store_append (store, &iter);
scale_factor = bg_source_get_scale_factor (BG_SOURCE (source));
thumbnail_height = bg_source_get_thumbnail_height (BG_SOURCE (source));
thumbnail_width = bg_source_get_thumbnail_width (BG_SOURCE (source));
pixbuf = cc_background_item_get_thumbnail (item, priv->thumb_factory,
thumbnail_width, thumbnail_height);
thumbnail_width, thumbnail_height,
scale_factor);
if (pixbuf == NULL)
goto out;
surface = gdk_cairo_surface_create_from_pixbuf (GDK_PIXBUF (pixbuf), scale_factor, NULL);
gtk_list_store_set (store, &iter,
0, pixbuf,
0, surface,
1, item,
2, cc_background_item_get_name (item),
-1);
out:
g_clear_pointer (&surface, (GDestroyNotify) cairo_surface_destroy);
if (pixbuf)
g_object_unref (pixbuf);
}
......
......@@ -413,18 +413,12 @@ cc_background_chooser_dialog_init (CcBackgroundChooserDialog *chooser)
g_signal_connect (priv->icon_view, "item-activated", G_CALLBACK (on_item_activated), chooser);
renderer = gtk_cell_renderer_pixbuf_new ();
/* set stock size to 32px so that emblems render at 16px. see:
* https://bugzilla.gnome.org/show_bug.cgi?id=682123#c4
*/
g_object_set (renderer,
"stock-size", GTK_ICON_SIZE_DND,
NULL);
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->icon_view),
renderer,
FALSE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->icon_view),
renderer,
"gicon", 0,
"surface", 0,
NULL);
gtk_dialog_add_button (GTK_DIALOG (chooser), _("_Cancel"), GTK_RESPONSE_CANCEL);
......
......@@ -25,6 +25,7 @@
#include <gtk/gtk.h>
#include <gio/gio.h>
#include <glib/gi18n-lib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <libgnome-desktop/gnome-bg.h>
#include <gdesktop-enums.h>
......@@ -52,6 +53,7 @@ struct CcBackgroundItemPrivate
guint64 modified;
/* internal */
GdkPixbuf *slideshow_emblem;
GnomeBG *bg;
char *mime_type;
int width;
......@@ -81,15 +83,63 @@ static void cc_background_item_finalize (GObject *object
G_DEFINE_TYPE (CcBackgroundItem, cc_background_item, G_TYPE_OBJECT)
static GEmblem *
get_slideshow_icon (void)
static GdkPixbuf *slideshow_emblem = NULL;
static GIcon *
get_emblemed_pixbuf (CcBackgroundItem *item, GdkPixbuf *pixbuf, gint scale_factor)
{
GIcon *themed;
GEmblem *emblem;
themed = g_themed_icon_new ("slideshow-emblem");
emblem = g_emblem_new_with_origin (themed, G_EMBLEM_ORIGIN_DEVICE);
g_object_unref (themed);
return emblem;
GIcon *icon = NULL;
GIcon *retval;
GtkIconInfo *icon_info = NULL;
int eh;
int ew;
int h;
int w;
int x;
int y;
retval = g_object_ref (pixbuf);
if (item->priv->slideshow_emblem == NULL) {
if (slideshow_emblem == NULL) {
GError *error = NULL;
GtkIconTheme *theme;
icon = g_themed_icon_new ("slideshow-emblem");
theme = gtk_icon_theme_get_default ();
icon_info = gtk_icon_theme_lookup_by_gicon_for_scale (theme,
icon,
16,
scale_factor,
GTK_ICON_LOOKUP_FORCE_SIZE |
GTK_ICON_LOOKUP_USE_BUILTIN);
slideshow_emblem = gtk_icon_info_load_icon (icon_info, &error);
if (slideshow_emblem == NULL) {
g_warning ("Failed to load slideshow emblem: %s", error->message);
g_error_free (error);
goto out;
}
g_object_add_weak_pointer (G_OBJECT (slideshow_emblem), (gpointer *) (&slideshow_emblem));
item->priv->slideshow_emblem = slideshow_emblem;
} else {
item->priv->slideshow_emblem = g_object_ref (slideshow_emblem);
}
}
eh = gdk_pixbuf_get_height (slideshow_emblem);
ew = gdk_pixbuf_get_width (slideshow_emblem);
h = gdk_pixbuf_get_height (pixbuf);
w = gdk_pixbuf_get_width (pixbuf);
x = w - ew;
y = h - eh;
gdk_pixbuf_composite (slideshow_emblem, pixbuf, x, y, ew, eh, x, y, 1.0, 1.0, GDK_INTERP_BILINEAR, 255);
out:
g_clear_object (&icon_info);
g_clear_object (&icon);
return retval;
}
static void
......@@ -174,6 +224,7 @@ cc_background_item_get_frame_thumbnail (CcBackgroundItem *item,
GnomeDesktopThumbnailFactory *thumbs,
int width,
int height,
int scale_factor,
int frame,
gboolean force_size)
{
......@@ -214,11 +265,7 @@ cc_background_item_get_frame_thumbnail (CcBackgroundItem *item,
if (pixbuf != NULL
&& frame != -2
&& gnome_bg_changes_with_time (item->priv->bg)) {
GEmblem *emblem;
emblem = get_slideshow_icon ();
icon = g_emblemed_icon_new (G_ICON (pixbuf), emblem);
g_object_unref (emblem);
icon = get_emblemed_pixbuf (item, pixbuf, scale_factor);
g_object_unref (pixbuf);
} else {
icon = G_ICON (pixbuf);
......@@ -241,9 +288,10 @@ GIcon *
cc_background_item_get_thumbnail (CcBackgroundItem *item,
GnomeDesktopThumbnailFactory *thumbs,
int width,
int height)
int height,
int scale_factor)
{
return cc_background_item_get_frame_thumbnail (item, thumbs, width, height, -1, FALSE);
return cc_background_item_get_frame_thumbnail (item, thumbs, width, height, scale_factor, -1, FALSE);
}
static void
......@@ -801,6 +849,8 @@ cc_background_item_finalize (GObject *object)
if (item->priv->bg != NULL)
g_object_unref (item->priv->bg);
g_clear_object (&item->priv->slideshow_emblem);
G_OBJECT_CLASS (cc_background_item_parent_class)->finalize (object);
}
......
......@@ -73,11 +73,13 @@ gboolean cc_background_item_changes_with_time (CcBackgroundItem
GIcon * cc_background_item_get_thumbnail (CcBackgroundItem *item,
GnomeDesktopThumbnailFactory *thumbs,
int width,
int height);
int height,
int scale_factor);
GIcon * cc_background_item_get_frame_thumbnail (CcBackgroundItem *item,
GnomeDesktopThumbnailFactory *thumbs,
int width,
int height,
int scale_factor,
int frame,
gboolean force_size);
......
......@@ -213,6 +213,7 @@ update_display_preview (CcBackgroundPanel *panel,
GtkAllocation allocation;
const gint preview_width = 309;
const gint preview_height = 168;
gint scale_factor;
GdkPixbuf *pixbuf;
GIcon *icon;
cairo_t *cr;
......@@ -222,10 +223,12 @@ update_display_preview (CcBackgroundPanel *panel,
if (!current_background)
return;
scale_factor = gtk_widget_get_scale_factor (widget);
icon = cc_background_item_get_frame_thumbnail (current_background,
priv->thumb_factory,
preview_width,
preview_height,
scale_factor,
-2, TRUE);
pixbuf = GDK_PIXBUF (icon);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment