]> git.mdlowis.com Git - proto/labwc.git/commitdiff
osd: split to osd.c and osd-classic.c
authortokyo4j <hrak1529@gmail.com>
Fri, 8 Aug 2025 03:29:08 +0000 (12:29 +0900)
committerJohan Malm <johanmalm@users.noreply.github.com>
Fri, 29 Aug 2025 19:42:01 +0000 (20:42 +0100)
include/osd.h
src/osd/meson.build
src/osd/osd-classic.c [new file with mode: 0644]
src/osd/osd.c

index 1457aeb290c35e89feda00777b947b3a742cf5a2..ad0b3bce1c9f4b29ec2e236be4f7d7b2158ef297 100644 (file)
@@ -5,6 +5,8 @@
 #include <stdbool.h>
 #include <wayland-server-core.h>
 
+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
index 0ea1abd3ba8e03c1edf448807b1ef1e94fcd3fab..4f4da2cba6b282d357b24d4589744cd0716a362a 100644 (file)
@@ -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 (file)
index 0000000..2467937
--- /dev/null
@@ -0,0 +1,218 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <assert.h>
+#include <cairo.h>
+#include <wlr/util/log.h>
+#include <wlr/util/box.h>
+#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,
+};
index 39846795395745d1851afc435024ed82d33fee35..51a0721c353d6f775b7b67f78d3744d3ace7eca3 100644 (file)
@@ -5,13 +5,10 @@
 #include <wlr/util/log.h>
 #include <wlr/util/box.h>
 #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 "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);
                }
        }