From 6b75cda128e8c908b0e8bef33bed24feeae611b2 Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Sun, 28 Jun 2026 02:04:20 +0800 Subject: [PATCH] =?UTF-8?q?feat(bar):=20bar=20item=20=E6=89=A9=E5=B1=95?= =?UTF-8?q?=E9=92=A9=E5=AD=90=E5=8A=9F=E8=83=BD=20bar=20cell=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=20fixed=5Fwidth=20=E5=B1=9E=E6=80=A7=E4=B8=8E?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - item type 加入可为空的 after_layout 和 after_draw 钩子 - cell 加 fixed_width 属性, cell api 添加 cell_set_fixed_width 和 cell_get_region 两个接口 - cell api 改为 const 避免外部修改 --- include/zdwm/bar.h | 21 ++++++++++ src/bar/bar.c | 98 +++++++++++++++++++++++++++++++++++++--------- src/bar/cell.c | 39 ++++++++++++++---- src/bar/cell.h | 2 +- src/bar/types.h | 6 +-- 5 files changed, 134 insertions(+), 32 deletions(-) diff --git a/include/zdwm/bar.h b/include/zdwm/bar.h index abf673b..0d00e7d 100644 --- a/include/zdwm/bar.h +++ b/include/zdwm/bar.h @@ -48,6 +48,11 @@ typedef struct zdwm_bar_config_t { typedef struct zdwm_bar_item_t zdwm_bar_item_t; +typedef struct zdwm_bar_x_region_t { + int32_t start; + int32_t end; +} zdwm_bar_x_region_t; + typedef struct zdwm_bar_cell_api_t { size_t (*get_cell_count)(zdwm_bar_item_t *item); void (*set_cell_count)(zdwm_bar_item_t *item, size_t count); @@ -57,6 +62,13 @@ typedef struct zdwm_bar_cell_api_t { void (*cell_set_fg)(zdwm_bar_item_t *item, size_t index, const char *color); void (*cell_set_icon)(zdwm_bar_item_t *item, size_t index, zdwm_icon_t icon); void (*cell_set_indicator)(zdwm_bar_item_t *item, size_t index, bool show); + void (*cell_set_fixed_width)( + zdwm_bar_item_t *item, + size_t index, + int32_t width + ); + + zdwm_bar_x_region_t (*cell_get_region)(zdwm_bar_item_t *item, size_t index); } zdwm_bar_cell_api_t; typedef struct zdwm_bar_click_params_t { @@ -68,6 +80,13 @@ typedef struct zdwm_bar_click_params_t { void *state; } zdwm_bar_click_params_t; +typedef struct zdwm_bar_item_hook_params_t { + zdwm_bar_item_t *item; + const zdwm_bar_cell_api_t *cell_api; + zdwm_bar_x_region_t region; + void *state; +} zdwm_bar_item_hook_params_t; + typedef struct zdwm_bar_item_type_t { void *(*create_state)(zdwm_output_id_t output_id, void *config); void (*update)( @@ -75,6 +94,8 @@ typedef struct zdwm_bar_item_type_t { const zdwm_bar_cell_api_t *cells, void *state ); + void (*after_layout)(const zdwm_bar_item_hook_params_t *params); + void (*after_draw)(const zdwm_bar_item_hook_params_t *params); zdwm_action_t (*on_click)(zdwm_bar_click_params_t *params); void (*destroy_state)(void *state); zdwm_bar_item_t *instance; diff --git a/src/bar/bar.c b/src/bar/bar.c index 87c3c2e..fe82e88 100644 --- a/src/bar/bar.c +++ b/src/bar/bar.c @@ -212,14 +212,16 @@ static void bar_output_layout(bar_output_t *bar_output, text_context_t *ctx) { item->region.start = start; for (size_t j = 0; j < item->count; ++j) { auto cell = &item->cells[j]; + auto fixed_width = cell->fixed_width; - int32_t width = 0; - text_context_get_text_size(ctx, cell->text, &width, nullptr); - - bar_x_region_t region = { - .start = start, - .end = start + width + item->cell_padding * 2, - }; + bar_x_region_t region = {.start = start, .end = start}; + if (fixed_width == 0) { + int32_t width = 0; + text_context_get_text_size(ctx, cell->text, &width, nullptr); + region.end += width + 2 * item->cell_padding; + } else if (fixed_width > 0) { + region.end += fixed_width; + } bar_cell_set_region(item, j, region); start = region.end; @@ -240,14 +242,16 @@ static void bar_output_layout(bar_output_t *bar_output, text_context_t *ctx) { for (size_t j = item->count; j > 0; --j) { auto cell_index = j - 1; auto cell = &item->cells[cell_index]; + auto fixed_width = cell->fixed_width; - int32_t width = 0; - text_context_get_text_size(ctx, cell->text, &width, nullptr); - - bar_x_region_t region = { - .start = end - width - item->cell_padding * 2, - .end = end, - }; + bar_x_region_t region = {.start = end, .end = end}; + if (fixed_width == 0) { + int32_t width = 0; + text_context_get_text_size(ctx, cell->text, &width, nullptr); + region.start -= width + item->cell_padding * 2; + } else if (fixed_width > 0) { + region.start -= fixed_width; + } bar_cell_set_region(item, cell_index, region); end = region.start; @@ -263,12 +267,30 @@ static void bar_output_layout(bar_output_t *bar_output, text_context_t *ctx) { if (center->count == 0) return; center->region = (bar_x_region_t){.start = start, .end = end}; - auto width = (end - start) / (int32_t)center->count; + auto center_width = end - start; + auto center_count = center->count; for (size_t i = 0; i < center->count; ++i) { - bar_x_region_t region = { - .start = start, - .end = start + width + center->cell_padding * 2, - }; + auto cell = ¢er->cells[i]; + auto fixed_width = cell->fixed_width; + if (fixed_width > 0) { + center_width -= fixed_width; + } else if (fixed_width < 0) { + /* 隐藏的 cell 不占任何空间,平分宽度时不参与 */ + --center_count; + } + } + + auto width = center_width / (int32_t)center_count; + for (size_t i = 0; i < center->count; ++i) { + auto cell = ¢er->cells[i]; + auto fixed_width = cell->fixed_width; + + bar_x_region_t region = {.start = start, .end = start}; + if (fixed_width == 0) { + region.end += width + center->cell_padding * 2; + } else if (fixed_width > 0) { + region.end += fixed_width; + } start = region.end; bar_cell_set_region(center, i, region); } @@ -386,6 +408,42 @@ bar_output_draw(bar_output_t *bar_output, text_context_t *ctx, color_t *bg) { bar_item_draw(cr, &bar_output->center, ctx, bar_output->height); } +static inline void bar_item_run_hook( + zdwm_bar_item_t *item, + void (*hook)(const zdwm_bar_item_hook_params_t *params) +) { + if (!hook) return; + + zdwm_bar_item_hook_params_t params = { + .item = item, + .cell_api = &bar_cell_api, + .region = item->region, + .state = item->state + }; + hook(¶ms); +} + +static void visitor_after_layout(zdwm_bar_item_t *item) { + bar_item_run_hook(item, item->api.after_layout); +} + +static void visitor_after_draw(zdwm_bar_item_t *item) { + bar_item_run_hook(item, item->api.after_draw); +} + +typedef void (*bar_item_visitor_t)(zdwm_bar_item_t *item); + +static void +bar_output_foreach_item(bar_output_t *bar_output, bar_item_visitor_t visit) { + for (size_t i = 0; i < bar_output->left.count; ++i) { + visit(&bar_output->left.items[i]); + } + visit(&bar_output->center); + for (size_t i = 0; i < bar_output->right.count; ++i) { + visit(&bar_output->right.items[i]); + } +} + bool bar_draw(bar_t *bar) { auto ctx = bar->ctx; @@ -396,7 +454,9 @@ bool bar_draw(bar_t *bar) { if (!bar_output_is_dirty(bar_output)) continue; bar_output_layout(bar_output, ctx); + bar_output_foreach_item(bar_output, visitor_after_layout); bar_output_draw(bar_output, ctx, &bar->palette.bg); + bar_output_foreach_item(bar_output, visitor_after_draw); changed = true; } diff --git a/src/bar/cell.c b/src/bar/cell.c index 322df80..f64d9a3 100644 --- a/src/bar/cell.c +++ b/src/bar/cell.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -119,15 +120,37 @@ bar_cell_set_indicator(zdwm_bar_item_t *item, size_t index, bool show) { item->dirty = true; } +static void +bar_cell_set_fixed_width(zdwm_bar_item_t *item, size_t index, int32_t width) { + if (index >= item->count) return; + + auto cell = &item->cells[index]; + if (cell->fixed_width == width) return; + + cell->fixed_width = width; + + cell->dirty = true; + item->dirty = true; +} + +static bar_x_region_t bar_cell_get_region(zdwm_bar_item_t *item, size_t index) { + if (index >= item->count) return (bar_x_region_t){0}; + + auto cell = &item->cells[index]; + return cell->region; +} + /* clang-format off */ -zdwm_bar_cell_api_t bar_cell_api = { - .get_cell_count = bar_cell_get_count, - .set_cell_count = bar_cell_set_count, - .cell_set_text = bar_cell_set_text, - .cell_set_bg = bar_cell_set_bg, - .cell_set_fg = bar_cell_set_fg, - .cell_set_icon = bar_cell_set_icon, - .cell_set_indicator = bar_cell_set_indicator, +const zdwm_bar_cell_api_t bar_cell_api = { + .get_cell_count = bar_cell_get_count, + .set_cell_count = bar_cell_set_count, + .cell_set_text = bar_cell_set_text, + .cell_set_bg = bar_cell_set_bg, + .cell_set_fg = bar_cell_set_fg, + .cell_set_icon = bar_cell_set_icon, + .cell_set_indicator = bar_cell_set_indicator, + .cell_set_fixed_width = bar_cell_set_fixed_width, + .cell_get_region = bar_cell_get_region, }; /* clang-format on */ diff --git a/src/bar/cell.h b/src/bar/cell.h index 2763168..04e43e4 100644 --- a/src/bar/cell.h +++ b/src/bar/cell.h @@ -12,4 +12,4 @@ void bar_cell_set_region( bar_x_region_t region ); -extern zdwm_bar_cell_api_t bar_cell_api; +extern const zdwm_bar_cell_api_t bar_cell_api; diff --git a/src/bar/types.h b/src/bar/types.h index 23e0450..23cc109 100644 --- a/src/bar/types.h +++ b/src/bar/types.h @@ -7,10 +7,7 @@ #include "base/color.h" -typedef struct bar_x_region_t { - int32_t start; - int32_t end; -} bar_x_region_t; +typedef struct zdwm_bar_x_region_t bar_x_region_t; typedef struct bar_cell_t { zdwm_icon_t icon; @@ -20,6 +17,7 @@ typedef struct bar_cell_t { color_t fg; color_t bg; bar_x_region_t region; + int32_t fixed_width; bool show_indicator; bool dirty; } bar_cell_t;