[gtk+] GtkWindow: Use cairo_surface_t for icons
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] GtkWindow: Use cairo_surface_t for icons
- Date: Sun, 22 Oct 2017 21:03:45 +0000 (UTC)
commit aa873e77090f788e6f231237f729552e42a6edc8
Author: Alexander Larsson <alexl redhat com>
Date: Sun Oct 22 22:57:21 2017 +0200
GtkWindow: Use cairo_surface_t for icons
gtk/gtkheaderbar.c | 13 +---
gtk/gtkwindow.c | 179 ++++++++++++++++++++++++++++++++----------------
gtk/gtkwindow.h | 6 +-
gtk/gtkwindowprivate.h | 5 +-
4 files changed, 130 insertions(+), 73 deletions(-)
---
diff --git a/gtk/gtkheaderbar.c b/gtk/gtkheaderbar.c
index de25017..ba8786d 100644
--- a/gtk/gtkheaderbar.c
+++ b/gtk/gtkheaderbar.c
@@ -200,7 +200,7 @@ _gtk_header_bar_update_window_icon (GtkHeaderBar *bar,
GtkWindow *window)
{
GtkHeaderBarPrivate *priv = gtk_header_bar_get_instance_private (bar);
- GdkPixbuf *pixbuf;
+ cairo_surface_t *surface;
gint scale;
if (priv->titlebar_icon == NULL)
@@ -208,19 +208,14 @@ _gtk_header_bar_update_window_icon (GtkHeaderBar *bar,
scale = gtk_widget_get_scale_factor (priv->titlebar_icon);
if (GTK_IS_BUTTON (gtk_widget_get_parent (priv->titlebar_icon)))
- pixbuf = gtk_window_get_icon_for_size (window, scale * 16);
+ surface = gtk_window_get_icon_for_size (window, 16, scale);
else
- pixbuf = gtk_window_get_icon_for_size (window, scale * 20);
+ surface = gtk_window_get_icon_for_size (window, 20, scale);
- if (pixbuf)
+ if (surface)
{
- cairo_surface_t *surface;
-
- surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale, gtk_widget_get_window
(priv->titlebar_icon));
-
gtk_image_set_from_surface (GTK_IMAGE (priv->titlebar_icon), surface);
cairo_surface_destroy (surface);
- g_object_unref (pixbuf);
gtk_widget_show (priv->titlebar_icon);
return TRUE;
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index c5d9c17..57cec5d 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -24,6 +24,8 @@
#include "config.h"
+#include <cairo-gobject.h>
+
#include "gtkwindow.h"
#include <string.h>
@@ -927,7 +929,7 @@ gtk_window_class_init (GtkWindowClass *klass)
g_param_spec_object ("icon",
P_("Icon"),
P_("Icon for this window"),
- GDK_TYPE_PIXBUF,
+ CAIRO_GOBJECT_TYPE_SURFACE,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
/**
@@ -4415,10 +4417,11 @@ static GList *
icon_list_from_theme (GtkWindow *window,
const gchar *name)
{
+ GtkWindowPrivate *priv = window->priv;
GList *list;
GtkIconTheme *icon_theme;
- GdkPixbuf *icon;
+ cairo_surface_t *icon;
gint *sizes;
gint i;
@@ -4437,11 +4440,15 @@ icon_list_from_theme (GtkWindow *window,
* fixed size of 48.
*/
if (sizes[i] == -1)
- icon = gtk_icon_theme_load_icon (icon_theme, name,
- 48, 0, NULL);
+ icon = gtk_icon_theme_load_surface (icon_theme, name,
+ 48, priv->scale,
+ _gtk_widget_get_window (GTK_WIDGET (window)),
+ 0, NULL);
else
- icon = gtk_icon_theme_load_icon (icon_theme, name,
- sizes[i], 0, NULL);
+ icon = gtk_icon_theme_load_surface (icon_theme, name,
+ sizes[i], priv->scale,
+ _gtk_widget_get_window (GTK_WIDGET (window)),
+ 0, NULL);
if (icon)
list = g_list_append (list, icon);
}
@@ -4526,43 +4533,90 @@ gtk_window_realize_icon (GtkWindow *window)
}
}
-static GdkPixbuf *
-icon_from_list (GList *list,
- gint size)
+static cairo_surface_t *
+icon_from_list (GtkWindow *window,
+ GList *list,
+ gint size,
+ gint scale)
{
- GdkPixbuf *best;
- GdkPixbuf *pixbuf;
+ cairo_surface_t *best;
+ cairo_surface_t *surface;
GList *l;
best = NULL;
+ /* Look for exact match */
for (l = list; l; l = l->next)
{
- pixbuf = list->data;
- if (gdk_pixbuf_get_width (pixbuf) <= size)
- {
- best = g_object_ref (pixbuf);
+ surface = list->data;
+ double x_scale;
+
+ cairo_surface_get_device_scale (surface, &x_scale, NULL);
+
+ if (cairo_image_surface_get_width (surface) == size &&
+ x_scale == scale)
+ {
+ best = cairo_surface_reference (surface);
break;
- }
+ }
}
- if (best == NULL)
- best = gdk_pixbuf_scale_simple (GDK_PIXBUF (list->data), size, size, GDK_INTERP_BILINEAR);
+ if (best != NULL)
+ return best;
+
+ /* Ignore scale */
+ for (l = list; l; l = l->next)
+ {
+ surface = list->data;
+ double x_scale;
+
+ cairo_surface_get_device_scale (surface, &x_scale, NULL);
+
+ if (cairo_image_surface_get_width (surface) * x_scale <= size)
+ {
+ best = cairo_surface_reference (surface);
+ break;
+ }
+ }
+
+ if (best == NULL && list != NULL)
+ best = (cairo_surface_t *)list->data;
+
+
+ if (best)
+ {
+ cairo_t *cr;
+ surface =
+ gdk_window_create_similar_image_surface (_gtk_widget_get_window (GTK_WIDGET(window)),
+ CAIRO_FORMAT_ARGB32,
+ size, size, scale);
+ cr = cairo_create (surface);
+ cairo_set_source_surface (cr, best, 0, 0);
+ cairo_scale (cr,
+ size / cairo_image_surface_get_width (best),
+ size / cairo_image_surface_get_height (best));
+ cairo_paint (cr);
+ cairo_destroy (cr);
+ }
return best;
}
-static GdkPixbuf *
-icon_from_name (const gchar *name,
- gint size)
+static cairo_surface_t *
+icon_from_name (GtkWindow *window,
+ const gchar *name,
+ gint size,
+ gint scale)
{
- return gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
- name, size,
- GTK_ICON_LOOKUP_FORCE_SIZE, NULL);
+ return gtk_icon_theme_load_surface (gtk_icon_theme_get_default (),
+ name, size, scale,
+ _gtk_widget_get_window (GTK_WIDGET(window)),
+ GTK_ICON_LOOKUP_FORCE_SIZE, NULL);
}
-GdkPixbuf *
+cairo_surface_t *
gtk_window_get_icon_for_size (GtkWindow *window,
- gint size)
+ int size,
+ int scale)
{
GtkWindowPrivate *priv = window->priv;
GtkWindowIconInfo *info;
@@ -4571,24 +4625,24 @@ gtk_window_get_icon_for_size (GtkWindow *window,
info = ensure_icon_info (window);
if (info->icon_list != NULL)
- return icon_from_list (info->icon_list, size);
+ return icon_from_list (window, info->icon_list, size, scale);
name = gtk_window_get_icon_name (window);
if (name != NULL)
- return icon_from_name (name, size);
+ return icon_from_name (window, name, size, scale);
if (priv->transient_parent != NULL)
{
info = ensure_icon_info (priv->transient_parent);
if (info->icon_list)
- return icon_from_list (info->icon_list, size);
+ return icon_from_list (window, info->icon_list, size, scale);
}
if (default_icon_list != NULL)
- return icon_from_list (default_icon_list, size);
+ return icon_from_list (window, default_icon_list, size, scale);
if (default_icon_name != NULL)
- return icon_from_name (default_icon_name, size);
+ return icon_from_name (window, default_icon_name, size, scale);
return NULL;
}
@@ -4614,7 +4668,7 @@ gtk_window_unrealize_icon (GtkWindow *window)
/**
* gtk_window_set_icon_list:
* @window: a #GtkWindow
- * @list: (element-type GdkPixbuf): list of #GdkPixbuf
+ * @list: (element-type cairo_surface_t): list of image surfaces
*
* Sets up the icon representing a #GtkWindow. The icon is used when
* the window is minimized (also known as iconified). Some window
@@ -4683,7 +4737,7 @@ gtk_window_set_icon_list (GtkWindow *window,
* The list is copied, but the reference count on each
* member won’t be incremented.
*
- * Returns: (element-type GdkPixbuf) (transfer container): copy of window’s icon list
+ * Returns: (element-type cairo_surface_t) (transfer container): copy of window’s icon list
**/
GList*
gtk_window_get_icon_list (GtkWindow *window)
@@ -4727,12 +4781,12 @@ gtk_window_get_icon_list (GtkWindow *window)
**/
void
gtk_window_set_icon (GtkWindow *window,
- GdkPixbuf *icon)
+ cairo_surface_t *icon)
{
GList *list;
g_return_if_fail (GTK_IS_WINDOW (window));
- g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
+ g_return_if_fail (icon == NULL);
list = NULL;
@@ -4829,7 +4883,7 @@ gtk_window_get_icon_name (GtkWindow *window)
*
* Returns: (transfer none): icon for window
**/
-GdkPixbuf*
+cairo_surface_t *
gtk_window_get_icon (GtkWindow *window)
{
GtkWindowIconInfo *info;
@@ -4838,19 +4892,21 @@ gtk_window_get_icon (GtkWindow *window)
info = get_icon_info (window);
if (info && info->icon_list)
- return GDK_PIXBUF (info->icon_list->data);
+ return (cairo_surface_t *) (info->icon_list->data);
else
return NULL;
}
-/* Load pixbuf, printing warning on failure if error == NULL
+/* Load surface, printing warning on failure if error == NULL
*/
-static GdkPixbuf *
-load_pixbuf_verbosely (const char *filename,
- GError **err)
+static cairo_surface_t *
+load_surface_verbosely (GdkWindow *window,
+ const char *filename,
+ GError **err)
{
GError *local_err = NULL;
GdkPixbuf *pixbuf;
+ cairo_surface_t *surface = NULL;
pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
@@ -4865,8 +4921,13 @@ load_pixbuf_verbosely (const char *filename,
g_error_free (local_err);
}
}
+ else
+ {
+ surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, window);
+ g_object_unref (pixbuf);
+ }
- return pixbuf;
+ return surface;
}
/**
@@ -4879,7 +4940,7 @@ load_pixbuf_verbosely (const char *filename,
* Warns on failure if @err is %NULL.
*
* This function is equivalent to calling gtk_window_set_icon()
- * with a pixbuf created by loading the image from @filename.
+ * with a surface created by loading the image from @filename.
*
* Returns: %TRUE if setting the icon succeeded.
*
@@ -4890,12 +4951,12 @@ gtk_window_set_icon_from_file (GtkWindow *window,
const gchar *filename,
GError **err)
{
- GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
+ cairo_surface_t *surface = load_surface_verbosely (_gtk_widget_get_window (GTK_WIDGET (window)), filename,
err);
- if (pixbuf)
+ if (surface)
{
- gtk_window_set_icon (window, pixbuf);
- g_object_unref (pixbuf);
+ gtk_window_set_icon (window, surface);
+ cairo_surface_destroy (surface);
return TRUE;
}
@@ -4905,7 +4966,7 @@ gtk_window_set_icon_from_file (GtkWindow *window,
/**
* gtk_window_set_default_icon_list:
- * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
+ * @list: (element-type cairo_surface_t) (transfer container): a list of #cairo_surface_t image surfaces
*
* Sets an icon list to be used as fallback for windows that haven't
* had gtk_window_set_icon_list() called on them to set up a
@@ -4928,9 +4989,9 @@ gtk_window_set_default_icon_list (GList *list)
default_icon_serial++;
g_list_foreach (list,
- (GFunc) g_object_ref, NULL);
+ (GFunc) cairo_surface_reference, NULL);
- g_list_free_full (default_icon_list, g_object_unref);
+ g_list_free_full (default_icon_list, (GDestroyNotify)cairo_surface_destroy);
default_icon_list = g_list_copy (list);
@@ -4960,16 +5021,16 @@ gtk_window_set_default_icon_list (GList *list)
* @icon: the icon
*
* Sets an icon to be used as fallback for windows that haven't
- * had gtk_window_set_icon() called on them from a pixbuf.
+ * had gtk_window_set_icon() called on them from a surface.
*
* Since: 2.4
**/
void
-gtk_window_set_default_icon (GdkPixbuf *icon)
+gtk_window_set_default_icon (cairo_surface_t *icon)
{
GList *list;
- g_return_if_fail (GDK_IS_PIXBUF (icon));
+ g_return_if_fail (cairo_surface_get_type (icon) == CAIRO_SURFACE_TYPE_IMAGE);
list = g_list_prepend (NULL, icon);
gtk_window_set_default_icon_list (list);
@@ -5059,12 +5120,12 @@ gboolean
gtk_window_set_default_icon_from_file (const gchar *filename,
GError **err)
{
- GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
+ cairo_surface_t *surface = load_surface_verbosely (NULL, filename, err);
- if (pixbuf)
+ if (surface)
{
- gtk_window_set_default_icon (pixbuf);
- g_object_unref (pixbuf);
+ gtk_window_set_default_icon (surface);
+ cairo_surface_destroy (surface);
return TRUE;
}
@@ -5077,10 +5138,10 @@ gtk_window_set_default_icon_from_file (const gchar *filename,
*
* Gets the value set by gtk_window_set_default_icon_list().
* The list is a copy and should be freed with g_list_free(),
- * but the pixbufs in the list have not had their reference count
+ * but the surfaces in the list have not had their reference count
* incremented.
*
- * Returns: (element-type GdkPixbuf) (transfer container): copy of default icon list
+ * Returns: (element-type cairo_surface_t) (transfer container): copy of default icon list
**/
GList*
gtk_window_get_default_icon_list (void)
diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h
index 0f247e0..05e86d2 100644
--- a/gtk/gtkwindow.h
+++ b/gtk/gtkwindow.h
@@ -277,7 +277,7 @@ GDK_AVAILABLE_IN_ALL
GList* gtk_window_get_icon_list (GtkWindow *window);
GDK_AVAILABLE_IN_ALL
void gtk_window_set_icon (GtkWindow *window,
- GdkPixbuf *icon);
+ cairo_surface_t *icon);
GDK_AVAILABLE_IN_ALL
void gtk_window_set_icon_name (GtkWindow *window,
const gchar *name);
@@ -286,7 +286,7 @@ gboolean gtk_window_set_icon_from_file (GtkWindow *window,
const gchar *filename,
GError **err);
GDK_AVAILABLE_IN_ALL
-GdkPixbuf* gtk_window_get_icon (GtkWindow *window);
+cairo_surface_t * gtk_window_get_icon (GtkWindow *window);
GDK_AVAILABLE_IN_ALL
const gchar * gtk_window_get_icon_name (GtkWindow *window);
GDK_AVAILABLE_IN_ALL
@@ -294,7 +294,7 @@ void gtk_window_set_default_icon_list (GList *list);
GDK_AVAILABLE_IN_ALL
GList* gtk_window_get_default_icon_list (void);
GDK_AVAILABLE_IN_ALL
-void gtk_window_set_default_icon (GdkPixbuf *icon);
+void gtk_window_set_default_icon (cairo_surface_t *icon);
GDK_AVAILABLE_IN_ALL
void gtk_window_set_default_icon_name (const gchar *name);
GDK_AVAILABLE_IN_ALL
diff --git a/gtk/gtkwindowprivate.h b/gtk/gtkwindowprivate.h
index 7c37ff3..fc6bde7 100644
--- a/gtk/gtkwindowprivate.h
+++ b/gtk/gtkwindowprivate.h
@@ -110,8 +110,9 @@ GtkWidget * _gtk_window_get_popover_parent (GtkWindow *window,
gboolean _gtk_window_is_popover_widget (GtkWindow *window,
GtkWidget *popover);
-GdkPixbuf *gtk_window_get_icon_for_size (GtkWindow *window,
- gint size);
+cairo_surface_t *gtk_window_get_icon_for_size (GtkWindow *window,
+ int size,
+ int scale);
void gtk_window_set_use_subsurface (GtkWindow *window,
gboolean use_subsurface);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]