core: 添加窗口规则 (rules) 数据结构和配置接口

This commit is contained in:
2026-04-12 02:11:57 +08:00
parent 823d8c1b65
commit b55d0c6b91
10 changed files with 169 additions and 7 deletions

View File

@@ -5,6 +5,7 @@
#include <stddef.h>
#include <stdint.h>
#include <zdwm/layout.h>
#include <zdwm/rules.h>
#include <zdwm/types.h>
#if defined(__cplusplus)
@@ -54,6 +55,19 @@ typedef struct zdwm_api_t {
const zdwm_layout_id_t *layout_ids,
size_t layout_count,
zdwm_layout_id_t initial_layout_id);
/**
* 用户调用这个函数添加窗口规则
* @param builder 配置构建上下文
* @param match 窗口匹配条件,不能为 nullptr
* @param action 匹配后执行的动作,不能为 nullptr
* @returns 添加成功返回 true ,不合法时返回 false
* @details 不合法的情况match 所有字段全为 nullptr
* 或 action 无任何动作;或 action 指定的 workspace 不存在
*/
bool (*add_rule)(zdwm_config_builder_t *builder,
const zdwm_rule_match_t *match,
const zdwm_rule_action_t *action);
} zdwm_api_t;
/**

38
include/zdwm/rules.h Normal file
View File

@@ -0,0 +1,38 @@
#ifndef ZDWM_RULES_H
#define ZDWM_RULES_H
#include <zdwm/types.h>
#if defined(__cplusplus)
extern "C" {
#endif
/**
* @brief 窗口匹配条件
* @details 仅匹配不为 nullptr 的字段,多个字段按且规则匹配
*/
typedef struct zdwm_rule_match_t {
const char *app_id;
const char *role;
const char *class_name;
const char *instance_name;
} zdwm_rule_match_t;
typedef struct zdwm_rule_action_t {
/**
* 目标 workspace id
* - 若规则不想指定 workspace ,则将其设为 ZDWM_WORKSPACE_ID_INVALID
*/
zdwm_workspace_id_t workspace;
bool switch_to_workspace; /* 自动切换到目标 workspace仅 true 时生效) */
bool fullscreen; /* 强制全屏(仅 true 时生效) */
bool maximize; /* 强制最大化(仅 true 时生效) */
bool floating; /* 强制浮动(仅 true 时生效) */
} zdwm_rule_action_t;
#if defined(__cplusplus)
}
#endif
#endif /* ZDWM_RULES_H */

View File

