fix: enable titlebar button scene_bufs for click and visibility
Buttons were rendered into the titlebar buffer with their own scene_buf nodes disabled. This made them invisible to wlr_scene_node_at and required a fragile coordinate-based hit-test (frame_buf_button_at). Switch to rendering each button into its own frame_buf image and enabling its scene_buf node. This makes buttons: - Visible as independent scene nodes - Directly hittable by wlr_scene_node_at - Properly clickable via the normal frame_buf_at path Update frame_buf_button_at to use a size threshold (<=30px) instead of the disabled-node check to identify button sub-windows.
This commit is contained in:
parent
9ed1c19d6b
commit
0cf867d548
|
|
@ -3975,7 +3975,9 @@ frame_buf_button_at(int px, int py)
|
||||||
wl_list_for_each(fb, &wl_state.frame_list, link) {
|
wl_list_for_each(fb, &wl_state.frame_list, link) {
|
||||||
if (!fb->parent_id) continue; /* top-level root */
|
if (!fb->parent_id) continue; /* top-level root */
|
||||||
if (!fb->scene_buf) continue; /* no scene node */
|
if (!fb->scene_buf) continue; /* no scene node */
|
||||||
if (fb->scene_buf->node.enabled) continue; /* visible node — titlebar/resizebar */
|
/* Buttons are small children of the titlebar with enabled scene_bufs.
|
||||||
|
* Skip large nodes (titlebars, resizebars) by size threshold. */
|
||||||
|
if (fb->width > 30 || fb->height > 30) continue;
|
||||||
if (px < fb->x || px >= fb->x + fb->width) continue;
|
if (px < fb->x || px >= fb->x + fb->width) continue;
|
||||||
if (py < fb->y || py >= fb->y + fb->height) continue;
|
if (py < fb->y || py >= fb->y + fb->height) continue;
|
||||||
/* Prefer the smallest (most specific) enclosing fb. */
|
/* Prefer the smallest (most specific) enclosing fb. */
|
||||||
|
|
@ -7584,16 +7586,10 @@ static void wl_frame_paint_button(WCoreWindow *button, WTexture *texture,
|
||||||
if (!fwin || !fwin->core)
|
if (!fwin || !fwin->core)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct wl_frame_buf *frame_fb = frame_buf_find(fwin->core->window);
|
|
||||||
struct wl_frame_buf *tb_fb = fwin->titlebar ? frame_buf_find(fwin->titlebar->window) : NULL;
|
|
||||||
struct wl_frame_buf *btn_fb = frame_buf_find(button->window);
|
struct wl_frame_buf *btn_fb = frame_buf_find(button->window);
|
||||||
/* Render into titlebar buffer if available, else frame buffer */
|
if (!btn_fb || !btn_fb->image)
|
||||||
struct wl_frame_buf *target = (tb_fb && tb_fb->image) ? tb_fb : frame_fb;
|
|
||||||
if (!target || !target->image || !btn_fb)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int bx = btn_fb->rel_x;
|
|
||||||
int by = btn_fb->rel_y;
|
|
||||||
int bw = btn_fb->width;
|
int bw = btn_fb->width;
|
||||||
int bh = btn_fb->height;
|
int bh = btn_fb->height;
|
||||||
|
|
||||||
|
|
@ -7613,19 +7609,36 @@ static void wl_frame_paint_button(WCoreWindow *button, WTexture *texture,
|
||||||
if (!icon)
|
if (!icon)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Clear button buffer with titlebar background */
|
||||||
|
struct wl_frame_buf *tb_fb = fwin->titlebar ? frame_buf_find(fwin->titlebar->window) : NULL;
|
||||||
|
uint32_t bg_pixel = 0xFF333333;
|
||||||
|
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);
|
||||||
|
int tb_stride = pixman_image_get_stride(tb_fb->image) / 4;
|
||||||
|
int sample_y = btn_fb->rel_y + bh / 2;
|
||||||
|
int sample_x = btn_fb->rel_x + bw / 2;
|
||||||
|
if (sample_y >= 0 && sample_y < tb_fb->height &&
|
||||||
|
sample_x >= 0 && sample_x < tb_fb->width)
|
||||||
|
bg_pixel = tb_data[sample_y * tb_stride + sample_x];
|
||||||
|
}
|
||||||
|
uint32_t *dst = pixman_image_get_data(btn_fb->image);
|
||||||
|
int dst_stride = pixman_image_get_stride(btn_fb->image) / 4;
|
||||||
|
for (int y = 0; y < bh; y++)
|
||||||
|
for (int x = 0; x < bw; x++)
|
||||||
|
dst[y * dst_stride + x] = bg_pixel;
|
||||||
|
|
||||||
/* Blit icon centered in button area */
|
/* Blit icon centered in button area */
|
||||||
uint32_t *dst = pixman_image_get_data(target->image);
|
int ix = (bw - icon->width) / 2 + (pushed ? 1 : 0);
|
||||||
int dst_stride = pixman_image_get_stride(target->image) / 4;
|
int iy = (bh - icon->height) / 2 + (pushed ? 1 : 0);
|
||||||
int ix = bx + (bw - icon->width) / 2 + (pushed ? 1 : 0);
|
|
||||||
int iy = by + (bh - icon->height) / 2 + (pushed ? 1 : 0);
|
|
||||||
|
|
||||||
for (int y = 0; y < icon->height; y++) {
|
for (int y = 0; y < icon->height; y++) {
|
||||||
int dy = iy + y;
|
int dy = iy + y;
|
||||||
if (dy < 0 || dy >= target->height) continue;
|
if (dy < 0 || dy >= bh) continue;
|
||||||
uint32_t *dst_row = dst + dy * dst_stride;
|
uint32_t *dst_row = dst + dy * dst_stride;
|
||||||
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 >= target->width) continue;
|
if (dx < 0 || dx >= bw) continue;
|
||||||
unsigned char r, g, b, a;
|
unsigned char r, g, b, a;
|
||||||
if (icon->format == RRGBAFormat) {
|
if (icon->format == RRGBAFormat) {
|
||||||
int off = (y * icon->width + x) * 4;
|
int off = (y * icon->width + x) * 4;
|
||||||
|
|
@ -7636,14 +7649,15 @@ static void wl_frame_paint_button(WCoreWindow *button, WTexture *texture,
|
||||||
r = icon->data[off]; g = icon->data[off+1];
|
r = icon->data[off]; g = icon->data[off+1];
|
||||||
b = icon->data[off+2]; a = 255;
|
b = icon->data[off+2]; a = 255;
|
||||||
}
|
}
|
||||||
if (a == 0) continue; /* transparent */
|
if (a == 0) continue;
|
||||||
dst_row[dx] = ((uint32_t)a << 24) | ((uint32_t)r << 16) |
|
dst_row[dx] = ((uint32_t)a << 24) | ((uint32_t)r << 16) |
|
||||||
((uint32_t)g << 8) | (uint32_t)b;
|
((uint32_t)g << 8) | (uint32_t)b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->scene_buf)
|
/* Enable and commit the button's own scene_buf */
|
||||||
wlr_scene_buffer_set_buffer(target->scene_buf, &target->base);
|
wlr_scene_buffer_set_buffer(btn_fb->scene_buf, &btn_fb->base);
|
||||||
|
wlr_scene_node_set_enabled(&btn_fb->scene_buf->node, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wl_noop_netwm_init(WScreen *scr) { (void)scr; }
|
static void wl_noop_netwm_init(WScreen *scr) { (void)scr; }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue