This commit is contained in:
John Lindgren 2026-03-15 14:28:27 +01:00 committed by GitHub
commit 0e81b071c5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 147 additions and 14 deletions

View file

@ -114,7 +114,7 @@ struct ssd {
struct wlr_scene_tree *tree;
struct ssd_border_subtree {
struct wlr_scene_tree *tree;
struct wlr_scene_rect *top, *bottom, *left, *right;
struct wlr_scene_buffer *top, *bottom, *left, *right;
} subtrees[2]; /* indexed by enum ssd_active_state */
} border;

View file

@ -14,6 +14,11 @@
struct lab_img;
/* XXX: using fixed border widths for now */
/* (top is narrower to blend with titlebar) */
#define BORDER_PX_TOP 2
#define BORDER_PX_SIDE 4
/*
* Openbox defines 7 types of Gradient background in addition to Solid.
* Currently, labwc supports only Vertical and SplitVertical.

View file

@ -2,7 +2,9 @@
#include <assert.h>
#include <wlr/types/wlr_scene.h>
#include "buffer.h"
#include "common/macros.h"
#include "common/mem.h"
#include "labwc.h"
#include "ssd.h"
#include "ssd-internal.h"
@ -17,13 +19,19 @@ ssd_border_create(struct ssd *ssd)
struct view *view = ssd->view;
struct theme *theme = view->server->theme;
#if 0
/* XXX: not using with textured borders */
int width = view->current.width;
int height = view_effective_height(view, /* use_pending */ false);
int full_width = width + 2 * theme->border_width;
int corner_width = ssd_get_corner_width();
#endif
ssd->border.tree = wlr_scene_tree_create(ssd->tree);
#if 0
/* XXX: eliminated this offset */
wlr_scene_node_set_position(&ssd->border.tree->node, -theme->border_width, 0);
#endif
enum ssd_active_state active;
FOR_EACH_ACTIVE_STATE(active) {
@ -31,8 +39,10 @@ ssd_border_create(struct ssd *ssd)
subtree->tree = wlr_scene_tree_create(ssd->border.tree);
struct wlr_scene_tree *parent = subtree->tree;
wlr_scene_node_set_enabled(&parent->node, active);
float *color = theme->window[active].border_color;
float *color = theme->window[active].title_bg.color;
#if 0
/* XXX: old solid color borders */
subtree->left = wlr_scene_rect_create(parent,
theme->border_width, height, color);
wlr_scene_node_set_position(&subtree->left->node, 0, 0);
@ -52,8 +62,79 @@ 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));
#endif
uint8_t r = color[0] * 255;
uint8_t g = color[1] * 255;
uint8_t b = color[2] * 255;
uint8_t a = color[3] * 255;
/* darker outline */
uint8_t r0 = r / 2;
uint8_t g0 = g / 2;
uint8_t b0 = b / 2;
/* 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);
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;
/* top and left start out the same */
uint32_t *left_data = znew_n(uint32_t, BORDER_PX_SIDE);
uint32_t *top_data = znew_n(uint32_t, BORDER_PX_TOP);
left_data[0] = top_data[0] = col0;
left_data[1] = top_data[1] = col1;
for (int i = 2; i < BORDER_PX_SIDE; i++) {
left_data[i] = col;
}
for (int i = 2; i < BORDER_PX_TOP; i++) {
top_data[i] = col;
}
/* bottom and right are identical */
uint32_t *right_data = znew_n(uint32_t, BORDER_PX_SIDE);
uint32_t *bottom_data = znew_n(uint32_t, BORDER_PX_SIDE);
for (int i = 0; i < BORDER_PX_SIDE - 1; i++) {
right_data[i] = col;
bottom_data[i] = col;
}
right_data[BORDER_PX_SIDE - 1] = col0;
bottom_data[BORDER_PX_SIDE - 1] = col0;
/* order matters here since the border overlap */
struct lab_data_buffer *bottom_buffer =
buffer_create_from_data(bottom_data, 1, BORDER_PX_SIDE, 4);
subtree->bottom = wlr_scene_buffer_create(parent, &bottom_buffer->base);
wlr_buffer_drop(&bottom_buffer->base);
struct lab_data_buffer *right_buffer =
buffer_create_from_data(right_data, BORDER_PX_SIDE, 1,
4 * BORDER_PX_SIDE);
subtree->right = wlr_scene_buffer_create(parent, &right_buffer->base);
wlr_buffer_drop(&right_buffer->base);
struct lab_data_buffer *left_buffer =
buffer_create_from_data(left_data, BORDER_PX_SIDE, 1,
4 * BORDER_PX_SIDE);
subtree->left = wlr_scene_buffer_create(parent, &left_buffer->base);
wlr_buffer_drop(&left_buffer->base);
struct lab_data_buffer *top_buffer =
buffer_create_from_data(top_data, 1, BORDER_PX_TOP, 4);
subtree->top = wlr_scene_buffer_create(parent, &top_buffer->base);
wlr_buffer_drop(&top_buffer->base);
}
/* Lower textured borders below titlebar for overlap */
wlr_scene_node_lower_to_bottom(&ssd->border.tree->node);
if (view->maximized == VIEW_AXIS_BOTH) {
wlr_scene_node_set_enabled(&ssd->border.tree->node, false);
}
@ -89,10 +170,10 @@ ssd_border_update(struct ssd *ssd)
ssd->margin = ssd_thickness(ssd->view);
}
struct theme *theme = view->server->theme;
int width = view->current.width;
int height = view_effective_height(view, /* use_pending */ false);
#if 0
/* XXX: ignoring lots of possible cases */
int full_width = width + 2 * theme->border_width;
int corner_width = ssd_get_corner_width();
@ -127,11 +208,19 @@ ssd_border_update(struct ssd *ssd)
int top_x = ssd->titlebar.height <= 0 || ssd->state.was_squared
? 0
: theme->border_width + corner_width;
#endif
int title_h = ssd->titlebar.height;
int side_y = -title_h - (BORDER_PX_TOP - 1);
int side_height = title_h + height + (BORDER_PX_TOP - 1) + (BORDER_PX_SIDE - 1);
int top_x = -(BORDER_PX_SIDE - 1);
int top_width = width + 2 * (BORDER_PX_SIDE - 1);
enum ssd_active_state active;
FOR_EACH_ACTIVE_STATE(active) {
struct ssd_border_subtree *subtree = &ssd->border.subtrees[active];
#if 0
/* XXX: old solid color borders */
wlr_scene_rect_set_size(subtree->left,
theme->border_width, side_height);
wlr_scene_node_set_position(&subtree->left->node,
@ -151,6 +240,27 @@ ssd_border_update(struct ssd *ssd)
top_width, theme->border_width);
wlr_scene_node_set_position(&subtree->top->node,
top_x, -(ssd->titlebar.height + theme->border_width));
#endif
wlr_scene_node_set_position(&subtree->left->node,
-BORDER_PX_SIDE, side_y);
wlr_scene_buffer_set_dest_size(subtree->left,
BORDER_PX_SIDE, side_height);
wlr_scene_node_set_position(&subtree->right->node,
width, side_y);
wlr_scene_buffer_set_dest_size(subtree->right,
BORDER_PX_SIDE, side_height);
wlr_scene_node_set_position(&subtree->bottom->node,
top_x, height);
wlr_scene_buffer_set_dest_size(subtree->bottom,
top_width, BORDER_PX_SIDE);
wlr_scene_node_set_position(&subtree->top->node,
top_x, -title_h - BORDER_PX_TOP);
wlr_scene_buffer_set_dest_size(subtree->top,
top_width, BORDER_PX_TOP);
}
}

View file

@ -29,6 +29,7 @@ ssd_titlebar_create(struct ssd *ssd)
struct view *view = ssd->view;
struct theme *theme = view->server->theme;
int width = view->current.width;
bool maximized = view->maximized == VIEW_AXIS_BOTH;
int corner_width = ssd_get_corner_width();
ssd->titlebar.tree = wlr_scene_tree_create(ssd->tree);
@ -62,7 +63,10 @@ ssd_titlebar_create(struct ssd *ssd)
wlr_scene_buffer_set_filter_mode(
subtree->bar, WLR_SCALE_FILTER_NEAREST);
}
wlr_scene_node_set_position(&subtree->bar->node, corner_width, 0);
int overlap = maximized ? 0 : BORDER_PX_SIDE - 2;
wlr_scene_node_set_position(&subtree->bar->node, -overlap, 0);
wlr_scene_buffer_set_dest_size(subtree->bar,
width + 2 * overlap, theme->titlebar_height);
subtree->corner_left = wlr_scene_buffer_create(parent, corner_top_left);
wlr_scene_node_set_position(&subtree->corner_left->node,
@ -113,7 +117,6 @@ ssd_titlebar_create(struct ssd *ssd)
ssd_update_title(ssd);
bool maximized = view->maximized == VIEW_AXIS_BOTH;
bool squared = ssd_should_be_squared(ssd);
if (maximized) {
set_alt_button_icon(ssd, LAB_NODE_BUTTON_MAXIMIZE, true);
@ -157,20 +160,25 @@ update_button_state(struct ssd_button *button, enum lab_button_state state,
static void
set_squared_corners(struct ssd *ssd, bool enable)
{
#if 0
struct view *view = ssd->view;
int width = view->current.width;
int corner_width = ssd_get_corner_width();
struct theme *theme = view->server->theme;
int x = enable ? 0 : corner_width;
#endif
enum ssd_active_state active;
FOR_EACH_ACTIVE_STATE(active) {
struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active];
#if 0
/* XXX: conflicts with overlap of textured borders */
wlr_scene_node_set_position(&subtree->bar->node, x, 0);
wlr_scene_buffer_set_dest_size(subtree->bar,
MAX(width - 2 * x, 0), theme->titlebar_height);
#endif
wlr_scene_node_set_enabled(&subtree->corner_left->node, !enable);
@ -284,7 +292,6 @@ ssd_titlebar_update(struct ssd *ssd)
if (ssd->state.was_maximized != maximized) {
set_alt_button_icon(ssd, LAB_NODE_BUTTON_MAXIMIZE, maximized);
}
ssd->state.was_maximized = maximized;
ssd->state.was_squared = squared;
}
@ -299,22 +306,25 @@ ssd_titlebar_update(struct ssd *ssd)
ssd->state.was_omnipresent = view->visible_on_all_workspaces;
}
if (width == ssd->state.geometry.width) {
if (ssd->state.was_maximized == maximized
&& ssd->state.geometry.width == width) {
return;
}
ssd->state.was_maximized = maximized;
update_visible_buttons(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;
enum ssd_active_state active;
FOR_EACH_ACTIVE_STATE(active) {
struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active];
int overlap = maximized ? 0 : BORDER_PX_SIDE - 2;
wlr_scene_node_set_position(&subtree->bar->node, -overlap, 0);
wlr_scene_buffer_set_dest_size(subtree->bar,
MAX(width - bg_offset * 2, 0), theme->titlebar_height);
width + 2 * overlap, theme->titlebar_height);
x = theme->window_titlebar_padding_width;
struct ssd_button *button;
@ -512,10 +522,15 @@ ssd_update_hovered_button(struct server *server, struct wlr_scene_node *node)
bool
ssd_should_be_squared(struct ssd *ssd)
{
#if 1
/* XXX: force squared corners with textured borders */
return true;
#else
struct view *view = ssd->view;
int corner_width = ssd_get_corner_width();
return (view_is_tiled_and_notify_tiled(view)
|| view->current.width < corner_width * 2)
&& view->maximized != VIEW_AXIS_BOTH;
#endif
}

View file

@ -49,10 +49,10 @@ ssd_thickness(struct view *view)
}
struct border thickness = {
.top = theme->titlebar_height + theme->border_width,
.right = theme->border_width,
.bottom = theme->border_width,
.left = theme->border_width,
.top = theme->titlebar_height + BORDER_PX_TOP,
.right = BORDER_PX_SIDE,
.bottom = BORDER_PX_SIDE,
.left = BORDER_PX_SIDE,
};
if (!view_titlebar_visible(view)) {
@ -346,10 +346,13 @@ ssd_enable_keybind_inhibit_indicator(struct ssd *ssd, bool enable)
return;
}
#if 0
/* XXX: doesn't work with textured borders */
float *color = enable
? rc.theme->window_toggled_keybinds_color
: rc.theme->window[SSD_ACTIVE].border_color;
wlr_scene_rect_set_color(ssd->border.subtrees[SSD_ACTIVE].top, color);
#endif
}
bool