@@ -1,6 +1,7 @@
#include "config/runtime_config.h"
#include <dlfcn.h>
#include <stddef.h>
#include <zdwm/config.h>
#include "base/array.h"
@@ -8,11 +9,14 @@
#include "config/defaults.h"
#include "config/loader.h"
#include "core/layout.h"
#include "core/rules.h"
#include "core/runtime.h"
#include "core/types.h"
#include "core/wm_desc.h"
struct zdwm_config_builder_t {
layout_registry_t layouts;
rules_t rules;
workspace_desc_t *workspaces;
size_t workspace_count;
size_t workspace_capacity;
@@ -89,6 +93,46 @@ static workspace_id_t runtime_config_define_workspace(
return workspace_id;
}
static bool rule_match_valid(const rule_match_t *match) {
if (!match) return false;
return match->app_id || match->role || match->class_name ||
match->instance_name;
}
static bool rule_action_valid(const rule_action_t *action,
size_t workspace_count) {
if (!action) return false;
bool flag_valid = action->switch_to_workspace || action->fullscreen ||
action->maximize || action->floating;
if (action->workspace == ZDWM_WORKSPACE_ID_INVALID) {
return flag_valid;
} else {
return action->workspace < workspace_count && flag_valid;
}
}
static bool runtime_config_add_rule(zdwm_config_builder_t *builder,
const zdwm_rule_match_t *match,
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;
rules_t *rules = &builder->rules;
rule_item_t *rule = array_push(rules->items, rules->count, rules->capacity);
rule->match.app_id = p_strdup_nullable(match->app_id);
rule->match.role = p_strdup_nullable(match->role);
rule->match.class_name = p_strdup_nullable(match->class_name);
rule->match.instance_name = p_strdup_nullable(match->instance_name);
rule->action = *action;
return true;
}
static bool config_builder_finish(zdwm_config_builder_t *builder,
runtime_init_desc_t *out) {
if (!builder || !out) return false;
@@ -96,6 +140,7 @@ static bool config_builder_finish(zdwm_config_builder_t *builder,
if (!builder->layouts.slot_count || !builder->workspace_count) return false;
if (!layout_registry_move(&builder->layouts, &out->layouts)) return false;
if (!rules_move(&builder->rules, &out->rules)) return false;
out->workspaces = builder->workspaces;
out->workspace_count = builder->workspace_count;
builder->workspaces = nullptr;
@@ -122,6 +167,7 @@ static bool runtime_config_build(zdwm_config_setup_fn *setup,
},
.register_layout = runtime_config_register_layout,
.define_workspace = runtime_config_define_workspace,
.add_rule = runtime_config_add_rule,
};
bool ok = setup(&api, &builder, outputs, output_count) &&
config_builder_finish(&builder, out);

37
src/core/rules.c Normal file
View File

@@ -0,0 +1,37 @@
#include "core/rules.h"
#include "base/memory.h"
#include "core/types.h"
bool rules_move(rules_t *src, rules_t *dest) {
if (!dest || !src) return false;
dest->items = src->items;
dest->count = src->count;
dest->capacity = src->capacity;
src->items = nullptr;
src->count = 0;
src->capacity = 0;
return true;
}
void rules_cleanup(rules_t *rules) {
for (size_t i = 0; i < rules->count; ++i) {
rule_match_t *match = &rules->items[i].match;
rule_action_t *action = &rules->items[i].action;
p_delete(&match->app_id);
p_delete(&match->role);
p_delete(&match->class_name);
p_delete(&match->instance_name);
p_clear(action, 1);
action->workspace = ZDWM_WORKSPACE_ID_INVALID;
}
p_delete(&rules->items);
rules->capacity = 0;
rules->count = 0;
}

19
src/core/rules.h Normal file
View File

@@ -0,0 +1,19 @@
#pragma once
#include <stddef.h>
#include "core/types.h"
typedef struct rule_item_t {
rule_match_t match;
rule_action_t action;
} rule_item_t;
typedef struct rules_t {
rule_item_t *items;
size_t count;
size_t capacity;
} rules_t;
bool rules_move(rules_t *dest, rules_t *src);
void rules_cleanup(rules_t *rules);

View File

@@ -5,6 +5,8 @@
#include "base/memory.h"
#include "core/backend.h"
#include "core/event.h"
#include "core/layout.h"
#include "core/rules.h"
#include "core/state.h"
#include "core/wm_desc.h"
@@ -42,11 +44,10 @@ bool runtime_init(runtime_t *runtime, runtime_init_desc_t *desc) {
p_clear(runtime, 1);
runtime->backend = desc->backend;
runtime->layouts = desc->layouts;
layout_registry_move(&desc->layouts, &runtime->layouts);
rules_move(&desc->rules, &runtime->rules);
runtime->config_module_handle = desc->config_module_handle;
desc->backend = nullptr;
p_clear(&desc->layouts, 1);
desc->config_module_handle = nullptr;
state_init(&runtime->state, desc->outputs, desc->output_count,
@@ -81,10 +82,8 @@ void runtime_init_desc_cleanup(runtime_init_desc_t *desc) {
void runtime_shutdown(runtime_t *runtime) {
runtime->running = false;
if (runtime->layouts.slots || runtime->layouts.slot_count ||
runtime->layouts.slot_capacity) {
layout_registry_cleanup(&runtime->layouts);
}
rules_cleanup(&runtime->rules);
state_cleanup(&runtime->state);
backend_destroy(runtime->backend);
runtime->backend = nullptr;

View File

@@ -4,6 +4,7 @@
#include "core/backend.h"
#include "core/layout.h"
#include "core/rules.h"
#include "core/state.h"
typedef struct runtime_init_desc_t {
@@ -12,6 +13,7 @@ typedef struct runtime_init_desc_t {
size_t output_count;
layout_registry_t layouts;
rules_t rules;
workspace_desc_t *workspaces;
size_t workspace_count;
void *config_module_handle;
@@ -23,6 +25,7 @@ typedef struct runtime_t {
state_t state;
layout_registry_t layouts;
rules_t rules;
backend_t *backend;
void *config_module_handle;
} runtime_t;

View File

@@ -1,6 +1,7 @@
#pragma once
#include <stdint.h>
#include <zdwm/rules.h>
#include <zdwm/types.h>
/* clang-format off */
@@ -11,6 +12,9 @@ typedef uint32_t output_id_t;
typedef zdwm_rect_t rect_t;
typedef zdwm_output_info_t output_info_t;
typedef zdwm_rule_match_t rule_match_t;
typedef zdwm_rule_action_t rule_action_t;
/* clang-format on */
#define ZDWM_OUTPUT_ID_INVALID ((output_id_t)UINT32_MAX)

View File

@@ -43,6 +43,7 @@ add_executable(${RUNTIME_CONFIG_TEST_APP_NAME}
${SOURCE_DIR}/config/runtime_config.c
${SOURCE_DIR}/core/layer.c
${SOURCE_DIR}/core/layout.c
${SOURCE_DIR}/core/rules.c
${SOURCE_DIR}/core/runtime.c
${SOURCE_DIR}/core/state.c
)

View File

@@ -12,6 +12,7 @@ add_executable(${TEST_APP_NAME}
${SOURCE_DIR}/backend/x11/window.c
${SOURCE_DIR}/core/layer.c
${SOURCE_DIR}/core/layout.c
${SOURCE_DIR}/core/rules.c
${SOURCE_DIR}/core/runtime.c
${SOURCE_DIR}/core/state.c
)