[mutter] x11: Change the iconcache / window icons to being cairo surfaces



commit af7f51b992b20da543312fa9fdf1dcef39704b37
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Wed Dec 31 20:39:36 2014 -0800

    x11: Change the iconcache / window icons to being cairo surfaces
    
    This simplifies the drawing codepath and makes us able to delete
    a bunch of GdkPixbuf manipulation.

 src/core/core.c           |    2 +-
 src/core/window-private.h |   10 +-
 src/core/window.c         |   36 +++--
 src/ui/frames.c           |    2 +-
 src/ui/theme-private.h    |    2 +-
 src/ui/theme.c            |   21 ++--
 src/ui/ui.c               |   50 ------
 src/ui/ui.h               |    7 -
 src/x11/iconcache.c       |  384 ++++++++++++---------------------------------
 src/x11/iconcache.h       |   22 ++--
 src/x11/window-x11.c      |    6 +-
 11 files changed, 155 insertions(+), 387 deletions(-)
---
diff --git a/src/core/core.c b/src/core/core.c
index 17572dc..62315e8 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -120,7 +120,7 @@ meta_core_get (Display *xdisplay,
           *((MetaFrameType*)answer) = meta_window_get_frame_type (window);
           break;
         case META_CORE_GET_MINI_ICON:
-          *((GdkPixbuf**)answer) = window->mini_icon;
+          *((cairo_surface_t**)answer) = window->mini_icon;
           break;
         case META_CORE_GET_FRAME_RECT:
           meta_window_get_frame_rect (window, ((MetaRectangle*)answer));
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 9d4849a..1ae29fc 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -106,8 +106,8 @@ struct _MetaWindow
   char *desc; /* used in debug spew */
   char *title;
 
-  GdkPixbuf *icon;
-  GdkPixbuf *mini_icon;
+  cairo_surface_t *icon;
+  cairo_surface_t *mini_icon;
 
   MetaWindowType type;
 
@@ -479,9 +479,9 @@ struct _MetaWindowClass
   void (*get_default_skip_hints) (MetaWindow *window,
                                   gboolean   *skip_taskbar_out,
                                   gboolean   *skip_pager_out);
-  gboolean (*update_icon)        (MetaWindow  *window,
-                                  GdkPixbuf  **icon,
-                                  GdkPixbuf  **mini_icon);
+  gboolean (*update_icon)        (MetaWindow       *window,
+                                  cairo_surface_t **icon,
+                                  cairo_surface_t **mini_icon);
 };
 
 /* These differ from window->has_foo_func in that they consider
diff --git a/src/core/window.c b/src/core/window.c
index bbb2536..eca1994 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -244,9 +244,9 @@ meta_window_real_get_default_skip_hints (MetaWindow *window,
 }
 
 static gboolean
-meta_window_real_update_icon (MetaWindow  *window,
-                              GdkPixbuf  **icon,
-                              GdkPixbuf  **mini_icon)
+meta_window_real_update_icon (MetaWindow       *window,
+                              cairo_surface_t **icon,
+                              cairo_surface_t **mini_icon)
 {
   *icon = NULL;
   *mini_icon = NULL;
@@ -259,10 +259,10 @@ meta_window_finalize (GObject *object)
   MetaWindow *window = META_WINDOW (object);
 
   if (window->icon)
-    g_object_unref (G_OBJECT (window->icon));
+    cairo_surface_destroy (window->icon);
 
   if (window->mini_icon)
-    g_object_unref (G_OBJECT (window->mini_icon));
+    cairo_surface_destroy (window->mini_icon);
 
   if (window->frame_bounds)
     cairo_region_destroy (window->frame_bounds);
@@ -4890,10 +4890,11 @@ redraw_icon (MetaWindow *window)
     meta_ui_queue_frame_draw (window->screen->ui, window->frame->xwindow);
 }
 
-static GdkPixbuf *
+static cairo_surface_t *
 load_default_window_icon (int size)
 {
   GtkIconTheme *theme = gtk_icon_theme_get_default ();
+  GdkPixbuf *pixbuf;
   const char *icon_name;
 
   if (gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME))
@@ -4901,13 +4902,14 @@ load_default_window_icon (int size)
   else
     icon_name = "image-missing";
 
-  return gtk_icon_theme_load_icon (theme, icon_name, size, 0, NULL);
+  pixbuf = gtk_icon_theme_load_icon (theme, icon_name, size, 0, NULL);
+  return gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
 }
 
-static GdkPixbuf *
+static cairo_surface_t *
 get_default_window_icon (void)
 {
-  static GdkPixbuf *default_icon = NULL;
+  static cairo_surface_t *default_icon = NULL;
 
   if (default_icon == NULL)
     {
@@ -4915,13 +4917,13 @@ get_default_window_icon (void)
       g_assert (default_icon);
     }
 
-  return g_object_ref (default_icon);
+  return cairo_surface_reference (default_icon);
 }
 
-static GdkPixbuf *
+static cairo_surface_t *
 get_default_mini_icon (void)
 {
-  static GdkPixbuf *default_icon = NULL;
+  static cairo_surface_t *default_icon = NULL;
 
   if (default_icon == NULL)
     {
@@ -4929,7 +4931,7 @@ get_default_mini_icon (void)
       g_assert (default_icon);
     }
 
-  return g_object_ref (default_icon);
+  return cairo_surface_reference (default_icon);
 }
 
 static void
@@ -4937,8 +4939,8 @@ meta_window_update_icon_now (MetaWindow *window,
                              gboolean    force)
 {
   gboolean changed;
-  GdkPixbuf *icon = NULL;
-  GdkPixbuf *mini_icon;
+  cairo_surface_t *icon = NULL;
+  cairo_surface_t *mini_icon;
 
   g_return_if_fail (!window->override_redirect);
 
@@ -4947,14 +4949,14 @@ meta_window_update_icon_now (MetaWindow *window,
   if (changed || force)
     {
       if (window->icon)
-        g_object_unref (window->icon);
+        cairo_surface_destroy (window->icon);
       if (icon)
         window->icon = icon;
       else
         window->icon = get_default_window_icon ();
 
       if (window->mini_icon)
-        g_object_unref (window->mini_icon);
+        cairo_surface_destroy (window->mini_icon);
       if (mini_icon)
         window->mini_icon = mini_icon;
       else
diff --git a/src/ui/frames.c b/src/ui/frames.c
index c648391..31c4b39 100644
--- a/src/ui/frames.c
+++ b/src/ui/frames.c
@@ -1673,7 +1673,7 @@ meta_frames_paint (MetaFrames   *frames,
 {
   MetaFrameFlags flags;
   MetaFrameType type;
-  GdkPixbuf *mini_icon;
+  cairo_surface_t *mini_icon;
   int w, h;
   MetaButtonState button_states[META_BUTTON_TYPE_LAST];
   int i;
diff --git a/src/ui/theme-private.h b/src/ui/theme-private.h
index 22608b9..e364983 100644
--- a/src/ui/theme-private.h
+++ b/src/ui/theme-private.h
@@ -265,7 +265,7 @@ void meta_theme_draw_frame (MetaTheme              *theme,
                             int                     text_height,
                             const MetaButtonLayout *button_layout,
                             MetaButtonState         button_states[META_BUTTON_TYPE_LAST],
-                            GdkPixbuf              *mini_icon);
+                            cairo_surface_t        *mini_icon);
 
 void meta_theme_get_frame_borders (MetaTheme         *theme,
                                    MetaStyleInfo     *style_info,
diff --git a/src/ui/theme.c b/src/ui/theme.c
index 0ccdd9b..03b168f 100644
--- a/src/ui/theme.c
+++ b/src/ui/theme.c
@@ -725,7 +725,7 @@ meta_frame_layout_draw_with_style (MetaFrameLayout         *layout,
                                    PangoLayout             *title_layout,
                                    MetaFrameFlags           flags,
                                    MetaButtonState          button_states[META_BUTTON_TYPE_LAST],
-                                   GdkPixbuf               *mini_icon)
+                                   cairo_surface_t         *mini_icon)
 {
   GtkStyleContext *style;
   GtkStateFlags state;
@@ -810,7 +810,7 @@ meta_frame_layout_draw_with_style (MetaFrameLayout         *layout,
 
       if (gdk_cairo_get_clip_rectangle (cr, NULL))
         {
-          GdkPixbuf *pixbuf = NULL;
+          cairo_surface_t *surface = NULL;
           const char *icon_name = NULL;
 
           gtk_render_background (style, cr,
@@ -838,7 +838,7 @@ meta_frame_layout_draw_with_style (MetaFrameLayout         *layout,
                icon_name = "open-menu-symbolic";
                break;
             case META_BUTTON_TYPE_APPMENU:
-               pixbuf = g_object_ref (mini_icon);
+               surface = cairo_surface_reference (mini_icon);
                break;
             default:
                icon_name = NULL;
@@ -849,18 +849,20 @@ meta_frame_layout_draw_with_style (MetaFrameLayout         *layout,
             {
               GtkIconTheme *theme = gtk_icon_theme_get_default ();
               GtkIconInfo *info;
+              GdkPixbuf *pixbuf;
 
               info = gtk_icon_theme_lookup_icon (theme, icon_name, layout->icon_size, 0);
               pixbuf = gtk_icon_info_load_symbolic_for_context (info, style, NULL, NULL);
+              surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
             }
 
-          if (pixbuf)
+          if (surface)
             {
               float width, height;
               int x, y;
 
-              width = gdk_pixbuf_get_width (pixbuf);
-              height = gdk_pixbuf_get_height (pixbuf);
+              width = cairo_image_surface_get_width (surface);
+              height = cairo_image_surface_get_height (surface);
               x = button_rect.x + (button_rect.width - width) / 2;
               y = button_rect.y + (button_rect.height - height) / 2;
 
@@ -868,11 +870,10 @@ meta_frame_layout_draw_with_style (MetaFrameLayout         *layout,
               cairo_scale (cr,
                            width / layout->icon_size,
                            height / layout->icon_size);
-
-              gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+              cairo_set_source_surface (cr, surface, 0, 0);
               cairo_paint (cr);
 
-              g_object_unref (pixbuf);
+              cairo_surface_destroy (surface);
             }
         }
       cairo_restore (cr);
@@ -1180,7 +1181,7 @@ meta_theme_draw_frame (MetaTheme              *theme,
                        int                     text_height,
                        const MetaButtonLayout *button_layout,
                        MetaButtonState         button_states[META_BUTTON_TYPE_LAST],
-                       GdkPixbuf              *mini_icon)
+                       cairo_surface_t        *mini_icon)
 {
   MetaFrameGeometry fgeom;
   MetaFrameLayout *layout;
diff --git a/src/ui/ui.c b/src/ui/ui.c
index 1f1f4c7..4f0a7f7 100644
--- a/src/ui/ui.c
+++ b/src/ui/ui.c
@@ -500,56 +500,6 @@ meta_ui_set_frame_title (MetaUI     *ui,
   meta_frames_set_title (ui->frames, xwindow, title);
 }
 
-GdkPixbuf*
-meta_gdk_pixbuf_get_from_pixmap (Pixmap       xpixmap,
-                                 int          src_x,
-                                 int          src_y,
-                                 int          width,
-                                 int          height)
-{
-  cairo_surface_t *surface;
-  Display *display;
-  Window root_return;
-  int x_ret, y_ret;
-  unsigned int w_ret, h_ret, bw_ret, depth_ret;
-  XWindowAttributes attrs;
-  GdkPixbuf *retval;
-
-  display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
-
-  if (!XGetGeometry (display, xpixmap, &root_return,
-                     &x_ret, &y_ret, &w_ret, &h_ret, &bw_ret, &depth_ret))
-    return NULL;
-
-  if (depth_ret == 1)
-    {
-      surface = cairo_xlib_surface_create_for_bitmap (display,
-                                                      xpixmap,
-                                                      GDK_SCREEN_XSCREEN (gdk_screen_get_default ()),
-                                                      w_ret,
-                                                      h_ret);
-    }
-  else
-    {
-      if (!XGetWindowAttributes (display, root_return, &attrs))
-        return NULL;
-
-      surface = cairo_xlib_surface_create (display,
-                                           xpixmap,
-                                           attrs.visual,
-                                           w_ret, h_ret);
-    }
-
-  retval = gdk_pixbuf_get_from_surface (surface,
-                                        src_x,
-                                        src_y,
-                                        width,
-                                        height);
-  cairo_surface_destroy (surface);
-
-  return retval;
-}
-
 gboolean
 meta_ui_window_should_not_cause_focus (Display *xdisplay,
                                        Window   xwindow)
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 8e460fe..5d77537 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -101,13 +101,6 @@ void meta_ui_repaint_frame (MetaUI *ui,
                             Window xwindow);
 
 
-/* FIXME these lack a display arg */
-GdkPixbuf* meta_gdk_pixbuf_get_from_pixmap (Pixmap       xpixmap,
-                                            int          src_x,
-                                            int          src_y,
-                                            int          width,
-                                            int          height);
-
 gboolean  meta_ui_window_should_not_cause_focus (Display *xdisplay,
                                                  Window   xwindow);
 
