diff --git a/gdk/broadway/gdkwindow-broadway.c b/gdk/broadway/gdkwindow-broadway.c index 44bc9ec15a..d66dd47925 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 6aad9e8625..7e1a079333 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 261762f0fa..72156e18ea 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 e92c85ec8e..2e5669fd99 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 d7b2f04747..387b38c0f6 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 1697dcda52..bb15eb1820 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 6d8f07893d..f0ba27f52e 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 3d3d305a7b..ad27a450f3 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 31d1444596..d0d1e454a5 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 86effa2187..4bcc9ace50 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");