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
This commit is contained in:
parent
b37d6ffd90
commit
7f606870a3
10 changed files with 121 additions and 32 deletions
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue