From 7897807941a92141226084f6649c4f26e6bf2810 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Mon, 23 Mar 2026 20:43:26 -0700 Subject: [PATCH 01/47] Draw beveled windowed borders, inspired by jlindgren https://github.com/labwc/labwc/pull/3382/files --- include/ssd-internal.h | 1 + src/ssd/ssd-border.c | 204 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 187 insertions(+), 18 deletions(-) diff --git a/include/ssd-internal.h b/include/ssd-internal.h index 600b9076..de91d558 100644 --- a/include/ssd-internal.h +++ b/include/ssd-internal.h @@ -115,6 +115,7 @@ struct ssd { struct ssd_border_subtree { struct wlr_scene_tree *tree; struct wlr_scene_rect *top, *bottom, *left, *right; + struct wlr_scene_buffer *tlcorner, *trcorner, *blcorner, *brcorner, *ttexture, *btexture, *ltexture, *rtexture; } subtrees[2]; /* indexed by enum ssd_active_state */ } border; diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index c2c99f8d..5083c0be 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -2,14 +2,16 @@ #include #include +#include "buffer.h" #include "common/macros.h" +#include "common/mem.h" #include "common/scene-helpers.h" #include "config/rcxml.h" #include "ssd.h" #include "ssd-internal.h" #include "theme.h" #include "view.h" - +#include "stdio.h" void ssd_border_create(struct ssd *ssd) { @@ -18,6 +20,7 @@ ssd_border_create(struct ssd *ssd) struct view *view = ssd->view; struct theme *theme = rc.theme; + int bw = theme->border_width; int width = view->current.width; int height = view_effective_height(view, /* use_pending */ false); int full_width = width + 2 * theme->border_width; @@ -26,6 +29,7 @@ ssd_border_create(struct ssd *ssd) ssd->border.tree = lab_wlr_scene_tree_create(ssd->tree); wlr_scene_node_set_position(&ssd->border.tree->node, -theme->border_width, 0); +printf("At 32\n"); enum ssd_active_state active; FOR_EACH_ACTIVE_STATE(active) { struct ssd_border_subtree *subtree = &ssd->border.subtrees[active]; @@ -34,6 +38,90 @@ ssd_border_create(struct ssd *ssd) wlr_scene_node_set_enabled(&parent->node, active); float *color = theme->window[active].border_color; + /* From Pull request 3382 */ + uint8_t r = color[0] * 255; + uint8_t g = color[1] * 255; + uint8_t b = color[2] * 255; + uint8_t a = color[3] * 255; + + /* highlight */ + uint8_t r1 = MIN(r * 5 / 4, a); + uint8_t g1 = MIN(g * 5 / 4, a); + uint8_t b1 = MIN(b * 5 / 4, a); + + /* darker outline */ + uint8_t r0 = r / 2; + uint8_t g0 = g / 2; + uint8_t b0 = b / 2; + + uint32_t col = ((uint32_t)a << 24) | ((uint32_t)r << 16) + | ((uint32_t)g << 8) | b; + uint32_t col0 = ((uint32_t)a << 24) | ((uint32_t)r0 << 16) + | ((uint32_t)g0 << 8) | b0; + uint32_t col1 = ((uint32_t)a << 24) | ((uint32_t)r1 << 16) + | ((uint32_t)g1 << 8) | b1; + + + uint32_t *left_data = znew_n(uint32_t, bw); + uint32_t *top_data = znew_n(uint32_t, bw); + left_data[0] = top_data[0] = col1; + left_data[1] = top_data[1] = col1; + for (int i = 2; i < bw; i++) { + left_data[i] = col; + top_data[i] = col; + } + left_data[bw-1] = top_data[bw-1] = col0; + left_data[bw-2] = top_data[bw-2] = col0; + + + + uint32_t *tl_data = znew_n(uint32_t, bw*bw); + uint32_t *tr_data = znew_n(uint32_t, bw*bw); + uint32_t *bl_data = znew_n(uint32_t, bw*bw); + uint32_t *br_data = znew_n(uint32_t, bw*bw); + for (int i=0; ibw -3) { + bl_data[i*bw + j] = col0; + br_data[i*bw + j] = col0; + } + if (j<2) { + tl_data[i*bw + j] = col1; + bl_data[i*bw + j] = col1; + } + if (j>bw -3) { + tr_data[i*bw + j] = col0; + br_data[i*bw + j] = col0; + } + } + } + tl_data[bw*bw -1] = col0; + tr_data[(bw-1)*bw + (0)] = col0; + bl_data[(0)*bw + (bw-1)] = col1; + br_data[(0)*bw + (0)] = col1; + + + /* bottom and right are identical */ + uint32_t *right_data = znew_n(uint32_t, theme->border_width); + uint32_t *bottom_data = znew_n(uint32_t, theme->border_width); + right_data[0]=bottom_data[0]=col1; + right_data[1]=bottom_data[1]=col1; + for (int i = 2; i < theme->border_width - 1; i++) { + right_data[i] = col; + bottom_data[i] = col; + } + right_data[theme->border_width - 1] = bottom_data[theme->border_width - 1] = col0; + right_data[theme->border_width - 2] = bottom_data[theme->border_width - 2] = col0; + + subtree->left = lab_wlr_scene_rect_create(parent, theme->border_width, height, color); wlr_scene_node_set_position(&subtree->left->node, 0, 0); @@ -53,7 +141,61 @@ ssd_border_create(struct ssd *ssd) wlr_scene_node_set_position(&subtree->top->node, theme->border_width + corner_width, -(ssd->titlebar.height + theme->border_width)); + + + struct lab_data_buffer *ttexture_buffer = + buffer_create_from_data(top_data, 1,theme->border_width, + 4); + subtree->ttexture = wlr_scene_buffer_create(parent, &ttexture_buffer->base); + wlr_buffer_drop(&ttexture_buffer->base); + + struct lab_data_buffer *btexture_buffer = + buffer_create_from_data(bottom_data, 1,theme->border_width, + 4); + subtree->btexture = wlr_scene_buffer_create(parent, &btexture_buffer->base); + wlr_buffer_drop(&btexture_buffer->base); + + struct lab_data_buffer *ltexture_buffer = + buffer_create_from_data(left_data, theme->border_width, 1, + 4*theme->border_width); + subtree->ltexture = wlr_scene_buffer_create(parent, <exture_buffer->base); + wlr_buffer_drop(<exture_buffer->base); + struct lab_data_buffer *rtexture_buffer = + buffer_create_from_data(right_data, theme->border_width, 1, + 4*theme->border_width); + subtree->rtexture = wlr_scene_buffer_create(parent, &rtexture_buffer->base); + wlr_buffer_drop(&rtexture_buffer->base); + + + struct lab_data_buffer *tltexture_buffer = + buffer_create_from_data(tl_data, theme->border_width, theme->border_width, + 4*theme->border_width); + subtree->tlcorner = wlr_scene_buffer_create(parent, &tltexture_buffer->base); + wlr_buffer_drop(&tltexture_buffer->base); + + struct lab_data_buffer *trtexture_buffer = + buffer_create_from_data(tr_data, theme->border_width, theme->border_width, + 4*theme->border_width); + subtree->trcorner = wlr_scene_buffer_create(parent, &trtexture_buffer->base); + wlr_buffer_drop(&trtexture_buffer->base); + + + struct lab_data_buffer *bltexture_buffer = + buffer_create_from_data(bl_data, theme->border_width, theme->border_width, + 4*theme->border_width); + subtree->blcorner = wlr_scene_buffer_create(parent, &bltexture_buffer->base); + wlr_buffer_drop(&bltexture_buffer->base); + + struct lab_data_buffer *brtexture_buffer = + buffer_create_from_data(br_data, theme->border_width, theme->border_width, + 4*theme->border_width); + subtree->brcorner = wlr_scene_buffer_create(parent, &brtexture_buffer->base); + wlr_buffer_drop(&brtexture_buffer->base); + } + + + if (view->maximized == VIEW_AXIS_BOTH) { wlr_scene_node_set_enabled(&ssd->border.tree->node, false); @@ -132,26 +274,52 @@ ssd_border_update(struct ssd *ssd) enum ssd_active_state active; FOR_EACH_ACTIVE_STATE(active) { struct ssd_border_subtree *subtree = &ssd->border.subtrees[active]; + + wlr_scene_buffer_set_dest_size(subtree->ttexture, + full_width, theme->border_width); + wlr_scene_node_set_position(&subtree->ttexture->node, + 0, -(ssd->titlebar.height + theme->border_width)); + + wlr_scene_buffer_set_dest_size(subtree->rtexture, + theme->border_width, side_height+(ssd->titlebar.height + theme->border_width)); + wlr_scene_node_set_position(&subtree->rtexture->node, + theme->border_width + width, -(ssd->titlebar.height + theme->border_width)); - wlr_scene_rect_set_size(subtree->left, - theme->border_width, side_height); - wlr_scene_node_set_position(&subtree->left->node, - 0, side_y); - - wlr_scene_rect_set_size(subtree->right, - theme->border_width, side_height); - wlr_scene_node_set_position(&subtree->right->node, - theme->border_width + width, side_y); - - wlr_scene_rect_set_size(subtree->bottom, - full_width, theme->border_width); - wlr_scene_node_set_position(&subtree->bottom->node, + wlr_scene_buffer_set_dest_size(subtree->btexture, + full_width, theme->border_width); + wlr_scene_node_set_position(&subtree->btexture->node, 0, height); + + wlr_scene_buffer_set_dest_size(subtree->ltexture, + theme->border_width, side_height+(ssd->titlebar.height + theme->border_width)); + wlr_scene_node_set_position(&subtree->ltexture->node, + 0, -(ssd->titlebar.height + theme->border_width)); + + wlr_scene_buffer_set_dest_size(subtree->tlcorner, + theme->border_width, theme->border_width); + wlr_scene_node_set_position(&subtree->tlcorner->node, + 0, -(ssd->titlebar.height + theme->border_width)); - wlr_scene_rect_set_size(subtree->top, - top_width, theme->border_width); - wlr_scene_node_set_position(&subtree->top->node, - top_x, -(ssd->titlebar.height + theme->border_width)); + wlr_scene_buffer_set_dest_size(subtree->trcorner, + theme->border_width, theme->border_width); + wlr_scene_node_set_position(&subtree->trcorner->node, + theme->border_width + width, -(ssd->titlebar.height + theme->border_width)); + + + wlr_scene_buffer_set_dest_size(subtree->brcorner, + theme->border_width, theme->border_width); + wlr_scene_node_set_position(&subtree->brcorner->node, + theme->border_width + width, height); + + + wlr_scene_buffer_set_dest_size(subtree->blcorner, + theme->border_width, theme->border_width); + wlr_scene_node_set_position(&subtree->blcorner->node, + 0, height); + + + + } } From ae507e5b0d3c9f8dd2d5cc226c4ac00c2e5a69f3 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Mon, 23 Mar 2026 20:50:42 -0700 Subject: [PATCH 02/47] Better internal corners --- src/ssd/ssd-border.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index 5083c0be..02987a10 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -104,9 +104,21 @@ printf("At 32\n"); } } tl_data[bw*bw -1] = col0; + tl_data[bw*bw -2] = col0; + tl_data[(bw-1)*bw -1] = col0; + tl_data[(bw-1)*bw -2] = col0; tr_data[(bw-1)*bw + (0)] = col0; + tr_data[(bw-1)*bw + (1)] = col0; + tr_data[(bw-2)*bw + (0)] = col0; + tr_data[(bw-2)*bw + (1)] = col0; bl_data[(0)*bw + (bw-1)] = col1; + bl_data[(0)*bw + (bw-2)] = col1; + bl_data[(1)*bw + (bw-1)] = col1; + bl_data[(1)*bw + (bw-2)] = col1; br_data[(0)*bw + (0)] = col1; + br_data[(0)*bw + (1)] = col1; + br_data[(1)*bw + (0)] = col1; + br_data[(1)*bw + (1)] = col1; /* bottom and right are identical */ From 12803b1aca7172391d5eff9594a84e81e300e135 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Mon, 23 Mar 2026 21:12:20 -0700 Subject: [PATCH 03/47] Remove old border residue and debug code --- src/ssd/ssd-border.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index 02987a10..4bdac5f7 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -11,7 +11,7 @@ #include "ssd-internal.h" #include "theme.h" #include "view.h" -#include "stdio.h" + void ssd_border_create(struct ssd *ssd) { @@ -29,7 +29,6 @@ ssd_border_create(struct ssd *ssd) ssd->border.tree = lab_wlr_scene_tree_create(ssd->tree); wlr_scene_node_set_position(&ssd->border.tree->node, -theme->border_width, 0); -printf("At 32\n"); enum ssd_active_state active; FOR_EACH_ACTIVE_STATE(active) { struct ssd_border_subtree *subtree = &ssd->border.subtrees[active]; @@ -136,23 +135,15 @@ printf("At 32\n"); subtree->left = lab_wlr_scene_rect_create(parent, theme->border_width, height, color); - wlr_scene_node_set_position(&subtree->left->node, 0, 0); - + subtree->right = lab_wlr_scene_rect_create(parent, theme->border_width, height, color); - wlr_scene_node_set_position(&subtree->right->node, - theme->border_width + width, 0); - + subtree->bottom = lab_wlr_scene_rect_create(parent, full_width, theme->border_width, color); - wlr_scene_node_set_position(&subtree->bottom->node, - 0, height); - + subtree->top = lab_wlr_scene_rect_create(parent, MAX(width - 2 * corner_width, 0), theme->border_width, color); - wlr_scene_node_set_position(&subtree->top->node, - theme->border_width + corner_width, - -(ssd->titlebar.height + theme->border_width)); struct lab_data_buffer *ttexture_buffer = From 4ff1832eb368a872f1179f9471aa933057f12a12 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Mon, 23 Mar 2026 22:14:28 -0700 Subject: [PATCH 04/47] Gate beveled borders behind border.beveled theme option --- include/theme.h | 1 + src/ssd/ssd-border.c | 407 +++++++++++++++++++++++-------------------- src/theme.c | 4 + 3 files changed, 226 insertions(+), 186 deletions(-) diff --git a/include/theme.h b/include/theme.h index 2fb499a9..6a8812f8 100644 --- a/include/theme.h +++ b/include/theme.h @@ -60,6 +60,7 @@ struct theme_background { struct theme { int border_width; + bool beveled_border; /* * the space between title bar border and diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index 4bdac5f7..685519ed 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -37,101 +37,6 @@ ssd_border_create(struct ssd *ssd) wlr_scene_node_set_enabled(&parent->node, active); float *color = theme->window[active].border_color; - /* From Pull request 3382 */ - uint8_t r = color[0] * 255; - uint8_t g = color[1] * 255; - uint8_t b = color[2] * 255; - uint8_t a = color[3] * 255; - - /* highlight */ - uint8_t r1 = MIN(r * 5 / 4, a); - uint8_t g1 = MIN(g * 5 / 4, a); - uint8_t b1 = MIN(b * 5 / 4, a); - - /* darker outline */ - uint8_t r0 = r / 2; - uint8_t g0 = g / 2; - uint8_t b0 = b / 2; - - uint32_t col = ((uint32_t)a << 24) | ((uint32_t)r << 16) - | ((uint32_t)g << 8) | b; - uint32_t col0 = ((uint32_t)a << 24) | ((uint32_t)r0 << 16) - | ((uint32_t)g0 << 8) | b0; - uint32_t col1 = ((uint32_t)a << 24) | ((uint32_t)r1 << 16) - | ((uint32_t)g1 << 8) | b1; - - - uint32_t *left_data = znew_n(uint32_t, bw); - uint32_t *top_data = znew_n(uint32_t, bw); - left_data[0] = top_data[0] = col1; - left_data[1] = top_data[1] = col1; - for (int i = 2; i < bw; i++) { - left_data[i] = col; - top_data[i] = col; - } - left_data[bw-1] = top_data[bw-1] = col0; - left_data[bw-2] = top_data[bw-2] = col0; - - - - uint32_t *tl_data = znew_n(uint32_t, bw*bw); - uint32_t *tr_data = znew_n(uint32_t, bw*bw); - uint32_t *bl_data = znew_n(uint32_t, bw*bw); - uint32_t *br_data = znew_n(uint32_t, bw*bw); - for (int i=0; ibw -3) { - bl_data[i*bw + j] = col0; - br_data[i*bw + j] = col0; - } - if (j<2) { - tl_data[i*bw + j] = col1; - bl_data[i*bw + j] = col1; - } - if (j>bw -3) { - tr_data[i*bw + j] = col0; - br_data[i*bw + j] = col0; - } - } - } - tl_data[bw*bw -1] = col0; - tl_data[bw*bw -2] = col0; - tl_data[(bw-1)*bw -1] = col0; - tl_data[(bw-1)*bw -2] = col0; - tr_data[(bw-1)*bw + (0)] = col0; - tr_data[(bw-1)*bw + (1)] = col0; - tr_data[(bw-2)*bw + (0)] = col0; - tr_data[(bw-2)*bw + (1)] = col0; - bl_data[(0)*bw + (bw-1)] = col1; - bl_data[(0)*bw + (bw-2)] = col1; - bl_data[(1)*bw + (bw-1)] = col1; - bl_data[(1)*bw + (bw-2)] = col1; - br_data[(0)*bw + (0)] = col1; - br_data[(0)*bw + (1)] = col1; - br_data[(1)*bw + (0)] = col1; - br_data[(1)*bw + (1)] = col1; - - - /* bottom and right are identical */ - uint32_t *right_data = znew_n(uint32_t, theme->border_width); - uint32_t *bottom_data = znew_n(uint32_t, theme->border_width); - right_data[0]=bottom_data[0]=col1; - right_data[1]=bottom_data[1]=col1; - for (int i = 2; i < theme->border_width - 1; i++) { - right_data[i] = col; - bottom_data[i] = col; - } - right_data[theme->border_width - 1] = bottom_data[theme->border_width - 1] = col0; - right_data[theme->border_width - 2] = bottom_data[theme->border_width - 2] = col0; - subtree->left = lab_wlr_scene_rect_create(parent, theme->border_width, height, color); @@ -144,56 +49,170 @@ ssd_border_create(struct ssd *ssd) subtree->top = lab_wlr_scene_rect_create(parent, MAX(width - 2 * corner_width, 0), theme->border_width, color); - - - struct lab_data_buffer *ttexture_buffer = - buffer_create_from_data(top_data, 1,theme->border_width, - 4); - subtree->ttexture = wlr_scene_buffer_create(parent, &ttexture_buffer->base); - wlr_buffer_drop(&ttexture_buffer->base); + + + + if (theme->beveled_border) { + /* From Pull request 3382 */ + uint8_t r = color[0] * 255; + uint8_t g = color[1] * 255; + uint8_t b = color[2] * 255; + uint8_t a = color[3] * 255; + + /* highlight */ + uint8_t r1 = MIN(r * 5 / 4, a); + uint8_t g1 = MIN(g * 5 / 4, a); + uint8_t b1 = MIN(b * 5 / 4, a); + + /* darker outline */ + uint8_t r0 = r / 2; + uint8_t g0 = g / 2; + uint8_t b0 = b / 2; + + uint32_t col = ((uint32_t)a << 24) | ((uint32_t)r << 16) + | ((uint32_t)g << 8) | b; + uint32_t col0 = ((uint32_t)a << 24) | ((uint32_t)r0 << 16) + | ((uint32_t)g0 << 8) | b0; + uint32_t col1 = ((uint32_t)a << 24) | ((uint32_t)r1 << 16) + | ((uint32_t)g1 << 8) | b1; + + + uint32_t *left_data = znew_n(uint32_t, bw); + uint32_t *top_data = znew_n(uint32_t, bw); + left_data[0] = top_data[0] = col1; + left_data[1] = top_data[1] = col1; + for (int i = 2; i < bw; i++) { + left_data[i] = col; + top_data[i] = col; + } + left_data[bw-1] = top_data[bw-1] = col0; + left_data[bw-2] = top_data[bw-2] = col0; + + + + uint32_t *tl_data = znew_n(uint32_t, bw*bw); + uint32_t *tr_data = znew_n(uint32_t, bw*bw); + uint32_t *bl_data = znew_n(uint32_t, bw*bw); + uint32_t *br_data = znew_n(uint32_t, bw*bw); + for (int i=0; ibw -3) { + bl_data[i*bw + j] = col0; + br_data[i*bw + j] = col0; + } + if (j<2) { + tl_data[i*bw + j] = col1; + bl_data[i*bw + j] = col1; + } + if (j>bw -3) { + tr_data[i*bw + j] = col0; + br_data[i*bw + j] = col0; + } + } + } + tl_data[bw*bw -1] = col0; + tl_data[bw*bw -2] = col0; + tl_data[(bw-1)*bw -1] = col0; + tl_data[(bw-1)*bw -2] = col0; + tr_data[(bw-1)*bw + (0)] = col0; + tr_data[(bw-1)*bw + (1)] = col0; + tr_data[(bw-2)*bw + (0)] = col0; + tr_data[(bw-2)*bw + (1)] = col0; + bl_data[(0)*bw + (bw-1)] = col1; + bl_data[(0)*bw + (bw-2)] = col1; + bl_data[(1)*bw + (bw-1)] = col1; + bl_data[(1)*bw + (bw-2)] = col1; + br_data[(0)*bw + (0)] = col1; + br_data[(0)*bw + (1)] = col1; + br_data[(1)*bw + (0)] = col1; + br_data[(1)*bw + (1)] = col1; + + + /* bottom and right are identical */ + uint32_t *right_data = znew_n(uint32_t, theme->border_width); + uint32_t *bottom_data = znew_n(uint32_t, theme->border_width); + right_data[0]=bottom_data[0]=col1; + right_data[1]=bottom_data[1]=col1; + for (int i = 2; i < theme->border_width - 1; i++) { + right_data[i] = col; + bottom_data[i] = col; + } + right_data[theme->border_width - 1] = bottom_data[theme->border_width - 1] = col0; + right_data[theme->border_width - 2] = bottom_data[theme->border_width - 2] = col0; + + + struct lab_data_buffer *ttexture_buffer = + buffer_create_from_data(top_data, 1,theme->border_width, + 4); + subtree->ttexture = wlr_scene_buffer_create(parent, &ttexture_buffer->base); + wlr_buffer_drop(&ttexture_buffer->base); + + struct lab_data_buffer *btexture_buffer = + buffer_create_from_data(bottom_data, 1,theme->border_width, + 4); + subtree->btexture = wlr_scene_buffer_create(parent, &btexture_buffer->base); + wlr_buffer_drop(&btexture_buffer->base); + + struct lab_data_buffer *ltexture_buffer = + buffer_create_from_data(left_data, theme->border_width, 1, + 4*theme->border_width); + subtree->ltexture = wlr_scene_buffer_create(parent, <exture_buffer->base); + wlr_buffer_drop(<exture_buffer->base); + + struct lab_data_buffer *rtexture_buffer = + buffer_create_from_data(right_data, theme->border_width, 1, + 4*theme->border_width); + subtree->rtexture = wlr_scene_buffer_create(parent, &rtexture_buffer->base); + wlr_buffer_drop(&rtexture_buffer->base); + + + struct lab_data_buffer *tltexture_buffer = + buffer_create_from_data(tl_data, theme->border_width, theme->border_width, + 4*theme->border_width); + subtree->tlcorner = wlr_scene_buffer_create(parent, &tltexture_buffer->base); + wlr_buffer_drop(&tltexture_buffer->base); + + struct lab_data_buffer *trtexture_buffer = + buffer_create_from_data(tr_data, theme->border_width, theme->border_width, + 4*theme->border_width); + subtree->trcorner = wlr_scene_buffer_create(parent, &trtexture_buffer->base); + wlr_buffer_drop(&trtexture_buffer->base); + + + struct lab_data_buffer *bltexture_buffer = + buffer_create_from_data(bl_data, theme->border_width, theme->border_width, + 4*theme->border_width); + subtree->blcorner = wlr_scene_buffer_create(parent, &bltexture_buffer->base); + wlr_buffer_drop(&bltexture_buffer->base); + + struct lab_data_buffer *brtexture_buffer = + buffer_create_from_data(br_data, theme->border_width, theme->border_width, + 4*theme->border_width); + subtree->brcorner = wlr_scene_buffer_create(parent, &brtexture_buffer->base); + wlr_buffer_drop(&brtexture_buffer->base); + } + + + + if (!theme->beveled_border) { + wlr_scene_node_set_position(&subtree->left->node, 0, 0); + wlr_scene_node_set_position(&subtree->right->node, + theme->border_width + width, 0); + wlr_scene_node_set_position(&subtree->bottom->node, + 0, height); - struct lab_data_buffer *btexture_buffer = - buffer_create_from_data(bottom_data, 1,theme->border_width, - 4); - subtree->btexture = wlr_scene_buffer_create(parent, &btexture_buffer->base); - wlr_buffer_drop(&btexture_buffer->base); - - struct lab_data_buffer *ltexture_buffer = - buffer_create_from_data(left_data, theme->border_width, 1, - 4*theme->border_width); - subtree->ltexture = wlr_scene_buffer_create(parent, <exture_buffer->base); - wlr_buffer_drop(<exture_buffer->base); - struct lab_data_buffer *rtexture_buffer = - buffer_create_from_data(right_data, theme->border_width, 1, - 4*theme->border_width); - subtree->rtexture = wlr_scene_buffer_create(parent, &rtexture_buffer->base); - wlr_buffer_drop(&rtexture_buffer->base); - - - struct lab_data_buffer *tltexture_buffer = - buffer_create_from_data(tl_data, theme->border_width, theme->border_width, - 4*theme->border_width); - subtree->tlcorner = wlr_scene_buffer_create(parent, &tltexture_buffer->base); - wlr_buffer_drop(&tltexture_buffer->base); - - struct lab_data_buffer *trtexture_buffer = - buffer_create_from_data(tr_data, theme->border_width, theme->border_width, - 4*theme->border_width); - subtree->trcorner = wlr_scene_buffer_create(parent, &trtexture_buffer->base); - wlr_buffer_drop(&trtexture_buffer->base); - - - struct lab_data_buffer *bltexture_buffer = - buffer_create_from_data(bl_data, theme->border_width, theme->border_width, - 4*theme->border_width); - subtree->blcorner = wlr_scene_buffer_create(parent, &bltexture_buffer->base); - wlr_buffer_drop(&bltexture_buffer->base); - - struct lab_data_buffer *brtexture_buffer = - buffer_create_from_data(br_data, theme->border_width, theme->border_width, - 4*theme->border_width); - subtree->brcorner = wlr_scene_buffer_create(parent, &brtexture_buffer->base); - wlr_buffer_drop(&brtexture_buffer->base); + wlr_scene_node_set_position(&subtree->top->node, + theme->border_width + corner_width, + -(ssd->titlebar.height + theme->border_width)); + } } @@ -277,52 +296,68 @@ ssd_border_update(struct ssd *ssd) enum ssd_active_state active; FOR_EACH_ACTIVE_STATE(active) { struct ssd_border_subtree *subtree = &ssd->border.subtrees[active]; - - wlr_scene_buffer_set_dest_size(subtree->ttexture, - full_width, theme->border_width); - wlr_scene_node_set_position(&subtree->ttexture->node, - 0, -(ssd->titlebar.height + theme->border_width)); - - wlr_scene_buffer_set_dest_size(subtree->rtexture, - theme->border_width, side_height+(ssd->titlebar.height + theme->border_width)); - wlr_scene_node_set_position(&subtree->rtexture->node, - theme->border_width + width, -(ssd->titlebar.height + theme->border_width)); - - wlr_scene_buffer_set_dest_size(subtree->btexture, - full_width, theme->border_width); - wlr_scene_node_set_position(&subtree->btexture->node, - 0, height); - - wlr_scene_buffer_set_dest_size(subtree->ltexture, - theme->border_width, side_height+(ssd->titlebar.height + theme->border_width)); - wlr_scene_node_set_position(&subtree->ltexture->node, - 0, -(ssd->titlebar.height + theme->border_width)); - wlr_scene_buffer_set_dest_size(subtree->tlcorner, - theme->border_width, theme->border_width); - wlr_scene_node_set_position(&subtree->tlcorner->node, - 0, -(ssd->titlebar.height + theme->border_width)); - - wlr_scene_buffer_set_dest_size(subtree->trcorner, - theme->border_width, theme->border_width); - wlr_scene_node_set_position(&subtree->trcorner->node, - theme->border_width + width, -(ssd->titlebar.height + theme->border_width)); - - - wlr_scene_buffer_set_dest_size(subtree->brcorner, - theme->border_width, theme->border_width); - wlr_scene_node_set_position(&subtree->brcorner->node, - theme->border_width + width, height); - - wlr_scene_buffer_set_dest_size(subtree->blcorner, - theme->border_width, theme->border_width); - wlr_scene_node_set_position(&subtree->blcorner->node, - 0, height); + if (theme->beveled_border) { + wlr_scene_buffer_set_dest_size(subtree->ttexture, + full_width, theme->border_width); + wlr_scene_node_set_position(&subtree->ttexture->node, + 0, -(ssd->titlebar.height + theme->border_width)); + + wlr_scene_buffer_set_dest_size(subtree->rtexture, + theme->border_width, side_height+(ssd->titlebar.height + theme->border_width)); + wlr_scene_node_set_position(&subtree->rtexture->node, + theme->border_width + width, -(ssd->titlebar.height + theme->border_width)); + + wlr_scene_buffer_set_dest_size(subtree->btexture, + full_width, theme->border_width); + wlr_scene_node_set_position(&subtree->btexture->node, + 0, height); + + wlr_scene_buffer_set_dest_size(subtree->ltexture, + theme->border_width, side_height+(ssd->titlebar.height + theme->border_width)); + wlr_scene_node_set_position(&subtree->ltexture->node, + 0, -(ssd->titlebar.height + theme->border_width)); + + wlr_scene_buffer_set_dest_size(subtree->tlcorner, + theme->border_width, theme->border_width); + wlr_scene_node_set_position(&subtree->tlcorner->node, + 0, -(ssd->titlebar.height + theme->border_width)); + + wlr_scene_buffer_set_dest_size(subtree->trcorner, + theme->border_width, theme->border_width); + wlr_scene_node_set_position(&subtree->trcorner->node, + theme->border_width + width, -(ssd->titlebar.height + theme->border_width)); - - + wlr_scene_buffer_set_dest_size(subtree->brcorner, + theme->border_width, theme->border_width); + wlr_scene_node_set_position(&subtree->brcorner->node, + theme->border_width + width, height); + + + wlr_scene_buffer_set_dest_size(subtree->blcorner, + theme->border_width, theme->border_width); + wlr_scene_node_set_position(&subtree->blcorner->node, + 0, height); + } else { + wlr_scene_rect_set_size(subtree->left, + theme->border_width, side_height); + wlr_scene_node_set_position(&subtree->left->node, + 0, side_y); + wlr_scene_rect_set_size(subtree->right, + theme->border_width, side_height); + wlr_scene_node_set_position(&subtree->right->node, + theme->border_width + width, side_y); + wlr_scene_rect_set_size(subtree->bottom, + full_width, theme->border_width); + wlr_scene_node_set_position(&subtree->bottom->node, + 0, height); + wlr_scene_rect_set_size(subtree->top, + top_width, theme->border_width); + wlr_scene_node_set_position(&subtree->top->node, + top_x, -(ssd->titlebar.height + theme->border_width)); + } } } diff --git a/src/theme.c b/src/theme.c index 93ac1c5e..8ba09f68 100644 --- a/src/theme.c +++ b/src/theme.c @@ -532,6 +532,7 @@ static void theme_builtin(struct theme *theme) { theme->border_width = 1; + theme->beveled_border = FALSE; theme->window_titlebar_padding_height = 0; theme->window_titlebar_padding_width = 0; @@ -695,6 +696,9 @@ entry(struct theme *theme, const char *key, const char *value) theme->border_width = get_int_if_positive( value, "border.width"); } + if (match_glob(key, "border.beveled")) { + set_bool(value, &theme->beveled_border); + } if (match_glob(key, "window.titlebar.padding.width")) { theme->window_titlebar_padding_width = get_int_if_positive( value, "window.titlebar.padding.width"); From ddd1ff5a6ad09920532094d0eb897e76e3ed103b Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Mon, 23 Mar 2026 22:50:07 -0700 Subject: [PATCH 05/47] Render beveled menus --- src/common/lab-scene-rect.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c index 6689d48f..eafb43ed 100644 --- a/src/common/lab-scene-rect.c +++ b/src/common/lab-scene-rect.c @@ -36,11 +36,34 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, for (int i = 0; i < rect->nr_borders; i++) { struct border_scene *border = &rect->borders[i]; float *color = opts->border_colors[i]; + + /* From Pull request 3382 */ + float r = color[0]; + float g = color[1]; + float b = color[2]; + float a = color[3]; + + /* highlight */ + float r1 = r * 5 / 4; + if (r1 > a) r1=a; + float g1 = g * 5 / 4; + if (g1 > a) g1=a; + float b1 = b * 5 / 4; + if (b1 > a) b1=a; + + /* darker outline */ + float r0 = r / 2; + float g0 = g / 2; + float b0 = b / 2; + + const float highlight[4] = {r1, g1, b1, a}; + const float lowlight[4] = {r0, g0, b0, a}; border->tree = lab_wlr_scene_tree_create(rect->tree); - border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, color); - border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, color); - border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0, color); - border->left = lab_wlr_scene_rect_create(border->tree, 0, 0, color); + border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, highlight); + border->right = lab_wlr_scene_rect_create(border->tree, 0, 0,lowlight); + border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0,lowlight); + border->left = lab_wlr_scene_rect_create(border->tree, 0, 0,highlight); + } rect->node_destroy.notify = handle_node_destroy; From 34ea693879d3ab3fa195acbfdf24b89f882f4d94 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Mon, 23 Mar 2026 23:34:06 -0700 Subject: [PATCH 06/47] Add bevels to workplace switcher --- src/workspaces.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/workspaces.c b/src/workspaces.c index 9b4ed664..010bc837 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -101,15 +101,36 @@ _osd_update(void) /* Background */ set_cairo_color(cairo, theme->osd_bg_color); cairo_rectangle(cairo, 0, 0, width, height); - cairo_fill(cairo); + cairo_fill(cairo); + + + /* Border */ - set_cairo_color(cairo, theme->osd_border_color); - struct wlr_fbox border_fbox = { - .width = width, - .height = height, + const float highlight[4] = { + theme->osd_bg_color[0] * 1.25, + theme->osd_bg_color[1] * 1.25, + theme->osd_bg_color[2] * 1.25, + theme->osd_bg_color[3] }; - draw_cairo_border(cairo, border_fbox, theme->osd_border_width); + const float lowlight[4] = { + theme->osd_bg_color[0] / 2, + theme->osd_bg_color[1] / 2, + theme->osd_bg_color[2] / 2, + theme->osd_bg_color[3] + }; + set_cairo_color(cairo, highlight); + cairo_rectangle(cairo, 0, 0, width, 2); + cairo_fill(cairo); + cairo_rectangle(cairo, 0, 0, 2, height); + cairo_fill(cairo); + + set_cairo_color(cairo, lowlight); + cairo_rectangle(cairo, width-2, 0, width, height); + cairo_fill(cairo); + cairo_rectangle(cairo, 0, height-2, width, height); + cairo_fill(cairo); + /* Boxes */ uint16_t x; From 939b339a8e29eed48e96399e7fcd4b4163fba497 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Wed, 25 Mar 2026 19:58:00 -0700 Subject: [PATCH 07/47] More scalable double-bevel setup for window frames --- src/ssd/ssd-border.c | 146 ++++++++++++++++++++++++++++++------------- 1 file changed, 102 insertions(+), 44 deletions(-) diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index 685519ed..3ea8e492 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -12,6 +12,8 @@ #include "theme.h" #include "view.h" +#define PIXEL(x,y) (bw * y + x) + void ssd_border_create(struct ssd *ssd) { @@ -53,6 +55,10 @@ ssd_border_create(struct ssd *ssd) if (theme->beveled_border) { + + + int bevelSize = 2; // TODO: configurable + /* From Pull request 3382 */ uint8_t r = color[0] * 255; uint8_t g = color[1] * 255; @@ -79,75 +85,127 @@ ssd_border_create(struct ssd *ssd) uint32_t *left_data = znew_n(uint32_t, bw); uint32_t *top_data = znew_n(uint32_t, bw); - left_data[0] = top_data[0] = col1; - left_data[1] = top_data[1] = col1; - for (int i = 2; i < bw; i++) { - left_data[i] = col; - top_data[i] = col; - } - left_data[bw-1] = top_data[bw-1] = col0; - left_data[bw-2] = top_data[bw-2] = col0; + uint32_t *right_data = znew_n(uint32_t, theme->border_width); + uint32_t *bottom_data = znew_n(uint32_t, theme->border_width); + for (int i = 0; i < bw; i++) { + if (i (bw-bevelSize-1)) { + left_data[i] = col0; + top_data[i] = col0; + right_data[i] = col0; + bottom_data[i] = col0; + + } else { + left_data[i] = col; + top_data[i] = col; + right_data[i] = col; + bottom_data[i] = col; + } + } uint32_t *tl_data = znew_n(uint32_t, bw*bw); uint32_t *tr_data = znew_n(uint32_t, bw*bw); uint32_t *bl_data = znew_n(uint32_t, bw*bw); uint32_t *br_data = znew_n(uint32_t, bw*bw); + // Fill with solid for (int i=0; ibw -3) { - bl_data[i*bw + j] = col0; - br_data[i*bw + j] = col0; - } - if (j<2) { - tl_data[i*bw + j] = col1; - bl_data[i*bw + j] = col1; - } - if (j>bw -3) { - tr_data[i*bw + j] = col0; - br_data[i*bw + j] = col0; - } + tl_data[PIXEL(i, j)] = col; + tr_data[PIXEL(i, j)] = col; + bl_data[PIXEL(i, j)] = col; + br_data[PIXEL(i, j)] = col; } } + + + // Main Corners + for (int i=0; i < bevelSize; i++) { + + // Solid bar parts + for (int j=0; j= i) ? col1 : col0; + + // Top Right corner: + // Last "bevel size" columns are lowlight, except for the top left + tr_data[PIXEL((bw-1-i), j)] = (j > i) ? col0 : col1; + + + // Inner Corners + // Top left corner: Bottom right is all dark + tl_data[PIXEL((bw-1-i), (bw - 1 - j))] = col0; + + // Bottom Right corner: Top left is all light + br_data[PIXEL(i, j)] = col1; + + // Top Right corner: + // Interior bottom left is dark on top, light on bottom + tr_data[PIXEL(i, (bw-1-j))] = (i > j) ? col1 : col0; + + // Bottom Left corner: + // Interior top right is dark on top, light on bottom + bl_data[PIXEL((bw-1-i), j)] = (i > j) ? col0 : col1; + + + + } + + + } tl_data[bw*bw -1] = col0; tl_data[bw*bw -2] = col0; tl_data[(bw-1)*bw -1] = col0; tl_data[(bw-1)*bw -2] = col0; tr_data[(bw-1)*bw + (0)] = col0; - tr_data[(bw-1)*bw + (1)] = col0; + tr_data[(bw-1)*bw + (1)] = col1; tr_data[(bw-2)*bw + (0)] = col0; tr_data[(bw-2)*bw + (1)] = col0; - bl_data[(0)*bw + (bw-1)] = col1; - bl_data[(0)*bw + (bw-2)] = col1; + bl_data[(0)*bw + (bw-1)] = col0; + bl_data[(0)*bw + (bw-2)] = col0; bl_data[(1)*bw + (bw-1)] = col1; - bl_data[(1)*bw + (bw-2)] = col1; + bl_data[(1)*bw + (bw-2)] = col0; br_data[(0)*bw + (0)] = col1; br_data[(0)*bw + (1)] = col1; br_data[(1)*bw + (0)] = col1; br_data[(1)*bw + (1)] = col1; - /* bottom and right are identical */ - uint32_t *right_data = znew_n(uint32_t, theme->border_width); - uint32_t *bottom_data = znew_n(uint32_t, theme->border_width); - right_data[0]=bottom_data[0]=col1; - right_data[1]=bottom_data[1]=col1; - for (int i = 2; i < theme->border_width - 1; i++) { - right_data[i] = col; - bottom_data[i] = col; - } - right_data[theme->border_width - 1] = bottom_data[theme->border_width - 1] = col0; - right_data[theme->border_width - 2] = bottom_data[theme->border_width - 2] = col0; - struct lab_data_buffer *ttexture_buffer = buffer_create_from_data(top_data, 1,theme->border_width, From effc16fc055739a36df5ed3ff9f4d1892cea87e3 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Wed, 25 Mar 2026 20:03:01 -0700 Subject: [PATCH 08/47] Window bevel depth is now configurable --- docs/themerc | 4 +++- include/theme.h | 1 + src/ssd/ssd-border.c | 2 +- src/theme.c | 5 +++++ 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/themerc b/docs/themerc index 83ea726b..195f36a0 100644 --- a/docs/themerc +++ b/docs/themerc @@ -6,7 +6,9 @@ # make sure all other lines are commented out or deleted. # general -border.width: 1 +border.width: 6 +border.beveled: yes +border.bevel_width:2 # # The global padding.{width,height} of openbox are not supported because diff --git a/include/theme.h b/include/theme.h index 6a8812f8..123558f5 100644 --- a/include/theme.h +++ b/include/theme.h @@ -61,6 +61,7 @@ struct theme_background { struct theme { int border_width; bool beveled_border; + int border_bevel_width; /* * the space between title bar border and diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index 3ea8e492..7e511381 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -57,7 +57,7 @@ ssd_border_create(struct ssd *ssd) if (theme->beveled_border) { - int bevelSize = 2; // TODO: configurable + int bevelSize = theme->border_bevel_width; // TODO: configurable /* From Pull request 3382 */ uint8_t r = color[0] * 255; diff --git a/src/theme.c b/src/theme.c index 8ba09f68..04200800 100644 --- a/src/theme.c +++ b/src/theme.c @@ -533,6 +533,7 @@ theme_builtin(struct theme *theme) { theme->border_width = 1; theme->beveled_border = FALSE; + theme->border_bevel_width=0; theme->window_titlebar_padding_height = 0; theme->window_titlebar_padding_width = 0; @@ -699,6 +700,10 @@ entry(struct theme *theme, const char *key, const char *value) if (match_glob(key, "border.beveled")) { set_bool(value, &theme->beveled_border); } + if (match_glob(key, "border.bevel_width")) { + theme->border_bevel_width = get_int_if_positive( + value, "border.bevel_width"); + } if (match_glob(key, "window.titlebar.padding.width")) { theme->window_titlebar_padding_width = get_int_if_positive( value, "window.titlebar.padding.width"); From 69e372cc5fec842ff4c802f4d7169d50bc1b9d10 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Wed, 25 Mar 2026 21:08:20 -0700 Subject: [PATCH 09/47] Sharp borders and flag-controlled bevels for the menus/dialogues --- include/common/lab-scene-rect.h | 3 + include/common/macros.h | 11 +++ src/common/lab-scene-rect.c | 158 ++++++++++++++++++++++++++------ src/ssd/ssd-border.c | 19 +--- 4 files changed, 147 insertions(+), 44 deletions(-) diff --git a/include/common/lab-scene-rect.h b/include/common/lab-scene-rect.h index 5005fbb3..51fe309b 100644 --- a/include/common/lab-scene-rect.h +++ b/include/common/lab-scene-rect.h @@ -3,6 +3,9 @@ #define LABWC_LAB_SCENE_RECT_H #include + +// Ensure we can access theme data to decide if we need bevels +extern struct rcxml rc; struct wlr_scene_tree; struct lab_scene_rect_options { diff --git a/include/common/macros.h b/include/common/macros.h index 25226261..9bcbe20c 100644 --- a/include/common/macros.h +++ b/include/common/macros.h @@ -65,4 +65,15 @@ #define LAB_WLR_VERSION_AT_LEAST(major, minor, micro) \ (WLR_VERSION_NUM >= (((major) << 16) | ((minor) << 8) | (micro))) + +/** + * PIXEL () - calculate pixel offset in an array of "bw" columns wide. + * + * @param x x-coordinate + * @param y y-coordinate + * Assumes "bw" was defined externally + */ + +#define PIXEL(x,y) (bw * y + x) + #endif /* LABWC_MACROS_H */ diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c index eafb43ed..65ddbfd3 100644 --- a/src/common/lab-scene-rect.c +++ b/src/common/lab-scene-rect.c @@ -4,10 +4,15 @@ #include #include "common/mem.h" #include "common/scene-helpers.h" +#include "common/macros.h" +#include "buffer.h" +#include "config/rcxml.h" +#include "theme.h" struct border_scene { struct wlr_scene_tree *tree; struct wlr_scene_rect *top, *bottom, *left, *right; + struct wlr_scene_buffer *tlcorner, *trcorner, *blcorner, *brcorner; }; static void @@ -28,6 +33,8 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, rect->nr_borders = opts->nr_borders; rect->borders = znew_n(rect->borders[0], opts->nr_borders); rect->tree = lab_wlr_scene_tree_create(parent); + + struct theme *theme = rc.theme; if (opts->bg_color) { rect->fill = lab_wlr_scene_rect_create(rect->tree, 0, 0, opts->bg_color); @@ -36,33 +43,105 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, for (int i = 0; i < rect->nr_borders; i++) { struct border_scene *border = &rect->borders[i]; float *color = opts->border_colors[i]; - - /* From Pull request 3382 */ - float r = color[0]; - float g = color[1]; - float b = color[2]; - float a = color[3]; - - /* highlight */ - float r1 = r * 5 / 4; - if (r1 > a) r1=a; - float g1 = g * 5 / 4; - if (g1 > a) g1=a; - float b1 = b * 5 / 4; - if (b1 > a) b1=a; - - /* darker outline */ - float r0 = r / 2; - float g0 = g / 2; - float b0 = b / 2; - - const float highlight[4] = {r1, g1, b1, a}; - const float lowlight[4] = {r0, g0, b0, a}; border->tree = lab_wlr_scene_tree_create(rect->tree); - border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, highlight); - border->right = lab_wlr_scene_rect_create(border->tree, 0, 0,lowlight); - border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0,lowlight); - border->left = lab_wlr_scene_rect_create(border->tree, 0, 0,highlight); + + if (theme->beveled_border) { + /* From Pull request 3382 */ + + int bw = rect->border_width; + + // Floats for the rect versions. + float r = color[0]; + float g = color[1]; + float b = color[2]; + float a = color[3]; + + + float r1 = r * 5 / 4; + if (r1 > a) r1=a; + float g1 = g * 5 / 4; + if (g1 > a) g1=a; + float b1 = b * 5 / 4; + if (b1 > a) b1=a; + + /* darker outline */ + float r0 = r / 2; + float g0 = g / 2; + float b0 = b / 2; + + + + // Buffers are AARRGGBB 32-bit packed int + uint32_t ll32 = ((uint32_t)(255*a) << 24) | ((uint32_t)(255*r0) << 16) + | ((uint32_t)(255*g0) << 8) | (uint32_t)(255*b0); + uint32_t hl32 = ((uint32_t)(255*a) << 24) | ((uint32_t)(255*r1) << 16) + | ((uint32_t)(255*g1) << 8) | (uint32_t)(255*b1); + + + const float highlight[4] = {r1, g1, b1, a}; + const float lowlight[4] = {r0, g0, b0, a}; + + + + + + border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, highlight); + border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, lowlight); + border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0, lowlight); + border->left = lab_wlr_scene_rect_create(border->tree, 0, 0, highlight); + + + + uint32_t *tl_data = znew_n(uint32_t, bw*bw); + uint32_t *tr_data = znew_n(uint32_t, bw*bw); + uint32_t *bl_data = znew_n(uint32_t, bw*bw); + uint32_t *br_data = znew_n(uint32_t, bw*bw); + + + // Fill with solid + for (int j=0; j k) ? hl32 : ll32; + bl_data[PIXEL(bw - 1 -j, k)] = (j > k) ? hl32 : ll32; + br_data[PIXEL(j, k)] = ll32; + } + } + + + struct lab_data_buffer *tltexture_buffer = + buffer_create_from_data(tl_data, bw, bw, 4*bw); + border->tlcorner = wlr_scene_buffer_create(parent, &tltexture_buffer->base); + wlr_buffer_drop(&tltexture_buffer->base); + + + struct lab_data_buffer *trtexture_buffer = + buffer_create_from_data(tr_data, bw, bw, 4*bw); + border->trcorner = wlr_scene_buffer_create(parent, &trtexture_buffer->base); + wlr_buffer_drop(&trtexture_buffer->base); + + + struct lab_data_buffer *bltexture_buffer = + buffer_create_from_data(bl_data, bw, bw, 4*bw); + border->blcorner = wlr_scene_buffer_create(parent, &bltexture_buffer->base); + wlr_buffer_drop(&bltexture_buffer->base); + + struct lab_data_buffer *brtexture_buffer = + buffer_create_from_data(br_data, bw, bw, 4*bw); + border->brcorner = wlr_scene_buffer_create(parent, &brtexture_buffer->base); + wlr_buffer_drop(&brtexture_buffer->base); + + + + + + } else { + border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, color); + border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, color); + border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0, color); + border->left = lab_wlr_scene_rect_create(border->tree, 0, 0, color); + } + } @@ -104,6 +183,33 @@ resize_border(struct border_scene *border, int border_width, int width, int heig 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); + + struct theme *theme = rc.theme; + if (theme->beveled_border) { + wlr_scene_buffer_set_dest_size(border->tlcorner, + border_width, border_width); + wlr_scene_node_set_position(&border->tlcorner->node, + 0,0); + + wlr_scene_buffer_set_dest_size(border->trcorner, + border_width, border_width); + wlr_scene_node_set_position(&border->trcorner->node, + width-border_width, 0); + + + wlr_scene_buffer_set_dest_size(border->brcorner, + border_width, border_width); + wlr_scene_node_set_position(&border->brcorner->node, + width-border_width , height-border_width); + + + wlr_scene_buffer_set_dest_size(border->blcorner, + border_width, border_width); + wlr_scene_node_set_position(&border->blcorner->node, + 0, height-border_width); + + + } } void diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index 7e511381..170546f6 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -12,7 +12,7 @@ #include "theme.h" #include "view.h" -#define PIXEL(x,y) (bw * y + x) + void ssd_border_create(struct ssd *ssd) @@ -188,23 +188,6 @@ ssd_border_create(struct ssd *ssd) } - tl_data[bw*bw -1] = col0; - tl_data[bw*bw -2] = col0; - tl_data[(bw-1)*bw -1] = col0; - tl_data[(bw-1)*bw -2] = col0; - tr_data[(bw-1)*bw + (0)] = col0; - tr_data[(bw-1)*bw + (1)] = col1; - tr_data[(bw-2)*bw + (0)] = col0; - tr_data[(bw-2)*bw + (1)] = col0; - bl_data[(0)*bw + (bw-1)] = col0; - bl_data[(0)*bw + (bw-2)] = col0; - bl_data[(1)*bw + (bw-1)] = col1; - bl_data[(1)*bw + (bw-2)] = col0; - br_data[(0)*bw + (0)] = col1; - br_data[(0)*bw + (1)] = col1; - br_data[(1)*bw + (0)] = col1; - br_data[(1)*bw + (1)] = col1; - struct lab_data_buffer *ttexture_buffer = From 8c46add98a970882f592ab6a6ca148343d5a5ce3 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Wed, 25 Mar 2026 21:36:57 -0700 Subject: [PATCH 10/47] Bevels on OSD popup are now controlled by the toggle and honour the specified width --- src/workspaces.c | 68 ++++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/src/workspaces.c b/src/workspaces.c index 010bc837..1e715ac1 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -103,33 +103,49 @@ _osd_update(void) cairo_rectangle(cairo, 0, 0, width, height); cairo_fill(cairo); - - - /* Border */ - const float highlight[4] = { - theme->osd_bg_color[0] * 1.25, - theme->osd_bg_color[1] * 1.25, - theme->osd_bg_color[2] * 1.25, - theme->osd_bg_color[3] - }; - const float lowlight[4] = { - theme->osd_bg_color[0] / 2, - theme->osd_bg_color[1] / 2, - theme->osd_bg_color[2] / 2, - theme->osd_bg_color[3] - }; - set_cairo_color(cairo, highlight); - cairo_rectangle(cairo, 0, 0, width, 2); - cairo_fill(cairo); - cairo_rectangle(cairo, 0, 0, 2, height); - cairo_fill(cairo); - - set_cairo_color(cairo, lowlight); - cairo_rectangle(cairo, width-2, 0, width, height); - cairo_fill(cairo); - cairo_rectangle(cairo, 0, height-2, width, height); - cairo_fill(cairo); + if (theme->beveled_border) { + const float highlight[4] = { + MIN(theme->osd_border_color[0] * 5/4, theme->osd_border_color[3]), + MIN(theme->osd_border_color[1] * 5/4, theme->osd_border_color[3]), + MIN(theme->osd_border_color[2] * 5/4, theme->osd_border_color[3]), + theme->osd_border_color[3] + }; + const float lowlight[4] = { + theme->osd_border_color[0] / 2, + theme->osd_border_color[1] / 2, + theme->osd_border_color[2] / 2, + theme->osd_border_color[3] + }; + set_cairo_color(cairo, highlight); + cairo_new_path(cairo); + cairo_move_to(cairo, 0, 0); + cairo_line_to(cairo, width, 0); + cairo_line_to(cairo, width - theme->osd_border_width, theme->osd_border_width); + cairo_line_to(cairo, theme->osd_border_width, theme->osd_border_width); + cairo_line_to(cairo, theme->osd_border_width, height-theme->osd_border_width); + cairo_line_to(cairo, 0, height); + cairo_close_path(cairo); + cairo_fill(cairo); + + set_cairo_color(cairo, lowlight); + cairo_new_path(cairo); + cairo_move_to(cairo, width, 0); + cairo_line_to(cairo, width - theme->osd_border_width, theme->osd_border_width); + cairo_line_to(cairo, width - theme->osd_border_width, height-theme->osd_border_width); + cairo_line_to(cairo, theme->osd_border_width, height-theme->osd_border_width); + cairo_line_to(cairo, 0, height); + cairo_line_to(cairo, width, height); + cairo_close_path(cairo); + cairo_fill(cairo); + } else { + set_cairo_color(cairo, theme->osd_border_color); + struct wlr_fbox border_fbox = { + .width = width, + .height = height, + }; + draw_cairo_border(cairo, border_fbox, theme->osd_border_width); + } /* Boxes */ From 25b5ad08e40f7c40d39172096ef6baf7873d1377 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Thu, 26 Mar 2026 19:35:38 -0700 Subject: [PATCH 11/47] Handle the highlights on the window switcher with a different bevel that doesn't involve leaving crumbs --- include/common/lab-scene-rect.h | 1 + src/common/lab-scene-rect.c | 61 ++++++++++++++++++--------------- src/cycle/cycle.c | 1 + src/cycle/osd-classic.c | 2 ++ src/cycle/osd-scroll.c | 1 + src/cycle/osd-thumbnail.c | 2 ++ src/menu/menu.c | 1 + 7 files changed, 42 insertions(+), 27 deletions(-) diff --git a/include/common/lab-scene-rect.h b/include/common/lab-scene-rect.h index 51fe309b..da83154e 100644 --- a/include/common/lab-scene-rect.h +++ b/include/common/lab-scene-rect.h @@ -15,6 +15,7 @@ struct lab_scene_rect_options { float *bg_color; /* can be NULL */ int width; int height; + int beveled; }; struct lab_scene_rect { diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c index 65ddbfd3..7782c18d 100644 --- a/src/common/lab-scene-rect.c +++ b/src/common/lab-scene-rect.c @@ -33,8 +33,6 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, rect->nr_borders = opts->nr_borders; rect->borders = znew_n(rect->borders[0], opts->nr_borders); rect->tree = lab_wlr_scene_tree_create(parent); - - struct theme *theme = rc.theme; if (opts->bg_color) { rect->fill = lab_wlr_scene_rect_create(rect->tree, 0, 0, opts->bg_color); @@ -44,8 +42,10 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, struct border_scene *border = &rect->borders[i]; float *color = opts->border_colors[i]; border->tree = lab_wlr_scene_tree_create(rect->tree); - - if (theme->beveled_border) { + // Beveled mode 0 = normal outline + // Beveled mode 1 = full bevel with sharp internal corners + // Beveled mode 2 = "light" bevel without sharp corners. + if (opts->beveled > 0) { /* From Pull request 3382 */ int bw = rect->border_width; @@ -108,30 +108,34 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, } } - - struct lab_data_buffer *tltexture_buffer = - buffer_create_from_data(tl_data, bw, bw, 4*bw); - border->tlcorner = wlr_scene_buffer_create(parent, &tltexture_buffer->base); - wlr_buffer_drop(&tltexture_buffer->base); - - - struct lab_data_buffer *trtexture_buffer = - buffer_create_from_data(tr_data, bw, bw, 4*bw); - border->trcorner = wlr_scene_buffer_create(parent, &trtexture_buffer->base); - wlr_buffer_drop(&trtexture_buffer->base); + if (opts->beveled == 1) { + struct lab_data_buffer *tltexture_buffer = + buffer_create_from_data(tl_data, bw, bw, 4*bw); + border->tlcorner = wlr_scene_buffer_create(parent, &tltexture_buffer->base); + wlr_buffer_drop(&tltexture_buffer->base); - struct lab_data_buffer *bltexture_buffer = - buffer_create_from_data(bl_data, bw, bw, 4*bw); - border->blcorner = wlr_scene_buffer_create(parent, &bltexture_buffer->base); - wlr_buffer_drop(&bltexture_buffer->base); + struct lab_data_buffer *trtexture_buffer = + buffer_create_from_data(tr_data, bw, bw, 4*bw); + border->trcorner = wlr_scene_buffer_create(parent, &trtexture_buffer->base); + wlr_buffer_drop(&trtexture_buffer->base); - struct lab_data_buffer *brtexture_buffer = - buffer_create_from_data(br_data, bw, bw, 4*bw); - border->brcorner = wlr_scene_buffer_create(parent, &brtexture_buffer->base); - wlr_buffer_drop(&brtexture_buffer->base); - - + + struct lab_data_buffer *bltexture_buffer = + buffer_create_from_data(bl_data, bw, bw, 4*bw); + border->blcorner = wlr_scene_buffer_create(parent, &bltexture_buffer->base); + wlr_buffer_drop(&bltexture_buffer->base); + + struct lab_data_buffer *brtexture_buffer = + buffer_create_from_data(br_data, bw, bw, 4*bw); + border->brcorner = wlr_scene_buffer_create(parent, &brtexture_buffer->base); + wlr_buffer_drop(&brtexture_buffer->base); + } else { + border->tlcorner=NULL; + border->trcorner=NULL; + border->blcorner=NULL; + border->brcorner=NULL; + } @@ -140,6 +144,10 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, color); border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0, color); border->left = lab_wlr_scene_rect_create(border->tree, 0, 0, color); + border->tlcorner=NULL; + border->trcorner=NULL; + border->blcorner=NULL; + border->brcorner=NULL; } @@ -184,8 +192,7 @@ resize_border(struct border_scene *border, int border_width, int width, int heig 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); - struct theme *theme = rc.theme; - if (theme->beveled_border) { + if (border->tlcorner != NULL) { wlr_scene_buffer_set_dest_size(border->tlcorner, border_width, border_width); wlr_scene_node_set_position(&border->tlcorner->node, diff --git a/src/cycle/cycle.c b/src/cycle/cycle.c index 77195176..a06b9a36 100644 --- a/src/cycle/cycle.c +++ b/src/cycle/cycle.c @@ -37,6 +37,7 @@ update_preview_outlines(struct view *view) }, .nr_borders = 3, .border_width = theme->osd_window_switcher_preview_border_width, + .beveled = 1, // Checked }; rect = lab_scene_rect_create(&server.scene->tree, &opts); wlr_scene_node_place_above(&rect->tree->node, diff --git a/src/cycle/osd-classic.c b/src/cycle/osd-classic.c index 7e5abfb6..8fbb723d 100644 --- a/src/cycle/osd-classic.c +++ b/src/cycle/osd-classic.c @@ -120,6 +120,7 @@ cycle_osd_classic_init(struct cycle_osd_output *osd_output) .bg_color = bg_color, .width = w, .height = h, + .beveled = 1, }; lab_scene_rect_create(osd_output->tree, &bg_opts); @@ -202,6 +203,7 @@ cycle_osd_classic_init(struct cycle_osd_output *osd_output) .bg_color = active_bg_color, .width = w - 2 * padding, .height = switcher_theme->item_height, + .beveled = 2, }; struct lab_scene_rect *highlight_rect = lab_scene_rect_create( item->active_tree, &highlight_opts); diff --git a/src/cycle/osd-scroll.c b/src/cycle/osd-scroll.c index e788a479..d0d6b716 100644 --- a/src/cycle/osd-scroll.c +++ b/src/cycle/osd-scroll.c @@ -35,6 +35,7 @@ cycle_osd_scroll_init(struct cycle_osd_output *osd_output, struct wlr_box bar_ar .bg_color = bg_color, .width = bar_area.width, .height = bar_area.height * nr_visible_rows / nr_rows, + .beveled = 1, }; scroll->bar = lab_scene_rect_create(scroll->bar_tree, &scrollbar_opts); } diff --git a/src/cycle/osd-thumbnail.c b/src/cycle/osd-thumbnail.c index aa853987..6976f651 100644 --- a/src/cycle/osd-thumbnail.c +++ b/src/cycle/osd-thumbnail.c @@ -150,6 +150,7 @@ create_item_scene(struct wlr_scene_tree *parent, struct view *view, .bg_color = switcher_theme->item_active_bg_color, .width = switcher_theme->item_width, .height = switcher_theme->item_height, + .beveled = 2, }; item->active_bg = lab_scene_rect_create(tree, &opts); @@ -282,6 +283,7 @@ cycle_osd_thumbnail_init(struct cycle_osd_output *osd_output) .bg_color = theme->osd_bg_color, .width = items_width + 2 * padding, .height = items_height + 2 * padding, + .beveled = 1, }; struct lab_scene_rect *bg = lab_scene_rect_create(osd_output->tree, &bg_opts); diff --git a/src/menu/menu.c b/src/menu/menu.c index 251f9a30..0221e0dd 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -457,6 +457,7 @@ menu_create_scene(struct menu *menu) .border_width = theme->menu_border_width, .width = menu->size.width, .height = menu->size.height, + .beveled = 1, }; struct lab_scene_rect *bg_rect = lab_scene_rect_create(menu->scene_tree, &opts); From c2e251de98611f54b8e6ee44efac5eb6274a0374 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Thu, 26 Mar 2026 20:06:08 -0700 Subject: [PATCH 12/47] Document why the different bevel models exist --- src/common/lab-scene-rect.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c index 7782c18d..7b64f9bc 100644 --- a/src/common/lab-scene-rect.c +++ b/src/common/lab-scene-rect.c @@ -45,6 +45,9 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, // Beveled mode 0 = normal outline // Beveled mode 1 = full bevel with sharp internal corners // Beveled mode 2 = "light" bevel without sharp corners. + // This mode doesn't use the extra buffers. It seems like when we render the window switcher + // it wants to render the highlight buffers "immediately" and pollute the screen, but the sides + // work normally if (opts->beveled > 0) { /* From Pull request 3382 */ From 476626b7b585063690211681f64986c3a6a6889f Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Thu, 26 Mar 2026 21:28:36 -0700 Subject: [PATCH 13/47] Fix residue of plain borders left during a reload --- src/ssd/ssd-border.c | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index 170546f6..91815409 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -38,23 +38,19 @@ ssd_border_create(struct ssd *ssd) struct wlr_scene_tree *parent = subtree->tree; wlr_scene_node_set_enabled(&parent->node, active); float *color = theme->window[active].border_color; - - - subtree->left = lab_wlr_scene_rect_create(parent, - theme->border_width, height, color); - - subtree->right = lab_wlr_scene_rect_create(parent, - theme->border_width, height, color); - - subtree->bottom = lab_wlr_scene_rect_create(parent, - full_width, theme->border_width, color); - - subtree->top = lab_wlr_scene_rect_create(parent, - MAX(width - 2 * corner_width, 0), theme->border_width, color); - - - if (theme->beveled_border) { + + // These will otherwise get left under the window when we reload + + subtree->left = lab_wlr_scene_rect_create(parent, 1, 1, color); + + + subtree->right = lab_wlr_scene_rect_create(parent, 1, 1, color); + + subtree->bottom = lab_wlr_scene_rect_create(parent, 1, 1, color); + + subtree->top = lab_wlr_scene_rect_create(parent, 1, 1, color); + int bevelSize = theme->border_bevel_width; // TODO: configurable @@ -239,11 +235,19 @@ ssd_border_create(struct ssd *ssd) 4*theme->border_width); subtree->brcorner = wlr_scene_buffer_create(parent, &brtexture_buffer->base); wlr_buffer_drop(&brtexture_buffer->base); - } - - + } else { + + subtree->left = lab_wlr_scene_rect_create(parent, + theme->border_width, height, color); - if (!theme->beveled_border) { + subtree->right = lab_wlr_scene_rect_create(parent, + theme->border_width, height, color); + + subtree->bottom = lab_wlr_scene_rect_create(parent, + full_width, theme->border_width, color); + + subtree->top = lab_wlr_scene_rect_create(parent, + MAX(width - 2 * corner_width, 0), theme->border_width, color); wlr_scene_node_set_position(&subtree->left->node, 0, 0); wlr_scene_node_set_position(&subtree->right->node, theme->border_width + width, 0); From f7d2be37ea923fd85f2a42af180e31786a5335c3 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Thu, 26 Mar 2026 21:50:55 -0700 Subject: [PATCH 14/47] Clean up codesniffer issues --- include/common/lab-scene-rect.h | 3 --- include/common/macros.h | 5 ++--- include/ssd-internal.h | 3 ++- src/common/lab-scene-rect.c | 2 -- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/include/common/lab-scene-rect.h b/include/common/lab-scene-rect.h index da83154e..d79d879d 100644 --- a/include/common/lab-scene-rect.h +++ b/include/common/lab-scene-rect.h @@ -3,9 +3,6 @@ #define LABWC_LAB_SCENE_RECT_H #include - -// Ensure we can access theme data to decide if we need bevels -extern struct rcxml rc; struct wlr_scene_tree; struct lab_scene_rect_options { diff --git a/include/common/macros.h b/include/common/macros.h index 9bcbe20c..7fb5d0dc 100644 --- a/include/common/macros.h +++ b/include/common/macros.h @@ -65,7 +65,6 @@ #define LAB_WLR_VERSION_AT_LEAST(major, minor, micro) \ (WLR_VERSION_NUM >= (((major) << 16) | ((minor) << 8) | (micro))) - /** * PIXEL () - calculate pixel offset in an array of "bw" columns wide. * @@ -73,7 +72,7 @@ * @param y y-coordinate * Assumes "bw" was defined externally */ - -#define PIXEL(x,y) (bw * y + x) + +#define PIXEL(x, y) (bw * y + x) #endif /* LABWC_MACROS_H */ diff --git a/include/ssd-internal.h b/include/ssd-internal.h index de91d558..965944dc 100644 --- a/include/ssd-internal.h +++ b/include/ssd-internal.h @@ -115,7 +115,8 @@ struct ssd { struct ssd_border_subtree { struct wlr_scene_tree *tree; struct wlr_scene_rect *top, *bottom, *left, *right; - struct wlr_scene_buffer *tlcorner, *trcorner, *blcorner, *brcorner, *ttexture, *btexture, *ltexture, *rtexture; + struct wlr_scene_buffer *tlcorner, *trcorner, *blcorner, *brcorner, + *ttexture, *btexture, *ltexture, *rtexture; } subtrees[2]; /* indexed by enum ssd_active_state */ } border; diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c index 7b64f9bc..93b750e1 100644 --- a/src/common/lab-scene-rect.c +++ b/src/common/lab-scene-rect.c @@ -6,8 +6,6 @@ #include "common/scene-helpers.h" #include "common/macros.h" #include "buffer.h" -#include "config/rcxml.h" -#include "theme.h" struct border_scene { struct wlr_scene_tree *tree; From c37f343377089295a36902dc357bea3c8ea4f8fb Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Fri, 27 Mar 2026 19:13:11 -0700 Subject: [PATCH 15/47] Fix incorect border drawing and remove light borders as no longer needed --- src/common/lab-scene-rect.c | 47 ++++++++++++++----------------------- src/cycle/osd-classic.c | 2 +- src/cycle/osd-thumbnail.c | 2 +- 3 files changed, 19 insertions(+), 32 deletions(-) diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c index 93b750e1..a6802117 100644 --- a/src/common/lab-scene-rect.c +++ b/src/common/lab-scene-rect.c @@ -42,10 +42,6 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, border->tree = lab_wlr_scene_tree_create(rect->tree); // Beveled mode 0 = normal outline // Beveled mode 1 = full bevel with sharp internal corners - // Beveled mode 2 = "light" bevel without sharp corners. - // This mode doesn't use the extra buffers. It seems like when we render the window switcher - // it wants to render the highlight buffers "immediately" and pollute the screen, but the sides - // work normally if (opts->beveled > 0) { /* From Pull request 3382 */ @@ -109,37 +105,28 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, } } - if (opts->beveled == 1) { - struct lab_data_buffer *tltexture_buffer = - buffer_create_from_data(tl_data, bw, bw, 4*bw); - border->tlcorner = wlr_scene_buffer_create(parent, &tltexture_buffer->base); - wlr_buffer_drop(&tltexture_buffer->base); + + struct lab_data_buffer *tltexture_buffer = + buffer_create_from_data(tl_data, bw, bw, 4*bw); + border->tlcorner = wlr_scene_buffer_create(border->tree, &tltexture_buffer->base); + wlr_buffer_drop(&tltexture_buffer->base); - struct lab_data_buffer *trtexture_buffer = - buffer_create_from_data(tr_data, bw, bw, 4*bw); - border->trcorner = wlr_scene_buffer_create(parent, &trtexture_buffer->base); - wlr_buffer_drop(&trtexture_buffer->base); + struct lab_data_buffer *trtexture_buffer = + buffer_create_from_data(tr_data, bw, bw, 4*bw); + border->trcorner = wlr_scene_buffer_create(border->tree, &trtexture_buffer->base); + wlr_buffer_drop(&trtexture_buffer->base); - struct lab_data_buffer *bltexture_buffer = - buffer_create_from_data(bl_data, bw, bw, 4*bw); - border->blcorner = wlr_scene_buffer_create(parent, &bltexture_buffer->base); - wlr_buffer_drop(&bltexture_buffer->base); + struct lab_data_buffer *bltexture_buffer = + buffer_create_from_data(bl_data, bw, bw, 4*bw); + border->blcorner = wlr_scene_buffer_create(border->tree, &bltexture_buffer->base); + wlr_buffer_drop(&bltexture_buffer->base); - struct lab_data_buffer *brtexture_buffer = - buffer_create_from_data(br_data, bw, bw, 4*bw); - border->brcorner = wlr_scene_buffer_create(parent, &brtexture_buffer->base); - wlr_buffer_drop(&brtexture_buffer->base); - } else { - border->tlcorner=NULL; - border->trcorner=NULL; - border->blcorner=NULL; - border->brcorner=NULL; - } - - - + struct lab_data_buffer *brtexture_buffer = + buffer_create_from_data(br_data, bw, bw, 4*bw); + border->brcorner = wlr_scene_buffer_create(border->tree, &brtexture_buffer->base); + wlr_buffer_drop(&brtexture_buffer->base); } else { border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, color); border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, color); diff --git a/src/cycle/osd-classic.c b/src/cycle/osd-classic.c index 8fbb723d..9cfd3cea 100644 --- a/src/cycle/osd-classic.c +++ b/src/cycle/osd-classic.c @@ -203,7 +203,7 @@ cycle_osd_classic_init(struct cycle_osd_output *osd_output) .bg_color = active_bg_color, .width = w - 2 * padding, .height = switcher_theme->item_height, - .beveled = 2, + .beveled = 1, }; struct lab_scene_rect *highlight_rect = lab_scene_rect_create( item->active_tree, &highlight_opts); diff --git a/src/cycle/osd-thumbnail.c b/src/cycle/osd-thumbnail.c index 6976f651..699fc1be 100644 --- a/src/cycle/osd-thumbnail.c +++ b/src/cycle/osd-thumbnail.c @@ -150,7 +150,7 @@ create_item_scene(struct wlr_scene_tree *parent, struct view *view, .bg_color = switcher_theme->item_active_bg_color, .width = switcher_theme->item_width, .height = switcher_theme->item_height, - .beveled = 2, + .beveled = 1, }; item->active_bg = lab_scene_rect_create(tree, &opts); From 2a0ff0d5b44ebf6c205428f57ec210443870bb8f Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Fri, 27 Mar 2026 20:24:24 -0700 Subject: [PATCH 16/47] Initial use of a centralized caching border generator --- include/common/borderset.h | 30 +++++++++ include/common/macros.h | 5 +- src/common/borderset.c | 115 +++++++++++++++++++++++++++++++++ src/common/lab-scene-rect.c | 122 ++++++++++++++++++------------------ src/common/meson.build | 1 + src/main.c | 3 + src/server.c | 3 + 7 files changed, 218 insertions(+), 61 deletions(-) create mode 100644 include/common/borderset.h create mode 100644 src/common/borderset.c diff --git a/include/common/borderset.h b/include/common/borderset.h new file mode 100644 index 00000000..2339b98a --- /dev/null +++ b/include/common/borderset.h @@ -0,0 +1,30 @@ +#include +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef LABWC_BORDERSET_H +#define LABWC_BORDERSET_H + +struct borderset { + uint32_t id; // Base colour, but could be used as a tracking hash for images or whatever in the future + int size; // width (since I suspect a 2px border scaled up to 20px might look weird) + int type; // Single or double bevel + uint32_t * top; + uint32_t * left; + uint32_t * right; + uint32_t * bottom; + uint32_t * tl; + uint32_t * tr; + uint32_t * bl; + uint32_t * br; + struct borderset * next; +}; + + +extern struct borderset * borderCache; + +struct borderset * getBorders(uint32_t id, int size, int type); + +struct borderset * createBuffer(uint32_t id, int size, int type); + +void clearBorderCache(struct borderset *borderset); + +#endif /* LABWC_LAB_SCENE_RECT_H */ diff --git a/include/common/macros.h b/include/common/macros.h index 7fb5d0dc..46a42fd4 100644 --- a/include/common/macros.h +++ b/include/common/macros.h @@ -66,13 +66,16 @@ (WLR_VERSION_NUM >= (((major) << 16) | ((minor) << 8) | (micro))) /** - * PIXEL () - calculate pixel offset in an array of "bw" columns wide. + * PIXEL () - calculate pixel offset in an array * * @param x x-coordinate * @param y y-coordinate + * @param size width of the buffer in pixes * Assumes "bw" was defined externally */ #define PIXEL(x, y) (bw * y + x) +#define PIXELSIZED(x, y, size) (size * y + x) + #endif /* LABWC_MACROS_H */ diff --git a/src/common/borderset.c b/src/common/borderset.c new file mode 100644 index 00000000..f4e352b5 --- /dev/null +++ b/src/common/borderset.c @@ -0,0 +1,115 @@ +#include "common/borderset.h" +#include "common/mem.h" +#include "common/macros.h" + + +struct borderset * getBorders(uint32_t id, int size, int type) { + struct borderset * current = borderCache; + struct borderset * last; + while (current != NULL) { + if (current->size == size && current->id == id && current->type == type) { + return current; + } + last = current; + current = current -> next; + } + // Fall through, we need to create a buffer. + + if (borderCache == NULL) { + borderCache = createBuffer(id, size, type); + return borderCache; + } else { + last->next = createBuffer(id, size, type); + return last->next; + } + return NULL; +} + +struct borderset * createBuffer(uint32_t id, int size, int type) { + struct borderset *newBorderset = znew(*newBorderset); + + newBorderset->next = NULL; + newBorderset->id = id; + newBorderset->size = size; + newBorderset->type = type; + + + // Use ID as a AARRGGBB colour + uint8_t a = id >> 24 & 255; + uint8_t r = id >> 16 & 255; + uint8_t g = id >> 8 & 255; + uint8_t b = id & 255; + + uint32_t r1 = r * 5 / 4; + if (r1 > a) r1=a; + uint32_t g1 = g * 5 / 4; + if (g1 > a) g1=a; + uint32_t b1 = b * 5 / 4; + if (b1 > a) b1=a; + + /* darker outline */ + uint32_t r0 = r / 2; + uint32_t g0 = g / 2; + uint32_t b0 = b / 2; + + uint32_t hl32 = ((uint32_t)a << 24) | ((uint32_t)r1 << 16) + | ((uint32_t)g1 << 8) | (uint32_t)b1; + uint32_t ll32 = ((uint32_t)a << 24) | ((uint32_t)r0 << 16) + | ((uint32_t)g0 << 8) | (uint32_t)b0; + + + newBorderset->tl = znew_n(uint32_t, size*size); + newBorderset->tr = znew_n(uint32_t, size*size); + newBorderset->bl = znew_n(uint32_t, size*size); + newBorderset->br = znew_n(uint32_t, size*size); + newBorderset->top = znew(uint32_t); + newBorderset->left = znew(uint32_t); + newBorderset->right = znew(uint32_t); + newBorderset->bottom = znew(uint32_t); + switch(type) { + case 1: + *newBorderset->top = hl32; + *newBorderset->left = hl32; + *newBorderset->right = ll32; + *newBorderset->bottom = ll32; + + // Fill with solid + for (int j=0; jtl[PIXELSIZED(j, k, size)] = hl32; + newBorderset->tr[PIXELSIZED(size - 1 - j, k, size)] = (j > k) ? hl32 : ll32; + newBorderset->bl[PIXELSIZED(size - 1 -j, k, size)] = (j > k) ? hl32 : ll32; + newBorderset->br[PIXELSIZED(j, k, size)] = ll32; + } + } + + + + break; + + + case 2: + + break; + + } + return newBorderset; +} + +void clearBorderCache(struct borderset * borderset) +{ + if (borderset == NULL) + return; + if (borderset->next != NULL) { + clearBorderCache(borderset->next); + } + free(borderset->top); + free(borderset->left); + free(borderset->right); + free(borderset->bottom); + free(borderset->tl); + free(borderset->tr); + free(borderset->bl); + free(borderset->br); + free(borderset); +} diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c index a6802117..e652e452 100644 --- a/src/common/lab-scene-rect.c +++ b/src/common/lab-scene-rect.c @@ -5,12 +5,14 @@ #include "common/mem.h" #include "common/scene-helpers.h" #include "common/macros.h" +#include "common/borderset.h" #include "buffer.h" struct border_scene { struct wlr_scene_tree *tree; struct wlr_scene_rect *top, *bottom, *left, *right; - struct wlr_scene_buffer *tlcorner, *trcorner, *blcorner, *brcorner; + struct wlr_scene_buffer *tlcorner, *trcorner, *blcorner, *brcorner, + *ttexture, *ltexture, *rtexture, *btexture; }; static void @@ -43,90 +45,65 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, // Beveled mode 0 = normal outline // Beveled mode 1 = full bevel with sharp internal corners if (opts->beveled > 0) { - /* From Pull request 3382 */ - - int bw = rect->border_width; - - // Floats for the rect versions. + float r = color[0]; float g = color[1]; float b = color[2]; float a = color[3]; - - - float r1 = r * 5 / 4; - if (r1 > a) r1=a; - float g1 = g * 5 / 4; - if (g1 > a) g1=a; - float b1 = b * 5 / 4; - if (b1 > a) b1=a; - - /* darker outline */ - float r0 = r / 2; - float g0 = g / 2; - float b0 = b / 2; + int bw = rect->border_width; + uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); + struct borderset * renderedborders = getBorders(colour32, bw, 1); + + - // Buffers are AARRGGBB 32-bit packed int - uint32_t ll32 = ((uint32_t)(255*a) << 24) | ((uint32_t)(255*r0) << 16) - | ((uint32_t)(255*g0) << 8) | (uint32_t)(255*b0); - uint32_t hl32 = ((uint32_t)(255*a) << 24) | ((uint32_t)(255*r1) << 16) - | ((uint32_t)(255*g1) << 8) | (uint32_t)(255*b1); - const float highlight[4] = {r1, g1, b1, a}; - const float lowlight[4] = {r0, g0, b0, a}; - - - - - - border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, highlight); - border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, lowlight); - border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0, lowlight); - border->left = lab_wlr_scene_rect_create(border->tree, 0, 0, highlight); - - - - uint32_t *tl_data = znew_n(uint32_t, bw*bw); - uint32_t *tr_data = znew_n(uint32_t, bw*bw); - uint32_t *bl_data = znew_n(uint32_t, bw*bw); - uint32_t *br_data = znew_n(uint32_t, bw*bw); - - // Fill with solid - for (int j=0; j k) ? hl32 : ll32; - bl_data[PIXEL(bw - 1 -j, k)] = (j > k) ? hl32 : ll32; - br_data[PIXEL(j, k)] = ll32; - } - } + + + + border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, color); + border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, color); + border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0, color); + border->left = lab_wlr_scene_rect_create(border->tree, 0, 0, color); + + struct lab_data_buffer *ttexture_buffer = + buffer_create_from_data(renderedborders->top, 1, 1, 4); + border->ttexture = wlr_scene_buffer_create(border->tree, &ttexture_buffer->base); + + struct lab_data_buffer *ltexture_buffer = + buffer_create_from_data(renderedborders->left, 1, 1, 4); + border->ltexture = wlr_scene_buffer_create(border->tree, <exture_buffer->base); + + struct lab_data_buffer *rtexture_buffer = + buffer_create_from_data(renderedborders->right, 1, 1, 4); + border->rtexture = wlr_scene_buffer_create(border->tree, &rtexture_buffer->base); + + struct lab_data_buffer *btexture_buffer = + buffer_create_from_data(renderedborders->bottom, 1, 1, 4); + border->btexture = wlr_scene_buffer_create(border->tree, &btexture_buffer->base); + struct lab_data_buffer *tltexture_buffer = - buffer_create_from_data(tl_data, bw, bw, 4*bw); + buffer_create_from_data(renderedborders->tl, bw, bw, 4*bw); border->tlcorner = wlr_scene_buffer_create(border->tree, &tltexture_buffer->base); - wlr_buffer_drop(&tltexture_buffer->base); struct lab_data_buffer *trtexture_buffer = - buffer_create_from_data(tr_data, bw, bw, 4*bw); + buffer_create_from_data(renderedborders->tr, bw, bw, 4*bw); border->trcorner = wlr_scene_buffer_create(border->tree, &trtexture_buffer->base); - wlr_buffer_drop(&trtexture_buffer->base); struct lab_data_buffer *bltexture_buffer = - buffer_create_from_data(bl_data, bw, bw, 4*bw); + buffer_create_from_data(renderedborders->bl, bw, bw, 4*bw); border->blcorner = wlr_scene_buffer_create(border->tree, &bltexture_buffer->base); - wlr_buffer_drop(&bltexture_buffer->base); struct lab_data_buffer *brtexture_buffer = - buffer_create_from_data(br_data, bw, bw, 4*bw); + buffer_create_from_data(renderedborders->br, bw, bw, 4*bw); border->brcorner = wlr_scene_buffer_create(border->tree, &brtexture_buffer->base); - wlr_buffer_drop(&brtexture_buffer->base); } else { border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, color); border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, color); @@ -181,6 +158,31 @@ resize_border(struct border_scene *border, int border_width, int width, int heig wlr_scene_rect_set_size(border->right, border_width, height - border_width * 2); if (border->tlcorner != NULL) { + wlr_scene_buffer_set_dest_size(border->ttexture, + width, border_width); + wlr_scene_node_set_position(&border->ttexture->node, + 0,0); + + wlr_scene_buffer_set_dest_size(border->btexture, + width, border_width); + wlr_scene_node_set_position(&border->btexture->node, + 0, height - border_width); + + + wlr_scene_buffer_set_dest_size(border->ltexture, + border_width, height - border_width * 2); + wlr_scene_node_set_position(&border->ltexture->node, + 0, border_width); + + wlr_scene_buffer_set_dest_size(border->rtexture, + border_width, height - border_width * 2); + wlr_scene_node_set_position(&border->rtexture->node, + width - border_width, border_width); + + + + + wlr_scene_buffer_set_dest_size(border->tlcorner, border_width, border_width); wlr_scene_node_set_position(&border->tlcorner->node, diff --git a/src/common/meson.build b/src/common/meson.build index 4cf52023..d9b24b23 100644 --- a/src/common/meson.build +++ b/src/common/meson.build @@ -1,4 +1,5 @@ labwc_sources += files( + 'borderset.c', 'box.c', 'buf.c', 'dir.c', diff --git a/src/main.c b/src/main.c index 373f4480..9b5d65b6 100644 --- a/src/main.c +++ b/src/main.c @@ -13,6 +13,7 @@ #include "theme.h" #include "translate.h" #include "menu/menu.h" +#include "common/borderset.h" /* * Globals @@ -40,6 +41,8 @@ static const struct option long_options[] = { {0, 0, 0, 0} }; +struct borderset * borderCache = NULL; + static const char labwc_usage[] = "Usage: labwc [options...]\n" " -c, --config Specify config file (with path)\n" diff --git a/src/server.c b/src/server.c index c5ca9fff..4461c042 100644 --- a/src/server.c +++ b/src/server.c @@ -69,6 +69,7 @@ #include "view.h" #include "workspaces.h" #include "xwayland.h" +#include "common/borderset.h" #define LAB_EXT_DATA_CONTROL_VERSION 1 #define LAB_EXT_FOREIGN_TOPLEVEL_LIST_VERSION 1 @@ -100,6 +101,8 @@ reload_config_and_theme(void) } cycle_finish(/*switch_focus*/ false); + clearBorderCache(borderCache); + borderCache = NULL; menu_reconfigure(); seat_reconfigure(); regions_reconfigure(); From 536847cb5b16c9092469294d0c5a3c44d03264e3 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Fri, 27 Mar 2026 20:57:28 -0700 Subject: [PATCH 17/47] Use cache for title bar double beveled borders --- include/common/borderset.h | 4 +- src/common/borderset.c | 127 +++++++++++++++++++++++++--- src/common/lab-scene-rect.c | 2 +- src/server.c | 6 +- src/ssd/ssd-border.c | 164 +++++------------------------------- 5 files changed, 143 insertions(+), 160 deletions(-) diff --git a/include/common/borderset.h b/include/common/borderset.h index 2339b98a..f0fc170d 100644 --- a/include/common/borderset.h +++ b/include/common/borderset.h @@ -21,9 +21,9 @@ struct borderset { extern struct borderset * borderCache; -struct borderset * getBorders(uint32_t id, int size, int type); +struct borderset * getBorders(uint32_t id, int size, int type, int bevelSize); -struct borderset * createBuffer(uint32_t id, int size, int type); +struct borderset * createBuffer(uint32_t id, int size, int type, int bevelSize); void clearBorderCache(struct borderset *borderset); diff --git a/src/common/borderset.c b/src/common/borderset.c index f4e352b5..2f80fc85 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -2,8 +2,7 @@ #include "common/mem.h" #include "common/macros.h" - -struct borderset * getBorders(uint32_t id, int size, int type) { +struct borderset * getBorders(uint32_t id, int size, int type, int bevelSize) { struct borderset * current = borderCache; struct borderset * last; while (current != NULL) { @@ -16,16 +15,16 @@ struct borderset * getBorders(uint32_t id, int size, int type) { // Fall through, we need to create a buffer. if (borderCache == NULL) { - borderCache = createBuffer(id, size, type); + borderCache = createBuffer(id, size, type, bevelSize); return borderCache; } else { - last->next = createBuffer(id, size, type); + last->next = createBuffer(id, size, type, bevelSize); return last->next; } return NULL; } -struct borderset * createBuffer(uint32_t id, int size, int type) { +struct borderset * createBuffer(uint32_t id, int size, int type, int bevelSize) { struct borderset *newBorderset = znew(*newBorderset); newBorderset->next = NULL; @@ -57,17 +56,19 @@ struct borderset * createBuffer(uint32_t id, int size, int type) { uint32_t ll32 = ((uint32_t)a << 24) | ((uint32_t)r0 << 16) | ((uint32_t)g0 << 8) | (uint32_t)b0; - + + // All borders have NxN corners newBorderset->tl = znew_n(uint32_t, size*size); newBorderset->tr = znew_n(uint32_t, size*size); newBorderset->bl = znew_n(uint32_t, size*size); newBorderset->br = znew_n(uint32_t, size*size); - newBorderset->top = znew(uint32_t); - newBorderset->left = znew(uint32_t); - newBorderset->right = znew(uint32_t); - newBorderset->bottom = znew(uint32_t); + switch(type) { - case 1: + case 1: // Single bevel borders have 1x1 sides + newBorderset->top = znew(uint32_t); + newBorderset->left = znew(uint32_t); + newBorderset->right = znew(uint32_t); + newBorderset->bottom = znew(uint32_t); *newBorderset->top = hl32; *newBorderset->left = hl32; *newBorderset->right = ll32; @@ -89,6 +90,109 @@ struct borderset * createBuffer(uint32_t id, int size, int type) { case 2: + newBorderset->top = znew_n(uint32_t, size); + newBorderset->left = znew_n(uint32_t, size); + newBorderset->right = znew_n(uint32_t, size); + newBorderset->bottom = znew_n(uint32_t, size); + + for (int i = 0; i < size; i++) { + if (ileft[i] = hl32; + newBorderset->top[i] = hl32; + newBorderset->right[i] = hl32; + newBorderset->bottom[i] = hl32; + + } else if (i > (size-bevelSize-1)) { + newBorderset->left[i] = ll32; + newBorderset->top[i] = ll32; + newBorderset->right[i] = ll32; + newBorderset->bottom[i] = ll32; + + } else { + newBorderset->left[i] = id; + newBorderset->top[i] = id; + newBorderset->right[i] = id; + newBorderset->bottom[i] = id; + } + } + + // Blank corners... + for (int i=0; itl[PIXELSIZED(i, j, size)] = id; + newBorderset->tr[PIXELSIZED(i, j, size)] = id; + newBorderset->bl[PIXELSIZED(i, j, size)] = id; + newBorderset->br[PIXELSIZED(i, j, size)] = id; + } + } + + + // Main Corners + for (int i=0; i < bevelSize; i++) { + + // Solid bar parts + for (int j=0; jtl[PIXELSIZED(j, i, size)] = hl32; + // First "bevel size" top columns are highlighted + newBorderset->tl[PIXELSIZED(i, j, size)] = hl32; + + // Bottom Right corner: Entire "bevel size" last rows are lowlight + newBorderset->br[PIXELSIZED(j, (size-1-i), size)] = ll32; + // Last "bevel size" columns are lowlight + newBorderset->br[PIXELSIZED((size-1-i), j, size)] = ll32; + + + // Bottom left corner: Entire "bevel size" last rows are lowlight + newBorderset->bl[PIXELSIZED(j, (size-1-i), size)] = ll32; + // First "bevel size" columns are highlight, except for the bottom right corner + newBorderset->bl[PIXELSIZED(i, j, size)] = hl32; + + // Top Right corner: Entire "bevel size" first rows are highlight + newBorderset->tr[PIXELSIZED(j, i, size)] = hl32; + // Last "bevel size" columns are lowlight, except for the top left + newBorderset->tr[PIXELSIZED((size-1-i), j, size)] = ll32; + + } + } + // Beveled Corner Parts + for (int i=0; i < bevelSize; i++) { + + for (int j=0; jbl[PIXELSIZED(i, (size - 1 - j), size)] = (j >= i) ? hl32 : ll32; + + // Top Right corner: + // Last "bevel size" columns are lowlight, except for the top left + newBorderset->tr[PIXELSIZED((size-1-i), j, size)] = (j > i) ? ll32 : hl32; + + + // Inner Corners + // Top left corner: Bottom right is all dark + newBorderset->tl[PIXELSIZED((size-1-i), (size - 1 - j), size)] = ll32; + + // Bottom Right corner: Top left is all light + newBorderset->br[PIXELSIZED(i, j, size)] = hl32; + + // Top Right corner: + // Interior bottom left is dark on top, light on bottom + newBorderset->tr[PIXELSIZED(i, (size-1-j), size)] = (i > j) ? hl32 : ll32; + + // Bottom Left corner: + // Interior top right is dark on top, light on bottom + newBorderset->bl[PIXELSIZED((size-1-i), j, size)] = (i > j) ? ll32 : hl32; + + + + } + + + } + + + break; @@ -103,6 +207,7 @@ void clearBorderCache(struct borderset * borderset) if (borderset->next != NULL) { clearBorderCache(borderset->next); } + free(borderset->top); free(borderset->left); free(borderset->right); diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c index e652e452..cebab211 100644 --- a/src/common/lab-scene-rect.c +++ b/src/common/lab-scene-rect.c @@ -52,7 +52,7 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, float a = color[3]; int bw = rect->border_width; uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, 1); + struct borderset * renderedborders = getBorders(colour32, bw, 1, 0); diff --git a/src/server.c b/src/server.c index 4461c042..3a3c2573 100644 --- a/src/server.c +++ b/src/server.c @@ -86,6 +86,10 @@ reload_config_and_theme(void) scaled_buffer_invalidate_sharing(); rcxml_finish(); + clearBorderCache(borderCache); + borderCache = NULL; + + rcxml_read(rc.config_file); theme_finish(rc.theme); theme_init(rc.theme, rc.theme_name); @@ -101,8 +105,6 @@ reload_config_and_theme(void) } cycle_finish(/*switch_focus*/ false); - clearBorderCache(borderCache); - borderCache = NULL; menu_reconfigure(); seat_reconfigure(); regions_reconfigure(); diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index 91815409..1309e752 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -11,6 +11,7 @@ #include "ssd-internal.h" #include "theme.h" #include "view.h" +#include "common/borderset.h" @@ -56,185 +57,60 @@ ssd_border_create(struct ssd *ssd) int bevelSize = theme->border_bevel_width; // TODO: configurable /* From Pull request 3382 */ - uint8_t r = color[0] * 255; - uint8_t g = color[1] * 255; - uint8_t b = color[2] * 255; - uint8_t a = color[3] * 255; - - /* highlight */ - uint8_t r1 = MIN(r * 5 / 4, a); - uint8_t g1 = MIN(g * 5 / 4, a); - uint8_t b1 = MIN(b * 5 / 4, a); - - /* darker outline */ - uint8_t r0 = r / 2; - uint8_t g0 = g / 2; - uint8_t b0 = b / 2; - - uint32_t col = ((uint32_t)a << 24) | ((uint32_t)r << 16) - | ((uint32_t)g << 8) | b; - uint32_t col0 = ((uint32_t)a << 24) | ((uint32_t)r0 << 16) - | ((uint32_t)g0 << 8) | b0; - uint32_t col1 = ((uint32_t)a << 24) | ((uint32_t)r1 << 16) - | ((uint32_t)g1 << 8) | b1; - - - uint32_t *left_data = znew_n(uint32_t, bw); - uint32_t *top_data = znew_n(uint32_t, bw); - uint32_t *right_data = znew_n(uint32_t, theme->border_width); - uint32_t *bottom_data = znew_n(uint32_t, theme->border_width); - - for (int i = 0; i < bw; i++) { - if (i (bw-bevelSize-1)) { - left_data[i] = col0; - top_data[i] = col0; - right_data[i] = col0; - bottom_data[i] = col0; - - } else { - left_data[i] = col; - top_data[i] = col; - right_data[i] = col; - bottom_data[i] = col; - } - } - - - uint32_t *tl_data = znew_n(uint32_t, bw*bw); - uint32_t *tr_data = znew_n(uint32_t, bw*bw); - uint32_t *bl_data = znew_n(uint32_t, bw*bw); - uint32_t *br_data = znew_n(uint32_t, bw*bw); - // Fill with solid - for (int i=0; i= i) ? col1 : col0; - - // Top Right corner: - // Last "bevel size" columns are lowlight, except for the top left - tr_data[PIXEL((bw-1-i), j)] = (j > i) ? col0 : col1; - - - // Inner Corners - // Top left corner: Bottom right is all dark - tl_data[PIXEL((bw-1-i), (bw - 1 - j))] = col0; - - // Bottom Right corner: Top left is all light - br_data[PIXEL(i, j)] = col1; - - // Top Right corner: - // Interior bottom left is dark on top, light on bottom - tr_data[PIXEL(i, (bw-1-j))] = (i > j) ? col1 : col0; - - // Bottom Left corner: - // Interior top right is dark on top, light on bottom - bl_data[PIXEL((bw-1-i), j)] = (i > j) ? col0 : col1; - - - - } - - - } + float r = color[0]; + float g = color[1]; + float b = color[2]; + float a = color[3]; + uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); + struct borderset * renderedborders = getBorders(colour32, bw, 2, bevelSize); struct lab_data_buffer *ttexture_buffer = - buffer_create_from_data(top_data, 1,theme->border_width, + buffer_create_from_data(renderedborders->top, 1,theme->border_width, 4); subtree->ttexture = wlr_scene_buffer_create(parent, &ttexture_buffer->base); - wlr_buffer_drop(&ttexture_buffer->base); + struct lab_data_buffer *btexture_buffer = - buffer_create_from_data(bottom_data, 1,theme->border_width, + buffer_create_from_data(renderedborders->bottom, 1,theme->border_width, 4); subtree->btexture = wlr_scene_buffer_create(parent, &btexture_buffer->base); - wlr_buffer_drop(&btexture_buffer->base); + struct lab_data_buffer *ltexture_buffer = - buffer_create_from_data(left_data, theme->border_width, 1, + buffer_create_from_data(renderedborders->left, theme->border_width, 1, 4*theme->border_width); subtree->ltexture = wlr_scene_buffer_create(parent, <exture_buffer->base); - wlr_buffer_drop(<exture_buffer->base); + struct lab_data_buffer *rtexture_buffer = - buffer_create_from_data(right_data, theme->border_width, 1, + buffer_create_from_data(renderedborders->right, theme->border_width, 1, 4*theme->border_width); subtree->rtexture = wlr_scene_buffer_create(parent, &rtexture_buffer->base); - wlr_buffer_drop(&rtexture_buffer->base); + struct lab_data_buffer *tltexture_buffer = - buffer_create_from_data(tl_data, theme->border_width, theme->border_width, + buffer_create_from_data(renderedborders->tl, theme->border_width, theme->border_width, 4*theme->border_width); subtree->tlcorner = wlr_scene_buffer_create(parent, &tltexture_buffer->base); - wlr_buffer_drop(&tltexture_buffer->base); struct lab_data_buffer *trtexture_buffer = - buffer_create_from_data(tr_data, theme->border_width, theme->border_width, + buffer_create_from_data(renderedborders->tr, theme->border_width, theme->border_width, 4*theme->border_width); subtree->trcorner = wlr_scene_buffer_create(parent, &trtexture_buffer->base); - wlr_buffer_drop(&trtexture_buffer->base); + struct lab_data_buffer *bltexture_buffer = - buffer_create_from_data(bl_data, theme->border_width, theme->border_width, + buffer_create_from_data(renderedborders->bl, theme->border_width, theme->border_width, 4*theme->border_width); subtree->blcorner = wlr_scene_buffer_create(parent, &bltexture_buffer->base); - wlr_buffer_drop(&bltexture_buffer->base); struct lab_data_buffer *brtexture_buffer = - buffer_create_from_data(br_data, theme->border_width, theme->border_width, + buffer_create_from_data(renderedborders->br, theme->border_width, theme->border_width, 4*theme->border_width); subtree->brcorner = wlr_scene_buffer_create(parent, &brtexture_buffer->base); - wlr_buffer_drop(&brtexture_buffer->base); } else { subtree->left = lab_wlr_scene_rect_create(parent, From adc2c911ffcda516b0ebadef1fed2f4427dbc948 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Fri, 27 Mar 2026 23:11:40 -0700 Subject: [PATCH 18/47] Use rendered borders with Cairo overlay for desktop switching OSD --- src/common/lab-scene-rect.c | 30 +++++------ src/workspaces.c | 104 ++++++++++++++++++++++++------------ 2 files changed, 86 insertions(+), 48 deletions(-) diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c index cebab211..9dc0921f 100644 --- a/src/common/lab-scene-rect.c +++ b/src/common/lab-scene-rect.c @@ -184,26 +184,26 @@ resize_border(struct border_scene *border, int border_width, int width, int heig wlr_scene_buffer_set_dest_size(border->tlcorner, - border_width, border_width); - wlr_scene_node_set_position(&border->tlcorner->node, - 0,0); + border_width, border_width); + wlr_scene_node_set_position(&border->tlcorner->node, + 0,0); - wlr_scene_buffer_set_dest_size(border->trcorner, - border_width, border_width); - wlr_scene_node_set_position(&border->trcorner->node, - width-border_width, 0); + wlr_scene_buffer_set_dest_size(border->trcorner, + border_width, border_width); + wlr_scene_node_set_position(&border->trcorner->node, + width-border_width, 0); - wlr_scene_buffer_set_dest_size(border->brcorner, - border_width, border_width); - wlr_scene_node_set_position(&border->brcorner->node, - width-border_width , height-border_width); + wlr_scene_buffer_set_dest_size(border->brcorner, + border_width, border_width); + wlr_scene_node_set_position(&border->brcorner->node, + width-border_width , height-border_width); - wlr_scene_buffer_set_dest_size(border->blcorner, - border_width, border_width); - wlr_scene_node_set_position(&border->blcorner->node, - 0, height-border_width); + wlr_scene_buffer_set_dest_size(border->blcorner, + border_width, border_width); + wlr_scene_node_set_position(&border->blcorner->node, + 0, height-border_width); } diff --git a/src/workspaces.c b/src/workspaces.c index 1e715ac1..0dc1205e 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -18,6 +18,7 @@ #include "common/scene-helpers.h" #include "config/rcxml.h" #include "input/keyboard.h" +#include "common/borderset.h" #include "labwc.h" #include "output.h" #include "protocols/cosmic-workspaces.h" @@ -25,6 +26,7 @@ #include "theme.h" #include "view.h" + #define COSMIC_WORKSPACES_VERSION 1 #define EXT_WORKSPACES_VERSION 1 @@ -98,46 +100,82 @@ _osd_update(void) cairo = cairo_create(buffer->surface); + int bw = theme->osd_border_width; /* Background */ set_cairo_color(cairo, theme->osd_bg_color); - cairo_rectangle(cairo, 0, 0, width, height); + cairo_rectangle(cairo, bw, bw, width-bw*2, height-bw*2); cairo_fill(cairo); /* Border */ - if (theme->beveled_border) { - const float highlight[4] = { - MIN(theme->osd_border_color[0] * 5/4, theme->osd_border_color[3]), - MIN(theme->osd_border_color[1] * 5/4, theme->osd_border_color[3]), - MIN(theme->osd_border_color[2] * 5/4, theme->osd_border_color[3]), - theme->osd_border_color[3] - }; - const float lowlight[4] = { - theme->osd_border_color[0] / 2, - theme->osd_border_color[1] / 2, - theme->osd_border_color[2] / 2, - theme->osd_border_color[3] - }; - set_cairo_color(cairo, highlight); - cairo_new_path(cairo); - cairo_move_to(cairo, 0, 0); - cairo_line_to(cairo, width, 0); - cairo_line_to(cairo, width - theme->osd_border_width, theme->osd_border_width); - cairo_line_to(cairo, theme->osd_border_width, theme->osd_border_width); - cairo_line_to(cairo, theme->osd_border_width, height-theme->osd_border_width); - cairo_line_to(cairo, 0, height); - cairo_close_path(cairo); - cairo_fill(cairo); + if (theme->beveled_border) { + float r = theme->osd_border_color[0]; + float g = theme->osd_border_color[1]; + float b = theme->osd_border_color[2]; + float a = theme->osd_border_color[3]; + + uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); + struct borderset * renderedborders = getBorders(colour32, bw, 1, 0); + - set_cairo_color(cairo, lowlight); - cairo_new_path(cairo); - cairo_move_to(cairo, width, 0); - cairo_line_to(cairo, width - theme->osd_border_width, theme->osd_border_width); - cairo_line_to(cairo, width - theme->osd_border_width, height-theme->osd_border_width); - cairo_line_to(cairo, theme->osd_border_width, height-theme->osd_border_width); - cairo_line_to(cairo, 0, height); - cairo_line_to(cairo, width, height); - cairo_close_path(cairo); + cairo_surface_t* top = cairo_image_surface_create_for_data((unsigned char *)renderedborders->top, CAIRO_FORMAT_ARGB32, 1, 1, 4); + cairo_set_source_surface(cairo, top, 0, 0); + cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); + cairo_rectangle(cairo, bw, 0, width-bw*2, bw); cairo_fill(cairo); + cairo_surface_finish(top); + + cairo_surface_t* bottom = cairo_image_surface_create_for_data((unsigned char *)renderedborders->bottom, CAIRO_FORMAT_ARGB32, 1, 1, 4); + cairo_set_source_surface(cairo, bottom, 0, 0); + cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); + cairo_rectangle(cairo, bw, height-bw, width-bw*2, bw); + cairo_fill(cairo); + cairo_surface_finish(bottom); + + + cairo_surface_t* left = cairo_image_surface_create_for_data((unsigned char *)renderedborders->left, CAIRO_FORMAT_ARGB32, 1, 1, 4); + cairo_set_source_surface(cairo, left, 0, 0); + cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); + cairo_rectangle(cairo, 0, bw, bw, height-bw*2); + cairo_fill(cairo); + cairo_surface_finish(left); + + cairo_surface_t* right = cairo_image_surface_create_for_data((unsigned char *)renderedborders->right, CAIRO_FORMAT_ARGB32, 1, 1, 4); + cairo_set_source_surface(cairo, right, 0, 0); + cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); + cairo_rectangle(cairo, width-bw, bw, bw, height-bw*2); + cairo_fill(cairo); + cairo_surface_finish(right); + + + cairo_surface_t* tl = cairo_image_surface_create_for_data((unsigned char *)renderedborders->tl, CAIRO_FORMAT_ARGB32, bw, bw, 4*bw); + cairo_set_source_surface(cairo, tl, 0, 0); + cairo_rectangle(cairo, 0, 0, bw, bw); + cairo_fill(cairo); + cairo_surface_finish(tl); + + + + + cairo_surface_t* tr = cairo_image_surface_create_for_data((unsigned char *)renderedborders->tr, CAIRO_FORMAT_ARGB32, bw, bw, 4*bw); + cairo_set_source_surface(cairo, tr, width-bw, 0); + cairo_rectangle(cairo, width - bw, 0, bw, bw); + cairo_fill(cairo); + cairo_surface_finish(tr); + + cairo_surface_t* bl = cairo_image_surface_create_for_data((unsigned char *)renderedborders->bl, CAIRO_FORMAT_ARGB32, bw, bw, 4*bw); + cairo_set_source_surface(cairo, bl, 0, height - bw); + cairo_rectangle(cairo, 0, height - bw, bw, bw); + cairo_fill(cairo); + cairo_surface_finish(bl); + + cairo_surface_t* br = cairo_image_surface_create_for_data((unsigned char *)renderedborders->br, CAIRO_FORMAT_ARGB32, bw, bw, 4*bw); + cairo_set_source_surface(cairo, br, width - bw, height -bw); + cairo_rectangle(cairo, width - bw, height - bw, bw, bw); + cairo_fill(cairo); + cairo_surface_finish(br); + + + set_cairo_color(cairo, theme->osd_border_color); } else { set_cairo_color(cairo, theme->osd_border_color); struct wlr_fbox border_fbox = { From 0be9082ea848911bda8ebc0d77e223118a76329a Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Fri, 27 Mar 2026 23:37:18 -0700 Subject: [PATCH 19/47] Add bevels to the window size/position box --- include/view.h | 1 + src/ssd/resize-indicator.c | 107 +++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/include/view.h b/include/view.h index c2764f94..374a9ed1 100644 --- a/include/view.h +++ b/include/view.h @@ -244,6 +244,7 @@ struct view { int width, height; struct wlr_scene_tree *tree; struct wlr_scene_rect *border; + struct wlr_scene_buffer *top, *left, *right, *bottom, *tl, *tr, *bl, *br; struct wlr_scene_rect *background; struct scaled_font_buffer *text; } resize_indicator; diff --git a/src/ssd/resize-indicator.c b/src/ssd/resize-indicator.c index fa1166a3..5ffa3aa5 100644 --- a/src/ssd/resize-indicator.c +++ b/src/ssd/resize-indicator.c @@ -12,6 +12,8 @@ #include "ssd.h" #include "theme.h" #include "view.h" +#include "common/borderset.h" +#include "buffer.h" #define PADDING rc.theme->osd_window_switcher_classic.padding @@ -50,7 +52,58 @@ resize_indicator_init(struct view *view) indicator->tree, 0, 0, rc.theme->osd_border_color); indicator->background = lab_wlr_scene_rect_create( indicator->tree, 0, 0, rc.theme->osd_bg_color); + + if (rc.theme->beveled_border) { + float r = rc.theme->osd_border_color[0]; + float g = rc.theme->osd_border_color[1]; + float b = rc.theme->osd_border_color[2]; + float a = rc.theme->osd_border_color[3]; + int bw = rc.theme->osd_border_width; + + uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); + struct borderset * renderedborders = getBorders(colour32, bw, 1, 0); + struct lab_data_buffer *ttexture_buffer = + buffer_create_from_data(renderedborders->top, 1, 1, 4); + indicator->top = wlr_scene_buffer_create(indicator->tree, &ttexture_buffer->base); + + struct lab_data_buffer *ltexture_buffer = + buffer_create_from_data(renderedborders->left, 1, 1, 4); + indicator->left = wlr_scene_buffer_create(indicator->tree, <exture_buffer->base); + + struct lab_data_buffer *rtexture_buffer = + buffer_create_from_data(renderedborders->right, 1, 1, 4); + indicator->right = wlr_scene_buffer_create(indicator->tree, &rtexture_buffer->base); + + struct lab_data_buffer *btexture_buffer = + buffer_create_from_data(renderedborders->bottom, 1, 1, 4); + indicator->bottom = wlr_scene_buffer_create(indicator->tree, &btexture_buffer->base); + + + struct lab_data_buffer *tltexture_buffer = + buffer_create_from_data(renderedborders->tl, bw, bw, 4*bw); + indicator->tl = wlr_scene_buffer_create(indicator->tree, &tltexture_buffer->base); + + + struct lab_data_buffer *trtexture_buffer = + buffer_create_from_data(renderedborders->tr, bw, bw, 4*bw); + indicator->tr = wlr_scene_buffer_create(indicator->tree, &trtexture_buffer->base); + + + struct lab_data_buffer *bltexture_buffer = + buffer_create_from_data(renderedborders->bl, bw, bw, 4*bw); + indicator->bl = wlr_scene_buffer_create(indicator->tree, &bltexture_buffer->base); + + struct lab_data_buffer *brtexture_buffer = + buffer_create_from_data(renderedborders->br, bw, bw, 4*bw); + indicator->br = wlr_scene_buffer_create(indicator->tree, &brtexture_buffer->base); + + + + } + + indicator->text = scaled_font_buffer_create(indicator->tree); + wlr_scene_node_set_enabled(&indicator->tree->node, false); resize_indicator_reconfigure_view(indicator); @@ -117,6 +170,60 @@ resize_indicator_set_size(struct resize_indicator *indicator, int width) wlr_scene_rect_set_size(indicator->background, indicator->width - 2 * rc.theme->osd_border_width, indicator->height - 2 * rc.theme->osd_border_width); + + if (rc.theme->beveled_border) { + + int height = indicator->height; + int border_width = rc.theme->osd_border_width; + + wlr_scene_buffer_set_dest_size(indicator->top, + indicator->width, border_width); + wlr_scene_node_set_position(&indicator->top->node, + 0,0); + + wlr_scene_buffer_set_dest_size(indicator->bottom, + indicator->width, border_width); + wlr_scene_node_set_position(&indicator->bottom->node, + 0, height - border_width); + + + wlr_scene_buffer_set_dest_size(indicator->left, + border_width, height - border_width * 2); + wlr_scene_node_set_position(&indicator->left->node, + 0, border_width); + + wlr_scene_buffer_set_dest_size(indicator->right, + border_width, height - border_width * 2); + wlr_scene_node_set_position(&indicator->right->node, + indicator->width - border_width, border_width); + + + + + + wlr_scene_buffer_set_dest_size(indicator->tl, + border_width, border_width); + wlr_scene_node_set_position(&indicator->tl->node, + 0,0); + + wlr_scene_buffer_set_dest_size(indicator->tr, + border_width, border_width); + wlr_scene_node_set_position(&indicator->tr->node, + indicator->width-border_width, 0); + + + wlr_scene_buffer_set_dest_size(indicator->br, + border_width, border_width); + wlr_scene_node_set_position(&indicator->br->node, + indicator->width-border_width , height-border_width); + + + wlr_scene_buffer_set_dest_size(indicator->bl, + border_width, border_width); + wlr_scene_node_set_position(&indicator->bl->node, + 0, height-border_width); + + } } void From 90e652a8a1fb9b5689023e5e1a94a0adcb3ae930 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sat, 28 Mar 2026 00:20:51 -0700 Subject: [PATCH 20/47] Bevels on selected menu items; support for sunken bevel rendering --- src/common/borderset.c | 24 +++++++++ src/menu/menu.c | 114 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 135 insertions(+), 3 deletions(-) diff --git a/src/common/borderset.c b/src/common/borderset.c index 2f80fc85..c385dccb 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -194,6 +194,30 @@ struct borderset * createBuffer(uint32_t id, int size, int type, int bevelSize) + break; + + case 3: // Sunken Single bevel borders have 1x1 sides + newBorderset->top = znew(uint32_t); + newBorderset->left = znew(uint32_t); + newBorderset->right = znew(uint32_t); + newBorderset->bottom = znew(uint32_t); + *newBorderset->top = ll32; + *newBorderset->left = ll32; + *newBorderset->right = hl32; + *newBorderset->bottom = hl32; + + // Fill with solid + for (int j=0; jtl[PIXELSIZED(j, k, size)] = ll32; + newBorderset->tr[PIXELSIZED(size - 1 - j, k, size)] = (j > k) ? ll32 : hl32; + newBorderset->bl[PIXELSIZED(size - 1 -j, k, size)] = (j > k) ? ll32 : hl32; + newBorderset->br[PIXELSIZED(j, k, size)] = hl32; + } + } + + + break; } diff --git a/src/menu/menu.c b/src/menu/menu.c index 0221e0dd..bf75f7dc 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -32,6 +32,8 @@ #include "translate.h" #include "view.h" #include "workspaces.h" +#include "common/borderset.h" +#include "buffer.h" #define PIPEMENU_MAX_BUF_SIZE 1048576 /* 1 MiB */ #define PIPEMENU_TIMEOUT_IN_MS 4000 /* 4 seconds */ @@ -163,10 +165,11 @@ item_create(struct menu *menu, const char *text, const char *icon_name, bool sho static struct wlr_scene_tree * item_create_scene_for_state(struct menuitem *item, float *text_color, - float *bg_color) + float *bg_color, int state) { struct menu *menu = item->parent; struct theme *theme = rc.theme; + struct wlr_scene_buffer *top, *left, *right, *bottom, *tl, *tr, *bl, *br; /* Tree to hold background and label buffers */ struct wlr_scene_tree *tree = lab_wlr_scene_tree_create(item->tree); @@ -191,6 +194,57 @@ item_create_scene_for_state(struct menuitem *item, float *text_color, /* Create background */ lab_wlr_scene_rect_create(tree, bg_width, theme->menu_item_height, bg_color); + int bw = theme->menu_border_width; + if (rc.theme->beveled_border && state) { + float r = bg_color[0]; + float g = bg_color[1]; + float b = bg_color[2]; + float a = bg_color[3]; + + + uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); + struct borderset * renderedborders = getBorders(colour32, bw, 3, 0); + struct lab_data_buffer *ttexture_buffer = + buffer_create_from_data(renderedborders->top, 1, 1, 4); + top = wlr_scene_buffer_create(tree, &ttexture_buffer->base); + + struct lab_data_buffer *ltexture_buffer = + buffer_create_from_data(renderedborders->left, 1, 1, 4); + left = wlr_scene_buffer_create(tree, <exture_buffer->base); + + struct lab_data_buffer *rtexture_buffer = + buffer_create_from_data(renderedborders->right, 1, 1, 4); + right = wlr_scene_buffer_create(tree, &rtexture_buffer->base); + + struct lab_data_buffer *btexture_buffer = + buffer_create_from_data(renderedborders->bottom, 1, 1, 4); + bottom = wlr_scene_buffer_create(tree, &btexture_buffer->base); + + + struct lab_data_buffer *tltexture_buffer = + buffer_create_from_data(renderedborders->tl, bw, bw, 4*bw); + tl = wlr_scene_buffer_create(tree, &tltexture_buffer->base); + + + struct lab_data_buffer *trtexture_buffer = + buffer_create_from_data(renderedborders->tr, bw, bw, 4*bw); + tr = wlr_scene_buffer_create(tree, &trtexture_buffer->base); + + + struct lab_data_buffer *bltexture_buffer = + buffer_create_from_data(renderedborders->bl, bw, bw, 4*bw); + bl = wlr_scene_buffer_create(tree, &bltexture_buffer->base); + + struct lab_data_buffer *brtexture_buffer = + buffer_create_from_data(renderedborders->br, bw, bw, 4*bw); + br = wlr_scene_buffer_create(tree, &brtexture_buffer->base); + + } + + + + + /* Create icon */ bool show_app_icon = !strcmp(item->parent->id, "client-list-combined-menu") && item->client_list_view; @@ -218,6 +272,60 @@ item_create_scene_for_state(struct menuitem *item, float *text_color, int x = theme->menu_items_padding_x + icon_width; int y = (theme->menu_item_height - label_buffer->height) / 2; wlr_scene_node_set_position(&label_buffer->scene_buffer->node, x, y); + + + if (rc.theme->beveled_border && state) { + + int height = theme->menu_item_height; + + wlr_scene_buffer_set_dest_size(top, + bg_width, bw); + wlr_scene_node_set_position(&top->node, + 0,0); + + wlr_scene_buffer_set_dest_size(bottom, + bg_width, bw); + wlr_scene_node_set_position(&bottom->node, + 0, height - bw); + + + wlr_scene_buffer_set_dest_size(left, + bw, height - bw * 2); + wlr_scene_node_set_position(&left->node, + 0, bw); + + wlr_scene_buffer_set_dest_size(right, + bw, height - bw * 2); + wlr_scene_node_set_position(&right->node, + bg_width - bw, bw); + + + + + + wlr_scene_buffer_set_dest_size(tl, + bw, bw); + wlr_scene_node_set_position(&tl->node, + 0,0); + + wlr_scene_buffer_set_dest_size(tr, + bw, bw); + wlr_scene_node_set_position(&tr->node, + bg_width-bw, 0); + + + wlr_scene_buffer_set_dest_size(br, + bw, bw); + wlr_scene_node_set_position(&br->node, + bg_width-bw , height-bw); + + + wlr_scene_buffer_set_dest_size(bl, + bw, bw); + wlr_scene_node_set_position(&bl->node, + 0, height-bw); + } + if (!item->arrow) { return tree; @@ -252,10 +360,10 @@ item_create_scene(struct menuitem *menuitem, int *item_y) /* Create scenes for unselected/selected states */ menuitem->normal_tree = item_create_scene_for_state(menuitem, theme->menu_items_text_color, - theme->menu_items_bg_color); + theme->menu_items_bg_color, 0); menuitem->selected_tree = item_create_scene_for_state(menuitem, theme->menu_items_active_text_color, - theme->menu_items_active_bg_color); + theme->menu_items_active_bg_color, 1); /* Hide selected state */ wlr_scene_node_set_enabled(&menuitem->selected_tree->node, false); From d80dd2470b73521966212c91c00c07c2c581f67a Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sat, 28 Mar 2026 09:01:21 -0700 Subject: [PATCH 21/47] Centralize buffer preparation and standardize placement --- include/common/borderset.h | 27 ++++- include/common/lab-scene-rect.h | 2 +- include/common/macros.h | 4 +- include/ssd-internal.h | 3 +- include/view.h | 2 +- src/common/borderset.c | 200 +++++++++++++++++++++++++++----- src/common/lab-scene-rect.c | 128 +++----------------- src/cycle/cycle.c | 2 +- src/cycle/osd-classic.c | 2 +- src/cycle/osd-scroll.c | 2 +- src/cycle/osd-thumbnail.c | 4 +- src/menu/menu.c | 113 +++++------------- src/ssd/resize-indicator.c | 94 +-------------- src/ssd/ssd-border.c | 95 +-------------- src/theme.c | 2 +- src/workspaces.c | 2 +- 16 files changed, 251 insertions(+), 431 deletions(-) diff --git a/include/common/borderset.h b/include/common/borderset.h index f0fc170d..f0392874 100644 --- a/include/common/borderset.h +++ b/include/common/borderset.h @@ -3,10 +3,14 @@ #ifndef LABWC_BORDERSET_H #define LABWC_BORDERSET_H +enum border_type { + BORDER_FLAT, BORDER_SINGLE, BORDER_DOUBLE, BORDER_INSET +}; + struct borderset { uint32_t id; // Base colour, but could be used as a tracking hash for images or whatever in the future int size; // width (since I suspect a 2px border scaled up to 20px might look weird) - int type; // Single or double bevel + enum border_type type; // Single or double bevel uint32_t * top; uint32_t * left; uint32_t * right; @@ -18,12 +22,29 @@ struct borderset { struct borderset * next; }; +struct bufferset { + enum border_type type; + int border_width; + struct wlr_scene_buffer * top; + struct wlr_scene_buffer * left; + struct wlr_scene_buffer * right; + struct wlr_scene_buffer * bottom; + struct wlr_scene_buffer * tl; + struct wlr_scene_buffer * tr; + struct wlr_scene_buffer * bl; + struct wlr_scene_buffer * br; + +}; extern struct borderset * borderCache; -struct borderset * getBorders(uint32_t id, int size, int type, int bevelSize); +struct borderset * getBorders(uint32_t id, int size, enum border_type, int bevelSize); -struct borderset * createBuffer(uint32_t id, int size, int type, int bevelSize); +struct borderset * createBuffer(uint32_t id, int size, enum border_type, int bevelSize); + +struct bufferset * generateBufferset(struct wlr_scene_tree * tree, struct borderset *borderset, int bw); + +void renderBufferset(struct bufferset *, int width, int height, int y); void clearBorderCache(struct borderset *borderset); diff --git a/include/common/lab-scene-rect.h b/include/common/lab-scene-rect.h index d79d879d..ebf243c7 100644 --- a/include/common/lab-scene-rect.h +++ b/include/common/lab-scene-rect.h @@ -12,7 +12,7 @@ struct lab_scene_rect_options { float *bg_color; /* can be NULL */ int width; int height; - int beveled; + bool beveled; }; struct lab_scene_rect { diff --git a/include/common/macros.h b/include/common/macros.h index 46a42fd4..f3240206 100644 --- a/include/common/macros.h +++ b/include/common/macros.h @@ -74,8 +74,6 @@ * Assumes "bw" was defined externally */ -#define PIXEL(x, y) (bw * y + x) - -#define PIXELSIZED(x, y, size) (size * y + x) +#define PIXEL(x, y, size) (size * y + x) #endif /* LABWC_MACROS_H */ diff --git a/include/ssd-internal.h b/include/ssd-internal.h index 965944dc..1d2ff1da 100644 --- a/include/ssd-internal.h +++ b/include/ssd-internal.h @@ -115,8 +115,7 @@ struct ssd { struct ssd_border_subtree { struct wlr_scene_tree *tree; struct wlr_scene_rect *top, *bottom, *left, *right; - struct wlr_scene_buffer *tlcorner, *trcorner, *blcorner, *brcorner, - *ttexture, *btexture, *ltexture, *rtexture; + struct bufferset * texturedBorders; } subtrees[2]; /* indexed by enum ssd_active_state */ } border; diff --git a/include/view.h b/include/view.h index 374a9ed1..a3d80609 100644 --- a/include/view.h +++ b/include/view.h @@ -244,7 +244,7 @@ struct view { int width, height; struct wlr_scene_tree *tree; struct wlr_scene_rect *border; - struct wlr_scene_buffer *top, *left, *right, *bottom, *tl, *tr, *bl, *br; + struct bufferset * texturedBorders; struct wlr_scene_rect *background; struct scaled_font_buffer *text; } resize_indicator; diff --git a/src/common/borderset.c b/src/common/borderset.c index c385dccb..0c02b6c1 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -1,8 +1,10 @@ +#include #include "common/borderset.h" #include "common/mem.h" #include "common/macros.h" +#include "buffer.h" -struct borderset * getBorders(uint32_t id, int size, int type, int bevelSize) { +struct borderset * getBorders(uint32_t id, int size, enum border_type type, int bevelSize) { struct borderset * current = borderCache; struct borderset * last; while (current != NULL) { @@ -24,7 +26,7 @@ struct borderset * getBorders(uint32_t id, int size, int type, int bevelSize) { return NULL; } -struct borderset * createBuffer(uint32_t id, int size, int type, int bevelSize) { +struct borderset * createBuffer(uint32_t id, int size, enum border_type type, int bevelSize) { struct borderset *newBorderset = znew(*newBorderset); newBorderset->next = NULL; @@ -64,7 +66,7 @@ struct borderset * createBuffer(uint32_t id, int size, int type, int bevelSize) newBorderset->br = znew_n(uint32_t, size*size); switch(type) { - case 1: // Single bevel borders have 1x1 sides + case BORDER_SINGLE: // Single bevel borders have 1x1 sides newBorderset->top = znew(uint32_t); newBorderset->left = znew(uint32_t); newBorderset->right = znew(uint32_t); @@ -77,10 +79,10 @@ struct borderset * createBuffer(uint32_t id, int size, int type, int bevelSize) // Fill with solid for (int j=0; jtl[PIXELSIZED(j, k, size)] = hl32; - newBorderset->tr[PIXELSIZED(size - 1 - j, k, size)] = (j > k) ? hl32 : ll32; - newBorderset->bl[PIXELSIZED(size - 1 -j, k, size)] = (j > k) ? hl32 : ll32; - newBorderset->br[PIXELSIZED(j, k, size)] = ll32; + newBorderset->tl[PIXEL(j, k, size)] = hl32; + newBorderset->tr[PIXEL(size - 1 - j, k, size)] = (j > k) ? hl32 : ll32; + newBorderset->bl[PIXEL(size - 1 -j, k, size)] = (j > k) ? hl32 : ll32; + newBorderset->br[PIXEL(j, k, size)] = ll32; } } @@ -89,7 +91,7 @@ struct borderset * createBuffer(uint32_t id, int size, int type, int bevelSize) break; - case 2: + case BORDER_DOUBLE: newBorderset->top = znew_n(uint32_t, size); newBorderset->left = znew_n(uint32_t, size); newBorderset->right = znew_n(uint32_t, size); @@ -119,10 +121,10 @@ struct borderset * createBuffer(uint32_t id, int size, int type, int bevelSize) // Blank corners... for (int i=0; itl[PIXELSIZED(i, j, size)] = id; - newBorderset->tr[PIXELSIZED(i, j, size)] = id; - newBorderset->bl[PIXELSIZED(i, j, size)] = id; - newBorderset->br[PIXELSIZED(i, j, size)] = id; + newBorderset->tl[PIXEL(i, j, size)] = id; + newBorderset->tr[PIXEL(i, j, size)] = id; + newBorderset->bl[PIXEL(i, j, size)] = id; + newBorderset->br[PIXEL(i, j, size)] = id; } } @@ -133,25 +135,25 @@ struct borderset * createBuffer(uint32_t id, int size, int type, int bevelSize) // Solid bar parts for (int j=0; jtl[PIXELSIZED(j, i, size)] = hl32; + newBorderset->tl[PIXEL(j, i, size)] = hl32; // First "bevel size" top columns are highlighted - newBorderset->tl[PIXELSIZED(i, j, size)] = hl32; + newBorderset->tl[PIXEL(i, j, size)] = hl32; // Bottom Right corner: Entire "bevel size" last rows are lowlight - newBorderset->br[PIXELSIZED(j, (size-1-i), size)] = ll32; + newBorderset->br[PIXEL(j, (size-1-i), size)] = ll32; // Last "bevel size" columns are lowlight - newBorderset->br[PIXELSIZED((size-1-i), j, size)] = ll32; + newBorderset->br[PIXEL((size-1-i), j, size)] = ll32; // Bottom left corner: Entire "bevel size" last rows are lowlight - newBorderset->bl[PIXELSIZED(j, (size-1-i), size)] = ll32; + newBorderset->bl[PIXEL(j, (size-1-i), size)] = ll32; // First "bevel size" columns are highlight, except for the bottom right corner - newBorderset->bl[PIXELSIZED(i, j, size)] = hl32; + newBorderset->bl[PIXEL(i, j, size)] = hl32; // Top Right corner: Entire "bevel size" first rows are highlight - newBorderset->tr[PIXELSIZED(j, i, size)] = hl32; + newBorderset->tr[PIXEL(j, i, size)] = hl32; // Last "bevel size" columns are lowlight, except for the top left - newBorderset->tr[PIXELSIZED((size-1-i), j, size)] = ll32; + newBorderset->tr[PIXEL((size-1-i), j, size)] = ll32; } } @@ -162,27 +164,27 @@ struct borderset * createBuffer(uint32_t id, int size, int type, int bevelSize) // Outer Corners // Bottom left corner: // First "bevel size" columns are highlight, except for the bottom right corner - newBorderset->bl[PIXELSIZED(i, (size - 1 - j), size)] = (j >= i) ? hl32 : ll32; + newBorderset->bl[PIXEL(i, (size - 1 - j), size)] = (j >= i) ? hl32 : ll32; // Top Right corner: // Last "bevel size" columns are lowlight, except for the top left - newBorderset->tr[PIXELSIZED((size-1-i), j, size)] = (j > i) ? ll32 : hl32; + newBorderset->tr[PIXEL((size-1-i), j, size)] = (j > i) ? ll32 : hl32; // Inner Corners // Top left corner: Bottom right is all dark - newBorderset->tl[PIXELSIZED((size-1-i), (size - 1 - j), size)] = ll32; + newBorderset->tl[PIXEL((size-1-i), (size - 1 - j), size)] = ll32; // Bottom Right corner: Top left is all light - newBorderset->br[PIXELSIZED(i, j, size)] = hl32; + newBorderset->br[PIXEL(i, j, size)] = hl32; // Top Right corner: // Interior bottom left is dark on top, light on bottom - newBorderset->tr[PIXELSIZED(i, (size-1-j), size)] = (i > j) ? hl32 : ll32; + newBorderset->tr[PIXEL(i, (size-1-j), size)] = (i > j) ? hl32 : ll32; // Bottom Left corner: // Interior top right is dark on top, light on bottom - newBorderset->bl[PIXELSIZED((size-1-i), j, size)] = (i > j) ? ll32 : hl32; + newBorderset->bl[PIXEL((size-1-i), j, size)] = (i > j) ? ll32 : hl32; @@ -196,7 +198,31 @@ struct borderset * createBuffer(uint32_t id, int size, int type, int bevelSize) break; - case 3: // Sunken Single bevel borders have 1x1 sides + case BORDER_FLAT: // Placeholder that uses buffers but for a flat colour + newBorderset->top = znew(uint32_t); + newBorderset->left = znew(uint32_t); + newBorderset->right = znew(uint32_t); + newBorderset->bottom = znew(uint32_t); + *newBorderset->top = id; + *newBorderset->left = id; + *newBorderset->right = id; + *newBorderset->bottom = id; + + // Fill with solid + for (int j=0; jtl[PIXEL(j, k, size)] = id; + newBorderset->tr[PIXEL(size - 1 - j, k, size)] = id; + newBorderset->bl[PIXEL(size - 1 -j, k, size)] = id; + newBorderset->br[PIXEL(j, k, size)] = id; + } + } + + + + break; + + case BORDER_INSET: // Sunken Single bevel borders have 1x1 sides newBorderset->top = znew(uint32_t); newBorderset->left = znew(uint32_t); newBorderset->right = znew(uint32_t); @@ -209,10 +235,10 @@ struct borderset * createBuffer(uint32_t id, int size, int type, int bevelSize) // Fill with solid for (int j=0; jtl[PIXELSIZED(j, k, size)] = ll32; - newBorderset->tr[PIXELSIZED(size - 1 - j, k, size)] = (j > k) ? ll32 : hl32; - newBorderset->bl[PIXELSIZED(size - 1 -j, k, size)] = (j > k) ? ll32 : hl32; - newBorderset->br[PIXELSIZED(j, k, size)] = hl32; + newBorderset->tl[PIXEL(j, k, size)] = ll32; + newBorderset->tr[PIXEL(size - 1 - j, k, size)] = (j > k) ? ll32 : hl32; + newBorderset->bl[PIXEL(size - 1 -j, k, size)] = (j > k) ? ll32 : hl32; + newBorderset->br[PIXEL(j, k, size)] = hl32; } } @@ -224,6 +250,118 @@ struct borderset * createBuffer(uint32_t id, int size, int type, int bevelSize) return newBorderset; } + +struct bufferset * generateBufferset(struct wlr_scene_tree * tree, struct borderset *borderset, int bw) +{ + struct bufferset * bufferset = znew(struct bufferset); + + bufferset->border_width = bw; + if (borderset->type == BORDER_DOUBLE) { + struct lab_data_buffer *ttexture_buffer = + buffer_create_from_data(borderset->top, 1, bw, 4); + bufferset->top = wlr_scene_buffer_create(tree, &ttexture_buffer->base); + + struct lab_data_buffer *ltexture_buffer = + buffer_create_from_data(borderset->left, bw, 1, 4*bw); + bufferset->left = wlr_scene_buffer_create(tree, <exture_buffer->base); + + struct lab_data_buffer *rtexture_buffer = + buffer_create_from_data(borderset->right, bw, 1, 4*bw); + bufferset->right = wlr_scene_buffer_create(tree, &rtexture_buffer->base); + + struct lab_data_buffer *btexture_buffer = + buffer_create_from_data(borderset->bottom, 1, bw, 4); + bufferset->bottom = wlr_scene_buffer_create(tree, &btexture_buffer->base); + + + } else { + struct lab_data_buffer *ttexture_buffer = + buffer_create_from_data(borderset->top, 1, 1, 4); + bufferset->top = wlr_scene_buffer_create(tree, &ttexture_buffer->base); + + struct lab_data_buffer *ltexture_buffer = + buffer_create_from_data(borderset->left, 1, 1, 4); + bufferset->left = wlr_scene_buffer_create(tree, <exture_buffer->base); + + struct lab_data_buffer *rtexture_buffer = + buffer_create_from_data(borderset->right, 1, 1, 4); + bufferset->right = wlr_scene_buffer_create(tree, &rtexture_buffer->base); + + struct lab_data_buffer *btexture_buffer = + buffer_create_from_data(borderset->bottom, 1, 1, 4); + bufferset->bottom = wlr_scene_buffer_create(tree, &btexture_buffer->base); + } + + + struct lab_data_buffer *tltexture_buffer = + buffer_create_from_data(borderset->tl, bw, bw, 4*bw); + bufferset->tl = wlr_scene_buffer_create(tree, &tltexture_buffer->base); + + + struct lab_data_buffer *trtexture_buffer = + buffer_create_from_data(borderset->tr, bw, bw, 4*bw); + bufferset->tr = wlr_scene_buffer_create(tree, &trtexture_buffer->base); + + + struct lab_data_buffer *bltexture_buffer = + buffer_create_from_data(borderset->bl, bw, bw, 4*bw); + bufferset->bl = wlr_scene_buffer_create(tree, &bltexture_buffer->base); + + struct lab_data_buffer *brtexture_buffer = + buffer_create_from_data(borderset->br, bw, bw, 4*bw); + bufferset->br = wlr_scene_buffer_create(tree, &brtexture_buffer->base); + + return bufferset; +} + +void renderBufferset(struct bufferset *bufferset, int width, int height, int y) +{ + + wlr_scene_buffer_set_dest_size(bufferset->top, + width - 2 * bufferset->border_width, bufferset->border_width); + wlr_scene_node_set_position(&bufferset->top->node, + bufferset->border_width,y); + + wlr_scene_buffer_set_dest_size(bufferset->bottom, + width - 2 * bufferset->border_width, bufferset->border_width); + wlr_scene_node_set_position(&bufferset->bottom->node, + bufferset->border_width, y+height - bufferset->border_width); + + + wlr_scene_buffer_set_dest_size(bufferset->left, + bufferset->border_width, height - bufferset->border_width * 2); + wlr_scene_node_set_position(&bufferset->left->node, + 0, bufferset->border_width+y); + + wlr_scene_buffer_set_dest_size(bufferset->right, + bufferset->border_width, height - bufferset->border_width * 2); + wlr_scene_node_set_position(&bufferset->right->node, + width - bufferset->border_width, y+ bufferset->border_width); + + wlr_scene_buffer_set_dest_size(bufferset->tl, + bufferset->border_width, bufferset->border_width); + wlr_scene_node_set_position(&bufferset->tl->node, + 0,y); + + wlr_scene_buffer_set_dest_size(bufferset->tr, + bufferset->border_width, bufferset->border_width); + wlr_scene_node_set_position(&bufferset->tr->node, + width-bufferset->border_width, y); + + + wlr_scene_buffer_set_dest_size(bufferset->br, + bufferset->border_width, bufferset->border_width); + wlr_scene_node_set_position(&bufferset->br->node, + width-bufferset->border_width , y+height-bufferset->border_width); + + + wlr_scene_buffer_set_dest_size(bufferset->bl, + bufferset->border_width, bufferset->border_width); + wlr_scene_node_set_position(&bufferset->bl->node, + 0, height-bufferset->border_width+y); + +} + void clearBorderCache(struct borderset * borderset) { if (borderset == NULL) diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c index 9dc0921f..4b45eeec 100644 --- a/src/common/lab-scene-rect.c +++ b/src/common/lab-scene-rect.c @@ -7,12 +7,12 @@ #include "common/macros.h" #include "common/borderset.h" #include "buffer.h" +#include struct border_scene { struct wlr_scene_tree *tree; struct wlr_scene_rect *top, *bottom, *left, *right; - struct wlr_scene_buffer *tlcorner, *trcorner, *blcorner, *brcorner, - *ttexture, *ltexture, *rtexture, *btexture; + struct bufferset * texturedBorders; }; static void @@ -42,77 +42,23 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, struct border_scene *border = &rect->borders[i]; float *color = opts->border_colors[i]; border->tree = lab_wlr_scene_tree_create(rect->tree); - // Beveled mode 0 = normal outline - // Beveled mode 1 = full bevel with sharp internal corners - if (opts->beveled > 0) { + border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, color); + border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, color); + border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0, color); + border->left = lab_wlr_scene_rect_create(border->tree, 0, 0, color); + + if (opts->beveled) { float r = color[0]; float g = color[1]; float b = color[2]; float a = color[3]; int bw = rect->border_width; uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, 1, 0); - - - - - - - - - - - - - border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, color); - border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, color); - border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0, color); - border->left = lab_wlr_scene_rect_create(border->tree, 0, 0, color); - - struct lab_data_buffer *ttexture_buffer = - buffer_create_from_data(renderedborders->top, 1, 1, 4); - border->ttexture = wlr_scene_buffer_create(border->tree, &ttexture_buffer->base); - - struct lab_data_buffer *ltexture_buffer = - buffer_create_from_data(renderedborders->left, 1, 1, 4); - border->ltexture = wlr_scene_buffer_create(border->tree, <exture_buffer->base); - - struct lab_data_buffer *rtexture_buffer = - buffer_create_from_data(renderedborders->right, 1, 1, 4); - border->rtexture = wlr_scene_buffer_create(border->tree, &rtexture_buffer->base); - - struct lab_data_buffer *btexture_buffer = - buffer_create_from_data(renderedborders->bottom, 1, 1, 4); - border->btexture = wlr_scene_buffer_create(border->tree, &btexture_buffer->base); - - - struct lab_data_buffer *tltexture_buffer = - buffer_create_from_data(renderedborders->tl, bw, bw, 4*bw); - border->tlcorner = wlr_scene_buffer_create(border->tree, &tltexture_buffer->base); - - - struct lab_data_buffer *trtexture_buffer = - buffer_create_from_data(renderedborders->tr, bw, bw, 4*bw); - border->trcorner = wlr_scene_buffer_create(border->tree, &trtexture_buffer->base); - - - struct lab_data_buffer *bltexture_buffer = - buffer_create_from_data(renderedborders->bl, bw, bw, 4*bw); - border->blcorner = wlr_scene_buffer_create(border->tree, &bltexture_buffer->base); - - struct lab_data_buffer *brtexture_buffer = - buffer_create_from_data(renderedborders->br, bw, bw, 4*bw); - border->brcorner = wlr_scene_buffer_create(border->tree, &brtexture_buffer->base); + struct borderset * renderedborders = getBorders(colour32, bw, BORDER_SINGLE, 0); + border->texturedBorders = generateBufferset(border->tree, renderedborders, bw); } else { - border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, color); - border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, color); - border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0, color); - border->left = lab_wlr_scene_rect_create(border->tree, 0, 0, color); - border->tlcorner=NULL; - border->trcorner=NULL; - border->blcorner=NULL; - border->brcorner=NULL; + border->texturedBorders = NULL; } @@ -156,56 +102,8 @@ resize_border(struct border_scene *border, int border_width, int width, int heig 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); - - if (border->tlcorner != NULL) { - wlr_scene_buffer_set_dest_size(border->ttexture, - width, border_width); - wlr_scene_node_set_position(&border->ttexture->node, - 0,0); - - wlr_scene_buffer_set_dest_size(border->btexture, - width, border_width); - wlr_scene_node_set_position(&border->btexture->node, - 0, height - border_width); - - - wlr_scene_buffer_set_dest_size(border->ltexture, - border_width, height - border_width * 2); - wlr_scene_node_set_position(&border->ltexture->node, - 0, border_width); - - wlr_scene_buffer_set_dest_size(border->rtexture, - border_width, height - border_width * 2); - wlr_scene_node_set_position(&border->rtexture->node, - width - border_width, border_width); - - - - - - wlr_scene_buffer_set_dest_size(border->tlcorner, - border_width, border_width); - wlr_scene_node_set_position(&border->tlcorner->node, - 0,0); - - wlr_scene_buffer_set_dest_size(border->trcorner, - border_width, border_width); - wlr_scene_node_set_position(&border->trcorner->node, - width-border_width, 0); - - - wlr_scene_buffer_set_dest_size(border->brcorner, - border_width, border_width); - wlr_scene_node_set_position(&border->brcorner->node, - width-border_width , height-border_width); - - - wlr_scene_buffer_set_dest_size(border->blcorner, - border_width, border_width); - wlr_scene_node_set_position(&border->blcorner->node, - 0, height-border_width); - - + if (border->texturedBorders != NULL) { + renderBufferset(border->texturedBorders, width, height, 0); } } diff --git a/src/cycle/cycle.c b/src/cycle/cycle.c index a06b9a36..28978792 100644 --- a/src/cycle/cycle.c +++ b/src/cycle/cycle.c @@ -37,7 +37,7 @@ update_preview_outlines(struct view *view) }, .nr_borders = 3, .border_width = theme->osd_window_switcher_preview_border_width, - .beveled = 1, // Checked + .beveled = true, }; rect = lab_scene_rect_create(&server.scene->tree, &opts); wlr_scene_node_place_above(&rect->tree->node, diff --git a/src/cycle/osd-classic.c b/src/cycle/osd-classic.c index 9cfd3cea..074de8f8 100644 --- a/src/cycle/osd-classic.c +++ b/src/cycle/osd-classic.c @@ -120,7 +120,7 @@ cycle_osd_classic_init(struct cycle_osd_output *osd_output) .bg_color = bg_color, .width = w, .height = h, - .beveled = 1, + .beveled = true, }; lab_scene_rect_create(osd_output->tree, &bg_opts); diff --git a/src/cycle/osd-scroll.c b/src/cycle/osd-scroll.c index d0d6b716..b8b579a2 100644 --- a/src/cycle/osd-scroll.c +++ b/src/cycle/osd-scroll.c @@ -35,7 +35,7 @@ cycle_osd_scroll_init(struct cycle_osd_output *osd_output, struct wlr_box bar_ar .bg_color = bg_color, .width = bar_area.width, .height = bar_area.height * nr_visible_rows / nr_rows, - .beveled = 1, + .beveled = true, }; scroll->bar = lab_scene_rect_create(scroll->bar_tree, &scrollbar_opts); } diff --git a/src/cycle/osd-thumbnail.c b/src/cycle/osd-thumbnail.c index 699fc1be..1e7ca8e2 100644 --- a/src/cycle/osd-thumbnail.c +++ b/src/cycle/osd-thumbnail.c @@ -150,7 +150,7 @@ create_item_scene(struct wlr_scene_tree *parent, struct view *view, .bg_color = switcher_theme->item_active_bg_color, .width = switcher_theme->item_width, .height = switcher_theme->item_height, - .beveled = 1, + .beveled = true, }; item->active_bg = lab_scene_rect_create(tree, &opts); @@ -283,7 +283,7 @@ cycle_osd_thumbnail_init(struct cycle_osd_output *osd_output) .bg_color = theme->osd_bg_color, .width = items_width + 2 * padding, .height = items_height + 2 * padding, - .beveled = 1, + .beveled = true, }; struct lab_scene_rect *bg = lab_scene_rect_create(osd_output->tree, &bg_opts); diff --git a/src/menu/menu.c b/src/menu/menu.c index bf75f7dc..056294a0 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -169,7 +169,7 @@ item_create_scene_for_state(struct menuitem *item, float *text_color, { struct menu *menu = item->parent; struct theme *theme = rc.theme; - struct wlr_scene_buffer *top, *left, *right, *bottom, *tl, *tr, *bl, *br; + struct bufferset * bufferset; /* Tree to hold background and label buffers */ struct wlr_scene_tree *tree = lab_wlr_scene_tree_create(item->tree); @@ -203,42 +203,8 @@ item_create_scene_for_state(struct menuitem *item, float *text_color, uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, 3, 0); - struct lab_data_buffer *ttexture_buffer = - buffer_create_from_data(renderedborders->top, 1, 1, 4); - top = wlr_scene_buffer_create(tree, &ttexture_buffer->base); - - struct lab_data_buffer *ltexture_buffer = - buffer_create_from_data(renderedborders->left, 1, 1, 4); - left = wlr_scene_buffer_create(tree, <exture_buffer->base); - - struct lab_data_buffer *rtexture_buffer = - buffer_create_from_data(renderedborders->right, 1, 1, 4); - right = wlr_scene_buffer_create(tree, &rtexture_buffer->base); - - struct lab_data_buffer *btexture_buffer = - buffer_create_from_data(renderedborders->bottom, 1, 1, 4); - bottom = wlr_scene_buffer_create(tree, &btexture_buffer->base); - - - struct lab_data_buffer *tltexture_buffer = - buffer_create_from_data(renderedborders->tl, bw, bw, 4*bw); - tl = wlr_scene_buffer_create(tree, &tltexture_buffer->base); - - - struct lab_data_buffer *trtexture_buffer = - buffer_create_from_data(renderedborders->tr, bw, bw, 4*bw); - tr = wlr_scene_buffer_create(tree, &trtexture_buffer->base); - - - struct lab_data_buffer *bltexture_buffer = - buffer_create_from_data(renderedborders->bl, bw, bw, 4*bw); - bl = wlr_scene_buffer_create(tree, &bltexture_buffer->base); - - struct lab_data_buffer *brtexture_buffer = - buffer_create_from_data(renderedborders->br, bw, bw, 4*bw); - br = wlr_scene_buffer_create(tree, &brtexture_buffer->base); - + struct borderset * renderedborders = getBorders(colour32, bw, BORDER_INSET, 0); + bufferset = generateBufferset(tree, renderedborders, bw); } @@ -275,55 +241,7 @@ item_create_scene_for_state(struct menuitem *item, float *text_color, if (rc.theme->beveled_border && state) { - - int height = theme->menu_item_height; - - wlr_scene_buffer_set_dest_size(top, - bg_width, bw); - wlr_scene_node_set_position(&top->node, - 0,0); - - wlr_scene_buffer_set_dest_size(bottom, - bg_width, bw); - wlr_scene_node_set_position(&bottom->node, - 0, height - bw); - - - wlr_scene_buffer_set_dest_size(left, - bw, height - bw * 2); - wlr_scene_node_set_position(&left->node, - 0, bw); - - wlr_scene_buffer_set_dest_size(right, - bw, height - bw * 2); - wlr_scene_node_set_position(&right->node, - bg_width - bw, bw); - - - - - - wlr_scene_buffer_set_dest_size(tl, - bw, bw); - wlr_scene_node_set_position(&tl->node, - 0,0); - - wlr_scene_buffer_set_dest_size(tr, - bw, bw); - wlr_scene_node_set_position(&tr->node, - bg_width-bw, 0); - - - wlr_scene_buffer_set_dest_size(br, - bw, bw); - wlr_scene_node_set_position(&br->node, - bg_width-bw , height-bw); - - - wlr_scene_buffer_set_dest_size(bl, - bw, bw); - wlr_scene_node_set_position(&bl->node, - 0, height-bw); + renderBufferset(bufferset, bg_width, theme->menu_item_height, 0); } @@ -446,6 +364,8 @@ title_create_scene(struct menuitem *menuitem, int *item_y) assert(menuitem->type == LAB_MENU_TITLE); struct menu *menu = menuitem->parent; struct theme *theme = rc.theme; + struct bufferset * bufferset; + float *bg_color = theme->menu_title_bg_color; float *text_color = theme->menu_title_text_color; @@ -464,6 +384,21 @@ title_create_scene(struct menuitem *menuitem, int *item_y) wlr_log(WLR_ERROR, "not enough space for menu title"); goto error; } + + + int bw = theme->menu_border_width; + if (rc.theme->beveled_border) { + float r = bg_color[0]; + float g = bg_color[1]; + float b = bg_color[2]; + float a = bg_color[3]; + + + uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); + struct borderset * renderedborders = getBorders(colour32, bw, BORDER_SINGLE, 0); + bufferset = generateBufferset(menuitem->tree, renderedborders, bw); + } + /* Background */ lab_wlr_scene_rect_create(menuitem->normal_tree, @@ -493,6 +428,10 @@ title_create_scene(struct menuitem *menuitem, int *item_y) int title_y = (theme->menu_header_height - title_font_buffer->height) / 2; wlr_scene_node_set_position(&title_font_buffer->scene_buffer->node, title_x, title_y); + + if (rc.theme->beveled_border) { + renderBufferset(bufferset, bg_width, theme->menu_item_height, 0); + } error: wlr_scene_node_set_position(&menuitem->tree->node, theme->menu_border_width, *item_y); @@ -565,7 +504,7 @@ menu_create_scene(struct menu *menu) .border_width = theme->menu_border_width, .width = menu->size.width, .height = menu->size.height, - .beveled = 1, + .beveled = true, }; struct lab_scene_rect *bg_rect = lab_scene_rect_create(menu->scene_tree, &opts); diff --git a/src/ssd/resize-indicator.c b/src/ssd/resize-indicator.c index 5ffa3aa5..c4af32d3 100644 --- a/src/ssd/resize-indicator.c +++ b/src/ssd/resize-indicator.c @@ -61,44 +61,8 @@ resize_indicator_init(struct view *view) int bw = rc.theme->osd_border_width; uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, 1, 0); - struct lab_data_buffer *ttexture_buffer = - buffer_create_from_data(renderedborders->top, 1, 1, 4); - indicator->top = wlr_scene_buffer_create(indicator->tree, &ttexture_buffer->base); - - struct lab_data_buffer *ltexture_buffer = - buffer_create_from_data(renderedborders->left, 1, 1, 4); - indicator->left = wlr_scene_buffer_create(indicator->tree, <exture_buffer->base); - - struct lab_data_buffer *rtexture_buffer = - buffer_create_from_data(renderedborders->right, 1, 1, 4); - indicator->right = wlr_scene_buffer_create(indicator->tree, &rtexture_buffer->base); - - struct lab_data_buffer *btexture_buffer = - buffer_create_from_data(renderedborders->bottom, 1, 1, 4); - indicator->bottom = wlr_scene_buffer_create(indicator->tree, &btexture_buffer->base); - - - struct lab_data_buffer *tltexture_buffer = - buffer_create_from_data(renderedborders->tl, bw, bw, 4*bw); - indicator->tl = wlr_scene_buffer_create(indicator->tree, &tltexture_buffer->base); - - - struct lab_data_buffer *trtexture_buffer = - buffer_create_from_data(renderedborders->tr, bw, bw, 4*bw); - indicator->tr = wlr_scene_buffer_create(indicator->tree, &trtexture_buffer->base); - - - struct lab_data_buffer *bltexture_buffer = - buffer_create_from_data(renderedborders->bl, bw, bw, 4*bw); - indicator->bl = wlr_scene_buffer_create(indicator->tree, &bltexture_buffer->base); - - struct lab_data_buffer *brtexture_buffer = - buffer_create_from_data(renderedborders->br, bw, bw, 4*bw); - indicator->br = wlr_scene_buffer_create(indicator->tree, &brtexture_buffer->base); - - - + struct borderset * renderedborders = getBorders(colour32, bw, BORDER_SINGLE, 0); + indicator->texturedBorders = generateBufferset(indicator->tree, renderedborders, bw); } @@ -171,58 +135,8 @@ resize_indicator_set_size(struct resize_indicator *indicator, int width) indicator->width - 2 * rc.theme->osd_border_width, indicator->height - 2 * rc.theme->osd_border_width); - if (rc.theme->beveled_border) { - - int height = indicator->height; - int border_width = rc.theme->osd_border_width; - - wlr_scene_buffer_set_dest_size(indicator->top, - indicator->width, border_width); - wlr_scene_node_set_position(&indicator->top->node, - 0,0); - - wlr_scene_buffer_set_dest_size(indicator->bottom, - indicator->width, border_width); - wlr_scene_node_set_position(&indicator->bottom->node, - 0, height - border_width); - - - wlr_scene_buffer_set_dest_size(indicator->left, - border_width, height - border_width * 2); - wlr_scene_node_set_position(&indicator->left->node, - 0, border_width); - - wlr_scene_buffer_set_dest_size(indicator->right, - border_width, height - border_width * 2); - wlr_scene_node_set_position(&indicator->right->node, - indicator->width - border_width, border_width); - - - - - - wlr_scene_buffer_set_dest_size(indicator->tl, - border_width, border_width); - wlr_scene_node_set_position(&indicator->tl->node, - 0,0); - - wlr_scene_buffer_set_dest_size(indicator->tr, - border_width, border_width); - wlr_scene_node_set_position(&indicator->tr->node, - indicator->width-border_width, 0); - - - wlr_scene_buffer_set_dest_size(indicator->br, - border_width, border_width); - wlr_scene_node_set_position(&indicator->br->node, - indicator->width-border_width , height-border_width); - - - wlr_scene_buffer_set_dest_size(indicator->bl, - border_width, border_width); - wlr_scene_node_set_position(&indicator->bl->node, - 0, height-border_width); - + if (rc.theme->beveled_border) { + renderBufferset(indicator->texturedBorders, indicator->width, indicator->height, 0); } } diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index 1309e752..91f54093 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -63,56 +63,9 @@ ssd_border_create(struct ssd *ssd) float a = color[3]; uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, 2, bevelSize); - - struct lab_data_buffer *ttexture_buffer = - buffer_create_from_data(renderedborders->top, 1,theme->border_width, - 4); - subtree->ttexture = wlr_scene_buffer_create(parent, &ttexture_buffer->base); - - - struct lab_data_buffer *btexture_buffer = - buffer_create_from_data(renderedborders->bottom, 1,theme->border_width, - 4); - subtree->btexture = wlr_scene_buffer_create(parent, &btexture_buffer->base); - - - struct lab_data_buffer *ltexture_buffer = - buffer_create_from_data(renderedborders->left, theme->border_width, 1, - 4*theme->border_width); - subtree->ltexture = wlr_scene_buffer_create(parent, <exture_buffer->base); - - - struct lab_data_buffer *rtexture_buffer = - buffer_create_from_data(renderedborders->right, theme->border_width, 1, - 4*theme->border_width); - subtree->rtexture = wlr_scene_buffer_create(parent, &rtexture_buffer->base); - - - - struct lab_data_buffer *tltexture_buffer = - buffer_create_from_data(renderedborders->tl, theme->border_width, theme->border_width, - 4*theme->border_width); - subtree->tlcorner = wlr_scene_buffer_create(parent, &tltexture_buffer->base); - - struct lab_data_buffer *trtexture_buffer = - buffer_create_from_data(renderedborders->tr, theme->border_width, theme->border_width, - 4*theme->border_width); - subtree->trcorner = wlr_scene_buffer_create(parent, &trtexture_buffer->base); - - - - struct lab_data_buffer *bltexture_buffer = - buffer_create_from_data(renderedborders->bl, theme->border_width, theme->border_width, - 4*theme->border_width); - subtree->blcorner = wlr_scene_buffer_create(parent, &bltexture_buffer->base); - - struct lab_data_buffer *brtexture_buffer = - buffer_create_from_data(renderedborders->br, theme->border_width, theme->border_width, - 4*theme->border_width); - subtree->brcorner = wlr_scene_buffer_create(parent, &brtexture_buffer->base); - } else { - + struct borderset * renderedborders = getBorders(colour32, bw, BORDER_DOUBLE, bevelSize); + subtree->texturedBorders = generateBufferset(subtree->tree, renderedborders, bw); + } else { subtree->left = lab_wlr_scene_rect_create(parent, theme->border_width, height, color); @@ -220,47 +173,7 @@ ssd_border_update(struct ssd *ssd) if (theme->beveled_border) { - wlr_scene_buffer_set_dest_size(subtree->ttexture, - full_width, theme->border_width); - wlr_scene_node_set_position(&subtree->ttexture->node, - 0, -(ssd->titlebar.height + theme->border_width)); - - wlr_scene_buffer_set_dest_size(subtree->rtexture, - theme->border_width, side_height+(ssd->titlebar.height + theme->border_width)); - wlr_scene_node_set_position(&subtree->rtexture->node, - theme->border_width + width, -(ssd->titlebar.height + theme->border_width)); - - wlr_scene_buffer_set_dest_size(subtree->btexture, - full_width, theme->border_width); - wlr_scene_node_set_position(&subtree->btexture->node, - 0, height); - - wlr_scene_buffer_set_dest_size(subtree->ltexture, - theme->border_width, side_height+(ssd->titlebar.height + theme->border_width)); - wlr_scene_node_set_position(&subtree->ltexture->node, - 0, -(ssd->titlebar.height + theme->border_width)); - - wlr_scene_buffer_set_dest_size(subtree->tlcorner, - theme->border_width, theme->border_width); - wlr_scene_node_set_position(&subtree->tlcorner->node, - 0, -(ssd->titlebar.height + theme->border_width)); - - wlr_scene_buffer_set_dest_size(subtree->trcorner, - theme->border_width, theme->border_width); - wlr_scene_node_set_position(&subtree->trcorner->node, - theme->border_width + width, -(ssd->titlebar.height + theme->border_width)); - - - wlr_scene_buffer_set_dest_size(subtree->brcorner, - theme->border_width, theme->border_width); - wlr_scene_node_set_position(&subtree->brcorner->node, - theme->border_width + width, height); - - - wlr_scene_buffer_set_dest_size(subtree->blcorner, - theme->border_width, theme->border_width); - wlr_scene_node_set_position(&subtree->blcorner->node, - 0, height); + renderBufferset(subtree->texturedBorders, full_width, side_height+(ssd->titlebar.height + 2*theme->border_width), -ssd->titlebar.height-theme->border_width); } else { wlr_scene_rect_set_size(subtree->left, theme->border_width, side_height); diff --git a/src/theme.c b/src/theme.c index 04200800..c831599d 100644 --- a/src/theme.c +++ b/src/theme.c @@ -532,7 +532,7 @@ static void theme_builtin(struct theme *theme) { theme->border_width = 1; - theme->beveled_border = FALSE; + theme->beveled_border = false; theme->border_bevel_width=0; theme->window_titlebar_padding_height = 0; theme->window_titlebar_padding_width = 0; diff --git a/src/workspaces.c b/src/workspaces.c index 0dc1205e..6e81a228 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -114,7 +114,7 @@ _osd_update(void) float a = theme->osd_border_color[3]; uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, 1, 0); + struct borderset * renderedborders = getBorders(colour32, bw, BORDER_SINGLE, 0); cairo_surface_t* top = cairo_image_surface_create_for_data((unsigned char *)renderedborders->top, CAIRO_FORMAT_ARGB32, 1, 1, 4); From 6148934dd7ad4c7cc872c4fd65484af0520df7d4 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sat, 28 Mar 2026 18:49:42 -0700 Subject: [PATCH 22/47] Protection around allocating malformed border buffers --- src/common/borderset.c | 15 +++++++++++++++ src/ssd/ssd-border.c | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/common/borderset.c b/src/common/borderset.c index 0c02b6c1..f889ae33 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -4,9 +4,24 @@ #include "common/macros.h" #include "buffer.h" + struct borderset * getBorders(uint32_t id, int size, enum border_type type, int bevelSize) { struct borderset * current = borderCache; struct borderset * last; + + // Preventing building nonsense borders: + // If you try for a double bevel but it's so deep they would overlap, convert to a single bevel + if (type == BORDER_DOUBLE && (bevelSize > size/2)) { + type = BORDER_SINGLE; + } + + // Anything with a size of 0 is converted to a 1-pixel flat border so as to prevent empty allocations + + if (size < 1) { + type = BORDER_FLAT; + size = 1; + } + while (current != NULL) { if (current->size == size && current->id == id && current->type == type) { return current; diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index 91f54093..4bfd40b5 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -54,7 +54,7 @@ ssd_border_create(struct ssd *ssd) - int bevelSize = theme->border_bevel_width; // TODO: configurable + int bevelSize = theme->border_bevel_width; /* From Pull request 3382 */ float r = color[0]; From f2867e5f0a8c6548062843c0d648a5cb008bc55b Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Sun, 29 Mar 2026 14:27:00 +0200 Subject: [PATCH 23/47] [wip] keep wlr_buffers around --- include/common/borderset.h | 16 +-- src/common/borderset.c | 262 ++++++++++++++++++------------------- 2 files changed, 132 insertions(+), 146 deletions(-) diff --git a/include/common/borderset.h b/include/common/borderset.h index f0392874..a7b2c0f8 100644 --- a/include/common/borderset.h +++ b/include/common/borderset.h @@ -11,14 +11,14 @@ struct borderset { uint32_t id; // Base colour, but could be used as a tracking hash for images or whatever in the future int size; // width (since I suspect a 2px border scaled up to 20px might look weird) enum border_type type; // Single or double bevel - uint32_t * top; - uint32_t * left; - uint32_t * right; - uint32_t * bottom; - uint32_t * tl; - uint32_t * tr; - uint32_t * bl; - uint32_t * br; + struct lab_data_buffer *top; + struct lab_data_buffer *left; + struct lab_data_buffer *right; + struct lab_data_buffer *bottom; + struct lab_data_buffer *tl; + struct lab_data_buffer *tr; + struct lab_data_buffer *bl; + struct lab_data_buffer *br; struct borderset * next; }; diff --git a/src/common/borderset.c b/src/common/borderset.c index f889ae33..259e94c6 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -1,3 +1,4 @@ +#include #include #include "common/borderset.h" #include "common/mem.h" @@ -43,6 +44,7 @@ struct borderset * getBorders(uint32_t id, int size, enum border_type type, int struct borderset * createBuffer(uint32_t id, int size, enum border_type type, int bevelSize) { struct borderset *newBorderset = znew(*newBorderset); + newBorderset->next = NULL; newBorderset->id = id; @@ -75,29 +77,35 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i // All borders have NxN corners - newBorderset->tl = znew_n(uint32_t, size*size); - newBorderset->tr = znew_n(uint32_t, size*size); - newBorderset->bl = znew_n(uint32_t, size*size); - newBorderset->br = znew_n(uint32_t, size*size); - + uint32_t *tl = znew_n(uint32_t, size*size); + uint32_t *tr = znew_n(uint32_t, size*size); + uint32_t *bl = znew_n(uint32_t, size*size); + uint32_t *br = znew_n(uint32_t, size*size); + uint32_t *top = NULL; + uint32_t *left = NULL; + uint32_t *right = NULL; + uint32_t *bottom = NULL; + size_t side_size = 0; + switch(type) { case BORDER_SINGLE: // Single bevel borders have 1x1 sides - newBorderset->top = znew(uint32_t); - newBorderset->left = znew(uint32_t); - newBorderset->right = znew(uint32_t); - newBorderset->bottom = znew(uint32_t); - *newBorderset->top = hl32; - *newBorderset->left = hl32; - *newBorderset->right = ll32; - *newBorderset->bottom = ll32; + top = znew(uint32_t); + left = znew(uint32_t); + right = znew(uint32_t); + bottom = znew(uint32_t); + side_size = 1; + *top = hl32; + *left = hl32; + *right = ll32; + *bottom = ll32; // Fill with solid for (int j=0; jtl[PIXEL(j, k, size)] = hl32; - newBorderset->tr[PIXEL(size - 1 - j, k, size)] = (j > k) ? hl32 : ll32; - newBorderset->bl[PIXEL(size - 1 -j, k, size)] = (j > k) ? hl32 : ll32; - newBorderset->br[PIXEL(j, k, size)] = ll32; + tl[PIXEL(j, k, size)] = hl32; + tr[PIXEL(size - 1 - j, k, size)] = (j > k) ? hl32 : ll32; + bl[PIXEL(size - 1 -j, k, size)] = (j > k) ? hl32 : ll32; + br[PIXEL(j, k, size)] = ll32; } } @@ -107,39 +115,40 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i case BORDER_DOUBLE: - newBorderset->top = znew_n(uint32_t, size); - newBorderset->left = znew_n(uint32_t, size); - newBorderset->right = znew_n(uint32_t, size); - newBorderset->bottom = znew_n(uint32_t, size); + top = znew_n(uint32_t, size); + left = znew_n(uint32_t, size); + right = znew_n(uint32_t, size); + bottom = znew_n(uint32_t, size); + side_size = size; for (int i = 0; i < size; i++) { if (ileft[i] = hl32; - newBorderset->top[i] = hl32; - newBorderset->right[i] = hl32; - newBorderset->bottom[i] = hl32; + left[i] = hl32; + top[i] = hl32; + right[i] = hl32; + bottom[i] = hl32; } else if (i > (size-bevelSize-1)) { - newBorderset->left[i] = ll32; - newBorderset->top[i] = ll32; - newBorderset->right[i] = ll32; - newBorderset->bottom[i] = ll32; + left[i] = ll32; + top[i] = ll32; + right[i] = ll32; + bottom[i] = ll32; } else { - newBorderset->left[i] = id; - newBorderset->top[i] = id; - newBorderset->right[i] = id; - newBorderset->bottom[i] = id; + left[i] = id; + top[i] = id; + right[i] = id; + bottom[i] = id; } } // Blank corners... for (int i=0; itl[PIXEL(i, j, size)] = id; - newBorderset->tr[PIXEL(i, j, size)] = id; - newBorderset->bl[PIXEL(i, j, size)] = id; - newBorderset->br[PIXEL(i, j, size)] = id; + tl[PIXEL(i, j, size)] = id; + tr[PIXEL(i, j, size)] = id; + bl[PIXEL(i, j, size)] = id; + br[PIXEL(i, j, size)] = id; } } @@ -150,25 +159,25 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i // Solid bar parts for (int j=0; jtl[PIXEL(j, i, size)] = hl32; + tl[PIXEL(j, i, size)] = hl32; // First "bevel size" top columns are highlighted - newBorderset->tl[PIXEL(i, j, size)] = hl32; + tl[PIXEL(i, j, size)] = hl32; // Bottom Right corner: Entire "bevel size" last rows are lowlight - newBorderset->br[PIXEL(j, (size-1-i), size)] = ll32; + br[PIXEL(j, (size-1-i), size)] = ll32; // Last "bevel size" columns are lowlight - newBorderset->br[PIXEL((size-1-i), j, size)] = ll32; + br[PIXEL((size-1-i), j, size)] = ll32; // Bottom left corner: Entire "bevel size" last rows are lowlight - newBorderset->bl[PIXEL(j, (size-1-i), size)] = ll32; + bl[PIXEL(j, (size-1-i), size)] = ll32; // First "bevel size" columns are highlight, except for the bottom right corner - newBorderset->bl[PIXEL(i, j, size)] = hl32; + bl[PIXEL(i, j, size)] = hl32; // Top Right corner: Entire "bevel size" first rows are highlight - newBorderset->tr[PIXEL(j, i, size)] = hl32; + tr[PIXEL(j, i, size)] = hl32; // Last "bevel size" columns are lowlight, except for the top left - newBorderset->tr[PIXEL((size-1-i), j, size)] = ll32; + tr[PIXEL((size-1-i), j, size)] = ll32; } } @@ -179,27 +188,27 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i // Outer Corners // Bottom left corner: // First "bevel size" columns are highlight, except for the bottom right corner - newBorderset->bl[PIXEL(i, (size - 1 - j), size)] = (j >= i) ? hl32 : ll32; + bl[PIXEL(i, (size - 1 - j), size)] = (j >= i) ? hl32 : ll32; // Top Right corner: // Last "bevel size" columns are lowlight, except for the top left - newBorderset->tr[PIXEL((size-1-i), j, size)] = (j > i) ? ll32 : hl32; + tr[PIXEL((size-1-i), j, size)] = (j > i) ? ll32 : hl32; // Inner Corners // Top left corner: Bottom right is all dark - newBorderset->tl[PIXEL((size-1-i), (size - 1 - j), size)] = ll32; + tl[PIXEL((size-1-i), (size - 1 - j), size)] = ll32; // Bottom Right corner: Top left is all light - newBorderset->br[PIXEL(i, j, size)] = hl32; + br[PIXEL(i, j, size)] = hl32; // Top Right corner: // Interior bottom left is dark on top, light on bottom - newBorderset->tr[PIXEL(i, (size-1-j), size)] = (i > j) ? hl32 : ll32; + tr[PIXEL(i, (size-1-j), size)] = (i > j) ? hl32 : ll32; // Bottom Left corner: // Interior top right is dark on top, light on bottom - newBorderset->bl[PIXEL((size-1-i), j, size)] = (i > j) ? ll32 : hl32; + bl[PIXEL((size-1-i), j, size)] = (i > j) ? ll32 : hl32; @@ -214,22 +223,23 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i break; case BORDER_FLAT: // Placeholder that uses buffers but for a flat colour - newBorderset->top = znew(uint32_t); - newBorderset->left = znew(uint32_t); - newBorderset->right = znew(uint32_t); - newBorderset->bottom = znew(uint32_t); - *newBorderset->top = id; - *newBorderset->left = id; - *newBorderset->right = id; - *newBorderset->bottom = id; + top = znew(uint32_t); + left = znew(uint32_t); + right = znew(uint32_t); + bottom = znew(uint32_t); + side_size = 1; + *top = id; + *left = id; + *right = id; + *bottom = id; // Fill with solid for (int j=0; jtl[PIXEL(j, k, size)] = id; - newBorderset->tr[PIXEL(size - 1 - j, k, size)] = id; - newBorderset->bl[PIXEL(size - 1 -j, k, size)] = id; - newBorderset->br[PIXEL(j, k, size)] = id; + tl[PIXEL(j, k, size)] = id; + tr[PIXEL(size - 1 - j, k, size)] = id; + bl[PIXEL(size - 1 -j, k, size)] = id; + br[PIXEL(j, k, size)] = id; } } @@ -238,22 +248,23 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i break; case BORDER_INSET: // Sunken Single bevel borders have 1x1 sides - newBorderset->top = znew(uint32_t); - newBorderset->left = znew(uint32_t); - newBorderset->right = znew(uint32_t); - newBorderset->bottom = znew(uint32_t); - *newBorderset->top = ll32; - *newBorderset->left = ll32; - *newBorderset->right = hl32; - *newBorderset->bottom = hl32; + top = znew(uint32_t); + left = znew(uint32_t); + right = znew(uint32_t); + bottom = znew(uint32_t); + side_size = 1; + *top = ll32; + *left = ll32; + *right = hl32; + *bottom = hl32; // Fill with solid for (int j=0; jtl[PIXEL(j, k, size)] = ll32; - newBorderset->tr[PIXEL(size - 1 - j, k, size)] = (j > k) ? ll32 : hl32; - newBorderset->bl[PIXEL(size - 1 -j, k, size)] = (j > k) ? ll32 : hl32; - newBorderset->br[PIXEL(j, k, size)] = hl32; + tl[PIXEL(j, k, size)] = ll32; + tr[PIXEL(size - 1 - j, k, size)] = (j > k) ? ll32 : hl32; + bl[PIXEL(size - 1 -j, k, size)] = (j > k) ? ll32 : hl32; + br[PIXEL(j, k, size)] = hl32; } } @@ -262,6 +273,18 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i break; } + assert(side_size > 0); + + newBorderset->top = buffer_create_from_data(top, 1, side_size, 4); + newBorderset->left = buffer_create_from_data(left, side_size, 1, side_size * 4); + newBorderset->right = buffer_create_from_data(right, side_size, 1, side_size * 4); + newBorderset->bottom = buffer_create_from_data(bottom, 1, side_size, 4); + + newBorderset->tl = buffer_create_from_data(tl, size, size, size * 4); + newBorderset->tr = buffer_create_from_data(tr, size, size, size * 4); + newBorderset->bl = buffer_create_from_data(bl, size, size, size * 4); + newBorderset->br = buffer_create_from_data(br, size, size, size * 4); + return newBorderset; } @@ -269,62 +292,26 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i struct bufferset * generateBufferset(struct wlr_scene_tree * tree, struct borderset *borderset, int bw) { struct bufferset * bufferset = znew(struct bufferset); - + + bufferset->top = wlr_scene_buffer_create(tree, &borderset->top->base); + bufferset->left= wlr_scene_buffer_create(tree, &borderset->left->base); + bufferset->right = wlr_scene_buffer_create(tree, &borderset->right->base); + bufferset->bottom = wlr_scene_buffer_create(tree, &borderset->bottom->base); + bufferset->tl = wlr_scene_buffer_create(tree, &borderset->tl->base); + bufferset->tr = wlr_scene_buffer_create(tree, &borderset->tr->base); + bufferset->bl = wlr_scene_buffer_create(tree, &borderset->bl->base); + bufferset->br = wlr_scene_buffer_create(tree, &borderset->br->base); + bufferset->border_width = bw; - if (borderset->type == BORDER_DOUBLE) { - struct lab_data_buffer *ttexture_buffer = - buffer_create_from_data(borderset->top, 1, bw, 4); - bufferset->top = wlr_scene_buffer_create(tree, &ttexture_buffer->base); - struct lab_data_buffer *ltexture_buffer = - buffer_create_from_data(borderset->left, bw, 1, 4*bw); - bufferset->left = wlr_scene_buffer_create(tree, <exture_buffer->base); - - struct lab_data_buffer *rtexture_buffer = - buffer_create_from_data(borderset->right, bw, 1, 4*bw); - bufferset->right = wlr_scene_buffer_create(tree, &rtexture_buffer->base); - - struct lab_data_buffer *btexture_buffer = - buffer_create_from_data(borderset->bottom, 1, bw, 4); - bufferset->bottom = wlr_scene_buffer_create(tree, &btexture_buffer->base); - - - } else { - struct lab_data_buffer *ttexture_buffer = - buffer_create_from_data(borderset->top, 1, 1, 4); - bufferset->top = wlr_scene_buffer_create(tree, &ttexture_buffer->base); - - struct lab_data_buffer *ltexture_buffer = - buffer_create_from_data(borderset->left, 1, 1, 4); - bufferset->left = wlr_scene_buffer_create(tree, <exture_buffer->base); - - struct lab_data_buffer *rtexture_buffer = - buffer_create_from_data(borderset->right, 1, 1, 4); - bufferset->right = wlr_scene_buffer_create(tree, &rtexture_buffer->base); - - struct lab_data_buffer *btexture_buffer = - buffer_create_from_data(borderset->bottom, 1, 1, 4); - bufferset->bottom = wlr_scene_buffer_create(tree, &btexture_buffer->base); - } - - - struct lab_data_buffer *tltexture_buffer = - buffer_create_from_data(borderset->tl, bw, bw, 4*bw); - bufferset->tl = wlr_scene_buffer_create(tree, &tltexture_buffer->base); - - - struct lab_data_buffer *trtexture_buffer = - buffer_create_from_data(borderset->tr, bw, bw, 4*bw); - bufferset->tr = wlr_scene_buffer_create(tree, &trtexture_buffer->base); - - - struct lab_data_buffer *bltexture_buffer = - buffer_create_from_data(borderset->bl, bw, bw, 4*bw); - bufferset->bl = wlr_scene_buffer_create(tree, &bltexture_buffer->base); - - struct lab_data_buffer *brtexture_buffer = - buffer_create_from_data(borderset->br, bw, bw, 4*bw); - bufferset->br = wlr_scene_buffer_create(tree, &brtexture_buffer->base); + wlr_scene_buffer_set_filter_mode(bufferset->top, WLR_SCALE_FILTER_NEAREST); + wlr_scene_buffer_set_filter_mode(bufferset->left, WLR_SCALE_FILTER_NEAREST); + wlr_scene_buffer_set_filter_mode(bufferset->right, WLR_SCALE_FILTER_NEAREST); + wlr_scene_buffer_set_filter_mode(bufferset->bottom, WLR_SCALE_FILTER_NEAREST); + wlr_scene_buffer_set_filter_mode(bufferset->tl, WLR_SCALE_FILTER_NEAREST); + wlr_scene_buffer_set_filter_mode(bufferset->tr, WLR_SCALE_FILTER_NEAREST); + wlr_scene_buffer_set_filter_mode(bufferset->bl, WLR_SCALE_FILTER_NEAREST); + wlr_scene_buffer_set_filter_mode(bufferset->br, WLR_SCALE_FILTER_NEAREST); return bufferset; } @@ -384,14 +371,13 @@ void clearBorderCache(struct borderset * borderset) if (borderset->next != NULL) { clearBorderCache(borderset->next); } - - free(borderset->top); - free(borderset->left); - free(borderset->right); - free(borderset->bottom); - free(borderset->tl); - free(borderset->tr); - free(borderset->bl); - free(borderset->br); + wlr_buffer_drop(&borderset->top->base); + wlr_buffer_drop(&borderset->left->base); + wlr_buffer_drop(&borderset->right->base); + wlr_buffer_drop(&borderset->bottom->base); + wlr_buffer_drop(&borderset->tl->base); + wlr_buffer_drop(&borderset->tr->base); + wlr_buffer_drop(&borderset->bl->base); + wlr_buffer_drop(&borderset->br->base); free(borderset); } From 8188f0a80e869800c51864dd007e834a1a087d9c Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Tue, 31 Mar 2026 22:23:54 -0700 Subject: [PATCH 24/47] Adapt workspace switcher Cairo logic to use modified border cache --- src/workspaces.c | 53 ++++++++++++++++-------------------------------- 1 file changed, 18 insertions(+), 35 deletions(-) diff --git a/src/workspaces.c b/src/workspaces.c index 6e81a228..b68729ec 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -116,64 +116,47 @@ _osd_update(void) uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); struct borderset * renderedborders = getBorders(colour32, bw, BORDER_SINGLE, 0); - - cairo_surface_t* top = cairo_image_surface_create_for_data((unsigned char *)renderedborders->top, CAIRO_FORMAT_ARGB32, 1, 1, 4); - cairo_set_source_surface(cairo, top, 0, 0); + cairo_set_source_surface(cairo, renderedborders->top->surface, 0, 0); cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); cairo_rectangle(cairo, bw, 0, width-bw*2, bw); cairo_fill(cairo); - cairo_surface_finish(top); - - cairo_surface_t* bottom = cairo_image_surface_create_for_data((unsigned char *)renderedborders->bottom, CAIRO_FORMAT_ARGB32, 1, 1, 4); - cairo_set_source_surface(cairo, bottom, 0, 0); + + cairo_set_source_surface(cairo, renderedborders->bottom->surface, 0, 0); cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); cairo_rectangle(cairo, bw, height-bw, width-bw*2, bw); cairo_fill(cairo); - cairo_surface_finish(bottom); + - - cairo_surface_t* left = cairo_image_surface_create_for_data((unsigned char *)renderedborders->left, CAIRO_FORMAT_ARGB32, 1, 1, 4); - cairo_set_source_surface(cairo, left, 0, 0); + + cairo_set_source_surface(cairo, renderedborders->left->surface, 0, 0); cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); cairo_rectangle(cairo, 0, bw, bw, height-bw*2); cairo_fill(cairo); - cairo_surface_finish(left); - - cairo_surface_t* right = cairo_image_surface_create_for_data((unsigned char *)renderedborders->right, CAIRO_FORMAT_ARGB32, 1, 1, 4); - cairo_set_source_surface(cairo, right, 0, 0); + + + cairo_set_source_surface(cairo, renderedborders->right->surface, 0, 0); cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); cairo_rectangle(cairo, width-bw, bw, bw, height-bw*2); cairo_fill(cairo); - cairo_surface_finish(right); + - - cairo_surface_t* tl = cairo_image_surface_create_for_data((unsigned char *)renderedborders->tl, CAIRO_FORMAT_ARGB32, bw, bw, 4*bw); - cairo_set_source_surface(cairo, tl, 0, 0); + + cairo_set_source_surface(cairo, renderedborders->tl->surface, 0, 0); cairo_rectangle(cairo, 0, 0, bw, bw); cairo_fill(cairo); - cairo_surface_finish(tl); - - - - cairo_surface_t* tr = cairo_image_surface_create_for_data((unsigned char *)renderedborders->tr, CAIRO_FORMAT_ARGB32, bw, bw, 4*bw); - cairo_set_source_surface(cairo, tr, width-bw, 0); + cairo_set_source_surface(cairo, renderedborders->tr->surface, width-bw, 0); cairo_rectangle(cairo, width - bw, 0, bw, bw); cairo_fill(cairo); - cairo_surface_finish(tr); - - cairo_surface_t* bl = cairo_image_surface_create_for_data((unsigned char *)renderedborders->bl, CAIRO_FORMAT_ARGB32, bw, bw, 4*bw); - cairo_set_source_surface(cairo, bl, 0, height - bw); + + cairo_set_source_surface(cairo, renderedborders->bl->surface, 0, height - bw); cairo_rectangle(cairo, 0, height - bw, bw, bw); cairo_fill(cairo); - cairo_surface_finish(bl); - - cairo_surface_t* br = cairo_image_surface_create_for_data((unsigned char *)renderedborders->br, CAIRO_FORMAT_ARGB32, bw, bw, 4*bw); - cairo_set_source_surface(cairo, br, width - bw, height -bw); + + cairo_set_source_surface(cairo, renderedborders->br->surface, width - bw, height -bw); cairo_rectangle(cairo, width - bw, height - bw, bw, bw); cairo_fill(cairo); - cairo_surface_finish(br); - + set_cairo_color(cairo, theme->osd_border_color); } else { From bfd4364ba9ec286b934b0a5496c777eae551c0bf Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Tue, 31 Mar 2026 22:29:35 -0700 Subject: [PATCH 25/47] Correct blundered merge conflict resolution --- src/workspaces.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/workspaces.c b/src/workspaces.c index ddb6c2bd..0edd1b36 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -25,11 +25,6 @@ #include "theme.h" #include "view.h" -<<<<<<< master - -#define COSMIC_WORKSPACES_VERSION 1 -======= ->>>>>>> master #define EXT_WORKSPACES_VERSION 1 /* Internal helpers */ From fe44a2e9b36388e8f6341322025b18bb6e9d6395 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Wed, 1 Apr 2026 19:39:24 -0700 Subject: [PATCH 26/47] Reuse common code for raised and sunken bevels --- include/common/borderset.h | 2 +- src/common/borderset.c | 39 +++++++++++--------------------------- 2 files changed, 12 insertions(+), 29 deletions(-) diff --git a/include/common/borderset.h b/include/common/borderset.h index a7b2c0f8..6b2a9602 100644 --- a/include/common/borderset.h +++ b/include/common/borderset.h @@ -4,7 +4,7 @@ #define LABWC_BORDERSET_H enum border_type { - BORDER_FLAT, BORDER_SINGLE, BORDER_DOUBLE, BORDER_INSET + BORDER_FLAT, BORDER_SINGLE, BORDER_DOUBLE, BORDER_INSET, BORDER_DOUBLE_INSET }; struct borderset { diff --git a/src/common/borderset.c b/src/common/borderset.c index 259e94c6..bae5c601 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -74,7 +74,7 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i | ((uint32_t)g1 << 8) | (uint32_t)b1; uint32_t ll32 = ((uint32_t)a << 24) | ((uint32_t)r0 << 16) | ((uint32_t)g0 << 8) | (uint32_t)b0; - + uint32_t temp; // All borders have NxN corners uint32_t *tl = znew_n(uint32_t, size*size); @@ -88,6 +88,11 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i size_t side_size = 0; switch(type) { + case BORDER_INSET: + temp = ll32; + ll32 = hl32; + hl32 = temp; + // Fall throgh intentional case BORDER_SINGLE: // Single bevel borders have 1x1 sides top = znew(uint32_t); left = znew(uint32_t); @@ -113,7 +118,11 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i break; - + case BORDER_DOUBLE_INSET: + temp = ll32; + ll32 = hl32; + hl32 = temp; + // Fall throgh intentional case BORDER_DOUBLE: top = znew_n(uint32_t, size); left = znew_n(uint32_t, size); @@ -246,32 +255,6 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i break; - - case BORDER_INSET: // Sunken Single bevel borders have 1x1 sides - top = znew(uint32_t); - left = znew(uint32_t); - right = znew(uint32_t); - bottom = znew(uint32_t); - side_size = 1; - *top = ll32; - *left = ll32; - *right = hl32; - *bottom = hl32; - - // Fill with solid - for (int j=0; j k) ? ll32 : hl32; - bl[PIXEL(size - 1 -j, k, size)] = (j > k) ? ll32 : hl32; - br[PIXEL(j, k, size)] = hl32; - } - } - - - - break; - } assert(side_size > 0); From b07165f154b405885925043d01bcd856be8e6474 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Wed, 1 Apr 2026 19:43:20 -0700 Subject: [PATCH 27/47] Ensure we use all details of borders when caching them --- include/common/borderset.h | 1 + src/common/borderset.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/common/borderset.h b/include/common/borderset.h index 6b2a9602..b1906668 100644 --- a/include/common/borderset.h +++ b/include/common/borderset.h @@ -11,6 +11,7 @@ struct borderset { uint32_t id; // Base colour, but could be used as a tracking hash for images or whatever in the future int size; // width (since I suspect a 2px border scaled up to 20px might look weird) enum border_type type; // Single or double bevel + int bevelSize; // So we can disambiguate multiple possible designs cached together struct lab_data_buffer *top; struct lab_data_buffer *left; struct lab_data_buffer *right; diff --git a/src/common/borderset.c b/src/common/borderset.c index bae5c601..13826161 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -24,7 +24,7 @@ struct borderset * getBorders(uint32_t id, int size, enum border_type type, int } while (current != NULL) { - if (current->size == size && current->id == id && current->type == type) { + if (current->size == size && current->id == id && current->type == type && current->bevelSize == bevelSize) { return current; } last = current; @@ -50,6 +50,7 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i newBorderset->id = id; newBorderset->size = size; newBorderset->type = type; + newBorderset->bevelSize = bevelSize; // Use ID as a AARRGGBB colour From 773996f1ee6af074b202753c1777ff7df2b71314 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Wed, 1 Apr 2026 20:18:43 -0700 Subject: [PATCH 28/47] add window.*.border.type and window.*.border.bevel-width options --- include/common/borderset.h | 1 + include/theme.h | 3 +++ src/common/borderset.c | 1 + src/ssd/ssd-border.c | 10 +++------- src/theme.c | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/include/common/borderset.h b/include/common/borderset.h index b1906668..d3bd8860 100644 --- a/include/common/borderset.h +++ b/include/common/borderset.h @@ -1,4 +1,5 @@ #include +#include /* SPDX-License-Identifier: GPL-2.0-only */ #ifndef LABWC_BORDERSET_H #define LABWC_BORDERSET_H diff --git a/include/theme.h b/include/theme.h index 123558f5..1ab6e323 100644 --- a/include/theme.h +++ b/include/theme.h @@ -11,6 +11,7 @@ #include #include #include "common/node-type.h" +#include "common/borderset.h" struct lab_img; @@ -98,6 +99,8 @@ struct theme { float border_color[4]; float toggled_keybinds_color[4]; float label_text_color[4]; + enum border_type border_type; + int bevel_width; /* window drop-shadows */ int shadow_size; diff --git a/src/common/borderset.c b/src/common/borderset.c index 13826161..083d451a 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -53,6 +53,7 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i newBorderset->bevelSize = bevelSize; + // Use ID as a AARRGGBB colour uint8_t a = id >> 24 & 255; uint8_t r = id >> 16 & 255; diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index 4bfd40b5..e26b80bf 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -39,7 +39,7 @@ ssd_border_create(struct ssd *ssd) struct wlr_scene_tree *parent = subtree->tree; wlr_scene_node_set_enabled(&parent->node, active); float *color = theme->window[active].border_color; - if (theme->beveled_border) { + if (theme->window[active].border_type) { // These will otherwise get left under the window when we reload @@ -51,10 +51,6 @@ ssd_border_create(struct ssd *ssd) subtree->bottom = lab_wlr_scene_rect_create(parent, 1, 1, color); subtree->top = lab_wlr_scene_rect_create(parent, 1, 1, color); - - - - int bevelSize = theme->border_bevel_width; /* From Pull request 3382 */ float r = color[0]; @@ -63,7 +59,7 @@ ssd_border_create(struct ssd *ssd) float a = color[3]; uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, BORDER_DOUBLE, bevelSize); + struct borderset * renderedborders = getBorders(colour32, bw, theme->window[active].border_type, theme->window[active].bevel_width); subtree->texturedBorders = generateBufferset(subtree->tree, renderedborders, bw); } else { subtree->left = lab_wlr_scene_rect_create(parent, @@ -172,7 +168,7 @@ ssd_border_update(struct ssd *ssd) struct ssd_border_subtree *subtree = &ssd->border.subtrees[active]; - if (theme->beveled_border) { + if (theme->window[active].border_type) { renderBufferset(subtree->texturedBorders, full_width, side_height+(ssd->titlebar.height + 2*theme->border_width), -ssd->titlebar.height-theme->border_width); } else { wlr_scene_rect_set_size(subtree->left, diff --git a/src/theme.c b/src/theme.c index c831599d..9e517a2d 100644 --- a/src/theme.c +++ b/src/theme.c @@ -450,6 +450,18 @@ parse_hexstrs(const char *hexes, float colors[3][4]) g_strfreev(elements); } +static enum border_type parse_border_type(const char *str) { + char *lower = g_ascii_strdown(str, -1); + if (strstr(lower, "doublesunken")) return BORDER_DOUBLE_INSET; + if (strstr(lower, "sunken")) return BORDER_INSET; + if (strstr(lower, "doubleraised")) return BORDER_DOUBLE; + if (strstr(lower, "raised")) return BORDER_SINGLE; + return BORDER_FLAT; + + + +} + static void parse_color(const char *str, float *rgba) { @@ -552,6 +564,10 @@ theme_builtin(struct theme *theme) theme->window[SSD_INACTIVE].title_bg.color_to[0] = FLT_MIN; theme->window[SSD_ACTIVE].title_bg.color_to_split_to[0] = FLT_MIN; theme->window[SSD_INACTIVE].title_bg.color_to_split_to[0] = FLT_MIN; + theme->window[SSD_ACTIVE].bevel_width = 0; + theme->window[SSD_ACTIVE].border_type = BORDER_FLAT; + theme->window[SSD_INACTIVE].bevel_width = 0; + theme->window[SSD_INACTIVE].border_type = BORDER_FLAT; parse_hexstr("#000000", theme->window[SSD_ACTIVE].label_text_color); parse_hexstr("#000000", theme->window[SSD_INACTIVE].label_text_color); @@ -722,9 +738,25 @@ entry(struct theme *theme, const char *key, const char *value) if (match_glob(key, "window.active.border.color")) { parse_color(value, theme->window[SSD_ACTIVE].border_color); } + + if (match_glob(key, "window.active.border.type")) { + theme->window[SSD_ACTIVE].border_type = parse_border_type(value); + } + if (match_glob(key, "window.active.border.bevel-width")) { + theme->window[SSD_ACTIVE].bevel_width = get_int_if_positive(value, "window.active.border.bevel-width"); + } + if (match_glob(key, "window.inactive.border.color")) { parse_color(value, theme->window[SSD_INACTIVE].border_color); } + + if (match_glob(key, "window.inactive.border.bevel-width")) { + theme->window[SSD_INACTIVE].bevel_width = get_int_if_positive(value, "window.inactive.border.bevel-width"); + } + + if (match_glob(key, "window.inactive.border.type")) { + theme->window[SSD_INACTIVE].border_type = parse_border_type(value); + } /* border.color is obsolete, but handled for backward compatibility */ if (match_glob(key, "border.color")) { parse_color(value, theme->window[SSD_ACTIVE].border_color); From 362c3e1b476bf90965a5dc87aac83f22c5e7cec8 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Wed, 1 Apr 2026 20:40:21 -0700 Subject: [PATCH 29/47] Add osd.border.type and osd.border.bevel-width options --- include/common/lab-scene-rect.h | 4 +++- include/theme.h | 2 ++ src/common/lab-scene-rect.c | 5 +++-- src/cycle/cycle.c | 3 ++- src/cycle/osd-classic.c | 6 ++++-- src/cycle/osd-scroll.c | 8 +++++++- src/cycle/osd-thumbnail.c | 6 ++++-- src/menu/menu.c | 2 +- src/theme.c | 9 +++++++++ 9 files changed, 35 insertions(+), 10 deletions(-) diff --git a/include/common/lab-scene-rect.h b/include/common/lab-scene-rect.h index ebf243c7..9bab96b2 100644 --- a/include/common/lab-scene-rect.h +++ b/include/common/lab-scene-rect.h @@ -2,6 +2,7 @@ #ifndef LABWC_LAB_SCENE_RECT_H #define LABWC_LAB_SCENE_RECT_H #include +#include "common/borderset.h" struct wlr_scene_tree; @@ -12,7 +13,8 @@ struct lab_scene_rect_options { float *bg_color; /* can be NULL */ int width; int height; - bool beveled; + enum border_type border_type; + int bevel_width; }; struct lab_scene_rect { diff --git a/include/theme.h b/include/theme.h index 1ab6e323..df487aa5 100644 --- a/include/theme.h +++ b/include/theme.h @@ -169,6 +169,8 @@ struct theme { float osd_bg_color[4]; float osd_border_color[4]; float osd_label_text_color[4]; + enum border_type osd_border_type; + int osd_border_bevel_width; struct window_switcher_classic_theme { int width; diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c index 4b45eeec..a5107e42 100644 --- a/src/common/lab-scene-rect.c +++ b/src/common/lab-scene-rect.c @@ -6,6 +6,7 @@ #include "common/scene-helpers.h" #include "common/macros.h" #include "common/borderset.h" +#include "theme.h" #include "buffer.h" #include @@ -48,14 +49,14 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0, color); border->left = lab_wlr_scene_rect_create(border->tree, 0, 0, color); - if (opts->beveled) { + if (opts->border_type) { float r = color[0]; float g = color[1]; float b = color[2]; float a = color[3]; int bw = rect->border_width; uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, BORDER_SINGLE, 0); + struct borderset * renderedborders = getBorders(colour32, bw, opts->border_type, opts->bevel_width); border->texturedBorders = generateBufferset(border->tree, renderedborders, bw); } else { border->texturedBorders = NULL; diff --git a/src/cycle/cycle.c b/src/cycle/cycle.c index 28978792..0c3643f9 100644 --- a/src/cycle/cycle.c +++ b/src/cycle/cycle.c @@ -37,7 +37,8 @@ update_preview_outlines(struct view *view) }, .nr_borders = 3, .border_width = theme->osd_window_switcher_preview_border_width, - .beveled = true, + .border_type = theme->osd_border_type, + .bevel_width = theme->osd_border_bevel_width }; rect = lab_scene_rect_create(&server.scene->tree, &opts); wlr_scene_node_place_above(&rect->tree->node, diff --git a/src/cycle/osd-classic.c b/src/cycle/osd-classic.c index 074de8f8..28590de7 100644 --- a/src/cycle/osd-classic.c +++ b/src/cycle/osd-classic.c @@ -120,7 +120,8 @@ cycle_osd_classic_init(struct cycle_osd_output *osd_output) .bg_color = bg_color, .width = w, .height = h, - .beveled = true, + .border_type = theme->osd_border_type, + .bevel_width = theme->osd_border_bevel_width }; lab_scene_rect_create(osd_output->tree, &bg_opts); @@ -203,7 +204,8 @@ cycle_osd_classic_init(struct cycle_osd_output *osd_output) .bg_color = active_bg_color, .width = w - 2 * padding, .height = switcher_theme->item_height, - .beveled = 1, + .border_type = theme->osd_border_type, + .bevel_width = theme->osd_border_bevel_width }; struct lab_scene_rect *highlight_rect = lab_scene_rect_create( item->active_tree, &highlight_opts); diff --git a/src/cycle/osd-scroll.c b/src/cycle/osd-scroll.c index b8b579a2..e51428be 100644 --- a/src/cycle/osd-scroll.c +++ b/src/cycle/osd-scroll.c @@ -3,7 +3,9 @@ #include #include "common/lab-scene-rect.h" #include "common/scene-helpers.h" +#include "config/rcxml.h" #include "labwc.h" +#include "theme.h" #include "cycle.h" #include "output.h" @@ -12,6 +14,9 @@ cycle_osd_scroll_init(struct cycle_osd_output *osd_output, struct wlr_box bar_ar int delta_y, int nr_cols, int nr_rows, int nr_visible_rows, float *border_color, float *bg_color) { + + struct theme *theme = rc.theme; + if (nr_visible_rows >= nr_rows) { /* OSD doesn't have so many windows to scroll through */ return; @@ -35,7 +40,8 @@ cycle_osd_scroll_init(struct cycle_osd_output *osd_output, struct wlr_box bar_ar .bg_color = bg_color, .width = bar_area.width, .height = bar_area.height * nr_visible_rows / nr_rows, - .beveled = true, + .border_type = theme->osd_border_type, + .bevel_width = theme->osd_border_bevel_width }; scroll->bar = lab_scene_rect_create(scroll->bar_tree, &scrollbar_opts); } diff --git a/src/cycle/osd-thumbnail.c b/src/cycle/osd-thumbnail.c index 1e7ca8e2..8dfd530f 100644 --- a/src/cycle/osd-thumbnail.c +++ b/src/cycle/osd-thumbnail.c @@ -150,7 +150,8 @@ create_item_scene(struct wlr_scene_tree *parent, struct view *view, .bg_color = switcher_theme->item_active_bg_color, .width = switcher_theme->item_width, .height = switcher_theme->item_height, - .beveled = true, + .border_type = theme->osd_border_type, + .bevel_width = theme->osd_border_bevel_width }; item->active_bg = lab_scene_rect_create(tree, &opts); @@ -283,7 +284,8 @@ cycle_osd_thumbnail_init(struct cycle_osd_output *osd_output) .bg_color = theme->osd_bg_color, .width = items_width + 2 * padding, .height = items_height + 2 * padding, - .beveled = true, + .border_type = theme->osd_border_type, + .bevel_width = theme->osd_border_bevel_width }; struct lab_scene_rect *bg = lab_scene_rect_create(osd_output->tree, &bg_opts); diff --git a/src/menu/menu.c b/src/menu/menu.c index 056294a0..d94f69d4 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -504,7 +504,7 @@ menu_create_scene(struct menu *menu) .border_width = theme->menu_border_width, .width = menu->size.width, .height = menu->size.height, - .beveled = true, + //.beveled = true, }; struct lab_scene_rect *bg_rect = lab_scene_rect_create(menu->scene_tree, &opts); diff --git a/src/theme.c b/src/theme.c index 9e517a2d..857cfed8 100644 --- a/src/theme.c +++ b/src/theme.c @@ -651,6 +651,8 @@ theme_builtin(struct theme *theme) theme->osd_border_width = INT_MIN; theme->osd_border_color[0] = FLT_MIN; theme->osd_label_text_color[0] = FLT_MIN; + theme->osd_border_type = BORDER_FLAT; + theme->osd_border_bevel_width = 0; if (wlr_renderer_is_pixman(server.renderer)) { /* Draw only outlined overlay by default to save CPU resource */ @@ -1003,6 +1005,13 @@ entry(struct theme *theme, const char *key, const char *value) if (match_glob(key, "osd.border.color")) { parse_color(value, theme->osd_border_color); } + + if (match_glob(key, "osd.border.type")) { + theme->osd_border_type = parse_border_type(value); + } + if (match_glob(key, "osd.border.bevel-width")) { + theme->osd_border_bevel_width = get_int_if_positive(value, "osd.border.bevel-width"); + } /* classic window switcher */ if (match_glob(key, "osd.window-switcher.style-classic.width") || match_glob(key, "osd.window-switcher.width")) { From e7b53c5d2873d92028ded10efaede6d8896596ee Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Wed, 1 Apr 2026 21:31:21 -0700 Subject: [PATCH 30/47] Pull menu bevels from theme --- include/theme.h | 10 ++++++-- src/common/borderset.c | 5 ++++ src/menu/menu.c | 29 +++++++++++++++------- src/ssd/resize-indicator.c | 6 ++--- src/theme.c | 49 +++++++++++++++++++++++++++++++------- src/workspaces.c | 4 ++-- 6 files changed, 78 insertions(+), 25 deletions(-) diff --git a/include/theme.h b/include/theme.h index df487aa5..6bf0473e 100644 --- a/include/theme.h +++ b/include/theme.h @@ -61,8 +61,6 @@ struct theme_background { struct theme { int border_width; - bool beveled_border; - int border_bevel_width; /* * the space between title bar border and @@ -147,6 +145,8 @@ struct theme { int menu_max_width; int menu_border_width; float menu_border_color[4]; + enum border_type menu_border_type; + int menu_bevel_width; int menu_items_padding_x; int menu_items_padding_y; @@ -154,6 +154,12 @@ struct theme { float menu_items_text_color[4]; float menu_items_active_bg_color[4]; float menu_items_active_text_color[4]; + enum border_type menu_items_border_type; + int menu_items_bevel_width; + enum border_type menu_title_border_type; + int menu_title_bevel_width; + enum border_type menu_items_active_border_type; + int menu_items_active_bevel_width; int menu_separator_line_thickness; int menu_separator_padding_width; diff --git a/src/common/borderset.c b/src/common/borderset.c index 083d451a..214d6ab1 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -16,6 +16,11 @@ struct borderset * getBorders(uint32_t id, int size, enum border_type type, int type = BORDER_SINGLE; } + if (type == BORDER_DOUBLE_INSET && (bevelSize > size/2)) { + type = BORDER_INSET; + } + + // Anything with a size of 0 is converted to a 1-pixel flat border so as to prevent empty allocations if (size < 1) { diff --git a/src/menu/menu.c b/src/menu/menu.c index d94f69d4..5bb2af14 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -169,7 +169,7 @@ item_create_scene_for_state(struct menuitem *item, float *text_color, { struct menu *menu = item->parent; struct theme *theme = rc.theme; - struct bufferset * bufferset; + struct bufferset * bufferset = NULL; /* Tree to hold background and label buffers */ struct wlr_scene_tree *tree = lab_wlr_scene_tree_create(item->tree); @@ -195,7 +195,7 @@ item_create_scene_for_state(struct menuitem *item, float *text_color, lab_wlr_scene_rect_create(tree, bg_width, theme->menu_item_height, bg_color); int bw = theme->menu_border_width; - if (rc.theme->beveled_border && state) { + if (rc.theme->menu_items_active_border_type && state) { float r = bg_color[0]; float g = bg_color[1]; float b = bg_color[2]; @@ -203,9 +203,19 @@ item_create_scene_for_state(struct menuitem *item, float *text_color, uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, BORDER_INSET, 0); + struct borderset * renderedborders = getBorders(colour32, bw, rc.theme->menu_items_active_border_type, rc.theme->menu_items_active_bevel_width); bufferset = generateBufferset(tree, renderedborders, bw); - } + } else if (rc.theme->menu_items_border_type && !state) { + float r = bg_color[0]; + float g = bg_color[1]; + float b = bg_color[2]; + float a = bg_color[3]; + + + uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); + struct borderset * renderedborders = getBorders(colour32, bw, rc.theme->menu_items_border_type, rc.theme->menu_items_bevel_width); + bufferset = generateBufferset(tree, renderedborders, bw); + } @@ -240,7 +250,7 @@ item_create_scene_for_state(struct menuitem *item, float *text_color, wlr_scene_node_set_position(&label_buffer->scene_buffer->node, x, y); - if (rc.theme->beveled_border && state) { + if (bufferset != NULL) { renderBufferset(bufferset, bg_width, theme->menu_item_height, 0); } @@ -387,7 +397,7 @@ title_create_scene(struct menuitem *menuitem, int *item_y) int bw = theme->menu_border_width; - if (rc.theme->beveled_border) { + if (rc.theme->menu_title_border_type) { float r = bg_color[0]; float g = bg_color[1]; float b = bg_color[2]; @@ -395,7 +405,7 @@ title_create_scene(struct menuitem *menuitem, int *item_y) uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, BORDER_SINGLE, 0); + struct borderset * renderedborders = getBorders(colour32, bw, rc.theme->menu_title_border_type, rc.theme->menu_title_bevel_width); bufferset = generateBufferset(menuitem->tree, renderedborders, bw); } @@ -429,7 +439,7 @@ title_create_scene(struct menuitem *menuitem, int *item_y) wlr_scene_node_set_position(&title_font_buffer->scene_buffer->node, title_x, title_y); - if (rc.theme->beveled_border) { + if (rc.theme->menu_title_border_type) { renderBufferset(bufferset, bg_width, theme->menu_item_height, 0); } error: @@ -504,7 +514,8 @@ menu_create_scene(struct menu *menu) .border_width = theme->menu_border_width, .width = menu->size.width, .height = menu->size.height, - //.beveled = true, + .border_type = theme->menu_border_type, + .bevel_width = theme->menu_bevel_width }; struct lab_scene_rect *bg_rect = lab_scene_rect_create(menu->scene_tree, &opts); diff --git a/src/ssd/resize-indicator.c b/src/ssd/resize-indicator.c index c4af32d3..f5ac6877 100644 --- a/src/ssd/resize-indicator.c +++ b/src/ssd/resize-indicator.c @@ -53,7 +53,7 @@ resize_indicator_init(struct view *view) indicator->background = lab_wlr_scene_rect_create( indicator->tree, 0, 0, rc.theme->osd_bg_color); - if (rc.theme->beveled_border) { + if (rc.theme->osd_border_type) { float r = rc.theme->osd_border_color[0]; float g = rc.theme->osd_border_color[1]; float b = rc.theme->osd_border_color[2]; @@ -61,7 +61,7 @@ resize_indicator_init(struct view *view) int bw = rc.theme->osd_border_width; uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, BORDER_SINGLE, 0); + struct borderset * renderedborders = getBorders(colour32, bw, rc.theme->osd_border_type, rc.theme->osd_border_bevel_width); indicator->texturedBorders = generateBufferset(indicator->tree, renderedborders, bw); } @@ -135,7 +135,7 @@ resize_indicator_set_size(struct resize_indicator *indicator, int width) indicator->width - 2 * rc.theme->osd_border_width, indicator->height - 2 * rc.theme->osd_border_width); - if (rc.theme->beveled_border) { + if (rc.theme->osd_border_type) { renderBufferset(indicator->texturedBorders, indicator->width, indicator->height, 0); } } diff --git a/src/theme.c b/src/theme.c index 857cfed8..7a2362f5 100644 --- a/src/theme.c +++ b/src/theme.c @@ -544,8 +544,6 @@ static void theme_builtin(struct theme *theme) { theme->border_width = 1; - theme->beveled_border = false; - theme->border_bevel_width=0; theme->window_titlebar_padding_height = 0; theme->window_titlebar_padding_width = 0; @@ -599,6 +597,8 @@ theme_builtin(struct theme *theme) theme->menu_max_width = 200; theme->menu_border_width = INT_MIN; theme->menu_border_color[0] = FLT_MIN; + theme->menu_border_type = BORDER_FLAT; + theme->menu_bevel_width = 0; theme->menu_items_padding_x = 7; theme->menu_items_padding_y = 4; @@ -606,6 +606,12 @@ theme_builtin(struct theme *theme) parse_hexstr("#000000", theme->menu_items_text_color); parse_hexstr("#e1dedb", theme->menu_items_active_bg_color); parse_hexstr("#000000", theme->menu_items_active_text_color); + theme->menu_items_border_type = BORDER_FLAT; + theme->menu_items_bevel_width = 0; + theme->menu_title_border_type = BORDER_FLAT; + theme->menu_title_bevel_width = 0; + theme->menu_items_active_border_type = BORDER_FLAT; + theme->menu_items_active_bevel_width = 0; theme->menu_separator_line_thickness = 1; theme->menu_separator_padding_width = 6; @@ -715,13 +721,7 @@ entry(struct theme *theme, const char *key, const char *value) theme->border_width = get_int_if_positive( value, "border.width"); } - if (match_glob(key, "border.beveled")) { - set_bool(value, &theme->beveled_border); - } - if (match_glob(key, "border.bevel_width")) { - theme->border_bevel_width = get_int_if_positive( - value, "border.bevel_width"); - } + if (match_glob(key, "window.titlebar.padding.width")) { theme->window_titlebar_padding_width = get_int_if_positive( value, "window.titlebar.padding.width"); @@ -948,6 +948,14 @@ entry(struct theme *theme, const char *key, const char *value) parse_color(value, theme->menu_border_color); } + if (match_glob(key, "menu.bg")) { + theme->menu_border_type = parse_border_type(value); + } + if (match_glob(key, "menu.bg.bevel-width")) { + theme->menu_bevel_width = get_int_if_positive(value, "menu.bg.bevel-width"); + } + + if (match_glob(key, "menu.items.padding.x")) { theme->menu_items_padding_x = get_int_if_positive( value, "menu.items.padding.x"); @@ -959,6 +967,13 @@ entry(struct theme *theme, const char *key, const char *value) if (match_glob(key, "menu.items.bg.color")) { parse_color(value, theme->menu_items_bg_color); } + if (match_glob(key, "menu.items.bg")) { + theme->menu_items_border_type = parse_border_type(value); + } + if (match_glob(key, "menu.items.bg.bevel-width")) { + theme->menu_items_bevel_width = get_int_if_positive(value, "menu.items.bg.bevel-width"); + } + if (match_glob(key, "menu.items.text.color")) { parse_color(value, theme->menu_items_text_color); } @@ -968,6 +983,14 @@ entry(struct theme *theme, const char *key, const char *value) if (match_glob(key, "menu.items.active.text.color")) { parse_color(value, theme->menu_items_active_text_color); } + + if (match_glob(key, "menu.items.active.bg")) { + theme->menu_items_active_border_type = parse_border_type(value); + } + if (match_glob(key, "menu.items.active.bg.bevel-width")) { + theme->menu_items_active_bevel_width = get_int_if_positive(value, "menu.items.active.bg.bevel-width"); + } + if (match_glob(key, "menu.separator.width")) { theme->menu_separator_line_thickness = get_int_if_positive( @@ -994,6 +1017,14 @@ entry(struct theme *theme, const char *key, const char *value) if (match_glob(key, "menu.title.text.color")) { parse_color(value, theme->menu_title_text_color); } + + if (match_glob(key, "menu.title.bg")) { + theme->menu_title_border_type = parse_border_type(value); + } + if (match_glob(key, "menu.title.bg.bevel-width")) { + theme->menu_title_bevel_width = get_int_if_positive(value, "menu.title.bg.bevel-width"); + } + if (match_glob(key, "osd.bg.color")) { parse_color(value, theme->osd_bg_color); diff --git a/src/workspaces.c b/src/workspaces.c index 0edd1b36..207d8e4c 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -104,14 +104,14 @@ _osd_update(void) cairo_fill(cairo); /* Border */ - if (theme->beveled_border) { + if (theme->osd_border_type) { float r = theme->osd_border_color[0]; float g = theme->osd_border_color[1]; float b = theme->osd_border_color[2]; float a = theme->osd_border_color[3]; uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, BORDER_SINGLE, 0); + struct borderset * renderedborders = getBorders(colour32, bw, theme->osd_border_type, theme->osd_border_bevel_width); cairo_set_source_surface(cairo, renderedborders->top->surface, 0, 0); cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); From 96ae2f2d9d7775f56733f98404e4cc1efb0e19a7 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Wed, 1 Apr 2026 21:36:44 -0700 Subject: [PATCH 31/47] Remove debug code --- src/common/lab-scene-rect.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c index a5107e42..71fe287d 100644 --- a/src/common/lab-scene-rect.c +++ b/src/common/lab-scene-rect.c @@ -8,7 +8,6 @@ #include "common/borderset.h" #include "theme.h" #include "buffer.h" -#include struct border_scene { struct wlr_scene_tree *tree; From f361a3bec9e78f6219a8ed5a3414c2109615ccdf Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Wed, 1 Apr 2026 22:31:52 -0700 Subject: [PATCH 32/47] Force discard of the resize popup after theme reload so we don't end up with residual old styles --- src/ssd/resize-indicator.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/ssd/resize-indicator.c b/src/ssd/resize-indicator.c index f5ac6877..f6d9e846 100644 --- a/src/ssd/resize-indicator.c +++ b/src/ssd/resize-indicator.c @@ -38,6 +38,20 @@ resize_indicator_reconfigure_view(struct resize_indicator *indicator) /* Colors */ wlr_scene_rect_set_color(indicator->border, theme->osd_border_color); wlr_scene_rect_set_color(indicator->background, theme->osd_bg_color); + + + if (rc.theme->osd_border_type) { + float r = theme->osd_border_color[0]; + float g = theme->osd_border_color[1]; + float b = theme->osd_border_color[2]; + float a = theme->osd_border_color[3]; + int bw = theme->osd_border_width; + + uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); + struct borderset * renderedborders = getBorders(colour32, bw, theme->osd_border_type, theme->osd_border_bevel_width); + indicator->texturedBorders = generateBufferset(indicator->tree, renderedborders, bw); + } + } static void @@ -53,18 +67,6 @@ resize_indicator_init(struct view *view) indicator->background = lab_wlr_scene_rect_create( indicator->tree, 0, 0, rc.theme->osd_bg_color); - if (rc.theme->osd_border_type) { - float r = rc.theme->osd_border_color[0]; - float g = rc.theme->osd_border_color[1]; - float b = rc.theme->osd_border_color[2]; - float a = rc.theme->osd_border_color[3]; - int bw = rc.theme->osd_border_width; - - uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, rc.theme->osd_border_type, rc.theme->osd_border_bevel_width); - indicator->texturedBorders = generateBufferset(indicator->tree, renderedborders, bw); - } - indicator->text = scaled_font_buffer_create(indicator->tree); @@ -97,7 +99,9 @@ resize_indicator_reconfigure(void) wl_list_for_each(view, &server.views, link) { struct resize_indicator *indicator = &view->resize_indicator; if (indicator->tree) { - resize_indicator_reconfigure_view(indicator); + // Destroy the old tree so it doesn't have the leftover styling/sizing. + wlr_scene_node_destroy(&indicator->tree->node); + indicator->tree = NULL; } if (view != server.grabbed_view) { continue; From 1c792134706feab3cf701b4418582bf5ab701459 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Wed, 1 Apr 2026 22:36:44 -0700 Subject: [PATCH 33/47] Use osd.bg for OSD border texture --- src/theme.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/theme.c b/src/theme.c index 7a2362f5..1a2781e2 100644 --- a/src/theme.c +++ b/src/theme.c @@ -1037,11 +1037,11 @@ entry(struct theme *theme, const char *key, const char *value) parse_color(value, theme->osd_border_color); } - if (match_glob(key, "osd.border.type")) { + if (match_glob(key, "osd.bg")) { theme->osd_border_type = parse_border_type(value); } - if (match_glob(key, "osd.border.bevel-width")) { - theme->osd_border_bevel_width = get_int_if_positive(value, "osd.border.bevel-width"); + if (match_glob(key, "osd.bg.bevel-width")) { + theme->osd_border_bevel_width = get_int_if_positive(value, "osd.bg.bevel-width"); } /* classic window switcher */ if (match_glob(key, "osd.window-switcher.style-classic.width") From 59c37bc91bbab3f7a6125ec03523a48f57242135 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Fri, 3 Apr 2026 23:17:28 -0700 Subject: [PATCH 34/47] Start on texture on the main title bar segment --- include/common/borderset.h | 2 ++ include/ssd-internal.h | 1 + include/theme.h | 5 +++++ src/common/borderset.c | 21 +++++++++++-------- src/ssd/ssd-titlebar.c | 33 ++++++++++++++++++++++++++++++ src/theme.c | 42 ++++++++++++++++++++++++++++++++++---- 6 files changed, 92 insertions(+), 12 deletions(-) diff --git a/include/common/borderset.h b/include/common/borderset.h index d3bd8860..445a261a 100644 --- a/include/common/borderset.h +++ b/include/common/borderset.h @@ -48,6 +48,8 @@ struct bufferset * generateBufferset(struct wlr_scene_tree * tree, struct border void renderBufferset(struct bufferset *, int width, int height, int y); +void renderBuffersetXY(struct bufferset *, int width, int height, int x, int y); + void clearBorderCache(struct borderset *borderset); #endif /* LABWC_LAB_SCENE_RECT_H */ diff --git a/include/ssd-internal.h b/include/ssd-internal.h index 1d2ff1da..5b888468 100644 --- a/include/ssd-internal.h +++ b/include/ssd-internal.h @@ -106,6 +106,7 @@ struct ssd { struct scaled_font_buffer *title; struct wl_list buttons_left; /* ssd_button.link */ struct wl_list buttons_right; /* ssd_button.link */ + struct bufferset * texturedBorders; } subtrees[2]; /* indexed by enum ssd_active_state */ } titlebar; diff --git a/include/theme.h b/include/theme.h index 6bf0473e..2612b46f 100644 --- a/include/theme.h +++ b/include/theme.h @@ -57,6 +57,11 @@ struct theme_background { float color_split_to[4]; float color_to[4]; float color_to_split_to[4]; + enum border_type border_type; + int border_width; + int bevel_width; + bool exclusive; + }; struct theme { diff --git a/src/common/borderset.c b/src/common/borderset.c index 214d6ab1..3ceccb1d 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -307,50 +307,55 @@ struct bufferset * generateBufferset(struct wlr_scene_tree * tree, struct border } void renderBufferset(struct bufferset *bufferset, int width, int height, int y) +{ + renderBuffersetXY(bufferset, width, height, 0, y); +} + +void renderBuffersetXY(struct bufferset *bufferset, int width, int height, int x, int y) { wlr_scene_buffer_set_dest_size(bufferset->top, width - 2 * bufferset->border_width, bufferset->border_width); wlr_scene_node_set_position(&bufferset->top->node, - bufferset->border_width,y); + x+bufferset->border_width,y); wlr_scene_buffer_set_dest_size(bufferset->bottom, width - 2 * bufferset->border_width, bufferset->border_width); wlr_scene_node_set_position(&bufferset->bottom->node, - bufferset->border_width, y+height - bufferset->border_width); + x+bufferset->border_width, y+height - bufferset->border_width); wlr_scene_buffer_set_dest_size(bufferset->left, bufferset->border_width, height - bufferset->border_width * 2); wlr_scene_node_set_position(&bufferset->left->node, - 0, bufferset->border_width+y); + x, bufferset->border_width+y); wlr_scene_buffer_set_dest_size(bufferset->right, bufferset->border_width, height - bufferset->border_width * 2); wlr_scene_node_set_position(&bufferset->right->node, - width - bufferset->border_width, y+ bufferset->border_width); + x+width - bufferset->border_width, y+ bufferset->border_width); wlr_scene_buffer_set_dest_size(bufferset->tl, bufferset->border_width, bufferset->border_width); wlr_scene_node_set_position(&bufferset->tl->node, - 0,y); + x,y); wlr_scene_buffer_set_dest_size(bufferset->tr, bufferset->border_width, bufferset->border_width); wlr_scene_node_set_position(&bufferset->tr->node, - width-bufferset->border_width, y); + x+width-bufferset->border_width, y); wlr_scene_buffer_set_dest_size(bufferset->br, bufferset->border_width, bufferset->border_width); wlr_scene_node_set_position(&bufferset->br->node, - width-bufferset->border_width , y+height-bufferset->border_width); + x+width-bufferset->border_width , y+height-bufferset->border_width); wlr_scene_buffer_set_dest_size(bufferset->bl, bufferset->border_width, bufferset->border_width); wlr_scene_node_set_position(&bufferset->bl->node, - 0, height-bufferset->border_width+y); + x, height-bufferset->border_width+y); } diff --git a/src/ssd/ssd-titlebar.c b/src/ssd/ssd-titlebar.c index d1a08810..79de5f1d 100644 --- a/src/ssd/ssd-titlebar.c +++ b/src/ssd/ssd-titlebar.c @@ -18,6 +18,7 @@ #include "ssd-internal.h" #include "theme.h" #include "view.h" +#include "common/borderset.h" static void set_squared_corners(struct ssd *ssd, bool enable); static void set_alt_button_icon(struct ssd *ssd, enum lab_node_type type, bool enable); @@ -52,6 +53,19 @@ ssd_titlebar_create(struct ssd *ssd) /* Background */ subtree->bar = lab_wlr_scene_buffer_create(parent, titlebar_fill); + + if (theme->window[active].title_bg.border_type) { + /* Beveled Titlebar */ + float *color = theme->window[active].title_bg.color; + float r = color[0]; + float g = color[1]; + float b = color[2]; + float a = color[3]; + + uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); + struct borderset * renderedborders = getBorders(colour32, theme->window[active].title_bg.border_width, theme->window[active].title_bg.border_type, theme->window[active].title_bg.bevel_width); + subtree->texturedBorders = generateBufferset(subtree->tree, renderedborders, theme->window[active].title_bg.border_width); + } /* * Work around the wlroots/pixman bug that widened 1px buffer * becomes translucent when bilinear filtering is used. @@ -318,10 +332,16 @@ ssd_titlebar_update(struct ssd *ssd) x = theme->window_titlebar_padding_width; struct ssd_button *button; + int button_count = 0; + + wl_list_for_each(button, &subtree->buttons_left, link) { wlr_scene_node_set_position(button->node, x, y); x += theme->window_button_width + theme->window_button_spacing; + button_count++; } + int exclusive_x = x; + x = width - corner_width; wlr_scene_node_set_position(&subtree->corner_right->node, @@ -331,7 +351,20 @@ ssd_titlebar_update(struct ssd *ssd) wl_list_for_each(button, &subtree->buttons_right, link) { x -= theme->window_button_width + theme->window_button_spacing; wlr_scene_node_set_position(button->node, x, y); + button_count++; } + + + if (theme->window[active].title_bg.border_type) { + int titlebar_x = 0; + int titlebar_width = MAX(width, 0); + if (theme->window[active].title_bg.exclusive) { + titlebar_x = exclusive_x+theme->window_titlebar_padding_width; + titlebar_width = MAX((theme->window_button_width + theme->window_button_spacing)* button_count, titlebar_width - (theme->window_button_width + theme->window_button_spacing)* button_count); + } + renderBuffersetXY(subtree->texturedBorders, titlebar_width, theme->titlebar_height, titlebar_x, 0); + } + } ssd_update_title(ssd); diff --git a/src/theme.c b/src/theme.c index 1a2781e2..f4dc8430 100644 --- a/src/theme.c +++ b/src/theme.c @@ -457,9 +457,6 @@ static enum border_type parse_border_type(const char *str) { if (strstr(lower, "doubleraised")) return BORDER_DOUBLE; if (strstr(lower, "raised")) return BORDER_SINGLE; return BORDER_FLAT; - - - } static void @@ -564,8 +561,16 @@ theme_builtin(struct theme *theme) theme->window[SSD_INACTIVE].title_bg.color_to_split_to[0] = FLT_MIN; theme->window[SSD_ACTIVE].bevel_width = 0; theme->window[SSD_ACTIVE].border_type = BORDER_FLAT; + theme->window[SSD_ACTIVE].title_bg.bevel_width = 0; + theme->window[SSD_ACTIVE].title_bg.border_width = 0; + theme->window[SSD_ACTIVE].title_bg.exclusive = FALSE; + theme->window[SSD_ACTIVE].title_bg.border_type = BORDER_FLAT; theme->window[SSD_INACTIVE].bevel_width = 0; theme->window[SSD_INACTIVE].border_type = BORDER_FLAT; + theme->window[SSD_INACTIVE].title_bg.bevel_width = 0; + theme->window[SSD_INACTIVE].title_bg.border_width = 0; + theme->window[SSD_INACTIVE].title_bg.exclusive = FALSE; + theme->window[SSD_INACTIVE].title_bg.border_type = BORDER_FLAT; parse_hexstr("#000000", theme->window[SSD_ACTIVE].label_text_color); parse_hexstr("#000000", theme->window[SSD_INACTIVE].label_text_color); @@ -736,7 +741,20 @@ entry(struct theme *theme, const char *key, const char *value) if (match_glob(key, "padding.height")) { wlr_log(WLR_INFO, "padding.height is no longer supported"); } - + + if (match_glob(key, "window.active.title.bg") && parse_border_type(value)) { + theme->window[SSD_ACTIVE].title_bg.border_type= parse_border_type(value); + } + if (match_glob(key, "window.active.title.bg.width")) { + theme->window[SSD_ACTIVE].title_bg.border_width = get_int_if_positive(value, "window.active.title.bg.width"); + } + + if (match_glob(key, "window.active.title.bg.exclusive")) { + set_bool(value, &theme->window[SSD_ACTIVE].title_bg.exclusive); + } + if (match_glob(key, "window.active.title.bg.bevel-width")) { + theme->window[SSD_ACTIVE].title_bg.bevel_width = get_int_if_positive(value, "window.active.title.bg.bevel-width"); + } if (match_glob(key, "window.active.border.color")) { parse_color(value, theme->window[SSD_ACTIVE].border_color); } @@ -772,6 +790,22 @@ entry(struct theme *theme, const char *key, const char *value) if (match_glob(key, "window.active.title.bg")) { theme->window[SSD_ACTIVE].title_bg.gradient = parse_gradient(value); } + + + if (match_glob(key, "window.inactive.title.bg") && parse_border_type(value)) { + theme->window[SSD_INACTIVE].title_bg.border_type= parse_border_type(value); + } + if (match_glob(key, "window.inactive.title.bg.width")) { + theme->window[SSD_INACTIVE].title_bg.border_width = get_int_if_positive(value, "window.inactive.title.bg.width"); + } + if (match_glob(key, "window.inactive.title.bg.bevel-width")) { + theme->window[SSD_INACTIVE].title_bg.bevel_width = get_int_if_positive(value, "window.inactive.title.bg.bevel-width"); + } + if (match_glob(key, "window.inactive.title.bg.exclusive")) { + set_bool(value, &theme->window[SSD_INACTIVE].title_bg.exclusive); + } + + if (match_glob(key, "window.inactive.title.bg")) { theme->window[SSD_INACTIVE].title_bg.gradient = parse_gradient(value); } From d1951f73ec7020c69bf9b38f7b10b552f0386322 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Fri, 3 Apr 2026 23:32:39 -0700 Subject: [PATCH 35/47] Don't clobber the border under the title --- src/ssd/ssd-titlebar.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/ssd/ssd-titlebar.c b/src/ssd/ssd-titlebar.c index 79de5f1d..c76df8e0 100644 --- a/src/ssd/ssd-titlebar.c +++ b/src/ssd/ssd-titlebar.c @@ -87,9 +87,16 @@ ssd_titlebar_create(struct ssd *ssd) width - corner_width, -rc.theme->border_width); /* Title */ - subtree->title = scaled_font_buffer_create_for_titlebar( - subtree->tree, theme->titlebar_height, - theme->window[active].titlebar_pattern); + if (theme->window[active].title_bg.border_type) { + // Use a blank background pattern so it doesn't overlay a pattern on the order. + subtree->title = scaled_font_buffer_create_for_titlebar( + subtree->tree, theme->titlebar_height, + NULL); + } else { + subtree->title = scaled_font_buffer_create_for_titlebar( + subtree->tree, theme->titlebar_height, + theme->window[active].titlebar_pattern); + } assert(subtree->title); node_descriptor_create(&subtree->title->scene_buffer->node, LAB_NODE_TITLE, view, /*data*/ NULL); From 73cd8eb0bbd99ac6b8f5f11a70dbefddb7f53a27 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sat, 4 Apr 2026 00:00:20 -0700 Subject: [PATCH 36/47] Force a redraw so we know we'll get a refreshed border after reconfig --- src/common/borderset.c | 1 - src/ssd/ssd-titlebar.c | 10 +++++++++- src/ssd/ssd.c | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/common/borderset.c b/src/common/borderset.c index 3ceccb1d..63db7929 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -5,7 +5,6 @@ #include "common/macros.h" #include "buffer.h" - struct borderset * getBorders(uint32_t id, int size, enum border_type type, int bevelSize) { struct borderset * current = borderCache; struct borderset * last; diff --git a/src/ssd/ssd-titlebar.c b/src/ssd/ssd-titlebar.c index c76df8e0..31ea7191 100644 --- a/src/ssd/ssd-titlebar.c +++ b/src/ssd/ssd-titlebar.c @@ -37,6 +37,7 @@ ssd_titlebar_create(struct ssd *ssd) LAB_NODE_TITLEBAR, view, /*data*/ NULL); enum ssd_active_state active; + bool shouldForceUpdate = FALSE; FOR_EACH_ACTIVE_STATE(active) { struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active]; subtree->tree = lab_wlr_scene_tree_create(ssd->titlebar.tree); @@ -53,7 +54,6 @@ ssd_titlebar_create(struct ssd *ssd) /* Background */ subtree->bar = lab_wlr_scene_buffer_create(parent, titlebar_fill); - if (theme->window[active].title_bg.border_type) { /* Beveled Titlebar */ float *color = theme->window[active].title_bg.color; @@ -65,6 +65,10 @@ ssd_titlebar_create(struct ssd *ssd) uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); struct borderset * renderedborders = getBorders(colour32, theme->window[active].title_bg.border_width, theme->window[active].title_bg.border_type, theme->window[active].title_bg.bevel_width); subtree->texturedBorders = generateBufferset(subtree->tree, renderedborders, theme->window[active].title_bg.border_width); + + // If we have the beveled borders, we actually have to run ssd_titlebar_update() to make sure we render the updated + // borders. Otherwise they disappear on reconfigure + shouldForceUpdate = true; } /* * Work around the wlroots/pixman bug that widened 1px buffer @@ -152,6 +156,10 @@ ssd_titlebar_create(struct ssd *ssd) if (view->visible_on_all_workspaces) { set_alt_button_icon(ssd, LAB_NODE_BUTTON_OMNIPRESENT, true); } + + if (shouldForceUpdate) { + ssd_titlebar_update(ssd); + } } static void diff --git a/src/ssd/ssd.c b/src/ssd/ssd.c index e2ab6375..9f62d689 100644 --- a/src/ssd/ssd.c +++ b/src/ssd/ssd.c @@ -176,6 +176,7 @@ ssd_create(struct view *view, bool active) ssd_enable_keybind_inhibit_indicator(ssd, view->inhibits_keybinds); ssd->state.geometry = view->current; + ssd_titlebar_update(ssd); return ssd; } From dfc3239ced4790f740b728fc06064154bcc0e6bc Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sat, 4 Apr 2026 00:02:10 -0700 Subject: [PATCH 37/47] Remove duplicate re-rendering: --- src/ssd/ssd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ssd/ssd.c b/src/ssd/ssd.c index 9f62d689..e2ab6375 100644 --- a/src/ssd/ssd.c +++ b/src/ssd/ssd.c @@ -176,7 +176,6 @@ ssd_create(struct view *view, bool active) ssd_enable_keybind_inhibit_indicator(ssd, view->inhibits_keybinds); ssd->state.geometry = view->current; - ssd_titlebar_update(ssd); return ssd; } From 44a0da2e7ff1c94637b53faf0aa68cabf9fcfc98 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sat, 4 Apr 2026 00:36:13 -0700 Subject: [PATCH 38/47] Better handling of exclusive mode --- src/ssd/ssd-titlebar.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ssd/ssd-titlebar.c b/src/ssd/ssd-titlebar.c index 31ea7191..27faac33 100644 --- a/src/ssd/ssd-titlebar.c +++ b/src/ssd/ssd-titlebar.c @@ -309,7 +309,7 @@ ssd_titlebar_update(struct ssd *ssd) if (ssd->state.was_maximized != maximized || ssd->state.was_squared != squared) { - set_squared_corners(ssd, maximized || squared); + set_squared_corners(ssd, maximized || squared || theme->window[SSD_ACTIVE].title_bg.border_type || theme->window[SSD_INACTIVE].title_bg.border_type); if (ssd->state.was_maximized != maximized) { set_alt_button_icon(ssd, LAB_NODE_BUTTON_MAXIMIZE, maximized); } @@ -337,7 +337,7 @@ ssd_titlebar_update(struct ssd *ssd) /* Center buttons vertically within titlebar */ int y = (theme->titlebar_height - theme->window_button_height) / 2; int x; - int bg_offset = maximized || squared ? 0 : corner_width; + int bg_offset = (maximized || squared || theme->window[SSD_INACTIVE].title_bg.border_type || theme->window[SSD_ACTIVE].title_bg.border_type) ? 0 : corner_width; enum ssd_active_state active; FOR_EACH_ACTIVE_STATE(active) { @@ -372,11 +372,12 @@ ssd_titlebar_update(struct ssd *ssd) if (theme->window[active].title_bg.border_type) { int titlebar_x = 0; - int titlebar_width = MAX(width, 0); + int titlebar_width = MAX(view->current.width, 0); if (theme->window[active].title_bg.exclusive) { titlebar_x = exclusive_x+theme->window_titlebar_padding_width; titlebar_width = MAX((theme->window_button_width + theme->window_button_spacing)* button_count, titlebar_width - (theme->window_button_width + theme->window_button_spacing)* button_count); } + renderBuffersetXY(subtree->texturedBorders, titlebar_width, theme->titlebar_height, titlebar_x, 0); } From 40208c57f15ab07afef7ba12c6ee6c82cb178bc6 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sat, 4 Apr 2026 00:45:35 -0700 Subject: [PATCH 39/47] Free a wasted allocation in parser --- src/theme.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/theme.c b/src/theme.c index f4dc8430..bdad35ed 100644 --- a/src/theme.c +++ b/src/theme.c @@ -452,11 +452,15 @@ parse_hexstrs(const char *hexes, float colors[3][4]) static enum border_type parse_border_type(const char *str) { char *lower = g_ascii_strdown(str, -1); - if (strstr(lower, "doublesunken")) return BORDER_DOUBLE_INSET; - if (strstr(lower, "sunken")) return BORDER_INSET; - if (strstr(lower, "doubleraised")) return BORDER_DOUBLE; - if (strstr(lower, "raised")) return BORDER_SINGLE; - return BORDER_FLAT; + enum border_type border_type; + if (strstr(lower, "doublesunken")) border_type = BORDER_DOUBLE_INSET; + else if (strstr(lower, "sunken")) border_type = BORDER_INSET; + else if (strstr(lower, "doubleraised")) border_type = BORDER_DOUBLE; + else if (strstr(lower, "raised")) border_type = BORDER_SINGLE; + else border_type = BORDER_FLAT; + + g_free(lower); + return border_type; } static void From 4d0ec3677390ab33ab734a0e87c74fe09460cb35 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sat, 4 Apr 2026 00:54:28 -0700 Subject: [PATCH 40/47] Avoid corner-related gaps reappearing after reconfigure --- src/ssd/ssd-titlebar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ssd/ssd-titlebar.c b/src/ssd/ssd-titlebar.c index 27faac33..4c82c76b 100644 --- a/src/ssd/ssd-titlebar.c +++ b/src/ssd/ssd-titlebar.c @@ -147,7 +147,7 @@ ssd_titlebar_create(struct ssd *ssd) if (squared) { ssd->state.was_squared = true; } - set_squared_corners(ssd, maximized || squared); + set_squared_corners(ssd, maximized || squared || theme->window[SSD_ACTIVE].title_bg.border_type || theme->window[SSD_INACTIVE].title_bg.border_type); if (view->shaded) { set_alt_button_icon(ssd, LAB_NODE_BUTTON_SHADE, true); From 43d643c878f4cdcb09ae1b268aefe6cbf39dabac Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sat, 4 Apr 2026 07:38:27 -0700 Subject: [PATCH 41/47] Explicitly differentiate between 'no border' and 'flat border' since it's visible with gradients --- include/common/borderset.h | 2 +- src/common/borderset.c | 1 + src/theme.c | 21 +++++++++++---------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/include/common/borderset.h b/include/common/borderset.h index 445a261a..23fb6c75 100644 --- a/include/common/borderset.h +++ b/include/common/borderset.h @@ -5,7 +5,7 @@ #define LABWC_BORDERSET_H enum border_type { - BORDER_FLAT, BORDER_SINGLE, BORDER_DOUBLE, BORDER_INSET, BORDER_DOUBLE_INSET + BORDER_NONE, BORDER_SINGLE, BORDER_DOUBLE, BORDER_INSET, BORDER_DOUBLE_INSET, BORDER_FLAT }; struct borderset { diff --git a/src/common/borderset.c b/src/common/borderset.c index 63db7929..b8573687 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -238,6 +238,7 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i break; case BORDER_FLAT: // Placeholder that uses buffers but for a flat colour + case BORDER_NONE: // Provided as a fallback but should not be actually requested/rendered top = znew(uint32_t); left = znew(uint32_t); right = znew(uint32_t); diff --git a/src/theme.c b/src/theme.c index bdad35ed..0c15264e 100644 --- a/src/theme.c +++ b/src/theme.c @@ -457,7 +457,8 @@ static enum border_type parse_border_type(const char *str) { else if (strstr(lower, "sunken")) border_type = BORDER_INSET; else if (strstr(lower, "doubleraised")) border_type = BORDER_DOUBLE; else if (strstr(lower, "raised")) border_type = BORDER_SINGLE; - else border_type = BORDER_FLAT; + else if (strstr(lower, "flat")) border_type = BORDER_FLAT; + else border_type = BORDER_NONE; g_free(lower); return border_type; @@ -564,17 +565,17 @@ theme_builtin(struct theme *theme) theme->window[SSD_ACTIVE].title_bg.color_to_split_to[0] = FLT_MIN; theme->window[SSD_INACTIVE].title_bg.color_to_split_to[0] = FLT_MIN; theme->window[SSD_ACTIVE].bevel_width = 0; - theme->window[SSD_ACTIVE].border_type = BORDER_FLAT; + theme->window[SSD_ACTIVE].border_type = BORDER_NONE; theme->window[SSD_ACTIVE].title_bg.bevel_width = 0; theme->window[SSD_ACTIVE].title_bg.border_width = 0; theme->window[SSD_ACTIVE].title_bg.exclusive = FALSE; - theme->window[SSD_ACTIVE].title_bg.border_type = BORDER_FLAT; + theme->window[SSD_ACTIVE].title_bg.border_type = BORDER_NONE; theme->window[SSD_INACTIVE].bevel_width = 0; - theme->window[SSD_INACTIVE].border_type = BORDER_FLAT; + theme->window[SSD_INACTIVE].border_type = BORDER_NONE; theme->window[SSD_INACTIVE].title_bg.bevel_width = 0; theme->window[SSD_INACTIVE].title_bg.border_width = 0; theme->window[SSD_INACTIVE].title_bg.exclusive = FALSE; - theme->window[SSD_INACTIVE].title_bg.border_type = BORDER_FLAT; + theme->window[SSD_INACTIVE].title_bg.border_type = BORDER_NONE; parse_hexstr("#000000", theme->window[SSD_ACTIVE].label_text_color); parse_hexstr("#000000", theme->window[SSD_INACTIVE].label_text_color); @@ -606,7 +607,7 @@ theme_builtin(struct theme *theme) theme->menu_max_width = 200; theme->menu_border_width = INT_MIN; theme->menu_border_color[0] = FLT_MIN; - theme->menu_border_type = BORDER_FLAT; + theme->menu_border_type = BORDER_NONE; theme->menu_bevel_width = 0; theme->menu_items_padding_x = 7; @@ -615,11 +616,11 @@ theme_builtin(struct theme *theme) parse_hexstr("#000000", theme->menu_items_text_color); parse_hexstr("#e1dedb", theme->menu_items_active_bg_color); parse_hexstr("#000000", theme->menu_items_active_text_color); - theme->menu_items_border_type = BORDER_FLAT; + theme->menu_items_border_type = BORDER_NONE; theme->menu_items_bevel_width = 0; - theme->menu_title_border_type = BORDER_FLAT; + theme->menu_title_border_type = BORDER_NONE; theme->menu_title_bevel_width = 0; - theme->menu_items_active_border_type = BORDER_FLAT; + theme->menu_items_active_border_type = BORDER_NONE; theme->menu_items_active_bevel_width = 0; theme->menu_separator_line_thickness = 1; @@ -666,7 +667,7 @@ theme_builtin(struct theme *theme) theme->osd_border_width = INT_MIN; theme->osd_border_color[0] = FLT_MIN; theme->osd_label_text_color[0] = FLT_MIN; - theme->osd_border_type = BORDER_FLAT; + theme->osd_border_type = BORDER_NONE; theme->osd_border_bevel_width = 0; if (wlr_renderer_is_pixman(server.renderer)) { From f3711b294a1cb37ec116003a281e88599ad8890d Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sat, 4 Apr 2026 08:56:12 -0700 Subject: [PATCH 42/47] Add fields for button borders --- include/theme.h | 8 ++++++++ src/theme.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/include/theme.h b/include/theme.h index 2612b46f..d0199962 100644 --- a/include/theme.h +++ b/include/theme.h @@ -88,6 +88,8 @@ struct theme { float window_button_hover_bg_color[4]; int window_button_hover_bg_corner_radius; + + /* * Themes/textures for each active/inactive window. Indexed by * ssd_active_state. @@ -98,6 +100,12 @@ struct theme { /* TODO: add toggled/hover/pressed/disabled colors for buttons */ float button_colors[LAB_NODE_BUTTON_LAST + 1][4]; + enum border_type button_border_type; + int button_border_width; + int button_bevel_width; + float button_border_color[4]; + float button_hover_border_color[4]; + float border_color[4]; float toggled_keybinds_color[4]; diff --git a/src/theme.c b/src/theme.c index 0c15264e..fa600a91 100644 --- a/src/theme.c +++ b/src/theme.c @@ -576,6 +576,17 @@ theme_builtin(struct theme *theme) theme->window[SSD_INACTIVE].title_bg.border_width = 0; theme->window[SSD_INACTIVE].title_bg.exclusive = FALSE; theme->window[SSD_INACTIVE].title_bg.border_type = BORDER_NONE; + theme->window[SSD_ACTIVE].button_border_type=BORDER_NONE; + theme->window[SSD_ACTIVE].button_border_width=0; + theme->window[SSD_ACTIVE].button_bevel_width=0; + theme->window[SSD_ACTIVE].button_border_color[0] = FLT_MIN; + theme->window[SSD_ACTIVE].button_hover_border_color[0] = FLT_MIN; + theme->window[SSD_INACTIVE].button_border_type=BORDER_NONE; + theme->window[SSD_INACTIVE].button_border_width=0; + theme->window[SSD_INACTIVE].button_bevel_width=0; + theme->window[SSD_INACTIVE].button_border_color[0] = FLT_MIN; + theme->window[SSD_INACTIVE].button_hover_border_color[0] = FLT_MIN; + parse_hexstr("#000000", theme->window[SSD_ACTIVE].label_text_color); parse_hexstr("#000000", theme->window[SSD_INACTIVE].label_text_color); @@ -870,6 +881,44 @@ entry(struct theme *theme, const char *key, const char *value) value, "window.button.spacing"); } + if (match_glob(key, "window.inactive.button.bg") && parse_border_type(value)) { + theme->window[SSD_INACTIVE].button_border_type= parse_border_type(value); + } + if (match_glob(key, "window.inactive.button.bg.width")) { + theme->window[SSD_INACTIVE].button_border_width = get_int_if_positive(value, "window.inactive.button.bg.width"); + } + if (match_glob(key, "window.inactive.button.bg.bevel-width")) { + theme->window[SSD_INACTIVE].button_bevel_width = get_int_if_positive(value, "window.inactive.button.bg.bevel-width"); + } + + if (match_glob(key, "window.inactive.button.bg.border-color")) { + parse_color(value, theme->window[SSD_INACTIVE].button_border_color); + } + + if (match_glob(key, "window.inactive.button.bg.border-hover-color")) { + parse_color(value, theme->window[SSD_INACTIVE].button_hover_border_color); + } + + if (match_glob(key, "window.active.button.bg") && parse_border_type(value)) { + theme->window[SSD_ACTIVE].button_border_type= parse_border_type(value); + } + if (match_glob(key, "window.active.button.bg.width")) { + theme->window[SSD_ACTIVE].button_border_width = get_int_if_positive(value, "window.active.button.bg.width"); + } + if (match_glob(key, "window.inactive.button.bg.bevel-width")) { + theme->window[SSD_ACTIVE].button_bevel_width = get_int_if_positive(value, "window.active.button.bg.bevel-width"); + } + + if (match_glob(key, "window.active.button.bg.border-color")) { + parse_color(value, theme->window[SSD_ACTIVE].button_border_color); + } + + if (match_glob(key, "window.active.button.bg.border-hover-color")) { + parse_color(value, theme->window[SSD_ACTIVE].button_hover_border_color); + } + + + /* botton hover overlay */ if (match_glob(key, "window.button.hover.bg.color")) { parse_color(value, theme->window_button_hover_bg_color); From 5846a95f98d3e50b2d9b631bddaae9e79e72fce4 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sat, 4 Apr 2026 09:35:08 -0700 Subject: [PATCH 43/47] Add beveled borders to buttons --- src/theme.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/theme.c b/src/theme.c index fa600a91..51941227 100644 --- a/src/theme.c +++ b/src/theme.c @@ -91,6 +91,92 @@ draw_hover_overlay_on_button(cairo_t *cairo, int w, int h) cairo_fill(cairo); } +static void draw_beveled_border_on_button(cairo_t* cairo, int w, int h, int active, int hover) +{ + if (rc.theme->window[active].button_border_type) { + int bw = rc.theme->window[active].button_border_width; + float r, g, b, a; + if (!hover) { + r = rc.theme->window[active].button_border_color[0]; + g = rc.theme->window[active].button_border_color[1]; + b = rc.theme->window[active].button_border_color[2]; + a = rc.theme->window[active].button_border_color[3]; + } else { + r = rc.theme->window[active].button_hover_border_color[0]; + g = rc.theme->window[active].button_hover_border_color[1]; + b = rc.theme->window[active].button_hover_border_color[2]; + a = rc.theme->window[active].button_hover_border_color[3]; + } + + uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); + struct borderset * renderedborders = getBorders(colour32, bw, rc.theme->window[active].button_border_type, rc.theme->window[active].button_bevel_width); + + + cairo_set_source_surface(cairo, renderedborders->top->surface, 0, 0); + cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); + cairo_rectangle(cairo, bw, 0, w-bw*2, bw); + cairo_fill(cairo); + + cairo_set_source_surface(cairo, renderedborders->bottom->surface, bw, h-bw); + cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); + cairo_rectangle(cairo, bw, h-bw, w-bw*2, bw); + cairo_fill(cairo); + + + + cairo_set_source_surface(cairo, renderedborders->left->surface, 0, 0); + cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); + cairo_rectangle(cairo, 0, bw, bw, h-bw*2); + cairo_fill(cairo); + + + cairo_set_source_surface(cairo, renderedborders->right->surface, w-bw, bw); + cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); + cairo_rectangle(cairo, w-bw, bw, bw, h-bw*2); + cairo_fill(cairo); + + + + cairo_set_source_surface(cairo, renderedborders->tl->surface, 0, 0); + cairo_rectangle(cairo, 0, 0, bw, bw); + cairo_fill(cairo); + + cairo_set_source_surface(cairo, renderedborders->tr->surface, w-bw, 0); + cairo_rectangle(cairo, w - bw, 0, bw, bw); + cairo_fill(cairo); + + cairo_set_source_surface(cairo, renderedborders->bl->surface, 0, h - bw); + cairo_rectangle(cairo, 0, h - bw, bw, bw); + cairo_fill(cairo); + + cairo_set_source_surface(cairo, renderedborders->br->surface, w - bw, h -bw); + cairo_rectangle(cairo, w - bw, h - bw, bw, bw); + cairo_fill(cairo); + } +} + +static void draw_hover_active_border_on_button(cairo_t *cairo, int w, int h) +{ + draw_beveled_border_on_button(cairo, w, h, SSD_ACTIVE, 1); +} + +static void draw_hover_inactive_border_on_button(cairo_t *cairo, int w, int h) +{ + draw_beveled_border_on_button(cairo, w, h, SSD_INACTIVE, 1); +} + +static void draw_nonhover_active_border_on_button(cairo_t *cairo, int w, int h) +{ + draw_beveled_border_on_button(cairo, w, h, SSD_ACTIVE, 0); +} + +static void draw_nonhover_inactive_border_on_button(cairo_t *cairo, int w, int h) +{ + draw_beveled_border_on_button(cairo, w, h, SSD_INACTIVE, 0); +} + + + /* Round the buffer for the leftmost button in the titlebar */ static void round_left_corner_button(cairo_t *cairo, int w, int h) @@ -222,6 +308,22 @@ load_button(struct theme *theme, struct button *b, enum ssd_active_state active) draw_hover_overlay_on_button); } + + if (theme->window[active].button_border_type) { + if (active) { + if (b->state_set & LAB_BS_HOVERED) { + lab_img_add_modifier(*img, draw_hover_active_border_on_button); + } else { + lab_img_add_modifier(*img, draw_nonhover_active_border_on_button); + } + } else { + if (b->state_set & LAB_BS_HOVERED) { + lab_img_add_modifier(*img, draw_hover_inactive_border_on_button); + } else { + lab_img_add_modifier(*img, draw_nonhover_inactive_border_on_button); + } + } + } /* * If the loaded button is at the corner of the titlebar, also create * rounded variants. From 987b2c2a894650fdd823e59d0596c98b0ad0cefb Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sun, 5 Apr 2026 17:48:57 -0700 Subject: [PATCH 44/47] Realign with codesniffer rules --- include/common/borderset.h | 48 ++-- include/ssd-internal.h | 4 +- include/theme.h | 4 - include/view.h | 2 +- src/common/borderset.c | 462 ++++++++++++++++++------------------ src/common/lab-scene-rect.c | 21 +- src/cycle/osd-scroll.c | 3 +- src/main.c | 2 +- src/menu/menu.c | 68 +++--- src/server.c | 1 - src/ssd/resize-indicator.c | 26 +- src/ssd/ssd-border.c | 44 ++-- src/ssd/ssd-titlebar.c | 70 ++++-- src/theme.c | 158 ++++++------ src/workspaces.c | 39 ++- 15 files changed, 486 insertions(+), 466 deletions(-) diff --git a/include/common/borderset.h b/include/common/borderset.h index 23fb6c75..c9d7248f 100644 --- a/include/common/borderset.h +++ b/include/common/borderset.h @@ -1,6 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ #include #include -/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef LABWC_BORDERSET_H #define LABWC_BORDERSET_H @@ -9,10 +10,14 @@ enum border_type { }; struct borderset { - uint32_t id; // Base colour, but could be used as a tracking hash for images or whatever in the future - int size; // width (since I suspect a 2px border scaled up to 20px might look weird) - enum border_type type; // Single or double bevel - int bevelSize; // So we can disambiguate multiple possible designs cached together + // Base colour, but could be used as a tracking hash for images or whatever in the future + uint32_t id; + // width (since I suspect a 2px border scaled up to 20px might look weird) + int size; + // Single or double bevel, etc. + enum border_type type; + // So we can disambiguate multiple possible designs cached together + int bevelSize; struct lab_data_buffer *top; struct lab_data_buffer *left; struct lab_data_buffer *right; @@ -21,35 +26,36 @@ struct borderset { struct lab_data_buffer *tr; struct lab_data_buffer *bl; struct lab_data_buffer *br; - struct borderset * next; + struct borderset *next; }; struct bufferset { enum border_type type; int border_width; - struct wlr_scene_buffer * top; - struct wlr_scene_buffer * left; - struct wlr_scene_buffer * right; - struct wlr_scene_buffer * bottom; - struct wlr_scene_buffer * tl; - struct wlr_scene_buffer * tr; - struct wlr_scene_buffer * bl; - struct wlr_scene_buffer * br; + struct wlr_scene_buffer *top; + struct wlr_scene_buffer *left; + struct wlr_scene_buffer *right; + struct wlr_scene_buffer *bottom; + struct wlr_scene_buffer *tl; + struct wlr_scene_buffer *tr; + struct wlr_scene_buffer *bl; + struct wlr_scene_buffer *br; }; -extern struct borderset * borderCache; +extern struct borderset *borderCache; -struct borderset * getBorders(uint32_t id, int size, enum border_type, int bevelSize); +struct borderset *getBorders(uint32_t id, int size, enum border_type, int bevelSize); -struct borderset * createBuffer(uint32_t id, int size, enum border_type, int bevelSize); +struct borderset *createBuffer(uint32_t id, int size, enum border_type, int bevelSize); -struct bufferset * generateBufferset(struct wlr_scene_tree * tree, struct borderset *borderset, int bw); +struct bufferset *generateBufferset(struct wlr_scene_tree *tree, + struct borderset *borderset, int bw); -void renderBufferset(struct bufferset *, int width, int height, int y); +void renderBufferset(struct bufferset *bufferset, int width, int height, int y); -void renderBuffersetXY(struct bufferset *, int width, int height, int x, int y); +void renderBuffersetXY(struct bufferset *bufferset, int width, int height, int x, int y); void clearBorderCache(struct borderset *borderset); -#endif /* LABWC_LAB_SCENE_RECT_H */ +#endif /* LABWC_BORDERSET_H */ diff --git a/include/ssd-internal.h b/include/ssd-internal.h index 5b888468..776fba34 100644 --- a/include/ssd-internal.h +++ b/include/ssd-internal.h @@ -106,7 +106,7 @@ struct ssd { struct scaled_font_buffer *title; struct wl_list buttons_left; /* ssd_button.link */ struct wl_list buttons_right; /* ssd_button.link */ - struct bufferset * texturedBorders; + struct bufferset *texturedBorders; } subtrees[2]; /* indexed by enum ssd_active_state */ } titlebar; @@ -116,7 +116,7 @@ struct ssd { struct ssd_border_subtree { struct wlr_scene_tree *tree; struct wlr_scene_rect *top, *bottom, *left, *right; - struct bufferset * texturedBorders; + struct bufferset *texturedBorders; } subtrees[2]; /* indexed by enum ssd_active_state */ } border; diff --git a/include/theme.h b/include/theme.h index d0199962..f28c0cab 100644 --- a/include/theme.h +++ b/include/theme.h @@ -61,7 +61,6 @@ struct theme_background { int border_width; int bevel_width; bool exclusive; - }; struct theme { @@ -88,8 +87,6 @@ struct theme { float window_button_hover_bg_color[4]; int window_button_hover_bg_corner_radius; - - /* * Themes/textures for each active/inactive window. Indexed by * ssd_active_state. @@ -105,7 +102,6 @@ struct theme { int button_bevel_width; float button_border_color[4]; float button_hover_border_color[4]; - float border_color[4]; float toggled_keybinds_color[4]; diff --git a/include/view.h b/include/view.h index a3d80609..a2acaa95 100644 --- a/include/view.h +++ b/include/view.h @@ -244,7 +244,7 @@ struct view { int width, height; struct wlr_scene_tree *tree; struct wlr_scene_rect *border; - struct bufferset * texturedBorders; + struct bufferset *texturedBorders; struct wlr_scene_rect *background; struct scaled_font_buffer *text; } resize_indicator; diff --git a/src/common/borderset.c b/src/common/borderset.c index b8573687..e06c39b3 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only #include #include #include "common/borderset.h" @@ -5,38 +6,41 @@ #include "common/macros.h" #include "buffer.h" -struct borderset * getBorders(uint32_t id, int size, enum border_type type, int bevelSize) { - struct borderset * current = borderCache; - struct borderset * last; - +struct borderset *getBorders(uint32_t id, int size, enum border_type type, int bevelSize) +{ + struct borderset *current = borderCache; + struct borderset *last; + // Preventing building nonsense borders: - // If you try for a double bevel but it's so deep they would overlap, convert to a single bevel + // If you try for a double bevel but it's so deep they would overlap, + // convert to a single bevel if (type == BORDER_DOUBLE && (bevelSize > size/2)) { type = BORDER_SINGLE; } - - if (type == BORDER_DOUBLE_INSET && (bevelSize > size/2)) { + + if (type == BORDER_DOUBLE_INSET && (bevelSize > size/2)) { type = BORDER_INSET; } - - - // Anything with a size of 0 is converted to a 1-pixel flat border so as to prevent empty allocations - + + // Anything with a size of 0 is converted to a 1-pixel flat border so as to + // prevent empty allocations + if (size < 1) { type = BORDER_FLAT; size = 1; } - - while (current != NULL) { - if (current->size == size && current->id == id && current->type == type && current->bevelSize == bevelSize) { + + while (current) { + if (current->size == size && current->id == id && + current->type == type && current->bevelSize == bevelSize) { return current; } - last = current; - current = current -> next; + last = current; + current = current->next; } // Fall through, we need to create a buffer. - - if (borderCache == NULL) { + + if (!borderCache) { borderCache = createBuffer(id, size, type, bevelSize); return borderCache; } else { @@ -46,41 +50,45 @@ struct borderset * getBorders(uint32_t id, int size, enum border_type type, int return NULL; } -struct borderset * createBuffer(uint32_t id, int size, enum border_type type, int bevelSize) { - struct borderset *newBorderset = znew(*newBorderset); +struct borderset *createBuffer(uint32_t id, int size, enum border_type type, int bevelSize) +{ + struct borderset *new_borderset = znew(*new_borderset); + + new_borderset->next = NULL; + new_borderset->id = id; + new_borderset->size = size; + new_borderset->type = type; + new_borderset->bevelSize = bevelSize; - - newBorderset->next = NULL; - newBorderset->id = id; - newBorderset->size = size; - newBorderset->type = type; - newBorderset->bevelSize = bevelSize; - - - // Use ID as a AARRGGBB colour uint8_t a = id >> 24 & 255; uint8_t r = id >> 16 & 255; uint8_t g = id >> 8 & 255; uint8_t b = id & 255; - - uint32_t r1 = r * 5 / 4; - if (r1 > a) r1=a; - uint32_t g1 = g * 5 / 4; - if (g1 > a) g1=a; - uint32_t b1 = b * 5 / 4; - if (b1 > a) b1=a; - /* darker outline */ + uint32_t r1 = r * 5 / 4; + if (r1 > a) { + r1 = a; + } + uint32_t g1 = g * 5 / 4; + if (g1 > a) { + g1 = a; + } + uint32_t b1 = b * 5 / 4; + if (b1 > a) { + b1 = a; + } + + /* darker outline */ uint32_t r0 = r / 2; uint32_t g0 = g / 2; uint32_t b0 = b / 2; - + uint32_t hl32 = ((uint32_t)a << 24) | ((uint32_t)r1 << 16) | ((uint32_t)g1 << 8) | (uint32_t)b1; uint32_t ll32 = ((uint32_t)a << 24) | ((uint32_t)r0 << 16) | ((uint32_t)g0 << 8) | (uint32_t)b0; - uint32_t temp; + uint32_t temp; // All borders have NxN corners uint32_t *tl = znew_n(uint32_t, size*size); @@ -93,198 +101,182 @@ struct borderset * createBuffer(uint32_t id, int size, enum border_type type, i uint32_t *bottom = NULL; size_t side_size = 0; - switch(type) { - case BORDER_INSET: - temp = ll32; - ll32 = hl32; - hl32 = temp; - // Fall throgh intentional - case BORDER_SINGLE: // Single bevel borders have 1x1 sides - top = znew(uint32_t); - left = znew(uint32_t); - right = znew(uint32_t); - bottom = znew(uint32_t); - side_size = 1; - *top = hl32; - *left = hl32; - *right = ll32; - *bottom = ll32; - - // Fill with solid - for (int j=0; j k) ? hl32 : ll32; - bl[PIXEL(size - 1 -j, k, size)] = (j > k) ? hl32 : ll32; - br[PIXEL(j, k, size)] = ll32; - } + switch (type) { + case BORDER_INSET: + temp = ll32; + ll32 = hl32; + hl32 = temp; + // Fall throgh intentional + case BORDER_SINGLE: // Single bevel borders have 1x1 sides + top = znew(uint32_t); + left = znew(uint32_t); + right = znew(uint32_t); + bottom = znew(uint32_t); + side_size = 1; + *top = hl32; + *left = hl32; + *right = ll32; + *bottom = ll32; + + // Fill with solid + for (int j = 0; j < size; j++) { + for (int k = 0; k < size; k++) { + tl[PIXEL(j, k, size)] = hl32; + tr[PIXEL(size - 1 - j, k, size)] = (j > k) ? hl32 : ll32; + bl[PIXEL(size - 1 -j, k, size)] = (j > k) ? hl32 : ll32; + br[PIXEL(j, k, size)] = ll32; } - - - + } + + break; + + case BORDER_DOUBLE_INSET: + temp = ll32; + ll32 = hl32; + hl32 = temp; + // Fall throgh intentional + case BORDER_DOUBLE: + top = znew_n(uint32_t, size); + left = znew_n(uint32_t, size); + right = znew_n(uint32_t, size); + bottom = znew_n(uint32_t, size); + side_size = size; + + for (int i = 0; i < size; i++) { + if (i < bevelSize) { + left[i] = hl32; + top[i] = hl32; + right[i] = hl32; + bottom[i] = hl32; + + } else if (i > (size-bevelSize-1)) { + left[i] = ll32; + top[i] = ll32; + right[i] = ll32; + bottom[i] = ll32; + + } else { + left[i] = id; + top[i] = id; + right[i] = id; + bottom[i] = id; + } + } + + // Blank corners... + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + tl[PIXEL(i, j, size)] = id; + tr[PIXEL(i, j, size)] = id; + bl[PIXEL(i, j, size)] = id; + br[PIXEL(i, j, size)] = id; + } + } + + // Main Corners + for (int i = 0; i < bevelSize; i++) { + // Solid bar parts + for (int j = 0; j < size; j++) { + // Top left corner: Entire "bevel size" top rows are highlighted + tl[PIXEL(j, i, size)] = hl32; + // First "bevel size" top columns are highlighted + tl[PIXEL(i, j, size)] = hl32; + + // Bottom Right corner: Entire "bevel size" last rows are lowlight + br[PIXEL(j, (size-1-i), size)] = ll32; + // Last "bevel size" columns are lowlight + br[PIXEL((size-1-i), j, size)] = ll32; + + // Bottom left corner: Entire "bevel size" last rows are lowlight + bl[PIXEL(j, (size-1-i), size)] = ll32; + // First "bevel size" columns are highlight, except for + // the bottom right corner + bl[PIXEL(i, j, size)] = hl32; + + // Top Right corner: Entire "bevel size" first rows are highlight + tr[PIXEL(j, i, size)] = hl32; + // Last "bevel size" columns are lowlight, except for the top left + tr[PIXEL((size-1-i), j, size)] = ll32; + } + } + // Beveled Corner Parts + for (int i = 0; i < bevelSize; i++) { + for (int j = 0; j < bevelSize; j++) { + // Outer Corners + // Bottom left corner: + // First "bevel size" columns are highlight, except + // for the bottom right corner + bl[PIXEL(i, (size - 1 - j), size)] = (j >= i) ? hl32 : ll32; + + // Top Right corner: + // Last "bevel size" columns are lowlight, except for the top left + tr[PIXEL((size-1-i), j, size)] = (j > i) ? ll32 : hl32; + + // Inner Corners + // Top left corner: Bottom right is all dark + tl[PIXEL((size-1-i), (size - 1 - j), size)] = ll32; + + // Bottom Right corner: Top left is all light + br[PIXEL(i, j, size)] = hl32; + + // Top Right corner: + // Interior bottom left is dark on top, light on bottom + tr[PIXEL(i, (size-1-j), size)] = (i > j) ? hl32 : ll32; + + // Bottom Left corner: + // Interior top right is dark on top, light on bottom + bl[PIXEL((size-1-i), j, size)] = (i > j) ? ll32 : hl32; + } + } + break; - case BORDER_DOUBLE_INSET: - temp = ll32; - ll32 = hl32; - hl32 = temp; - // Fall throgh intentional - case BORDER_DOUBLE: - top = znew_n(uint32_t, size); - left = znew_n(uint32_t, size); - right = znew_n(uint32_t, size); - bottom = znew_n(uint32_t, size); - side_size = size; + case BORDER_FLAT: // Placeholder that uses buffers but for a flat colour + case BORDER_NONE: // Provided as a fallback but should not be actually requested/rendered + top = znew(uint32_t); + left = znew(uint32_t); + right = znew(uint32_t); + bottom = znew(uint32_t); + side_size = 1; + *top = id; + *left = id; + *right = id; + *bottom = id; - for (int i = 0; i < size; i++) { - if (i (size-bevelSize-1)) { - left[i] = ll32; - top[i] = ll32; - right[i] = ll32; - bottom[i] = ll32; - - } else { - left[i] = id; - top[i] = id; - right[i] = id; - bottom[i] = id; - } + // Fill with solid + for (int j = 0; j < size; j++) { + for (int k = 0; k < size; k++) { + tl[PIXEL(j, k, size)] = id; + tr[PIXEL(size - 1 - j, k, size)] = id; + bl[PIXEL(size - 1 -j, k, size)] = id; + br[PIXEL(j, k, size)] = id; } + } - // Blank corners... - for (int i=0; i= i) ? hl32 : ll32; - - // Top Right corner: - // Last "bevel size" columns are lowlight, except for the top left - tr[PIXEL((size-1-i), j, size)] = (j > i) ? ll32 : hl32; - - - // Inner Corners - // Top left corner: Bottom right is all dark - tl[PIXEL((size-1-i), (size - 1 - j), size)] = ll32; - - // Bottom Right corner: Top left is all light - br[PIXEL(i, j, size)] = hl32; - - // Top Right corner: - // Interior bottom left is dark on top, light on bottom - tr[PIXEL(i, (size-1-j), size)] = (i > j) ? hl32 : ll32; - - // Bottom Left corner: - // Interior top right is dark on top, light on bottom - bl[PIXEL((size-1-i), j, size)] = (i > j) ? ll32 : hl32; - - - - } - - - } - - - - - break; - - case BORDER_FLAT: // Placeholder that uses buffers but for a flat colour - case BORDER_NONE: // Provided as a fallback but should not be actually requested/rendered - top = znew(uint32_t); - left = znew(uint32_t); - right = znew(uint32_t); - bottom = znew(uint32_t); - side_size = 1; - *top = id; - *left = id; - *right = id; - *bottom = id; - - // Fill with solid - for (int j=0; j 0); - newBorderset->top = buffer_create_from_data(top, 1, side_size, 4); - newBorderset->left = buffer_create_from_data(left, side_size, 1, side_size * 4); - newBorderset->right = buffer_create_from_data(right, side_size, 1, side_size * 4); - newBorderset->bottom = buffer_create_from_data(bottom, 1, side_size, 4); + new_borderset->top = buffer_create_from_data(top, 1, side_size, 4); + new_borderset->left = buffer_create_from_data(left, side_size, 1, side_size * 4); + new_borderset->right = buffer_create_from_data(right, side_size, 1, side_size * 4); + new_borderset->bottom = buffer_create_from_data(bottom, 1, side_size, 4); - newBorderset->tl = buffer_create_from_data(tl, size, size, size * 4); - newBorderset->tr = buffer_create_from_data(tr, size, size, size * 4); - newBorderset->bl = buffer_create_from_data(bl, size, size, size * 4); - newBorderset->br = buffer_create_from_data(br, size, size, size * 4); + new_borderset->tl = buffer_create_from_data(tl, size, size, size * 4); + new_borderset->tr = buffer_create_from_data(tr, size, size, size * 4); + new_borderset->bl = buffer_create_from_data(bl, size, size, size * 4); + new_borderset->br = buffer_create_from_data(br, size, size, size * 4); - return newBorderset; + return new_borderset; } - -struct bufferset * generateBufferset(struct wlr_scene_tree * tree, struct borderset *borderset, int bw) +struct bufferset *generateBufferset(struct wlr_scene_tree *tree, + struct borderset *borderset, int bw) { - struct bufferset * bufferset = znew(struct bufferset); + struct bufferset *bufferset = znew(struct bufferset); bufferset->top = wlr_scene_buffer_create(tree, &borderset->top->base); - bufferset->left= wlr_scene_buffer_create(tree, &borderset->left->base); + bufferset->left = wlr_scene_buffer_create(tree, &borderset->left->base); bufferset->right = wlr_scene_buffer_create(tree, &borderset->right->base); bufferset->bottom = wlr_scene_buffer_create(tree, &borderset->bottom->base); bufferset->tl = wlr_scene_buffer_create(tree, &borderset->tl->base); @@ -308,62 +300,58 @@ struct bufferset * generateBufferset(struct wlr_scene_tree * tree, struct border void renderBufferset(struct bufferset *bufferset, int width, int height, int y) { - renderBuffersetXY(bufferset, width, height, 0, y); + renderBuffersetXY(bufferset, width, height, 0, y); } void renderBuffersetXY(struct bufferset *bufferset, int width, int height, int x, int y) { - wlr_scene_buffer_set_dest_size(bufferset->top, - width - 2 * bufferset->border_width, bufferset->border_width); + width - 2 * bufferset->border_width, bufferset->border_width); wlr_scene_node_set_position(&bufferset->top->node, - x+bufferset->border_width,y); + x+bufferset->border_width, y); wlr_scene_buffer_set_dest_size(bufferset->bottom, - width - 2 * bufferset->border_width, bufferset->border_width); + width - 2 * bufferset->border_width, bufferset->border_width); wlr_scene_node_set_position(&bufferset->bottom->node, - x+bufferset->border_width, y+height - bufferset->border_width); - + x+bufferset->border_width, y+height - bufferset->border_width); wlr_scene_buffer_set_dest_size(bufferset->left, bufferset->border_width, height - bufferset->border_width * 2); wlr_scene_node_set_position(&bufferset->left->node, - x, bufferset->border_width+y); + x, bufferset->border_width+y); wlr_scene_buffer_set_dest_size(bufferset->right, bufferset->border_width, height - bufferset->border_width * 2); wlr_scene_node_set_position(&bufferset->right->node, - x+width - bufferset->border_width, y+ bufferset->border_width); + x+width - bufferset->border_width, y+bufferset->border_width); wlr_scene_buffer_set_dest_size(bufferset->tl, - bufferset->border_width, bufferset->border_width); + bufferset->border_width, bufferset->border_width); wlr_scene_node_set_position(&bufferset->tl->node, - x,y); + x, y); wlr_scene_buffer_set_dest_size(bufferset->tr, - bufferset->border_width, bufferset->border_width); + bufferset->border_width, bufferset->border_width); wlr_scene_node_set_position(&bufferset->tr->node, - x+width-bufferset->border_width, y); - + x+width-bufferset->border_width, y); wlr_scene_buffer_set_dest_size(bufferset->br, - bufferset->border_width, bufferset->border_width); + bufferset->border_width, bufferset->border_width); wlr_scene_node_set_position(&bufferset->br->node, - x+width-bufferset->border_width , y+height-bufferset->border_width); - + x+width-bufferset->border_width, y+height-bufferset->border_width); wlr_scene_buffer_set_dest_size(bufferset->bl, - bufferset->border_width, bufferset->border_width); + bufferset->border_width, bufferset->border_width); wlr_scene_node_set_position(&bufferset->bl->node, - x, height-bufferset->border_width+y); - + x, height-bufferset->border_width+y); } -void clearBorderCache(struct borderset * borderset) +void clearBorderCache(struct borderset *borderset) { - if (borderset == NULL) + if (!borderset) { return; - if (borderset->next != NULL) { + } + if (borderset->next) { clearBorderCache(borderset->next); } wlr_buffer_drop(&borderset->top->base); diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c index 71fe287d..8ad48a28 100644 --- a/src/common/lab-scene-rect.c +++ b/src/common/lab-scene-rect.c @@ -12,7 +12,7 @@ struct border_scene { struct wlr_scene_tree *tree; struct wlr_scene_rect *top, *bottom, *left, *right; - struct bufferset * texturedBorders; + struct bufferset *texturedBorders; }; static void @@ -42,7 +42,7 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, struct border_scene *border = &rect->borders[i]; float *color = opts->border_colors[i]; border->tree = lab_wlr_scene_tree_create(rect->tree); - + border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, color); border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, color); border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0, color); @@ -54,14 +54,17 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, float b = color[2]; float a = color[3]; int bw = rect->border_width; - uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, opts->border_type, opts->bevel_width); - border->texturedBorders = generateBufferset(border->tree, renderedborders, bw); + uint32_t colour32 = (uint32_t)(a*255) << 24 | + (uint32_t)(r*255) << 16 | + (uint32_t)(g*255) << 8 | + (uint32_t)(b*255); + struct borderset *renderedborders = getBorders(colour32, bw, + opts->border_type, opts->bevel_width); + border->texturedBorders = generateBufferset(border->tree, + renderedborders, bw); } else { border->texturedBorders = NULL; } - - } rect->node_destroy.notify = handle_node_destroy; @@ -102,8 +105,8 @@ resize_border(struct border_scene *border, int border_width, int width, int heig 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); - if (border->texturedBorders != NULL) { - renderBufferset(border->texturedBorders, width, height, 0); + if (border->texturedBorders) { + renderBufferset(border->texturedBorders, width, height, 0); } } diff --git a/src/cycle/osd-scroll.c b/src/cycle/osd-scroll.c index e51428be..128b5031 100644 --- a/src/cycle/osd-scroll.c +++ b/src/cycle/osd-scroll.c @@ -14,9 +14,8 @@ cycle_osd_scroll_init(struct cycle_osd_output *osd_output, struct wlr_box bar_ar int delta_y, int nr_cols, int nr_rows, int nr_visible_rows, float *border_color, float *bg_color) { - struct theme *theme = rc.theme; - + if (nr_visible_rows >= nr_rows) { /* OSD doesn't have so many windows to scroll through */ return; diff --git a/src/main.c b/src/main.c index 9b5d65b6..f25c48c2 100644 --- a/src/main.c +++ b/src/main.c @@ -41,7 +41,7 @@ static const struct option long_options[] = { {0, 0, 0, 0} }; -struct borderset * borderCache = NULL; +struct borderset *borderCache; static const char labwc_usage[] = "Usage: labwc [options...]\n" diff --git a/src/menu/menu.c b/src/menu/menu.c index 5bb2af14..188bba12 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -169,7 +169,7 @@ item_create_scene_for_state(struct menuitem *item, float *text_color, { struct menu *menu = item->parent; struct theme *theme = rc.theme; - struct bufferset * bufferset = NULL; + struct bufferset *bufferset = NULL; /* Tree to hold background and label buffers */ struct wlr_scene_tree *tree = lab_wlr_scene_tree_create(item->tree); @@ -194,32 +194,36 @@ item_create_scene_for_state(struct menuitem *item, float *text_color, /* Create background */ lab_wlr_scene_rect_create(tree, bg_width, theme->menu_item_height, bg_color); - int bw = theme->menu_border_width; - if (rc.theme->menu_items_active_border_type && state) { + int bw = theme->menu_border_width; + if (rc.theme->menu_items_active_border_type && state) { float r = bg_color[0]; float g = bg_color[1]; float b = bg_color[2]; float a = bg_color[3]; - - uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, rc.theme->menu_items_active_border_type, rc.theme->menu_items_active_bevel_width); - bufferset = generateBufferset(tree, renderedborders, bw); + uint32_t colour32 = (uint32_t)(a*255) << 24 | + (uint32_t)(r*255) << 16 | + (uint32_t)(g*255) << 8 | + (uint32_t)(b*255); + struct borderset *renderedborders = getBorders(colour32, bw, + rc.theme->menu_items_active_border_type, + rc.theme->menu_items_active_bevel_width); + bufferset = generateBufferset(tree, renderedborders, bw); } else if (rc.theme->menu_items_border_type && !state) { float r = bg_color[0]; float g = bg_color[1]; float b = bg_color[2]; float a = bg_color[3]; - - uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, rc.theme->menu_items_border_type, rc.theme->menu_items_bevel_width); - bufferset = generateBufferset(tree, renderedborders, bw); + uint32_t colour32 = (uint32_t)(a*255) << 24 | + (uint32_t)(r*255) << 16 | + (uint32_t)(g*255) << 8 | + (uint32_t)(b*255); + struct borderset *renderedborders = getBorders(colour32, bw, + rc.theme->menu_items_border_type, + rc.theme->menu_items_bevel_width); + bufferset = generateBufferset(tree, renderedborders, bw); } - - - - /* Create icon */ bool show_app_icon = !strcmp(item->parent->id, "client-list-combined-menu") @@ -248,12 +252,10 @@ item_create_scene_for_state(struct menuitem *item, float *text_color, int x = theme->menu_items_padding_x + icon_width; int y = (theme->menu_item_height - label_buffer->height) / 2; wlr_scene_node_set_position(&label_buffer->scene_buffer->node, x, y); - - - if (bufferset != NULL) { + + if (bufferset) { renderBufferset(bufferset, bg_width, theme->menu_item_height, 0); } - if (!item->arrow) { return tree; @@ -374,7 +376,7 @@ title_create_scene(struct menuitem *menuitem, int *item_y) assert(menuitem->type == LAB_MENU_TITLE); struct menu *menu = menuitem->parent; struct theme *theme = rc.theme; - struct bufferset * bufferset; + struct bufferset *bufferset; float *bg_color = theme->menu_title_bg_color; float *text_color = theme->menu_title_text_color; @@ -394,21 +396,23 @@ title_create_scene(struct menuitem *menuitem, int *item_y) wlr_log(WLR_ERROR, "not enough space for menu title"); goto error; } - - - int bw = theme->menu_border_width; - if (rc.theme->menu_title_border_type) { + + int bw = theme->menu_border_width; + if (rc.theme->menu_title_border_type) { float r = bg_color[0]; float g = bg_color[1]; float b = bg_color[2]; float a = bg_color[3]; - - uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, rc.theme->menu_title_border_type, rc.theme->menu_title_bevel_width); - bufferset = generateBufferset(menuitem->tree, renderedborders, bw); - } - + uint32_t colour32 = (uint32_t)(a*255) << 24 | + (uint32_t)(r*255) << 16 | + (uint32_t)(g*255) << 8 | + (uint32_t)(b*255); + struct borderset *renderedborders = getBorders(colour32, bw, + rc.theme->menu_title_border_type, + rc.theme->menu_title_bevel_width); + bufferset = generateBufferset(menuitem->tree, renderedborders, bw); + } /* Background */ lab_wlr_scene_rect_create(menuitem->normal_tree, @@ -438,8 +442,8 @@ title_create_scene(struct menuitem *menuitem, int *item_y) int title_y = (theme->menu_header_height - title_font_buffer->height) / 2; wlr_scene_node_set_position(&title_font_buffer->scene_buffer->node, title_x, title_y); - - if (rc.theme->menu_title_border_type) { + + if (rc.theme->menu_title_border_type) { renderBufferset(bufferset, bg_width, theme->menu_item_height, 0); } error: diff --git a/src/server.c b/src/server.c index fd4f6036..8af35e4a 100644 --- a/src/server.c +++ b/src/server.c @@ -93,7 +93,6 @@ reload_config_and_theme(void) clearBorderCache(borderCache); borderCache = NULL; - rcxml_read(rc.config_file); theme_finish(rc.theme); theme_init(rc.theme, rc.theme_name); diff --git a/src/ssd/resize-indicator.c b/src/ssd/resize-indicator.c index f6d9e846..8f2105d8 100644 --- a/src/ssd/resize-indicator.c +++ b/src/ssd/resize-indicator.c @@ -38,20 +38,23 @@ resize_indicator_reconfigure_view(struct resize_indicator *indicator) /* Colors */ wlr_scene_rect_set_color(indicator->border, theme->osd_border_color); wlr_scene_rect_set_color(indicator->background, theme->osd_bg_color); - - - if (rc.theme->osd_border_type) { + + if (rc.theme->osd_border_type) { float r = theme->osd_border_color[0]; float g = theme->osd_border_color[1]; float b = theme->osd_border_color[2]; float a = theme->osd_border_color[3]; int bw = theme->osd_border_width; - uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, theme->osd_border_type, theme->osd_border_bevel_width); - indicator->texturedBorders = generateBufferset(indicator->tree, renderedborders, bw); + uint32_t colour32 = (uint32_t)(a*255) << 24 | + (uint32_t)(r*255) << 16 | + (uint32_t)(g*255) << 8 | + (uint32_t)(b*255); + struct borderset *renderedborders = getBorders(colour32, bw, theme->osd_border_type, + theme->osd_border_bevel_width); + indicator->texturedBorders = generateBufferset(indicator->tree, + renderedborders, bw); } - } static void @@ -67,9 +70,7 @@ resize_indicator_init(struct view *view) indicator->background = lab_wlr_scene_rect_create( indicator->tree, 0, 0, rc.theme->osd_bg_color); - indicator->text = scaled_font_buffer_create(indicator->tree); - wlr_scene_node_set_enabled(&indicator->tree->node, false); resize_indicator_reconfigure_view(indicator); @@ -138,9 +139,10 @@ resize_indicator_set_size(struct resize_indicator *indicator, int width) wlr_scene_rect_set_size(indicator->background, indicator->width - 2 * rc.theme->osd_border_width, indicator->height - 2 * rc.theme->osd_border_width); - - if (rc.theme->osd_border_type) { - renderBufferset(indicator->texturedBorders, indicator->width, indicator->height, 0); + + if (rc.theme->osd_border_type) { + renderBufferset(indicator->texturedBorders, indicator->width, + indicator->height, 0); } } diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index e26b80bf..69d3e569 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -13,8 +13,6 @@ #include "view.h" #include "common/borderset.h" - - void ssd_border_create(struct ssd *ssd) { @@ -40,54 +38,48 @@ ssd_border_create(struct ssd *ssd) wlr_scene_node_set_enabled(&parent->node, active); float *color = theme->window[active].border_color; if (theme->window[active].border_type) { - // These will otherwise get left under the window when we reload - - subtree->left = lab_wlr_scene_rect_create(parent, 1, 1, color); - + subtree->left = lab_wlr_scene_rect_create(parent, 1, 1, color); subtree->right = lab_wlr_scene_rect_create(parent, 1, 1, color); - subtree->bottom = lab_wlr_scene_rect_create(parent, 1, 1, color); - subtree->top = lab_wlr_scene_rect_create(parent, 1, 1, color); - + /* From Pull request 3382 */ float r = color[0]; float g = color[1]; float b = color[2]; float a = color[3]; - uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, theme->window[active].border_type, theme->window[active].bevel_width); - subtree->texturedBorders = generateBufferset(subtree->tree, renderedborders, bw); - } else { + uint32_t colour32 = (uint32_t)(a*255) << 24 | + (uint32_t)(r*255) << 16 | + (uint32_t)(g*255) << 8 | + (uint32_t)(b*255); + struct borderset *renderedborders = getBorders(colour32, bw, + theme->window[active].border_type, + theme->window[active].bevel_width); + subtree->texturedBorders = generateBufferset(subtree->tree, + renderedborders, bw); + } else { subtree->left = lab_wlr_scene_rect_create(parent, theme->border_width, height, color); - subtree->right = lab_wlr_scene_rect_create(parent, theme->border_width, height, color); - subtree->bottom = lab_wlr_scene_rect_create(parent, full_width, theme->border_width, color); - subtree->top = lab_wlr_scene_rect_create(parent, MAX(width - 2 * corner_width, 0), theme->border_width, color); + wlr_scene_node_set_position(&subtree->left->node, 0, 0); wlr_scene_node_set_position(&subtree->right->node, theme->border_width + width, 0); wlr_scene_node_set_position(&subtree->bottom->node, 0, height); - wlr_scene_node_set_position(&subtree->top->node, theme->border_width + corner_width, -(ssd->titlebar.height + theme->border_width)); } - } - - - if (view->maximized == VIEW_AXIS_BOTH) { wlr_scene_node_set_enabled(&ssd->border.tree->node, false); @@ -166,15 +158,15 @@ ssd_border_update(struct ssd *ssd) enum ssd_active_state active; FOR_EACH_ACTIVE_STATE(active) { struct ssd_border_subtree *subtree = &ssd->border.subtrees[active]; - - - if (theme->window[active].border_type) { - renderBufferset(subtree->texturedBorders, full_width, side_height+(ssd->titlebar.height + 2*theme->border_width), -ssd->titlebar.height-theme->border_width); + if (theme->window[active].border_type) { + renderBufferset(subtree->texturedBorders, full_width, + side_height+(ssd->titlebar.height + 2*theme->border_width), + -ssd->titlebar.height-theme->border_width); } else { wlr_scene_rect_set_size(subtree->left, theme->border_width, side_height); wlr_scene_node_set_position(&subtree->left->node, - 0, side_y); + 0, side_y); wlr_scene_rect_set_size(subtree->right, theme->border_width, side_height); wlr_scene_node_set_position(&subtree->right->node, diff --git a/src/ssd/ssd-titlebar.c b/src/ssd/ssd-titlebar.c index 4c82c76b..7575b841 100644 --- a/src/ssd/ssd-titlebar.c +++ b/src/ssd/ssd-titlebar.c @@ -37,7 +37,7 @@ ssd_titlebar_create(struct ssd *ssd) LAB_NODE_TITLEBAR, view, /*data*/ NULL); enum ssd_active_state active; - bool shouldForceUpdate = FALSE; + bool should_force_update = FALSE; FOR_EACH_ACTIVE_STATE(active) { struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active]; subtree->tree = lab_wlr_scene_tree_create(ssd->titlebar.tree); @@ -62,13 +62,21 @@ ssd_titlebar_create(struct ssd *ssd) float b = color[2]; float a = color[3]; - uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, theme->window[active].title_bg.border_width, theme->window[active].title_bg.border_type, theme->window[active].title_bg.bevel_width); - subtree->texturedBorders = generateBufferset(subtree->tree, renderedborders, theme->window[active].title_bg.border_width); - - // If we have the beveled borders, we actually have to run ssd_titlebar_update() to make sure we render the updated - // borders. Otherwise they disappear on reconfigure - shouldForceUpdate = true; + uint32_t colour32 = (uint32_t)(a*255) << 24 | + (uint32_t)(r*255) << 16 | + (uint32_t)(g*255) << 8 | + (uint32_t)(b*255); + struct borderset *renderedborders = getBorders(colour32, + theme->window[active].title_bg.border_width, + theme->window[active].title_bg.border_type, + theme->window[active].title_bg.bevel_width); + subtree->texturedBorders = generateBufferset(subtree->tree, renderedborders, + theme->window[active].title_bg.border_width); + + // If we have the beveled borders, we actually have to run + // ssd_titlebar_update() to make sure we render the updated borders. + // Otherwise they disappear on reconfigure + should_force_update = true; } /* * Work around the wlroots/pixman bug that widened 1px buffer @@ -92,7 +100,8 @@ ssd_titlebar_create(struct ssd *ssd) /* Title */ if (theme->window[active].title_bg.border_type) { - // Use a blank background pattern so it doesn't overlay a pattern on the order. + // Use a blank background pattern so it doesn't overlay + // a pattern on the order. subtree->title = scaled_font_buffer_create_for_titlebar( subtree->tree, theme->titlebar_height, NULL); @@ -147,7 +156,10 @@ ssd_titlebar_create(struct ssd *ssd) if (squared) { ssd->state.was_squared = true; } - set_squared_corners(ssd, maximized || squared || theme->window[SSD_ACTIVE].title_bg.border_type || theme->window[SSD_INACTIVE].title_bg.border_type); + set_squared_corners(ssd, maximized || + squared || + theme->window[SSD_ACTIVE].title_bg.border_type || + theme->window[SSD_INACTIVE].title_bg.border_type); if (view->shaded) { set_alt_button_icon(ssd, LAB_NODE_BUTTON_SHADE, true); @@ -156,8 +168,8 @@ ssd_titlebar_create(struct ssd *ssd) if (view->visible_on_all_workspaces) { set_alt_button_icon(ssd, LAB_NODE_BUTTON_OMNIPRESENT, true); } - - if (shouldForceUpdate) { + + if (should_force_update) { ssd_titlebar_update(ssd); } } @@ -309,7 +321,10 @@ ssd_titlebar_update(struct ssd *ssd) if (ssd->state.was_maximized != maximized || ssd->state.was_squared != squared) { - set_squared_corners(ssd, maximized || squared || theme->window[SSD_ACTIVE].title_bg.border_type || theme->window[SSD_INACTIVE].title_bg.border_type); + set_squared_corners(ssd, maximized || + squared || + theme->window[SSD_ACTIVE].title_bg.border_type || + theme->window[SSD_INACTIVE].title_bg.border_type); if (ssd->state.was_maximized != maximized) { set_alt_button_icon(ssd, LAB_NODE_BUTTON_MAXIMIZE, maximized); } @@ -337,7 +352,11 @@ ssd_titlebar_update(struct ssd *ssd) /* Center buttons vertically within titlebar */ int y = (theme->titlebar_height - theme->window_button_height) / 2; int x; - int bg_offset = (maximized || squared || theme->window[SSD_INACTIVE].title_bg.border_type || theme->window[SSD_ACTIVE].title_bg.border_type) ? 0 : corner_width; + int bg_offset = (maximized || + squared || + theme->window[SSD_INACTIVE].title_bg.border_type || + theme->window[SSD_ACTIVE].title_bg.border_type) + ? 0 : corner_width; enum ssd_active_state active; FOR_EACH_ACTIVE_STATE(active) { @@ -348,15 +367,13 @@ ssd_titlebar_update(struct ssd *ssd) x = theme->window_titlebar_padding_width; struct ssd_button *button; int button_count = 0; - - + wl_list_for_each(button, &subtree->buttons_left, link) { wlr_scene_node_set_position(button->node, x, y); x += theme->window_button_width + theme->window_button_spacing; - button_count++; + button_count++; } int exclusive_x = x; - x = width - corner_width; wlr_scene_node_set_position(&subtree->corner_right->node, @@ -368,19 +385,24 @@ ssd_titlebar_update(struct ssd *ssd) wlr_scene_node_set_position(button->node, x, y); button_count++; } - - + if (theme->window[active].title_bg.border_type) { int titlebar_x = 0; int titlebar_width = MAX(view->current.width, 0); if (theme->window[active].title_bg.exclusive) { titlebar_x = exclusive_x+theme->window_titlebar_padding_width; - titlebar_width = MAX((theme->window_button_width + theme->window_button_spacing)* button_count, titlebar_width - (theme->window_button_width + theme->window_button_spacing)* button_count); + titlebar_width = MAX( + (theme->window_button_width + theme->window_button_spacing) + * button_count, + titlebar_width - + (theme->window_button_width + theme->window_button_spacing) + * button_count + ); } - - renderBuffersetXY(subtree->texturedBorders, titlebar_width, theme->titlebar_height, titlebar_x, 0); + + renderBuffersetXY(subtree->texturedBorders, titlebar_width, + theme->titlebar_height, titlebar_x, 0); } - } ssd_update_title(ssd); diff --git a/src/theme.c b/src/theme.c index 51941227..59693f10 100644 --- a/src/theme.c +++ b/src/theme.c @@ -91,7 +91,7 @@ draw_hover_overlay_on_button(cairo_t *cairo, int w, int h) cairo_fill(cairo); } -static void draw_beveled_border_on_button(cairo_t* cairo, int w, int h, int active, int hover) +static void draw_beveled_border_on_button(cairo_t *cairo, int w, int h, int active, int hover) { if (rc.theme->window[active].button_border_type) { int bw = rc.theme->window[active].button_border_width; @@ -108,9 +108,13 @@ static void draw_beveled_border_on_button(cairo_t* cairo, int w, int h, int acti a = rc.theme->window[active].button_hover_border_color[3]; } - uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, rc.theme->window[active].button_border_type, rc.theme->window[active].button_bevel_width); - + uint32_t colour32 = (uint32_t)(a*255) << 24 | + (uint32_t)(r*255) << 16 | + (uint32_t)(g*255) << 8 | + (uint32_t)(b*255); + struct borderset *renderedborders = getBorders(colour32, bw, + rc.theme->window[active].button_border_type, + rc.theme->window[active].button_bevel_width); cairo_set_source_surface(cairo, renderedborders->top->surface, 0, 0); cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); @@ -122,21 +126,16 @@ static void draw_beveled_border_on_button(cairo_t* cairo, int w, int h, int acti cairo_rectangle(cairo, bw, h-bw, w-bw*2, bw); cairo_fill(cairo); - - cairo_set_source_surface(cairo, renderedborders->left->surface, 0, 0); cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); cairo_rectangle(cairo, 0, bw, bw, h-bw*2); cairo_fill(cairo); - cairo_set_source_surface(cairo, renderedborders->right->surface, w-bw, bw); cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); cairo_rectangle(cairo, w-bw, bw, bw, h-bw*2); cairo_fill(cairo); - - cairo_set_source_surface(cairo, renderedborders->tl->surface, 0, 0); cairo_rectangle(cairo, 0, 0, bw, bw); cairo_fill(cairo); @@ -175,8 +174,6 @@ static void draw_nonhover_inactive_border_on_button(cairo_t *cairo, int w, int h draw_beveled_border_on_button(cairo, w, h, SSD_INACTIVE, 0); } - - /* Round the buffer for the leftmost button in the titlebar */ static void round_left_corner_button(cairo_t *cairo, int w, int h) @@ -308,16 +305,15 @@ load_button(struct theme *theme, struct button *b, enum ssd_active_state active) draw_hover_overlay_on_button); } - if (theme->window[active].button_border_type) { if (active) { - if (b->state_set & LAB_BS_HOVERED) { + if (b->state_set & LAB_BS_HOVERED) { lab_img_add_modifier(*img, draw_hover_active_border_on_button); } else { lab_img_add_modifier(*img, draw_nonhover_active_border_on_button); } } else { - if (b->state_set & LAB_BS_HOVERED) { + if (b->state_set & LAB_BS_HOVERED) { lab_img_add_modifier(*img, draw_hover_inactive_border_on_button); } else { lab_img_add_modifier(*img, draw_nonhover_inactive_border_on_button); @@ -552,16 +548,24 @@ parse_hexstrs(const char *hexes, float colors[3][4]) g_strfreev(elements); } -static enum border_type parse_border_type(const char *str) { +static enum border_type parse_border_type(const char *str) +{ char *lower = g_ascii_strdown(str, -1); enum border_type border_type; - if (strstr(lower, "doublesunken")) border_type = BORDER_DOUBLE_INSET; - else if (strstr(lower, "sunken")) border_type = BORDER_INSET; - else if (strstr(lower, "doubleraised")) border_type = BORDER_DOUBLE; - else if (strstr(lower, "raised")) border_type = BORDER_SINGLE; - else if (strstr(lower, "flat")) border_type = BORDER_FLAT; - else border_type = BORDER_NONE; - + if (strstr(lower, "doublesunken")) { + border_type = BORDER_DOUBLE_INSET; + } else if (strstr(lower, "sunken")) { + border_type = BORDER_INSET; + } else if (strstr(lower, "doubleraised")) { + border_type = BORDER_DOUBLE; + } else if (strstr(lower, "raised")) { + border_type = BORDER_SINGLE; + } else if (strstr(lower, "flat")) { + border_type = BORDER_FLAT; + } else { + border_type = BORDER_NONE; + } + g_free(lower); return border_type; } @@ -678,17 +682,16 @@ theme_builtin(struct theme *theme) theme->window[SSD_INACTIVE].title_bg.border_width = 0; theme->window[SSD_INACTIVE].title_bg.exclusive = FALSE; theme->window[SSD_INACTIVE].title_bg.border_type = BORDER_NONE; - theme->window[SSD_ACTIVE].button_border_type=BORDER_NONE; - theme->window[SSD_ACTIVE].button_border_width=0; - theme->window[SSD_ACTIVE].button_bevel_width=0; + theme->window[SSD_ACTIVE].button_border_type = BORDER_NONE; + theme->window[SSD_ACTIVE].button_border_width = 0; + theme->window[SSD_ACTIVE].button_bevel_width = 0; theme->window[SSD_ACTIVE].button_border_color[0] = FLT_MIN; theme->window[SSD_ACTIVE].button_hover_border_color[0] = FLT_MIN; - theme->window[SSD_INACTIVE].button_border_type=BORDER_NONE; - theme->window[SSD_INACTIVE].button_border_width=0; - theme->window[SSD_INACTIVE].button_bevel_width=0; + theme->window[SSD_INACTIVE].button_border_type = BORDER_NONE; + theme->window[SSD_INACTIVE].button_border_width = 0; + theme->window[SSD_INACTIVE].button_bevel_width = 0; theme->window[SSD_INACTIVE].button_border_color[0] = FLT_MIN; theme->window[SSD_INACTIVE].button_hover_border_color[0] = FLT_MIN; - parse_hexstr("#000000", theme->window[SSD_ACTIVE].label_text_color); parse_hexstr("#000000", theme->window[SSD_INACTIVE].label_text_color); @@ -844,7 +847,7 @@ entry(struct theme *theme, const char *key, const char *value) theme->border_width = get_int_if_positive( value, "border.width"); } - + if (match_glob(key, "window.titlebar.padding.width")) { theme->window_titlebar_padding_width = get_int_if_positive( value, "window.titlebar.padding.width"); @@ -859,39 +862,43 @@ entry(struct theme *theme, const char *key, const char *value) if (match_glob(key, "padding.height")) { wlr_log(WLR_INFO, "padding.height is no longer supported"); } - + if (match_glob(key, "window.active.title.bg") && parse_border_type(value)) { - theme->window[SSD_ACTIVE].title_bg.border_type= parse_border_type(value); + theme->window[SSD_ACTIVE].title_bg.border_type = parse_border_type(value); } if (match_glob(key, "window.active.title.bg.width")) { - theme->window[SSD_ACTIVE].title_bg.border_width = get_int_if_positive(value, "window.active.title.bg.width"); + theme->window[SSD_ACTIVE].title_bg.border_width = + get_int_if_positive(value, "window.active.title.bg.width"); } - + if (match_glob(key, "window.active.title.bg.exclusive")) { set_bool(value, &theme->window[SSD_ACTIVE].title_bg.exclusive); } if (match_glob(key, "window.active.title.bg.bevel-width")) { - theme->window[SSD_ACTIVE].title_bg.bevel_width = get_int_if_positive(value, "window.active.title.bg.bevel-width"); + theme->window[SSD_ACTIVE].title_bg.bevel_width = + get_int_if_positive(value, "window.active.title.bg.bevel-width"); } if (match_glob(key, "window.active.border.color")) { parse_color(value, theme->window[SSD_ACTIVE].border_color); } - + if (match_glob(key, "window.active.border.type")) { theme->window[SSD_ACTIVE].border_type = parse_border_type(value); } if (match_glob(key, "window.active.border.bevel-width")) { - theme->window[SSD_ACTIVE].bevel_width = get_int_if_positive(value, "window.active.border.bevel-width"); + theme->window[SSD_ACTIVE].bevel_width = + get_int_if_positive(value, "window.active.border.bevel-width"); } - + if (match_glob(key, "window.inactive.border.color")) { parse_color(value, theme->window[SSD_INACTIVE].border_color); } - + if (match_glob(key, "window.inactive.border.bevel-width")) { - theme->window[SSD_INACTIVE].bevel_width = get_int_if_positive(value, "window.inactive.border.bevel-width"); + theme->window[SSD_INACTIVE].bevel_width = + get_int_if_positive(value, "window.inactive.border.bevel-width"); } - + if (match_glob(key, "window.inactive.border.type")) { theme->window[SSD_INACTIVE].border_type = parse_border_type(value); } @@ -908,22 +915,22 @@ entry(struct theme *theme, const char *key, const char *value) if (match_glob(key, "window.active.title.bg")) { theme->window[SSD_ACTIVE].title_bg.gradient = parse_gradient(value); } - - + if (match_glob(key, "window.inactive.title.bg") && parse_border_type(value)) { - theme->window[SSD_INACTIVE].title_bg.border_type= parse_border_type(value); + theme->window[SSD_INACTIVE].title_bg.border_type = parse_border_type(value); } if (match_glob(key, "window.inactive.title.bg.width")) { - theme->window[SSD_INACTIVE].title_bg.border_width = get_int_if_positive(value, "window.inactive.title.bg.width"); + theme->window[SSD_INACTIVE].title_bg.border_width = + get_int_if_positive(value, "window.inactive.title.bg.width"); } if (match_glob(key, "window.inactive.title.bg.bevel-width")) { - theme->window[SSD_INACTIVE].title_bg.bevel_width = get_int_if_positive(value, "window.inactive.title.bg.bevel-width"); + theme->window[SSD_INACTIVE].title_bg.bevel_width = + get_int_if_positive(value, "window.inactive.title.bg.bevel-width"); } if (match_glob(key, "window.inactive.title.bg.exclusive")) { set_bool(value, &theme->window[SSD_INACTIVE].title_bg.exclusive); } - - + if (match_glob(key, "window.inactive.title.bg")) { theme->window[SSD_INACTIVE].title_bg.gradient = parse_gradient(value); } @@ -984,43 +991,45 @@ entry(struct theme *theme, const char *key, const char *value) } if (match_glob(key, "window.inactive.button.bg") && parse_border_type(value)) { - theme->window[SSD_INACTIVE].button_border_type= parse_border_type(value); + theme->window[SSD_INACTIVE].button_border_type = parse_border_type(value); } if (match_glob(key, "window.inactive.button.bg.width")) { - theme->window[SSD_INACTIVE].button_border_width = get_int_if_positive(value, "window.inactive.button.bg.width"); + theme->window[SSD_INACTIVE].button_border_width = + get_int_if_positive(value, "window.inactive.button.bg.width"); } if (match_glob(key, "window.inactive.button.bg.bevel-width")) { - theme->window[SSD_INACTIVE].button_bevel_width = get_int_if_positive(value, "window.inactive.button.bg.bevel-width"); + theme->window[SSD_INACTIVE].button_bevel_width = + get_int_if_positive(value, "window.inactive.button.bg.bevel-width"); } - + if (match_glob(key, "window.inactive.button.bg.border-color")) { parse_color(value, theme->window[SSD_INACTIVE].button_border_color); } - + if (match_glob(key, "window.inactive.button.bg.border-hover-color")) { parse_color(value, theme->window[SSD_INACTIVE].button_hover_border_color); } - + if (match_glob(key, "window.active.button.bg") && parse_border_type(value)) { - theme->window[SSD_ACTIVE].button_border_type= parse_border_type(value); + theme->window[SSD_ACTIVE].button_border_type = parse_border_type(value); } if (match_glob(key, "window.active.button.bg.width")) { - theme->window[SSD_ACTIVE].button_border_width = get_int_if_positive(value, "window.active.button.bg.width"); + theme->window[SSD_ACTIVE].button_border_width = + get_int_if_positive(value, "window.active.button.bg.width"); } if (match_glob(key, "window.inactive.button.bg.bevel-width")) { - theme->window[SSD_ACTIVE].button_bevel_width = get_int_if_positive(value, "window.active.button.bg.bevel-width"); + theme->window[SSD_ACTIVE].button_bevel_width = + get_int_if_positive(value, "window.active.button.bg.bevel-width"); } - + if (match_glob(key, "window.active.button.bg.border-color")) { parse_color(value, theme->window[SSD_ACTIVE].button_border_color); } - + if (match_glob(key, "window.active.button.bg.border-hover-color")) { parse_color(value, theme->window[SSD_ACTIVE].button_hover_border_color); } - - - + /* botton hover overlay */ if (match_glob(key, "window.button.hover.bg.color")) { parse_color(value, theme->window_button_hover_bg_color); @@ -1142,10 +1151,10 @@ entry(struct theme *theme, const char *key, const char *value) theme->menu_border_type = parse_border_type(value); } if (match_glob(key, "menu.bg.bevel-width")) { - theme->menu_bevel_width = get_int_if_positive(value, "menu.bg.bevel-width"); + theme->menu_bevel_width = + get_int_if_positive(value, "menu.bg.bevel-width"); } - - + if (match_glob(key, "menu.items.padding.x")) { theme->menu_items_padding_x = get_int_if_positive( value, "menu.items.padding.x"); @@ -1161,9 +1170,10 @@ entry(struct theme *theme, const char *key, const char *value) theme->menu_items_border_type = parse_border_type(value); } if (match_glob(key, "menu.items.bg.bevel-width")) { - theme->menu_items_bevel_width = get_int_if_positive(value, "menu.items.bg.bevel-width"); + theme->menu_items_bevel_width = + get_int_if_positive(value, "menu.items.bg.bevel-width"); } - + if (match_glob(key, "menu.items.text.color")) { parse_color(value, theme->menu_items_text_color); } @@ -1173,14 +1183,14 @@ entry(struct theme *theme, const char *key, const char *value) if (match_glob(key, "menu.items.active.text.color")) { parse_color(value, theme->menu_items_active_text_color); } - + if (match_glob(key, "menu.items.active.bg")) { theme->menu_items_active_border_type = parse_border_type(value); } if (match_glob(key, "menu.items.active.bg.bevel-width")) { - theme->menu_items_active_bevel_width = get_int_if_positive(value, "menu.items.active.bg.bevel-width"); + theme->menu_items_active_bevel_width = + get_int_if_positive(value, "menu.items.active.bg.bevel-width"); } - if (match_glob(key, "menu.separator.width")) { theme->menu_separator_line_thickness = get_int_if_positive( @@ -1207,14 +1217,14 @@ entry(struct theme *theme, const char *key, const char *value) if (match_glob(key, "menu.title.text.color")) { parse_color(value, theme->menu_title_text_color); } - + if (match_glob(key, "menu.title.bg")) { theme->menu_title_border_type = parse_border_type(value); } if (match_glob(key, "menu.title.bg.bevel-width")) { - theme->menu_title_bevel_width = get_int_if_positive(value, "menu.title.bg.bevel-width"); + theme->menu_title_bevel_width = + get_int_if_positive(value, "menu.title.bg.bevel-width"); } - if (match_glob(key, "osd.bg.color")) { parse_color(value, theme->osd_bg_color); @@ -1226,7 +1236,7 @@ entry(struct theme *theme, const char *key, const char *value) if (match_glob(key, "osd.border.color")) { parse_color(value, theme->osd_border_color); } - + if (match_glob(key, "osd.bg")) { theme->osd_border_type = parse_border_type(value); } diff --git a/src/workspaces.c b/src/workspaces.c index 207d8e4c..7c089c2b 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -101,18 +101,22 @@ _osd_update(void) /* Background */ set_cairo_color(cairo, theme->osd_bg_color); cairo_rectangle(cairo, bw, bw, width-bw*2, height-bw*2); - cairo_fill(cairo); + cairo_fill(cairo); /* Border */ - if (theme->osd_border_type) { + if (theme->osd_border_type) { float r = theme->osd_border_color[0]; float g = theme->osd_border_color[1]; float b = theme->osd_border_color[2]; float a = theme->osd_border_color[3]; - uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset * renderedborders = getBorders(colour32, bw, theme->osd_border_type, theme->osd_border_bevel_width); - + uint32_t colour32 = (uint32_t)(a*255) << 24 | + (uint32_t)(r*255) << 16 | + (uint32_t)(g*255) << 8 | + (uint32_t)(b*255); + struct borderset *renderedborders = getBorders(colour32, bw, + theme->osd_border_type, theme->osd_border_bevel_width); + cairo_set_source_surface(cairo, renderedborders->top->surface, 0, 0); cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); cairo_rectangle(cairo, bw, 0, width-bw*2, bw); @@ -122,22 +126,17 @@ _osd_update(void) cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); cairo_rectangle(cairo, bw, height-bw, width-bw*2, bw); cairo_fill(cairo); - - - + cairo_set_source_surface(cairo, renderedborders->left->surface, 0, 0); cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); cairo_rectangle(cairo, 0, bw, bw, height-bw*2); cairo_fill(cairo); - - + cairo_set_source_surface(cairo, renderedborders->right->surface, 0, 0); cairo_pattern_set_extend(cairo_get_source(cairo), CAIRO_EXTEND_REPEAT); cairo_rectangle(cairo, width-bw, bw, bw, height-bw*2); cairo_fill(cairo); - - - + cairo_set_source_surface(cairo, renderedborders->tl->surface, 0, 0); cairo_rectangle(cairo, 0, 0, bw, bw); cairo_fill(cairo); @@ -145,16 +144,17 @@ _osd_update(void) cairo_set_source_surface(cairo, renderedborders->tr->surface, width-bw, 0); cairo_rectangle(cairo, width - bw, 0, bw, bw); cairo_fill(cairo); - - cairo_set_source_surface(cairo, renderedborders->bl->surface, 0, height - bw); + + cairo_set_source_surface(cairo, renderedborders->bl->surface, + 0, height - bw); cairo_rectangle(cairo, 0, height - bw, bw, bw); cairo_fill(cairo); - - cairo_set_source_surface(cairo, renderedborders->br->surface, width - bw, height -bw); + + cairo_set_source_surface(cairo, renderedborders->br->surface, + width - bw, height -bw); cairo_rectangle(cairo, width - bw, height - bw, bw, bw); cairo_fill(cairo); - - + set_cairo_color(cairo, theme->osd_border_color); } else { set_cairo_color(cairo, theme->osd_border_color); @@ -165,7 +165,6 @@ _osd_update(void) draw_cairo_border(cairo, border_fbox, theme->osd_border_width); } - /* Boxes */ uint16_t x; if (!hide_boxes) { From 8997f35607e9f618f6f4d8a6ff8b70c007540500 Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sun, 5 Apr 2026 17:57:15 -0700 Subject: [PATCH 45/47] Rename camelcase names --- include/common/borderset.h | 10 +++++----- include/ssd-internal.h | 4 ++-- include/view.h | 2 +- src/common/borderset.c | 20 ++++++++++---------- src/common/lab-scene-rect.c | 12 ++++++------ src/main.c | 2 +- src/menu/menu.c | 12 ++++++------ src/server.c | 4 ++-- src/ssd/resize-indicator.c | 8 ++++---- src/ssd/ssd-border.c | 6 +++--- src/ssd/ssd-titlebar.c | 8 ++++---- src/theme.c | 2 +- src/workspaces.c | 2 +- 13 files changed, 46 insertions(+), 46 deletions(-) diff --git a/include/common/borderset.h b/include/common/borderset.h index c9d7248f..d4016d8c 100644 --- a/include/common/borderset.h +++ b/include/common/borderset.h @@ -43,19 +43,19 @@ struct bufferset { }; -extern struct borderset *borderCache; +extern struct borderset *border_cache; -struct borderset *getBorders(uint32_t id, int size, enum border_type, int bevelSize); +struct borderset *get_borders(uint32_t id, int size, enum border_type, int bevelSize); -struct borderset *createBuffer(uint32_t id, int size, enum border_type, int bevelSize); +struct borderset *create_buffer(uint32_t id, int size, enum border_type, int bevelSize); -struct bufferset *generateBufferset(struct wlr_scene_tree *tree, +struct bufferset *generate_bufferset(struct wlr_scene_tree *tree, struct borderset *borderset, int bw); void renderBufferset(struct bufferset *bufferset, int width, int height, int y); void renderBuffersetXY(struct bufferset *bufferset, int width, int height, int x, int y); -void clearBorderCache(struct borderset *borderset); +void clearborder_cache(struct borderset *borderset); #endif /* LABWC_BORDERSET_H */ diff --git a/include/ssd-internal.h b/include/ssd-internal.h index 776fba34..38280582 100644 --- a/include/ssd-internal.h +++ b/include/ssd-internal.h @@ -106,7 +106,7 @@ struct ssd { struct scaled_font_buffer *title; struct wl_list buttons_left; /* ssd_button.link */ struct wl_list buttons_right; /* ssd_button.link */ - struct bufferset *texturedBorders; + struct bufferset *textured_borders; } subtrees[2]; /* indexed by enum ssd_active_state */ } titlebar; @@ -116,7 +116,7 @@ struct ssd { struct ssd_border_subtree { struct wlr_scene_tree *tree; struct wlr_scene_rect *top, *bottom, *left, *right; - struct bufferset *texturedBorders; + struct bufferset *textured_borders; } subtrees[2]; /* indexed by enum ssd_active_state */ } border; diff --git a/include/view.h b/include/view.h index a2acaa95..6c6dc795 100644 --- a/include/view.h +++ b/include/view.h @@ -244,7 +244,7 @@ struct view { int width, height; struct wlr_scene_tree *tree; struct wlr_scene_rect *border; - struct bufferset *texturedBorders; + struct bufferset *textured_borders; struct wlr_scene_rect *background; struct scaled_font_buffer *text; } resize_indicator; diff --git a/src/common/borderset.c b/src/common/borderset.c index e06c39b3..1c6f8962 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -6,9 +6,9 @@ #include "common/macros.h" #include "buffer.h" -struct borderset *getBorders(uint32_t id, int size, enum border_type type, int bevelSize) +struct borderset *get_borders(uint32_t id, int size, enum border_type type, int bevelSize) { - struct borderset *current = borderCache; + struct borderset *current = border_cache; struct borderset *last; // Preventing building nonsense borders: @@ -40,17 +40,17 @@ struct borderset *getBorders(uint32_t id, int size, enum border_type type, int b } // Fall through, we need to create a buffer. - if (!borderCache) { - borderCache = createBuffer(id, size, type, bevelSize); - return borderCache; + if (!border_cache) { + border_cache = create_buffer(id, size, type, bevelSize); + return border_cache; } else { - last->next = createBuffer(id, size, type, bevelSize); + last->next = create_buffer(id, size, type, bevelSize); return last->next; } return NULL; } -struct borderset *createBuffer(uint32_t id, int size, enum border_type type, int bevelSize) +struct borderset *create_buffer(uint32_t id, int size, enum border_type type, int bevelSize) { struct borderset *new_borderset = znew(*new_borderset); @@ -270,7 +270,7 @@ struct borderset *createBuffer(uint32_t id, int size, enum border_type type, int return new_borderset; } -struct bufferset *generateBufferset(struct wlr_scene_tree *tree, +struct bufferset *generate_bufferset(struct wlr_scene_tree *tree, struct borderset *borderset, int bw) { struct bufferset *bufferset = znew(struct bufferset); @@ -346,13 +346,13 @@ void renderBuffersetXY(struct bufferset *bufferset, int width, int height, int x x, height-bufferset->border_width+y); } -void clearBorderCache(struct borderset *borderset) +void clearborder_cache(struct borderset *borderset) { if (!borderset) { return; } if (borderset->next) { - clearBorderCache(borderset->next); + clearborder_cache(borderset->next); } wlr_buffer_drop(&borderset->top->base); wlr_buffer_drop(&borderset->left->base); diff --git a/src/common/lab-scene-rect.c b/src/common/lab-scene-rect.c index 8ad48a28..ad5c4cf7 100644 --- a/src/common/lab-scene-rect.c +++ b/src/common/lab-scene-rect.c @@ -12,7 +12,7 @@ struct border_scene { struct wlr_scene_tree *tree; struct wlr_scene_rect *top, *bottom, *left, *right; - struct bufferset *texturedBorders; + struct bufferset *textured_borders; }; static void @@ -58,12 +58,12 @@ lab_scene_rect_create(struct wlr_scene_tree *parent, (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset *renderedborders = getBorders(colour32, bw, + struct borderset *renderedborders = get_borders(colour32, bw, opts->border_type, opts->bevel_width); - border->texturedBorders = generateBufferset(border->tree, + border->textured_borders = generate_bufferset(border->tree, renderedborders, bw); } else { - border->texturedBorders = NULL; + border->textured_borders = NULL; } } @@ -105,8 +105,8 @@ resize_border(struct border_scene *border, int border_width, int width, int heig 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); - if (border->texturedBorders) { - renderBufferset(border->texturedBorders, width, height, 0); + if (border->textured_borders) { + renderBufferset(border->textured_borders, width, height, 0); } } diff --git a/src/main.c b/src/main.c index f25c48c2..0534b542 100644 --- a/src/main.c +++ b/src/main.c @@ -41,7 +41,7 @@ static const struct option long_options[] = { {0, 0, 0, 0} }; -struct borderset *borderCache; +struct borderset *border_cache; static const char labwc_usage[] = "Usage: labwc [options...]\n" diff --git a/src/menu/menu.c b/src/menu/menu.c index 188bba12..24958304 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -205,10 +205,10 @@ item_create_scene_for_state(struct menuitem *item, float *text_color, (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset *renderedborders = getBorders(colour32, bw, + struct borderset *renderedborders = get_borders(colour32, bw, rc.theme->menu_items_active_border_type, rc.theme->menu_items_active_bevel_width); - bufferset = generateBufferset(tree, renderedborders, bw); + bufferset = generate_bufferset(tree, renderedborders, bw); } else if (rc.theme->menu_items_border_type && !state) { float r = bg_color[0]; float g = bg_color[1]; @@ -219,10 +219,10 @@ item_create_scene_for_state(struct menuitem *item, float *text_color, (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset *renderedborders = getBorders(colour32, bw, + struct borderset *renderedborders = get_borders(colour32, bw, rc.theme->menu_items_border_type, rc.theme->menu_items_bevel_width); - bufferset = generateBufferset(tree, renderedborders, bw); + bufferset = generate_bufferset(tree, renderedborders, bw); } /* Create icon */ @@ -408,10 +408,10 @@ title_create_scene(struct menuitem *menuitem, int *item_y) (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset *renderedborders = getBorders(colour32, bw, + struct borderset *renderedborders = get_borders(colour32, bw, rc.theme->menu_title_border_type, rc.theme->menu_title_bevel_width); - bufferset = generateBufferset(menuitem->tree, renderedborders, bw); + bufferset = generate_bufferset(menuitem->tree, renderedborders, bw); } /* Background */ diff --git a/src/server.c b/src/server.c index 8af35e4a..a25ed300 100644 --- a/src/server.c +++ b/src/server.c @@ -90,8 +90,8 @@ reload_config_and_theme(void) scaled_buffer_invalidate_sharing(); rcxml_finish(); - clearBorderCache(borderCache); - borderCache = NULL; + clearborder_cache(border_cache); + border_cache = NULL; rcxml_read(rc.config_file); theme_finish(rc.theme); diff --git a/src/ssd/resize-indicator.c b/src/ssd/resize-indicator.c index 8f2105d8..8f17e3e8 100644 --- a/src/ssd/resize-indicator.c +++ b/src/ssd/resize-indicator.c @@ -50,9 +50,9 @@ resize_indicator_reconfigure_view(struct resize_indicator *indicator) (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset *renderedborders = getBorders(colour32, bw, theme->osd_border_type, - theme->osd_border_bevel_width); - indicator->texturedBorders = generateBufferset(indicator->tree, + struct borderset *renderedborders = get_borders(colour32, bw, + theme->osd_border_type, theme->osd_border_bevel_width); + indicator->textured_borders = generate_bufferset(indicator->tree, renderedborders, bw); } } @@ -141,7 +141,7 @@ resize_indicator_set_size(struct resize_indicator *indicator, int width) indicator->height - 2 * rc.theme->osd_border_width); if (rc.theme->osd_border_type) { - renderBufferset(indicator->texturedBorders, indicator->width, + renderBufferset(indicator->textured_borders, indicator->width, indicator->height, 0); } } diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index 69d3e569..8885b0d1 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -55,10 +55,10 @@ ssd_border_create(struct ssd *ssd) (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset *renderedborders = getBorders(colour32, bw, + struct borderset *renderedborders = get_borders(colour32, bw, theme->window[active].border_type, theme->window[active].bevel_width); - subtree->texturedBorders = generateBufferset(subtree->tree, + subtree->textured_borders = generate_bufferset(subtree->tree, renderedborders, bw); } else { subtree->left = lab_wlr_scene_rect_create(parent, @@ -159,7 +159,7 @@ ssd_border_update(struct ssd *ssd) FOR_EACH_ACTIVE_STATE(active) { struct ssd_border_subtree *subtree = &ssd->border.subtrees[active]; if (theme->window[active].border_type) { - renderBufferset(subtree->texturedBorders, full_width, + renderBufferset(subtree->textured_borders, full_width, side_height+(ssd->titlebar.height + 2*theme->border_width), -ssd->titlebar.height-theme->border_width); } else { diff --git a/src/ssd/ssd-titlebar.c b/src/ssd/ssd-titlebar.c index 7575b841..9b2aa9dc 100644 --- a/src/ssd/ssd-titlebar.c +++ b/src/ssd/ssd-titlebar.c @@ -66,12 +66,12 @@ ssd_titlebar_create(struct ssd *ssd) (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset *renderedborders = getBorders(colour32, + struct borderset *renderedborders = get_borders(colour32, theme->window[active].title_bg.border_width, theme->window[active].title_bg.border_type, theme->window[active].title_bg.bevel_width); - subtree->texturedBorders = generateBufferset(subtree->tree, renderedborders, - theme->window[active].title_bg.border_width); + subtree->textured_borders = generate_bufferset(subtree->tree, + renderedborders, theme->window[active].title_bg.border_width); // If we have the beveled borders, we actually have to run // ssd_titlebar_update() to make sure we render the updated borders. @@ -400,7 +400,7 @@ ssd_titlebar_update(struct ssd *ssd) ); } - renderBuffersetXY(subtree->texturedBorders, titlebar_width, + renderBuffersetXY(subtree->textured_borders, titlebar_width, theme->titlebar_height, titlebar_x, 0); } } diff --git a/src/theme.c b/src/theme.c index 59693f10..3fa9600a 100644 --- a/src/theme.c +++ b/src/theme.c @@ -112,7 +112,7 @@ static void draw_beveled_border_on_button(cairo_t *cairo, int w, int h, int acti (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset *renderedborders = getBorders(colour32, bw, + struct borderset *renderedborders = get_borders(colour32, bw, rc.theme->window[active].button_border_type, rc.theme->window[active].button_bevel_width); diff --git a/src/workspaces.c b/src/workspaces.c index 7c089c2b..892f95ff 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -114,7 +114,7 @@ _osd_update(void) (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255); - struct borderset *renderedborders = getBorders(colour32, bw, + struct borderset *renderedborders = get_borders(colour32, bw, theme->osd_border_type, theme->osd_border_bevel_width); cairo_set_source_surface(cairo, renderedborders->top->surface, 0, 0); From 308a3291cb7d490ee3153b52e8d2ad14f08eeeca Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sun, 5 Apr 2026 18:02:50 -0700 Subject: [PATCH 46/47] Remove attempt to reuse code with switch fallthrough --- src/common/borderset.c | 120 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 2 deletions(-) diff --git a/src/common/borderset.c b/src/common/borderset.c index 1c6f8962..59d9827c 100644 --- a/src/common/borderset.c +++ b/src/common/borderset.c @@ -106,7 +106,29 @@ struct borderset *create_buffer(uint32_t id, int size, enum border_type type, in temp = ll32; ll32 = hl32; hl32 = temp; - // Fall throgh intentional + + top = znew(uint32_t); + left = znew(uint32_t); + right = znew(uint32_t); + bottom = znew(uint32_t); + side_size = 1; + *top = hl32; + *left = hl32; + *right = ll32; + *bottom = ll32; + + // Fill with solid + for (int j = 0; j < size; j++) { + for (int k = 0; k < size; k++) { + tl[PIXEL(j, k, size)] = hl32; + tr[PIXEL(size - 1 - j, k, size)] = (j > k) ? hl32 : ll32; + bl[PIXEL(size - 1 -j, k, size)] = (j > k) ? hl32 : ll32; + br[PIXEL(j, k, size)] = ll32; + } + } + + break; + case BORDER_SINGLE: // Single bevel borders have 1x1 sides top = znew(uint32_t); left = znew(uint32_t); @@ -134,7 +156,101 @@ struct borderset *create_buffer(uint32_t id, int size, enum border_type type, in temp = ll32; ll32 = hl32; hl32 = temp; - // Fall throgh intentional + top = znew_n(uint32_t, size); + left = znew_n(uint32_t, size); + right = znew_n(uint32_t, size); + bottom = znew_n(uint32_t, size); + side_size = size; + + for (int i = 0; i < size; i++) { + if (i < bevelSize) { + left[i] = hl32; + top[i] = hl32; + right[i] = hl32; + bottom[i] = hl32; + + } else if (i > (size-bevelSize-1)) { + left[i] = ll32; + top[i] = ll32; + right[i] = ll32; + bottom[i] = ll32; + + } else { + left[i] = id; + top[i] = id; + right[i] = id; + bottom[i] = id; + } + } + + // Blank corners... + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + tl[PIXEL(i, j, size)] = id; + tr[PIXEL(i, j, size)] = id; + bl[PIXEL(i, j, size)] = id; + br[PIXEL(i, j, size)] = id; + } + } + + // Main Corners + for (int i = 0; i < bevelSize; i++) { + // Solid bar parts + for (int j = 0; j < size; j++) { + // Top left corner: Entire "bevel size" top rows are highlighted + tl[PIXEL(j, i, size)] = hl32; + // First "bevel size" top columns are highlighted + tl[PIXEL(i, j, size)] = hl32; + + // Bottom Right corner: Entire "bevel size" last rows are lowlight + br[PIXEL(j, (size-1-i), size)] = ll32; + // Last "bevel size" columns are lowlight + br[PIXEL((size-1-i), j, size)] = ll32; + + // Bottom left corner: Entire "bevel size" last rows are lowlight + bl[PIXEL(j, (size-1-i), size)] = ll32; + // First "bevel size" columns are highlight, except for + // the bottom right corner + bl[PIXEL(i, j, size)] = hl32; + + // Top Right corner: Entire "bevel size" first rows are highlight + tr[PIXEL(j, i, size)] = hl32; + // Last "bevel size" columns are lowlight, except for the top left + tr[PIXEL((size-1-i), j, size)] = ll32; + } + } + // Beveled Corner Parts + for (int i = 0; i < bevelSize; i++) { + for (int j = 0; j < bevelSize; j++) { + // Outer Corners + // Bottom left corner: + // First "bevel size" columns are highlight, except + // for the bottom right corner + bl[PIXEL(i, (size - 1 - j), size)] = (j >= i) ? hl32 : ll32; + + // Top Right corner: + // Last "bevel size" columns are lowlight, except for the top left + tr[PIXEL((size-1-i), j, size)] = (j > i) ? ll32 : hl32; + + // Inner Corners + // Top left corner: Bottom right is all dark + tl[PIXEL((size-1-i), (size - 1 - j), size)] = ll32; + + // Bottom Right corner: Top left is all light + br[PIXEL(i, j, size)] = hl32; + + // Top Right corner: + // Interior bottom left is dark on top, light on bottom + tr[PIXEL(i, (size-1-j), size)] = (i > j) ? hl32 : ll32; + + // Bottom Left corner: + // Interior top right is dark on top, light on bottom + bl[PIXEL((size-1-i), j, size)] = (i > j) ? ll32 : hl32; + } + } + + break; + case BORDER_DOUBLE: top = znew_n(uint32_t, size); left = znew_n(uint32_t, size); From 25916610051ff687b5ba3e880121dd73a34038fb Mon Sep 17 00:00:00 2001 From: Jack Zeal Date: Sun, 5 Apr 2026 18:07:25 -0700 Subject: [PATCH 47/47] Guard for possible null menu buffer Guard for possible null menu buffer, attempt 2 --- src/menu/menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/menu/menu.c b/src/menu/menu.c index 24958304..61d9caf7 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -376,7 +376,7 @@ title_create_scene(struct menuitem *menuitem, int *item_y) assert(menuitem->type == LAB_MENU_TITLE); struct menu *menu = menuitem->parent; struct theme *theme = rc.theme; - struct bufferset *bufferset; + struct bufferset *bufferset = NULL; float *bg_color = theme->menu_title_bg_color; float *text_color = theme->menu_title_text_color; @@ -443,7 +443,7 @@ title_create_scene(struct menuitem *menuitem, int *item_y) wlr_scene_node_set_position(&title_font_buffer->scene_buffer->node, title_x, title_y); - if (rc.theme->menu_title_border_type) { + if (bufferset && rc.theme->menu_title_border_type) { renderBufferset(bufferset, bg_width, theme->menu_item_height, 0); } error: