]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Replace multi_rect with lab_scene_rect
authortokyo4j <hrak1529@gmail.com>
Mon, 9 Jun 2025 07:27:17 +0000 (16:27 +0900)
committerHiroaki Yamamoto <hrak1529@gmail.com>
Mon, 9 Jun 2025 21:03:03 +0000 (06:03 +0900)
lab_scene_rect accepts the arbitrary number of borders and a background
color.

12 files changed:
include/common/graphic-helpers.h
include/common/lab-scene-rect.h [new file with mode: 0644]
include/labwc.h
include/overlay.h
include/view.h
src/common/graphic-helpers.c
src/common/lab-scene-rect.c [new file with mode: 0644]
src/common/meson.build
src/debug.c
src/osd.c
src/overlay.c
src/resize-outlines.c

index 067da644ea39e9b52ec6e4c72ae51913639afaae..e1986d4ec0701373efcb3077ed4f38868ffe221b 100644 (file)
@@ -3,41 +3,9 @@
 #define LABWC_GRAPHIC_HELPERS_H
 
 #include <cairo.h>
-#include <wayland-server-core.h>
 
-struct wlr_scene_tree;
-struct wlr_scene_rect;
 struct wlr_fbox;
 
-struct multi_rect {
-       struct wlr_scene_tree *tree;
-       int line_width; /* read-only */
-
-       /* Private */
-       struct wlr_scene_rect *top[3];
-       struct wlr_scene_rect *bottom[3];
-       struct wlr_scene_rect *left[3];
-       struct wlr_scene_rect *right[3];
-       struct wl_listener destroy;
-};
-
-/**
- * Create a new multi_rect.
- * A multi_rect consists of 3 nested rectangular outlines.
- * Each of the rectangular outlines is using the same @line_width
- * but its own color based on the @colors argument.
- *
- * The multi-rect can be positioned by positioning multi_rect->tree->node.
- *
- * It can be destroyed by destroying its tree node (or one of its
- * parent nodes). Once the tree node has been destroyed the struct
- * will be free'd automatically.
- */
-struct multi_rect *multi_rect_create(struct wlr_scene_tree *parent,
-               float *colors[3], int line_width);
-
-void multi_rect_set_size(struct multi_rect *rect, int width, int height);
-
 /**
  * Sets the cairo color.
  * Splits a float[4] single color array into its own arguments
diff --git a/include/common/lab-scene-rect.h b/include/common/lab-scene-rect.h
new file mode 100644 (file)
index 0000000..5005fbb
--- /dev/null
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef LABWC_LAB_SCENE_RECT_H
+#define LABWC_LAB_SCENE_RECT_H
+#include <wayland-server-core.h>
+
+struct wlr_scene_tree;
+
+struct lab_scene_rect_options {
+       float **border_colors;
+       int nr_borders;
+       int border_width;
+       float *bg_color; /* can be NULL */
+       int width;
+       int height;
+};
+
+struct lab_scene_rect {
+       struct wlr_scene_tree *tree;
+       int border_width;
+       int nr_borders;
+       struct border_scene *borders;
+       struct wlr_scene_rect *fill;
+
+       struct wl_listener node_destroy;
+};
+
+/**
+ * Create a new rectangle with borders.
+ *
+ * The rectangle can be positioned by positioning border_rect->tree->node.
+ *
+ * It can be destroyed by destroying its tree node (or one of its parent nodes).
+ * Once the tree node has been destroyed the struct will be free'd automatically.
+ */
+struct lab_scene_rect *lab_scene_rect_create(struct wlr_scene_tree *parent,
+       struct lab_scene_rect_options *opts);
+
+void lab_scene_rect_set_size(struct lab_scene_rect *rect, int width, int height);
+
+#endif /* LABWC_LAB_SCENE_RECT_H */
index 837ebc74c3007a45d0d9f007f79f6afd30b850c5..af4511402356b4b9c7ff3a46183a6096dfbae18d 100644 (file)
@@ -392,7 +392,7 @@ struct server {
                struct wlr_scene_node *preview_node;
                struct wlr_scene_tree *preview_parent;
                struct wlr_scene_node *preview_anchor;
-               struct multi_rect *preview_outline;
+               struct lab_scene_rect *preview_outline;
        } osd_state;
 
        struct theme *theme;
