408 lines
8.7 KiB
Markdown
408 lines
8.7 KiB
Markdown
# Zdwm 配置系统设计文档
|
||
|
||
## 概述
|
||
|
||
三层配置系统,按优先级从低到高加载:
|
||
|
||
```
|
||
内置默认配置 → XResources → 动态库配置
|
||
(后者覆盖前者)
|
||
```
|
||
|
||
---
|
||
|
||
## 配置层次
|
||
|
||
### 第一层:内置默认配置
|
||
- **位置**: 编译到二进制中
|
||
- **作用**: 提供完整的默认配置,确保无外部配置时也能正常运行
|
||
- **范围**: 所有配置项
|
||
|
||
### 第二层:XResources 配置
|
||
- **位置**: `~/.Xresources` 或 `~/.config/zdwm/Xresources`
|
||
- **作用**: 覆盖外观配置(颜色、字体、边框等)
|
||
- **特点**: 无需重新编译,`xrdb` 后重启生效
|
||
- **范围**: 仅外观配置
|
||
|
||
### 第三层:动态库配置
|
||
- **位置**: `~/.config/zdwm/config.c` → `config.so`
|
||
- **作用**: 高级配置(快捷键、规则、自定义布局等)
|
||
- **特点**: 最大灵活性,需编译 C 代码
|
||
- **范围**: 所有配置项
|
||
|
||
---
|
||
|
||
## 配置加载流程
|
||
|
||
```
|
||
1. 加载内置默认配置
|
||
↓
|
||
2. 尝试加载 XResources
|
||
├─ 成功 → 覆盖默认配置中的外观项
|
||
└─ 失败 → 跳过,保持默认值
|
||
↓
|
||
3. 尝试加载动态库
|
||
├─ 存在 → 调用 zdwm_config_init(),增量修改配置
|
||
└─ 不存在 → 跳过
|
||
↓
|
||
4. 应用最终配置
|
||
```
|
||
|
||
---
|
||
|
||
## 数据结构
|
||
|
||
### 配置优先级标记
|
||
|
||
```c
|
||
typedef struct config_source_t {
|
||
bool has_xres; // 是否加载了 XResources
|
||
bool has_user_lib; // 是否加载了用户动态库
|
||
} config_source_t;
|
||
```
|
||
|
||
### 完整配置结构
|
||
|
||
```c
|
||
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
|
||
|
||
```c
|
||
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;
|
||
```
|
||
|
||
### 用户配置初始化函数
|
||
|
||
```c
|
||
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. 配置加载函数
|
||
|
||
```c
|
||
// src/config.h
|
||
config_t *config_load_full(void);
|
||
void config_free(config_t *config);
|
||
config_t *config_reload(void);
|
||
```
|
||
|
||
### 2. 加载顺序
|
||
|
||
```c
|
||
// 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 解析
|
||
|
||
```c
|
||
// 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. 动态库加载
|
||
|
||
```c
|
||
// 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 后的操作流程:
|
||
|
||
```bash
|
||
# 1. 编辑配置文件
|
||
vim ~/.Xresources
|
||
|
||
# 2. 加载到 X Server
|
||
xrdb -merge ~/.Xresources
|
||
|
||
# 3. 重载 zdwm 配置
|
||
killall -HUP zdwm
|
||
```
|
||
|
||
### 实现要点
|
||
|
||
```c
|
||
// 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 模块需要添加
|
||
|
||
```c
|
||
// 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**: 增强功能,可后续添加
|