Files
zdwm/docs/ARCHITECTURE_REFACTORING_PLAN.org

37 KiB
Raw Permalink Blame History

ZDWM 窗口管理器完整抽象层设计方案

设计目标

创建一个清晰、实用、可落地的抽象层体系,解决当前项目的架构问题,提升可维护性和可扩展性,同时保持项目的简洁性和高性能。

当前架构优势保留

ZDWM 现有的优秀设计基础:

  • 清晰的四层架构UI/业务/数据/基础设施)
  • 优秀的观察者模式(状态栏更新)
  • 灵活的策略模式(布局系统)
  • 高效的事件驱动模型
  • 良好的资源管理

核心抽象层设计

第一层:基础设施抽象层 (Infrastructure Layer)

1.1 上下文管理器

问题: 当前全局 wm 对象导致所有模块紧密耦合

解决方案: 引入上下文对象,实现依赖注入

// src/core/context.h
// 前向声明
typedef struct display_backend_t display_backend_t;

typedef struct wm_context_t {
    // 显示后端X11 或 Wayland
    display_backend_t *display_backend;

    // 核心状态
    monitor_t *monitor_list;
    client_t *client_list;
    tag_t *tag_list;

    // 配置和状态
    config_t *config;
    status_t *status;

    // 事件循环
    GMainContext *main_context;

    // 引用计数
    atomic_int ref_count;
} wm_context_t;

// 上下文生命周期管理
wm_context_t *wm_context_create(display_backend_type_t backend_type);
wm_context_t *wm_context_ref(wm_context_t *ctx);
void wm_context_unref(wm_context_t *ctx);

// 获取全局上下文(向后兼容)
wm_context_t *wm_context_get_default(void);

// 显示后端访问(向后兼容)
static inline xcb_connection_t* context_get_xcb_conn(wm_context_t *ctx) {
    return ctx->display_backend ?
           (xcb_connection_t*)ctx->display_backend->get_platform_handle() : NULL;
}

优势:

  • 支持多实例(测试环境)
  • 清晰的生命周期管理
  • 便于依赖注入
  • 保持向后兼容
1.2 日志系统

问题: 当前 logger() 输出简单,=fatal()= 直接退出

解决方案: 分级日志系统

// src/core/log.h
typedef enum log_level_t {
    LOG_LEVEL_DEBUG = 0,
    LOG_LEVEL_INFO,
    LOG_LEVEL_WARN,
    LOG_LEVEL_ERROR,
    LOG_LEVEL_FATAL
} log_level_t;

typedef struct log_handler_t {
    void (*write)(log_level_t level, const char *file, int line,
                  const char *fmt, va_list args);
    log_level_t min_level;
    log_handler_t *next;
} log_handler_t;

// 日志API
void log_init(log_level_t default_level);
void log_cleanup(void);
void log_add_handler(log_handler_t *handler);
void log_remove_handler(log_handler_t *handler);

// 便捷宏
#define LOG_DEBUG(fmt, ...) log_write(LOG_LEVEL_DEBUG, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define LOG_INFO(fmt, ...)  log_write(LOG_LEVEL_INFO, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define LOG_WARN(fmt, ...)  log_write(LOG_LEVEL_WARN, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define LOG_ERROR(fmt, ...) log_write(LOG_LEVEL_ERROR, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define LOG_FATAL(fmt, ...) log_write(LOG_LEVEL_FATAL, __FILE__, __LINE__, fmt, ##__VA_ARGS__)

// 替代现有的 logger/fatal/warn
#define logger LOG_INFO
#define warn LOG_WARN
#define fatal LOG_FATAL
1.3 错误处理机制

问题: GError 使用不当,错误信息丢失

解决方案: 统一错误处理接口

// src/core/error.h
typedef enum error_code_t {
    ERROR_NONE = 0,
    ERROR_NOMEM,
    ERROR_INVALID_ARG,
    ERROR_XCB_FAILED,
    ERROR_FILE_NOT_FOUND,
    ERROR_PARSE_FAILED,
    // ... 更多错误码
} error_code_t;

typedef struct error_t {
    error_code_t code;
    char message[256];
    const char *file;
    int line;
} error_t;

// 错误处理API
void error_set(error_t **err, error_code_t code, const char *fmt, ...);
void error_clear(error_t **err);
const char *error_get_message(const error_t *err);

// 错误传播宏
#define CHECK_ERROR(cond, err, code, fmt, ...) \
    if (!(cond)) { \
        error_set(err, code, fmt, ##__VA_ARGS__); \
        return false; \
    }

第二层:数据抽象层 (Data Layer)

2.1 状态管理器

问题: 状态散落在多个模块,难以同步

解决方案: 统一状态管理接口

// src/core/state.h
typedef enum state_type_t {
    STATE_MONITOR,
    STATE_CLIENT,
    STATE_TAG,
    STATUS_LAYOUT,
    STATE_CONFIG
} state_type_t;

typedef struct state_change_t {
    state_type_t type;
    void *old_state;
    void *new_state;
} state_change_t;

typedef void (*state_change_callback)(const state_change_t *change, void *user_data);

typedef struct state_manager_t {
    // 状态变更监听器
    state_change_callback *listeners;
    void **listener_data;
    size_t listener_count;

    // 状态存储
    hash_table_t *states;
} state_manager_t;

// 状态管理API
state_manager_t *state_manager_create(void);
void state_manager_destroy(state_manager_t *mgr);

void state_manager_notify(state_manager_t *mgr, const state_change_t *change);
void state_manager_subscribe(state_manager_t *mgr,
                            state_change_callback callback,
                            void *user_data);

// 状态访问
void *state_get(state_manager_t *mgr, state_type_t type);
void state_set(state_manager_t *mgr, state_type_t type, void *data);
2.2 配置抽象层

问题: 配置系统不统一,缺少热重载

解决方案: 分层配置系统

// src/config/config_layer.h
typedef enum config_source_t {
    CONFIG_SOURCE_DEFAULT,    // 编译时默认值
    CONFIG_SOURCE_FILE,       // 配置文件
    CONFIG_SOURCE_XRESOURCE,  // X资源数据库
    CONFIG_SOURCE_RUNTIME,    // 运行时API最高优先级
} config_source_t;

typedef struct config_value_t {
    config_source_t source;
    union {
        bool boolean;
        int integer;
        char *string;
        void *pointer;
    } value;
} config_value_t;

typedef struct config_layer_t {
    hash_table_t *values;  // key -> config_value_t
    config_source_t source;
    bool readonly;
} config_layer_t;

typedef struct config_stack_t {
    config_layer_t **layers;
    size_t layer_count;
} config_stack_t;

// 配置API
config_stack_t *config_stack_create(void);
void config_stack_destroy(config_stack_t *stack);

void config_stack_push_layer(config_stack_t *stack, config_source_t source);
void config_stack_pop_layer(config_stack_t *stack);

// 配置访问(自动从最高优先级层查找)
bool config_get_bool(config_stack_t *stack, const char *key, bool *value);
bool config_get_int(config_stack_t *stack, const char *key, int *value);
bool config_get_string(config_stack_t *stack, const char *key, char **value);

// 配置设置(总是设置到运行时层)
bool config_set_bool(config_stack_t *stack, const char *key, bool value);
bool config_set_int(config_stack_t *stack, const char *key, int value);
bool config_set_string(config_stack_t *stack, const char *key, const char *value);

// 配置热重载
bool config_reload_from_file(config_stack_t *stack, const char *filepath);

第三层:服务抽象层 (Service Layer)

3.1 显示后端抽象

问题: XCB调用散落各处难以测试且无法支持 Wayland

解决方案: 显示服务器无关的统一接口,支持 X11 和 Wayland

// src/services/display_backend.h

// 显示后端类型
typedef enum display_backend_type_t {
    DISPLAY_BACKEND_AUTO,      // 自动检测
    DISPLAY_BACKEND_X11,
    DISPLAY_BACKEND_WAYLAND
} display_backend_type_t;

// 统一的窗口表示(跨平台)
typedef struct window_t {
    uint64_t id;              // 平台无关的窗口ID
    void *platform_handle;    // XCB window or wl_surface
} window_t;

// 几何信息
typedef struct rect_t {
    int32_t x, y;
    uint32_t width, height;
} rect_t;

// 输入事件
typedef struct input_event_t {
    enum { INPUT_KEY, INPUT_BUTTON, INPUT_MOTION, INPUT_AXIS } type;
    uint32_t time;
    uint32_t detail;          // keycode or button number
    uint32_t state;           // modifier state
    int32_t x, y;             // cursor position
    int32_t axis;             // scroll axis delta
} input_event_t;

// 渲染表面
typedef struct render_surface_t {
    void *handle;             // cairo_surface_t* for X11, EGLSurface for Wayland
    uint32_t width, height;
} render_surface_t;

// 显示后端接口
typedef struct display_backend_t {
    const char *name;
    const char *version;

    // 生命周期
    bool (*init)(wm_context_t *ctx);
    void (*cleanup)(void);

    // 事件处理
    int (*get_fd)(void);                    // 获取事件文件描述符
    bool (*dispatch_event)(void);           // 分发单个事件
    void (*flush)(void);                    // 刷新请求

    // 屏幕信息
    bool (*get_screen_geometry)(size_t screen_index, rect_t *geometry);
    size_t (*get_screen_count)(void);

    // 窗口操作
    window_t (*create_window)(const rect_t *geometry);
    void (*destroy_window)(window_t window);
    void (*map_window)(window_t window);
    void (*unmap_window)(window_t window);

    // 窗口属性
    typedef enum {
        WINDOW_PROPERTY_TITLE,
        WINDOW_PROPERTY_CLASS,
        WINDOW_PROPERTY_ROLE,
        WINDOW_PROPERTY_PID,
        WINDOW_PROPERTY_TYPE,
        WINDOW_PROPERTY_TRANSIENT_FOR,
        WINDOW_PROPERTY_SIZE_HINTS,
        WINDOW_PROPERTY_MOTIF_HINTS,
        WINDOW_PROPERTY_FULLSCREEN,
        WINDOW_PROPERTY_OPACITY,
    } window_property_t;

    bool (*get_window_property)(window_t window, window_property_t prop,
                               void *data, size_t *size);
    bool (*set_window_property)(window_t window, window_property_t prop,
                               const void *data, size_t size);

    // 窗口几何
    bool (*configure_window)(window_t window, const rect_t *geometry);
    bool (*get_window_geometry)(window_t window, rect_t *geometry);
    void (*raise_window)(window_t window);
    void (*focus_window)(window_t window);

    // 输入处理
    bool (*grab_keyboard)(window_t window);
    bool (*grab_pointer)(window_t window);
    void (*ungrab_keyboard)(void);
    void (*ungrab_pointer)(void);

    // 渲染集成
    render_surface_t (*create_render_surface)(window_t window,
                                             uint32_t width, uint32_t height);
    void (*destroy_render_surface)(render_surface_t surface);
    cairo_t* (*create_cairo_context)(render_surface_t surface);

    // Wayland 特定:窗口状态(用于 xdg-shell
    typedef enum {
        STATE_FLAG_FULLSCREEN = (1 << 0),
        STATE_FLAG_MAXIMIZED   = (1 << 1),
        STATE_FLAG_ RESIZING    = (1 << 2),
        STATE_FLAG_ACTIVATING  = (1 << 3),
    } state_flag_t;

    bool (*set_window_state)(window_t window, uint32_t state_flags);
    bool (*set_window_bounds)(window_t window, const rect_t *bounds);

    // 平台特定扩展
    void* (*get_platform_handle)(void);  // xcb_connection_t* or wl_display*
} display_backend_t;

// 显示后端管理
display_backend_t *display_backend_create(display_backend_type_t type);
bool display_backend_init(wm_context_t *ctx, display_backend_type_t type);
void display_backend_cleanup(display_backend_t *backend);

// X11 后端声明
extern display_backend_t x11_backend;

// Wayland 后端声明(未来实现)
extern display_backend_t wayland_backend;

优势:

  • 为 Wayland 移植奠定基础
  • 显示逻辑与核心逻辑分离
  • 便于使用 mock 后端进行测试
  • 运行时可切换显示后端

X11 后端实现:

// src/services/x11_backend.c
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
#include <cairo-xcb.h>

typedef struct x11_backend_data_t {
    xcb_connection_t *conn;
    xcb_screen_t *screen;
    xcb_window_t root_window;
    xcb_atom_t wm_protocols;
    xcb_atom_t wm_delete_window;
    GHashTable *window_map;  // uint64_t -> xcb_window_t
} x11_backend_data_t;

static bool x11_init(wm_context_t *ctx) {
    x11_backend_data_t *data = calloc(1, sizeof(x11_backend_data_t));

    data->conn = xcb_connect(NULL, NULL);
    if (xcb_connection_has_error(data->conn)) {
        free(data);
        return false;
    }

    data->screen = xcb_setup_roots_iterator(xcb_get_setup(data->conn)).data;
    data->root_window = data->screen->root;

    // 初始化 atoms 和其他资源
    // ...

    return true;
}

static window_t x11_create_window(const rect_t *geometry) {
    x11_backend_data_t *data = display_backend_get_data(&x11_backend);

    xcb_window_t xcb_win = xcb_generate_id(data->conn);
    // 创建窗口...

    return (window_t){
        .id = (uint64_t)xcb_win,
        .platform_handle = (void *)(uintptr_t)xcb_win
    };
}

// ... 其他 X11 实现

display_backend_t x11_backend = {
    .name = "x11",
    .version = "1.0",
    .init = x11_init,
    .cleanup = x11_cleanup,
    .create_window = x11_create_window,
    // ... 其他函数指针
};

Wayland 后端框架:

// src/services/wayland_backend.c
#include <wayland-client.h>

typedef struct wayland_backend_data_t {
    struct wl_display *display;
    struct wl_compositor *compositor;
    struct wl_seat *seat;
    struct xdg_wm_base *xdg_wm_base;
    GHashTable *window_map;
} wayland_backend_data_t;

static bool wayland_init(wm_context_t *ctx) {
    wayland_backend_data_t *data = calloc(1, sizeof(wayland_backend_data_t));

    data->display = wl_display_connect(NULL);
    if (!data->display) {
        free(data);
        return false;
    }

    // 注册全局对象监听器
    wl_display_roundtrip(data->display);

    return true;
}

// ... 其他 Wayland 实现(未来工作)

display_backend_t wayland_backend = {
    .name = "wayland",
    .version = "1.0",
    .init = wayland_init,
    // ... 其他函数指针
};
3.2 事件总线

问题: 事件处理直接耦合业务逻辑

解决方案: 发布-订阅事件系统

// src/services/event_bus.h
typedef enum event_type_t {
    // 窗口事件
    EVENT_WINDOW_CREATE,
    EVENT_WINDOW_DESTROY,
    EVENT_WINDOW_CONFIGURE,
    EVENT_WINDOW_FOCUS,

    // 监视器事件
    EVENT_MONITOR_ADD,
    EVENT_MONITOR_REMOVE,
    EVENT_MONITOR_CHANGE,

    // 标签事件
    EVENT_TAG_ADD,
    EVENT_TAG_REMOVE,
    EVENT_TAG_CHANGE,

    // 用户事件
    EVENT_KEY_PRESS,
    EVENT_MOUSE_PRESS,
    EVENT_COMMAND,

    // 系统事件
    EVENT_CONFIG_RELOAD,
    EVENT_RESTART,
    EVENT_EXIT
} event_type_t;

typedef struct event_t {
    event_type_t type;
    void *data;           // 事件特定数据
    void *source;         // 事件源对象
} event_t;

typedef void (*event_callback)(const event_t *event, void *user_data);

typedef struct event_subscription_t {
    event_type_t type;
    event_callback callback;
    void *user_data;
    bool once;            // 是否只触发一次
} event_subscription_t;

typedef struct event_bus_t {
    event_subscription_t **subscriptions;
    size_t subscription_count;
    size_t capacity;
} event_bus_t;

// 事件总线API
event_bus_t *event_bus_create(void);
void event_bus_destroy(event_bus_t *bus);

// 订阅事件
event_subscription_t *event_bus_subscribe(event_bus_t *bus,
                                         event_type_t type,
                                         event_callback callback,
                                         void *user_data);
void event_bus_unsubscribe(event_bus_t *bus, event_subscription_t *sub);

// 发布事件
void event_bus_publish(event_bus_t *bus, const event_t *event);

// 便捷宏
#define EVENT_SUBSCRIBE(bus, type, callback, data) \
    event_bus_subscribe(bus, type, callback, data)

#define EVENT_PUBLISH(bus, type, data) \
    event_bus_publish(bus, &(event_t){ .type = type, .data = data })
3.3 插件系统

问题: 扩展功能需要修改核心代码

解决方案: 轻量级插件接口

// src/services/plugin.h
typedef struct plugin_t {
    char *name;
    char *version;
    void *handle;         // dlopen句柄

    // 生命周期
    bool (*init)(wm_context_t *ctx);
    void (*cleanup)(void);

    // 事件处理
    void (*on_event)(const event_t *event);

    // 配置
    bool (*set_config)(const char *key, const char *value);
} plugin_t;

typedef struct plugin_manager_t {
    plugin_t **plugins;
    size_t plugin_count;
    event_bus_t *event_bus;
} plugin_manager_t;

// 插件管理API
plugin_manager_t *plugin_manager_create(event_bus_t *bus);
void plugin_manager_destroy(plugin_manager_t *mgr);

// 插件加载
bool plugin_manager_load(plugin_manager_t *mgr, const char *path);
bool plugin_manager_unload(plugin_manager_t *mgr, const char *name);

// 插件API供插件实现者使用
void plugin_register(plugin_t *plugin);
void plugin_unregister(const char *name);

// 插件宏(简化插件开发)
#define PLUGIN_EXPORT(name, version, init_fn, cleanup_fn) \
    __attribute__((used)) plugin_t *_plugin_get_info(void) { \
        static plugin_t plugin = { \
            .name = name, \
            .version = version, \
            .init = init_fn, \
            .cleanup = cleanup_fn \
        }; \
        return &plugin; \
    }

第四层:业务抽象层 (Business Layer)

4.1 客户端抽象

问题: client.c 职责过多,难以维护

解决方案: 客户端接口抽象

// src/business/client_interface.h
// 客户端状态机
typedef enum client_state_t {
    CLIENT_STATE_NEW,
    CLIENT_STATE_NORMAL,
    CLIENT_STATE_FLOATING,
    CLIENT_STATE_FULLSCREEN,
    CLIENT_STATE_MAXIMIZED,
    CLIENT_STATE_MINIMIZED,
    CLIENT_STATE_DOCK,
    CLIENT_STATE_DYING
} client_state_t;

// 客户端接口
typedef struct client_interface_t {
    // 生命周期
    client_t* (*create)(xcb_window_t window);
    void (*destroy)(client_t *client);

    // 状态管理
    client_state_t (*get_state)(const client_t *client);
    bool (*set_state)(client_t *client, client_state_t new_state);

    // 几何管理
    bool (*set_geometry)(client_t *client, const rect_t *geometry);
    rect_t (*get_geometry)(const client_t *client);

    // 焦点管理
    bool (*focus)(client_t *client);
    bool (*is_focused)(const client_t *client);

    // 属性管理
    bool (*set_property)(client_t *client, const char *key, void *value);
    void* (*get_property)(const client_t *client, const char *key);

    // 渲染
    bool (*needs_redraw)(const client_t *client);
    void (*draw)(client_t *client, cairo_t *cr);
} client_interface_t;

// 客户端管理器
typedef struct client_manager_t {
    client_interface_t *iface;
    list_t *clients;          // 所有客户端
    hash_table_t *window_map; // window -> client
} client_manager_t;

// 客户端管理API
client_manager_t *client_manager_create(client_interface_t *iface);
void client_manager_destroy(client_manager_t *mgr);

client_t *client_manager_add(client_manager_t *mgr, xcb_window_t window);
bool client_manager_remove(client_manager_t *mgr, client_t *client);
client_t *client_manager_find(client_manager_t *mgr, xcb_window_t window);
4.2 布局引擎抽象

问题: 布局系统已经设计良好,但缺少插件化

解决方案: 布局插件接口

// src/business/layout_engine.h
typedef struct layout_context_t {
    tag_t *tag;
    rect_t workarea;
    client_t **clients;
    size_t client_count;
} layout_context_t;

typedef struct layout_algorithm_t {
    const char *name;
    const char *symbol;

    // 布局计算
    void (*arrange)(const layout_context_t *ctx, rect_t *geometries);

    // 可选:预览布局(不实际应用)
    void (*preview)(const layout_context_t *ctx, rect_t *geometries);

    // 可选:布局参数
    bool (*set_param)(const char *key, void *value);
} layout_algorithm_t;

typedef struct layout_engine_t {
    layout_algorithm_t **algorithms;
    size_t algorithm_count;
    layout_algorithm_t *default_algorithm;
} layout_engine_t;

// 布局引擎API
layout_engine_t *layout_engine_create(void);
void layout_engine_destroy(layout_engine_t *engine);

bool layout_engine_register(layout_engine_t *engine, layout_algorithm_t *algo);
bool layout_engine_unregister(layout_engine_t *engine, const char *name);

layout_algorithm_t *layout_engine_find(layout_engine_t *engine, const char *name);
void layout_engine_arrange(layout_engine_t *engine, const layout_context_t *ctx);

// 便捷宏:定义布局算法
#define LAYOUT_ALGORITHM(name, symbol, arrange_fn) \
    static layout_algorithm_t _layout_##name = { \
        .name = #name, \
        .symbol = symbol, \
        .arrange = arrange_fn \
    }; \
    __attribute__((constructor)) \
    static void _layout_register_##name(void) { \
        layout_engine_register(layout_engine_get_default(), &_layout_##name); \
    }
4.3 操作抽象

问题: 操作系统已经设计良好,可以增强

解决方案: 命令模式增强

// src/business/command.h
typedef enum command_arg_type_t {
    COMMAND_ARG_NONE,
    COMMAND_ARG_INT,
    COMMAND_ARG_STRING,
    COMMAND_ARG_BOOLEAN
} command_arg_type_t;

typedef struct command_arg_t {
    command_arg_type_t type;
    union {
        int integer;
        char *string;
        bool boolean;
    } value;
} command_arg_t;

typedef struct command_result_t {
    bool success;
    char *message;
    void *data;          // 可选的返回数据
    void (*data_cleanup)(void *data);
} command_result_t;

typedef struct command_t {
    const char *name;
    const char *description;

    // 参数定义
    command_arg_type_t *arg_types;
    size_t arg_count;

    // 执行函数
    command_result_t (*execute)(wm_context_t *ctx,
                               const command_arg_t *args,
                               size_t arg_count);

    // 可选:自动完成
    char* (*complete)(const char *prefix, size_t arg_index);
} command_t;

typedef struct command_registry_t {
    hash_table_t *commands;  // name -> command_t
} command_registry_t;

// 命令注册API
command_registry_t *command_registry_create(void);
void command_registry_destroy(command_registry_t *registry);