diff --git a/src/x11/iconcache.c b/src/x11/iconcache.c
index 45a8679..932af7b 100644
--- a/src/x11/iconcache.c
+++ b/src/x11/iconcache.c
@@ -19,14 +19,16 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include "config.h"
+
 #include "iconcache.h"
-#include "ui.h"
+
 #include <meta/errors.h>
 
-#include <X11/Xatom.h>
+#include <cairo.h>
+#include <cairo-xlib.h>
 
-/* The icon-reading code is also in libwnck, please sync bugfixes */
+#include <X11/Xatom.h>
 
 static gboolean
 find_largest_sizes (gulong *data,
@@ -156,51 +158,40 @@ find_best_size (gulong  *data,
     return FALSE;
 }
 
-static void
-argbdata_to_pixdata (gulong *argb_data, int len, guchar **pixdata)
+static cairo_surface_t *
+argbdata_to_surface (gulong *argb_data, int w, int h)
 {
-  guchar *p;
-  int i;
+  cairo_surface_t *surface;
+  int y, x, stride;
+  uint8_t *data;
 
-  *pixdata = g_new (guchar, len * 4);
-  p = *pixdata;
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h);
+  stride = cairo_image_surface_get_stride (surface);
+  data = cairo_image_surface_get_data (surface);
 
   /* One could speed this up a lot. */
-  i = 0;
-  while (i < len)
+  for (y = 0; y < h; y++)
     {
-      guint argb;
-      guint rgba;
-
-      argb = argb_data[i];
-      rgba = (argb << 8) | (argb >> 24);
-
-      *p = rgba >> 24;
-      ++p;
-      *p = (rgba >> 16) & 0xff;
-      ++p;
-      *p = (rgba >> 8) & 0xff;
-      ++p;
-      *p = rgba & 0xff;
-      ++p;
-
-      ++i;
+      for (x = 0; x < w; x++)
+        {
+          uint32_t *p = (uint32_t *) &data[y * stride + x];
+          gulong *d = &argb_data[y * w + x];
+          *p = *d;
+        }
     }
+
+  return surface;
 }
 
 static gboolean
