Compare commits
2 Commits
6561b16be0
...
2fc4b33359
| Author | SHA1 | Date | |
|---|---|---|---|
|
2fc4b33359
|
|||
|
7b5404e8e0
|
@@ -5,12 +5,34 @@ BasedOnStyle: Google
|
||||
IndentWidth: 2
|
||||
ConstructorInitializerIndentWidth: 2
|
||||
ContinuationIndentWidth: 2
|
||||
---
|
||||
Language: C
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Right
|
||||
---
|
||||
Language: Cpp
|
||||
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: true
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: true
|
||||
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: true
|
||||
|
||||
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
|
||||
|
||||
IndentCaseLabels: false
|
||||
|
||||
# 多行函数每个参数单独一行
|
||||
AlignAfterOpenBracket: BlockIndent
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
|
||||
# 指针样式(右对齐)
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Right
|
||||
---
|
||||
|
||||
@@ -24,8 +24,10 @@ typedef struct wm_backend_api_t {
|
||||
* X11 这类需要被动抓键的平台可以在这里建立平台侧 grab;
|
||||
* 总能收到所有键盘事件的 backend 可以把它留空。
|
||||
*/
|
||||
bool (*set_keybindings)(wm_backend_t *backend,
|
||||
const wm_key_binding_table_t *keybindings);
|
||||
bool (*set_keybindings)(
|
||||
wm_backend_t *backend,
|
||||
const wm_key_binding_table_t *keybindings
|
||||
);
|
||||
/*
|
||||
* 安装 bootstrap 固定下来的鼠标按键绑定表。
|
||||
* X11 这类需要被动抓按钮的平台可以把它缓存下来,并在 root 或新受管窗口
|
||||
@@ -34,12 +36,16 @@ typedef struct wm_backend_api_t {
|
||||
*/
|
||||
bool (*set_pointer_bindings)(
|
||||
wm_backend_t *backend,
|
||||
const wm_pointer_binding_table_t *pointer_bindings);
|
||||
const wm_pointer_binding_table_t *pointer_bindings
|
||||
);
|
||||
/*
|
||||
* 返回一个 backend 轮询结果。
|
||||
* 只有返回 WM_BACKEND_NEXT_EVENT 时,out 才包含一个完整的 runtime 输入事件。
|
||||
*/
|
||||
wm_backend_next_result_t (*next_event)(wm_backend_t *backend, wm_event_t *out);
|
||||
wm_backend_next_result_t (*next_event)(
|
||||
wm_backend_t *backend,
|
||||
wm_event_t *out
|
||||
);
|
||||
/*
|
||||
* Runtime filters out service-side effects such as WM_EFFECT_RENDER_OUTPUT.
|
||||
* Backends only receive platform effects here.
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "wm_command.h"
|
||||
#include "wm_types.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
* 输入绑定只匹配 backend 已归一化后的输入事件。
|
||||
@@ -71,8 +72,10 @@ typedef struct wm_pointer_binding_table_t {
|
||||
* 出现在 key binding table 里。
|
||||
*/
|
||||
const wm_key_binding_t *wm_key_binding_find(
|
||||
const wm_key_binding_table_t *table, wm_keysym_t keysym,
|
||||
wm_modifier_mask_t modifiers);
|
||||
const wm_key_binding_table_t *table,
|
||||
wm_keysym_t keysym,
|
||||
wm_modifier_mask_t modifiers
|
||||
);
|
||||
|
||||
/*
|
||||
* 查找与当前按钮按下事件匹配的鼠标绑定。
|
||||
@@ -82,5 +85,8 @@ const wm_key_binding_t *wm_key_binding_find(
|
||||
* 匹配顺序与键盘绑定一致:先 exact,再 allow-extra-modifiers。
|
||||
*/
|
||||
const wm_pointer_binding_t *wm_pointer_binding_find(
|
||||
const wm_pointer_binding_table_t *table, wm_button_t button,
|
||||
wm_modifier_mask_t modifiers, bool hits_window);
|
||||
const wm_pointer_binding_table_t *table,
|
||||
wm_button_t button,
|
||||
wm_modifier_mask_t modifiers,
|
||||
bool hits_window
|
||||
);
|
||||
|
||||
@@ -71,7 +71,8 @@ typedef struct wm_pointer_enter_event_t {
|
||||
wm_point_t root;
|
||||
// 相对 window 的坐标;若 window == WM_WINDOW_ID_INVALID,则该值未定义
|
||||
wm_point_t local;
|
||||
// 当前进入并获得 pointer focus 的窗口;若未命中窗口,则为 WM_WINDOW_ID_INVALID
|
||||
// 当前进入并获得 pointer focus 的窗口;若未命中窗口,则为
|
||||
// WM_WINDOW_ID_INVALID
|
||||
wm_window_id_t window;
|
||||
} wm_pointer_enter_event_t;
|
||||
|
||||
|
||||
@@ -27,8 +27,10 @@ typedef struct wm_layout_result_t {
|
||||
size_t item_capacity;
|
||||
} wm_layout_result_t;
|
||||
|
||||
typedef bool (*wm_layout_fn)(const wm_layout_ctx_t *ctx,
|
||||
wm_layout_result_t *out);
|
||||
typedef bool (*wm_layout_fn)(
|
||||
const wm_layout_ctx_t *ctx,
|
||||
wm_layout_result_t *out
|
||||
);
|
||||
|
||||
typedef struct wm_layout_slot_t {
|
||||
wm_layout_id_t id;
|
||||
@@ -67,17 +69,20 @@ bool wm_layout_result_push(wm_layout_result_t *result, wm_layout_item_t item);
|
||||
void wm_layout_registry_init(wm_layout_registry_t *registry);
|
||||
void wm_layout_registry_shutdown(wm_layout_registry_t *registry);
|
||||
size_t wm_layout_registry_count(const wm_layout_registry_t *registry);
|
||||
const wm_layout_slot_t *wm_layout_registry_at(
|
||||
const wm_layout_registry_t *registry, size_t index);
|
||||
const wm_layout_slot_t *
|
||||
wm_layout_registry_at(const wm_layout_registry_t *registry, size_t index);
|
||||
|
||||
wm_layout_id_t wm_layout_register(wm_layout_registry_t *registry,
|
||||
const char *name, const char *symbol,
|
||||
wm_layout_fn fn);
|
||||
wm_layout_id_t wm_layout_register(
|
||||
wm_layout_registry_t *registry,
|
||||
const char *name,
|
||||
const char *symbol,
|
||||
wm_layout_fn fn
|
||||
);
|
||||
/*
|
||||
* layout registry 只允许在 bootstrap / 初始化阶段注册。
|
||||
* 运行时布局集合保持固定,只允许切换 workspace 当前选中的 layout_id。
|
||||
*/
|
||||
wm_layout_fn wm_layout_lookup(const wm_layout_registry_t *registry,
|
||||
wm_layout_id_t id);
|
||||
const wm_layout_slot_t *wm_layout_slot_get(const wm_layout_registry_t *registry,
|
||||
wm_layout_id_t id);
|
||||
wm_layout_fn
|
||||
wm_layout_lookup(const wm_layout_registry_t *registry, wm_layout_id_t id);
|
||||
const wm_layout_slot_t *
|
||||
wm_layout_slot_get(const wm_layout_registry_t *registry, wm_layout_id_t id);
|
||||
|
||||
@@ -20,14 +20,19 @@ void wm_command_buffer_shutdown(wm_command_buffer_t *buffer);
|
||||
|
||||
bool wm_command_buffer_push(wm_command_buffer_t *buffer, wm_command_t command);
|
||||
|
||||
bool wm_policy_route_event(const wm_state_t *state,
|
||||
bool wm_policy_route_event(
|
||||
const wm_state_t *state,
|
||||
const wm_policy_config_t *policy,
|
||||
const wm_key_binding_table_t *keybindings,
|
||||
const wm_pointer_binding_table_t *pointer_bindings,
|
||||
const wm_event_t *event,
|
||||
wm_command_buffer_t *out);
|
||||
wm_command_buffer_t *out
|
||||
);
|
||||
|
||||
bool wm_policy_apply_command(wm_state_t *state,
|
||||
bool wm_policy_apply_command(
|
||||
wm_state_t *state,
|
||||
const wm_policy_config_t *policy,
|
||||
const wm_layout_registry_t *layouts,
|
||||
const wm_command_t *command, wm_plan_t *plan);
|
||||
const wm_command_t *command,
|
||||
wm_plan_t *plan
|
||||
);
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "wm_binding.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "wm_backend.h"
|
||||
#include "wm_binding.h"
|
||||
#include "wm_layout.h"
|
||||
#include "wm_plan.h"
|
||||
#include "wm_policy_config.h"
|
||||
#include "wm_policy.h"
|
||||
#include "wm_policy_config.h"
|
||||
#include "wm_service.h"
|
||||
#include "wm_state.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum wm_interaction_mode_t {
|
||||
WM_INTERACTION_NONE,
|
||||
@@ -63,7 +64,8 @@ typedef struct wm_runtime_bootstrap_t {
|
||||
|
||||
/*
|
||||
* 不可变键盘绑定表。
|
||||
* 当前草案把它视为 bootstrap 提供的只读视图;items 的生命周期必须覆盖 runtime。
|
||||
* 当前草案把它视为 bootstrap 提供的只读视图;items 的生命周期必须覆盖
|
||||
* runtime。
|
||||
*/
|
||||
wm_key_binding_table_t keybindings;
|
||||
|
||||
@@ -115,8 +117,11 @@ typedef struct wm_runtime_t {
|
||||
wm_service_registry_t services;
|
||||
} wm_runtime_t;
|
||||
|
||||
bool wm_runtime_init(wm_runtime_t *runtime, wm_backend_t backend,
|
||||
const wm_runtime_bootstrap_t *bootstrap);
|
||||
bool wm_runtime_init(
|
||||
wm_runtime_t *runtime,
|
||||
wm_backend_t backend,
|
||||
const wm_runtime_bootstrap_t *bootstrap
|
||||
);
|
||||
bool wm_runtime_register_service(wm_runtime_t *runtime, wm_service_t service);
|
||||
|
||||
/*
|
||||
|
||||
@@ -30,8 +30,11 @@ typedef struct wm_service_t wm_service_t;
|
||||
|
||||
typedef struct wm_service_api_t {
|
||||
bool (*init)(wm_service_t *service);
|
||||
void (*handle_event)(wm_service_t *service, const wm_service_event_t *event,
|
||||
const wm_state_t *state);
|
||||
void (*handle_event)(
|
||||
wm_service_t *service,
|
||||
const wm_service_event_t *event,
|
||||
const wm_state_t *state
|
||||
);
|
||||
void (*shutdown)(wm_service_t *service);
|
||||
} wm_service_api_t;
|
||||
|
||||
@@ -49,8 +52,12 @@ typedef struct wm_service_registry_t {
|
||||
void wm_service_registry_init(wm_service_registry_t *registry);
|
||||
void wm_service_registry_shutdown(wm_service_registry_t *registry);
|
||||
|
||||
bool wm_service_registry_register(wm_service_registry_t *registry,
|
||||
wm_service_t service);
|
||||
void wm_service_registry_emit(wm_service_registry_t *registry,
|
||||
bool wm_service_registry_register(
|
||||
wm_service_registry_t *registry,
|
||||
wm_service_t service
|
||||
);
|
||||
void wm_service_registry_emit(
|
||||
wm_service_registry_t *registry,
|
||||
const wm_service_event_t *event,
|
||||
const wm_state_t *state);
|
||||
const wm_state_t *state
|
||||
);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "wm_types.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "wm_types.h"
|
||||
|
||||
// ========== 核心实体定义 ==========
|
||||
|
||||
typedef struct wm_window_t {
|
||||
@@ -80,9 +81,11 @@ typedef struct wm_state_t {
|
||||
|
||||
// 初始化/清理
|
||||
// workspace/output 集合大小在 init 时一次性确定,之后不再变化。
|
||||
void wm_state_init(wm_state_t *state,
|
||||
void wm_state_init(
|
||||
wm_state_t *state,
|
||||
size_t workspace_count,
|
||||
size_t output_count);
|
||||
size_t output_count
|
||||
);
|
||||
void wm_state_shutdown(wm_state_t *state);
|
||||
|
||||
// ========== Workspace 访问 ==========
|
||||
@@ -91,14 +94,18 @@ wm_workspace_t *wm_state_workspace(wm_state_t *state, wm_workspace_id_t id);
|
||||
wm_workspace_t *wm_state_workspace_at(wm_state_t *state, size_t index);
|
||||
size_t wm_state_workspace_count(const wm_state_t *state);
|
||||
bool wm_state_workspace_valid(wm_state_t *state, wm_workspace_id_t id);
|
||||
void wm_state_workspace_set_focused_window(wm_state_t *state,
|
||||
void wm_state_workspace_set_focused_window(
|
||||
wm_state_t *state,
|
||||
wm_workspace_id_t workspace_id,
|
||||
wm_window_id_t window_id);
|
||||
wm_window_id_t window_id
|
||||
);
|
||||
|
||||
// 查询某个 output 的所有 workspace(只读视图)
|
||||
size_t wm_state_workspace_get_by_output(const wm_state_t *state,
|
||||
size_t wm_state_workspace_get_by_output(
|
||||
const wm_state_t *state,
|
||||
wm_output_id_t output_id,
|
||||
wm_workspace_t **out_workspaces);
|
||||
wm_workspace_t **out_workspaces
|
||||
);
|
||||
|
||||
// ========== Workspace 布局操作 ==========
|
||||
|
||||
@@ -106,16 +113,18 @@ size_t wm_state_workspace_get_by_output(const wm_state_t *state,
|
||||
* 设置 workspace 的可用布局列表。
|
||||
* 仅允许在 bootstrap / 初始化阶段调用;运行时不应修改。
|
||||
*/
|
||||
void wm_workspace_set_layouts(wm_workspace_t *workspace,
|
||||
void wm_workspace_set_layouts(
|
||||
wm_workspace_t *workspace,
|
||||
const wm_layout_id_t *layouts,
|
||||
size_t count);
|
||||
size_t count
|
||||
);
|
||||
|
||||
/*
|
||||
* 获取 workspace 的可用布局列表。
|
||||
* 该列表在 bootstrap 完成后保持不变。
|
||||
*/
|
||||
const wm_layout_id_t *wm_workspace_get_layouts(const wm_workspace_t *workspace,
|
||||
size_t *out_count);
|
||||
const wm_layout_id_t *
|
||||
wm_workspace_get_layouts(const wm_workspace_t *workspace, size_t *out_count);
|
||||
|
||||
/*
|
||||
* 切换到下一个布局(循环)
|
||||
@@ -130,7 +139,10 @@ bool wm_workspace_set_layout_by_index(wm_workspace_t *workspace, size_t index);
|
||||
/*
|
||||
* 切换到指定 ID 的布局(如果该布局在可用列表中)
|
||||
*/
|
||||
bool wm_workspace_set_layout_by_id(wm_workspace_t *workspace, wm_layout_id_t id);
|
||||
bool wm_workspace_set_layout_by_id(
|
||||
wm_workspace_t *workspace,
|
||||
wm_layout_id_t id
|
||||
);
|
||||
|
||||
// ========== Output 访问 ==========
|
||||
|
||||
@@ -143,9 +155,11 @@ bool wm_state_output_valid(wm_state_t *state, wm_output_id_t id);
|
||||
* 这不会修改 output 集合本身,也不会改变 workspace->output_id 绑定。
|
||||
* 调用方必须保证目标 workspace 固定归属于该 output。
|
||||
*/
|
||||
void wm_state_output_set_current_workspace(wm_state_t *state,
|
||||
void wm_state_output_set_current_workspace(
|
||||
wm_state_t *state,
|
||||
wm_output_id_t output_id,
|
||||
wm_workspace_id_t workspace_id);
|
||||
wm_workspace_id_t workspace_id
|
||||
);
|
||||
|
||||
// ========== Window 操作 ==========
|
||||
|
||||
@@ -154,43 +168,81 @@ wm_window_t *wm_state_window_get(wm_state_t *state, wm_window_id_t id);
|
||||
wm_window_t *wm_state_window_at(wm_state_t *state, size_t index);
|
||||
void wm_state_window_remove(wm_state_t *state, wm_window_id_t id);
|
||||
size_t wm_state_window_count(const wm_state_t *state);
|
||||
void wm_state_window_set_workspace(wm_state_t *state, wm_window_id_t window_id,
|
||||
wm_workspace_id_t workspace_id);
|
||||
void wm_state_window_set_geometry_mode(wm_state_t *state,
|
||||
void wm_state_window_set_workspace(
|
||||
wm_state_t *state,
|
||||
wm_window_id_t window_id,
|
||||
wm_window_geometry_mode_t geometry_mode);
|
||||
void wm_state_window_set_floating(wm_state_t *state, wm_window_id_t window_id,
|
||||
bool floating);
|
||||
void wm_state_window_set_sticky(wm_state_t *state, wm_window_id_t window_id,
|
||||
bool sticky);
|
||||
void wm_state_window_set_urgent(wm_state_t *state, wm_window_id_t window_id,
|
||||
bool urgent);
|
||||
void wm_state_window_set_fixed_size(wm_state_t *state,
|
||||
wm_workspace_id_t workspace_id
|
||||
);
|
||||
void wm_state_window_set_geometry_mode(
|
||||
wm_state_t *state,
|
||||
wm_window_id_t window_id,
|
||||
bool fixed_size);
|
||||
void wm_state_window_set_skip_taskbar(wm_state_t *state,
|
||||
wm_window_geometry_mode_t geometry_mode
|
||||
);
|
||||
void wm_state_window_set_floating(
|
||||
wm_state_t *state,
|
||||
wm_window_id_t window_id,
|
||||
bool skip_taskbar);
|
||||
void wm_state_window_set_float_rect(wm_state_t *state, wm_window_id_t window_id,
|
||||
wm_rect_t float_rect);
|
||||
void wm_state_window_set_frame_rect(wm_state_t *state, wm_window_id_t window_id,
|
||||
wm_rect_t frame_rect);
|
||||
bool wm_state_window_set_title(wm_state_t *state, wm_window_id_t window_id,
|
||||
const char *title);
|
||||
bool wm_state_window_set_app_id(wm_state_t *state, wm_window_id_t window_id,
|
||||
const char *app_id);
|
||||
bool wm_state_window_set_class(wm_state_t *state, wm_window_id_t window_id,
|
||||
const char *class_name);
|
||||
bool wm_state_window_set_instance(wm_state_t *state, wm_window_id_t window_id,
|
||||
const char *instance_name);
|
||||
bool floating
|
||||
);
|
||||
void wm_state_window_set_sticky(
|
||||
wm_state_t *state,
|
||||
wm_window_id_t window_id,
|
||||
bool sticky
|
||||
);
|
||||
void wm_state_window_set_urgent(
|
||||
wm_state_t *state,
|
||||
wm_window_id_t window_id,
|
||||
bool urgent
|
||||
);
|
||||
void wm_state_window_set_fixed_size(
|
||||
wm_state_t *state,
|
||||
wm_window_id_t window_id,
|
||||
bool fixed_size
|
||||
);
|
||||
void wm_state_window_set_skip_taskbar(
|
||||
wm_state_t *state,
|
||||
wm_window_id_t window_id,
|
||||
bool skip_taskbar
|
||||
);
|
||||
void wm_state_window_set_float_rect(
|
||||
wm_state_t *state,
|
||||
wm_window_id_t window_id,
|
||||
wm_rect_t float_rect
|
||||
);
|
||||
void wm_state_window_set_frame_rect(
|
||||
wm_state_t *state,
|
||||
wm_window_id_t window_id,
|
||||
wm_rect_t frame_rect
|
||||
);
|
||||
bool wm_state_window_set_title(
|
||||
wm_state_t *state,
|
||||
wm_window_id_t window_id,
|
||||
const char *title
|
||||
);
|
||||
bool wm_state_window_set_app_id(
|
||||
wm_state_t *state,
|
||||
wm_window_id_t window_id,
|
||||
const char *app_id
|
||||
);
|
||||
bool wm_state_window_set_class(
|
||||
wm_state_t *state,
|
||||
wm_window_id_t window_id,
|
||||
const char *class_name
|
||||
);
|
||||
bool wm_state_window_set_instance(
|
||||
wm_state_t *state,
|
||||
wm_window_id_t window_id,
|
||||
const char *instance_name
|
||||
);
|
||||
|
||||
// ========== 查询辅助函数 ==========
|
||||
|
||||
/*
|
||||
* 判断工作区是否可见(某个 output 正在显示它)
|
||||
*/
|
||||
bool wm_state_workspace_is_visible(const wm_state_t *state,
|
||||
wm_workspace_id_t workspace_id);
|
||||
bool wm_state_workspace_is_visible(
|
||||
const wm_state_t *state,
|
||||
wm_workspace_id_t workspace_id
|
||||
);
|
||||
|
||||
/*
|
||||
* 判断窗口是否可见
|
||||
@@ -199,12 +251,16 @@ bool wm_state_workspace_is_visible(const wm_state_t *state,
|
||||
* 2. 否则,窗口的 workspace 固定归属某个 output
|
||||
* 3. 且该 output 当前正显示这个 workspace
|
||||
*/
|
||||
bool wm_state_window_should_be_visible(const wm_state_t *state,
|
||||
const wm_window_t *window);
|
||||
bool wm_state_window_should_be_visible(
|
||||
const wm_state_t *state,
|
||||
const wm_window_t *window
|
||||
);
|
||||
|
||||
/*
|
||||
* 判断窗口是否在特定 output 上可见
|
||||
*/
|
||||
bool wm_state_window_should_be_visible_on_output(const wm_state_t *state,
|
||||
bool wm_state_window_should_be_visible_on_output(
|
||||
const wm_state_t *state,
|
||||
const wm_window_t *window,
|
||||
const wm_output_t *output);
|
||||
const wm_output_t *output
|
||||
);
|
||||
|
||||
@@ -31,9 +31,9 @@ typedef uint32_t wm_rgba32_t;
|
||||
|
||||
// 无效 ID 标记
|
||||
#define WM_WINDOW_ID_INVALID ((wm_window_id_t)0)
|
||||
#define WM_WORKSPACE_ID_INVALID ((wm_workspace_id_t)-1)
|
||||
#define WM_OUTPUT_ID_INVALID ((wm_output_id_t)-1)
|
||||
#define WM_LAYOUT_ID_INVALID ((wm_layout_id_t)-1)
|
||||
#define WM_WORKSPACE_ID_INVALID ((wm_workspace_id_t) - 1)
|
||||
#define WM_OUTPUT_ID_INVALID ((wm_output_id_t) - 1)
|
||||
#define WM_LAYOUT_ID_INVALID ((wm_layout_id_t) - 1)
|
||||
#define WM_KEYSYM_INVALID ((wm_keysym_t)0)
|
||||
|
||||
/*
|
||||
|
||||
@@ -35,10 +35,13 @@ typedef struct zdwm_api_t {
|
||||
* @returns 返回布局算法对应的布局 id ,如果注册失败,返回
|
||||
* ZDWM_LAYOUT_ID_INVALID
|
||||
*/
|
||||
zdwm_layout_id_t (*register_layout)(zdwm_config_builder_t *builder,
|
||||
const char *name, const char *symbol,
|
||||
zdwm_layout_id_t (*register_layout)(
|
||||
zdwm_config_builder_t *builder,
|
||||
const char *name,
|
||||
const char *symbol,
|
||||
const char *description,
|
||||
zdwm_layout_fn fn);
|
||||
zdwm_layout_fn fn
|
||||
);
|
||||
|
||||
/**
|
||||
* 用户调用这个函数添加 output 中的工作空间
|
||||
@@ -50,11 +53,14 @@ typedef struct zdwm_api_t {
|
||||
* @param initial_layout_id 初始布局算法 id
|
||||
* @returns 返回工作空间 id 。如果注册失败,返回 ZDWM_WORKSPACE_ID_INVALID
|
||||
*/
|
||||
zdwm_workspace_id_t (*define_workspace)(zdwm_config_builder_t *builder,
|
||||
size_t output_index, const char *name,
|
||||
zdwm_workspace_id_t (*define_workspace)(
|
||||
zdwm_config_builder_t *builder,
|
||||
size_t output_index,
|
||||
const char *name,
|
||||
const zdwm_layout_id_t *layout_ids,
|
||||
size_t layout_count,
|
||||
zdwm_layout_id_t initial_layout_id);
|
||||
zdwm_layout_id_t initial_layout_id
|
||||
);
|
||||
|
||||
/**
|
||||
* 用户调用这个函数添加窗口规则
|
||||
@@ -65,9 +71,11 @@ typedef struct zdwm_api_t {
|
||||
* @details 不合法的情况:match 所有字段全为 nullptr;
|
||||
* 或 action 无任何动作;或 action 指定的 workspace 不存在
|
||||
*/
|
||||
bool (*add_rule)(zdwm_config_builder_t *builder,
|
||||
bool (*add_rule)(
|
||||
zdwm_config_builder_t *builder,
|
||||
const zdwm_rule_match_t *match,
|
||||
const zdwm_rule_action_t *action);
|
||||
const zdwm_rule_action_t *action
|
||||
);
|
||||
} zdwm_api_t;
|
||||
|
||||
/**
|
||||
@@ -79,10 +87,12 @@ typedef struct zdwm_api_t {
|
||||
* @param output_count 屏幕个数
|
||||
* @returns 用户配置成功返回 true ,配置失败返回 false
|
||||
*/
|
||||
typedef bool zdwm_config_setup_fn(const zdwm_api_t *api,
|
||||
typedef bool zdwm_config_setup_fn(
|
||||
const zdwm_api_t *api,
|
||||
zdwm_config_builder_t *builder,
|
||||
const zdwm_output_info_t *outputs,
|
||||
size_t output_count);
|
||||
size_t output_count
|
||||
);
|
||||
|
||||
/* 用户在自己的动态链接库配置中必须实现该函数 */
|
||||
extern zdwm_config_setup_fn setup;
|
||||
|
||||
@@ -30,16 +30,18 @@ typedef struct zdwm_layout_result_t {
|
||||
size_t item_capacity;
|
||||
} zdwm_layout_result_t;
|
||||
|
||||
typedef bool (*zdwm_layout_fn)(const zdwm_layout_ctx_t *ctx,
|
||||
zdwm_layout_result_t *out);
|
||||
typedef bool (*zdwm_layout_fn)(
|
||||
const zdwm_layout_ctx_t *ctx,
|
||||
zdwm_layout_result_t *out
|
||||
);
|
||||
|
||||
static inline void zdwm_layout_result_reset(zdwm_layout_result_t *result) {
|
||||
if (!result) abort();
|
||||
result->item_count = 0;
|
||||
}
|
||||
|
||||
static inline void zdwm_layout_result_push(zdwm_layout_result_t *result,
|
||||
zdwm_layout_item_t item) {
|
||||
static inline void
|
||||
zdwm_layout_result_push(zdwm_layout_result_t *result, zdwm_layout_item_t item) {
|
||||
if (!result) abort();
|
||||
|
||||
if (result->item_count == result->item_capacity) {
|
||||
@@ -47,6 +49,7 @@ static inline void zdwm_layout_result_push(zdwm_layout_result_t *result,
|
||||
zdwm_layout_item_t *items =
|
||||
realloc(result->items, capacity * sizeof(*result->items));
|
||||
if (!items) abort();
|
||||
|
||||
result->items = items;
|
||||
result->item_capacity = capacity;
|
||||
}
|
||||
|
||||
@@ -11,11 +11,9 @@ typedef uint32_t zdwm_layout_id_t;
|
||||
typedef uint32_t zdwm_window_id_t;
|
||||
typedef uint32_t zdwm_workspace_id_t;
|
||||
|
||||
/* clang-format off */
|
||||
#define ZDWM_LAYOUT_ID_INVALID ((zdwm_layout_id_t)UINT32_MAX)
|
||||
#define ZDWM_WINDOW_ID_INVALID ((zdwm_window_id_t)0)
|
||||
#define ZDWM_WORKSPACE_ID_INVALID ((zdwm_workspace_id_t)UINT32_MAX)
|
||||
/* clang-format on */
|
||||
|
||||
typedef struct zdwm_rect_t {
|
||||
int32_t x;
|
||||
|
||||
16
src/.clang-format
Normal file
16
src/.clang-format
Normal file
@@ -0,0 +1,16 @@
|
||||
# -*- mode: yaml; -*-
|
||||
|
||||
---
|
||||
BasedOnStyle: Google
|
||||
IndentWidth: 2
|
||||
ConstructorInitializerIndentWidth: 2
|
||||
ContinuationIndentWidth: 2
|
||||
---
|
||||
Language: C
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Right
|
||||
---
|
||||
Language: Cpp
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Right
|
||||
---
|
||||
@@ -78,8 +78,8 @@ void raise_or_run(const user_action_arg_t *arg) {
|
||||
bool monitor_changed = client->monitor != wm.current_monitor;
|
||||
bool tag_changed = client->tags != client->monitor->selected_tag->mask;
|
||||
if (monitor_changed || tag_changed) {
|
||||
point_t point = monitor_changed ? monitor_get_restore_cursor_point(
|
||||
client->monitor)
|
||||
point_t point = monitor_changed
|
||||
? monitor_get_restore_cursor_point(client->monitor)
|
||||
: xcursor_query_pointer_position();
|
||||
wm_ignore_enter_notify_at_point(point);
|
||||
}
|
||||
|
||||
1
src/backend/.clang-format
Symbolic link
1
src/backend/.clang-format
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.clang-format
|
||||
@@ -14,8 +14,8 @@ static inline bool fully_contains(rect_t outer, rect_t inner) {
|
||||
right(inner) <= right(outer) && bottom(inner) <= bottom(outer);
|
||||
}
|
||||
|
||||
backend_detect_t *output_remove_duplication(const output_info_t *output,
|
||||
const size_t count) {
|
||||
backend_detect_t *
|
||||
output_remove_duplication(const output_info_t *output, const size_t count) {
|
||||
if (!output || count < 1) return nullptr;
|
||||
|
||||
bool *remove = p_new(bool, count);
|
||||
|
||||
@@ -5,5 +5,5 @@
|
||||
#include "core/backend.h"
|
||||
#include "core/types.h"
|
||||
|
||||
backend_detect_t *output_remove_duplication(const output_info_t *output,
|
||||
const size_t count);
|
||||
backend_detect_t *
|
||||
output_remove_duplication(const output_info_t *output, const size_t count);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "base/macros.h"
|
||||
#include "base/memory.h"
|
||||
#include "core/types.h"
|
||||
#include "internal.h" /* IWYU pragma: keep */
|
||||
#include "internal.h"
|
||||
|
||||
typedef struct atom_item_t {
|
||||
const char *name;
|
||||
@@ -28,64 +28,9 @@ static void atoms_init(backend_t *backend) {
|
||||
xcb_connection_t *conn = backend->conn;
|
||||
atoms_t *atoms = &backend->atoms;
|
||||
|
||||
atom_item_t atom_list[] = {
|
||||
{"COMPOUND_TEXT", sizeof("COMPOUND_TEXT") - 1, &atoms->COMPOUND_TEXT},
|
||||
{"UTF8_STRING", sizeof("UTF8_STRING") - 1, &atoms->UTF8_STRING},
|
||||
|
||||
{"WM_WINDOW_ROLE", sizeof("WM_WINDOW_ROLE") - 1, &atoms->WM_WINDOW_ROLE},
|
||||
{"WM_NAME", sizeof("WM_NAME") - 1, &atoms->WM_NAME},
|
||||
{"_NET_WM_NAME", sizeof("_NET_WM_NAME") - 1, &atoms->_NET_WM_NAME},
|
||||
|
||||
{"_NET_WM_STATE", sizeof("_NET_WM_STATE") - 1, &atoms->_NET_WM_STATE},
|
||||
{"_NET_WM_STATE_FULLSCREEN", sizeof("_NET_WM_STATE_FULLSCREEN") - 1,
|
||||
&atoms->_NET_WM_STATE_FULLSCREEN},
|
||||
{"_NET_WM_STATE_ABOVE", sizeof("_NET_WM_STATE_ABOVE") - 1,
|
||||
&atoms->_NET_WM_STATE_ABOVE},
|
||||
{"_NET_WM_STATE_STICKY", sizeof("_NET_WM_STATE_STICKY") - 1,
|
||||
&atoms->_NET_WM_STATE_STICKY},
|
||||
{"_NET_WM_STATE_MODAL", sizeof("_NET_WM_STATE_MODAL") - 1,
|
||||
&atoms->_NET_WM_STATE_MODAL},
|
||||
{"_NET_WM_STATE_SKIP_TASKBAR", sizeof("_NET_WM_STATE_SKIP_TASKBAR") - 1,
|
||||
&atoms->_NET_WM_STATE_SKIP_TASKBAR},
|
||||
{"_NET_WM_STATE_MAXIMIZED_VERT", sizeof("_NET_WM_STATE_MAXIMIZED_VERT") - 1,
|
||||
&atoms->_NET_WM_STATE_MAXIMIZED_VERT},
|
||||
{"_NET_WM_STATE_MAXIMIZED_HORZ", sizeof("_NET_WM_STATE_MAXIMIZED_HORZ") - 1,
|
||||
&atoms->_NET_WM_STATE_MAXIMIZED_HORZ},
|
||||
|
||||
{"_NET_WM_WINDOW_TYPE", sizeof("_NET_WM_WINDOW_TYPE") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE},
|
||||
{"_NET_WM_WINDOW_TYPE_NORMAL", sizeof("_NET_WM_WINDOW_TYPE_NORMAL") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE_NORMAL},
|
||||
{"_NET_WM_WINDOW_TYPE_DESKTOP", sizeof("_NET_WM_WINDOW_TYPE_DESKTOP") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE_DESKTOP},
|
||||
{"_NET_WM_WINDOW_TYPE_DOCK", sizeof("_NET_WM_WINDOW_TYPE_DOCK") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE_DOCK},
|
||||
{"_NET_WM_WINDOW_TYPE_TOOLBAR", sizeof("_NET_WM_WINDOW_TYPE_TOOLBAR") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE_TOOLBAR},
|
||||
{"_NET_WM_WINDOW_TYPE_DIALOG", sizeof("_NET_WM_WINDOW_TYPE_DIALOG") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE_DIALOG},
|
||||
{"_NET_WM_WINDOW_TYPE_UTILITY", sizeof("_NET_WM_WINDOW_TYPE_UTILITY") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE_UTILITY},
|
||||
{"_NET_WM_WINDOW_TYPE_SPLASH", sizeof("_NET_WM_WINDOW_TYPE_SPLASH") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE_SPLASH},
|
||||
{"_NET_WM_WINDOW_TYPE_MENU", sizeof("_NET_WM_WINDOW_TYPE_MENU") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE_MENU},
|
||||
{"_NET_WM_WINDOW_TYPE_DROPDOWN_MENU",
|
||||
sizeof("_NET_WM_WINDOW_TYPE_DROPDOWN_MENU") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE_DROPDOWN_MENU},
|
||||
{"_NET_WM_WINDOW_TYPE_POPUP_MENU",
|
||||
sizeof("_NET_WM_WINDOW_TYPE_POPUP_MENU") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE_POPUP_MENU},
|
||||
{"_NET_WM_WINDOW_TYPE_TOOLTIP", sizeof("_NET_WM_WINDOW_TYPE_TOOLTIP") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE_TOOLTIP},
|
||||
{"_NET_WM_WINDOW_TYPE_COMBO", sizeof("_NET_WM_WINDOW_TYPE_COMBO") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE_COMBO},
|
||||
{"_NET_WM_WINDOW_TYPE_DND", sizeof("_NET_WM_WINDOW_TYPE_DND") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE_DND},
|
||||
{"_NET_WM_WINDOW_TYPE_NOTIFICATION",
|
||||
sizeof("_NET_WM_WINDOW_TYPE_NOTIFICATION") - 1,
|
||||
&atoms->_NET_WM_WINDOW_TYPE_NOTIFICATION},
|
||||
};
|
||||
#define ATOM_ITEM(name) {#name, sizeof(#name) - 1, &atoms->name},
|
||||
atom_item_t atom_list[] = {ATOM_LIST(ATOM_ITEM)};
|
||||
#undef ATOM_ITEM
|
||||
|
||||
xcb_intern_atom_cookie_t cookies[countof(atom_list)];
|
||||
for (size_t i = 0; i < countof(atom_list); ++i) {
|
||||
@@ -125,7 +70,8 @@ backend_t *backend_create(const char *display_name) {
|
||||
if (xcb_request_check(conn, cookie)) {
|
||||
fatal(
|
||||
"another window manager is already running (cannot select "
|
||||
"SubstructureRedirect)");
|
||||
"SubstructureRedirect)"
|
||||
);
|
||||
}
|
||||
|
||||
backend_t *backend = p_new(backend_t, 1);
|
||||
@@ -138,7 +84,10 @@ backend_t *backend_create(const char *display_name) {
|
||||
xcb_get_extension_data(conn, &xcb_xfixes_id);
|
||||
if (query && query->present) {
|
||||
xcb_xfixes_query_version_cookie_t cookie = xcb_xfixes_query_version(
|
||||
conn, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION);
|
||||
conn,
|
||||
XCB_XFIXES_MAJOR_VERSION,
|
||||
XCB_XFIXES_MINOR_VERSION
|
||||
);
|
||||
xcb_xfixes_query_version_reply_t *reply =
|
||||
xcb_xfixes_query_version_reply(conn, cookie, nullptr);
|
||||
|
||||
@@ -163,15 +112,21 @@ void backend_destroy(backend_t *backend) {
|
||||
free(backend);
|
||||
}
|
||||
|
||||
static bool detect_monitor_by_randr(const backend_t *backend,
|
||||
output_info_t **outputs, size_t *count) {
|
||||
static bool detect_monitor_by_randr(
|
||||
const backend_t *backend,
|
||||
output_info_t **outputs,
|
||||
size_t *count
|
||||
) {
|
||||
xcb_prefetch_extension_data(backend->conn, &xcb_randr_id);
|
||||
const xcb_query_extension_reply_t *query =
|
||||
xcb_get_extension_data(backend->conn, &xcb_randr_id);
|
||||
if (!query || !query->present) return false;
|
||||
|
||||
xcb_randr_query_version_cookie_t cookie = xcb_randr_query_version(
|
||||
backend->conn, XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION);
|
||||
backend->conn,
|
||||
XCB_RANDR_MAJOR_VERSION,
|
||||
XCB_RANDR_MINOR_VERSION
|
||||
);
|
||||
xcb_randr_query_version_reply_t *reply =
|
||||
xcb_randr_query_version_reply(backend->conn, cookie, nullptr);
|
||||
if (!reply) return false;
|
||||
@@ -236,15 +191,21 @@ static bool detect_monitor_by_randr(const backend_t *backend,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool detect_monitor_by_xinerama(const backend_t *backend,
|
||||
output_info_t **outputs, size_t *count) {
|
||||
static bool detect_monitor_by_xinerama(
|
||||
const backend_t *backend,
|
||||
output_info_t **outputs,
|
||||
size_t *count
|
||||
) {
|
||||
xcb_prefetch_extension_data(backend->conn, &xcb_xinerama_id);
|
||||
const xcb_query_extension_reply_t *query =
|
||||
xcb_get_extension_data(backend->conn, &xcb_xinerama_id);
|
||||
if (!query || !query->present) return false;
|
||||
|
||||
xcb_xinerama_query_version_cookie_t cookie = xcb_xinerama_query_version(
|
||||
backend->conn, XCB_XINERAMA_MAJOR_VERSION, XCB_XINERAMA_MINOR_VERSION);
|
||||
backend->conn,
|
||||
XCB_XINERAMA_MAJOR_VERSION,
|
||||
XCB_XINERAMA_MINOR_VERSION
|
||||
);
|
||||
xcb_xinerama_query_version_reply_t *version_reply =
|
||||
xcb_xinerama_query_version_reply(backend->conn, cookie, nullptr);
|
||||
if (!version_reply) return false;
|
||||
@@ -338,8 +299,11 @@ void backend_detect_destroy(backend_detect_t *detect) {
|
||||
free(detect);
|
||||
}
|
||||
|
||||
bool backend_apply_effect(backend_t *backend, const effect_t *effects,
|
||||
size_t effect_count) {
|
||||
bool backend_apply_effect(
|
||||
backend_t *backend,
|
||||
const effect_t *effects,
|
||||
size_t effect_count
|
||||
) {
|
||||
/* TODO: */
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -11,11 +11,14 @@
|
||||
#include "core/backend.h"
|
||||
#include "core/types.h"
|
||||
#include "core/window.h"
|
||||
#include "internal.h" /* IWYU pragma: keep */
|
||||
#include "internal.h"
|
||||
|
||||
static window_state_t *derive_window_states(const atoms_t *atoms,
|
||||
static window_state_t *derive_window_states(
|
||||
const atoms_t *atoms,
|
||||
const xcb_atom_t *raw,
|
||||
uint32_t count, size_t *out_count) {
|
||||
uint32_t count,
|
||||
size_t *out_count
|
||||
) {
|
||||
if (!raw || count == 0) {
|
||||
*out_count = 0;
|
||||
return nullptr;
|
||||
@@ -35,22 +38,29 @@ static window_state_t *derive_window_states(const atoms_t *atoms,
|
||||
return buf;
|
||||
}
|
||||
|
||||
static bool derive_skip_taskbar(const atoms_t *atoms, const xcb_atom_t *raw,
|
||||
uint32_t count) {
|
||||
static bool derive_skip_taskbar(
|
||||
const atoms_t *atoms,
|
||||
const xcb_atom_t *raw,
|
||||
uint32_t count
|
||||
) {
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
if (raw[i] == atoms->_NET_WM_STATE_SKIP_TASKBAR) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static window_geometry_mode_t geometry_mode_from_hints(
|
||||
const xcb_icccm_wm_hints_t *hints) {
|
||||
const xcb_icccm_wm_hints_t *hints
|
||||
) {
|
||||
if (hints->initial_state == XCB_ICCCM_WM_STATE_ICONIC)
|
||||
return ZDWM_GEOMETRY_MINIMIZED;
|
||||
return ZDWM_GEOMETRY_NORMAL;
|
||||
}
|
||||
|
||||
static window_geometry_mode_t geometry_mode_from_states(
|
||||
const atoms_t *atoms, const xcb_atom_t *state_atoms, uint32_t state_count) {
|
||||
const atoms_t *atoms,
|
||||
const xcb_atom_t *state_atoms,
|
||||
uint32_t state_count
|
||||
) {
|
||||
for (uint32_t i = 0; i < state_count; i++) {
|
||||
if (state_atoms[i] == atoms->_NET_WM_STATE_FULLSCREEN)
|
||||
return ZDWM_GEOMETRY_FULLSCREEN;
|
||||
@@ -61,8 +71,11 @@ static window_geometry_mode_t geometry_mode_from_states(
|
||||
return ZDWM_GEOMETRY_NORMAL;
|
||||
}
|
||||
|
||||
static bool handle_map_request(backend_t *backend, event_t *event,
|
||||
const xcb_map_request_event_t *xcb_event) {
|
||||
static bool handle_map_request(
|
||||
backend_t *backend,
|
||||
event_t *event,
|
||||
const xcb_map_request_event_t *xcb_event
|
||||
) {
|
||||
xcb_window_t window = xcb_event->window;
|
||||
|
||||
event_reset(event);
|
||||
@@ -91,8 +104,13 @@ static bool handle_map_request(backend_t *backend, event_t *event,
|
||||
const atoms_t *atoms = &backend->atoms;
|
||||
xcb_atom_t *state_atoms = nullptr;
|
||||
uint32_t state_count = 0;
|
||||
if (!window_get_atom_array(backend, window, atoms->_NET_WM_STATE,
|
||||
&state_atoms, &state_count)) {
|
||||
if (!window_get_atom_array(
|
||||
backend,
|
||||
window,
|
||||
atoms->_NET_WM_STATE,
|
||||
&state_atoms,
|
||||
&state_count
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -103,8 +121,12 @@ static bool handle_map_request(backend_t *backend, event_t *event,
|
||||
|
||||
if (state_atoms) {
|
||||
ev->skip_taskbar = derive_skip_taskbar(atoms, state_atoms, state_count);
|
||||
ev->props.states = derive_window_states(atoms, state_atoms, state_count,
|
||||
&ev->props.state_count);
|
||||
ev->props.states = derive_window_states(
|
||||
atoms,
|
||||
state_atoms,
|
||||
state_count,
|
||||
&ev->props.state_count
|
||||
);
|
||||
}
|
||||
|
||||
p_delete(&state_atoms);
|
||||
@@ -117,22 +139,32 @@ static bool handle_map_request(backend_t *backend, event_t *event,
|
||||
|
||||
ev->metadata.role = window_get_role(backend, window);
|
||||
ev->metadata.title = window_get_title(backend, window);
|
||||
window_get_class(backend, window, &ev->metadata.class_name,
|
||||
&ev->metadata.instance_name);
|
||||
window_get_class(
|
||||
backend,
|
||||
window,
|
||||
&ev->metadata.class_name,
|
||||
&ev->metadata.instance_name
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool handle_unmap_notify(backend_t *backend, event_t *event,
|
||||
const xcb_unmap_notify_event_t *xcb_event) {
|
||||
static bool handle_unmap_notify(
|
||||
backend_t *backend,
|
||||
event_t *event,
|
||||
const xcb_unmap_notify_event_t *xcb_event
|
||||
) {
|
||||
event_reset(event);
|
||||
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
||||
/* TODO: */
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool handle_destroy_notify(backend_t *backend, event_t *event,
|
||||
const xcb_destroy_notify_event_t *xcb_event) {
|
||||
static bool handle_destroy_notify(
|
||||
backend_t *backend,
|
||||
event_t *event,
|
||||
const xcb_destroy_notify_event_t *xcb_event
|
||||
) {
|
||||
event_reset(event);
|
||||
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
||||
/* TODO: */
|
||||
@@ -140,8 +172,10 @@ static bool handle_destroy_notify(backend_t *backend, event_t *event,
|
||||
}
|
||||
|
||||
static bool handle_configure_request(
|
||||
backend_t *backend, event_t *event,
|
||||
const xcb_configure_request_event_t *xcb_event) {
|
||||
backend_t *backend,
|
||||
event_t *event,
|
||||
const xcb_configure_request_event_t *xcb_event
|
||||
) {
|
||||
event_reset(event);
|
||||
event->type = ZDWM_EVENT_CONFIGURE_REQUEST;
|
||||
/* TODO: */
|
||||
|
||||
@@ -3,38 +3,43 @@
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
#include "core/backend.h" /* IWYU pragma: keep */
|
||||
#define ATOM_LIST(X) \
|
||||
X(COMPOUND_TEXT) \
|
||||
X(UTF8_STRING) \
|
||||
\
|
||||
X(WM_WINDOW_ROLE) \
|
||||
X(WM_NAME) \
|
||||
X(_NET_WM_NAME) \
|
||||
\
|
||||
X(_NET_WM_STATE) \
|
||||
X(_NET_WM_STATE_FULLSCREEN) \
|
||||
X(_NET_WM_STATE_ABOVE) \
|
||||
X(_NET_WM_STATE_STICKY) \
|
||||
X(_NET_WM_STATE_MODAL) \
|
||||
X(_NET_WM_STATE_SKIP_TASKBAR) \
|
||||
X(_NET_WM_STATE_MAXIMIZED_VERT) \
|
||||
X(_NET_WM_STATE_MAXIMIZED_HORZ) \
|
||||
\
|
||||
X(_NET_WM_WINDOW_TYPE) \
|
||||
X(_NET_WM_WINDOW_TYPE_NORMAL) \
|
||||
X(_NET_WM_WINDOW_TYPE_DESKTOP) \
|
||||
X(_NET_WM_WINDOW_TYPE_DOCK) \
|
||||
X(_NET_WM_WINDOW_TYPE_TOOLBAR) \
|
||||
X(_NET_WM_WINDOW_TYPE_DIALOG) \
|
||||
X(_NET_WM_WINDOW_TYPE_UTILITY) \
|
||||
X(_NET_WM_WINDOW_TYPE_SPLASH) \
|
||||
X(_NET_WM_WINDOW_TYPE_MENU) \
|
||||
X(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU) \
|
||||
X(_NET_WM_WINDOW_TYPE_POPUP_MENU) \
|
||||
X(_NET_WM_WINDOW_TYPE_TOOLTIP) \
|
||||
X(_NET_WM_WINDOW_TYPE_COMBO) \
|
||||
X(_NET_WM_WINDOW_TYPE_DND) \
|
||||
X(_NET_WM_WINDOW_TYPE_NOTIFICATION)
|
||||
|
||||
typedef struct atoms_t {
|
||||
xcb_atom_t COMPOUND_TEXT;
|
||||
xcb_atom_t UTF8_STRING;
|
||||
xcb_atom_t WM_WINDOW_ROLE;
|
||||
xcb_atom_t WM_NAME;
|
||||
xcb_atom_t _NET_WM_NAME;
|
||||
xcb_atom_t _NET_WM_STATE;
|
||||
xcb_atom_t _NET_WM_STATE_FULLSCREEN;
|
||||
xcb_atom_t _NET_WM_STATE_ABOVE;
|
||||
xcb_atom_t _NET_WM_STATE_STICKY;
|
||||
xcb_atom_t _NET_WM_STATE_MODAL;
|
||||
xcb_atom_t _NET_WM_STATE_SKIP_TASKBAR;
|
||||
xcb_atom_t _NET_WM_STATE_MAXIMIZED_VERT;
|
||||
xcb_atom_t _NET_WM_STATE_MAXIMIZED_HORZ;
|
||||
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE;
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE_NORMAL;
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE_DESKTOP;
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE_DOCK;
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE_TOOLBAR;
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE_DIALOG;
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE_UTILITY;
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE_SPLASH;
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE_MENU;
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE_DROPDOWN_MENU;
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE_POPUP_MENU;
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE_TOOLTIP;
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE_COMBO;
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE_DND;
|
||||
xcb_atom_t _NET_WM_WINDOW_TYPE_NOTIFICATION;
|
||||
#define DECLARATION_ATOM(name) xcb_atom_t name;
|
||||
ATOM_LIST(DECLARATION_ATOM);
|
||||
#undef DECLARATION_ATOM
|
||||
} atoms_t;
|
||||
|
||||
struct backend_t {
|
||||
|
||||
@@ -7,12 +7,23 @@
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
#include "base/memory.h"
|
||||
#include "core/backend.h"
|
||||
#include "internal.h"
|
||||
|
||||
static char *window_get_text_property(backend_t *backend, xcb_window_t window,
|
||||
xcb_atom_t property) {
|
||||
static char *window_get_text_property(
|
||||
backend_t *backend,
|
||||
xcb_window_t window,
|
||||
xcb_atom_t property
|
||||
) {
|
||||
xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(
|
||||
backend->conn, false, window, property, XCB_ATOM_ANY, 0, UINT32_MAX);
|
||||
backend->conn,
|
||||
false,
|
||||
window,
|
||||
property,
|
||||
XCB_ATOM_ANY,
|
||||
0,
|
||||
UINT32_MAX
|
||||
);
|
||||
xcb_get_property_reply_t *reply =
|
||||
xcb_get_property_reply(backend->conn, cookie, nullptr);
|
||||
if (!reply) return nullptr;
|
||||
@@ -47,8 +58,12 @@ char *window_get_title(backend_t *backend, xcb_window_t window) {
|
||||
return name;
|
||||
}
|
||||
|
||||
void window_get_class(backend_t *backend, xcb_window_t window, char **class_out,
|
||||
char **instance_out) {
|
||||
void window_get_class(
|
||||
backend_t *backend,
|
||||
xcb_window_t window,
|
||||
char **class_out,
|
||||
char **instance_out
|
||||
) {
|
||||
xcb_icccm_get_wm_class_reply_t prop;
|
||||
xcb_get_property_cookie_t cookie =
|
||||
xcb_icccm_get_wm_class_unchecked(backend->conn, window);
|
||||
@@ -74,15 +89,15 @@ xcb_window_t window_get_transient_for(backend_t *backend, xcb_window_t window) {
|
||||
return XCB_WINDOW_NONE;
|
||||
}
|
||||
|
||||
xcb_get_window_attributes_reply_t *window_get_attributes(backend_t *backend,
|
||||
xcb_window_t window) {
|
||||
xcb_get_window_attributes_reply_t *
|
||||
window_get_attributes(backend_t *backend, xcb_window_t window) {
|
||||
xcb_get_window_attributes_cookie_t cookie =
|
||||
xcb_get_window_attributes(backend->conn, window);
|
||||
return xcb_get_window_attributes_reply(backend->conn, cookie, nullptr);
|
||||
}
|
||||
|
||||
static window_type_t atom_to_window_type(const atoms_t *atoms,
|
||||
xcb_atom_t atom) {
|
||||
static window_type_t
|
||||
atom_to_window_type(const atoms_t *atoms, xcb_atom_t atom) {
|
||||
if (atom == atoms->_NET_WM_WINDOW_TYPE_DESKTOP)
|
||||
return ZDWM_WINDOW_TYPE_DESKTOP;
|
||||
if (atom == atoms->_NET_WM_WINDOW_TYPE_DOCK) return ZDWM_WINDOW_TYPE_DOCK;
|
||||
@@ -106,13 +121,21 @@ static window_type_t atom_to_window_type(const atoms_t *atoms,
|
||||
return ZDWM_WINDOW_TYPE_NORMAL;
|
||||
}
|
||||
|
||||
bool window_get_types(backend_t *backend, xcb_window_t window,
|
||||
window_type_t **types, size_t *count) {
|
||||
bool window_get_types(
|
||||
backend_t *backend,
|
||||
xcb_window_t window,
|
||||
window_type_t **types,
|
||||
size_t *count
|
||||
) {
|
||||
uint32_t atom_count = 0;
|
||||
xcb_atom_t *atoms = nullptr;
|
||||
if (!window_get_atom_array(backend, window,
|
||||
backend->atoms._NET_WM_WINDOW_TYPE, &atoms,
|
||||
&atom_count)) {
|
||||
if (!window_get_atom_array(
|
||||
backend,
|
||||
window,
|
||||
backend->atoms._NET_WM_WINDOW_TYPE,
|
||||
&atoms,
|
||||
&atom_count
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
if (!atoms) {
|
||||
@@ -165,11 +188,22 @@ bool window_get_geometry(backend_t *backend, xcb_window_t window, rect_t *out) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool window_get_atom_array(backend_t *backend, xcb_window_t window,
|
||||
xcb_atom_t property, xcb_atom_t **out_atoms,
|
||||
uint32_t *out_len) {
|
||||
bool window_get_atom_array(
|
||||
backend_t *backend,
|
||||
xcb_window_t window,
|
||||
xcb_atom_t property,
|
||||
xcb_atom_t **out_atoms,
|
||||
uint32_t *out_len
|
||||
) {
|
||||
xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(
|
||||
backend->conn, false, window, property, XCB_ATOM_ATOM, 0, UINT32_MAX);
|
||||
backend->conn,
|
||||
false,
|
||||
window,
|
||||
property,
|
||||
XCB_ATOM_ATOM,
|
||||
0,
|
||||
UINT32_MAX
|
||||
);
|
||||
xcb_get_property_reply_t *reply =
|
||||
xcb_get_property_reply(backend->conn, cookie, nullptr);
|
||||
if (!reply) return false;
|
||||
@@ -187,8 +221,11 @@ bool window_get_atom_array(backend_t *backend, xcb_window_t window,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool window_get_wm_hints(backend_t *backend, xcb_window_t window,
|
||||
xcb_icccm_wm_hints_t *out) {
|
||||
bool window_get_wm_hints(
|
||||
backend_t *backend,
|
||||
xcb_window_t window,
|
||||
xcb_icccm_wm_hints_t *out
|
||||
) {
|
||||
xcb_get_property_cookie_t cookie =
|
||||
xcb_icccm_get_wm_hints_unchecked(backend->conn, window);
|
||||
if (!xcb_icccm_get_wm_hints_reply(backend->conn, cookie, out, nullptr)) {
|
||||
|
||||
@@ -35,18 +35,33 @@ char *window_get_title(backend_t *backend, xcb_window_t window);
|
||||
* @param instance_out instance 信息返回指针,调用者持有其内存并负责调用 free
|
||||
* 释放
|
||||
*/
|
||||
void window_get_class(backend_t *backend, xcb_window_t window, char **class_out,
|
||||
char **instance_out);
|
||||
void window_get_class(
|
||||
backend_t *backend,
|
||||
xcb_window_t window,
|
||||
char **class_out,
|
||||
char **instance_out
|
||||
);
|
||||
xcb_window_t window_get_transient_for(backend_t *backend, xcb_window_t window);
|
||||
xcb_get_window_attributes_reply_t *window_get_attributes(backend_t *backend,
|
||||
xcb_window_t window);
|
||||
bool window_get_types(backend_t *backend, xcb_window_t window,
|
||||
window_type_t **types, size_t *count);
|
||||
xcb_get_window_attributes_reply_t *
|
||||
window_get_attributes(backend_t *backend, xcb_window_t window);
|
||||
bool window_get_types(
|
||||
backend_t *backend,
|
||||
xcb_window_t window,
|
||||
window_type_t **types,
|
||||
size_t *count
|
||||
);
|
||||
bool window_get_fixed_size(backend_t *backend, xcb_window_t window, bool *out);
|
||||
bool window_get_geometry(backend_t *backend, xcb_window_t window, rect_t *out);
|
||||
bool window_get_atom_array(backend_t *backend, xcb_window_t window,
|
||||
xcb_atom_t property, xcb_atom_t **out_atoms,
|
||||
uint32_t *out_len);
|
||||
bool window_get_wm_hints(backend_t *backend, xcb_window_t window,
|
||||
xcb_icccm_wm_hints_t *out);
|
||||
bool window_get_atom_array(
|
||||
backend_t *backend,
|
||||
xcb_window_t window,
|
||||
xcb_atom_t property,
|
||||
xcb_atom_t **out_atoms,
|
||||
uint32_t *out_len
|
||||
);
|
||||
bool window_get_wm_hints(
|
||||
backend_t *backend,
|
||||
xcb_window_t window,
|
||||
xcb_icccm_wm_hints_t *out
|
||||
);
|
||||
window_state_t atom_to_window_state(const atoms_t *atoms, xcb_atom_t atom);
|
||||
|
||||
1
src/base/.clang-format
Symbolic link
1
src/base/.clang-format
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.clang-format
|
||||
@@ -24,8 +24,12 @@ static inline size_t next_capacity(size_t capacity) {
|
||||
* @param capacity 当前容量地址
|
||||
* @param need 目标容量
|
||||
*/
|
||||
static inline void array_reserve_impl(void **items, size_t item_size,
|
||||
size_t *capacity, size_t need) {
|
||||
static inline void array_reserve_impl(
|
||||
void **items,
|
||||
size_t item_size,
|
||||
size_t *capacity,
|
||||
size_t need
|
||||
) {
|
||||
if (*capacity >= need) return;
|
||||
|
||||
size_t new_capacity = next_capacity(*capacity);
|
||||
@@ -51,8 +55,12 @@ static inline void array_reserve_impl(void **items, size_t item_size,
|
||||
*
|
||||
* @return void* 新槽位地址
|
||||
*/
|
||||
static inline void *array_push_impl(void **items, size_t item_size,
|
||||
size_t *count, size_t *capacity) {
|
||||
static inline void *array_push_impl(
|
||||
void **items,
|
||||
size_t item_size,
|
||||
size_t *count,
|
||||
size_t *capacity
|
||||
) {
|
||||
array_reserve_impl(items, item_size, capacity, *count + 1);
|
||||
|
||||
void *slot = (char *)*items + *count * item_size;
|
||||
@@ -71,8 +79,8 @@ static inline void *array_push_impl(void **items, size_t item_size,
|
||||
* @return true 删除成功
|
||||
* @return false 下标越界
|
||||
*/
|
||||
static inline bool array_erase_impl(void *items, size_t item_size,
|
||||
size_t *count, size_t index) {
|
||||
static inline bool
|
||||
array_erase_impl(void *items, size_t item_size, size_t *count, size_t index) {
|
||||
if (index >= *count) return false;
|
||||
|
||||
size_t tail_count = *count - index - 1;
|
||||
|
||||
@@ -5,14 +5,23 @@
|
||||
|
||||
#define fatal(format, ...) \
|
||||
_fatal(__LINE__, __FUNCTION__, __FILE__, format, ##__VA_ARGS__)
|
||||
void _fatal(int line, const char *function, const char *file,
|
||||
const char *format, ...) __attribute__((noreturn))
|
||||
__attribute__((format(printf, 4, 5)));
|
||||
void _fatal(
|
||||
int line,
|
||||
const char *function,
|
||||
const char *file,
|
||||
const char *format,
|
||||
...
|
||||
) __attribute__((noreturn)) __attribute__((format(printf, 4, 5)));
|
||||
|
||||
#define warn(format, ...) \
|
||||
_warn(__LINE__, __FUNCTION__, __FILE__, format, ##__VA_ARGS__)
|
||||
void _warn(int line, const char *function, const char *file, const char *format,
|
||||
...) __attribute__((format(printf, 4, 5)));
|
||||
void _warn(
|
||||
int line,
|
||||
const char *function,
|
||||
const char *file,
|
||||
const char *format,
|
||||
...
|
||||
) __attribute__((format(printf, 4, 5)));
|
||||
|
||||
const char *current_time_str(void);
|
||||
|
||||
|
||||
@@ -64,8 +64,7 @@ static inline void *xmemcopy(const void *src, size_t n) {
|
||||
}
|
||||
|
||||
static inline void xrealloc(void **ptr, ssize_t newsize) {
|
||||
if (newsize <= 0)
|
||||
p_delete(ptr);
|
||||
if (newsize <= 0) p_delete(ptr);
|
||||
else {
|
||||
*ptr = realloc(*ptr, newsize);
|
||||
if (!*ptr) abort();
|
||||
|
||||
1
src/config/.clang-format
Symbolic link
1
src/config/.clang-format
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.clang-format
|
||||
@@ -2,16 +2,28 @@
|
||||
|
||||
#include "base/macros.h"
|
||||
|
||||
bool config_defaults_build(const zdwm_api_t *api,
|
||||
bool config_defaults_build(
|
||||
const zdwm_api_t *api,
|
||||
zdwm_config_builder_t *builder,
|
||||
const zdwm_output_info_t *outputs,
|
||||
size_t output_count) {
|
||||
size_t output_count
|
||||
) {
|
||||
if (!api || !builder || !outputs || output_count == 0) return false;
|
||||
|
||||
zdwm_layout_id_t tile_id = api->register_layout(
|
||||
builder, "tile", "[]=", "builtin tile", api->builtin_layouts.tile);
|
||||
builder,
|
||||
"tile",
|
||||
"[]=",
|
||||
"builtin tile",
|
||||
api->builtin_layouts.tile
|
||||
);
|
||||
zdwm_layout_id_t monocle_id = api->register_layout(
|
||||
builder, "monocle", "[M]", "builtin monocle", api->builtin_layouts.monocle);
|
||||
builder,
|
||||
"monocle",
|
||||
"[M]",
|
||||
"builtin monocle",
|
||||
api->builtin_layouts.monocle
|
||||
);
|
||||
zdwm_layout_id_t floating_id =
|
||||
api->register_layout(builder, "floating", "><>", "floating", nullptr);
|
||||
if (tile_id == ZDWM_LAYOUT_ID_INVALID ||
|
||||
@@ -22,9 +34,14 @@ bool config_defaults_build(const zdwm_api_t *api,
|
||||
|
||||
zdwm_layout_id_t layout_ids[] = {tile_id, monocle_id, floating_id};
|
||||
for (size_t i = 0; i < output_count; i++) {
|
||||
if (api->define_workspace(builder, i, "main", layout_ids,
|
||||
if (api->define_workspace(
|
||||
builder,
|
||||
i,
|
||||
"main",
|
||||
layout_ids,
|
||||
countof(layout_ids),
|
||||
tile_id) == ZDWM_WORKSPACE_ID_INVALID) {
|
||||
tile_id
|
||||
) == ZDWM_WORKSPACE_ID_INVALID) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,11 @@ static char *config_loader_join_path(const char *base, const char *suffix) {
|
||||
return path;
|
||||
}
|
||||
|
||||
static bool config_loader_resolve_path(char **out_path, bool *out_is_explicit,
|
||||
const char *override_path) {
|
||||
static bool config_loader_resolve_path(
|
||||
char **out_path,
|
||||
bool *out_is_explicit,
|
||||
const char *override_path
|
||||
) {
|
||||
const char *path = override_path;
|
||||
if (path && *path) {
|
||||
*out_path = p_strdup(path);
|
||||
|
||||
@@ -48,17 +48,25 @@ static void config_builder_cleanup(zdwm_config_builder_t *builder) {
|
||||
}
|
||||
|
||||
static layout_id_t runtime_config_register_layout(
|
||||
zdwm_config_builder_t *builder, const char *name, const char *symbol,
|
||||
const char *description, layout_fn fn) {
|
||||
zdwm_config_builder_t *builder,
|
||||
const char *name,
|
||||
const char *symbol,
|
||||
const char *description,
|
||||
layout_fn fn
|
||||
) {
|
||||
if (!builder || !name || !symbol) return ZDWM_LAYOUT_ID_INVALID;
|
||||
|
||||
return layout_register(&builder->layouts, name, symbol, description, fn);
|
||||
}
|
||||
|
||||
static workspace_id_t runtime_config_define_workspace(
|
||||
zdwm_config_builder_t *builder, size_t output_index, const char *name,
|
||||
const layout_id_t *layout_ids, size_t layout_count,
|
||||
layout_id_t initial_layout_id) {
|
||||
zdwm_config_builder_t *builder,
|
||||
size_t output_index,
|
||||
const char *name,
|
||||
const layout_id_t *layout_ids,
|
||||
size_t layout_count,
|
||||
layout_id_t initial_layout_id
|
||||
) {
|
||||
if (!builder) return ZDWM_WORKSPACE_ID_INVALID;
|
||||
if (output_index >= builder->output_count) return ZDWM_WORKSPACE_ID_INVALID;
|
||||
if (builder->workspace_count >= (size_t)ZDWM_WORKSPACE_ID_INVALID) {
|
||||
@@ -84,7 +92,10 @@ static workspace_id_t runtime_config_define_workspace(
|
||||
|
||||
workspace_id_t workspace_id = (workspace_id_t)builder->workspace_count;
|
||||
workspace_desc_t *slot = array_push(
|
||||
builder->workspaces, builder->workspace_count, builder->workspace_capacity);
|
||||
builder->workspaces,
|
||||
builder->workspace_count,
|
||||
builder->workspace_capacity
|
||||
);
|
||||
slot->output_index = output_index;
|
||||
slot->name = p_strdup(name);
|
||||
slot->layout_ids = p_copy(layout_ids, layout_count);
|
||||
@@ -100,8 +111,8 @@ static bool rule_match_valid(const rule_match_t *match) {
|
||||
match->instance_name;
|
||||
}
|
||||
|
||||
static bool rule_action_valid(const rule_action_t *action,
|
||||
size_t workspace_count) {
|
||||
static bool
|
||||
rule_action_valid(const rule_action_t *action, size_t workspace_count) {
|
||||
if (!action) return false;
|
||||
|
||||
if (action->workspace == ZDWM_WORKSPACE_ID_INVALID) {
|
||||
@@ -112,9 +123,11 @@ static bool rule_action_valid(const rule_action_t *action,
|
||||
return action->workspace < workspace_count;
|
||||
}
|
||||
|
||||
static bool runtime_config_add_rule(zdwm_config_builder_t *builder,
|
||||
static bool runtime_config_add_rule(
|
||||
zdwm_config_builder_t *builder,
|
||||
const zdwm_rule_match_t *match,
|
||||
const zdwm_rule_action_t *action) {
|
||||
const zdwm_rule_action_t *action
|
||||
) {
|
||||
if (!builder) return false;
|
||||
if (!rule_match_valid(match)) return false;
|
||||
if (!rule_action_valid(action, builder->workspace_count)) return false;
|
||||
@@ -131,8 +144,10 @@ static bool runtime_config_add_rule(zdwm_config_builder_t *builder,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool config_builder_finish(zdwm_config_builder_t *builder,
|
||||
runtime_init_desc_t *out) {
|
||||
static bool config_builder_finish(
|
||||
zdwm_config_builder_t *builder,
|
||||
runtime_init_desc_t *out
|
||||
) {
|
||||
if (!builder || !out) return false;
|
||||
|
||||
if (!builder->layouts.slot_count || !builder->workspace_count) return false;
|
||||
@@ -148,10 +163,12 @@ static bool config_builder_finish(zdwm_config_builder_t *builder,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool runtime_config_build(zdwm_config_setup_fn *setup,
|
||||
static bool runtime_config_build(
|
||||
zdwm_config_setup_fn *setup,
|
||||
const output_info_t *outputs,
|
||||
size_t output_count,
|
||||
runtime_init_desc_t *out) {
|
||||
runtime_init_desc_t *out
|
||||
) {
|
||||
if (!setup || !out) return false;
|
||||
zdwm_config_builder_t builder = {0};
|
||||
builder.output_count = output_count;
|
||||
|
||||
1
src/core/.clang-format
Symbolic link
1
src/core/.clang-format
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.clang-format
|
||||
@@ -32,5 +32,8 @@ void backend_detect_destroy(backend_detect_t *detect);
|
||||
* 无需 cleanup 的状态,调用方可以直接退出循环。
|
||||
*/
|
||||
bool backend_next_event(backend_t *backend, event_t *event);
|
||||
bool backend_apply_effect(backend_t *backend, const effect_t *effects,
|
||||
size_t effect_count);
|
||||
bool backend_apply_effect(
|
||||
backend_t *backend,
|
||||
const effect_t *effects,
|
||||
size_t effect_count
|
||||
);
|
||||
|
||||
@@ -53,15 +53,19 @@ size_t layout_registry_count(const layout_registry_t *registry) {
|
||||
return registry->slot_count;
|
||||
}
|
||||
|
||||
const layout_slot_t *layout_registry_at(const layout_registry_t *registry,
|
||||
size_t index) {
|
||||
const layout_slot_t *
|
||||
layout_registry_at(const layout_registry_t *registry, size_t index) {
|
||||
if (index >= registry->slot_count) return nullptr;
|
||||
return ®istry->slots[index];
|
||||
}
|
||||
|
||||
layout_id_t layout_register(layout_registry_t *registry, const char *name,
|
||||
const char *symbol, const char *description,
|
||||
layout_fn fn) {
|
||||
layout_id_t layout_register(
|
||||
layout_registry_t *registry,
|
||||
const char *name,
|
||||
const char *symbol,
|
||||
const char *description,
|
||||
layout_fn fn
|
||||
) {
|
||||
if (!name || !symbol) return ZDWM_LAYOUT_ID_INVALID;
|
||||
|
||||
layout_id_t id = (layout_id_t)registry->slot_count;
|
||||
@@ -82,8 +86,8 @@ layout_fn layout_get(const layout_registry_t *registry, layout_id_t id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const layout_slot_t *layout_slot_get(const layout_registry_t *registry,
|
||||
layout_id_t id) {
|
||||
const layout_slot_t *
|
||||
layout_slot_get(const layout_registry_t *registry, layout_id_t id) {
|
||||
if (id >= registry->slot_count) return nullptr;
|
||||
return ®istry->slots[id];
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@ void layout_result_push(layout_result_t *result, layout_item_t item);
|
||||
void layout_registry_cleanup(layout_registry_t *registry);
|
||||
bool layout_registry_move(layout_registry_t *src, layout_registry_t *dest);
|
||||
size_t layout_registry_count(const layout_registry_t *registry);
|
||||
const layout_slot_t *layout_registry_at(const layout_registry_t *registry,
|
||||
size_t index);
|
||||
const layout_slot_t *
|
||||
layout_registry_at(const layout_registry_t *registry, size_t index);
|
||||
|
||||
/*
|
||||
* 注册一个布局并返回其稳定 ID。
|
||||
@@ -75,9 +75,13 @@ const layout_slot_t *layout_registry_at(const layout_registry_t *registry,
|
||||
*
|
||||
* 注册成功后,布局 ID 与其在 registry 中的槽位索引保持一致。
|
||||
*/
|
||||
layout_id_t layout_register(layout_registry_t *registry, const char *name,
|
||||
const char *symbol, const char *description,
|
||||
layout_fn fn);
|
||||
layout_id_t layout_register(
|
||||
layout_registry_t *registry,
|
||||
const char *name,
|
||||
const char *symbol,
|
||||
const char *description,
|
||||
layout_fn fn
|
||||
);
|
||||
/*
|
||||
* 获取可执行的布局函数。
|
||||
*
|
||||
@@ -87,5 +91,5 @@ layout_id_t layout_register(layout_registry_t *registry, const char *name,
|
||||
* - slot 存在,但 fn == NULL(表示 floating 布局)
|
||||
*/
|
||||
layout_fn layout_get(const layout_registry_t *registry, layout_id_t id);
|
||||
const layout_slot_t *layout_slot_get(const layout_registry_t *registry,
|
||||
layout_id_t id);
|
||||
const layout_slot_t *
|
||||
layout_slot_get(const layout_registry_t *registry, layout_id_t id);
|
||||
|
||||
@@ -16,9 +16,12 @@ static workspace_id_t derive_window_workspace(const state_t *state) {
|
||||
return state->outputs[state->current_output_index].current_workspace_id;
|
||||
}
|
||||
|
||||
static bool route_map_request(const state_t *state, const rules_t *rules,
|
||||
static bool route_map_request(
|
||||
const state_t *state,
|
||||
const rules_t *rules,
|
||||
const window_map_request_event_t *e,
|
||||
command_buffer_t *out) {
|
||||
command_buffer_t *out
|
||||
) {
|
||||
if (state_window_get(state, e->window)) return false;
|
||||
|
||||
layer_type_t layer_type = layer_classify(&e->props);
|
||||
@@ -29,11 +32,9 @@ static bool route_map_request(const state_t *state, const rules_t *rules,
|
||||
|
||||
command_t cmd = {
|
||||
.type = ZDWM_COMMAND_MANAGE_WINDOW,
|
||||
.as.manage_window =
|
||||
{
|
||||
.as.manage_window = {
|
||||
.workspace = derive_window_workspace(state),
|
||||
.info =
|
||||
{
|
||||
.info = {
|
||||
.id = e->window,
|
||||
.transient_for = e->transient_for,
|
||||
.frame_rect = e->rect,
|
||||
@@ -79,8 +80,7 @@ static bool route_map_request(const state_t *state, const rules_t *rules,
|
||||
if (workspace) {
|
||||
command_t switch_workspace_cmd = {
|
||||
.type = ZDWM_COMMAND_SWITCH_WORKSPACE,
|
||||
.as.switch_workspace =
|
||||
{
|
||||
.as.switch_workspace = {
|
||||
.output = workspace->output_id,
|
||||
.workspace = workspace_id,
|
||||
},
|
||||
@@ -96,16 +96,22 @@ static bool route_map_request(const state_t *state, const rules_t *rules,
|
||||
bool policy_route_event(const policy_context_t *ctx, command_buffer_t *out) {
|
||||
switch (ctx->event->type) {
|
||||
case ZDWM_EVENT_WINDOW_MAP_REQUEST:
|
||||
return route_map_request(ctx->state, ctx->rules,
|
||||
&ctx->event->as.window_map_request, out);
|
||||
return route_map_request(
|
||||
ctx->state,
|
||||
ctx->rules,
|
||||
&ctx->event->as.window_map_request,
|
||||
out
|
||||
);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool policy_apply_command(const policy_context_t *ctx,
|
||||
bool policy_apply_command(
|
||||
const policy_context_t *ctx,
|
||||
const command_buffer_t *command_buffer,
|
||||
plan_t *plan) {
|
||||
plan_t *plan
|
||||
) {
|
||||
/* TODO: */
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -13,5 +13,8 @@ typedef struct policy_context_t {
|
||||
} policy_context_t;
|
||||
|
||||
bool policy_route_event(const policy_context_t *ctx, command_buffer_t *out);
|
||||
bool policy_apply_command(const policy_context_t *ctx,
|
||||
const command_buffer_t *command_buffer, plan_t *plan);
|
||||
bool policy_apply_command(
|
||||
const policy_context_t *ctx,
|
||||
const command_buffer_t *command_buffer,
|
||||
plan_t *plan
|
||||
);
|
||||
|
||||
@@ -44,8 +44,8 @@ static inline bool str_match(const char *pattern, const char *value) {
|
||||
return !pattern || (value && strcmp(pattern, value) == 0);
|
||||
}
|
||||
|
||||
static bool rule_match_window(const rule_match_t *match,
|
||||
const window_metadata_t *meta) {
|
||||
static bool
|
||||
rule_match_window(const rule_match_t *match, const window_metadata_t *meta) {
|
||||
return str_match(match->app_id, meta->app_id) &&
|
||||
str_match(match->role, meta->role) &&
|
||||
str_match(match->class_name, meta->class_name) &&
|
||||
@@ -64,8 +64,11 @@ static void rule_action_merge(const rule_action_t *src, rule_action_t *dest) {
|
||||
dest->floating |= src->floating;
|
||||
}
|
||||
|
||||
bool rules_resolve(const rules_t *rules, const window_metadata_t *metadata,
|
||||
rule_action_t *action_out) {
|
||||
bool rules_resolve(
|
||||
const rules_t *rules,
|
||||
const window_metadata_t *metadata,
|
||||
rule_action_t *action_out
|
||||
) {
|
||||
if (!action_out) return false;
|
||||
|
||||
bool matched = false;
|
||||
|
||||
@@ -19,5 +19,8 @@ typedef struct rules_t {
|
||||
bool rules_move(rules_t *src, rules_t *dest);
|
||||
void rules_cleanup(rules_t *rules);
|
||||
|
||||
bool rules_resolve(const rules_t *rules, const window_metadata_t *metadata,
|
||||
rule_action_t *action_out);
|
||||
bool rules_resolve(
|
||||
const rules_t *rules,
|
||||
const window_metadata_t *metadata,
|
||||
rule_action_t *action_out
|
||||
);
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
#include "core/wm_desc.h"
|
||||
|
||||
static bool runtime_workspace_desc_has_valid_layouts(
|
||||
const layout_registry_t *layouts, const workspace_desc_t *workspace) {
|
||||
const layout_registry_t *layouts,
|
||||
const workspace_desc_t *workspace
|
||||
) {
|
||||
if (!layouts || !workspace) return false;
|
||||
|
||||
for (size_t i = 0; i < workspace->layout_count; i++) {
|
||||
@@ -53,8 +55,13 @@ bool runtime_init(runtime_t *runtime, runtime_init_desc_t *desc) {
|
||||
desc->backend = nullptr;
|
||||
desc->config_module_handle = nullptr;
|
||||
|
||||
state_init(&runtime->state, desc->outputs, desc->output_count,
|
||||
desc->workspaces, desc->workspace_count);
|
||||
state_init(
|
||||
&runtime->state,
|
||||
desc->outputs,
|
||||
desc->output_count,
|
||||
desc->workspaces,
|
||||
desc->workspace_count
|
||||
);
|
||||
|
||||
workspace_desc_list_cleanup(&desc->workspaces, &desc->workspace_count);
|
||||
desc->outputs = nullptr;
|
||||
|
||||
169
src/core/state.c
169
src/core/state.c
@@ -13,9 +13,13 @@
|
||||
#include "core/types.h"
|
||||
#include "core/wm_desc.h"
|
||||
|
||||
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_init(
|
||||
state_t *state,
|
||||
const output_info_t *outputs,
|
||||
size_t output_count,
|
||||
const workspace_desc_t *workspaces,
|
||||
size_t workspace_count
|
||||
) {
|
||||
p_clear(state, 1);
|
||||
|
||||
state->outputs = p_new(output_t, output_count);
|
||||
@@ -102,8 +106,8 @@ void state_cleanup(state_t *state) {
|
||||
p_clear(state, 1);
|
||||
}
|
||||
|
||||
const workspace_t *state_workspace_get(const state_t *state,
|
||||
workspace_id_t id) {
|
||||
const workspace_t *
|
||||
state_workspace_get(const state_t *state, workspace_id_t id) {
|
||||
if (id < state->workspace_count) return &state->workspaces[id];
|
||||
return nullptr;
|
||||
}
|
||||
@@ -113,8 +117,10 @@ const workspace_t *state_workspace_at(const state_t *state, size_t index) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void state_workspace_adjust_focused_window(const state_t *state,
|
||||
workspace_id_t workspace_id) {
|
||||
static void state_workspace_adjust_focused_window(
|
||||
const state_t *state,
|
||||
workspace_id_t workspace_id
|
||||
) {
|
||||
workspace_t *workspace =
|
||||
(workspace_t *)state_workspace_get(state, workspace_id);
|
||||
if (!workspace) return;
|
||||
@@ -160,9 +166,11 @@ bool state_workspace_cycle_layout(state_t *state, workspace_id_t workspace_id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool state_workspace_set_layout_by_index(state_t *state,
|
||||
bool state_workspace_set_layout_by_index(
|
||||
state_t *state,
|
||||
workspace_id_t workspace_id,
|
||||
size_t index) {
|
||||
size_t index
|
||||
) {
|
||||
workspace_t *workspace =
|
||||
(workspace_t *)state_workspace_get(state, workspace_id);
|
||||
if (!workspace) return false;
|
||||
@@ -172,9 +180,11 @@ bool state_workspace_set_layout_by_index(state_t *state,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool state_workspace_set_layout_by_id(state_t *state,
|
||||
bool state_workspace_set_layout_by_id(
|
||||
state_t *state,
|
||||
workspace_id_t workspace_id,
|
||||
layout_id_t layout_id) {
|
||||
layout_id_t layout_id
|
||||
) {
|
||||
workspace_t *workspace =
|
||||
(workspace_t *)state_workspace_get(state, workspace_id);
|
||||
if (!workspace) return false;
|
||||
@@ -188,9 +198,11 @@ bool state_workspace_set_layout_by_id(state_t *state,
|
||||
return false;
|
||||
}
|
||||
|
||||
void state_workspace_set_focused_window(state_t *state,
|
||||
void state_workspace_set_focused_window(
|
||||
state_t *state,
|
||||
workspace_id_t workspace_id,
|
||||
window_id_t window_id) {
|
||||
window_id_t window_id
|
||||
) {
|
||||
workspace_t *workspace =
|
||||
(workspace_t *)state_workspace_get(state, workspace_id);
|
||||
if (!workspace) return;
|
||||
@@ -235,14 +247,20 @@ const output_t *state_output_at(const state_t *state, size_t index) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void state_output_set_workarea(state_t *state, output_id_t output_id,
|
||||
rect_t workarea) {
|
||||
void state_output_set_workarea(
|
||||
state_t *state,
|
||||
output_id_t output_id,
|
||||
rect_t workarea
|
||||
) {
|
||||
output_t *output = (output_t *)state_output_get(state, output_id);
|
||||
if (output) output->workarea = workarea;
|
||||
}
|
||||
|
||||
void state_output_set_current_workspace(state_t *state, output_id_t output_id,
|
||||
workspace_id_t workspace_id) {
|
||||
void state_output_set_current_workspace(
|
||||
state_t *state,
|
||||
output_id_t output_id,
|
||||
workspace_id_t workspace_id
|
||||
) {
|
||||
output_t *output = (output_t *)state_output_get(state, output_id);
|
||||
if (!output) return;
|
||||
const workspace_t *workspace = state_workspace_get(state, workspace_id);
|
||||
@@ -277,7 +295,9 @@ void state_cycle_current_output(state_t *state, int delta) {
|
||||
}
|
||||
|
||||
static inline void window_set_geometry_mode(
|
||||
window_t *window, window_geometry_mode_t geometry_mode) {
|
||||
window_t *window,
|
||||
window_geometry_mode_t geometry_mode
|
||||
) {
|
||||
window->geometry_mode = geometry_mode;
|
||||
}
|
||||
static inline void window_set_floating(window_t *window, bool floating) {
|
||||
@@ -317,13 +337,13 @@ static inline void window_set_class(window_t *window, const char *class_name) {
|
||||
p_delete(&window->class_name);
|
||||
window->class_name = p_strdup_nullable(class_name);
|
||||
}
|
||||
static inline void window_set_instance(window_t *window,
|
||||
const char *instance_name) {
|
||||
static inline void
|
||||
window_set_instance(window_t *window, const char *instance_name) {
|
||||
p_delete(&window->instance_name);
|
||||
window->instance_name = p_strdup_nullable(instance_name);
|
||||
}
|
||||
static inline void window_set_skip_taskbar(window_t *window,
|
||||
bool skip_taskbar) {
|
||||
static inline void
|
||||
window_set_skip_taskbar(window_t *window, bool skip_taskbar) {
|
||||
window->skip_taskbar = skip_taskbar;
|
||||
}
|
||||
|
||||
@@ -416,8 +436,11 @@ void state_window_remove(state_t *state, window_id_t id) {
|
||||
|
||||
size_t state_window_count(const state_t *state) { return state->window_count; }
|
||||
|
||||
void state_window_set_workspace(state_t *state, window_id_t window_id,
|
||||
workspace_id_t workspace_id) {
|
||||
void state_window_set_workspace(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
workspace_id_t workspace_id
|
||||
) {
|
||||
const workspace_t *workspace = state_workspace_get(state, workspace_id);
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (!workspace || !window || window->workspace_id == workspace_id) return;
|
||||
@@ -432,57 +455,84 @@ void state_window_set_workspace(state_t *state, window_id_t window_id,
|
||||
state_workspace_adjust_focused_window(state, 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_geometry_mode(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
window_geometry_mode_t geometry_mode
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (window) window_set_geometry_mode(window, geometry_mode);
|
||||
}
|
||||
|
||||
void state_window_set_floating(state_t *state, window_id_t window_id,
|
||||
bool floating) {
|
||||
void state_window_set_floating(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
bool floating
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (window) window_set_floating(window, floating);
|
||||
}
|
||||
|
||||
void state_window_set_sticky(state_t *state, window_id_t window_id,
|
||||
bool sticky) {
|
||||
void state_window_set_sticky(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
bool sticky
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (window) window_set_sticky(window, sticky);
|
||||
}
|
||||
|
||||
void state_window_set_urgent(state_t *state, window_id_t window_id,
|
||||
bool urgent) {
|
||||
void state_window_set_urgent(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
bool urgent
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (window) window_set_urgent(window, urgent);
|
||||
}
|
||||
|
||||
void state_window_set_fixed_size(state_t *state, window_id_t window_id,
|
||||
bool fixed_size) {
|
||||
void state_window_set_fixed_size(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
bool fixed_size
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (window) window_set_fixed_size(window, fixed_size);
|
||||
}
|
||||
|
||||
void state_window_set_skip_taskbar(state_t *state, window_id_t window_id,
|
||||
bool skip_taskbar) {
|
||||
void state_window_set_skip_taskbar(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
bool skip_taskbar
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (window) window_set_skip_taskbar(window, skip_taskbar);
|
||||
}
|
||||
|
||||
void state_window_set_float_rect(state_t *state, window_id_t window_id,
|
||||
rect_t float_rect) {
|
||||
void state_window_set_float_rect(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
rect_t float_rect
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (window) window_set_float_rect(window, float_rect);
|
||||
}
|
||||
|
||||
void state_window_set_frame_rect(state_t *state, window_id_t window_id,
|
||||
rect_t frame_rect) {
|
||||
void state_window_set_frame_rect(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
rect_t frame_rect
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (window) window_set_frame_rect(window, frame_rect);
|
||||
}
|
||||
|
||||
bool state_window_take_metadata(state_t *state, window_id_t window_id,
|
||||
bool state_window_take_metadata(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
window_metadata_t *metadata,
|
||||
uint32_t changed_fields) {
|
||||
uint32_t changed_fields
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (!window) return false;
|
||||
|
||||
@@ -505,8 +555,11 @@ bool state_window_take_metadata(state_t *state, window_id_t window_id,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool state_window_set_title(state_t *state, window_id_t window_id,
|
||||
const char *title) {
|
||||
bool state_window_set_title(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
const char *title
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (!window) return false;
|
||||
|
||||
@@ -514,8 +567,11 @@ bool state_window_set_title(state_t *state, window_id_t window_id,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool state_window_set_app_id(state_t *state, window_id_t window_id,
|
||||
const char *app_id) {
|
||||
bool state_window_set_app_id(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
const char *app_id
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (!window) return false;
|
||||
|
||||
@@ -523,8 +579,11 @@ bool state_window_set_app_id(state_t *state, window_id_t window_id,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool state_window_set_role(state_t *state, window_id_t window_id,
|
||||
const char *role) {
|
||||
bool state_window_set_role(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
const char *role
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (!window) return false;
|
||||
|
||||
@@ -532,8 +591,11 @@ bool state_window_set_role(state_t *state, window_id_t window_id,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool state_window_set_class(state_t *state, window_id_t window_id,
|
||||
const char *class_name) {
|
||||
bool state_window_set_class(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
const char *class_name
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (!window) return false;
|
||||
|
||||
@@ -541,8 +603,11 @@ bool state_window_set_class(state_t *state, window_id_t window_id,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool state_window_set_instance(state_t *state, window_id_t window_id,
|
||||
const char *instance_name) {
|
||||
bool state_window_set_instance(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
const char *instance_name
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (!window) return false;
|
||||
|
||||
|
||||
147
src/core/state.h
147
src/core/state.h
@@ -90,9 +90,13 @@ typedef struct state_t {
|
||||
* 每个 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_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);
|
||||
|
||||
/*
|
||||
@@ -104,15 +108,21 @@ void state_cleanup(state_t *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,
|
||||
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,
|
||||
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,
|
||||
layout_id_t layout_id
|
||||
);
|
||||
void state_workspace_set_focused_window(
|
||||
state_t *state,
|
||||
workspace_id_t workspace_id,
|
||||
window_id_t window_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);
|
||||
|
||||
@@ -124,10 +134,16 @@ bool state_workspace_valid(const state_t *state, workspace_id_t id);
|
||||
*/
|
||||
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);
|
||||
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);
|
||||
@@ -153,24 +169,51 @@ 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);
|
||||
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 状态实例指针
|
||||
@@ -185,19 +228,37 @@ void state_window_set_frame_rect(state_t *state, window_id_t window_id,
|
||||
* 失败时,不接管 metadata 中任何字段的所有权,metadata 保持不变,仍由调用方负
|
||||
* 责后续访问与释放。
|
||||
*/
|
||||
bool state_window_take_metadata(state_t *state, window_id_t window_id,
|
||||
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);
|
||||
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);
|
||||
|
||||
@@ -47,8 +47,8 @@ static inline void workspace_desc_cleanup(workspace_desc_t *workspace) {
|
||||
workspace->initial_layout_id = ZDWM_LAYOUT_ID_INVALID;
|
||||
}
|
||||
|
||||
static inline void workspace_desc_list_cleanup(workspace_desc_t **list,
|
||||
size_t *count) {
|
||||
static inline void
|
||||
workspace_desc_list_cleanup(workspace_desc_t **list, size_t *count) {
|
||||
if (!list || !count) return;
|
||||
|
||||
for (size_t i = 0; i < *count; i++) {
|
||||
@@ -65,7 +65,8 @@ static inline void workspace_desc_list_cleanup(workspace_desc_t **list,
|
||||
* 这组接口只校验描述表自身的一致性,不访问 state。
|
||||
*/
|
||||
static inline bool workspace_desc_layouts_valid(
|
||||
const workspace_desc_t *workspace) {
|
||||
const workspace_desc_t *workspace
|
||||
) {
|
||||
if (!workspace || !workspace->layout_count || !workspace->layout_ids) {
|
||||
return false;
|
||||
}
|
||||
@@ -77,8 +78,8 @@ static inline bool workspace_desc_layouts_valid(
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool workspace_desc_valid(const workspace_desc_t *workspace,
|
||||
size_t output_count) {
|
||||
static inline bool
|
||||
workspace_desc_valid(const workspace_desc_t *workspace, size_t output_count) {
|
||||
if (!workspace || !workspace->name) return false;
|
||||
if (workspace->output_index >= output_count) return false;
|
||||
|
||||
|
||||
@@ -91,9 +91,9 @@ static const button_t button_list[] = {
|
||||
};
|
||||
|
||||
#define TAGKEYS(KEY, TAG) \
|
||||
{modifier_super, KEY, select_tag_of_current_monitor, {.ui = TAG}}, { \
|
||||
modifier_super | modifier_shift, KEY, send_client_to_tag, {.ui = TAG}, \
|
||||
}
|
||||
{modifier_super, KEY, select_tag_of_current_monitor, {.ui = TAG}}, { \
|
||||
modifier_super | modifier_shift, KEY, send_client_to_tag, {.ui = TAG}, \
|
||||
}
|
||||
|
||||
static const char launcher[] =
|
||||
"rofi -show combi -modes combi -combi-modes window,drun,run,ssh,windowcd";
|
||||
|
||||
@@ -113,7 +113,8 @@ static image_cache_entry_t *image_cache_get(const char *path) {
|
||||
entry->surface = nullptr;
|
||||
}
|
||||
|
||||
if (!image_load_surface(path, &entry->surface, &entry->width, &entry->height)) {
|
||||
if (!image_load_surface(path, &entry->surface, &entry->width,
|
||||
&entry->height)) {
|
||||
return nullptr;
|
||||
}
|
||||
return entry;
|
||||
|
||||
@@ -17,7 +17,8 @@ size_t rect_subtract(rect_t source, rect_t clip, rect_t remaining[4]);
|
||||
* @param source 源矩形
|
||||
* @param clips 要减去的矩形数组,可为 nullptr
|
||||
* @param clip_count clips 的长度
|
||||
* @param remaining 输出剩余矩形数组;若不为 nullptr,则由函数分配内存并由调用方释放
|
||||
* @param remaining 输出剩余矩形数组;若不为
|
||||
* nullptr,则由函数分配内存并由调用方释放
|
||||
* @return 剩余矩形数量
|
||||
*
|
||||
* @code{.c}
|
||||
|
||||
42
src/tray.c
42
src/tray.c
@@ -123,7 +123,8 @@ static void tray_get_icon_layout(const tray_icon_t *icon, uint16_t *width,
|
||||
}
|
||||
|
||||
static uint16_t tray_compute_width(void) {
|
||||
if (!tray.initialized || tray.host_monitor == nullptr || tray.icon_count == 0) {
|
||||
if (!tray.initialized || tray.host_monitor == nullptr ||
|
||||
tray.icon_count == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -163,11 +164,10 @@ static void tray_select_icon_events(xcb_window_t window) {
|
||||
xcb_params_cw_t params = {
|
||||
.back_pixel = wm.color_set.bar_bg.argb,
|
||||
.border_pixel = 0,
|
||||
.event_mask = XCB_EVENT_MASK_PROPERTY_CHANGE |
|
||||
XCB_EVENT_MASK_STRUCTURE_NOTIFY,
|
||||
.event_mask =
|
||||
XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY,
|
||||
};
|
||||
uint32_t mask =
|
||||
XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK;
|
||||
uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK;
|
||||
xcb_aux_change_window_attributes(wm.xcb_conn, window, mask, ¶ms);
|
||||
xcb_clear_area(wm.xcb_conn, false, window, 0, 0, 0, 0);
|
||||
}
|
||||
@@ -180,8 +180,8 @@ static void tray_release_icon_window(tray_icon_t *icon) {
|
||||
.event_mask = XCB_EVENT_MASK_NO_EVENT,
|
||||
.border_pixel = 0,
|
||||
};
|
||||
xcb_aux_change_window_attributes(
|
||||
wm.xcb_conn, icon->window, XCB_CW_EVENT_MASK | XCB_CW_BORDER_PIXEL,
|
||||
xcb_aux_change_window_attributes(wm.xcb_conn, icon->window,
|
||||
XCB_CW_EVENT_MASK | XCB_CW_BORDER_PIXEL,
|
||||
¶ms);
|
||||
xcb_reparent_window(wm.xcb_conn, icon->window, wm.screen->root, 0, 0);
|
||||
}
|
||||
@@ -299,7 +299,8 @@ static void tray_add_icon(xcb_window_t window) {
|
||||
|
||||
static bool tray_create_window(void) {
|
||||
static xcb_colormap_t colormap = XCB_NONE;
|
||||
if (tray.host_monitor == nullptr || tray.host_monitor->bar_window == XCB_NONE) {
|
||||
if (tray.host_monitor == nullptr ||
|
||||
tray.host_monitor->bar_window == XCB_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -319,8 +320,8 @@ static bool tray_create_window(void) {
|
||||
const xcb_create_window_value_list_t value_list = {
|
||||
.background_pixel = wm.color_set.bar_bg.argb,
|
||||
.border_pixel = 0,
|
||||
.event_mask = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT |
|
||||
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY,
|
||||
.event_mask =
|
||||
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY,
|
||||
.colormap = colormap,
|
||||
};
|
||||
|
||||
@@ -362,7 +363,8 @@ static bool tray_take_selection_owner(void) {
|
||||
XCB_CURRENT_TIME);
|
||||
|
||||
owner_cookie = xcb_get_selection_owner(wm.xcb_conn, tray.selection_atom);
|
||||
owner_reply = xcb_get_selection_owner_reply(wm.xcb_conn, owner_cookie, nullptr);
|
||||
owner_reply =
|
||||
xcb_get_selection_owner_reply(wm.xcb_conn, owner_cookie, nullptr);
|
||||
bool success = owner_reply && owner_reply->owner == tray.window;
|
||||
p_delete(&owner_reply);
|
||||
|
||||
@@ -378,18 +380,12 @@ static void tray_set_properties(void) {
|
||||
|
||||
const color_t *fg = &wm.color_set.tag_color;
|
||||
uint32_t colors[12] = {
|
||||
tray_color_component_u16(fg->red),
|
||||
tray_color_component_u16(fg->green),
|
||||
tray_color_component_u16(fg->blue),
|
||||
tray_color_component_u16(fg->red),
|
||||
tray_color_component_u16(fg->green),
|
||||
tray_color_component_u16(fg->blue),
|
||||
tray_color_component_u16(fg->red),
|
||||
tray_color_component_u16(fg->green),
|
||||
tray_color_component_u16(fg->blue),
|
||||
tray_color_component_u16(fg->red),
|
||||
tray_color_component_u16(fg->green),
|
||||
tray_color_component_u16(fg->blue),
|
||||
tray_color_component_u16(fg->red), tray_color_component_u16(fg->green),
|
||||
tray_color_component_u16(fg->blue), tray_color_component_u16(fg->red),
|
||||
tray_color_component_u16(fg->green), tray_color_component_u16(fg->blue),
|
||||
tray_color_component_u16(fg->red), tray_color_component_u16(fg->green),
|
||||
tray_color_component_u16(fg->blue), tray_color_component_u16(fg->red),
|
||||
tray_color_component_u16(fg->green), tray_color_component_u16(fg->blue),
|
||||
};
|
||||
xcb_change_property(wm.xcb_conn, XCB_PROP_MODE_REPLACE, tray.window,
|
||||
_NET_SYSTEM_TRAY_COLORS, XCB_ATOM_CARDINAL, 32,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
typedef struct wallpaper_context_t wallpaper_context_t;
|
||||
|
||||
@@ -6,8 +6,13 @@
|
||||
#include "core/types.h"
|
||||
#include "utils.h"
|
||||
|
||||
static void assert_output_geometry(const output_info_t *output, int32_t x,
|
||||
int32_t y, int32_t width, int32_t height) {
|
||||
static void assert_output_geometry(
|
||||
const output_info_t *output,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t width,
|
||||
int32_t height
|
||||
) {
|
||||
assert(output);
|
||||
assert(output->geometry.x == x);
|
||||
assert(output->geometry.y == y);
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
#include "config/loader.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config/loader.h"
|
||||
#include "helpers.h"
|
||||
|
||||
static void test_config_loader_loads_explicit_override(const char *fixture_path) {
|
||||
static void test_config_loader_loads_explicit_override(
|
||||
const char *fixture_path
|
||||
) {
|
||||
config_test_clear_env();
|
||||
|
||||
config_loader_t loader = {0};
|
||||
@@ -22,9 +23,12 @@ static void test_config_loader_loads_explicit_override(const char *fixture_path)
|
||||
}
|
||||
|
||||
static void test_config_loader_override_has_priority_over_env(
|
||||
const char *fixture_path) {
|
||||
const char *fixture_path
|
||||
) {
|
||||
config_test_clear_env();
|
||||
assert(setenv("ZDWM_CONFIG_LIB", "/tmp/definitely-missing-config.so", 1) == 0);
|
||||
assert(
|
||||
setenv("ZDWM_CONFIG_LIB", "/tmp/definitely-missing-config.so", 1) == 0
|
||||
);
|
||||
|
||||
config_loader_t loader = {0};
|
||||
assert(config_loader_load(&loader, fixture_path));
|
||||
@@ -37,7 +41,8 @@ static void test_config_loader_override_has_priority_over_env(
|
||||
}
|
||||
|
||||
static void test_config_loader_uses_zdwm_config_lib_env(
|
||||
const char *fixture_path) {
|
||||
const char *fixture_path
|
||||
) {
|
||||
config_test_clear_env();
|
||||
assert(setenv("ZDWM_CONFIG_LIB", fixture_path, 1) == 0);
|
||||
|
||||
@@ -58,11 +63,18 @@ static void test_config_loader_uses_xdg_config_home(const char *fixture_path) {
|
||||
char config_dir[PATH_MAX] = {0};
|
||||
char config_path[PATH_MAX] = {0};
|
||||
|
||||
config_test_make_temp_dir(temp_root, sizeof(temp_root),
|
||||
"zdwm-config-loader-xdg");
|
||||
config_test_make_temp_dir(
|
||||
temp_root,
|
||||
sizeof(temp_root),
|
||||
"zdwm-config-loader-xdg"
|
||||
);
|
||||
config_test_join_path(config_dir, sizeof(config_dir), temp_root, "zdwm");
|
||||
config_test_join_path(config_path, sizeof(config_path), config_dir,
|
||||
"config.so");
|
||||
config_test_join_path(
|
||||
config_path,
|
||||
sizeof(config_path),
|
||||
config_dir,
|
||||
"config.so"
|
||||
);
|
||||
config_test_mkdir(config_dir);
|
||||
config_test_symlink(fixture_path, config_path);
|
||||
assert(setenv("XDG_CONFIG_HOME", temp_root, 1) == 0);
|
||||
@@ -88,12 +100,19 @@ static void test_config_loader_uses_home_fallback(const char *fixture_path) {
|
||||
char zdwm_dir[PATH_MAX] = {0};
|
||||
char config_path[PATH_MAX] = {0};
|
||||
|
||||
config_test_make_temp_dir(temp_root, sizeof(temp_root),
|
||||
"zdwm-config-loader-home");
|
||||
config_test_make_temp_dir(
|
||||
temp_root,
|
||||
sizeof(temp_root),
|
||||
"zdwm-config-loader-home"
|
||||
);
|
||||
config_test_join_path(config_root, sizeof(config_root), temp_root, ".config");
|
||||
config_test_join_path(zdwm_dir, sizeof(zdwm_dir), config_root, "zdwm");
|
||||
config_test_join_path(config_path, sizeof(config_path), zdwm_dir,
|
||||
"config.so");
|
||||
config_test_join_path(
|
||||
config_path,
|
||||
sizeof(config_path),
|
||||
zdwm_dir,
|
||||
"config.so"
|
||||
);
|
||||
config_test_mkdir(config_root);
|
||||
config_test_mkdir(zdwm_dir);
|
||||
config_test_symlink(fixture_path, config_path);
|
||||
@@ -119,10 +138,17 @@ static void test_config_loader_allows_missing_implicit_library(void) {
|
||||
char temp_root[PATH_MAX] = {0};
|
||||
char expected_path[PATH_MAX] = {0};
|
||||
|
||||
config_test_make_temp_dir(temp_root, sizeof(temp_root),
|
||||
"zdwm-config-loader-missing");
|
||||
config_test_join_path(expected_path, sizeof(expected_path), temp_root,
|
||||
"zdwm/config.so");
|
||||
config_test_make_temp_dir(
|
||||
temp_root,
|
||||
sizeof(temp_root),
|
||||
"zdwm-config-loader-missing"
|
||||
);
|
||||
config_test_join_path(
|
||||
expected_path,
|
||||
sizeof(expected_path),
|
||||
temp_root,
|
||||
"zdwm/config.so"
|
||||
);
|
||||
assert(setenv("XDG_CONFIG_HOME", temp_root, 1) == 0);
|
||||
|
||||
config_loader_t loader = {0};
|
||||
@@ -147,7 +173,8 @@ static void test_config_loader_rejects_missing_explicit_library(void) {
|
||||
}
|
||||
|
||||
static void test_config_loader_rejects_library_without_setup(
|
||||
const char *fixture_path) {
|
||||
const char *fixture_path
|
||||
) {
|
||||
config_test_clear_env();
|
||||
|
||||
config_loader_t loader = {0};
|
||||
|
||||
@@ -1,28 +1,45 @@
|
||||
#include <zdwm/config.h>
|
||||
|
||||
static bool fixture_layout(const zdwm_layout_ctx_t *ctx,
|
||||
zdwm_layout_result_t *out) {
|
||||
static bool
|
||||
fixture_layout(const zdwm_layout_ctx_t *ctx, zdwm_layout_result_t *out) {
|
||||
if (!ctx || !out) return false;
|
||||
|
||||
zdwm_layout_result_reset(out);
|
||||
if (!ctx->window_ids || ctx->window_count == 0) return true;
|
||||
|
||||
zdwm_layout_result_push(out, (zdwm_layout_item_t){
|
||||
zdwm_layout_result_push(
|
||||
out,
|
||||
(zdwm_layout_item_t){
|
||||
.window_id = ctx->window_ids[0],
|
||||
.rect = ctx->workarea,
|
||||
});
|
||||
}
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setup(const zdwm_api_t *api, zdwm_config_builder_t *builder,
|
||||
const zdwm_output_info_t *outputs, size_t output_count) {
|
||||
bool setup(
|
||||
const zdwm_api_t *api,
|
||||
zdwm_config_builder_t *builder,
|
||||
const zdwm_output_info_t *outputs,
|
||||
size_t output_count
|
||||
) {
|
||||
if (!api || !builder || !outputs || output_count == 0) return false;
|
||||
|
||||
zdwm_layout_id_t layout_id =
|
||||
api->register_layout(builder, "test-only", "[T]", "fixture layout",
|
||||
fixture_layout);
|
||||
zdwm_layout_id_t layout_id = api->register_layout(
|
||||
builder,
|
||||
"test-only",
|
||||
"[T]",
|
||||
"fixture layout",
|
||||
fixture_layout
|
||||
);
|
||||
if (layout_id == ZDWM_LAYOUT_ID_INVALID) return false;
|
||||
|
||||
return api->define_workspace(builder, 0, "from-so", &layout_id, 1,
|
||||
layout_id) != ZDWM_WORKSPACE_ID_INVALID;
|
||||
return api->define_workspace(
|
||||
builder,
|
||||
0,
|
||||
"from-so",
|
||||
&layout_id,
|
||||
1,
|
||||
layout_id
|
||||
) != ZDWM_WORKSPACE_ID_INVALID;
|
||||
}
|
||||
|
||||
@@ -15,17 +15,20 @@ static inline void config_test_clear_env(void) {
|
||||
assert(unsetenv("HOME") == 0);
|
||||
}
|
||||
|
||||
static inline void config_test_make_temp_dir(char *path, size_t path_size,
|
||||
const char *prefix) {
|
||||
static inline void
|
||||
config_test_make_temp_dir(char *path, size_t path_size, const char *prefix) {
|
||||
int len = snprintf(path, path_size, "/tmp/%s-XXXXXX", prefix);
|
||||
assert(len > 0);
|
||||
assert((size_t)len < path_size);
|
||||
assert(mkdtemp(path) == path);
|
||||
}
|
||||
|
||||
static inline void config_test_join_path(char *out, size_t out_size,
|
||||
static inline void config_test_join_path(
|
||||
char *out,
|
||||
size_t out_size,
|
||||
const char *base,
|
||||
const char *suffix) {
|
||||
const char *suffix
|
||||
) {
|
||||
int len = snprintf(out, out_size, "%s/%s", base, suffix);
|
||||
assert(len > 0);
|
||||
assert((size_t)len < out_size);
|
||||
|
||||
@@ -22,8 +22,11 @@ bool backend_next_event(backend_t *backend, event_t *event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool backend_apply_effect(backend_t *backend, const effect_t *effects,
|
||||
size_t effect_count) {
|
||||
bool backend_apply_effect(
|
||||
backend_t *backend,
|
||||
const effect_t *effects,
|
||||
size_t effect_count
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -79,7 +82,8 @@ static void test_runtime_config_loads_user_library(const char *fixture_path) {
|
||||
}
|
||||
|
||||
static void test_runtime_config_keeps_module_loaded_after_runtime_init(
|
||||
const char *fixture_path) {
|
||||
const char *fixture_path
|
||||
) {
|
||||
config_test_clear_env();
|
||||
|
||||
output_info_t outputs[] = {
|
||||
@@ -132,7 +136,8 @@ static void test_runtime_config_keeps_module_loaded_after_runtime_init(
|
||||
|
||||
static void
|
||||
test_runtime_config_falls_back_to_defaults_when_implicit_library_is_missing(
|
||||
void) {
|
||||
void
|
||||
) {
|
||||
config_test_clear_env();
|
||||
|
||||
output_info_t outputs[] = {
|
||||
@@ -147,8 +152,11 @@ test_runtime_config_falls_back_to_defaults_when_implicit_library_is_missing(
|
||||
};
|
||||
|
||||
char temp_root[PATH_MAX] = {0};
|
||||
config_test_make_temp_dir(temp_root, sizeof(temp_root),
|
||||
"zdwm-runtime-config-missing");
|
||||
config_test_make_temp_dir(
|
||||
temp_root,
|
||||
sizeof(temp_root),
|
||||
"zdwm-runtime-config-missing"
|
||||
);
|
||||
assert(setenv("XDG_CONFIG_HOME", temp_root, 1) == 0);
|
||||
|
||||
runtime_init_desc_t desc = {
|
||||
@@ -190,7 +198,8 @@ static void test_runtime_config_rejects_missing_explicit_library(void) {
|
||||
}
|
||||
|
||||
static void test_runtime_config_rejects_library_without_setup(
|
||||
const char *fixture_path) {
|
||||
const char *fixture_path
|
||||
) {
|
||||
config_test_clear_env();
|
||||
|
||||
output_info_t outputs[] = {
|
||||
|
||||
Reference in New Issue
Block a user