bool command_registry_register(command_registry_t *registry, command_t *cmd);
bool command_registry_unregister(command_registry_t *registry, const char *name);

command_result_t command_execute(command_registry_t *registry,
                                wm_context_t *ctx,
                                const char *name,
                                const command_arg_t *args,
                                size_t arg_count);

// 便捷宏
#define COMMAND_REGISTER(registry, name, fn) \
    command_registry_register(registry, &(command_t){ \
        .name = name, \
        .execute = fn \
    })

第五层UI抽象层 (Presentation Layer)

5.1 渲染器抽象

问题: 渲染逻辑散落各处,难以扩展

解决方案: 统一渲染接口

// src/ui/renderer.h
typedef struct render_context_t {
    cairo_t *cr;
    rect_t viewport;
    color_scheme_t *colors;
} render_context_t;

typedef struct renderer_t {
    const char *name;

    // 初始化
    bool (*init)(wm_context_t *ctx);

    // 清理
    void (*cleanup)(void);

    // 渲染
    void (*render)(const render_context_t *ctx, void *data);

    // 尺寸计算
    void (*measure)(const render_context_t *ctx, void *data, size_t *width, size_t *height);
} renderer_t;

typedef struct renderer_manager_t {
    renderer_t **renderers;
    size_t renderer_count;
} renderer_manager_t;

// 渲染器管理API
renderer_manager_t *renderer_manager_create(void);
void renderer_manager_destroy(renderer_manager_t *mgr);

bool renderer_manager_register(renderer_manager_t *mgr, renderer_t *r);
bool renderer_manager_unregister(renderer_manager_t *mgr, const char *name);

renderer_t *renderer_manager_find(renderer_manager_t *mgr, const char *name);
void renderer_manager_render(renderer_manager_t *mgr, const char *name,
                            const render_context_t *ctx, void *data);
5.2 状态栏组件系统

问题: 状态栏已经设计良好,可以组件化

解决方案: 组件化状态栏

// src/ui/statusbar_component.h
typedef struct statusbar_component_t {
    const char *name;
    size_t preferred_width;
    size_t preferred_height;

    // 渲染
    void (*render)(const render_context_t *ctx, void *data);

    // 尺寸计算
    void (*measure)(const render_context_t *ctx, void *data,
                   size_t *width, size_t *height);

    // 事件处理
    void (*on_click)(void *data, int x, int y);
    void (*on_scroll)(void *data, int delta);

    // 生命周期
    void (*init)(wm_context_t *ctx, void **data);
    void (*cleanup)(void *data);
} statusbar_component_t;

typedef struct statusbar_t {
    statusbar_component_t **components;
    void **component_data;
    size_t component_count;

    // 布局管理
    enum {
        STATUSBAR_LAYOUT_LEFT_TO_RIGHT,
        STATUSBAR_LAYOUT_RIGHT_TO_LEFT
    } layout_direction;
} statusbar_t;

