osd-classic: add theme options for selected window item

This commit adds new theme options:
- osd.window-switcher.style-classic.item.active.border.color
- osd.window-switcher.style-classic.item.active.bg.color

These theme options configures the border/background of selected window
item in the `classic` style window switcher. Their default values are
identical to `thumbnail` style window switcher, which means the default
border color is now `osd.label.text.color` with 50% opacity and the
default background color is now `osd.label.text.color` with 15% opacity.
This commit is contained in:
tokyo4j 2025-10-01 14:25:43 +09:00
parent 5f981226c2
commit 5a9133edb5
5 changed files with 96 additions and 46 deletions

View file

@ -327,6 +327,14 @@ all are supported.
Border width of the selection box in the window switcher in pixels. Border width of the selection box in the window switcher in pixels.
Default is 2. Default is 2.
*osd.window-switcher.style-classic.item.active.border.color*
Border color around the selected window switcher item.
Default is *osd.label.text.color* with 50% opacity.
*osd.window-switcher.style-classic.item.active.bg.color*
Background color of the selected window switcher item.
Default is *osd.label.text.color* with 15% opacity.
*osd.window-switcher.style-classic.item.icon.size* *osd.window-switcher.style-classic.item.icon.size*
Size of the icon in window switcher, in pixels. Size of the icon in window switcher, in pixels.
If not set, the font size derived from <theme><font place="OnScreenDisplay"> If not set, the font size derived from <theme><font place="OnScreenDisplay">

View file

@ -97,6 +97,8 @@ osd.window-switcher.style-classic.padding: 4
osd.window-switcher.style-classic.item.padding.x: 10 osd.window-switcher.style-classic.item.padding.x: 10
osd.window-switcher.style-classic.item.padding.y: 1 osd.window-switcher.style-classic.item.padding.y: 1
osd.window-switcher.style-classic.item.active.border.width: 2 osd.window-switcher.style-classic.item.active.border.width: 2
osd.window-switcher.style-classic.item.active.border.color: #706f6d
osd.window-switcher.style-classic.item.active.bg.color: #bfbcba
# The icon size the same as the font size by default # The icon size the same as the font size by default
# osd.window-switcher.style-classic.item.icon.size: 50 # osd.window-switcher.style-classic.item.icon.size: 50

View file

@ -170,6 +170,8 @@ struct theme {
int item_padding_x; int item_padding_x;
int item_padding_y; int item_padding_y;
int item_active_border_width; int item_active_border_width;
float item_active_border_color[4];
float item_active_bg_color[4];
int item_icon_size; int item_icon_size;
bool width_is_percent; bool width_is_percent;

View file

@ -19,9 +19,59 @@
struct osd_classic_scene_item { struct osd_classic_scene_item {
struct view *view; struct view *view;
struct wlr_scene_node *highlight_outline; struct wlr_scene_tree *normal_tree, *active_tree;
}; };
static void
create_fields_scene(struct server *server, struct view *view,
struct wlr_scene_tree *parent, const float *text_color,
const float *bg_color, int field_widths_sum, int x, int y)
{
struct theme *theme = server->theme;
struct window_switcher_classic_theme *switcher_theme =
&theme->osd_window_switcher_classic;
struct window_switcher_field *field;
wl_list_for_each(field, &rc.window_switcher.fields, link) {
int field_width = field_widths_sum * field->width / 100.0;
struct wlr_scene_node *node = NULL;
int height = -1;
if (field->content == LAB_FIELD_ICON) {
int icon_size = MIN(field_width,
switcher_theme->item_icon_size);
struct scaled_icon_buffer *icon_buffer =
scaled_icon_buffer_create(parent,
server, icon_size, icon_size);
scaled_icon_buffer_set_view(icon_buffer, view);
node = &icon_buffer->scene_buffer->node;
height = icon_size;
} else {
struct buf buf = BUF_INIT;
osd_field_get_content(field, &buf, view);
if (!string_null_or_empty(buf.data)) {
struct scaled_font_buffer *font_buffer =
scaled_font_buffer_create(parent);
scaled_font_buffer_update(font_buffer,
buf.data, field_width,
&rc.font_osd, text_color, bg_color);
node = &font_buffer->scene_buffer->node;
height = font_height(&rc.font_osd);
}
buf_reset(&buf);
}
if (node) {
int item_height = switcher_theme->item_height;
wlr_scene_node_set_position(node,
x, y + (item_height - height) / 2);
}
x += field_width + switcher_theme->item_padding_x;
}
}
static void static void
osd_classic_create(struct output *output, struct wl_array *views) osd_classic_create(struct output *output, struct wl_array *views)
{ {
@ -126,62 +176,33 @@ osd_classic_create(struct output *output, struct wl_array *views)
+ switcher_theme->item_padding_x; + switcher_theme->item_padding_x;
struct wlr_scene_tree *item_root = struct wlr_scene_tree *item_root =
wlr_scene_tree_create(output->osd_scene.tree); wlr_scene_tree_create(output->osd_scene.tree);
item->normal_tree = wlr_scene_tree_create(item_root);
item->active_tree = wlr_scene_tree_create(item_root);
wlr_scene_node_set_enabled(&item->active_tree->node, false);
struct window_switcher_field *field; float *active_bg_color = switcher_theme->item_active_bg_color;
wl_list_for_each(field, &rc.window_switcher.fields, link) { float *active_border_color = switcher_theme->item_active_border_color;
int field_width = field_widths_sum * field->width / 100.0;
struct wlr_scene_node *node = NULL;
int height = -1;
if (field->content == LAB_FIELD_ICON) {
int icon_size = MIN(field_width,
switcher_theme->item_icon_size);
struct scaled_icon_buffer *icon_buffer =
scaled_icon_buffer_create(item_root,
server, icon_size, icon_size);
scaled_icon_buffer_set_view(icon_buffer, *view);
node = &icon_buffer->scene_buffer->node;
height = icon_size;
} else {
buf_clear(&buf);
osd_field_get_content(field, &buf, *view);
if (!string_null_or_empty(buf.data)) {
struct scaled_font_buffer *font_buffer =
scaled_font_buffer_create(item_root);
scaled_font_buffer_update(font_buffer,
buf.data, field_width,
&rc.font_osd, text_color, bg_color);
node = &font_buffer->scene_buffer->node;
height = font_height(&rc.font_osd);
}
}
if (node) {
int item_height = switcher_theme->item_height;
wlr_scene_node_set_position(node,
x, y + (item_height - height) / 2);
}
x += field_width + switcher_theme->item_padding_x;
}
/* Highlight around selected window's item */ /* Highlight around selected window's item */
int highlight_x = theme->osd_border_width int highlight_x = theme->osd_border_width
+ switcher_theme->padding; + switcher_theme->padding;
struct lab_scene_rect_options highlight_opts = { struct lab_scene_rect_options highlight_opts = {
.border_colors = (float *[1]) {text_color}, .border_colors = (float *[1]) {active_border_color},
.bg_color = active_bg_color,
.nr_borders = 1, .nr_borders = 1,
.border_width = switcher_theme->item_active_border_width, .border_width = switcher_theme->item_active_border_width,
.width = w - 2 * theme->osd_border_width .width = w - 2 * theme->osd_border_width
- 2 * switcher_theme->padding, - 2 * switcher_theme->padding,
.height = switcher_theme->item_height, .height = switcher_theme->item_height,
}; };
struct lab_scene_rect *highlight_rect = lab_scene_rect_create( struct lab_scene_rect *highlight_rect = lab_scene_rect_create(
output->osd_scene.tree, &highlight_opts); item->active_tree, &highlight_opts);
item->highlight_outline = &highlight_rect->tree->node; wlr_scene_node_set_position(&highlight_rect->tree->node, highlight_x, y);
wlr_scene_node_set_position(item->highlight_outline, highlight_x, y);
wlr_scene_node_set_enabled(item->highlight_outline, false); create_fields_scene(server, *view, item->normal_tree,
text_color, bg_color, field_widths_sum, x, y);
create_fields_scene(server, *view, item->active_tree,
text_color, active_bg_color, field_widths_sum, x, y);
y += switcher_theme->item_height; y += switcher_theme->item_height;
} }
@ -200,8 +221,9 @@ osd_classic_update(struct output *output)
{ {
struct osd_classic_scene_item *item; struct osd_classic_scene_item *item;
wl_array_for_each(item, &output->osd_scene.items) { wl_array_for_each(item, &output->osd_scene.items) {
wlr_scene_node_set_enabled(item->highlight_outline, bool active = item->view == output->server->osd_state.cycle_view;
item->view == output->server->osd_state.cycle_view); wlr_scene_node_set_enabled(&item->normal_tree->node, !active);
wlr_scene_node_set_enabled(&item->active_tree->node, active);
} }
} }

View file

@ -604,6 +604,8 @@ theme_builtin(struct theme *theme, struct server *server)
theme->osd_window_switcher_classic.item_padding_x = 10; theme->osd_window_switcher_classic.item_padding_x = 10;
theme->osd_window_switcher_classic.item_padding_y = 1; theme->osd_window_switcher_classic.item_padding_y = 1;
theme->osd_window_switcher_classic.item_active_border_width = 2; theme->osd_window_switcher_classic.item_active_border_width = 2;
theme->osd_window_switcher_classic.item_active_border_color[0] = FLT_MIN;
theme->osd_window_switcher_classic.item_active_bg_color[0] = FLT_MIN;
theme->osd_window_switcher_classic.item_icon_size = -1; theme->osd_window_switcher_classic.item_icon_size = -1;
theme->osd_window_switcher_thumbnail.max_width = 80; theme->osd_window_switcher_thumbnail.max_width = 80;
@ -989,6 +991,12 @@ entry(struct theme *theme, const char *key, const char *value)
get_int_if_positive(value, get_int_if_positive(value,
"osd.window-switcher.style-classic.item.active.border.width"); "osd.window-switcher.style-classic.item.active.border.width");
} }
if (match_glob(key, "osd.window-switcher.style-classic.item.active.border.color")) {
parse_color(value, switcher_classic_theme->item_active_border_color);
}
if (match_glob(key, "osd.window-switcher.style-classic.item.active.bg.color")) {
parse_color(value, switcher_classic_theme->item_active_bg_color);
}
if (match_glob(key, "osd.window-switcher.style-classic.item.icon.size") if (match_glob(key, "osd.window-switcher.style-classic.item.icon.size")
|| match_glob(key, "osd.window-switcher.item.icon.size")) { || match_glob(key, "osd.window-switcher.item.icon.size")) {
switcher_classic_theme->item_icon_size = switcher_classic_theme->item_icon_size =
@ -1746,6 +1754,14 @@ post_processing(struct theme *theme)
memcpy(theme->osd_border_color, theme->osd_label_text_color, memcpy(theme->osd_border_color, theme->osd_label_text_color,
sizeof(theme->osd_border_color)); sizeof(theme->osd_border_color));
} }
if (switcher_classic_theme->item_active_border_color[0] == FLT_MIN) {
blend_color_with_bg(switcher_classic_theme->item_active_border_color,
theme->osd_label_text_color, 0.50, theme->osd_bg_color);
}
if (switcher_classic_theme->item_active_bg_color[0] == FLT_MIN) {
blend_color_with_bg(switcher_classic_theme->item_active_bg_color,
theme->osd_label_text_color, 0.15, theme->osd_bg_color);
}
if (switcher_thumb_theme->item_active_border_color[0] == FLT_MIN) { if (switcher_thumb_theme->item_active_border_color[0] == FLT_MIN) {
blend_color_with_bg(switcher_thumb_theme->item_active_border_color, blend_color_with_bg(switcher_thumb_theme->item_active_border_color,
theme->osd_label_text_color, 0.50, theme->osd_bg_color); theme->osd_label_text_color, 0.50, theme->osd_bg_color);