From 3d258bdc8bfa316f2c188cb0fde46b7458d2671a Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Sat, 18 Jul 2026 18:23:52 +0800 Subject: [PATCH] =?UTF-8?q?feat(bar):=20=E5=B0=86=20tray=20=E4=BD=9C?= =?UTF-8?q?=E4=B8=BA=E4=B8=80=E4=B8=AA=20item=20=E9=9B=86=E6=88=90?= =?UTF-8?q?=E5=88=B0=20bar=20=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 1 + src/bar/bar.c | 10 ++++++ src/bar/bar.h | 2 ++ src/bar/tray.c | 78 +++++++++++++++++++++++++++++++++++++++++++ src/bar/tray.h | 5 +++ src/runtime/runtime.c | 1 + 6 files changed, 97 insertions(+) create mode 100644 src/bar/tray.c create mode 100644 src/bar/tray.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8257685..4804068 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ add_executable(${APP_NAME} ${SOURCE_DIR}/bar/binding.c ${SOURCE_DIR}/bar/cell.c ${SOURCE_DIR}/bar/text.c + ${SOURCE_DIR}/bar/tray.c ${SOURCE_DIR}/bar/windows.c ${SOURCE_DIR}/bar/workspaces.c diff --git a/src/bar/bar.c b/src/bar/bar.c index fe82e88..43e7902 100644 --- a/src/bar/bar.c +++ b/src/bar/bar.c @@ -12,6 +12,7 @@ #include "bar/binding.h" #include "bar/cell.h" #include "bar/text.h" +#include "bar/tray.h" #include "bar/types.h" #include "bar/windows.h" #include "bar/workspaces.h" @@ -130,9 +131,14 @@ static void bar_output_add_windows( bar_windows_add_listeners(listeners, item->state); } +static inline void bar_output_add_tray(bar_output_t *bar_output, tray_t *tray) { + bar_add_item(bar_output->output_id, &bar_output->right, bar_tray, tray); +} + void bar_init(bar_t *bar, listeners_t *listeners) { auto c = &bar->config; bar->ctx = text_context_create(c->font_family, c->font_size, c->dpi); + auto tray = &bar->tray; for (size_t i = 0; i < bar->count; ++i) { auto bar_output = &bar->bars[i]; @@ -141,6 +147,10 @@ void bar_init(bar_t *bar, listeners_t *listeners) { bar_output_add_workspace(bar_output, &bar->config, listeners); bar_output_add_binding(bar_output, &bar->config, listeners); bar_output_add_windows(bar_output, &bar->config, listeners); + + if (tray->api.host_window(tray->handle) == bar_output->window_id) { + bar_output_add_tray(bar_output, &bar->tray); + } } bar->timerfd = time_create_monotonic_timerfd_by_fps(bar->config.fps); diff --git a/src/bar/bar.h b/src/bar/bar.h index 0152383..d009350 100644 --- a/src/bar/bar.h +++ b/src/bar/bar.h @@ -11,6 +11,7 @@ #include "bar/types.h" #include "base/color.h" #include "common/listeners.h" +#include "interface/tray.h" typedef struct bar_output_t { cairo_t *cr; @@ -37,6 +38,7 @@ typedef struct bar_t { zdwm_bar_config_t config; bar_palette_t palette; text_context_t *ctx; + tray_t tray; } bar_t; void bar_init(bar_t *bar, listeners_t *listeners); diff --git a/src/bar/tray.c b/src/bar/tray.c new file mode 100644 index 0000000..cfe2f86 --- /dev/null +++ b/src/bar/tray.c @@ -0,0 +1,78 @@ +#include "bar/tray.h" + +#include +#include +#include +#include + +#include "base/memory.h" +#include "interface/tray.h" + +typedef struct bar_tray_state_t { + tray_t tray; + bool dirty; +} bar_tray_state_t; + +static void bar_tray_icons_changed(void *user_data) { + bar_tray_state_t *state = user_data; + state->dirty = true; +} + +static void *bar_tray_create_state(zdwm_output_id_t output_id, void *config) { + tray_t *tray = config; + assert(tray != nullptr); + + auto state = p_new(bar_tray_state_t, 1); + state->tray = *tray; + tray->api.set_listener(tray->handle, bar_tray_icons_changed, state); + + return state; +} + +static void bar_tray_update( + zdwm_bar_item_t *item, + const zdwm_bar_cell_api_t *cell_api, + void *state +) { + bar_tray_state_t *data = state; + if (!data->dirty) return; + + auto tray_handle = data->tray.handle; + auto tray_api = &data->tray.api; + auto icon_count = tray_api->icon_count(tray_handle); + auto cell_count = cell_api->get_cell_count(item); + if (cell_count == icon_count) { + data->dirty = false; + return; + } + + cell_api->set_cell_count(item, icon_count); + auto cell_width = tray_api->icon_size(tray_handle); + for (size_t i = 0; i < icon_count; ++i) { + cell_api->cell_set_fixed_width(item, i, cell_width); + } + + data->dirty = false; +} + +static void bar_tray_after_layout(const zdwm_bar_item_hook_params_t *params) { + bar_tray_state_t *state = params->state; + auto tray_handle = state->tray.handle; + auto tray_api = &state->tray.api; + tray_api->place(tray_handle, params->region.start); +} + +static void bar_tray_destroy_state(void *state) { + if (!state) return; + + bar_tray_state_t *data = state; + p_delete(&data); +} + +zdwm_bar_item_type_t bar_tray = { + .create_state = bar_tray_create_state, + .update = bar_tray_update, + .after_layout = bar_tray_after_layout, + .destroy_state = bar_tray_destroy_state, + .update_interval_ms = 0, +}; diff --git a/src/bar/tray.h b/src/bar/tray.h new file mode 100644 index 0000000..ceb6ed9 --- /dev/null +++ b/src/bar/tray.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern zdwm_bar_item_type_t bar_tray; diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index b7f4bb0..40d272b 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -122,6 +122,7 @@ static void runtime_init_bar(runtime_t *runtime) { auto color = bar->palette.bg.argb; auto bar_window = backend_create_bar_window(backend, bar_rect, color, false); + bar->tray = bar_window.tray; auto bar_output = &bar->bars[i]; bar_output->cr = bar_window.cr; bar_output->window_id = bar_window.window_id;