Implemented SDL_SetWindowIcon(), with translucent icon support under X11.
authorSam Lantinga <slouken@libsdl.org>
Fri, 02 Jan 2009 17:39:48 +0000
changeset 2967 e4a469d6ddab
parent 2966 c1e3621ba959
child 2968 efe4d0ce2e97
Implemented SDL_SetWindowIcon(), with translucent icon support under X11.
include/SDL_video.h
src/SDL_compat.c
src/video/SDL_bmp.c
src/video/SDL_pixels.c
src/video/SDL_pixels_c.h
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/x11/SDL_x11render.c
src/video/x11/SDL_x11video.c
src/video/x11/SDL_x11window.c
src/video/x11/SDL_x11window.h
--- a/include/SDL_video.h	Fri Jan 02 16:38:31 2009 +0000
+++ b/include/SDL_video.h	Fri Jan 02 17:39:48 2009 +0000
@@ -591,13 +591,13 @@
 extern DECLSPEC const char *SDLCALL SDL_GetWindowTitle(SDL_WindowID windowID);
 
 /**
- * \fn void SDL_SetWindowIcon(SDL_Surface *icon)
+ * \fn void SDL_SetWindowIcon(SDL_WindowID windowID, SDL_Surface *icon)
  *
  * \brief Set the icon of the window.
  *
  * \param icon The icon for the window
  */
-extern DECLSPEC void SDLCALL SDL_SetWindowIcon(SDL_Surface * icon);
+extern DECLSPEC void SDLCALL SDL_SetWindowIcon(SDL_WindowID windowID, SDL_Surface * icon);
 
 /**
  * \fn void SDL_SetWindowData(SDL_WindowID windowID, void *userdata)
--- a/src/SDL_compat.c	Fri Jan 02 16:38:31 2009 +0000
+++ b/src/SDL_compat.c	Fri Jan 02 17:39:48 2009 +0000
@@ -39,6 +39,7 @@
 static SDL_GLContext *SDL_VideoContext = NULL;
 static Uint32 SDL_VideoFlags = 0;
 static char *wm_title = NULL;
+static SDL_Surface *SDL_VideoIcon;
 
 char *
 SDL_AudioDriverName(char *namebuf, int maxlen)
@@ -522,6 +523,7 @@
     if (!SDL_VideoWindow) {
         return NULL;
     }
+    SDL_SetWindowIcon(SDL_VideoWindow, SDL_VideoIcon);
 
     window_flags = SDL_GetWindowFlags(SDL_VideoWindow);
     surface_flags = 0;
@@ -868,7 +870,7 @@
 void
 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
 {
-    /* FIXME */
+    SDL_VideoIcon = icon;
 }
 
 int
--- a/src/video/SDL_bmp.c	Fri Jan 02 16:38:31 2009 +0000
+++ b/src/video/SDL_bmp.c	Fri Jan 02 17:39:48 2009 +0000
@@ -397,22 +397,19 @@
             ) {
             surface = saveme;
         } else {
-            SDL_PixelFormat *format;
+            SDL_PixelFormat format;
 
             /* Convert to 24 bits per pixel */
-            format = SDL_AllocFormat(24,
+            SDL_InitFormat(&format, 24,
 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
-                                     0x00FF0000, 0x0000FF00, 0x000000FF,
+                           0x00FF0000, 0x0000FF00, 0x000000FF,
 #else
-                                     0x000000FF, 0x0000FF00, 0x00FF0000,
+                           0x000000FF, 0x0000FF00, 0x00FF0000,
 #endif
-                                     0);
-            if (format != NULL) {
-                surface = SDL_ConvertSurface(saveme, format, 0);
-                if (!surface) {
-                    SDL_SetError("Couldn't convert image to 24 bpp");
-                }
-                SDL_FreeFormat(format);
+                           0);
+            surface = SDL_ConvertSurface(saveme, &format, 0);
+            if (!surface) {
+                SDL_SetError("Couldn't convert image to 24 bpp");
             }
         }
     }
