[gtk+] GtkWindow/GdkWindow: Finish converting icons to surfaces



commit d3fc937b4ddad6462bfca6402ce0a186f98d4908
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Oct 23 13:43:50 2017 +0200

    GtkWindow/GdkWindow: Finish converting icons to surfaces
    
    There were some parts left, for instance gdk_window_set_icon_list.

 gdk/broadway/gdkwindow-broadway.c |    2 +-
 gdk/gdkwindow.c                   |    8 +-
 gdk/gdkwindow.h                   |    2 +-
 gdk/mir/gdkmirwindowimpl.c        |    2 +-
 gdk/quartz/gdkwindow-quartz.c     |    2 +-
 gdk/wayland/gdkwindow-wayland.c   |    2 +-
 gdk/win32/gdkwindow-win32.c       |   47 +++++++++------
 gdk/x11/gdkwindow-x11.c           |  115 +++++++++++++++++++-----------------
 gtk/gtkwindow.c                   |    6 +-
 tests/testgtk.c                   |    8 ++-
 10 files changed, 107 insertions(+), 87 deletions(-)
---
diff --git a/gdk/broadway/gdkwindow-broadway.c b/gdk/broadway/gdkwindow-broadway.c
index 44bc9ec..d66dd47 100644
--- a/gdk/broadway/gdkwindow-broadway.c
+++ b/gdk/broadway/gdkwindow-broadway.c
@@ -791,7 +791,7 @@ gdk_broadway_window_set_focus_on_map (GdkWindow *window,
 
 static void
 gdk_broadway_window_set_icon_list (GdkWindow *window,
-                                  GList     *pixbufs)
+                                  GList     *surfaces)
 {
 }
 
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 6aad9e8..7e1a079 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -6643,8 +6643,8 @@ gdk_window_get_event_compression (GdkWindow *window)
 /**
  * gdk_window_set_icon_list:
  * @window: The #GdkWindow toplevel window to set the icon of.
- * @pixbufs: (transfer none) (element-type GdkPixbuf):
- *     A list of pixbufs, of different sizes.
+ * @surfaces: (transfer none) (element-type cairo_surface_t):
+ *     A list of image surfaces, of different sizes.
  *
  * Sets a list of icons for the window. One of these will be used
  * to represent the window when it has been iconified. The icon is
@@ -6658,9 +6658,9 @@ gdk_window_get_event_compression (GdkWindow *window)
  */
 void
 gdk_window_set_icon_list (GdkWindow *window,
-                         GList     *pixbufs)
+                          GList     *surfaces)
 {
-  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_icon_list (window, pixbufs);
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_icon_list (window, surfaces);
 }
 
 /**
diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h
index 261762f..72156e1 100644
--- a/gdk/gdkwindow.h
+++ b/gdk/gdkwindow.h
@@ -728,7 +728,7 @@ GdkEventMask  gdk_window_get_source_events (GdkWindow      *window,
 
 GDK_AVAILABLE_IN_ALL
 void          gdk_window_set_icon_list   (GdkWindow       *window,
-                                         GList           *pixbufs);
+                                         GList           *surfaces);
 GDK_AVAILABLE_IN_ALL
 void         gdk_window_set_icon_name   (GdkWindow       *window, 
                                          const gchar     *name);
diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c
index e92c85e..2e5669f 100644
--- a/gdk/mir/gdkmirwindowimpl.c
+++ b/gdk/mir/gdkmirwindowimpl.c
@@ -1528,7 +1528,7 @@ gdk_mir_window_impl_set_focus_on_map (GdkWindow *window,
 
 static void
 gdk_mir_window_impl_set_icon_list (GdkWindow *window,
-                                   GList     *pixbufs)
+                                   GList     *surface)
 {
   // ??
 }
diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c
index d7b2f04..387b38c 100644
--- a/gdk/quartz/gdkwindow-quartz.c
+++ b/gdk/quartz/gdkwindow-quartz.c
@@ -2126,7 +2126,7 @@ gdk_quartz_window_begin_move_drag (GdkWindow *window,
 
 static void
 gdk_quartz_window_set_icon_list (GdkWindow *window,
-                                 GList     *pixbufs)
+                                 GList     *surfaces)
 {
   /* FIXME: Implement */
 }
diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c
index 1697dcd..bb15eb1 100644
--- a/gdk/wayland/gdkwindow-wayland.c
+++ b/gdk/wayland/gdkwindow-wayland.c
@@ -3215,7 +3215,7 @@ gdk_wayland_window_set_focus_on_map (GdkWindow *window,
 
 static void
 gdk_wayland_window_set_icon_list (GdkWindow *window,
-                                  GList     *pixbufs)
+                                  GList     *surfaces)
 {
 }
 
diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c
index 6d8f078..f0ba27f 100644
--- a/gdk/win32/gdkwindow-win32.c
+++ b/gdk/win32/gdkwindow-win32.c
@@ -2315,9 +2315,10 @@ gdk_win32_window_set_focus_on_map (GdkWindow *window,
 
 static void
 gdk_win32_window_set_icon_list (GdkWindow *window,
-                         GList     *pixbufs)
+                                GList     *surfaces)
 {
-  GdkPixbuf *pixbuf, *big_pixbuf, *small_pixbuf;
+  cairo_surface_t *surface, *big_surface, *small_surface;
+  GdkPixbuf *big_pixbuf, *small_pixbuf;
   gint big_diff, small_diff;
   gint big_w, big_h, small_w, small_h;
   gint w, h;
@@ -2339,40 +2340,48 @@ gdk_win32_window_set_icon_list (GdkWindow *window,
   small_h = GetSystemMetrics (SM_CYSMICON);
 
   /* find closest sized icons in the list */
-  big_pixbuf = NULL;
-  small_pixbuf = NULL;
+  big_surface = NULL;
+  small_surface = NULL;
   big_diff = 0;
   small_diff = 0;
-  while (pixbufs)
+  while (surfaces)
     {
-      pixbuf = (GdkPixbuf*) pixbufs->data;
-      w = gdk_pixbuf_get_width (pixbuf);
-      h = gdk_pixbuf_get_height (pixbuf);
+      surface = (GdkPixbuf*) surfaces->data;
+      w = cairo_image_surface_get_width (surface);
+      h = cairo_image_surface_get_height (surface);
 
       dw = ABS (w - big_w);
       dh = ABS (h - big_h);
       diff = dw*dw + dh*dh;
-      if (big_pixbuf == NULL || diff < big_diff)
-       {
-         big_pixbuf = pixbuf;
-         big_diff = diff;
-       }
+      if (big_surface == NULL || diff < big_diff)
+        {
+          big_surface = surface;
+          big_diff = diff;
+        }
 
       dw = ABS (w - small_w);
       dh = ABS (h - small_h);
       diff = dw*dw + dh*dh;
-      if (small_pixbuf == NULL || diff < small_diff)
-       {
-         small_pixbuf = pixbuf;
-         small_diff = diff;
-       }
+      if (small_surface == NULL || diff < small_diff)
+        {
+          small_surface = surface;
+          small_diff = diff;
+        }
 
-      pixbufs = pixbufs->next;
+      surfaces = surfaces->next;
     }
 
   /* Create the icons */
+  big_pixbuf = gdk_pixbuf_get_from_surface (big_surface, 0, 0,
+                                            cairo_image_surface_get_width (big_surface)
+                                            cairo_image_surface_get_height (big_surface));
   big_hicon = _gdk_win32_pixbuf_to_hicon (big_pixbuf);
+  g_object_unref (big_pixbuf);
+  small_pixbuf = gdk_pixbuf_get_from_surface (small_surface, 0, 0,
+                                              cairo_image_surface_get_width (small_surface)
+                                              cairo_image_surface_get_height (small_surface));
   small_hicon = _gdk_win32_pixbuf_to_hicon (small_pixbuf);
+  g_object_unref (small_pixbuf);
 
   /* Set the icons */
   SendMessageW (GDK_WINDOW_HWND (window), WM_SETICON, ICON_BIG,
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index 3d3d305..ad27a45 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -3145,10 +3145,10 @@ gdk_window_update_icon (GdkWindow *window,
                         GList     *icon_list)
 {
   GdkToplevelX11 *toplevel;
-  GdkPixbuf *best_icon;
+  cairo_surface_t *best_icon;
   GList *tmp_list;
   int best_size;
-  
+
   toplevel = _gdk_x11_window_get_toplevel (window);
 
   if (toplevel->icon_pixmap != NULL)
@@ -3156,31 +3156,31 @@ gdk_window_update_icon (GdkWindow *window,
       cairo_surface_destroy (toplevel->icon_pixmap);
       toplevel->icon_pixmap = NULL;
     }
-  
+
   if (toplevel->icon_mask != NULL)
     {
       cairo_surface_destroy (toplevel->icon_mask);
       toplevel->icon_mask = NULL;
     }
-  
+
 #define IDEAL_SIZE 48
-  
+
   best_size = G_MAXINT;
   best_icon = NULL;
   for (tmp_list = icon_list; tmp_list; tmp_list = tmp_list->next)
     {
-      GdkPixbuf *pixbuf = tmp_list->data;
+      cairo_surface_t *surface = tmp_list->data;
       int this;
-  
+
       /* average width and height - if someone passes in a rectangular
        * icon they deserve what they get.
        */
-      this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
+      this = cairo_image_surface_get_width (surface) + cairo_image_surface_get_height (surface);
       this /= 2;
-  
+
       if (best_icon == NULL)
         {
-          best_icon = pixbuf;
+          best_icon = surface;
           best_size = this;
         }
       else
@@ -3192,7 +3192,7 @@ gdk_window_update_icon (GdkWindow *window,
               (ABS (best_size - IDEAL_SIZE) <
                ABS (this - IDEAL_SIZE)))
             {
-              best_icon = pixbuf;
+              best_icon = surface;
               best_size = this;
             }
         }
@@ -3200,8 +3200,8 @@ gdk_window_update_icon (GdkWindow *window,
 
   if (best_icon)
     {
-      int width = gdk_pixbuf_get_width (best_icon);
-      int height = gdk_pixbuf_get_height (best_icon);
+      int width = cairo_image_surface_get_width (best_icon);
+      int height = cairo_image_surface_get_height (best_icon);
       cairo_t *cr;
 
       toplevel->icon_pixmap = gdk_x11_window_create_pixmap_surface (window,
@@ -3210,8 +3210,8 @@ gdk_window_update_icon (GdkWindow *window,
 
       cr = cairo_create (toplevel->icon_pixmap);
       cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-      gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
-      if (gdk_pixbuf_get_has_alpha (best_icon))
+      cairo_set_source_surface (cr, best_icon, 0, 0);
+      if (cairo_surface_get_content (best_icon) == CAIRO_CONTENT_COLOR_ALPHA)
         {
           /* Saturate the image, so it has bilevel alpha */
           cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
@@ -3223,14 +3223,14 @@ gdk_window_update_icon (GdkWindow *window,
       cairo_paint (cr);
       cairo_destroy (cr);
 
-      if (gdk_pixbuf_get_has_alpha (best_icon))
+      if (cairo_surface_get_content (best_icon) == CAIRO_CONTENT_COLOR_ALPHA)
         {
           toplevel->icon_mask = _gdk_x11_window_create_bitmap_surface (window,
                                                                        width,
                                                                        height);
 
           cr = cairo_create (toplevel->icon_mask);
-          gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
+          cairo_set_source_surface (cr, best_icon, 0, 0);
           cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
           cairo_paint (cr);
           cairo_destroy (cr);
@@ -3242,84 +3242,91 @@ gdk_window_update_icon (GdkWindow *window,
 
 static void
 gdk_x11_window_set_icon_list (GdkWindow *window,
-                             GList     *pixbufs)
+                             GList     *surfaces)
 {
   gulong *data;
   guchar *pixels;
   gulong *p;
   gint size;
   GList *l;
-  GdkPixbuf *pixbuf;
+  cairo_surface_t *surface;
   gint width, height, stride;
   gint x, y;
-  gint n_channels;
   GdkDisplay *display;
   gint n;
-  
+  cairo_format_t format;
+
   if (GDK_WINDOW_DESTROYED (window) ||
       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
     return;
 
   display = gdk_window_get_display (window);
-  
-  l = pixbufs;
+
   size = 0;
   n = 0;
-  while (l)
+  for (l = surfaces; l != NULL; l = l->next)
     {
-      pixbuf = l->data;
-      g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
+      surface = l->data;
+
+      width = cairo_image_surface_get_width (surface);
+      height = cairo_image_surface_get_height (surface);
+      format = cairo_image_surface_get_format (surface);
+
+      if (format != CAIRO_FORMAT_ARGB32 && format != CAIRO_FORMAT_RGB24)
+        continue;
 
-      width = gdk_pixbuf_get_width (pixbuf);
-      height = gdk_pixbuf_get_height (pixbuf);
-      
       /* silently ignore overlarge icons */
       if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
-       break;
-     
+        break;
+
       n++;
       size += 2 + width * height;
-      
-      l = l->next;
     }
 
   data = g_malloc (size * sizeof (gulong));
 
-  l = pixbufs;
   p = data;
-  while (l && n > 0)
+  for (l = surfaces; l != NULL && n > 0; l = l->next)
     {
-      pixbuf = l->data;
-      
-      width = gdk_pixbuf_get_width (pixbuf);
-      height = gdk_pixbuf_get_height (pixbuf);
-      stride = gdk_pixbuf_get_rowstride (pixbuf);
-      n_channels = gdk_pixbuf_get_n_channels (pixbuf);
-      
+      surface = l->data;
+
+      width = cairo_image_surface_get_width (surface);
+      height = cairo_image_surface_get_height (surface);
+      stride = cairo_image_surface_get_stride (surface);
+      format = cairo_image_surface_get_format (surface);
+
+      if (format != CAIRO_FORMAT_ARGB32 && format != CAIRO_FORMAT_RGB24)
+        continue;
+
       *p++ = width;
       *p++ = height;
 
-      pixels = gdk_pixbuf_get_pixels (pixbuf);
+      pixels = cairo_image_surface_get_data (surface);
 
       for (y = 0; y < height; y++)
        {
          for (x = 0; x < width; x++)
            {
              guchar r, g, b, a;
-             
-             r = pixels[y*stride + x*n_channels + 0];
-             g = pixels[y*stride + x*n_channels + 1];
-             b = pixels[y*stride + x*n_channels + 2];
-             if (n_channels >= 4)
-               a = pixels[y*stride + x*n_channels + 3];
-             else
-               a = 255;
-             
+              a = 255;
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+              if (format == CAIRO_FORMAT_ARGB32)
+                a = pixels[y*stride + x*4 + 3];
+              r = pixels[y*stride + x*4 + 2];
+              g = pixels[y*stride + x*4 + 1];
+              b = pixels[y*stride + x*4 + 0];
+#else
+              if (format == CAIRO_FORMAT_ARGB32)
+                a = pixels[y*stride + x*4 + 0];
+              r = pixels[y*stride + x*4 + 1];
+              g = pixels[y*stride + x*4 + 2];
+              b = pixels[y*stride + x*4 + 3];
+#endif
+
              *p++ = a << 24 | r << 16 | g << 8 | b ;
            }
        }
 
-      l = l->next;
       n--;
     }
 
@@ -3341,7 +3348,7 @@ gdk_x11_window_set_icon_list (GdkWindow *window,
   
   g_free (data);
 
-  gdk_window_update_icon (window, pixbufs);
+  gdk_window_update_icon (window, surfaces);
 }
 
 static gboolean
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 31d1444..d0d1e45 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -4588,7 +4588,7 @@ icon_from_list (GtkWindow *window,
       surface =
        gdk_window_create_similar_image_surface (_gtk_widget_get_window (GTK_WIDGET(window)),
                                                 CAIRO_FORMAT_ARGB32,
-                                                size, size, scale);
+                                                size * scale, size * scale, scale);
       cr = cairo_create (surface);
       cairo_set_source_surface (cr, best, 0, 0);
       cairo_scale (cr,
@@ -4710,9 +4710,9 @@ gtk_window_set_icon_list (GtkWindow  *window,
     return;
 
   g_list_foreach (list,
-                  (GFunc) g_object_ref, NULL);
+                  (GFunc) cairo_surface_reference, NULL);
 
-  g_list_free_full (info->icon_list, g_object_unref);
+  g_list_free_full (info->icon_list, (GDestroyNotify)cairo_surface_destroy);
 
   info->icon_list = g_list_copy (list);
 
diff --git a/tests/testgtk.c b/tests/testgtk.c
index 86effa2..4bcc9ac 100644
--- a/tests/testgtk.c
+++ b/tests/testgtk.c
@@ -5721,6 +5721,7 @@ create_wmhints (GtkWidget *widget)
   GtkWidget *box2;
   GdkWindow *gdk_window;
   GdkPixbuf *pixbuf;
+  cairo_surface_t *surface;
   GList *list;
 
   if (!window)
@@ -5741,11 +5742,14 @@ create_wmhints (GtkWidget *widget)
       gdk_window = gtk_widget_get_window (window);
 
       pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) openfile);
-      list = g_list_prepend (NULL, pixbuf);
+      surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
 
-      gdk_window_set_icon_list (gdk_window, list);
+      list = g_list_prepend (NULL, surface);
+
+      gtk_window_set_icon_list (GTK_WINDOW (window), list);
 
       g_list_free (list);
+      cairo_surface_destroy (surface);
       g_object_unref (pixbuf);
 
       gdk_window_set_icon_name (gdk_window, "WMHints Test Icon");


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