From 9b903e93e3cd0601b436c55b7cea1fbecf29895f Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Tue, 17 Feb 2015 23:37:01 -0800 Subject: [PATCH] iconcache: Fix the icon of Kerbel Space Program Kerbel Space Program, and perhaps some other SDL-based programs, use a really dumb way of specifying icons, which is totally non-standards-compliant. The ICCCM specifies that the icon_pixmap field of WM_HINTS should be a 1-bit-deep Pixmap, but we've seen applications set it to a pixmap of the root depth as well, so we support that. Kerbel Space Program seems to use it with a 32-bit depth Pixmap, signifying ARGB32 (which it is), along with a 1-bit icon_mask, which crashes us. Keep in mind that Pixmaps, by definition, have no Visual attached, so we simply have to make a guess at the correct visual based on the depth. Do that by assuming that a depth-32 visual always means ARGB32, which is a pretty safe bet. --- src/x11/iconcache.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/x11/iconcache.c b/src/x11/iconcache.c index 71b7417dd..4747295d4 100644 --- a/src/x11/iconcache.c +++ b/src/x11/iconcache.c @@ -27,8 +27,10 @@ #include #include +#include #include +#include static gboolean find_largest_sizes (gulong *data, @@ -284,34 +286,42 @@ get_pixmap_geometry (MetaDisplay *display, *d = depth; } +static int +standard_pict_format_for_depth (int depth) +{ + switch (depth) + { + case 1: + return PictStandardA1; + case 24: + return PictStandardRGB24; + case 32: + return PictStandardARGB32; + default: + g_assert_not_reached (); + } +} + +static XRenderPictFormat * +pict_format_for_depth (Display *xdisplay, int depth) +{ + return XRenderFindStandardFormat (xdisplay, standard_pict_format_for_depth (depth)); +} + static cairo_surface_t * surface_from_pixmap (Display *xdisplay, Pixmap xpixmap, int width, int height) { - 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; - if (depth_ret == 1) - { - surface = cairo_xlib_surface_create_for_bitmap (xdisplay, xpixmap, DefaultScreenOfDisplay (xdisplay), - w_ret, h_ret); - } - else - { - if (!XGetWindowAttributes (xdisplay, root_return, &attrs)) - return NULL; - - surface = cairo_xlib_surface_create (xdisplay, xpixmap, attrs.visual, w_ret, h_ret); - } - - return surface; + return cairo_xlib_surface_create_with_xrender_format (xdisplay, xpixmap, DefaultScreenOfDisplay (xdisplay), + pict_format_for_depth (xdisplay, depth_ret), w_ret, h_ret); } static gboolean