--- a/src/video/SDL_pixels.c	Fri Jan 02 16:38:31 2009 +0000
+++ b/src/video/SDL_pixels.c	Fri Jan 02 17:39:48 2009 +0000
@@ -347,16 +347,25 @@
                 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
 {
     SDL_PixelFormat *format;
-    Uint32 mask;
 
     /* Allocate an empty pixel format structure */
-    format = SDL_calloc(1, sizeof(*format));
+    format = SDL_malloc(sizeof(*format));
     if (format == NULL) {
         SDL_OutOfMemory();
         return (NULL);
     }
 
     /* Set up the format */
+    return SDL_InitFormat(format, bpp, Rmask, Gmask, Bmask, Amask);
+}
+
+SDL_PixelFormat *
+SDL_InitFormat(SDL_PixelFormat *format, int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
+{
+    Uint32 mask;
+
+    /* Set up the format */
+    SDL_zerop(format);
     format->BitsPerPixel = bpp;
     format->BytesPerPixel = (bpp + 7) / 8;
     if (Rmask || Bmask || Gmask) {      /* Packed pixels with custom mask */
@@ -426,7 +435,7 @@
     }
     format->palette = NULL;
 
-    return (format);
+    return format;
 }
 
 /*
--- a/src/video/SDL_pixels_c.h	Fri Jan 02 16:38:31 2009 +0000
+++ b/src/video/SDL_pixels_c.h	Fri Jan 02 17:39:48 2009 +0000
@@ -29,6 +29,9 @@
 extern SDL_PixelFormat *SDL_AllocFormat(int bpp,
                                         Uint32 Rmask, Uint32 Gmask,
                                         Uint32 Bmask, Uint32 Amask);
+extern SDL_PixelFormat *SDL_InitFormat(SDL_PixelFormat *format, int bpp,
+                                        Uint32 Rmask, Uint32 Gmask,
+                                        Uint32 Bmask, Uint32 Amask);
 extern void SDL_FormatChanged(SDL_Surface * surface);
 extern void SDL_FreeFormat(SDL_PixelFormat * format);
 
--- a/src/video/SDL_sysvideo.h	Fri Jan 02 16:38:31 2009 +0000
+++ b/src/video/SDL_sysvideo.h	Fri Jan 02 17:39:48 2009 +0000
@@ -238,6 +238,7 @@
     int (*CreateWindow) (_THIS, SDL_Window * window);
     int (*CreateWindowFrom) (_THIS, SDL_Window * window, const void *data);
     void (*SetWindowTitle) (_THIS, SDL_Window * window);
+    void (*SetWindowIcon) (_THIS, SDL_Window * window, SDL_Surface * icon);
     void (*SetWindowPosition) (_THIS, SDL_Window * window);
     void (*SetWindowSize) (_THIS, SDL_Window * window);
     void (*ShowWindow) (_THIS, SDL_Window * window);
--- a/src/video/SDL_video.c	Fri Jan 02 16:38:31 2009 +0000
+++ b/src/video/SDL_video.c	Fri Jan 02 17:39:48 2009 +0000
@@ -966,6 +966,19 @@
 }
 
 void
+SDL_SetWindowIcon(SDL_WindowID windowID, SDL_Surface * icon)
+{
+    SDL_Window *window = SDL_GetWindowFromID(windowID);
+
+    if (!window) {
+        return;
+    }
+    if (_this->SetWindowIcon) {
+        _this->SetWindowIcon(_this, window, icon);
+    }
+}
+
+void
 SDL_SetWindowData(SDL_WindowID windowID, void *userdata)
 {
     SDL_Window *window = SDL_GetWindowFromID(windowID);
@@ -1590,33 +1603,30 @@
                               surface->pitch);
         }
     } else {
-        SDL_PixelFormat *dst_fmt;
+        SDL_PixelFormat dst_fmt;
         SDL_Surface *dst = NULL;
 
         /* Set up a destination surface for the texture update */
-        dst_fmt = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
-        if (dst_fmt) {
-            if (SDL_ISPIXELFORMAT_INDEXED(format)) {
-                dst_fmt->palette =
-                    SDL_AllocPalette((1 << SDL_BITSPERPIXEL(format)));
-                if (dst_fmt->palette) {
-                    /*
-                     * FIXME: Should we try to copy
-                     * fmt->palette?
-                     */
-                    SDL_DitherColors(dst_fmt->palette->colors,
-                                     SDL_BITSPERPIXEL(format));
-                }
+        SDL_InitFormat(&dst_fmt, bpp, Rmask, Gmask, Bmask, Amask);
+        if (SDL_ISPIXELFORMAT_INDEXED(format)) {
+            dst_fmt.palette =
+                SDL_AllocPalette((1 << SDL_BITSPERPIXEL(format)));
+            if (dst_fmt.palette) {
+                /*
+                 * FIXME: Should we try to copy
+                 * fmt->palette?
+                 */
+                SDL_DitherColors(dst_fmt.palette->colors,
+                                 SDL_BITSPERPIXEL(format));
             }
-            dst = SDL_ConvertSurface(surface, dst_fmt, 0);
-            if (dst) {
-                SDL_UpdateTexture(textureID, NULL, dst->pixels, dst->pitch);
-                SDL_FreeSurface(dst);
-            }
-            if (dst_fmt->palette) {
-                SDL_FreePalette(dst_fmt->palette);
-            }
-            SDL_FreeFormat(dst_fmt);
+        }
+        dst = SDL_ConvertSurface(surface, &dst_fmt, 0);
+        if (dst) {
+            SDL_UpdateTexture(textureID, NULL, dst->pixels, dst->pitch);
+            SDL_FreeSurface(dst);
+        }
+        if (dst_fmt.palette) {
+            SDL_FreePalette(dst_fmt.palette);
         }
         if (!dst) {
             SDL_DestroyTexture(textureID);
--- a/src/video/x11/SDL_x11render.c	Fri Jan 02 16:38:31 2009 +0000
+++ b/src/video/x11/SDL_x11render.c	Fri Jan 02 17:39:48 2009 +0000
@@ -87,7 +87,7 @@
     Pixmap pixmaps[3];
     int current_pixmap;
     Drawable drawable;
-    SDL_PixelFormat *format;
+    SDL_PixelFormat format;
     GC gc;
     SDL_DirtyRectList dirty;
     SDL_bool makedirty;
@@ -251,11 +251,7 @@
         X11_DestroyRenderer(renderer);
         return NULL;
     }
-    data->format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
-    if (!data->format) {
-        X11_DestroyRenderer(renderer);
-        return NULL;
-    }
+    SDL_InitFormat(&data->format, bpp, Rmask, Gmask, Bmask, Amask);
 
     /* Create the drawing context */
     gcv.graphics_exposures = False;
@@ -583,11 +579,11 @@
     Uint8 b = renderer->b;
     Uint8 a = renderer->a;
     if (premult)
-        return SDL_MapRGBA(data->format, ((int) r * (int) a) / 255,
+        return SDL_MapRGBA(&data->format, ((int) r * (int) a) / 255,
                            ((int) g * (int) a) / 255,
                            ((int) b * (int) a) / 255, 255);
     else
-        return SDL_MapRGBA(data->format, r, g, b, a);
+        return SDL_MapRGBA(&data->format, r, g, b, a);
 }
 
 static int
@@ -852,9 +848,6 @@
                 XFreePixmap(data->display, data->pixmaps[i]);
             }
         }
-        if (data->format) {
-            SDL_FreeFormat(data->format);
-        }
         if (data->gc) {
             XFreeGC(data->display, data->gc);
         }
--- a/src/video/x11/SDL_x11video.c	Fri Jan 02 16:38:31 2009 +0000
+++ b/src/video/x11/SDL_x11video.c	Fri Jan 02 17:39:48 2009 +0000
@@ -174,6 +174,7 @@
     device->CreateWindow = X11_CreateWindow;
     device->CreateWindowFrom = X11_CreateWindowFrom;
     device->SetWindowTitle = X11_SetWindowTitle;
+    device->SetWindowIcon = X11_SetWindowIcon;
     device->SetWindowPosition = X11_SetWindowPosition;
     device->SetWindowSize = X11_SetWindowSize;
     device->ShowWindow = X11_ShowWindow;
--- a/src/video/x11/SDL_x11window.c	Fri Jan 02 16:38:31 2009 +0000
+++ b/src/video/x11/SDL_x11window.c	Fri Jan 02 17:39:48 2009 +0000
@@ -646,6 +646,43 @@
 }
 
 void
