#pragma once #include #include #include "core/layer.h" #include "core/types.h" #include "core/window.h" #include "core/wm_desc.h" /* 核心实体定义 */ typedef struct window_t { window_id_t id; window_id_t transient_for; workspace_id_t workspace_id; layer_type_t layer; window_geometry_mode_t geometry_mode; bool floating; bool sticky; bool urgent; bool fixed_size; /* 几何信息(均为包含边框后的外框矩形) */ rect_t float_rect; /* floating 模式下记忆的外框矩形 */ rect_t frame_rect; /* 当前外框矩形(由 layout 或 float_rect 解析) */ /* 元数据(核心算法不依赖,仅用于规则匹配和信息展示) */ char *title; char *app_id; char *role; char *class_name; char *instance_name; bool skip_taskbar; } window_t; typedef struct workspace_t { workspace_id_t id; output_id_t output_id; /* 固定归属某个输出 */ layout_id_t layout_id; /* 当前活动布局(可用布局列表中的一个) */ window_id_t focused_window_id; /* 当前 workspace 的可用布局列表 */ const layout_id_t *available_layouts; size_t layout_count; /* 名称(核心算法不依赖) */ const char *name; } workspace_t; typedef struct output_t { output_id_t id; workspace_id_t current_workspace_id; const char *name; rect_t geometry; /* 输出完整几何 */ rect_t workarea; /* 可用区域(排除面板等) */ } output_t; /* 全局状态容器 */ typedef struct state_t { /* 按 id 稳定引用的 workspace / output 集合 */ workspace_t *workspaces; size_t workspace_count; output_t *outputs; size_t output_count; size_t current_output_index; window_t *windows; size_t window_count; size_t window_capacity; /* 分层堆叠顺序:每层内部从低到高排列 */ layer_stack_t stacks[ZDWM_WINDOW_LAYER_COUNT]; } state_t; /* * 调用约束: * - state 必须是有效的非空指针 * - state_init() / state_cleanup() 必须成对调用 * - 同一个 state 生命周期内,state_init() 不允许重复调用 * - 除 state_init() 外,其余 state 相关接口都要求 state 已初始化 * - workspaces[i] 必须满足 workspace_desc_valid(&workspaces[i], * output_count) * - 传入空指针、未初始化对象或违反前置条件属于调用方错误 * * 初始化时根据描述表构建 outputs[] 与 workspaces[]。 * workspace_id 由 state 按描述表顺序分配并保持稳定,不从 desc 中读取。 * 每个 output 的 current_workspace_id 会自动设置为首个归属到该 output 的 * workspace;若某个 output 没有任何归属 workspace,state_init() 会失败。 */ void state_init(state_t *state, const output_info_t *outputs, size_t output_count, const workspace_desc_t *workspaces, size_t workspace_count); void state_cleanup(state_t *state); /* * state 持有的 workspace 集合接口 * * 这组接口对外只提供只读访问。 * workspace 的运行期可变状态必须通过专门的 state 级更新接口修改。 */ const workspace_t *state_workspace_get(const state_t *state, workspace_id_t id); const workspace_t *state_workspace_at(const state_t *state, size_t index); bool state_workspace_cycle_layout(state_t *state, workspace_id_t workspace_id); bool state_workspace_set_layout_by_index(state_t *state, workspace_id_t workspace_id, size_t index); bool state_workspace_set_layout_by_id(state_t *state, workspace_id_t workspace_id, layout_id_t layout_id); void state_workspace_set_focused_window(state_t *state, workspace_id_t workspace_id, window_id_t window_id); size_t state_workspace_count(const state_t *state); bool state_workspace_valid(const state_t *state, workspace_id_t id); /* * state 持有的 output 集合接口 * * 这组接口对外只提供只读访问。 * output 的运行期可变状态必须通过专门的 state 级更新接口修改。 */ const output_t *state_output_get(const state_t *state, output_id_t id); const output_t *state_output_at(const state_t *state, size_t index); void state_output_set_workarea(state_t *state, output_id_t output_id, rect_t workarea); void state_output_set_current_workspace(state_t *state, output_id_t output_id, workspace_id_t workspace_id); size_t state_output_count(const state_t *state); bool state_output_valid(const state_t *state, output_id_t id); void state_cycle_current_output(state_t *state, int delta); /* * state 持有的 window 集合接口 * * 这组接口负责管理 state_t.windows[] 容器本身,并维护分层的堆叠顺序。 * 接口返回的 window 对象仅提供只读访问。 * window 的运行期可变状态必须通过专门的 state 级更新接口修改。 */ /* * 添加窗口,并将其追加到对应堆栈顶部 * * info 提供窗口的基础信息 * workspace 归属与其他策略相关字段由后续 state_window_* 接口设置。 */ const window_t *state_window_add(state_t *state, const window_info_t *info); const window_t *state_window_get(const state_t *state, window_id_t id); const window_t *state_window_at(const state_t *state, size_t index); /* 删除窗口,并同步将其从对应的堆叠栈中移除 */ void state_window_remove(state_t *state, window_id_t id); size_t state_window_count(const state_t *state); /* state 持有的单个 window 状态更新接口 */ void state_window_set_workspace(state_t *state, window_id_t window_id, workspace_id_t workspace_id); void state_window_set_geometry_mode(state_t *state, window_id_t window_id, window_geometry_mode_t geometry_mode); void state_window_set_floating(state_t *state, window_id_t window_id, bool floating); void state_window_set_sticky(state_t *state, window_id_t window_id, bool sticky); void state_window_set_urgent(state_t *state, window_id_t window_id, bool urgent); void state_window_set_fixed_size(state_t *state, window_id_t window_id, bool fixed_size); void state_window_set_skip_taskbar(state_t *state, window_id_t window_id, bool skip_taskbar); void state_window_set_float_rect(state_t *state, window_id_t window_id, rect_t float_rect); void state_window_set_frame_rect(state_t *state, window_id_t window_id, rect_t frame_rect); /** * @brief 按字段掩码转移窗口元数据的所有权 * @param state 状态实例指针 * @param window_id 目标窗口 id * @param metadata 元数据来源;成功时仅被转移字段会被置空 * @param changed_fields 需要转移的字段掩码 * @return 成功返回 true;若目标窗口不存在则返回 false * @details * 成功时,仅转移 changed_fields 指定的字段到目标 window,并将 metadata 中对应 * 字段置空;未置位字段保持在 metadata 中,所有权仍归调用方。 * * 失败时,不接管 metadata 中任何字段的所有权,metadata 保持不变,仍由调用方负 * 责后续访问与释放。 */ bool state_window_take_metadata(state_t *state, window_id_t window_id, window_metadata_t *metadata, uint32_t changed_fields); bool state_window_set_title(state_t *state, window_id_t window_id, const char *title); bool state_window_set_app_id(state_t *state, window_id_t window_id, const char *app_id); bool state_window_set_role(state_t *state, window_id_t window_id, const char *role); bool state_window_set_class(state_t *state, window_id_t window_id, const char *class_name); bool state_window_set_instance(state_t *state, window_id_t window_id, const char *instance_name); bool state_stack_raise(state_t *state, window_id_t window_id); bool state_stack_lower(state_t *state, window_id_t window_id);