Files
zdwm/docs/config_system.org
Zedhugh Chen 329943ab3e 完善最小核心架构设计和数据结构简化
主要变更:

- 数据结构简化
  - 合并窗口元数据到 wm_window_t(删除 wm_window_meta.h)
  - 合并工作区名称到 wm_workspace_t(删除 wm_workspace_desc.h)
  - 简化布局标识符,只保留 name 字段
  - 删除 window_map,采用直接索引+线性查找

- 架构设计完善
  - 确定 window→workspace→output 固定归属关系
  - 制定 ID 分配策略(半静态实体直接索引,动态实体线性查找)
  - 确定显示器热插拔策略(检测到变化时重启 WM)
  - 添加工作区配置示例和多种配置方式

- 新增模块
  - wm_policy_config.h:策略配置开关
  - wm_service.h:核心外服务注册和事件订阅
  - WM_EVENT_ROUTING.org:事件路由详细文档
  - WORKSPACE_CONFIG_EXAMPLES.org:工作区配置示例
  - MINIMAL_CORE_WITH_EXTENSIONS.org:设计对比文档
  - config_system.org:配置系统设计

- 文档完善
  - 大幅扩展 README.org,补充 ID 分配、热插拔、配置集成等说明
  - 更新 WM_COMMAND_RULES.org,补充命令规则细节
  - 更新 WM_POLICY_APPLY_COMMAND_SKELETON.org,完善实现骨架
2026-03-11 05:28:39 +08:00