+X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
+{
+    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+    Display *display = data->videodata->display;
+    Atom _NET_WM_ICON = XInternAtom(display, "_NET_WM_ICON", False);
+
+    if (icon) {
+        SDL_PixelFormat format;
+        SDL_Surface *surface;
+        int propsize;
+        Uint32 *propdata;
+
+        /* Convert the icon to ARGB for modern window managers */
+        SDL_InitFormat(&format, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
+        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(Uint32));
+        if (propdata) {
+            propdata[0] = icon->w;
+            propdata[1] = icon->h;
+            SDL_memcpy(&propdata[2], surface->pixels, surface->h*surface->pitch);
+            XChangeProperty(display, data->window, _NET_WM_ICON, 
+                            XA_CARDINAL, 32, PropModeReplace,
+                            (unsigned char *) propdata, propsize);
+        }
+        SDL_FreeSurface(surface);
+    } else {
+        XDeleteProperty(display, data->window, _NET_WM_ICON);
+    }
+}
+
+void
 X11_SetWindowPosition(_THIS, SDL_Window * window)
 {
     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
--- a/src/video/x11/SDL_x11window.h	Fri Jan 02 16:38:31 2009 +0000
+++ b/src/video/x11/SDL_x11window.h	Fri Jan 02 17:39:48 2009 +0000
@@ -36,6 +36,7 @@
 extern int X11_CreateWindow(_THIS, SDL_Window * window);
 extern int X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data);
 extern void X11_SetWindowTitle(_THIS, SDL_Window * window);
+extern void X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
 extern void X11_SetWindowPosition(_THIS, SDL_Window * window);
 extern void X11_SetWindowSize(_THIS, SDL_Window * window);
 extern void X11_ShowWindow(_THIS, SDL_Window * window);