summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan C. Gordon <icculus@icculus.org>2012-10-05 22:41:02 -0400
committerRyan C. Gordon <icculus@icculus.org>2012-10-05 22:41:02 -0400
commit6da2a22e07161479ba909ef77e15f52340f8a407 (patch)
treee52c759e9feb1c7bc17b0d5fa2078a4ed4b07e96
parentc0bfdea2c020aa93aaad6516a3c5bd071bd2d2d5 (diff)
downloadsdl-6da2a22e07161479ba909ef77e15f52340f8a407.tar.gz
Try to use _NET_WM_ICON if possible for X11's SDL_WM_SetIcon() implementation.
This lets us have larger icons with more colors.
-rw-r--r--src/video/x11/SDL_x11wm.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/video/x11/SDL_x11wm.c b/src/video/x11/SDL_x11wm.c
index 14c816b94..cb77a78f7 100644
--- a/src/video/x11/SDL_x11wm.c
+++ b/src/video/x11/SDL_x11wm.c
@@ -43,6 +43,7 @@ static Uint8 reverse_byte(Uint8 x)
void X11_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask)
{
+ Atom _NET_WM_ICON = XInternAtom(SDL_Display, "_NET_WM_ICON", False);
SDL_Surface *sicon;
XWMHints *wmhints;
XImage *icon_image;
@@ -60,6 +61,80 @@ void X11_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask)
SDL_Lock_EventThread();
+ if (_NET_WM_ICON) { /* better interface for modern systems. */
+ SDL_PixelFormat format;
+ SDL_Surface *surface;
+ int propsize;
+ long *propdata;
+
+ /* Convert the icon to ARGB for modern window managers */
+ SDL_memset(&format, 0, sizeof (format));
+ format.BitsPerPixel = 32;
+ format.BytesPerPixel = 4;
+ #if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ format.Rshift = 8;
+ format.Gshift = 16;
+ format.Bshift = 24;
+ format.Ashift = 0;
+ #else
+ format.Rshift = 16;
+ format.Gshift = 8;
+ format.Bshift = 0;
+ format.Ashift = 24;
+ #endif
+ format.Rmask = 0xFF << format.Rshift;
+ format.Gmask = 0xFF << format.Gshift;
+ format.Bmask = 0xFF << format.Bshift;
+ format.Amask = 0xFF << format.Ashift;
+ format.alpha = SDL_ALPHA_OPAQUE;
+
+ surface = SDL_ConvertSurface(icon, &format, 0);
+ if (!surface) {
+ return;
+ }
+
+ /* Set the _NET_WM_ICON property */
+ propsize = 2 + (icon->w * icon->h);
+ propdata = SDL_malloc(propsize * sizeof(long));
+ if (propdata) {
+ const Uint32 alpha = format.Amask;
+ int x, y;
+ Uint32 *src;
+ long *dst;
+
+ propdata[0] = icon->w;
+ propdata[1] = icon->h;
+ dst = &propdata[2];
+
+ size_t maskidx = 0;
+ for (y = 0; y < icon->h; ++y) {
+ src = (Uint32*)((Uint8*)surface->pixels + y * surface->pitch);
+ for (x = 0; x < icon->w; ++x) {
+ const Uint32 pixel = *(src++);
+ if (mask[maskidx / 8] & (1<<(7-(maskidx % 8)))) {
+ *dst++ = pixel | alpha;
+ } else {
+ *dst++ = pixel & ~alpha;
+ }
+ maskidx++;
+ }
+ }
+
+ XChangeProperty(SDL_Display, WMwindow, _NET_WM_ICON, XA_CARDINAL,
+ 32, PropModeReplace, (unsigned char *) propdata,
+ propsize);
+ }
+
+ SDL_FreeSurface(surface);
+ SDL_free(propdata);
+
+ SDL_Unlock_EventThread();
+
+ return;
+ }
+
+ /* Do it the old way... */
+
/* The icon must use the default visual, depth and colormap of the
screen, so it might need a conversion */
dvis = DefaultVisual(SDL_Display, SDL_Screen);