Files
zdwm/docs/config_system.md

8.7 KiB
Raw Blame History

Zdwm 配置系统设计文档

概述

三层配置系统,按优先级从低到高加载:

内置默认配置 → XResources → 动态库配置
(后者覆盖前者)

配置层次

第一层:内置默认配置

  • 位置: 编译到二进制中
  • 作用: 提供完整的默认配置,确保无外部配置时也能正常运行
  • 范围: 所有配置项

第二层XResources 配置

  • 位置: ~/.Xresources~/.config/zdwm/Xresources
  • 作用: 覆盖外观配置(颜色、字体、边框等)
  • 特点: 无需重新编译,xrdb 后重启生效
  • 范围: 仅外观配置

第三层:动态库配置

  • 位置: ~/.config/zdwm/config.cconfig.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: 增强功能,可后续添加