From 5a9133edb506f16535708588a1eeffdeb0a09bbb Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Wed, 1 Oct 2025 14:25:43 +0900 Subject: [PATCH] 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. --- docs/labwc-theme.5.scd | 8 +++ docs/themerc | 2 + include/theme.h | 2 + src/osd/osd-classic.c | 114 ++++++++++++++++++++++++----------------- src/theme.c | 16 ++++++ 5 files changed, 96 insertions(+), 46 deletions(-) diff --git a/docs/labwc-theme.5.scd b/docs/labwc-theme.5.scd index fad8a77e..8097615b 100644 --- a/docs/labwc-theme.5.scd +++ b/docs/labwc-theme.5.scd @@ -327,6 +327,14 @@ all are supported. Border width of the selection box in the window switcher in pixels. 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* Size of the icon in window switcher, in pixels. If not set, the font size derived from diff --git a/docs/themerc b/docs/themerc index a52dfacd..9139170c 100644 --- a/docs/themerc +++ b/docs/themerc @@ -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.y: 1 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 # osd.window-switcher.style-classic.item.icon.size: 50 diff --git a/include/theme.h b/include/theme.h index 797b5072..e7e13d66 100644 --- a/include/theme.h +++ b/include/theme.h @@ -170,6 +170,8 @@ struct theme { int item_padding_x; int item_padding_y; int item_active_border_width; + float item_active_border_color[4]; + float item_active_bg_color[4]; int item_icon_size; bool width_is_percent; diff --git a/src/osd/osd-classic.c b/src/osd/osd-classic.c index be740f2f..4cb92867 100644 --- a/src/osd/osd-classic.c +++ b/src/osd/osd-classic.c @@ -19,9 +19,59 @@ struct osd_classic_scene_item { 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 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; struct wlr_scene_tree *item_root = 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; - 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(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; - } + float *active_bg_color = switcher_theme->item_active_bg_color; + float *active_border_color = switcher_theme->item_active_border_color; /* Highlight around selected window's item */ int highlight_x = theme->osd_border_width + switcher_theme->padding; 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, .border_width = switcher_theme->item_active_border_width, .width = w - 2 * theme->osd_border_width - 2 * switcher_theme->padding, .height = switcher_theme->item_height, }; - struct lab_scene_rect *highlight_rect = lab_scene_rect_create( - output->osd_scene.tree, &highlight_opts); - item->highlight_outline = &highlight_rect->tree->node; - wlr_scene_node_set_position(item->highlight_outline, highlight_x, y); - wlr_scene_node_set_enabled(item->highlight_outline, false); + item->active_tree, &highlight_opts); + wlr_scene_node_set_position(&highlight_rect->tree->node, highlight_x, y); + + 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; } @@ -200,8 +221,9 @@ osd_classic_update(struct output *output) { struct osd_classic_scene_item *item; wl_array_for_each(item, &output->osd_scene.items) { - wlr_scene_node_set_enabled(item->highlight_outline, - item->view == output->server->osd_state.cycle_view); + bool active = 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); } } diff --git a/src/theme.c b/src/theme.c index a3aec34a..acdbc16b 100644 --- a/src/theme.c +++ b/src/theme.c @@ -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_y = 1; 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_thumbnail.max_width = 80; @@ -989,6 +991,12 @@ entry(struct theme *theme, const char *key, const char *value) get_int_if_positive(value, "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") || match_glob(key, "osd.window-switcher.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, 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) { blend_color_with_bg(switcher_thumb_theme->item_active_border_color, theme->osd_label_text_color, 0.50, theme->osd_bg_color);