// 状态栏组件API
statusbar_t *statusbar_create(void);
void statusbar_destroy(statusbar_t *bar);

bool statusbar_add_component(statusbar_t *bar, statusbar_component_t *comp);
bool statusbar_remove_component(statusbar_t *bar, const char *name);

void statusbar_render(statusbar_t *bar, const render_context_t *ctx);
void statusbar_handle_event(statusbar_t *bar, const event_t *event);

// 预定义组件
extern statusbar_component_t statusbar_clock_component;
extern statusbar_component_t statusbar_cpu_component;
extern statusbar_component_t statusbar_memory_component;
extern statusbar_component_t statusbar_network_component;

架构分层图

┌─────────────────────────────────────────────────────────────┐
│                    UI 抽象层                                │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐       │
│  │ 渲染器管理   │  │ 状态栏组件   │  │ 通知系统     │       │
│  └──────────────┘  └──────────────┘  └──────────────┘       │
└─────────────────────────────────────────────────────────────┘
                            ▲
                            │
┌─────────────────────────────────────────────────────────────┐
│                   业务抽象层                                │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐       │
│  │ 客户端接口   │  │ 布局引擎     │  │ 命令系统     │       │
│  └──────────────┘  └──────────────┘  └──────────────┘       │
└─────────────────────────────────────────────────────────────┘
                            ▲
                            │
