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();