From 92ee5083f035a807cf7185eb2ee303988d0482d4 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Fri, 8 Aug 2025 12:29:08 +0900 Subject: [PATCH] osd: split to osd.c and osd-classic.c --- include/osd.h | 18 ++++ src/osd/meson.build | 1 + src/osd/osd-classic.c | 218 ++++++++++++++++++++++++++++++++++++++++++ src/osd/osd.c | 197 +------------------------------------- 4 files changed, 240 insertions(+), 194 deletions(-) create mode 100644 src/osd/osd-classic.c diff --git a/include/osd.h b/include/osd.h index 1457aeb2..ad0b3bce 100644 --- a/include/osd.h +++ b/include/osd.h @@ -5,6 +5,8 @@ #include #include +struct output; + enum lab_cycle_dir { LAB_CYCLE_DIR_NONE, LAB_CYCLE_DIR_FORWARD, @@ -66,4 +68,20 @@ void osd_field_arg_from_xml_node(struct window_switcher_field *field, bool osd_field_is_valid(struct window_switcher_field *field); void osd_field_free(struct window_switcher_field *field); +/* Internal API */ +struct osd_impl { + /* + * Create a scene-tree of OSD for an output. + * This sets output->osd_scene.{items,tree}. + */ + void (*create)(struct output *output, struct wl_array *views); + /* + * Update output->osd_scene.tree to highlight + * server->osd_state.cycle_view. + */ + void (*update)(struct output *output); +}; + +extern struct osd_impl osd_classic_impl; + #endif // LABWC_OSD_H diff --git a/src/osd/meson.build b/src/osd/meson.build index 0ea1abd3..4f4da2cb 100644 --- a/src/osd/meson.build +++ b/src/osd/meson.build @@ -1,4 +1,5 @@ labwc_sources += files( 'osd.c', + 'osd-classic.c', 'osd-field.c', ) diff --git a/src/osd/osd-classic.c b/src/osd/osd-classic.c new file mode 100644 index 00000000..24679378 --- /dev/null +++ b/src/osd/osd-classic.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include +#include "common/array.h" +#include "common/buf.h" +#include "common/font.h" +#include "common/lab-scene-rect.h" +#include "common/scaled-font-buffer.h" +#include "common/scaled-icon-buffer.h" +#include "common/scene-helpers.h" +#include "common/string-helpers.h" +#include "config/rcxml.h" +#include "labwc.h" +#include "node.h" +#include "osd.h" +#include "output.h" +#include "theme.h" +#include "view.h" +#include "window-rules.h" +#include "workspaces.h" + +struct osd_classic_scene_item { + struct view *view; + struct wlr_scene_node *highlight_outline; +}; + +static void +osd_classic_create(struct output *output, struct wl_array *views) +{ + assert(!output->osd_scene.tree); + + struct server *server = output->server; + struct theme *theme = server->theme; + bool show_workspace = wl_list_length(&rc.workspace_config.workspaces) > 1; + const char *workspace_name = server->workspaces.current->name; + + int w = theme->osd_window_switcher_width; + if (theme->osd_window_switcher_width_is_percent) { + w = output->wlr_output->width + * theme->osd_window_switcher_width / 100; + } + int h = wl_array_len(views) * rc.theme->osd_window_switcher_item_height + + 2 * rc.theme->osd_border_width + + 2 * rc.theme->osd_window_switcher_padding; + if (show_workspace) { + /* workspace indicator */ + h += theme->osd_window_switcher_item_height; + } + + output->osd_scene.tree = wlr_scene_tree_create(output->osd_tree); + + float *text_color = theme->osd_label_text_color; + float *bg_color = theme->osd_bg_color; + + /* Draw background */ + struct lab_scene_rect_options bg_opts = { + .border_colors = (float *[1]) {theme->osd_border_color}, + .nr_borders = 1, + .border_width = theme->osd_border_width, + .bg_color = bg_color, + .width = w, + .height = h, + }; + lab_scene_rect_create(output->osd_scene.tree, &bg_opts); + + int y = theme->osd_border_width + theme->osd_window_switcher_padding; + + /* Draw workspace indicator */ + if (show_workspace) { + struct font font = rc.font_osd; + font.weight = PANGO_WEIGHT_BOLD; + + /* Center workspace indicator on the x axis */ + int x = (w - font_width(&font, workspace_name)) / 2; + if (x < 0) { + wlr_log(WLR_ERROR, + "not enough space for workspace name in osd"); + goto error; + } + + struct scaled_font_buffer *font_buffer = + scaled_font_buffer_create(output->osd_scene.tree); + wlr_scene_node_set_position(&font_buffer->scene_buffer->node, + x, y + (theme->osd_window_switcher_item_height + - font_height(&font)) / 2); + scaled_font_buffer_update(font_buffer, workspace_name, 0, + &font, text_color, bg_color); + y += theme->osd_window_switcher_item_height; + } + + struct buf buf = BUF_INIT; + int nr_fields = wl_list_length(&rc.window_switcher.fields); + + /* This is the width of the area available for text fields */ + int field_widths_sum = w - 2 * theme->osd_border_width + - 2 * theme->osd_window_switcher_padding + - 2 * theme->osd_window_switcher_item_active_border_width + - (nr_fields + 1) * theme->osd_window_switcher_item_padding_x; + if (field_widths_sum <= 0) { + wlr_log(WLR_ERROR, "Not enough spaces for osd contents"); + goto error; + } + + /* Draw text for each node */ + struct view **view; + wl_array_for_each(view, views) { + struct osd_classic_scene_item *item = + wl_array_add(&output->osd_scene.items, sizeof(*item)); + item->view = *view; + /* + * OSD border + * +---------------------------------+ + * | | + * | item border | + * |+-------------------------------+| + * || || + * ||padding between each field || + * ||| field-1 | field-2 | field-n ||| + * || || + * || || + * |+-------------------------------+| + * | | + * | | + * +---------------------------------+ + */ + int x = theme->osd_border_width + + theme->osd_window_switcher_padding + + theme->osd_window_switcher_item_active_border_width + + theme->osd_window_switcher_item_padding_x; + struct wlr_scene_tree *item_root = + wlr_scene_tree_create(output->osd_scene.tree); + + 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, + theme->osd_window_switcher_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 = + theme->osd_window_switcher_item_height; + wlr_scene_node_set_position(node, + x, y + (item_height - height) / 2); + } + x += field_width + theme->osd_window_switcher_item_padding_x; + } + + /* Highlight around selected window's item */ + int highlight_x = theme->osd_border_width + + theme->osd_window_switcher_padding; + struct lab_scene_rect_options highlight_opts = { + .border_colors = (float *[1]) {text_color}, + .nr_borders = 1, + .border_width = + theme->osd_window_switcher_item_active_border_width, + .width = w - 2 * theme->osd_border_width + - 2 * theme->osd_window_switcher_padding, + .height = theme->osd_window_switcher_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); + + y += theme->osd_window_switcher_item_height; + } + buf_reset(&buf); + +error:; + /* Center OSD */ + struct wlr_box usable = output_usable_area_in_layout_coords(output); + wlr_scene_node_set_position(&output->osd_scene.tree->node, + usable.x + usable.width / 2 - w / 2, + usable.y + usable.height / 2 - h / 2); +} + +static void +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); + } +} + +struct osd_impl osd_classic_impl = { + .create = osd_classic_create, + .update = osd_classic_update, +}; diff --git a/src/osd/osd.c b/src/osd/osd.c index 39846795..51a0721c 100644 --- a/src/osd/osd.c +++ b/src/osd/osd.c @@ -5,13 +5,10 @@ #include #include #include "common/array.h" -#include "common/buf.h" -#include "common/font.h" #include "common/lab-scene-rect.h" #include "common/scaled-font-buffer.h" #include "common/scaled-icon-buffer.h" #include "common/scene-helpers.h" -#include "common/string-helpers.h" #include "config/rcxml.h" #include "labwc.h" #include "node.h" @@ -21,11 +18,6 @@ #include "window-rules.h" #include "workspaces.h" -struct osd_scene_item { - struct view *view; - struct wlr_scene_node *highlight_outline; -}; - static void update_osd(struct server *server); static void @@ -267,196 +259,13 @@ preview_cycled_view(struct view *view) wlr_scene_node_raise_to_top(osd_state->preview_node); } -static void -create_osd_scene(struct output *output, struct wl_array *views) -{ - struct server *server = output->server; - struct theme *theme = server->theme; - bool show_workspace = wl_list_length(&rc.workspace_config.workspaces) > 1; - const char *workspace_name = server->workspaces.current->name; - - int w = theme->osd_window_switcher_width; - if (theme->osd_window_switcher_width_is_percent) { - w = output->wlr_output->width - * theme->osd_window_switcher_width / 100; - } - int h = wl_array_len(views) * rc.theme->osd_window_switcher_item_height - + 2 * rc.theme->osd_border_width - + 2 * rc.theme->osd_window_switcher_padding; - if (show_workspace) { - /* workspace indicator */ - h += theme->osd_window_switcher_item_height; - } - - output->osd_scene.tree = wlr_scene_tree_create(output->osd_tree); - - float *text_color = theme->osd_label_text_color; - float *bg_color = theme->osd_bg_color; - - /* Draw background */ - struct lab_scene_rect_options bg_opts = { - .border_colors = (float *[1]) {theme->osd_border_color}, - .nr_borders = 1, - .border_width = theme->osd_border_width, - .bg_color = bg_color, - .width = w, - .height = h, - }; - lab_scene_rect_create(output->osd_scene.tree, &bg_opts); - - int y = theme->osd_border_width + theme->osd_window_switcher_padding; - - /* Draw workspace indicator */ - if (show_workspace) { - struct font font = rc.font_osd; - font.weight = PANGO_WEIGHT_BOLD; - - /* Center workspace indicator on the x axis */ - int x = (w - font_width(&font, workspace_name)) / 2; - if (x < 0) { - wlr_log(WLR_ERROR, - "not enough space for workspace name in osd"); - goto error; - } - - struct scaled_font_buffer *font_buffer = - scaled_font_buffer_create(output->osd_scene.tree); - wlr_scene_node_set_position(&font_buffer->scene_buffer->node, - x, y + (theme->osd_window_switcher_item_height - - font_height(&font)) / 2); - scaled_font_buffer_update(font_buffer, workspace_name, 0, - &font, text_color, bg_color); - y += theme->osd_window_switcher_item_height; - } - - struct buf buf = BUF_INIT; - int nr_fields = wl_list_length(&rc.window_switcher.fields); - - /* This is the width of the area available for text fields */ - int field_widths_sum = w - 2 * theme->osd_border_width - - 2 * theme->osd_window_switcher_padding - - 2 * theme->osd_window_switcher_item_active_border_width - - (nr_fields + 1) * theme->osd_window_switcher_item_padding_x; - if (field_widths_sum <= 0) { - wlr_log(WLR_ERROR, "Not enough spaces for osd contents"); - goto error; - } - - /* Draw text for each node */ - struct view **view; - wl_array_for_each(view, views) { - struct osd_scene_item *item = - wl_array_add(&output->osd_scene.items, sizeof(*item)); - item->view = *view; - /* - * OSD border - * +---------------------------------+ - * | | - * | item border | - * |+-------------------------------+| - * || || - * ||padding between each field || - * ||| field-1 | field-2 | field-n ||| - * || || - * || || - * |+-------------------------------+| - * | | - * | | - * +---------------------------------+ - */ - int x = theme->osd_border_width - + theme->osd_window_switcher_padding - + theme->osd_window_switcher_item_active_border_width - + theme->osd_window_switcher_item_padding_x; - struct wlr_scene_tree *item_root = - wlr_scene_tree_create(output->osd_scene.tree); - - 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, - theme->osd_window_switcher_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 = - theme->osd_window_switcher_item_height; - wlr_scene_node_set_position(node, - x, y + (item_height - height) / 2); - } - x += field_width + theme->osd_window_switcher_item_padding_x; - } - - /* Highlight around selected window's item */ - int highlight_x = theme->osd_border_width - + theme->osd_window_switcher_padding; - struct lab_scene_rect_options highlight_opts = { - .border_colors = (float *[1]) {text_color}, - .nr_borders = 1, - .border_width = - theme->osd_window_switcher_item_active_border_width, - .width = w - 2 * theme->osd_border_width - - 2 * theme->osd_window_switcher_padding, - .height = theme->osd_window_switcher_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); - - y += theme->osd_window_switcher_item_height; - } - buf_reset(&buf); - -error:; - /* Center OSD */ - struct wlr_box usable = output_usable_area_in_layout_coords(output); - wlr_scene_node_set_position(&output->osd_scene.tree->node, - usable.x + usable.width / 2 - w / 2, - usable.y + usable.height / 2 - h / 2); -} - -static void -update_item_highlight(struct output *output) -{ - struct osd_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); - } -} - static void update_osd(struct server *server) { struct wl_array views; wl_array_init(&views); view_array_append(server, &views, rc.window_switcher.criteria); + struct osd_impl *osd_impl = &osd_classic_impl; if (!wl_array_len(&views) || !server->osd_state.cycle_view) { osd_finish(server); @@ -471,10 +280,10 @@ update_osd(struct server *server) continue; } if (!output->osd_scene.tree) { - create_osd_scene(output, &views); + osd_impl->create(output, &views); assert(output->osd_scene.tree); } - update_item_highlight(output); + osd_impl->update(output); } } -- 2.52.0