feat(bar): bar item 扩展钩子功能 bar cell 添加 fixed_width 属性与操作接口
- item type 加入可为空的 after_layout 和 after_draw 钩子 - cell 加 fixed_width 属性, cell api 添加 cell_set_fixed_width 和 cell_get_region 两个接口 - cell api 改为 const 避免外部修改
This commit is contained in:
@@ -48,6 +48,11 @@ typedef struct zdwm_bar_config_t {
|
|||||||
|
|
||||||
typedef struct zdwm_bar_item_t zdwm_bar_item_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 {
|
typedef struct zdwm_bar_cell_api_t {
|
||||||
size_t (*get_cell_count)(zdwm_bar_item_t *item);
|
size_t (*get_cell_count)(zdwm_bar_item_t *item);
|
||||||
void (*set_cell_count)(zdwm_bar_item_t *item, size_t count);
|
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_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_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_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;
|
} zdwm_bar_cell_api_t;
|
||||||
|
|
||||||
typedef struct zdwm_bar_click_params_t {
|
typedef struct zdwm_bar_click_params_t {
|
||||||
@@ -68,6 +80,13 @@ typedef struct zdwm_bar_click_params_t {
|
|||||||
void *state;
|
void *state;
|
||||||
} zdwm_bar_click_params_t;
|
} 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 {
|
typedef struct zdwm_bar_item_type_t {
|
||||||
void *(*create_state)(zdwm_output_id_t output_id, void *config);
|
void *(*create_state)(zdwm_output_id_t output_id, void *config);
|
||||||
void (*update)(
|
void (*update)(
|
||||||
@@ -75,6 +94,8 @@ typedef struct zdwm_bar_item_type_t {
|
|||||||
const zdwm_bar_cell_api_t *cells,
|
const zdwm_bar_cell_api_t *cells,
|
||||||
void *state
|
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);
|
zdwm_action_t (*on_click)(zdwm_bar_click_params_t *params);
|
||||||
void (*destroy_state)(void *state);
|
void (*destroy_state)(void *state);
|
||||||
zdwm_bar_item_t *instance;
|
zdwm_bar_item_t *instance;
|
||||||
|
|||||||
@@ -212,14 +212,16 @@ static void bar_output_layout(bar_output_t *bar_output, text_context_t *ctx) {
|
|||||||
item->region.start = start;
|
item->region.start = start;
|
||||||
for (size_t j = 0; j < item->count; ++j) {
|
for (size_t j = 0; j < item->count; ++j) {
|
||||||
auto cell = &item->cells[j];
|
auto cell = &item->cells[j];
|
||||||
|
auto fixed_width = cell->fixed_width;
|
||||||
|
|
||||||
int32_t width = 0;
|
bar_x_region_t region = {.start = start, .end = start};
|
||||||
text_context_get_text_size(ctx, cell->text, &width, nullptr);
|
if (fixed_width == 0) {
|
||||||
|
int32_t width = 0;
|
||||||
bar_x_region_t region = {
|
text_context_get_text_size(ctx, cell->text, &width, nullptr);
|
||||||
.start = start,
|
region.end += width + 2 * item->cell_padding;
|
||||||
.end = start + width + item->cell_padding * 2,
|
} else if (fixed_width > 0) {
|
||||||
};
|
region.end += fixed_width;
|
||||||
|
}
|
||||||
bar_cell_set_region(item, j, region);
|
bar_cell_set_region(item, j, region);
|
||||||
|
|
||||||
start = region.end;
|
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) {
|
for (size_t j = item->count; j > 0; --j) {
|
||||||
auto cell_index = j - 1;
|
auto cell_index = j - 1;
|
||||||
auto cell = &item->cells[cell_index];
|
auto cell = &item->cells[cell_index];
|
||||||
|
auto fixed_width = cell->fixed_width;
|
||||||
|
|
||||||
int32_t width = 0;
|
bar_x_region_t region = {.start = end, .end = end};
|
||||||
text_context_get_text_size(ctx, cell->text, &width, nullptr);
|
if (fixed_width == 0) {
|
||||||
|
int32_t width = 0;
|
||||||
bar_x_region_t region = {
|
text_context_get_text_size(ctx, cell->text, &width, nullptr);
|
||||||
.start = end - width - item->cell_padding * 2,
|
region.start -= width + item->cell_padding * 2;
|
||||||
.end = end,
|
} else if (fixed_width > 0) {
|
||||||
};
|
region.start -= fixed_width;
|
||||||
|
}
|
||||||
bar_cell_set_region(item, cell_index, region);
|
bar_cell_set_region(item, cell_index, region);
|
||||||
|
|
||||||
end = region.start;
|
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;
|
if (center->count == 0) return;
|
||||||
center->region = (bar_x_region_t){.start = start, .end = end};
|
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) {
|
for (size_t i = 0; i < center->count; ++i) {
|
||||||
bar_x_region_t region = {
|
auto cell = ¢er->cells[i];
|
||||||
.start = start,
|
auto fixed_width = cell->fixed_width;
|
||||||
.end = start + width + center->cell_padding * 2,
|
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;
|
start = region.end;
|
||||||
bar_cell_set_region(center, i, region);
|
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);
|
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) {
|
bool bar_draw(bar_t *bar) {
|
||||||
auto ctx = bar->ctx;
|
auto ctx = bar->ctx;
|
||||||
|
|
||||||
@@ -396,7 +454,9 @@ bool bar_draw(bar_t *bar) {
|
|||||||
if (!bar_output_is_dirty(bar_output)) continue;
|
if (!bar_output_is_dirty(bar_output)) continue;
|
||||||
|
|
||||||
bar_output_layout(bar_output, ctx);
|
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_draw(bar_output, ctx, &bar->palette.bg);
|
||||||
|
bar_output_foreach_item(bar_output, visitor_after_draw);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <zdwm/types.h>
|
#include <zdwm/types.h>
|
||||||
@@ -119,15 +120,37 @@ bar_cell_set_indicator(zdwm_bar_item_t *item, size_t index, bool show) {
|
|||||||
item->dirty = true;
|
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 */
|
/* clang-format off */
|
||||||
zdwm_bar_cell_api_t bar_cell_api = {
|
const zdwm_bar_cell_api_t bar_cell_api = {
|
||||||
.get_cell_count = bar_cell_get_count,
|
.get_cell_count = bar_cell_get_count,
|
||||||
.set_cell_count = bar_cell_set_count,
|
.set_cell_count = bar_cell_set_count,
|
||||||
.cell_set_text = bar_cell_set_text,
|
.cell_set_text = bar_cell_set_text,
|
||||||
.cell_set_bg = bar_cell_set_bg,
|
.cell_set_bg = bar_cell_set_bg,
|
||||||
.cell_set_fg = bar_cell_set_fg,
|
.cell_set_fg = bar_cell_set_fg,
|
||||||
.cell_set_icon = bar_cell_set_icon,
|
.cell_set_icon = bar_cell_set_icon,
|
||||||
.cell_set_indicator = bar_cell_set_indicator,
|
.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 */
|
/* clang-format on */
|
||||||
|
|
||||||
|
|||||||
@@ -12,4 +12,4 @@ void bar_cell_set_region(
|
|||||||
bar_x_region_t 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;
|
||||||
|
|||||||
@@ -7,10 +7,7 @@
|
|||||||
|
|
||||||
#include "base/color.h"
|
#include "base/color.h"
|
||||||
|
|
||||||
typedef struct bar_x_region_t {
|
typedef struct zdwm_bar_x_region_t bar_x_region_t;
|
||||||
int32_t start;
|
|
||||||
int32_t end;
|
|
||||||
} bar_x_region_t;
|
|
||||||
|
|
||||||
typedef struct bar_cell_t {
|
typedef struct bar_cell_t {
|
||||||
zdwm_icon_t icon;
|
zdwm_icon_t icon;
|
||||||
@@ -20,6 +17,7 @@ typedef struct bar_cell_t {
|
|||||||
color_t fg;
|
color_t fg;
|
||||||
color_t bg;
|
color_t bg;
|
||||||
bar_x_region_t region;
|
bar_x_region_t region;
|
||||||
|
int32_t fixed_width;
|
||||||
bool show_indicator;
|
bool show_indicator;
|
||||||
bool dirty;
|
bool dirty;
|
||||||
} bar_cell_t;
|
} bar_cell_t;
|
||||||
|
|||||||
Reference in New Issue
Block a user