From 95ac0ff4d644e60345d41923550c2ae841357d00 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Mon, 29 Dec 2025 13:26:19 -0500 Subject: [PATCH] wayland: Center non-square icon images Center icon images instead of scaling to preserve the aspect ratio. --- src/video/wayland/SDL_waylandwindow.c | 36 ++++++++++----------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index c6ea8ea17c..51246eaf18 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -3029,11 +3029,7 @@ bool Wayland_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surfa // Calculate the size of the buffer pool. size_t pool_size = 0; for (int i = 0; i < image_count; ++i) { - // Ignore non-square images; if we got here, we know that at least the base image is square. - if (images[i]->w != images[i]->h) { - SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "wayland: icon width and height must be equal, got %ix%i for image level %i; icon will be scaled", images[i]->w, images[i]->h, i); - } - + // Images must be square. Non-square images will be centered. const int size = SDL_max(images[i]->w, images[i]->h); pool_size += size * size * 4; } @@ -3066,25 +3062,10 @@ bool Wayland_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surfa } } - if (surface->w != surface->h) { - SDL_Surface *scaled_surface = SDL_ScaleSurface(surface, level_size, level_size, SDL_SCALEMODE_LINEAR); - - // Clean up the temporary conversion surface. - if (surface != images[i]) { - SDL_DestroySurface(surface); - } - surface = scaled_surface; - - if (!surface) { - SDL_SetError("wayland: failed to scale the non-square icon image to the required size"); - goto failure_cleanup; - } - } - void *buffer_mem; - struct wl_buffer *buffer = Wayland_AllocBufferFromPool(shm_pool, surface->w, surface->h, &buffer_mem); + struct wl_buffer *buffer = Wayland_AllocBufferFromPool(shm_pool, level_size, level_size, &buffer_mem); if (!buffer) { - // Clean up the temporary scaled or conversion surface. + // Clean up the temporary conversion surface. if (surface != images[i]) { SDL_DestroySurface(surface); } @@ -3094,8 +3075,17 @@ bool Wayland_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surfa wind->icon_buffers[wind->icon_buffer_count++] = buffer; + // Center non-square images. + if (surface->w < level_size) { + SDL_memset(buffer_mem, 0, level_size * level_size * 4); + buffer_mem = (Uint8 *)buffer_mem + (((level_size - surface->w) / 2) * 4); + } else if (surface->h < level_size) { + SDL_memset(buffer_mem, 0, level_size * level_size * 4); + buffer_mem = (Uint8 *)buffer_mem + (((level_size - surface->h) / 2) * (level_size * 4)); + } + SDL_PremultiplyAlpha(surface->w, surface->h, surface->format, surface->pixels, surface->pitch, - SDL_PIXELFORMAT_ARGB8888, buffer_mem, surface->w * 4, true); + SDL_PIXELFORMAT_ARGB8888, buffer_mem, level_size * 4, true); xdg_toplevel_icon_v1_add_buffer(wind->xdg_toplevel_icon_v1, buffer, scale);