-read_rgb_icon (MetaDisplay   *display,
-               Window         xwindow,
-               int            ideal_width,
-               int            ideal_height,
-               int            ideal_mini_width,
-               int            ideal_mini_height,
-               int           *width,
-               int           *height,
-               guchar       **pixdata,
-               int           *mini_width,
-               int           *mini_height,
-               guchar       **mini_pixdata)
+read_rgb_icon (MetaDisplay      *display,
+               Window            xwindow,
+               int               ideal_width,
+               int               ideal_height,
+               int               ideal_mini_width,
+               int               ideal_mini_height,
+               cairo_surface_t **icon,
+               cairo_surface_t **mini_icon)
 {
   Atom type;
   int format;
@@ -253,14 +244,8 @@ read_rgb_icon (MetaDisplay   *display,
       return FALSE;
     }
 
-  *width = w;
-  *height = h;
-
-  *mini_width = mini_w;
-  *mini_height = mini_h;
-
-  argbdata_to_pixdata (best, w * h, pixdata);
-  argbdata_to_pixdata (best_mini, mini_w * mini_h, mini_pixdata);
+  *icon = argbdata_to_surface (best, w, h);
+  *mini_icon = argbdata_to_surface (best_mini, mini_w, mini_h);
 
   XFree (data);
 
@@ -268,12 +253,6 @@ read_rgb_icon (MetaDisplay   *display,
 }
 
 static void
-free_pixels (guchar *pixels, gpointer data)
-{
-  g_free (pixels);
-}
-
-static void
 get_pixmap_geometry (MetaDisplay *display,
                      Pixmap       pixmap,
                      int         *w,
@@ -305,96 +284,44 @@ get_pixmap_geometry (MetaDisplay *display,
     *d = depth;
 }
 
-static void
-apply_foreground_background (GdkPixbuf *pixbuf)
+static cairo_surface_t *
+surface_from_pixmap (Display *xdisplay, Pixmap xpixmap,
+                     int width, int height)
 {
-  int w, h;
-  int i, j;
-  guchar *pixels;
-  int stride;
-
-  w = gdk_pixbuf_get_width (pixbuf);
-  h = gdk_pixbuf_get_height (pixbuf);
-  pixels = gdk_pixbuf_get_pixels (pixbuf);
-  stride = gdk_pixbuf_get_rowstride (pixbuf);
+  cairo_surface_t *surface;
+  Window root_return;
+  int x_ret, y_ret;
+  unsigned int w_ret, h_ret, bw_ret, depth_ret;
+  XWindowAttributes attrs;
+
+  if (!XGetGeometry (xdisplay, xpixmap, &root_return,
+                     &x_ret, &y_ret, &w_ret, &h_ret, &bw_ret, &depth_ret))
+    return NULL;
 
-  i = 0;
-  while (i < h)
+  if (depth_ret == 1)
     {
-      j = 0;
-      while (j < w)
-        {
-          guchar *p = pixels + i * stride + j * 4;
-          if (p[3] == 0)
-            p[0] = p[1] = p[2] =  0xff; /* white background */
-          else
-            p[0] = p[1] = p[2] = 0x00; /* black foreground */
-
-          p[3] = 0xff;
-
-          ++j;
-        }
-
-      ++i;
+      surface = cairo_xlib_surface_create_for_bitmap (xdisplay, xpixmap, DefaultScreenOfDisplay (xdisplay),
+                                                      w_ret, h_ret);
     }
-}
-
-static GdkPixbuf*
-apply_mask (GdkPixbuf *pixbuf,
-            GdkPixbuf *mask)
-{
-  int w, h;
-  int i, j;
-  GdkPixbuf *with_alpha;
-  guchar *src;
-  guchar *dest;
-  int src_stride;
-  int dest_stride;
-
-  w = MIN (gdk_pixbuf_get_width (mask), gdk_pixbuf_get_width (pixbuf));
-  h = MIN (gdk_pixbuf_get_height (mask), gdk_pixbuf_get_height (pixbuf));
-
-  with_alpha = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
-
-  dest = gdk_pixbuf_get_pixels (with_alpha);
-  src = gdk_pixbuf_get_pixels (mask);
-
-  dest_stride = gdk_pixbuf_get_rowstride (with_alpha);
-  src_stride = gdk_pixbuf_get_rowstride (mask);
-
-  i = 0;
-  while (i < h)
+  else
     {
-      j = 0;
-      while (j < w)
-        {
-          guchar *s = src + i * src_stride + j * 4;
-          guchar *d = dest + i * dest_stride + j * 4;
-
-          d[3] = s[3];
+      if (!XGetWindowAttributes (xdisplay, root_return, &attrs))
+        return NULL;
 
-          ++j;
-        }
-
-      ++i;
+      surface = cairo_xlib_surface_create (xdisplay, xpixmap, attrs.visual, w_ret, h_ret);
     }
 
-  return with_alpha;
+  return surface;
 }
 
 static gboolean
-try_pixmap_and_mask (MetaDisplay *display,
-                     Pixmap       src_pixmap,
-                     Pixmap       src_mask,
-                     GdkPixbuf  **iconp,
-                     int          ideal_width,
-                     int          ideal_height,
-                     GdkPixbuf  **mini_iconp,
-                     int          ideal_mini_width,
-                     int          ideal_mini_height)
+try_pixmap_and_mask (MetaDisplay      *display,
+                     Pixmap            src_pixmap,
+                     Pixmap            src_mask,
+                     cairo_surface_t **iconp)
 {
-  GdkPixbuf *unscaled = NULL;
-  GdkPixbuf *mask = NULL;
+  Display *xdisplay = display->xdisplay;
+  cairo_surface_t *icon, *mask = NULL;
   int w, h, d;
 
   if (src_pixmap == None)
@@ -403,72 +330,48 @@ try_pixmap_and_mask (MetaDisplay *display,
   meta_error_trap_push (display);
 
   get_pixmap_geometry (display, src_pixmap, &w, &h, &d);
+  icon = surface_from_pixmap (xdisplay, src_pixmap, w, h);
 
-  unscaled = meta_gdk_pixbuf_get_from_pixmap (src_pixmap,
-                                              0, 0,
-                                              w, h);
-
-  /* A depth 1 pixmap has 0 background, and 1 foreground, but
-   * cairo and meta_gdk_pixbuf_get_from_pixmap consider it
-   * to be 0 transparent, 1 opaque */
-  if (d == 1)
-    apply_foreground_background (unscaled);
-
-  if (unscaled && src_mask != None)
+  if (icon && src_mask != None)
     {
       get_pixmap_geometry (display, src_mask, &w, &h, &d);
+
       if (d == 1)
-        mask = meta_gdk_pixbuf_get_from_pixmap (src_mask,
-                                                0, 0,
-                                                w, h);
+        mask = surface_from_pixmap (xdisplay, src_mask, w, h);
     }
 
   meta_error_trap_pop (display);
 
-  if (mask)
+  if (icon && mask)
     {
-      GdkPixbuf *masked;
+      cairo_surface_t *masked;
+      cairo_t *cr;
+
+      masked = cairo_surface_create_similar_image (icon,
+                                                   CAIRO_FORMAT_ARGB32,
+                                                   cairo_image_surface_get_width (icon),
+                                                   cairo_image_surface_get_height (icon));
+      cr = cairo_create (masked);
+
+      cairo_set_source_surface (cr, icon, 0, 0);
+      cairo_mask_surface (cr, mask, 0, 0);
 
-      masked = apply_mask (unscaled, mask);
-      g_object_unref (G_OBJECT (unscaled));
-      unscaled = masked;
+      cairo_destroy (cr);
+      cairo_surface_destroy (icon);
+      cairo_surface_destroy (mask);
 
-      g_object_unref (G_OBJECT (mask));
-      mask = NULL;
+      icon = masked;
     }
 
-  if (unscaled)
+  if (icon)
     {
-      *iconp =
-        gdk_pixbuf_scale_simple (unscaled,
-                                 ideal_width > 0 ? ideal_width :
-                                 gdk_pixbuf_get_width (unscaled),
-                                 ideal_height > 0 ? ideal_height :
-                                 gdk_pixbuf_get_height (unscaled),
-                                 GDK_INTERP_BILINEAR);
-      *mini_iconp =
-        gdk_pixbuf_scale_simple (unscaled,
-                                 ideal_mini_width > 0 ? ideal_mini_width :
-                                 gdk_pixbuf_get_width (unscaled),
-                                 ideal_mini_height > 0 ? ideal_mini_height :
-                                 gdk_pixbuf_get_height (unscaled),
-                                 GDK_INTERP_BILINEAR);
-
-      g_object_unref (G_OBJECT (unscaled));
-
-      if (*iconp && *mini_iconp)
-        return TRUE;
-      else
-        {
-          if (*iconp)
-            g_object_unref (G_OBJECT (*iconp));
-          if (*mini_iconp)
-            g_object_unref (G_OBJECT (*mini_iconp));
-          return FALSE;
-        }
+      *iconp = icon;
+      return TRUE;
     }
   else
-    return FALSE;
+    {
+      return FALSE;
+    }
 }
 
 static void
@@ -562,74 +465,18 @@ meta_icon_cache_get_icon_invalidated (MetaIconCache *icon_cache)
     return FALSE;
 }
 
-static GdkPixbuf*
-scaled_from_pixdata (guchar *pixdata,
-                     int     w,
-                     int     h,
-                     int     new_w,
-                     int     new_h)
-{
-  GdkPixbuf *src;
-  GdkPixbuf *dest;
-
-  src = gdk_pixbuf_new_from_data (pixdata,
-                                  GDK_COLORSPACE_RGB,
-                                  TRUE,
-                                  8,
-                                  w, h, w * 4,
-                                  free_pixels,
-                                  NULL);
-
-  if (src == NULL)
-    return NULL;
-
-  if (w != h)
-    {
-      GdkPixbuf *tmp;
-      int size;
-
-      size = MAX (w, h);
-
-      tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, size, size);
-
-      if (tmp)
-       {
-         gdk_pixbuf_fill (tmp, 0);
-         gdk_pixbuf_copy_area (src, 0, 0, w, h,
-                               tmp,
-                               (size - w) / 2, (size - h) / 2);
-
-         g_object_unref (src);
-         src = tmp;
-       }
-    }
-
-  if (w != new_w || h != new_h)
-    {
-      dest = gdk_pixbuf_scale_simple (src, new_w, new_h, GDK_INTERP_BILINEAR);
-
-      g_object_unref (G_OBJECT (src));
-    }
-  else
-    {
-      dest = src;
-    }
-
-  return dest;
-}
-
 gboolean
-meta_read_icons (MetaScreen     *screen,
-                 Window          xwindow,
-                 MetaIconCache  *icon_cache,
-                 Pixmap          wm_hints_pixmap,
-                 Pixmap          wm_hints_mask,
-                 GdkPixbuf     **iconp,
-                 int             ideal_width,
-                 int             ideal_height,
-                 GdkPixbuf     **mini_iconp,
-                 int             ideal_mini_width,
-                 int             ideal_mini_height)
+meta_read_icons (MetaScreen       *screen,
+                 Window            xwindow,
+                 MetaIconCache    *icon_cache,
+                 Pixmap            wm_hints_pixmap,
+                 Pixmap            wm_hints_mask,
+                 cairo_surface_t **iconp,
+                 int               ideal_width,
+                 int               ideal_height,
+                 cairo_surface_t **mini_iconp,
+                 int               ideal_mini_width,
+                 int               ideal_mini_height)
 {
   /* Return value is whether the icon changed */
 
@@ -653,37 +500,15 @@ meta_read_icons (MetaScreen     *screen,
   if (icon_cache->origin <= USING_NET_WM_ICON &&
       icon_cache->net_wm_icon_dirty)
     {
-      guchar *pixdata;
-      int w, h;
-      guchar *mini_pixdata;
-      int mini_w, mini_h;
-
       icon_cache->net_wm_icon_dirty = FALSE;
 
       if (read_rgb_icon (screen->display, xwindow,
                          ideal_width, ideal_height,
                          ideal_mini_width, ideal_mini_height,
-                         &w, &h, &pixdata,
-                         &mini_w, &mini_h, &mini_pixdata))
+                         iconp, mini_iconp))
         {
-          *iconp = scaled_from_pixdata (pixdata, w, h,
-                                        ideal_width, ideal_height);
-
-          *mini_iconp = scaled_from_pixdata (mini_pixdata, mini_w, mini_h,
-                                             ideal_mini_width, ideal_mini_height);
-
-          if (*iconp && *mini_iconp)
-            {
-              icon_cache->origin = USING_NET_WM_ICON;
-              return TRUE;
-            }
-          else
-            {
-              if (*iconp)
-                g_object_unref (G_OBJECT (*iconp));
-              if (*mini_iconp)
-                g_object_unref (G_OBJECT (*mini_iconp));
-            }
+          icon_cache->origin = USING_NET_WM_ICON;
+          return TRUE;
         }
     }
 
@@ -706,11 +531,9 @@ meta_read_icons (MetaScreen     *screen,
            mask != icon_cache->prev_mask) &&
           pixmap != None)
         {
-          if (try_pixmap_and_mask (screen->display,
-                                   pixmap, mask,
-                                   iconp, ideal_width, ideal_height,
-                                   mini_iconp, ideal_mini_width, ideal_mini_height))
+          if (try_pixmap_and_mask (screen->display, pixmap, mask, iconp))
             {
+              *mini_iconp = cairo_surface_reference (*iconp);
               icon_cache->prev_pixmap = pixmap;
               icon_cache->prev_mask = mask;
               icon_cache->origin = USING_WM_HINTS;
@@ -733,10 +556,9 @@ meta_read_icons (MetaScreen     *screen,
            mask != icon_cache->prev_mask) &&
           pixmap != None)
         {
-          if (try_pixmap_and_mask (screen->display, pixmap, mask,
-                                   iconp, ideal_width, ideal_height,
-                                   mini_iconp, ideal_mini_width, ideal_mini_height))
+          if (try_pixmap_and_mask (screen->display, pixmap, mask, iconp))
             {
+              *mini_iconp = cairo_surface_reference (*iconp);
               icon_cache->prev_pixmap = pixmap;
               icon_cache->prev_mask = mask;
               icon_cache->origin = USING_KWM_WIN_ICON;
diff --git a/src/x11/iconcache.h b/src/x11/iconcache.h
index 814fef5..f5ba406 100644
--- a/src/x11/iconcache.h
+++ b/src/x11/iconcache.h
@@ -56,17 +56,17 @@ void           meta_icon_cache_property_changed     (MetaIconCache *icon_cache,
                                                      Atom           atom);
 gboolean       meta_icon_cache_get_icon_invalidated (MetaIconCache *icon_cache);
 
-gboolean meta_read_icons         (MetaScreen     *screen,
-                                  Window          xwindow,
-                                  MetaIconCache  *icon_cache,
-                                  Pixmap          wm_hints_pixmap,
-                                  Pixmap          wm_hints_mask,
-                                  GdkPixbuf     **iconp,
-                                  int             ideal_width,
-                                  int             ideal_height,
-                                  GdkPixbuf     **mini_iconp,
-                                  int             ideal_mini_width,
-                                  int             ideal_mini_height);
+gboolean meta_read_icons         (MetaScreen       *screen,
+                                  Window            xwindow,
+                                  MetaIconCache    *icon_cache,
+                                  Pixmap            wm_hints_pixmap,
+                                  Pixmap            wm_hints_mask,
+                                  cairo_surface_t **iconp,
+                                  int               ideal_width,
+                                  int               ideal_height,
+                                  cairo_surface_t **mini_iconp,
+                                  int               ideal_mini_width,
+                                  int               ideal_mini_height);
 
 #endif
 
diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
index fefef3b..5a1f619 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -1459,9 +1459,9 @@ meta_window_x11_get_default_skip_hints (MetaWindow *window,
 }
 
 static gboolean
-meta_window_x11_update_icon (MetaWindow  *window,
-                             GdkPixbuf  **icon,
-                             GdkPixbuf  **mini_icon)
+meta_window_x11_update_icon (MetaWindow       *window,
+                             cairo_surface_t **icon,
+                             cairo_surface_t **mini_icon)
 {
   MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
   MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]