8.7 KiB
8.7 KiB
Zdwm 配置系统设计文档
概述
三层配置系统,按优先级从低到高加载:
内置默认配置 → XResources → 动态库配置
(后者覆盖前者)
配置层次
第一层:内置默认配置
- 位置: 编译到二进制中
- 作用: 提供完整的默认配置,确保无外部配置时也能正常运行
- 范围: 所有配置项
第二层:XResources 配置
- 位置:
~/.Xresources或~/.config/zdwm/Xresources - 作用: 覆盖外观配置(颜色、字体、边框等)
- 特点: 无需重新编译,
xrdb后重启生效 - 范围: 仅外观配置
第三层:动态库配置
- 位置:
~/.config/zdwm/config.c→config.so - 作用: 高级配置(快捷键、规则、自定义布局等)
- 特点: 最大灵活性,需编译 C 代码
- 范围: 所有配置项
配置加载流程
1. 加载内置默认配置
↓
2. 尝试加载 XResources
├─ 成功 → 覆盖默认配置中的外观项
└─ 失败 → 跳过,保持默认值
↓
3. 尝试加载动态库
├─ 存在 → 调用 zdwm_config_init(),增量修改配置
└─ 不存在 → 跳过
↓
4. 应用最终配置
数据结构
配置优先级标记
typedef struct config_source_t {
bool has_xres; // 是否加载了 XResources
bool has_user_lib; // 是否加载了用户动态库
} config_source_t;
完整配置结构
typedef struct 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;
// 快捷键
const keyboard_t *key_list;
size_t key_count;
// 布局
const layout_t *layout_list;
size_t layout_count;
// 标签
const char *const *tags;
// 规则
const rule_t *rules;
size_t rules_count;
// 自动启动
const char *const *autostart_list;
// 钩子
void (*hook_manage_new)(client_t *client);
void (*hook_manage_unmanage)(client_t *client);
// 元数据
config_source_t source;
} config_t;
API 接口(动态库)
zdwm_api_t
typedef struct zdwm_api_t {
uint32_t version;
// 外观(覆盖 XResources)
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);
// 快捷键(增量式)
void (*add_keybinding)(uint32_t modifiers, xcb_keysym_t keysym,
void (*action)(const void *),
const void *arg);
void (*remove_keybinding)(uint32_t modifiers, xcb_keysym_t keysym);
void (*clear_keybindings)(void);
// 规则
void (*add_rule)(const char *role, const char *class,
int32_t tag_index, bool floating,
bool fullscreen, bool maximize,
bool switch_to_tag);
// 自动启动
void (*add_autostart)(const char *command);
// 布局
void (*add_layout)(const char *symbol, void (*arrange)(tag_t *tag));
// 钩子
void (*hook_manage_new)(void (*hook)(client_t *client));
void (*hook_manage_unmanage)(void (*hook)(client_t *client));
} zdwm_api_t;
用户配置初始化函数
typedef struct zdwm_user_config_t {
void (*cleanup)(void);
} zdwm_user_config_t;
// 用户在 config.c 中实现此函数(可选)
zdwm_user_config_t *zdwm_config_init(zdwm_api_t *api);
XResources 支持的配置项
配置项命名规范
Zdwm.font.family # 字体族
Zdwm.font.size # 字体大小
Zdwm.border.width # 边框宽度
Zdwm.padding.bar_y # Bar 上下内边距
Zdwm.padding.tag_x # Tag 左右内边距
Zdwm.color.bar # Bar 背景色
Zdwm.color.tag # Tag 背景色
Zdwm.color.tagActive # 活动 Tag 背景色
Zdwm.color.tagText # Tag 文字颜色
Zdwm.color.tagActiveText # 活动 Tag 文字颜色
Zdwm.color.border # 边框颜色
Zdwm.color.borderActive # 活动窗口边框颜色
数据类型映射
XResources 类型 → C 类型
--------------------------→-------------------
字符串 → char *
整数 → uint32_t
颜色 (#RRGGBB) → color_t (uint32_t argb)
实现要点
1. 配置加载函数
// src/config.h
config_t *config_load_full(void);
void config_free(config_t *config);
config_t *config_reload(void);
2. 加载顺序
// src/config.c
config_t *config_load_full(void) {
config_t *config = calloc(1, sizeof(config_t));
// 第一步:默认配置
config_apply_defaults(config);
// 第二步:XResources(覆盖外观)
config_load_xres(config);
// 第三步:动态库(覆盖所有)
config_load_user_lib(config);
return config;
}
3. XResources 解析
// src/config_xres.c
bool config_load_xres(config_t *config) {
if (!xres_init_xrm_db()) return false;
// 覆盖外观配置
xres_get_string("Zdwm.font.family", &config->font_family, default_font);
xres_get_uint32("Zdwm.font.size", &config->font_size);
// ...
xres_clean();
return true;
}
4. 动态库加载
// src/config_lib.c
bool config_load_user_lib(config_t *config) {
const char *path = "~/.config/zdwm/config.so";
void *handle = dlopen(path, RTLD_LAZY);
if (!handle) return false;
zdwm_user_config_t *(*init)(zdwm_api_t *) = dlsym(handle, "zdwm_config_init");
if (!init) {
dlclose(handle);
return false; // 没有配置函数是正常的
}
zdwm_api_t api = create_api(config);
init(&api);
return true;
}
配置热重载
XResources 热重载
编辑 XResources 后的操作流程:
# 1. 编辑配置文件
vim ~/.Xresources
# 2. 加载到 X Server
xrdb -merge ~/.Xresources
# 3. 重载 zdwm 配置
killall -HUP zdwm
实现要点
// src/wm.c
// 重新应用配置
static void wm_reapply_config(void) {
// 重新初始化字体
text_reinit_pango_layout(wm.font_family, wm.font_size, wm.dpi);
// 重新计算 bar 高度
wm.bar_height = text_get_height() + 2 * wm.padding.bar_y;
// 刷新所有 monitor 的 bar
for (monitor_t *m = wm.monitor_list; m; m = m->next) {
monitor_draw_bar(m);
}
xcb_flush(wm.xcb_conn);
}
// SIGHUP 信号处理器
static void reload_config_handler(int sig) {
log("Received SIGHUP, reloading configuration...");
// 清理旧的 XResources 数据库
xres_clean();
// 重新加载 XResources
wm_get_xres_config();
// 重新应用配置
wm_reapply_config();
log("Configuration reloaded successfully");
}
// 在 wm_setup_signal() 中注册
void wm_setup_signal(void) {
// ... 现有信号处理 ...
signal(SIGHUP, reload_config_handler);
signal(SIGUSR1, reload_config_handler); // 备用信号
}
xres 模块需要添加
// src/xres.h
void xres_reload(void);
// src/xres.c
void xres_reload(void) {
if (wm.xrm) {
xcb_xrm_database_free(wm.xrm);
wm.xrm = nullptr;
}
xres_init_xrm_db();
}
完整重载流程
用户编辑 XResources
↓
xrdb -merge ~/.Xresources (加载到 X Server)
↓
killall -HUP zdwm (发送重载信号)
↓
zdwm 收到 SIGHUP
↓
xres_clean() (清理旧数据库)
↓
wm_get_xres_config() (重新读取 XResources)
↓
wm_reapply_config() (应用新配置)
↓
monitor_draw_bar() (刷新显示)
文件结构
src/
├── config.h # 配置系统头文件
├── config.c # 配置加载主逻辑
├── config_default.c # 内置默认配置
├── config_xres.c # XResources 解析
├── config_lib.c # 动态库加载
└── config_api.c # API 实现(供动态库调用)
docs/
└── config_system.md # 本文档
依赖关系
config.c
├── config_default.c (内置默认值)
├── config_xres.c (XResources 解析)
│ └── xres.c (已有)
└── config_lib.c (动态库加载)
└── dlopen()
实现优先级
| 优先级 | 模块 | 说明 |
|---|---|---|
| P0 | config_default.c | 定义默认配置值 |
| P0 | config.c | 主加载逻辑 |
| P1 | config_xres.c | XResources 支持(已有基础) |
| P1 | 热重载 | SIGHUP 支持(配合 XResources) |
| P1 | config_lib.c | 动态库加载 |
| P2 | config_api.c | API 实现 |
P0: 核心功能,必须实现 P1: 重要功能,提升用户体验 P2: 增强功能,可后续添加