From fea6781d860b6c31e921a37b168e29a73b56fb7e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 2 Jan 2009 17:39:48 +0000 Subject: [PATCH] Implemented SDL_SetWindowIcon(), with translucent icon support under X11. --HG-- extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%403429 --- include/SDL_video.h | 4 +-- src/SDL_compat.c | 4 ++- src/video/SDL_bmp.c | 19 +++++------- src/video/SDL_pixels.c | 15 ++++++++-- src/video/SDL_pixels_c.h | 3 ++ src/video/SDL_sysvideo.h | 1 + src/video/SDL_video.c | 56 +++++++++++++++++++++-------------- src/video/x11/SDL_x11render.c | 15 +++------- src/video/x11/SDL_x11video.c | 1 + src/video/x11/SDL_x11window.c | 37 +++++++++++++++++++++++ src/video/x11/SDL_x11window.h | 1 + 11 files changed, 105 insertions(+), 51 deletions(-) diff --git a/include/SDL_video.h b/include/SDL_video.h index 389de9e18..0644de94c 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -591,13 +591,13 @@ extern DECLSPEC void SDLCALL SDL_SetWindowTitle(SDL_WindowID windowID, 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) diff --git a/src/SDL_compat.c b/src/SDL_compat.c index 68e233554..d1f040cb6 100644 --- a/src/SDL_compat.c +++ b/src/SDL_compat.c @@ -39,6 +39,7 @@ static SDL_Surface *SDL_PublicSurface = NULL; 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 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) if (!SDL_VideoWindow) { return NULL; } + SDL_SetWindowIcon(SDL_VideoWindow, SDL_VideoIcon); window_flags = SDL_GetWindowFlags(SDL_VideoWindow); surface_flags = 0; @@ -868,7 +870,7 @@ SDL_WM_GetCaption(const char **title, const char **icon) void SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask) { - /* FIXME */ + SDL_VideoIcon = icon; } int diff --git a/src/video/SDL_bmp.c b/src/video/SDL_bmp.c index d8706d9f1..49e6089d3 100644 --- a/src/video/SDL_bmp.c +++ b/src/video/SDL_bmp.c @@ -397,22 +397,19 @@ SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst) ) { 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"); } } } diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c index f609da346..cb9246164 100644 --- a/src/video/SDL_pixels.c +++ b/src/video/SDL_pixels.c @@ -347,16 +347,25 @@ SDL_AllocFormat(int bpp, 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 @@ SDL_AllocFormat(int bpp, } format->palette = NULL; - return (format); + return format; } /* diff --git a/src/video/SDL_pixels_c.h b/src/video/SDL_pixels_c.h index 32bcf4e11..d619eedb2 100644 --- a/src/video/SDL_pixels_c.h +++ b/src/video/SDL_pixels_c.h @@ -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); diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index a510d6c34..eb2e8bdd8 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -238,6 +238,7 @@ struct SDL_VideoDevice 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); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 480b5fac7..c5af4076d 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -965,6 +965,19 @@ SDL_GetWindowTitle(SDL_WindowID windowID) return window->title; } +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) { @@ -1590,33 +1603,30 @@ SDL_CreateTextureFromSurface(Uint32 format, SDL_Surface * surface) 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); diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index c39a88d01..e51248c70 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -87,7 +87,7 @@ typedef struct 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_CreateRenderer(SDL_Window * window, Uint32 flags) 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 @@ renderdrawcolor(SDL_Renderer * renderer, int premult) 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 @@ X11_DestroyRenderer(SDL_Renderer * renderer) XFreePixmap(data->display, data->pixmaps[i]); } } - if (data->format) { - SDL_FreeFormat(data->format); - } if (data->gc) { XFreeGC(data->display, data->gc); } diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 53d241e0c..2cb5edd2c 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -174,6 +174,7 @@ X11_CreateDevice(int devindex) 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; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 8d178e2ed..91e0f8ea6 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -645,6 +645,43 @@ X11_SetWindowTitle(_THIS, SDL_Window * window) } } +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) { diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 7ef8e089f..5478f6013 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -36,6 +36,7 @@ typedef struct 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);