feat(bar): 实现 bar 可见性切换 action

This commit is contained in:
2026-06-06 04:44:56 +08:00
parent be37b17c2e
commit adf839bf21
11 changed files with 152 additions and 5 deletions

View File

@@ -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 {

View File

@@ -5,6 +5,7 @@
#include <stddef.h>
#include <stdint.h>
#include <zdwm/action.h>
#include <zdwm/bar.h>
#include <zdwm/layout.h>
#include <zdwm/listeners.h>
#include <zdwm/rules.h>
@@ -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;
/**

View File

@@ -1,5 +1,6 @@
#pragma once
#include <cairo.h>
#include <stddef.h>
#include <zdwm/bar.h>
#include <zdwm/types.h>
@@ -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];

View File

@@ -2,6 +2,7 @@
#include <dlfcn.h>
#include <stddef.h>
#include <zdwm/bar.h>
#include <zdwm/config.h>
#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);

View File

@@ -1,6 +1,7 @@
#pragma once
#include <stddef.h>
#include <zdwm/bar.h>
#include <zdwm/types.h>
#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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -1,7 +1,9 @@
#pragma once
#include <stdint.h>
#include <zdwm/action.h>
#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;
/**

View File

@@ -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,

View File

@@ -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,

View File

@@ -5,9 +5,11 @@
#include <stdint.h>
#include <zdwm/layout.h>
#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;
}