From adf839bf218da162518bf1be466f14df943b68bf Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Sat, 6 Jun 2026 04:44:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(bar):=20=E5=AE=9E=E7=8E=B0=20bar=20?= =?UTF-8?q?=E5=8F=AF=E8=A7=81=E6=80=A7=E5=88=87=E6=8D=A2=20action?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/zdwm/action.h | 2 ++ include/zdwm/config.h | 9 +++++++ src/bar/bar.h | 2 ++ src/config/runtime_config.c | 14 +++++++++++ src/config/runtime_config.h | 2 ++ src/core/command.h | 6 +++++ src/core/policy.c | 47 +++++++++++++++++++++++++++++++++++++ src/core/policy.h | 10 ++++++++ src/core/state.c | 16 +++++++++++++ src/core/state.h | 24 +++++++++++++++++++ src/runtime/runtime.c | 25 ++++++++++++++++---- 11 files changed, 152 insertions(+), 5 deletions(-) diff --git a/include/zdwm/action.h b/include/zdwm/action.h index 3511185..af36852 100644 --- a/include/zdwm/action.h +++ b/include/zdwm/action.h @@ -31,6 +31,8 @@ typedef enum zdwm_action_type_t { ZDWM_ACTION_WINDOW_SEND_TO_WORKSPACE_SAME_OUTPUT_BY_INDEX, ZDWM_ACTION_WINDOW_CYCLE_OUTPUT, + + ZDWM_ACTION_BAR_TOGGLE_VISIBILITY, } zdwm_action_type_t; typedef struct zdwm_action_data_spawn_t { diff --git a/include/zdwm/config.h b/include/zdwm/config.h index d6e49e2..349380c 100644 --- a/include/zdwm/config.h +++ b/include/zdwm/config.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -206,6 +207,14 @@ typedef struct zdwm_api_t { ); /** @} */ + + /** @name bar 配置 + * @{ */ + void (*set_bar_config)( + zdwm_config_builder_t *builder, + zdwm_bar_config_t config + ); + /** @} */ } zdwm_api_t; /** diff --git a/src/bar/bar.h b/src/bar/bar.h index e3b642e..e71763e 100644 --- a/src/bar/bar.h +++ b/src/bar/bar.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -7,6 +8,7 @@ #include "bar/types.h" typedef struct bar_output_t { + cairo_t *cr; zdwm_window_id_t window_id; zdwm_output_id_t output_id; bar_side_t sides[ZDWM_BAR_SIDE_COUNT]; diff --git a/src/config/runtime_config.c b/src/config/runtime_config.c index f8e6b6c..ea08e0a 100644 --- a/src/config/runtime_config.c +++ b/src/config/runtime_config.c @@ -2,6 +2,7 @@ #include #include +#include #include #include "base/array.h" @@ -29,6 +30,7 @@ struct zdwm_config_builder_t { border_config_t border; binding_table_t *binding_table; listeners_t listeners; + zdwm_bar_config_t bar; }; void runtime_config_cleanup(runtime_init_desc_t *desc) { @@ -279,6 +281,14 @@ static void runtime_config_subscribe_window_removed( listeners_add_window_removed_listener(&builder->listeners, fn, user_data); } +static void runtime_config_set_bar_config( + zdwm_config_builder_t *builder, + zdwm_bar_config_t config +) { + if (!builder) return; + builder->bar = config; +} + static bool config_builder_finish( zdwm_config_builder_t *builder, runtime_init_desc_t *out @@ -294,12 +304,14 @@ static bool config_builder_finish( out->workspaces = builder->workspaces; out->workspace_count = builder->workspace_count; out->listeners = builder->listeners; + out->bar = builder->bar; builder->binding_table = nullptr; builder->workspaces = nullptr; builder->workspace_count = 0; builder->workspace_capacity = 0; builder->output_count = 0; p_clear(&builder->listeners, 1); + p_clear(&builder->bar, 1); return true; } @@ -342,6 +354,8 @@ static bool runtime_config_build( .subscribe_window_added = runtime_config_subscribe_window_added, .subscribe_window_updated = runtime_config_subscribe_window_updated, .subscribe_window_removed = runtime_config_subscribe_window_removed, + + .set_bar_config = runtime_config_set_bar_config, }; bool ok = setup(&api, &builder, outputs, output_count) && config_builder_finish(&builder, out); diff --git a/src/config/runtime_config.h b/src/config/runtime_config.h index 30ccd96..69a1612 100644 --- a/src/config/runtime_config.h +++ b/src/config/runtime_config.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "core/backend.h" @@ -24,6 +25,7 @@ typedef struct runtime_init_desc_t { void *config_module_handle; binding_table_t *binding_table; listeners_t listeners; + zdwm_bar_config_t bar; } runtime_init_desc_t; bool runtime_config_load(const char *override_path, runtime_init_desc_t *out); diff --git a/src/core/command.h b/src/core/command.h index 1069b29..5fcaf6f 100644 --- a/src/core/command.h +++ b/src/core/command.h @@ -22,6 +22,7 @@ typedef enum command_type_t { ZDWM_COMMAND_SET_CURRENT_OUTPUT, ZDWM_COMMAND_SET_LAYOUT, ZDWM_COMMAND_SET_BINDING_MODE, + ZDWM_COMMAND_SET_BAR_VISIBILITY, ZDWM_COMMAND_QUIT, } command_type_t; @@ -64,6 +65,10 @@ typedef struct set_binding_mode_command_t { zdwm_binding_mode_id_t mode; } set_binding_mode_command_t; +typedef struct visibility_command_t { + bool visible; +} visibility_command_t; + typedef struct quit_command_t { bool will_restart; } quit_command_t; @@ -98,6 +103,7 @@ typedef struct command_t { set_current_output_command_t current_output; set_layout_command_t layout; set_binding_mode_command_t binding_mode; + visibility_command_t bar_visibility; quit_command_t quit; } as; } command_t; diff --git a/src/core/policy.c b/src/core/policy.c index c7c9e69..abc0842 100644 --- a/src/core/policy.c +++ b/src/core/policy.c @@ -355,6 +355,19 @@ static void send_window_to_workspace_same_output_by_index( command_buffer_push(command_buffer, &send_window_to_workspace_command); } +static void toggle_bar_visibility( + const policy_bar_t *bar, + command_buffer_t *command_buffer +) { + command_t set_bar_visibility_command = { + .type = ZDWM_COMMAND_SET_BAR_VISIBILITY, + .as.bar_visibility = { + .visible = !*bar->visible, + }, + }; + command_buffer_push(command_buffer, &set_bar_visibility_command); +} + static void policy_resolve_action( const policy_context_t *ctx, const zdwm_action_t *action, @@ -420,6 +433,9 @@ static void policy_resolve_action( case ZDWM_ACTION_WINDOW_CYCLE_OUTPUT: cycle_window_output(ctx->state, &action->as.window_cycle_output, out); break; + case ZDWM_ACTION_BAR_TOGGLE_VISIBILITY: + toggle_bar_visibility(&ctx->bar, out); + break; } } @@ -1365,6 +1381,34 @@ static void set_binding_mode( listeners_notify_binding_mode(ctx->listeners, ctx->bind_table); } +static void +set_bar_visibility(const policy_context_t *ctx, bool visible, plan_t *plan) { + auto bar = &ctx->bar; + if (*bar->visible == visible) return; + + *bar->visible = visible; + + inset_t inset = {0}; + if (visible) { + if (bar->show_top) inset.top = bar->height; + else inset.bottom = bar->height; + } + + auto state = ctx->state; + for (size_t i = 0; i < state->output_count; ++i) { + auto output = state_output_at(state, i); + state_output_inset_workarea(state, output->id, inset); + } + + auto push_effect = visible ? plan_push_map_effect : plan_push_unmap_effect; + for (size_t i = 0; i < bar->windows->count; ++i) { + auto window_id = bar->windows->windows[i]; + push_effect(plan, window_id); + } + + plan->need_relayout = true; +} + void policy_apply_command( const policy_context_t *ctx, const command_buffer_t *command_buffer, @@ -1428,6 +1472,9 @@ void policy_apply_command( case ZDWM_COMMAND_SET_BINDING_MODE: set_binding_mode(ctx, cmd->as.binding_mode.mode, plan); break; + case ZDWM_COMMAND_SET_BAR_VISIBILITY: + set_bar_visibility(ctx, cmd->as.bar_visibility.visible, plan); + break; case ZDWM_COMMAND_QUIT: plan->quit = true; plan->will_restart = cmd->as.quit.will_restart; diff --git a/src/core/policy.h b/src/core/policy.h index 26ea93a..ed47bad 100644 --- a/src/core/policy.h +++ b/src/core/policy.h @@ -1,7 +1,9 @@ #pragma once +#include #include +#include "base/window_list.h" #include "core/binding.h" #include "core/command_buffer.h" #include "core/event.h" @@ -12,6 +14,13 @@ #include "core/state.h" #include "core/types.h" +typedef struct policy_bar_t { + bool *visible; + window_list_t *windows; + int32_t height; + bool show_top; +} policy_bar_t; + typedef struct policy_context_t { binding_table_t *bind_table; state_t *state; @@ -19,6 +28,7 @@ typedef struct policy_context_t { const listeners_t *listeners; const border_config_t *border; const layout_registry_t *layouts; + const policy_bar_t bar; } policy_context_t; /** diff --git a/src/core/state.c b/src/core/state.c index 1ab3d49..c3fa300 100644 --- a/src/core/state.c +++ b/src/core/state.c @@ -232,6 +232,22 @@ const output_t *state_output_at(const state_t *state, size_t index) { return nullptr; } +void state_output_inset_workarea( + state_t *state, + output_id_t output_id, + inset_t inset +) { + auto output = (output_t *)state_output_get(state, output_id); + if (!output) return; + + auto workarea = output->geometry; + workarea.y += inset.top; + workarea.x += inset.left; + workarea.width -= inset.left + inset.right; + workarea.height -= inset.top + inset.bottom; + output->workarea = workarea; +} + void state_output_set_workarea( state_t *state, output_id_t output_id, diff --git a/src/core/state.h b/src/core/state.h index 5108704..2353a77 100644 --- a/src/core/state.h +++ b/src/core/state.h @@ -115,6 +115,30 @@ bool state_workspace_show(const state_t *state, workspace_id_t workspace_id); */ const output_t *state_output_get(const state_t *state, output_id_t id); const output_t *state_output_at(const state_t *state, size_t index); + +typedef struct inset_t { + int32_t top; + int32_t right; + int32_t bottom; + int32_t left; +} inset_t; + +/** + * @brief 按四边内缩量重新计算 output 的可用区域 + * + * @details 以 output->geometry 为基准,各边向内收缩对应像素数,将结果写入 + * output->workarea。未设置的边默认为 0,表示该边不收缩。 + * + * @param state 状态实例指针 + * @param output_id 目标 output 的 id + * @param inset 四边内缩量(像素),值为 0 表示该边不收缩 + */ +void state_output_inset_workarea( + state_t *state, + output_id_t output_id, + inset_t inset +); + void state_output_set_workarea( state_t *state, output_id_t output_id, diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 579adf1..0a55db1 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -5,9 +5,11 @@ #include #include +#include "bar/bar.h" #include "base/array.h" #include "base/log.h" #include "base/memory.h" +#include "base/window_list.h" #include "config/runtime_config.h" #include "core/backend.h" #include "core/binding.h" @@ -38,6 +40,9 @@ typedef struct runtime_t { void *config_module_handle; binding_table_t *binding_table; listeners_t listeners; + + bar_t bar; + window_list_t bar_windows; } runtime_t; static bool runtime_workspace_desc_has_valid_layouts( @@ -82,10 +87,12 @@ static bool runtime_init(runtime_t *runtime, runtime_init_desc_t *desc) { runtime->config_module_handle = desc->config_module_handle; runtime->binding_table = desc->binding_table; runtime->listeners = desc->listeners; + runtime->bar.config = desc->bar; desc->backend = nullptr; desc->config_module_handle = nullptr; desc->binding_table = nullptr; p_clear(&desc->listeners, 1); + p_clear(&desc->bar, 1); state_init( &runtime->state, @@ -137,6 +144,7 @@ static void runtime_shutdown(runtime_t *runtime) { binding_table_destroy(runtime->binding_table); runtime->binding_table = nullptr; listeners_cleanup(&runtime->listeners); + window_list_cleanup(&runtime->bar_windows); backend_destroy(runtime->backend); runtime->backend = nullptr; if (runtime->config_module_handle) dlclose(runtime->config_module_handle); @@ -318,13 +326,20 @@ static void runtime_arrange(runtime_t *runtime) { static policy_context_t policy_context_init(runtime_t *runtime) { policy_context_t ctx = { - .bind_table = (runtime)->binding_table, - .state = &(runtime)->state, - .rules = &(runtime)->rules, + .bind_table = runtime->binding_table, + .state = &runtime->state, + .rules = &runtime->rules, .listeners = &runtime->listeners, - .border = &(runtime)->border, - .layouts = &(runtime)->layouts, + .border = &runtime->border, + .layouts = &runtime->layouts, + .bar = { + .visible = &runtime->bar.visible, + .windows = &runtime->bar_windows, + .height = runtime->bar.config.height, + .show_top = runtime->bar.config.show_top, + }, }; + return ctx; }