#pragma once #include #include #include "base/window_list.h" #include "core/layer.h" #include "core/types.h" #include "core/window.h" #include "core/wm_desc.h" 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); /** * @brief 当前 workspace 是否显示 * * @return 若 workspace_id 代表的 workspace 是其所属的 output 当前显示的 * workspace 则返回 true ,否则返回 false */ bool state_workspace_show(const state_t *state, workspace_id_t workspace_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 ); /** * @brief 设置 output 的当前 workspace * * @param state 状态实例指针 * @param output_id 需要切换的当前 workspace 的 output 的 id * @param workspace_id 目标 workspace 的 id * @param old_workspace_id 用于输出变更之前 output 显示的 workspace , * 如果不关心,可以传 nullptr * * @return 若 workspace 需要切换返回 true ,否则返回 false */ bool state_output_set_current_workspace( state_t *state, output_id_t output_id, workspace_id_t workspace_id, workspace_id_t *old_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); /** * @brief 设置当前 output * * @param state 状态实例指针 * @param output_id 目标 output 的 id * * @return 有变更返回 true ,无变更返回 false */ bool state_set_current_output(state_t *state, output_id_t output_id); /* * 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); /* 删除窗口,同步将其从对应的堆叠栈中移除,并调整对应 workspace 的焦点窗口 */ 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_fullscreen( state_t *state, window_id_t window_id, bool fullscreen ); void state_window_set_maximized( state_t *state, window_id_t window_id, bool maximized ); void state_window_set_minimized( state_t *state, window_id_t window_id, bool minimized ); 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_border_width( state_t *state, window_id_t window_id, uint32_t border_width ); 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); /** * @brief 获取 workspace_id 对应 workspace 需要自动布局的窗口列表 * * @details 该函数不负责 window_list_out 参数的初始化 * * @param state 状态实例指针 * @param workspace_id 目标 workspace 的 id * @param window_list_out 存储窗口列表结果的结构体指针 */ void state_get_windows_need_layout_in_workspace( const state_t *state, workspace_id_t workspace_id, window_list_t *window_list_out );