From 95ac0ff4d644e60345d41923550c2ae841357d00 Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
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 c6ea8ea17c3b1..51246eaf18584 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);