index ebcaabccd0c1eb400a370fea6afffb95b7b207a2..6a0ee0206cf8a972e9c0fafcb00147d326b03550 100644 (file)
@@ -7,6 +7,7 @@
 #include "regions.h"
 #include "view.h"
 
+/* TODO: replace this with single lab_scene_rect */
 struct overlay_rect {
        struct wlr_scene_tree *tree;
 
@@ -14,7 +15,7 @@ struct overlay_rect {
        struct wlr_scene_rect *bg_rect;
 
        bool border_enabled;
-       struct multi_rect *border_rect;
+       struct lab_scene_rect *border_rect;
 };
 
 struct overlay {
index 613f9160a5abcd5bbb21bd61fa1f80b66054d641..cf0c0471ba55181b254e60be8555a10ee3d04657 100644 (file)
@@ -264,7 +264,7 @@ struct view {
        } resize_indicator;
        struct resize_outlines {
                struct wlr_box view_geo;
-               struct multi_rect *rect;
+               struct lab_scene_rect *rect;
        } resize_outlines;
 
        struct mappable mappable;
index 4739b899778bc48c55669043b3576bbc731d1667..29ba8ddbcbd2534f158fa4511b4e6eaa249e3cb5 100644 (file)
@@ -1,85 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
-#include <assert.h>
 #include <cairo.h>
-#include <stdlib.h>
-#include <string.h>
 #include <wlr/types/wlr_scene.h>
-#include <wlr/util/box.h>
-#include "buffer.h"
 #include "common/graphic-helpers.h"
-#include "common/macros.h"
-#include "common/mem.h"
-
-static void
-multi_rect_destroy_notify(struct wl_listener *listener, void *data)
-{
-       struct multi_rect *rect = wl_container_of(listener, rect, destroy);
-       wl_list_remove(&rect->destroy.link);
-       free(rect);
-}
-
-struct multi_rect *
-multi_rect_create(struct wlr_scene_tree *parent, float *colors[3], int line_width)
-{
-       struct multi_rect *rect = znew(*rect);
-       rect->line_width = line_width;
-       rect->tree = wlr_scene_tree_create(parent);
-       rect->destroy.notify = multi_rect_destroy_notify;
-       wl_signal_add(&rect->tree->node.events.destroy, &rect->destroy);
-       for (size_t i = 0; i < 3; i++) {
-               rect->top[i] = wlr_scene_rect_create(rect->tree, 0, 0, colors[i]);
-               rect->right[i] = wlr_scene_rect_create(rect->tree, 0, 0, colors[i]);
-               rect->bottom[i] = wlr_scene_rect_create(rect->tree, 0, 0, colors[i]);
-               rect->left[i] = wlr_scene_rect_create(rect->tree, 0, 0, colors[i]);
-               wlr_scene_node_set_position(&rect->top[i]->node,
-                       i * line_width, i * line_width);
-               wlr_scene_node_set_position(&rect->left[i]->node,
-                       i * line_width, (i + 1) * line_width);
-       }
-       return rect;
-}
-
-void
-multi_rect_set_size(struct multi_rect *rect, int width, int height)
-{
-       assert(rect);
-       int line_width = rect->line_width;
-
-       /*
-        * The outmost outline is drawn like below:
-        *
-        * |--width--|
-        *
-        * +---------+  ---
-        * +-+-----+-+   |
-        * | |     | | height
-        * | |     | |   |
-        * +-+-----+-+   |
-        * +---------+  ---
-        */
-       for (int i = 0; i < 3; i++) {
-               /* Reposition, top and left don't ever change */
-               wlr_scene_node_set_position(&rect->right[i]->node,
-                       width - (i + 1) * line_width, (i + 1) * line_width);
-               wlr_scene_node_set_position(&rect->bottom[i]->node,
-                       i * line_width, height - (i + 1) * line_width);
-
-               /* Update sizes */
-               wlr_scene_rect_set_size(rect->top[i],
-                       MAX(width - i * line_width * 2, 0),
-                       line_width);
-               wlr_scene_rect_set_size(rect->bottom[i],
-                       MAX(width - i * line_width * 2, 0),
-                       line_width);
-               wlr_scene_rect_set_size(rect->left[i],
-                       line_width,
-                       MAX(height - (i + 1) * line_width * 2, 0));
-               wlr_scene_rect_set_size(rect->right[i],
-                       line_width,
-                       MAX(height - (i + 1) * line_width * 2, 0));
-       }
-}
 
 /* Draws a border with a specified line width */
 void
diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c
new file mode 100644 (file)
index 0000000..bc23422
--- /dev/null
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <assert.h>
+#include <wlr/types/wlr_scene.h>
+#include "common/lab-scene-rect.h"
+#include "common/mem.h"
+
+struct border_scene {
+       struct wlr_scene_tree *tree;
+       struct wlr_scene_rect *top, *bottom, *left, *right;
+};
+
+static void
+handle_node_destroy(struct wl_listener *listener, void *data)
+{
+       struct lab_scene_rect *rect = wl_container_of(listener, rect, node_destroy);
+       wl_list_remove(&rect->node_destroy.link);
+       free(rect->borders);
+       free(rect);
+}
+
+struct lab_scene_rect *
+lab_scene_rect_create(struct wlr_scene_tree *parent,
+               struct lab_scene_rect_options *opts)
+{
+       struct lab_scene_rect *rect = znew(*rect);
+       rect->border_width = opts->border_width;
+       rect->nr_borders = opts->nr_borders;
+       rect->borders = znew_n(rect->borders[0], opts->nr_borders);
+       rect->tree = wlr_scene_tree_create(parent);
+
+       if (opts->bg_color) {
+               rect->fill = wlr_scene_rect_create(rect->tree, 0, 0, opts->bg_color);
+       }
+
+       for (int i = 0; i < rect->nr_borders; i++) {
+               struct border_scene *border = &rect->borders[i];
+               float *color = opts->border_colors[i];
+               border->tree = wlr_scene_tree_create(rect->tree);
+               border->top = wlr_scene_rect_create(border->tree, 0, 0, color);
+               border->right = wlr_scene_rect_create(border->tree, 0, 0, color);
+               border->bottom = wlr_scene_rect_create(border->tree, 0, 0, color);
+               border->left = wlr_scene_rect_create(border->tree, 0, 0, color);
+       }
+
+       rect->node_destroy.notify = handle_node_destroy;
+       wl_signal_add(&rect->tree->node.events.destroy, &rect->node_destroy);
+
+       lab_scene_rect_set_size(rect, opts->width, opts->height);
+
+       return rect;
+}
+
+static void
+resize_border(struct border_scene *border, int border_width, int width, int height)
+{
+       /*
+        * The border is drawn like below:
+        *
+        * <--width-->
+        * +---------+   ^
+        * +-+-----+-+   |
+        * | |     | | height
+        * | |     | |   |
+        * +-+-----+-+   |
+        * +---------+   v
+        */
+
+       if ((width < border_width * 2) || (height < border_width * 2)) {
+               wlr_scene_node_set_enabled(&border->tree->node, false);
+               return;
+       }
+       wlr_scene_node_set_enabled(&border->tree->node, true);
+
+       wlr_scene_node_set_position(&border->top->node, 0, 0);
+       wlr_scene_node_set_position(&border->bottom->node, 0, height - border_width);
+       wlr_scene_node_set_position(&border->left->node, 0, border_width);
+       wlr_scene_node_set_position(&border->right->node, width - border_width, border_width);
+
+       wlr_scene_rect_set_size(border->top, width, border_width);
+       wlr_scene_rect_set_size(border->bottom, width, border_width);
+       wlr_scene_rect_set_size(border->left, border_width, height - border_width * 2);
+       wlr_scene_rect_set_size(border->right, border_width, height - border_width * 2);
+}
+
+void
+lab_scene_rect_set_size(struct lab_scene_rect *rect, int width, int height)
+{
+       assert(rect);
+       int border_width = rect->border_width;
+
+       for (int i = 0; i < rect->nr_borders; i++) {
+               struct border_scene *border = &rect->borders[i];
+               resize_border(border, border_width,
+                       width - 2 * border_width * i,
+                       height - 2 * border_width * i);
+               wlr_scene_node_set_position(&border->tree->node,
+                       i * border_width, i * border_width);
+       }
+
+       if (rect->fill) {
+               wlr_scene_rect_set_size(rect->fill, width, height);
+       }
+}
index 15910f327020c4dfd5d5e3657e0d9c9aa2dd4b47..74dd6ef66c90cd157a1194223674f3d41d9113c4 100644 (file)
@@ -8,6 +8,7 @@ labwc_sources += files(
   'font.c',
   'grab-file.c',
   'graphic-helpers.c',
+  'lab-scene-rect.c',
   'match.c',
   'mem.c',
   'nodename.c',
index 43ae0c0657f5cebceb27d735ed29c92b78094220..4123187b60e337d8eebe57b6bafb93846e3ab2d4 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 #include <wlr/types/wlr_layer_shell_v1.h>
 #include <wlr/types/wlr_scene.h>
-#include "common/graphic-helpers.h"
+#include "common/lab-scene-rect.h"
 #include "common/scene-helpers.h"
 #include "common/string-helpers.h"
 #include "debug.h"
@@ -220,11 +220,11 @@ dump_tree(struct server *server, struct wlr_scene_node *node,
        }
        printf("%.*s %*c %4d  %4d  [%p]\n", max_width - 1, type, padding, ' ', x, y, node);
 
-       struct multi_rect *osd_preview_outline =
+       struct lab_scene_rect *osd_preview_outline =
                server->osd_state.preview_outline;
-       struct multi_rect *region_snapping_overlay_outline =
+       struct lab_scene_rect *region_snapping_overlay_outline =
                server->seat.overlay.region_rect.border_rect;
-       struct multi_rect *edge_snapping_overlay_outline =
+       struct lab_scene_rect *edge_snapping_overlay_outline =
                server->seat.overlay.edge_rect.border_rect;
        if ((IGNORE_MENU && node == &server->menu_tree->node)
                        || (IGNORE_SSD && last_view
index 45b4b2de54139c5ba00182bb26fad49b89cebefb..7348af8b9ab0d6d00f7a820878b74a43a645ec58 100644 (file)
--- a/src/osd.c
+++ b/src/osd.c
@@ -6,6 +6,7 @@
 #include "common/array.h"
 #include "common/buf.h"
 #include "common/font.h"
+#include "common/lab-scene-rect.h"
 #include "common/macros.h"
 #include "common/scaled-font-buffer.h"
 #include "common/scaled-icon-buffer.h"
@@ -46,21 +47,25 @@ osd_update_preview_outlines(struct view *view)
 {
        /* Create / Update preview outline tree */
        struct server *server = view->server;
-       struct multi_rect *rect = view->server->osd_state.preview_outline;
+       struct theme *theme = server->theme;
+       struct lab_scene_rect *rect = view->server->osd_state.preview_outline;
        if (!rect) {
-               int line_width = server->theme->osd_window_switcher_preview_border_width;
-               float *colors[] = {
-                       server->theme->osd_window_switcher_preview_border_color[0],
-                       server->theme->osd_window_switcher_preview_border_color[1],
-                       server->theme->osd_window_switcher_preview_border_color[2],
+               struct lab_scene_rect_options opts = {
+                       .border_colors = (float *[3]) {
+                               theme->osd_window_switcher_preview_border_color[0],
+                               theme->osd_window_switcher_preview_border_color[1],
+                               theme->osd_window_switcher_preview_border_color[2],
+                       },
+                       .nr_borders = 3,
+                       .border_width = theme->osd_window_switcher_preview_border_width,
                };
-               rect = multi_rect_create(&server->scene->tree, colors, line_width);
+               rect = lab_scene_rect_create(&server->scene->tree, &opts);
                wlr_scene_node_place_above(&rect->tree->node, &server->menu_tree->node);
                server->osd_state.preview_outline = rect;
        }
 
        struct wlr_box geo = ssd_max_extents(view);
-       multi_rect_set_size(rect, geo.width, geo.height);
+       lab_scene_rect_set_size(rect, geo.width, geo.height);
        wlr_scene_node_set_position(&rect->tree->node, geo.x, geo.y);
 }
 
index ba2cab3b2da38f3509cbe5ed88e16f064ef76a55..354f5ad97e6e6705bee41b7284331f0c0fba3d7e 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 #include <assert.h>
+#include "common/lab-scene-rect.h"
 #include "labwc.h"
 #include "overlay.h"
 #include "view.h"
@@ -23,13 +24,16 @@ create_overlay_rect(struct seat *seat, struct overlay_rect *rect,
 
        if (rect->border_enabled) {
                /* Create outlines */
-               float *colors[3] = {
-                       theme->border_color[0],
-                       theme->border_color[1],
-                       theme->border_color[2],
+               struct lab_scene_rect_options opts = {
+                       .border_colors = (float *[3]) {
+                               theme->border_color[0],
+                               theme->border_color[1],
+                               theme->border_color[2],
+                       },
+                       .nr_borders = 3,
+                       .border_width = theme->border_width,
                };
-               rect->border_rect = multi_rect_create(
-                       rect->tree, colors, theme->border_width);
+               rect->border_rect = lab_scene_rect_create(rect->tree, &opts);
        }
 
        wlr_scene_node_set_enabled(&rect->tree->node, false);
@@ -67,7 +71,7 @@ show_overlay(struct seat *seat, struct overlay_rect *rect, struct wlr_box *box)
                wlr_scene_rect_set_size(rect->bg_rect, box->width, box->height);
        }
        if (rect->border_enabled) {
-               multi_rect_set_size(rect->border_rect, box->width, box->height);
+               lab_scene_rect_set_size(rect->border_rect, box->width, box->height);
        }
 
        struct wlr_scene_node *node = &rect->tree->node;
index fbb10c73ad890664b09b1f25a1c798d828bc7ca4..9186bc6f32ccb932264ee1d74362073c708034f8 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
 #include <wlr/types/wlr_scene.h>
-#include "common/graphic-helpers.h"
+#include "common/lab-scene-rect.h"
 #include "ssd.h"
 #include "resize-outlines.h"
 #include "labwc.h"
@@ -19,14 +19,16 @@ resize_outlines_update(struct view *view, struct wlr_box new_geo)
        struct resize_outlines *outlines = &view->resize_outlines;
 
        if (!outlines->rect) {
-               float *colors[3] = {
-                       view->server->theme->osd_bg_color,
-                       view->server->theme->osd_label_text_color,
-                       view->server->theme->osd_bg_color,
+               struct lab_scene_rect_options opts = {
+                       .border_colors = (float *[3]) {
+                               view->server->theme->osd_bg_color,
+                               view->server->theme->osd_label_text_color,
+                               view->server->theme->osd_bg_color,
+                       },
+                       .nr_borders = 3,
+                       .border_width = 1,
                };
-               int width = 1;
-               outlines->rect = multi_rect_create(
-                       view->scene_tree, colors, width);
+               outlines->rect = lab_scene_rect_create(view->scene_tree, &opts);
        }
 
        struct border margin = ssd_get_margin(view->ssd);
@@ -36,7 +38,7 @@ resize_outlines_update(struct view *view, struct wlr_box new_geo)
                .width = new_geo.width + margin.left + margin.right,
                .height = new_geo.height + margin.top + margin.bottom,
        };
-       multi_rect_set_size(outlines->rect, box.width, box.height);
+       lab_scene_rect_set_size(outlines->rect, box.width, box.height);
        wlr_scene_node_set_position(&outlines->rect->tree->node,
                box.x - view->current.x, box.y - view->current.y);
        wlr_scene_node_set_enabled(