fix: titlebar button rendering — proper colors and bevel

- Background: matches titlebar background (sampled)
- Foreground: uses title text color (the color parameter)
- Pressed state: swaps fg/bg (inverted colors)
- Border: raised bevel when normal, sunken when pushed
- Icon pixels rendered in fg color (not raw XPM colors)
This commit is contained in:
lkn 2026-05-23 14:16:44 +02:00
parent a34d8281b9
commit 5a4d989a78
1 changed files with 25 additions and 17 deletions

View File

@ -7581,7 +7581,7 @@ static void wl_noop_frame_update_texture(struct WFrameWindow *fwin) { (void)fwin
static void wl_frame_paint_button(WCoreWindow *button, WTexture *texture, static void wl_frame_paint_button(WCoreWindow *button, WTexture *texture,
unsigned long color, WPixmap *image, int pushed) unsigned long color, WPixmap *image, int pushed)
{ {
(void)texture; (void)color; (void)image; (void)texture; (void)image;
WFrameWindow *fwin = (WFrameWindow *)button->descriptor.parent; WFrameWindow *fwin = (WFrameWindow *)button->descriptor.parent;
if (!fwin || !fwin->core) if (!fwin || !fwin->core)
return; return;
@ -7609,11 +7609,10 @@ static void wl_frame_paint_button(WCoreWindow *button, WTexture *texture,
if (!icon) if (!icon)
return; return;
/* Clear button buffer with titlebar background */ /* Get titlebar background color */
struct wl_frame_buf *tb_fb = fwin->titlebar ? frame_buf_find(fwin->titlebar->window) : NULL; struct wl_frame_buf *tb_fb = fwin->titlebar ? frame_buf_find(fwin->titlebar->window) : NULL;
uint32_t bg_pixel = 0xFF333333; uint32_t bg_pixel = 0xFF333333;
if (tb_fb && tb_fb->image) { if (tb_fb && tb_fb->image) {
/* Sample background color from titlebar at button position */
uint32_t *tb_data = pixman_image_get_data(tb_fb->image); uint32_t *tb_data = pixman_image_get_data(tb_fb->image);
int tb_stride = pixman_image_get_stride(tb_fb->image) / 4; int tb_stride = pixman_image_get_stride(tb_fb->image) / 4;
int sample_y = btn_fb->rel_y + bh / 2; int sample_y = btn_fb->rel_y + bh / 2;
@ -7622,13 +7621,28 @@ static void wl_frame_paint_button(WCoreWindow *button, WTexture *texture,
sample_x >= 0 && sample_x < tb_fb->width) sample_x >= 0 && sample_x < tb_fb->width)
bg_pixel = tb_data[sample_y * tb_stride + sample_x]; bg_pixel = tb_data[sample_y * tb_stride + sample_x];
} }
/* Foreground = title text color; when pushed, swap fg/bg */
uint32_t fg_pixel = 0xFF000000 | ((color >> 16 & 0xFF) << 16) |
((color >> 8 & 0xFF) << 8) | (color & 0xFF);
uint32_t fill_bg = pushed ? fg_pixel : bg_pixel;
uint32_t fill_fg = pushed ? bg_pixel : fg_pixel;
uint32_t *dst = pixman_image_get_data(btn_fb->image); uint32_t *dst = pixman_image_get_data(btn_fb->image);
int dst_stride = pixman_image_get_stride(btn_fb->image) / 4; int dst_stride = pixman_image_get_stride(btn_fb->image) / 4;
/* Fill background */
for (int y = 0; y < bh; y++) for (int y = 0; y < bh; y++)
for (int x = 0; x < bw; x++) for (int x = 0; x < bw; x++)
dst[y * dst_stride + x] = bg_pixel; dst[y * dst_stride + x] = fill_bg;
/* Blit icon centered in button area */ /* Draw border bevel (raised when normal, sunken when pushed) */
uint32_t hi = pushed ? 0xFF222222 : 0xFFDDDDDD;
uint32_t lo = pushed ? 0xFFDDDDDD : 0xFF222222;
for (int x = 0; x < bw; x++) { dst[x] = hi; dst[(bh-1) * dst_stride + x] = lo; }
for (int y = 0; y < bh; y++) { dst[y * dst_stride] = hi; dst[y * dst_stride + bw - 1] = lo; }
/* Blit icon centered, using fill_fg color for opaque pixels */
int ix = (bw - icon->width) / 2 + (pushed ? 1 : 0); int ix = (bw - icon->width) / 2 + (pushed ? 1 : 0);
int iy = (bh - icon->height) / 2 + (pushed ? 1 : 0); int iy = (bh - icon->height) / 2 + (pushed ? 1 : 0);
@ -7639,19 +7653,13 @@ static void wl_frame_paint_button(WCoreWindow *button, WTexture *texture,
for (int x = 0; x < icon->width; x++) { for (int x = 0; x < icon->width; x++) {
int dx = ix + x; int dx = ix + x;
if (dx < 0 || dx >= bw) continue; if (dx < 0 || dx >= bw) continue;
unsigned char r, g, b, a; unsigned char a;
if (icon->format == RRGBAFormat) { if (icon->format == RRGBAFormat)
int off = (y * icon->width + x) * 4; a = icon->data[(y * icon->width + x) * 4 + 3];
r = icon->data[off]; g = icon->data[off+1]; else
b = icon->data[off+2]; a = icon->data[off+3]; a = 255;
} else {
int off = (y * icon->width + x) * 3;
r = icon->data[off]; g = icon->data[off+1];
b = icon->data[off+2]; a = 255;
}
if (a == 0) continue; if (a == 0) continue;
dst_row[dx] = ((uint32_t)a << 24) | ((uint32_t)r << 16) | dst_row[dx] = fill_fg;
((uint32_t)g << 8) | (uint32_t)b;
} }
} }