From 10b2021f0a98f1575400aac2beffd8e3c47ecdd5 Mon Sep 17 00:00:00 2001 From: Victor Kareh Date: Tue, 1 May 2018 00:24:38 -0400 Subject: Convert launcher icons to cairo surfaces This improves support for HiDPI by loading properly scaled surfaces for launcher and drawer icons. It also Fixes the Show Desktop wncklet to show a surface icon. Other wncklets have their icons determined by libwnck, so they remain as pixbufs. Fixes mate-desktop/mate-desktop#314 --- mate-panel/button-widget.c | 153 ++++++++++++++++++++++++--------------------- mate-panel/button-widget.h | 2 +- mate-panel/launcher.c | 34 +++++----- mate-panel/panel-util.c | 15 +++-- mate-panel/panel-util.h | 2 +- mate-panel/xstuff.c | 17 +++-- mate-panel/xstuff.h | 2 +- 7 files changed, 124 insertions(+), 101 deletions(-) (limited to 'mate-panel') diff --git a/mate-panel/button-widget.c b/mate-panel/button-widget.c index 94d031f0..796e3179 100644 --- a/mate-panel/button-widget.c +++ b/mate-panel/button-widget.c @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include "button-widget.h" #include "panel-widget.h" @@ -22,8 +22,8 @@ struct _ButtonWidgetPrivate { GtkIconTheme *icon_theme; - GdkPixbuf *pixbuf; - GdkPixbuf *pixbuf_hc; + cairo_surface_t *surface; + cairo_surface_t *surface_hc; char *filename; @@ -38,7 +38,7 @@ struct _ButtonWidgetPrivate { }; static void button_widget_icon_theme_changed (ButtonWidget *button); -static void button_widget_reload_pixbuf (ButtonWidget *button); +static void button_widget_reload_surface (ButtonWidget *button); enum { PROP_0, @@ -54,9 +54,9 @@ enum { G_DEFINE_TYPE (ButtonWidget, button_widget, GTK_TYPE_BUTTON) -/* colorshift a pixbuf */ +/* colorshift a surface */ static void -do_colorshift (GdkPixbuf *dest, GdkPixbuf *src, int shift) +do_colorshift (cairo_surface_t *dest, cairo_surface_t *src, int shift) { gint i, j; gint width, height, has_alpha, srcrowstride, destrowstride; @@ -67,13 +67,13 @@ do_colorshift (GdkPixbuf *dest, GdkPixbuf *src, int shift) int val; guchar r,g,b; - has_alpha = gdk_pixbuf_get_has_alpha (src); - width = gdk_pixbuf_get_width (src); - height = gdk_pixbuf_get_height (src); - srcrowstride = gdk_pixbuf_get_rowstride (src); - destrowstride = gdk_pixbuf_get_rowstride (dest); - target_pixels = gdk_pixbuf_get_pixels (dest); - original_pixels = gdk_pixbuf_get_pixels (src); + has_alpha = cairo_surface_get_content (src) != CAIRO_CONTENT_COLOR; + width = cairo_image_surface_get_width (src); + height = cairo_image_surface_get_height (src); + srcrowstride = cairo_image_surface_get_stride (src); + destrowstride = cairo_image_surface_get_stride (dest); + original_pixels = cairo_image_surface_get_data (src); + target_pixels = cairo_image_surface_get_data (dest); for (i = 0; i < height; i++) { pixdest = target_pixels + i*destrowstride; @@ -94,20 +94,25 @@ do_colorshift (GdkPixbuf *dest, GdkPixbuf *src, int shift) } } -static GdkPixbuf * -make_hc_pixbuf (GdkPixbuf *pb) +static cairo_surface_t * +make_hc_surface (cairo_surface_t *surface) { - GdkPixbuf *new; - - if (!pb) + cairo_t *cr; + cairo_surface_t *new; + + if (!surface) return NULL; - new = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (pb), - gdk_pixbuf_get_has_alpha (pb), - gdk_pixbuf_get_bits_per_sample (pb), - gdk_pixbuf_get_width (pb), - gdk_pixbuf_get_height (pb)); - do_colorshift (new, pb, 30); + new = cairo_surface_create_similar (surface, + cairo_surface_get_content (surface), + cairo_image_surface_get_width (surface), + cairo_image_surface_get_height (surface)); + + do_colorshift (new, surface, 30); + + cr = cairo_create (new); + cairo_set_operator (cr, CAIRO_OPERATOR_DEST_IN); + cairo_mask_surface (cr, surface, 0, 0); return new; } @@ -128,7 +133,7 @@ button_widget_realize(GtkWidget *widget) widget, G_CONNECT_SWAPPED); - button_widget_reload_pixbuf (BUTTON_WIDGET (widget)); + button_widget_reload_surface (BUTTON_WIDGET (widget)); } static void @@ -142,49 +147,54 @@ button_widget_unrealize (GtkWidget *widget) } static void -button_widget_unset_pixbufs (ButtonWidget *button) +button_widget_unset_surfaces (ButtonWidget *button) { - if (button->priv->pixbuf) - g_object_unref (button->priv->pixbuf); - button->priv->pixbuf = NULL; + if (button->priv->surface) + cairo_surface_destroy (button->priv->surface); + button->priv->surface = NULL; - if (button->priv->pixbuf_hc) - g_object_unref (button->priv->pixbuf_hc); - button->priv->pixbuf_hc = NULL; + if (button->priv->surface_hc) + cairo_surface_destroy (button->priv->surface_hc); + button->priv->surface_hc = NULL; } static void -button_widget_reload_pixbuf (ButtonWidget *button) +button_widget_reload_surface (ButtonWidget *button) { - button_widget_unset_pixbufs (button); + button_widget_unset_surfaces (button); if (button->priv->size <= 1 || button->priv->icon_theme == NULL) return; if (button->priv->filename != NULL && button->priv->filename [0] != '\0') { + gint scale; char *error = NULL; - button->priv->pixbuf = + scale = gtk_widget_get_scale_factor (GTK_WIDGET (button)); + + button->priv->surface = panel_load_icon (button->priv->icon_theme, button->priv->filename, - button->priv->size, - button->priv->orientation & PANEL_VERTICAL_MASK ? button->priv->size : -1, - button->priv->orientation & PANEL_HORIZONTAL_MASK ? button->priv->size : -1, + button->priv->size * scale, + button->priv->orientation & PANEL_VERTICAL_MASK ? button->priv->size * scale : -1, + button->priv->orientation & PANEL_HORIZONTAL_MASK ? button->priv->size * scale: -1, &error); if (error) { //FIXME: this is not rendered at button->priv->size GtkIconTheme *icon_theme = gtk_icon_theme_get_default(); - button->priv->pixbuf = gtk_icon_theme_load_icon (icon_theme, + button->priv->surface = gtk_icon_theme_load_surface (icon_theme, "image-missing", GTK_ICON_SIZE_BUTTON, + scale, + NULL, GTK_ICON_LOOKUP_FORCE_SVG | GTK_ICON_LOOKUP_USE_BUILTIN, NULL); g_free (error); } } - button->priv->pixbuf_hc = make_hc_pixbuf (button->priv->pixbuf); + button->priv->surface_hc = make_hc_surface (button->priv->surface); gtk_widget_queue_resize (GTK_WIDGET (button)); } @@ -193,7 +203,7 @@ static void button_widget_icon_theme_changed (ButtonWidget *button) { if (button->priv->filename != NULL) - button_widget_reload_pixbuf (button); + button_widget_reload_surface (button); } static void @@ -201,7 +211,7 @@ button_widget_finalize (GObject *object) { ButtonWidget *button = (ButtonWidget *) object; - button_widget_unset_pixbufs (button); + button_widget_unset_surfaces (button); g_free (button->priv->filename); button->priv->filename = NULL; @@ -341,50 +351,47 @@ button_widget_draw (GtkWidget *widget, GtkStateFlags state_flags; int off; int x, y, w, h; - GdkPixbuf *pb = NULL; - + int scale; + g_return_val_if_fail (BUTTON_IS_WIDGET (widget), FALSE); button_widget = BUTTON_WIDGET (widget); - if (!button_widget->priv->pixbuf_hc && !button_widget->priv->pixbuf) + if (!button_widget->priv->surface_hc && !button_widget->priv->surface) return FALSE; state_flags = gtk_widget_get_state_flags (widget); width = gtk_widget_get_allocated_width (widget); height = gtk_widget_get_allocated_height (widget); + scale = gtk_widget_get_scale_factor (widget); /* offset for pressed buttons */ off = (button_widget->priv->activatable && (state_flags & GTK_STATE_FLAG_PRELIGHT) && (state_flags & GTK_STATE_FLAG_ACTIVE)) ? BUTTON_WIDGET_DISPLACEMENT * height / 48.0 : 0; - if (!button_widget->priv->activatable) { - pb = gdk_pixbuf_copy (button_widget->priv->pixbuf); - gdk_pixbuf_saturate_and_pixelate (button_widget->priv->pixbuf, - pb, - 0.8, - TRUE); - } else if (panel_global_config_get_highlight_when_over () && - (state_flags & GTK_STATE_FLAG_PRELIGHT || gtk_widget_has_focus (widget))) - pb = g_object_ref (button_widget->priv->pixbuf_hc); - else - pb = g_object_ref (button_widget->priv->pixbuf); + w = cairo_image_surface_get_width (button_widget->priv->surface) / scale; + h = cairo_image_surface_get_height (button_widget->priv->surface) / scale; + x = off + (width - w) / 2; + y = off + (height - h) / 2; - g_assert (pb != NULL); + cairo_save (cr); - w = gdk_pixbuf_get_width (pb); - h = gdk_pixbuf_get_height (pb); - x = off + (width - w)/2; - y = off + (height - h)/2; + if (!button_widget->priv->activatable) { + cairo_set_source_surface (cr, button_widget->priv->surface, x, y); + cairo_mask_surface (cr, button_widget->priv->surface, x, y); + cairo_set_operator (cr, CAIRO_OPERATOR_HSL_SATURATION); + cairo_set_source_rgba (cr, 0, 0, 0, 0.2); + } else if (panel_global_config_get_highlight_when_over () && + (state_flags & GTK_STATE_FLAG_PRELIGHT || gtk_widget_has_focus (widget))) { + cairo_set_source_surface (cr, button_widget->priv->surface_hc, x, y); + } else { + cairo_set_source_surface (cr, button_widget->priv->surface, x, y); + } - cairo_save (cr); - gdk_cairo_set_source_pixbuf (cr, pb, x, y); cairo_paint (cr); cairo_restore (cr); - g_object_unref (pb); - context = gtk_widget_get_style_context (widget); if (button_widget->priv->arrow) { @@ -494,7 +501,7 @@ button_widget_size_allocate (GtkWidget *widget, if (button_widget->priv->size != size) { button_widget->priv->size = size; - button_widget_reload_pixbuf (button_widget); + button_widget_reload_surface (button_widget); } } @@ -571,8 +578,8 @@ button_widget_init (ButtonWidget *button) button->priv = BUTTON_WIDGET_GET_PRIVATE (button); button->priv->icon_theme = NULL; - button->priv->pixbuf = NULL; - button->priv->pixbuf_hc = NULL; + button->priv->surface = NULL; + button->priv->surface_hc = NULL; button->priv->filename = NULL; @@ -724,7 +731,7 @@ button_widget_set_icon_name (ButtonWidget *button, g_free (button->priv->filename); button->priv->filename = g_strdup (icon_name); - button_widget_reload_pixbuf (button); + button_widget_reload_surface (button); g_object_notify (G_OBJECT (button), "icon-name"); } @@ -850,13 +857,13 @@ button_widget_get_icon_theme (ButtonWidget *button) return button->priv->icon_theme; } -GdkPixbuf * -button_widget_get_pixbuf (ButtonWidget *button) +cairo_surface_t * +button_widget_get_surface (ButtonWidget *button) { g_return_val_if_fail (BUTTON_IS_WIDGET (button), NULL); - if (!button->priv->pixbuf) + if (!button->priv->surface) return NULL; - return g_object_ref (button->priv->pixbuf); + return cairo_surface_reference (button->priv->surface); } diff --git a/mate-panel/button-widget.h b/mate-panel/button-widget.h index e9b87e6d..372c33b9 100644 --- a/mate-panel/button-widget.h +++ b/mate-panel/button-widget.h @@ -51,7 +51,7 @@ void button_widget_set_ignore_leave (ButtonWidget *button, gboolean ignore_leave); gboolean button_widget_get_ignore_leave (ButtonWidget *button); GtkIconTheme *button_widget_get_icon_theme (ButtonWidget *button); -GdkPixbuf *button_widget_get_pixbuf (ButtonWidget *button); +cairo_surface_t *button_widget_get_surface (ButtonWidget *button); #ifdef __cplusplus } diff --git a/mate-panel/launcher.c b/mate-panel/launcher.c index d8d65ad1..67746b06 100644 --- a/mate-panel/launcher.c +++ b/mate-panel/launcher.c @@ -184,15 +184,15 @@ drag_data_received_cb (GtkWidget *widget, GList *file_list; if (panel_global_config_get_enable_animations ()) { - GdkPixbuf *pixbuf; - pixbuf = button_widget_get_pixbuf (BUTTON_WIDGET (widget)); + cairo_surface_t *surface; + surface = button_widget_get_surface (BUTTON_WIDGET (widget)); xstuff_zoom_animate (widget, - pixbuf, + surface, button_widget_get_orientation (BUTTON_WIDGET (widget)), NULL); - g_object_unref (pixbuf); + cairo_surface_destroy (surface); } - + file_list = NULL; uris = g_uri_list_extract_uris ((const char *) gtk_selection_data_get_data (selection_data)); for (i = 0; uris[i]; i++) @@ -402,13 +402,13 @@ clicked_cb (Launcher *launcher, GtkWidget *widget) { if (panel_global_config_get_enable_animations ()) { - GdkPixbuf *pixbuf; - pixbuf = button_widget_get_pixbuf (BUTTON_WIDGET (widget)); + cairo_surface_t *surface; + surface = button_widget_get_surface (BUTTON_WIDGET (widget)); xstuff_zoom_animate (widget, - pixbuf, + surface, button_widget_get_orientation (BUTTON_WIDGET (widget)), NULL); - g_object_unref (pixbuf); + cairo_surface_destroy (surface); } launcher_launch (launcher, NULL); @@ -1157,7 +1157,7 @@ void panel_launcher_set_dnd_enabled (Launcher *launcher, gboolean dnd_enabled) { - GdkPixbuf *pixbuf; + cairo_surface_t *surface; if (dnd_enabled) { static GtkTargetEntry dnd_targets[] = { @@ -1170,16 +1170,20 @@ panel_launcher_set_dnd_enabled (Launcher *launcher, GDK_BUTTON1_MASK, dnd_targets, 2, GDK_ACTION_COPY | GDK_ACTION_MOVE); - //FIXME: this doesn't work since the pixbuf isn't loaded yet - pixbuf = button_widget_get_pixbuf (BUTTON_WIDGET (launcher->button)); - if (pixbuf) { + surface = button_widget_get_surface (BUTTON_WIDGET (launcher->button)); + if (surface) { + GdkPixbuf *pixbuf; + pixbuf = gdk_pixbuf_get_from_surface (surface, + 0, + 0, + cairo_image_surface_get_width (surface), + cairo_image_surface_get_height (surface)); gtk_drag_source_set_icon_pixbuf (launcher->button, pixbuf); g_object_unref (pixbuf); + cairo_surface_destroy (surface); } gtk_widget_set_has_window (launcher->button, FALSE); - - } else gtk_drag_source_unset (launcher->button); } diff --git a/mate-panel/panel-util.c b/mate-panel/panel-util.c index a958a761..f9832473 100644 --- a/mate-panel/panel-util.c +++ b/mate-panel/panel-util.c @@ -327,7 +327,7 @@ panel_find_icon (GtkIconTheme *icon_theme, return retval; } -GdkPixbuf * +cairo_surface_t * panel_load_icon (GtkIconTheme *icon_theme, const char *icon_name, int size, @@ -335,7 +335,8 @@ panel_load_icon (GtkIconTheme *icon_theme, int desired_height, char **error_msg) { - GdkPixbuf *retval; + GdkPixbuf *pixbuf; + cairo_surface_t *surface; char *file; GError *error; @@ -351,19 +352,25 @@ panel_load_icon (GtkIconTheme *icon_theme, } error = NULL; - retval = gdk_pixbuf_new_from_file_at_size (file, + pixbuf = gdk_pixbuf_new_from_file_at_scale (file, desired_width, desired_height, + TRUE, &error); if (error) { if (error_msg) *error_msg = g_strdup (error->message); g_error_free (error); + surface = NULL; + } + else { + surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 0, NULL); } g_free (file); + g_object_unref (pixbuf); - return retval; + return surface; } static char* panel_lock_screen_action_get_command(const char* action) diff --git a/mate-panel/panel-util.h b/mate-panel/panel-util.h index 21352970..8d9fb2ef 100644 --- a/mate-panel/panel-util.h +++ b/mate-panel/panel-util.h @@ -31,7 +31,7 @@ GIcon * panel_gicon_from_icon_name (const char *icon_name); char * panel_find_icon (GtkIconTheme *icon_theme, const char *icon_name, int size); -GdkPixbuf * panel_load_icon (GtkIconTheme *icon_theme, +cairo_surface_t *panel_load_icon (GtkIconTheme *icon_theme, const char *icon_name, int size, int desired_width, diff --git a/mate-panel/xstuff.c b/mate-panel/xstuff.c index 7db48acf..21d58825 100644 --- a/mate-panel/xstuff.c +++ b/mate-panel/xstuff.c @@ -328,7 +328,7 @@ draw_zoom_animation (GdkScreen *gscreen, void xstuff_zoom_animate (GtkWidget *widget, - GdkPixbuf *pixbuf, + cairo_surface_t *surface, PanelOrientation orientation, GdkRectangle *opt_rect) { @@ -353,12 +353,17 @@ xstuff_zoom_animate (GtkWidget *widget, gscreen = gtk_widget_get_screen (widget); - if (gdk_screen_is_composited (gscreen) && pixbuf) + if (gdk_screen_is_composited (gscreen) && surface) { + GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface (surface, + 0, 0, + cairo_image_surface_get_width (surface), + cairo_image_surface_get_height (surface)); draw_zoom_animation_composited (gscreen, - rect.x, rect.y, - rect.width, rect.height, - pixbuf, orientation); - else { + rect.x, rect.y, + rect.width, rect.height, + pixbuf, orientation); + g_object_unref (pixbuf); + } else { display = gdk_screen_get_display (gscreen); monitor = gdk_display_get_monitor_at_window (display, gtk_widget_get_window (widget)); diff --git a/mate-panel/xstuff.h b/mate-panel/xstuff.h index 507a1dd3..83af4645 100644 --- a/mate-panel/xstuff.h +++ b/mate-panel/xstuff.h @@ -5,7 +5,7 @@ #include void xstuff_zoom_animate (GtkWidget *widget, - GdkPixbuf *pixbuf, + cairo_surface_t *surface, PanelOrientation orientation, GdkRectangle *opt_src_rect); -- cgit v1.2.1