Try to use _NET_WM_ICON if possible for X11's SDL_WM_SetIcon() implementation. SDL-1.2
authorRyan C. Gordon <icculus@icculus.org>
Fri, 05 Oct 2012 22:41:02 -0400
branchSDL-1.2
changeset 6561ea34ef329509
parent 6460 2a971ffe1fad
child 6563 ba187d0466e6
Try to use _NET_WM_ICON if possible for X11's SDL_WM_SetIcon() implementation.

This lets us have larger icons with more colors.
src/video/x11/SDL_x11wm.c
     1.1 --- a/src/video/x11/SDL_x11wm.c	Tue Sep 25 20:51:31 2012 -0700
     1.2 +++ b/src/video/x11/SDL_x11wm.c	Fri Oct 05 22:41:02 2012 -0400
     1.3 @@ -43,6 +43,7 @@
     1.4  
     1.5  void X11_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask)
     1.6  {
     1.7 +	Atom _NET_WM_ICON = XInternAtom(SDL_Display, "_NET_WM_ICON", False);
     1.8  	SDL_Surface *sicon;
     1.9  	XWMHints *wmhints;
    1.10  	XImage *icon_image;
    1.11 @@ -60,6 +61,80 @@
    1.12  
    1.13  	SDL_Lock_EventThread();
    1.14  
    1.15 +	if (_NET_WM_ICON) {   /* better interface for modern systems. */
    1.16 +		SDL_PixelFormat format;
    1.17 +		SDL_Surface *surface;
    1.18 +		int propsize;
    1.19 +		long *propdata;
    1.20 +
    1.21 +		/* Convert the icon to ARGB for modern window managers */
    1.22 +		SDL_memset(&format, 0, sizeof (format));
    1.23 +		format.BitsPerPixel = 32;
    1.24 +		format.BytesPerPixel = 4;
    1.25 +		#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    1.26 +		format.Rshift = 8;
    1.27 +		format.Gshift = 16;
    1.28 +		format.Bshift = 24;
    1.29 +		format.Ashift = 0;
    1.30 +		#else
    1.31 +		format.Rshift = 16;
    1.32 +		format.Gshift = 8;
    1.33 +		format.Bshift = 0;
    1.34 +		format.Ashift = 24;
    1.35 +		#endif
    1.36 +		format.Rmask = 0xFF << format.Rshift;
    1.37 +		format.Gmask = 0xFF << format.Gshift;
    1.38 +		format.Bmask = 0xFF << format.Bshift;
    1.39 +		format.Amask = 0xFF << format.Ashift;
    1.40 +		format.alpha = SDL_ALPHA_OPAQUE;
    1.41 +
    1.42 +		surface = SDL_ConvertSurface(icon, &format, 0);
    1.43 +		if (!surface) {
    1.44 +			return;
    1.45 +		}
    1.46 +
    1.47 +		/* Set the _NET_WM_ICON property */
    1.48 +		propsize = 2 + (icon->w * icon->h);
    1.49 +		propdata = SDL_malloc(propsize * sizeof(long));
    1.50 +		if (propdata) {
    1.51 +			const Uint32 alpha = format.Amask;
    1.52 +			int x, y;
    1.53 +			Uint32 *src;
    1.54 +			long *dst;
    1.55 +
    1.56 +			propdata[0] = icon->w;
    1.57 +			propdata[1] = icon->h;
    1.58 +			dst = &propdata[2];
    1.59 +
    1.60 +			size_t maskidx = 0;
    1.61 +			for (y = 0; y < icon->h; ++y) {
    1.62 +				src = (Uint32*)((Uint8*)surface->pixels + y * surface->pitch);
    1.63 +				for (x = 0; x < icon->w; ++x) {
    1.64 +					const Uint32 pixel = *(src++);
    1.65 +					if (mask[maskidx / 8] & (1<<(7-(maskidx % 8)))) {
    1.66 +						*dst++ = pixel | alpha;
    1.67 +					} else {
    1.68 +						*dst++ = pixel & ~alpha;
    1.69 +					}
    1.70 +					maskidx++;
    1.71 +				}
    1.72 +			}
    1.73 +
    1.74 +			XChangeProperty(SDL_Display, WMwindow, _NET_WM_ICON, XA_CARDINAL,
    1.75 +			                32, PropModeReplace, (unsigned char *) propdata,
    1.76 +			                propsize);
    1.77 +		}
    1.78 +
    1.79 +		SDL_FreeSurface(surface);
    1.80 +		SDL_free(propdata);
    1.81 +
    1.82 +		SDL_Unlock_EventThread();
    1.83 +
    1.84 +		return;
    1.85 +	}
    1.86 +
    1.87 +	/* Do it the old way... */
    1.88 +
    1.89  	/* The icon must use the default visual, depth and colormap of the
    1.90  	   screen, so it might need a conversion */
    1.91  	dvis = DefaultVisual(SDL_Display, SDL_Screen);