413 lines
10 KiB
Org Mode
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
* ZDWM 配置系统设计
** 概述
配置系统现在只保留两类正式输入:
1. 编译进二进制的默认配置
2. 用户动态库配置(=~/.config/zdwm/config.c= 编译得到 =config.so=
不再支持 XResources也不再保留 =Xft.dpi= 作为兼容输入。字体、DPI、颜色、边框、布局、规则、快捷键和服务设置都只来自默认配置和动态库配置。
配置系统的职责也收紧为:
1. 生成 core-native 配置快照。
2. 为 runtime adapter、service 层和输入绑定层提供稳定输入。
3. 不直接操作 =wm_state_t=
4. 不再暴露 =client_t==tag_t==monitor_t= 之类的旧对象。
** 设计目标
1. 配置层继续放在核心之外。
2. 配置结果必须能无损对接新的 =runtime/policy/layout/service= 边界。
3. 配置重载应以“重建快照并显式应用”为单位,而不是任意时刻写全局内存。
4. 彻底移除 XResources 路径,避免维护两套并行语义。
** 配置来源与优先级
最终有效配置按下面顺序构建:
#+BEGIN_EXAMPLE
默认配置
动态库配置 config.so
冻结为 zdwm_config_t
#+END_EXAMPLE
动态库配置优先级高于默认配置。
** 非目标
下面这些能力不再属于配置系统设计范围:
1. =Zdwm.*= 风格的 XResources 覆盖。
2. =Xft.dpi= 的额外兼容读取。
3. =hook_manage_new(client_t *)==hook_manage_unmanage(client_t *)= 这类直接对象钩子。
4. =arrange(tag_t *)= 这类依赖旧 tag 模型的布局接口。
5. 从配置层直接访问或修改 =wm= 全局对象。
** 配置输出模型
配置系统输出一份冻结后的配置快照,而不是一组可随时调用的副作用回调。
*** 外观配置
#+BEGIN_SRC c
typedef struct zdwm_appearance_config_t {
char *font_family;
uint32_t font_size;
uint32_t dpi;
uint16_t border_width;
uint16_t bar_y_padding;
uint16_t tag_x_padding;
color_set_t colors;
} zdwm_appearance_config_t;
#+END_SRC
这部分不进入最小核心状态,而是供 render/bar/text 这类核心外服务使用。
*** workspace 配置
=wm_workspace_t= 是运行时状态结构,里面包含 =focused_window_id= 这类不属于静态配置的数据。因此配置层应单独定义 workspace 配置描述:
#+BEGIN_SRC c
typedef struct zdwm_workspace_config_t {
wm_workspace_id_t id;
wm_layout_id_t initial_layout_id;
const char *name;
const char *symbol_text;
const char *symbol_icon_path;
} zdwm_workspace_config_t;
#+END_SRC
runtime adapter 会把它拆成:
1. =wm_workspace_t= 的初始数组
2. =wm_workspace_desc_t= 描述表
*** 管理规则
#+BEGIN_SRC c
typedef struct zdwm_manage_rule_t {
const char *title;
const char *app_id;
const char *class_name;
const char *instance_name;
wm_workspace_id_t workspace_id;
wm_manage_window_init_t initial_state;
bool switch_to_workspace;
} zdwm_manage_rule_t;
#+END_SRC
规则层的职责仅限于:
1. 匹配窗口元数据。
2. 决定 =MANAGE_WINDOW= 的 =workspace_id= 。
3. 决定 =MANAGE_WINDOW= 的 =initial_state= 。
4. 可选地决定是否切到目标 workspace。
规则层不直接管理窗口对象,也不直接写 =wm_state_t= 。
*** 快捷键绑定
快捷键也需要从旧的“直接 action 回调”收敛到新边界。
#+BEGIN_SRC c
typedef enum zdwm_binding_target_t {
ZDWM_BINDING_CORE_COMMAND,
ZDWM_BINDING_SERVICE_ACTION,
} zdwm_binding_target_t;
typedef struct zdwm_service_action_t {
const char *service_name;
const char *action_name;
const char *string_arg;
int32_t int_arg;
} zdwm_service_action_t;
typedef struct zdwm_keybinding_t {
uint32_t modifiers;
xkb_keysym_t keysym;
zdwm_binding_target_t target;
union {
wm_command_t command;
zdwm_service_action_t service_action;
} as;
} zdwm_keybinding_t;
#+END_SRC
=core command= 用于工作区切换、布局切换、浮动切换、焦点切换等窗口管理行为。
=service action= 用于启动外部程序、刷新状态服务、触发核心外功能。
*** 服务设置
#+BEGIN_SRC c
typedef struct zdwm_service_setting_t {
const char *service_name;
const char *key;
const char *value;
} zdwm_service_setting_t;
#+END_SRC
服务配置由配置层生成,但仍由 service 层解释和持有。
*** 总配置快照
#+BEGIN_SRC c
typedef struct zdwm_config_source_t {
bool has_user_lib;
} zdwm_config_source_t;
typedef struct zdwm_runtime_config_t {
wm_policy_config_t policy;
zdwm_workspace_config_t *workspaces;
size_t workspace_count;
wm_layout_slot_t *layouts;
size_t layout_count;
} zdwm_runtime_config_t;
typedef struct zdwm_config_t {
zdwm_runtime_config_t runtime;
zdwm_appearance_config_t appearance;
zdwm_manage_rule_t *rules;
size_t rule_count;
zdwm_keybinding_t *keybindings;
size_t keybinding_count;
const char *const *autostart_list;
zdwm_service_setting_t *service_settings;
size_t service_setting_count;
zdwm_config_source_t source;
} zdwm_config_t;
#+END_SRC
注意这里故意不把 =outputs= 和启动时已有窗口塞进配置结果里。它们属于 backend 发现结果,不属于静态配置。
** 与最小核心的集成方式
配置层与 runtime 的拼装分为两步:
*** 第一步:构建配置快照
#+BEGIN_EXAMPLE
默认配置
config.so 覆盖与增量注册
zdwm_config_t
#+END_EXAMPLE
*** 第二步:由 adapter 组装 runtime bootstrap
#+BEGIN_EXAMPLE
zdwm_config_t
+
backend 发现的 outputs
+
backend 扫描得到的初始 MANAGE_WINDOW 命令
wm_runtime_bootstrap_t
#+END_EXAMPLE
组装规则应为:
1. =policy= 来自 =config.runtime.policy= 。
2. =workspaces= 来自 =config.runtime.workspaces[]= 的静态定义。
3. =workspace_descs= 来自 =config.runtime.workspaces[]= 中的展示字段。
4. =outputs= 来自 backend。
5. =initial_commands= 来自 backend 对已有窗口的扫描和规则匹配。
这样配置层不需要知道当前有哪些物理输出,也不需要自己扫描窗口。
** 动态库 API
动态库 API 由“builder 风格”的配置写入接口组成:
#+BEGIN_SRC c
typedef struct zdwm_api_t {
uint32_t version;
// appearance
void (*set_font)(const char *family, uint32_t size);
void (*set_dpi)(uint32_t dpi);
void (*set_color)(const char *name, const char *hex);
void (*set_border_width)(uint16_t width);
void (*set_padding)(uint16_t bar_y, uint16_t tag_x);
// runtime config
void (*set_policy)(wm_policy_config_t policy);
void (*define_workspace)(zdwm_workspace_config_t workspace);
void (*register_layout)(wm_layout_slot_t layout);
// rules
void (*add_rule)(zdwm_manage_rule_t rule);
// bindings
void (*add_keybinding)(zdwm_keybinding_t binding);
void (*clear_keybindings)(void);
// autostart and services
void (*add_autostart)(const char *command);
void (*set_service_option)(const char *service_name,
const char *key,
const char *value);
} zdwm_api_t;
#+END_SRC
用户动态库入口保持简单:
#+BEGIN_SRC c
typedef struct zdwm_user_config_t {
void (*cleanup)(void);
} zdwm_user_config_t;
zdwm_user_config_t *zdwm_config_init(zdwm_api_t *api);
#+END_SRC
=cleanup()= 只负责动态库自身资源,不负责 runtime 状态回收。
** 加载流程
#+BEGIN_SRC c
zdwm_config_t *config_load(void) {
zdwm_config_t *config = calloc(1, sizeof(*config));
config_apply_defaults(config);
config_load_user_lib(config);
config_finalize(config);
return config;
}
#+END_SRC
这里的 =config_finalize()= 建议至少做这些事情:
1. 检查 workspace id 是否唯一。
2. 检查 layout id 是否唯一。
3. 检查规则和快捷键数组是否合法。
4. 补齐未设置的默认值。
5. 冻结动态数组,避免运行时再被随意写入。
** 管理规则接入链路
管理规则不直接操作窗口,推荐链路如下:
#+BEGIN_EXAMPLE
backend 发现新窗口
同步窗口 metadata
在 rules 中匹配
生成 WM_COMMAND_MANAGE_WINDOW
- workspace_id
- initial_state
runtime / policy apply_command()
#+END_EXAMPLE
这样规则层只负责“把 metadata 翻译成命令参数”。
** 快捷键接入链路
#+BEGIN_EXAMPLE
backend 输入事件
keybinding table 匹配
若 target == ZDWM_BINDING_CORE_COMMAND:
生成 wm_command_t
若 target == ZDWM_BINDING_SERVICE_ACTION:
发送给 service 层
#+END_EXAMPLE
配置层不再保存 =void (*action)(const void *)= 这类旧式回调。
** 热重载
配置热重载仍然可以保留,但边界必须清晰。
推荐流程:
#+BEGIN_EXAMPLE
收到 SIGHUP
重建 zdwm_config_t
原子替换:
- appearance
- policy
- keybindings
- workspace descriptors
- layout registry
- service settings
通知相关 service 刷新
#+END_EXAMPLE
热重载约束:
1. 不直接改 =wm_state_t=
2. 规则变更只影响后续新管理的窗口,不回溯重算现有窗口。
3. workspace 描述、颜色、字体、DPI、bindings、policy 适合热重载。
4. 大规模布局或 service 拓扑变化,必要时可以走受控重启。
** 文件结构
#+BEGIN_EXAMPLE
src/
├── config.h # 配置系统头文件
├── config.c # 配置加载主逻辑
├── config_defaults.c # 默认配置
├── config_lib.c # 动态库加载
├── config_api.c # builder API
└── config_validate.c # 配置收尾校验(可选)
docs/
└── config_system.org # 本文档
#+END_EXAMPLE
这里不再有 =config_xres.c= 或任何通用 XResources 解析模块。
** 迁移说明
下面这些旧设计应视为废弃:
1. =默认配置 -> XResources -> 动态库配置= 三层覆盖模型。
2. =Xft.dpi= 的兼容读取。
3. =hook_manage_new(client_t *)==hook_manage_unmanage(client_t *)=
4. =add_layout(... arrange(tag_t *tag))=
5. 任何直接依赖 =client_t==tag_t==monitor_t= 的配置接口。
迁移后的对应关系:
1. tag 名称与符号 → =zdwm_workspace_config_t=
2. 布局注册 → =wm_layout_slot_t=
3. 窗口规则 → =zdwm_manage_rule_t=
4. 快捷键动作 → =wm_command_t==zdwm_service_action_t=
5. 外观设置 → =zdwm_appearance_config_t=
** 实施优先级
1. =config_defaults.c=
先保证“无用户配置”也能跑。
2. =config.c + config_lib.c=
打通默认配置和动态库配置装配。
3. =config_api.c=
落地新的 builder API替代旧 action/hook 模型。
4. runtime adapter 对接
=zdwm_config_t= 装配成 =wm_runtime_bootstrap_t= 、规则表、service 设置和 keybinding table。