┌─────────────────────────────────────────────────────────────┐
│                   服务抽象层                                │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐       │
│  │ 显示后端     │  │ 事件总线     │  │ 插件系统     │       │
│  │ (X11/Wayland)│  │              │  │              │       │
│  └──────────────┘  └──────────────┘  └──────────────┘       │
└─────────────────────────────────────────────────────────────┘
                            ▲
                            │
┌─────────────────────────────────────────────────────────────┐
│                   数据抽象层                                │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐       │
│  │ 状态管理器   │  │ 配置系统     │  │ 资源缓存     │       │
│  └──────────────┘  └──────────────┘  └──────────────┘       │
└─────────────────────────────────────────────────────────────┘
                            ▲
                            │
┌─────────────────────────────────────────────────────────────┐
│                  基础设施抽象层                             │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐       │
│  │ 上下文管理   │  │ 日志系统     │  │ 错误处理     │       │
│  └──────────────┘  └──────────────┘  └──────────────┘       │
└─────────────────────────────────────────────────────────────┘

实施路径

阶段1基础设施层 (2-3周)

  1. 上下文管理器

    • 创建 wm_context_t
    • 修改现有代码使用上下文
    • 保持向后兼容宏
  2. 日志系统

    • 实现 log.h/c
    • 替换所有 logger/fatal/warn
    • 添加文件输出 handler
  3. 错误处理

    • 实现 error.h/c
    • 修复 GError 使用
    • 添加错误恢复机制

阶段2数据抽象层 (3-4周)

  1. 状态管理器

    • 实现 state_manager_t
    • 迁移关键状态到统一管理
    • 添加状态变更监听
  2. 配置系统

    • 实现配置栈
    • 支持配置文件热重载
    • 添加配置验证

阶段3服务抽象层 (4-6周)

  1. 显示后端抽象

    • 定义显示后端统一接口
    • 实现 X11 后端(迁移现有 XCB 调用)
    • 创建 Wayland 后端框架(仅接口定义)
    • 实现 Mock 后端用于单元测试
    • 修改核心逻辑使用显示后端接口
    • 添加后端自动检测和运行时切换
  2. 事件总线

    • 实现发布-订阅系统
    • 迁移现有事件处理
    • 添加事件日志
  3. 插件系统

    • 实现插件加载器
    • 定义插件接口
    • 创建示例插件

阶段4业务抽象层 (6-8周)

  1. 客户端重构

    • 定义客户端接口
    • 实现状态机
    • 拆分 client.c
  2. 布局引擎

    • 提取布局算法
    • 支持动态注册
    • 添加布局预览
  3. 命令系统

    • 统一命令接口
    • 支持参数验证
    • 添加自动完成

阶段5UI抽象层 (4-6周)

  1. 渲染器管理

    • 统一渲染接口
    • 支持多种渲染器
    • 添加渲染缓存
  2. 状态栏组件化

    • 提取组件接口
    • 实现预定义组件
    • 支持自定义组件

向后兼容策略

  1. 渐进式迁移

    • 新旧API并存
    • 使用宏提供兼容层
    • 标记旧API为deprecated
  2. 编译时选项

    #ifdef USE_NEW_ARCH
        // 使用新API
    #else
        // 使用旧API
    #endif
  3. 运行时切换

    • 支持命令行参数选择架构
    • 便于性能对比和问题定位

测试策略

  1. 单元测试

    • 每个抽象层独立测试
    • 使用mock对象隔离依赖
  2. 集成测试

    • 测试层间交互
    • 端到端场景测试
  3. 性能测试

    • 对比新旧架构性能
    • 内存使用分析
    • 响应时间测试

预期收益

可维护性提升

  • 清晰的职责划分
  • 松耦合的模块设计
  • 易于定位和修复问题

可扩展性提升

  • 插件化架构
  • 组件化UI
  • 动态配置系统

可测试性提升

  • 依赖注入支持
  • Mock对象友好
  • 隔离测试环境

