diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index dee6474e7..ce3aec46d 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -743,6 +743,9 @@ extern DECLSPEC const char *SDLCALL SDL_GetWindowTitle(SDL_Window *window); /** * Set the icon for a window. * + * Systems that do not support setting an icon to the window, will always fail, + * reporting `SDL_UNSUPPORTED`. + * * \param window the window to change * \param icon an SDL_Surface structure containing the icon for the window * \returns 0 on success or a negative error code on failure; call diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index d444af0bd..38a83a365 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -244,7 +244,7 @@ struct SDL_VideoDevice int (*CreateSDLWindow)(_THIS, SDL_Window *window); int (*CreateSDLWindowFrom)(_THIS, SDL_Window *window, const void *data); void (*SetWindowTitle)(_THIS, SDL_Window *window); - void (*SetWindowIcon)(_THIS, SDL_Window *window, SDL_Surface *icon); + int (*SetWindowIcon)(_THIS, SDL_Window *window, SDL_Surface *icon); void (*SetWindowPosition)(_THIS, SDL_Window *window); void (*SetWindowSize)(_THIS, SDL_Window *window); void (*SetWindowMinimumSize)(_THIS, SDL_Window *window); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index e2e2673af..571713ac7 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2080,7 +2080,7 @@ int SDL_SetWindowIcon(SDL_Window *window, SDL_Surface *icon) CHECK_WINDOW_MAGIC(window, -1); if (icon == NULL) { - return 0; + return SDL_InvalidParamError("icon"); } SDL_DestroySurface(window->icon); @@ -2088,13 +2088,14 @@ int SDL_SetWindowIcon(SDL_Window *window, SDL_Surface *icon) /* Convert the icon into ARGB8888 */ window->icon = SDL_ConvertSurfaceFormat(icon, SDL_PIXELFORMAT_ARGB8888); if (!window->icon) { - return -1; + return SDL_SetError("SDL_SetWindowIcon(): Unable to convert the icon's format"); } - if (_this->SetWindowIcon) { - _this->SetWindowIcon(_this, window, window->icon); + if (!_this->SetWindowIcon) { + return SDL_Unsupported(); } - return 0; + + return _this->SetWindowIcon(_this, window, window->icon); } void *SDL_SetWindowData(SDL_Window *window, const char *name, void *userdata) diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h index 009229b2f..ebc576ef2 100644 --- a/src/video/cocoa/SDL_cocoawindow.h +++ b/src/video/cocoa/SDL_cocoawindow.h @@ -142,7 +142,7 @@ extern int Cocoa_CreateWindow(_THIS, SDL_Window *window); extern int Cocoa_CreateWindowFrom(_THIS, SDL_Window *window, const void *data); extern void Cocoa_SetWindowTitle(_THIS, SDL_Window *window); -extern void Cocoa_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); +extern int Cocoa_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); extern void Cocoa_SetWindowPosition(_THIS, SDL_Window *window); extern void Cocoa_SetWindowSize(_THIS, SDL_Window *window); extern void Cocoa_SetWindowMinimumSize(_THIS, SDL_Window *window); diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 1b7cdd12e..90506c89e 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1874,14 +1874,18 @@ void Cocoa_SetWindowTitle(_THIS, SDL_Window *window) } } -void Cocoa_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon) +int Cocoa_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon) { @autoreleasepool { NSImage *nsimage = Cocoa_CreateImage(icon); if (nsimage) { [NSApp setApplicationIconImage:nsimage]; + + return 0; } + + return -1; } } diff --git a/src/video/haiku/SDL_bwindow.cc b/src/video/haiku/SDL_bwindow.cc index 852db3da8..368a72031 100644 --- a/src/video/haiku/SDL_bwindow.cc +++ b/src/video/haiku/SDL_bwindow.cc @@ -127,8 +127,10 @@ void HAIKU_SetWindowTitle(_THIS, SDL_Window * window) { _ToBeWin(window)->PostMessage(&msg); } -void HAIKU_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon) { - /* FIXME: Icons not supported by Haiku */ +int HAIKU_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon) { + /* Icons not supported by Haiku */ + SDL_Unsupported(); + return SDL_UNSUPPORTED; } void HAIKU_SetWindowPosition(_THIS, SDL_Window * window) { diff --git a/src/video/haiku/SDL_bwindow.h b/src/video/haiku/SDL_bwindow.h index d42c3e580..0e825448f 100644 --- a/src/video/haiku/SDL_bwindow.h +++ b/src/video/haiku/SDL_bwindow.h @@ -27,7 +27,7 @@ extern int HAIKU_CreateWindow(_THIS, SDL_Window *window); extern int HAIKU_CreateWindowFrom(_THIS, SDL_Window *window, const void *data); extern void HAIKU_SetWindowTitle(_THIS, SDL_Window *window); -extern void HAIKU_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); +extern int HAIKU_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); extern void HAIKU_SetWindowPosition(_THIS, SDL_Window *window); extern void HAIKU_SetWindowSize(_THIS, SDL_Window *window); extern void HAIKU_SetWindowMinimumSize(_THIS, SDL_Window *window); diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index ca4c3d0af..1cf66b63b 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -1560,8 +1560,10 @@ int KMSDRM_CreateWindowFrom(_THIS, SDL_Window *window, const void *data) void KMSDRM_SetWindowTitle(_THIS, SDL_Window *window) { } -void KMSDRM_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon) +int KMSDRM_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon) { + SDL_Unsupported(); + return SDL_UNSUPPORTED; } void KMSDRM_SetWindowPosition(_THIS, SDL_Window *window) { diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h index 025a09c01..9260055d6 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.h +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h @@ -124,7 +124,7 @@ int KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mod int KMSDRM_CreateWindow(_THIS, SDL_Window *window); int KMSDRM_CreateWindowFrom(_THIS, SDL_Window *window, const void *data); void KMSDRM_SetWindowTitle(_THIS, SDL_Window *window); -void KMSDRM_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); +int KMSDRM_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); void KMSDRM_SetWindowPosition(_THIS, SDL_Window *window); void KMSDRM_SetWindowSize(_THIS, SDL_Window *window); void KMSDRM_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *_display, SDL_bool fullscreen); diff --git a/src/video/psp/SDL_pspvideo.c b/src/video/psp/SDL_pspvideo.c index 0d407522a..0392df98f 100644 --- a/src/video/psp/SDL_pspvideo.c +++ b/src/video/psp/SDL_pspvideo.c @@ -216,8 +216,10 @@ int PSP_CreateWindowFrom(_THIS, SDL_Window *window, const void *data) void PSP_SetWindowTitle(_THIS, SDL_Window *window) { } -void PSP_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon) +int PSP_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon) { + SDL_Unsupported(); + return SDL_UNSUPPORTED; } void PSP_SetWindowPosition(_THIS, SDL_Window *window) { diff --git a/src/video/psp/SDL_pspvideo.h b/src/video/psp/SDL_pspvideo.h index 098d07979..6faa8c7c8 100644 --- a/src/video/psp/SDL_pspvideo.h +++ b/src/video/psp/SDL_pspvideo.h @@ -52,7 +52,7 @@ int PSP_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode); int PSP_CreateWindow(_THIS, SDL_Window *window); int PSP_CreateWindowFrom(_THIS, SDL_Window *window, const void *data); void PSP_SetWindowTitle(_THIS, SDL_Window *window); -void PSP_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); +int PSP_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); void PSP_SetWindowPosition(_THIS, SDL_Window *window); void PSP_SetWindowSize(_THIS, SDL_Window *window); void PSP_ShowWindow(_THIS, SDL_Window *window); diff --git a/src/video/raspberry/SDL_rpivideo.c b/src/video/raspberry/SDL_rpivideo.c index 480084c04..23a5aef99 100644 --- a/src/video/raspberry/SDL_rpivideo.c +++ b/src/video/raspberry/SDL_rpivideo.c @@ -352,6 +352,8 @@ void RPI_SetWindowTitle(_THIS, SDL_Window *window) } void RPI_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon) { + SDL_Unsupported(); + return SDL_UNSUPPORTED; } void RPI_SetWindowPosition(_THIS, SDL_Window *window) { diff --git a/src/video/raspberry/SDL_rpivideo.h b/src/video/raspberry/SDL_rpivideo.h index 629ba8b09..ef69344f3 100644 --- a/src/video/raspberry/SDL_rpivideo.h +++ b/src/video/raspberry/SDL_rpivideo.h @@ -66,7 +66,7 @@ int RPI_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode); int RPI_CreateWindow(_THIS, SDL_Window *window); int RPI_CreateWindowFrom(_THIS, SDL_Window *window, const void *data); void RPI_SetWindowTitle(_THIS, SDL_Window *window); -void RPI_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); +int RPI_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); void RPI_SetWindowPosition(_THIS, SDL_Window *window); void RPI_SetWindowSize(_THIS, SDL_Window *window); void RPI_ShowWindow(_THIS, SDL_Window *window); diff --git a/src/video/vita/SDL_vitavideo.c b/src/video/vita/SDL_vitavideo.c index 7b806d815..ed488bc8d 100644 --- a/src/video/vita/SDL_vitavideo.c +++ b/src/video/vita/SDL_vitavideo.c @@ -304,8 +304,10 @@ int VITA_CreateWindowFrom(_THIS, SDL_Window *window, const void *data) void VITA_SetWindowTitle(_THIS, SDL_Window *window) { } -void VITA_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon) +int VITA_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon) { + SDL_Unsupported(); + return SDL_UNSUPPORTED; } void VITA_SetWindowPosition(_THIS, SDL_Window *window) { diff --git a/src/video/vita/SDL_vitavideo.h b/src/video/vita/SDL_vitavideo.h index 0aba3ffb2..4a779a62f 100644 --- a/src/video/vita/SDL_vitavideo.h +++ b/src/video/vita/SDL_vitavideo.h @@ -65,7 +65,7 @@ int VITA_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode) int VITA_CreateWindow(_THIS, SDL_Window *window); int VITA_CreateWindowFrom(_THIS, SDL_Window *window, const void *data); void VITA_SetWindowTitle(_THIS, SDL_Window *window); -void VITA_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); +int VITA_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); void VITA_SetWindowPosition(_THIS, SDL_Window *window); void VITA_SetWindowSize(_THIS, SDL_Window *window); void VITA_ShowWindow(_THIS, SDL_Window *window); diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 24230b3bb..62c294a75 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -628,8 +628,9 @@ void WIN_SetWindowTitle(_THIS, SDL_Window *window) #endif } -void WIN_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon) +int WIN_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon) { + int retVal = 0; #if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) HWND hwnd = window->driverdata->hwnd; HICON hicon = NULL; @@ -677,12 +678,21 @@ void WIN_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon) SDL_small_free(icon_bmp, isstack); + if (hicon == NULL) { + SDL_SetError("SDL_SetWindowIcon(): Unable to create a resource from the icon"); + retVal = (int)GetLastError(); + } + /* Set the icon for the window */ SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon); /* Set the icon in the task manager (should we do this?) */ SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicon); +#else + SDL_Unsupported(); + retVal = SDL_UNSUPPORTED; #endif + return retVal; } void WIN_SetWindowPosition(_THIS, SDL_Window *window) diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index 9f263bed3..2aa59c93e 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -77,7 +77,7 @@ struct SDL_WindowData extern int WIN_CreateWindow(_THIS, SDL_Window *window); extern int WIN_CreateWindowFrom(_THIS, SDL_Window *window, const void *data); extern void WIN_SetWindowTitle(_THIS, SDL_Window *window); -extern void WIN_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); +extern int WIN_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); extern void WIN_SetWindowPosition(_THIS, SDL_Window *window); extern void WIN_SetWindowSize(_THIS, SDL_Window *window); extern int WIN_GetWindowBordersSize(_THIS, SDL_Window *window, int *top, int *left, int *bottom, int *right); diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 2b7d0968f..6206c7f41 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -739,45 +739,6 @@ void X11_SetWindowTitle(_THIS, SDL_Window *window) SDL_X11_SetWindowTitle(display, xwindow, title); } -void X11_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon) -{ - SDL_WindowData *data = window->driverdata; - Display *display = data->videodata->display; - Atom _NET_WM_ICON = data->videodata->_NET_WM_ICON; - - if (icon) { - int propsize; - long *propdata; - - /* Set the _NET_WM_ICON property */ - SDL_assert(icon->format->format == SDL_PIXELFORMAT_ARGB8888); - propsize = 2 + (icon->w * icon->h); - propdata = SDL_malloc(propsize * sizeof(long)); - if (propdata) { - int x, y; - Uint32 *src; - long *dst; - - propdata[0] = icon->w; - propdata[1] = icon->h; - dst = &propdata[2]; - for (y = 0; y < icon->h; ++y) { - src = (Uint32 *)((Uint8 *)icon->pixels + y * icon->pitch); - for (x = 0; x < icon->w; ++x) { - *dst++ = *src++; - } - } - X11_XChangeProperty(display, data->xwindow, _NET_WM_ICON, XA_CARDINAL, - 32, PropModeReplace, (unsigned char *)propdata, - propsize); - } - SDL_free(propdata); - } else { - X11_XDeleteProperty(display, data->xwindow, _NET_WM_ICON); - } - X11_XFlush(display); -} - static SDL_bool caught_x11_error = SDL_FALSE; static int X11_CatchAnyError(Display *d, XErrorEvent *e) { @@ -787,6 +748,76 @@ static int X11_CatchAnyError(Display *d, XErrorEvent *e) return 0; } +int X11_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon) +{ + SDL_WindowData *data = window->driverdata; + Display *display = data->videodata->display; + Atom _NET_WM_ICON = data->videodata->_NET_WM_ICON; + int retVal = 0; + int (*prevHandler)(Display *, XErrorEvent *) = NULL; + + if (icon) { + int propsize; + long *propdata; + + int x, y; + Uint32 *src; + long *dst; + + /* Set the _NET_WM_ICON property */ + SDL_assert(icon->format->format == SDL_PIXELFORMAT_ARGB8888); + propsize = 2 + (icon->w * icon->h); + propdata = SDL_malloc(propsize * sizeof(long)); + + if (!propdata) { + SDL_OutOfMemory(); + return SDL_ENOMEM; + } + + prevHandler = X11_XSetErrorHandler(X11_CatchAnyError); + + propdata[0] = icon->w; + propdata[1] = icon->h; + dst = &propdata[2]; + + for (y = 0; y < icon->h; ++y) { + src = (Uint32 *)((Uint8 *)icon->pixels + y * icon->pitch); + for (x = 0; x < icon->w; ++x) { + *dst++ = *src++; + } + } + + X11_XChangeProperty(display, data->xwindow, _NET_WM_ICON, XA_CARDINAL, + 32, PropModeReplace, (unsigned char *)propdata, + propsize); + SDL_free(propdata); + + if (caught_x11_error) { + SDL_SetError("SDL_SetWindowIcon(): An error occurred while trying to set the window's icon"); + retVal = -1; + } + + } else { + prevHandler = X11_XSetErrorHandler(X11_CatchAnyError); + X11_XDeleteProperty(display, data->xwindow, _NET_WM_ICON); + + if (caught_x11_error) { + SDL_SetError("SDL_SetWindowIcon(): An error occurred while trying to unset the window's icon"); + retVal = -1; + } + } + + + X11_XFlush(display); + + if (prevHandler != NULL) { + X11_XSetErrorHandler(prevHandler); + caught_x11_error = SDL_FALSE; + } + + return retVal; +} + void X11_SetWindowPosition(_THIS, SDL_Window *window) { SDL_WindowData *data = window->driverdata; diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 05a263685..fe1321849 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -87,7 +87,7 @@ extern int X11_CreateWindow(_THIS, SDL_Window *window); extern int X11_CreateWindowFrom(_THIS, SDL_Window *window, const void *data); extern char *X11_GetWindowTitle(_THIS, Window xwindow); extern void X11_SetWindowTitle(_THIS, SDL_Window *window); -extern void X11_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); +extern int X11_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon); extern void X11_SetWindowPosition(_THIS, SDL_Window *window); extern void X11_SetWindowMinimumSize(_THIS, SDL_Window *window); extern void X11_SetWindowMaximumSize(_THIS, SDL_Window *window);