From 97ce4131bbef7c1365e501dcdd1551ce95df5ee5 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Mon, 9 Jun 2025 16:28:34 +0900 Subject: [PATCH] Replace scaled_rect_buffer with lab_scene_rect This fixes the gap between menu items and the menu border in an output with a fractional scale due to the semantic gap between cairo and wlroots's position-independent scene renderer. --- include/common/scaled-rect-buffer.h | 31 -------- src/common/meson.build | 1 - src/common/scaled-rect-buffer.c | 116 ---------------------------- src/menu/menu.c | 19 +++-- src/osd.c | 36 +++++---- 5 files changed, 33 insertions(+), 170 deletions(-) delete mode 100644 include/common/scaled-rect-buffer.h delete mode 100644 src/common/scaled-rect-buffer.c diff --git a/include/common/scaled-rect-buffer.h b/include/common/scaled-rect-buffer.h deleted file mode 100644 index 47059828..00000000 --- a/include/common/scaled-rect-buffer.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef LABWC_SCALED_RECT_BUFFER_H -#define LABWC_SCALED_RECT_BUFFER_H - -#include - -struct wlr_scene_tree; -struct wlr_scene_buffer; -struct scaled_scene_buffer; - -struct scaled_rect_buffer { - struct wlr_scene_buffer *scene_buffer; - struct scaled_scene_buffer *scaled_buffer; - int width; - int height; - int border_width; - float fill_color[4]; - float border_color[4]; -}; - -/* - * Create an auto scaling borderd-rectangle buffer, providing a wlr_scene_buffer - * node for display. It gets destroyed automatically when the backing - * scaled_scene_buffer is being destroyed which in turn happens automatically - * when the backing wlr_scene_buffer (or one of its parents) is being destroyed. - */ -struct scaled_rect_buffer *scaled_rect_buffer_create( - struct wlr_scene_tree *parent, int width, int height, int border_width, - float fill_color[4], float border_color[4]); - -#endif /* LABWC_SCALED_RECT_BUFFER_H */ diff --git a/src/common/meson.build b/src/common/meson.build index 74dd6ef6..1e226297 100644 --- a/src/common/meson.build +++ b/src/common/meson.build @@ -17,7 +17,6 @@ labwc_sources += files( 'scaled-font-buffer.c', 'scaled-icon-buffer.c', 'scaled-img-buffer.c', - 'scaled-rect-buffer.c', 'scaled-scene-buffer.c', 'scene-helpers.c', 'set.c', diff --git a/src/common/scaled-rect-buffer.c b/src/common/scaled-rect-buffer.c deleted file mode 100644 index 318176c4..00000000 --- a/src/common/scaled-rect-buffer.c +++ /dev/null @@ -1,116 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -#define _POSIX_C_SOURCE 200809L -#include -#include -#include -#include -#include -#include "buffer.h" -#include "common/graphic-helpers.h" -#include "common/macros.h" -#include "common/mem.h" -#include "common/scaled-scene-buffer.h" -#include "common/scaled-rect-buffer.h" - -static void -draw_rectangle_path(cairo_t *cairo, int width, int height, int border_width) -{ - double offset = border_width / 2.0; - double right_x = width - offset; - double bottom_y = height - offset; - - cairo_move_to(cairo, offset, offset); - cairo_line_to(cairo, right_x, offset); - cairo_line_to(cairo, right_x, bottom_y); - cairo_line_to(cairo, offset, bottom_y); - cairo_close_path(cairo); -} - -static struct lab_data_buffer * -_create_buffer(struct scaled_scene_buffer *scaled_buffer, double scale) -{ - struct scaled_rect_buffer *self = scaled_buffer->data; - struct lab_data_buffer *buffer = buffer_create_cairo( - self->width, self->height, scale); - if (!buffer) { - return NULL; - } - - cairo_t *cairo = cairo_create(buffer->surface); - - /* Clear background */ - cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); - cairo_paint(cairo); - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - - /* Fill rectangle */ - draw_rectangle_path(cairo, self->width, self->height, 0); - set_cairo_color(cairo, self->fill_color); - cairo_fill(cairo); - - /* Draw borders */ - draw_rectangle_path(cairo, self->width, self->height, - self->border_width); - cairo_set_line_width(cairo, self->border_width); - set_cairo_color(cairo, self->border_color); - cairo_stroke(cairo); - - cairo_surface_flush(buffer->surface); - cairo_destroy(cairo); - - return buffer; -} - -static void -_destroy(struct scaled_scene_buffer *scaled_buffer) -{ - struct scaled_rect_buffer *self = scaled_buffer->data; - scaled_buffer->data = NULL; - free(self); -} - -static bool -_equal(struct scaled_scene_buffer *scaled_buffer_a, struct scaled_scene_buffer *scaled_buffer_b) -{ - struct scaled_rect_buffer *a = scaled_buffer_a->data; - struct scaled_rect_buffer *b = scaled_buffer_b->data; - - return a->width == b->width - && a->height == b->height - && a->border_width == b->border_width - && !memcmp(a->fill_color, b->fill_color, sizeof(a->fill_color)) - && !memcmp(a->border_color, b->border_color, sizeof(a->border_color)); -} - -static const struct scaled_scene_buffer_impl impl = { - .create_buffer = _create_buffer, - .destroy = _destroy, - .equal = _equal, -}; - -struct scaled_rect_buffer *scaled_rect_buffer_create( - struct wlr_scene_tree *parent, int width, int height, int border_width, - float fill_color[4], float border_color[4]) -{ - /* TODO: support rounded corners for menus and OSDs */ - - assert(parent); - assert(width >= 0 && height >= 0); - - struct scaled_rect_buffer *self = znew(*self); - struct scaled_scene_buffer *scaled_buffer = scaled_scene_buffer_create( - parent, &impl, /* drop_buffer */ true); - scaled_buffer->data = self; - self->scaled_buffer = scaled_buffer; - self->scene_buffer = scaled_buffer->scene_buffer; - self->width = width; - self->height = height; - self->border_width = border_width; - memcpy(self->fill_color, fill_color, sizeof(self->fill_color)); - memcpy(self->border_color, border_color, sizeof(self->border_color)); - - scaled_scene_buffer_request_update(scaled_buffer, - self->width, self->height); - - return self; -} diff --git a/src/menu/menu.c b/src/menu/menu.c index 0c2d0c3d..3a4c6b2b 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -15,13 +15,13 @@ #include "common/buf.h" #include "common/dir.h" #include "common/font.h" +#include "common/lab-scene-rect.h" #include "common/list.h" #include "common/macros.h" #include "common/mem.h" #include "common/nodename.h" #include "common/scaled-font-buffer.h" #include "common/scaled-icon-buffer.h" -#include "common/scaled-rect-buffer.h" #include "common/scene-helpers.h" #include "common/spawn.h" #include "common/string-helpers.h" @@ -446,13 +446,16 @@ menu_create_scene(struct menu *menu) } menu->size.height = item_y + theme->menu_border_width; - float transparent[4] = {0}; - struct scaled_rect_buffer *bg_buffer = scaled_rect_buffer_create( - menu->scene_tree, menu->size.width, menu->size.height, - theme->menu_border_width, transparent, - theme->menu_border_color); - assert(bg_buffer); - wlr_scene_node_lower_to_bottom(&bg_buffer->scene_buffer->node); + struct lab_scene_rect_options opts = { + .border_colors = (float *[1]) {theme->menu_border_color}, + .nr_borders = 1, + .border_width = theme->menu_border_width, + .width = menu->size.width, + .height = menu->size.height, + }; + struct lab_scene_rect *bg_rect = + lab_scene_rect_create(menu->scene_tree, &opts); + wlr_scene_node_lower_to_bottom(&bg_rect->tree->node); } /* diff --git a/src/osd.c b/src/osd.c index 7348af8b..9213a1b3 100644 --- a/src/osd.c +++ b/src/osd.c @@ -10,7 +10,6 @@ #include "common/macros.h" #include "common/scaled-font-buffer.h" #include "common/scaled-icon-buffer.h" -#include "common/scaled-rect-buffer.h" #include "common/scene-helpers.h" #include "common/string-helpers.h" #include "config/rcxml.h" @@ -294,8 +293,15 @@ create_osd_scene(struct output *output, struct wl_array *views) float *bg_color = theme->osd_bg_color; /* Draw background */ - scaled_rect_buffer_create(output->osd_scene.tree, w, h, - theme->osd_border_width, bg_color, theme->osd_border_color); + struct lab_scene_rect_options bg_opts = { + .border_colors = (float *[1]) {theme->osd_border_color}, + .nr_borders = 1, + .border_width = theme->osd_border_width, + .bg_color = bg_color, + .width = w, + .height = h, + }; + lab_scene_rect_create(output->osd_scene.tree, &bg_opts); int y = theme->osd_border_width + theme->osd_window_switcher_padding; @@ -404,19 +410,21 @@ create_osd_scene(struct output *output, struct wl_array *views) } /* Highlight around selected window's item */ - int highlight_w = w - 2 * theme->osd_border_width - - 2 * theme->osd_window_switcher_padding; - int highlight_h = theme->osd_window_switcher_item_height; int highlight_x = theme->osd_border_width + theme->osd_window_switcher_padding; - int border_width = theme->osd_window_switcher_item_active_border_width; - float transparent[4] = {0}; - - struct scaled_rect_buffer *highlight_buffer = scaled_rect_buffer_create( - output->osd_scene.tree, highlight_w, highlight_h, - border_width, transparent, text_color); - assert(highlight_buffer); - item->highlight_outline = &highlight_buffer->scene_buffer->node; + struct lab_scene_rect_options highlight_opts = { + .border_colors = (float *[1]) {text_color}, + .nr_borders = 1, + .border_width = + theme->osd_window_switcher_item_active_border_width, + .width = w - 2 * theme->osd_border_width + - 2 * theme->osd_window_switcher_padding, + .height = theme->osd_window_switcher_item_height, + }; + + struct lab_scene_rect *highlight_rect = lab_scene_rect_create( + output->osd_scene.tree, &highlight_opts); + item->highlight_outline = &highlight_rect->tree->node; wlr_scene_node_set_position(item->highlight_outline, highlight_x, y); wlr_scene_node_set_enabled(item->highlight_outline, false); -- 2.52.0