用户体验提升

  • 配置热重载
  • 插件生态
  • 更好的错误提示

这个抽象层设计既保持了ZDWM的简洁高效又大幅提升了可维护性和可扩展性为项目的长期发展奠定坚实基础。

显示后端抽象与 Wayland 支持

设计目标

通过引入显示后端抽象层,实现以下目标:

  • 为 Wayland 移植奠定基础,适应显示服务器技术演进
  • 显示逻辑与核心业务逻辑完全分离
  • 支持运行时后端切换,用户可选择 X11 或 Wayland
  • 便于使用 Mock 后端进行单元测试

架构优势

  1. 显示服务器无关性: 核心窗口管理逻辑不依赖特定显示服务器
  2. 渐进式迁移: 先完善 X11 后端,再逐步实现 Wayland 后端
  3. 性能无损: 通过编译时优化和内联函数保持高性能
  4. 测试友好: Mock 后端使单元测试更简单

X11 后端实现重点

// X11 后端的核心职责
- 管理 xcb_connection_t  xcb_screen_t
- 窗口生命周期管理(创建、销毁、映射、取消映射)
- ICCCM/EWMH 协议实现
- 事件转换(XCB 事件  通用 display_event_t
- Cairo 集成(cairo_xcb_surface_t
- 输入设备抓取(键盘、鼠标)

Wayland 后端实现路线图

阶段1基础框架未来 3-6 个月)

  • 实现 Wayland 客户端协议绑定
  • 支持 wl_display, wl_compositor, wl_shm
  • 实现 xdg-shell 基础功能
  • 窗口创建和基本管理

阶段2核心功能未来 6-12 个月)

  • 完整的 xdg-shell 支持
  • 输入事件处理wl_seat, wl_pointer, wl_keyboard
  • 表面和帧回调wl_surface, wl_callback
  • EGL/渲染集成

阶段3高级特性未来 12-18 个月)

  • xdg-activation 协议(焦点管理)
  • xdg-decoration 协议(服务器端装饰)
  • wl_output 多显示器支持
  • Layer-shell 支持(面板、覆盖层)

后端切换策略

  1. *编译时选择*(零成本抽象)

    #if defined(DISPLAY_BACKEND_X11)
        #define DISPLAY_CALL(func, ...) x11_##func(__VA_ARGS__)
    #elif defined(DISPLAY_BACKEND_WAYLAND)
        #define DISPLAY_CALL(func, ...) wayland_##func(__VA_ARGS__)
    #endif
  2. *运行时切换*(灵活性)

    // 通过环境变量选择
    export ZDWM_BACKEND=x11  // 或 wayland
    
    // 通过命令行参数选择
    zdwm --backend=x11
    zdwm --backend=wayland
    
    // 自动检测
    if (getenv("WAYLAND_DISPLAY")) {
        backend = &wayland_backend;
    } else if (getenv("DISPLAY")) {
        backend = &x11_backend;
    }

配置示例

// 配置文件支持
typedef struct display_config_t {
    display_backend_type_t backend;
    struct {
        bool enable_ssd;        // 服务器端装饰X11
        bool enable_csd;        // 客户端装饰Wayland
    } decoration;
    struct {
        bool enable_vsync;
        bool use_egl;           // EGL vs SHMWayland
    } rendering;
} display_config_t;

兼容性考虑

  1. 向后兼容: 保持现有 XCB 调用接口,通过宏迁移到新接口
  2. 功能对等: 确保 X11 和 Wayland 后端功能一致性
  3. 性能保持: Wayland 后端性能应不低于 X11 后端

测试策略

  1. Mock 后端测试

    // 用于单元测试的模拟后端
    static display_backend_t mock_backend = {
        .name = "mock",
        .init = mock_init,
        .create_window = mock_create_window,
        // ... 其他实现
    };
    
    // 测试核心逻辑
    void test_client_management_with_mock_backend() {
        wm_context_t *ctx = wm_context_create(DISPLAY_BACKEND_MOCK);
        // 测试逻辑...
    }
  2. 双后端集成测试

    • 使用相同测试用例验证 X11 和 Wayland 后端
    • 确保行为一致性

预期收益

  1. 未来兼容性: 为 Wayland 移植奠定基础
  2. 架构清晰: 显示逻辑与核心逻辑分离
  3. 测试友好: Mock 后端简化单元测试
  4. 性能无损: 通过编译时优化保持高性能
  5. 用户选择: 用户可根据需求选择 X11 或 Wayland

这个显示后端抽象设计确保了 ZDWM 能够适应显示服务器技术的演进,同时保持当前的优秀性能和稳定性。