Compare commits
9 Commits
b55d0c6b91
...
6561b16be0
| Author | SHA1 | Date | |
|---|---|---|---|
|
6561b16be0
|
|||
|
20e5e57c8c
|
|||
|
0c86f9aad8
|
|||
|
0c24fb2a32
|
|||
|
637f658318
|
|||
|
5230b8b718
|
|||
|
ead8160a61
|
|||
|
9dd3ae00d2
|
|||
|
71eba04de1
|
@@ -337,3 +337,9 @@ void backend_detect_destroy(backend_detect_t *detect) {
|
|||||||
p_delete(&detect->outputs);
|
p_delete(&detect->outputs);
|
||||||
free(detect);
|
free(detect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool backend_apply_effect(backend_t *backend, const effect_t *effects,
|
||||||
|
size_t effect_count) {
|
||||||
|
/* TODO: */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ static bool handle_map_request(backend_t *backend, event_t *event,
|
|||||||
const xcb_map_request_event_t *xcb_event) {
|
const xcb_map_request_event_t *xcb_event) {
|
||||||
xcb_window_t window = xcb_event->window;
|
xcb_window_t window = xcb_event->window;
|
||||||
|
|
||||||
p_clear(event, 1);
|
event_reset(event);
|
||||||
event->type = ZDWM_EVENT_WINDOW_MAP_REQUEST;
|
event->type = ZDWM_EVENT_WINDOW_MAP_REQUEST;
|
||||||
|
|
||||||
window_map_request_event_t *ev = &event->as.window_map_request;
|
window_map_request_event_t *ev = &event->as.window_map_request;
|
||||||
@@ -125,7 +125,7 @@ static bool handle_map_request(backend_t *backend, event_t *event,
|
|||||||
|
|
||||||
static bool handle_unmap_notify(backend_t *backend, event_t *event,
|
static bool handle_unmap_notify(backend_t *backend, event_t *event,
|
||||||
const xcb_unmap_notify_event_t *xcb_event) {
|
const xcb_unmap_notify_event_t *xcb_event) {
|
||||||
p_clear(event, 1);
|
event_reset(event);
|
||||||
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
||||||
/* TODO: */
|
/* TODO: */
|
||||||
return true;
|
return true;
|
||||||
@@ -133,7 +133,7 @@ static bool handle_unmap_notify(backend_t *backend, event_t *event,
|
|||||||
|
|
||||||
static bool handle_destroy_notify(backend_t *backend, event_t *event,
|
static bool handle_destroy_notify(backend_t *backend, event_t *event,
|
||||||
const xcb_destroy_notify_event_t *xcb_event) {
|
const xcb_destroy_notify_event_t *xcb_event) {
|
||||||
p_clear(event, 1);
|
event_reset(event);
|
||||||
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
||||||
/* TODO: */
|
/* TODO: */
|
||||||
return true;
|
return true;
|
||||||
@@ -142,7 +142,7 @@ static bool handle_destroy_notify(backend_t *backend, event_t *event,
|
|||||||
static bool handle_configure_request(
|
static bool handle_configure_request(
|
||||||
backend_t *backend, event_t *event,
|
backend_t *backend, event_t *event,
|
||||||
const xcb_configure_request_event_t *xcb_event) {
|
const xcb_configure_request_event_t *xcb_event) {
|
||||||
p_clear(event, 1);
|
event_reset(event);
|
||||||
event->type = ZDWM_EVENT_CONFIGURE_REQUEST;
|
event->type = ZDWM_EVENT_CONFIGURE_REQUEST;
|
||||||
/* TODO: */
|
/* TODO: */
|
||||||
return true;
|
return true;
|
||||||
@@ -179,5 +179,6 @@ bool backend_next_event(backend_t *backend, event_t *event) {
|
|||||||
|
|
||||||
p_delete(&raw_event);
|
p_delete(&raw_event);
|
||||||
if (handled) return true;
|
if (handled) return true;
|
||||||
|
event_reset(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,14 +104,12 @@ static bool rule_action_valid(const rule_action_t *action,
|
|||||||
size_t workspace_count) {
|
size_t workspace_count) {
|
||||||
if (!action) return false;
|
if (!action) return false;
|
||||||
|
|
||||||
bool flag_valid = action->switch_to_workspace || action->fullscreen ||
|
|
||||||
action->maximize || action->floating;
|
|
||||||
|
|
||||||
if (action->workspace == ZDWM_WORKSPACE_ID_INVALID) {
|
if (action->workspace == ZDWM_WORKSPACE_ID_INVALID) {
|
||||||
return flag_valid;
|
return action->switch_to_workspace || action->fullscreen ||
|
||||||
} else {
|
action->maximize || action->floating;
|
||||||
return action->workspace < workspace_count && flag_valid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "core/event.h"
|
#include "core/event.h"
|
||||||
|
#include "core/plan.h"
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
|
|
||||||
typedef struct backend_t backend_t;
|
typedef struct backend_t backend_t;
|
||||||
@@ -18,4 +19,18 @@ void backend_destroy(backend_t *backend);
|
|||||||
backend_detect_t *backend_detect(backend_t *backend);
|
backend_detect_t *backend_detect(backend_t *backend);
|
||||||
void backend_detect_destroy(backend_detect_t *detect);
|
void backend_detect_destroy(backend_detect_t *detect);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 阻塞等待 backend 产出下一个可交给 runtime 的归一化事件
|
||||||
|
* @details
|
||||||
|
* backend 可以在内部丢弃无关的原始平台事件,直到拿到一个可路由事件或遇到
|
||||||
|
* stop/error 条件。
|
||||||
|
*
|
||||||
|
* 返回 true 时,`event` 已被完整填充;若其中包含堆内存,所有权转交给调用方,
|
||||||
|
* 调用方必须在本轮处理结束后调用 event_cleanup() 或 event_reset()。
|
||||||
|
*
|
||||||
|
* 返回 false 时,表示 backend 请求停止或遇到错误;此时 `event` 必须保持为
|
||||||
|
* 无需 cleanup 的状态,调用方可以直接退出循环。
|
||||||
|
*/
|
||||||
bool backend_next_event(backend_t *backend, event_t *event);
|
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);
|
||||||
|
|||||||
38
src/core/command.h
Normal file
38
src/core/command.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/types.h"
|
||||||
|
#include "core/wm_desc.h"
|
||||||
|
|
||||||
|
typedef enum command_type_t {
|
||||||
|
ZDWM_COMMAND_MANAGE_WINDOW,
|
||||||
|
ZDWM_COMMAND_SWITCH_WORKSPACE
|
||||||
|
} command_type_t;
|
||||||
|
|
||||||
|
typedef struct manage_window_command_t {
|
||||||
|
workspace_id_t workspace;
|
||||||
|
bool floating;
|
||||||
|
bool switch_to_workspace;
|
||||||
|
window_info_t info;
|
||||||
|
} manage_window_command_t;
|
||||||
|
|
||||||
|
typedef struct switch_workspace_command_t {
|
||||||
|
output_id_t output;
|
||||||
|
workspace_id_t workspace;
|
||||||
|
} switch_workspace_command_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 非 owning 的命令值对象
|
||||||
|
* @details
|
||||||
|
* command_t 自身不拥有任何堆内存;其当前所有 payload 中出现的指针字段均为借用
|
||||||
|
* 语义。
|
||||||
|
*
|
||||||
|
* 因此 command_t 支持按值浅拷贝,且不需要单独的 cleanup 接口。若接收方需要在
|
||||||
|
* 源数据生命周期之外继续持有相关内容,必须自行复制。
|
||||||
|
*/
|
||||||
|
typedef struct command_t {
|
||||||
|
command_type_t type;
|
||||||
|
union {
|
||||||
|
manage_window_command_t manage_window;
|
||||||
|
switch_workspace_command_t switch_workspace;
|
||||||
|
} as;
|
||||||
|
} command_t;
|
||||||
23
src/core/command_buffer.c
Normal file
23
src/core/command_buffer.c
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#include "core/command_buffer.h"
|
||||||
|
|
||||||
|
#include "base/array.h"
|
||||||
|
#include "base/memory.h"
|
||||||
|
#include "core/command.h"
|
||||||
|
|
||||||
|
void command_buffer_reset(command_buffer_t *buffer) {
|
||||||
|
if (!buffer->items || !buffer->capacity) return;
|
||||||
|
|
||||||
|
p_clear(buffer->items, buffer->capacity);
|
||||||
|
buffer->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void command_buffer_cleanup(command_buffer_t *buffer) {
|
||||||
|
p_delete(&buffer->items);
|
||||||
|
buffer->count = 0;
|
||||||
|
buffer->capacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void command_buffer_push(command_buffer_t *buffer, const command_t *command) {
|
||||||
|
command_t *cmd = array_push(buffer->items, buffer->count, buffer->capacity);
|
||||||
|
*cmd = *command;
|
||||||
|
}
|
||||||
15
src/core/command_buffer.h
Normal file
15
src/core/command_buffer.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "core/command.h"
|
||||||
|
|
||||||
|
typedef struct command_buffer_t {
|
||||||
|
command_t *items;
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
} command_buffer_t;
|
||||||
|
|
||||||
|
void command_buffer_reset(command_buffer_t *buffer);
|
||||||
|
void command_buffer_cleanup(command_buffer_t *buffer);
|
||||||
|
void command_buffer_push(command_buffer_t *buffer, const command_t *command);
|
||||||
45
src/core/event.c
Normal file
45
src/core/event.c
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#include "core/event.h"
|
||||||
|
|
||||||
|
#include "base/memory.h"
|
||||||
|
|
||||||
|
static void window_layer_props_cleanup(window_layer_props_t *props) {
|
||||||
|
if (!props) return;
|
||||||
|
|
||||||
|
p_delete(&props->types);
|
||||||
|
props->type_count = 0;
|
||||||
|
p_delete(&props->states);
|
||||||
|
props->state_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void window_metadata_cleanup(window_metadata_t *metadata) {
|
||||||
|
if (!metadata) return;
|
||||||
|
|
||||||
|
p_delete(&metadata->title);
|
||||||
|
p_delete(&metadata->app_id);
|
||||||
|
p_delete(&metadata->role);
|
||||||
|
p_delete(&metadata->class_name);
|
||||||
|
p_delete(&metadata->instance_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void event_cleanup(event_t *event) {
|
||||||
|
if (!event) return;
|
||||||
|
|
||||||
|
switch (event->type) {
|
||||||
|
case ZDWM_EVENT_WINDOW_MAP_REQUEST:
|
||||||
|
window_layer_props_cleanup(&event->as.window_map_request.props);
|
||||||
|
window_metadata_cleanup(&event->as.window_map_request.metadata);
|
||||||
|
break;
|
||||||
|
case ZDWM_EVENT_WINDOW_METADATA_CHANGED:
|
||||||
|
window_metadata_cleanup(&event->as.window_metadata_change.metadata);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void event_reset(event_t *event) {
|
||||||
|
if (!event) return;
|
||||||
|
|
||||||
|
event_cleanup(event);
|
||||||
|
p_clear(event, 1);
|
||||||
|
}
|
||||||
@@ -178,3 +178,6 @@ typedef struct event_t {
|
|||||||
configure_request_event_t configure_request;
|
configure_request_event_t configure_request;
|
||||||
} as;
|
} as;
|
||||||
} event_t;
|
} event_t;
|
||||||
|
|
||||||
|
void event_cleanup(event_t *event);
|
||||||
|
void event_reset(event_t *event);
|
||||||
|
|||||||
@@ -21,14 +21,15 @@ void layout_result_push(layout_result_t *result, layout_item_t item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void layout_registry_cleanup(layout_registry_t *registry) {
|
void layout_registry_cleanup(layout_registry_t *registry) {
|
||||||
while (registry->slot_count > 0) {
|
for (size_t i = 0; i < registry->slot_count; ++i) {
|
||||||
layout_slot_t *r = ®istry->slots[--registry->slot_count];
|
layout_slot_t *r = ®istry->slots[i];
|
||||||
p_delete(&r->name);
|
p_delete(&r->name);
|
||||||
p_delete(&r->symbol);
|
p_delete(&r->symbol);
|
||||||
p_delete(&r->description);
|
p_delete(&r->description);
|
||||||
r->fn = nullptr;
|
r->fn = nullptr;
|
||||||
r->id = ZDWM_LAYOUT_ID_INVALID;
|
r->id = ZDWM_LAYOUT_ID_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_delete(®istry->slots);
|
p_delete(®istry->slots);
|
||||||
registry->slot_count = 0;
|
registry->slot_count = 0;
|
||||||
registry->slot_capacity = 0;
|
registry->slot_capacity = 0;
|
||||||
|
|||||||
22
src/core/plan.c
Normal file
22
src/core/plan.c
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#include "core/plan.h"
|
||||||
|
|
||||||
|
#include "base/array.h"
|
||||||
|
#include "base/memory.h"
|
||||||
|
|
||||||
|
void plan_reset(plan_t *plan) {
|
||||||
|
if (!plan->effects || !plan->capacity) return;
|
||||||
|
|
||||||
|
p_clear(plan->effects, plan->capacity);
|
||||||
|
plan->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plan_cleanup(plan_t *plan) {
|
||||||
|
p_delete(&plan->effects);
|
||||||
|
plan->count = 0;
|
||||||
|
plan->capacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plan_push_effect(plan_t *plan, const effect_t *effect) {
|
||||||
|
effect_t *eft = array_push(plan->effects, plan->count, plan->capacity);
|
||||||
|
*eft = *effect;
|
||||||
|
}
|
||||||
44
src/core/plan.h
Normal file
44
src/core/plan.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "core/types.h"
|
||||||
|
|
||||||
|
typedef uint32_t dirty_mask_t;
|
||||||
|
|
||||||
|
typedef enum dirty_flags_t : dirty_mask_t {
|
||||||
|
ZDWM_DIRTY_NONE = 0,
|
||||||
|
ZDWM_DIRTY_LAYOUT = 1u << 0,
|
||||||
|
} dirty_flags_t;
|
||||||
|
|
||||||
|
typedef enum effect_type_t {
|
||||||
|
ZDWM_EFFECT_NONE,
|
||||||
|
ZDWM_EFFECT_MAP_WINDOW,
|
||||||
|
ZDWM_EFFECT_UNMAP_WINDOW,
|
||||||
|
ZDWM_EFFECT_FOCUS_WINDOW,
|
||||||
|
} effect_type_t;
|
||||||
|
|
||||||
|
typedef struct effect_only_window_id_t {
|
||||||
|
window_id_t window;
|
||||||
|
} effect_only_window_id_t;
|
||||||
|
|
||||||
|
typedef struct effect_t {
|
||||||
|
effect_type_t type;
|
||||||
|
union {
|
||||||
|
effect_only_window_id_t map;
|
||||||
|
effect_only_window_id_t unmap;
|
||||||
|
effect_only_window_id_t focus;
|
||||||
|
} as;
|
||||||
|
} effect_t;
|
||||||
|
|
||||||
|
typedef struct plan_t {
|
||||||
|
effect_t *effects;
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
dirty_mask_t dirty_flags;
|
||||||
|
} plan_t;
|
||||||
|
|
||||||
|
void plan_reset(plan_t *plan);
|
||||||
|
void plan_cleanup(plan_t *plan);
|
||||||
|
void plan_push_effect(plan_t *plan, const effect_t *effect);
|
||||||
@@ -1,10 +1,111 @@
|
|||||||
#include "core/policy.h"
|
#include "core/policy.h"
|
||||||
|
|
||||||
#include "base/macros.h"
|
#include <zdwm/types.h>
|
||||||
#include "core/state.h"
|
|
||||||
|
|
||||||
layer_type_t policy_adjust_window_layer_from_transient(
|
#include "base/macros.h"
|
||||||
const state_t *state, window_id_t transient_for, layer_type_t base_layer) {
|
#include "core/command.h"
|
||||||
const window_t *window = state_window_get(state, transient_for);
|
#include "core/command_buffer.h"
|
||||||
return MAX(window->layer, base_layer);
|
#include "core/event.h"
|
||||||
|
#include "core/layer.h"
|
||||||
|
#include "core/rules.h"
|
||||||
|
#include "core/state.h"
|
||||||
|
#include "core/types.h"
|
||||||
|
#include "core/wm_desc.h"
|
||||||
|
|
||||||
|
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,
|
||||||
|
const window_map_request_event_t *e,
|
||||||
|
command_buffer_t *out) {
|
||||||
|
if (state_window_get(state, e->window)) return false;
|
||||||
|
|
||||||
|
layer_type_t layer_type = layer_classify(&e->props);
|
||||||
|
if (e->transient_for != ZDWM_WINDOW_ID_INVALID) {
|
||||||
|
const window_t *window = state_window_get(state, e->transient_for);
|
||||||
|
if (window) layer_type = MAX(window->layer, layer_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
command_t cmd = {
|
||||||
|
.type = ZDWM_COMMAND_MANAGE_WINDOW,
|
||||||
|
.as.manage_window =
|
||||||
|
{
|
||||||
|
.workspace = derive_window_workspace(state),
|
||||||
|
.info =
|
||||||
|
{
|
||||||
|
.id = e->window,
|
||||||
|
.transient_for = e->transient_for,
|
||||||
|
.frame_rect = e->rect,
|
||||||
|
|
||||||
|
.title = e->metadata.title,
|
||||||
|
.app_id = e->metadata.app_id,
|
||||||
|
.role = e->metadata.role,
|
||||||
|
.class_name = e->metadata.class_name,
|
||||||
|
.instance_name = e->metadata.instance_name,
|
||||||
|
|
||||||
|
.geometry_mode = e->geometry_mode,
|
||||||
|
.layer_type = layer_type,
|
||||||
|
.urgent = e->urgent,
|
||||||
|
.fixed_size = e->fixed_size,
|
||||||
|
.skip_taskbar = e->skip_taskbar,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
rule_action_t action = {.workspace = ZDWM_WORKSPACE_ID_INVALID};
|
||||||
|
bool have_rule_match = rules_resolve(rules, &e->metadata, &action);
|
||||||
|
if (have_rule_match) {
|
||||||
|
manage_window_command_t *data = &cmd.as.manage_window;
|
||||||
|
if (action.workspace != ZDWM_WORKSPACE_ID_INVALID) {
|
||||||
|
data->workspace = action.workspace;
|
||||||
|
}
|
||||||
|
if (action.floating) {
|
||||||
|
data->floating = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.fullscreen) {
|
||||||
|
data->info.geometry_mode = ZDWM_GEOMETRY_FULLSCREEN;
|
||||||
|
} else if (action.maximize) {
|
||||||
|
data->info.geometry_mode = ZDWM_GEOMETRY_MAXIMIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command_buffer_push(out, &cmd);
|
||||||
|
if (have_rule_match && action.switch_to_workspace) {
|
||||||
|
workspace_id_t workspace_id = cmd.as.manage_window.workspace;
|
||||||
|
const workspace_t *workspace = state_workspace_get(state, workspace_id);
|
||||||
|
|
||||||
|
if (workspace) {
|
||||||
|
command_t switch_workspace_cmd = {
|
||||||
|
.type = ZDWM_COMMAND_SWITCH_WORKSPACE,
|
||||||
|
.as.switch_workspace =
|
||||||
|
{
|
||||||
|
.output = workspace->output_id,
|
||||||
|
.workspace = workspace_id,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
command_buffer_push(out, &switch_workspace_cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool policy_apply_command(const policy_context_t *ctx,
|
||||||
|
const command_buffer_t *command_buffer,
|
||||||
|
plan_t *plan) {
|
||||||
|
/* TODO: */
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/layer.h"
|
#include "core/command_buffer.h"
|
||||||
|
#include "core/event.h"
|
||||||
|
#include "core/plan.h"
|
||||||
|
#include "core/rules.h"
|
||||||
#include "core/state.h"
|
#include "core/state.h"
|
||||||
#include "core/types.h"
|
|
||||||
|
|
||||||
layer_type_t policy_adjust_window_layer_from_transient(
|
typedef struct policy_context_t {
|
||||||
const state_t *state, window_id_t transient_for, layer_type_t base_layer);
|
const state_t *state;
|
||||||
|
const rules_t *rules;
|
||||||
|
const event_t *event;
|
||||||
|
} 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);
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
#include "core/rules.h"
|
#include "core/rules.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <zdwm/types.h>
|
||||||
|
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
|
|
||||||
@@ -35,3 +39,43 @@ void rules_cleanup(rules_t *rules) {
|
|||||||
rules->capacity = 0;
|
rules->capacity = 0;
|
||||||
rules->count = 0;
|
rules->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
return str_match(match->app_id, meta->app_id) &&
|
||||||
|
str_match(match->role, meta->role) &&
|
||||||
|
str_match(match->class_name, meta->class_name) &&
|
||||||
|
str_match(match->instance_name, meta->instance_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rule_action_merge(const rule_action_t *src, rule_action_t *dest) {
|
||||||
|
if (!src || !dest) return;
|
||||||
|
|
||||||
|
if (src->workspace != ZDWM_WORKSPACE_ID_INVALID) {
|
||||||
|
dest->workspace = src->workspace;
|
||||||
|
}
|
||||||
|
dest->switch_to_workspace |= src->switch_to_workspace;
|
||||||
|
dest->fullscreen |= src->fullscreen;
|
||||||
|
dest->maximize |= src->maximize;
|
||||||
|
dest->floating |= src->floating;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < rules->count; ++i) {
|
||||||
|
if (!rule_match_window(&rules->items[i].match, metadata)) continue;
|
||||||
|
|
||||||
|
matched = true;
|
||||||
|
rule_action_merge(&rules->items[i].action, action_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
|
#include "core/window.h"
|
||||||
|
|
||||||
typedef struct rule_item_t {
|
typedef struct rule_item_t {
|
||||||
rule_match_t match;
|
rule_match_t match;
|
||||||
@@ -15,5 +16,8 @@ typedef struct rules_t {
|
|||||||
size_t capacity;
|
size_t capacity;
|
||||||
} rules_t;
|
} rules_t;
|
||||||
|
|
||||||
bool rules_move(rules_t *dest, rules_t *src);
|
bool rules_move(rules_t *src, rules_t *dest);
|
||||||
void rules_cleanup(rules_t *rules);
|
void rules_cleanup(rules_t *rules);
|
||||||
|
|
||||||
|
bool rules_resolve(const rules_t *rules, const window_metadata_t *metadata,
|
||||||
|
rule_action_t *action_out);
|
||||||
|
|||||||
@@ -4,8 +4,11 @@
|
|||||||
|
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/backend.h"
|
#include "core/backend.h"
|
||||||
|
#include "core/command_buffer.h"
|
||||||
#include "core/event.h"
|
#include "core/event.h"
|
||||||
#include "core/layout.h"
|
#include "core/layout.h"
|
||||||
|
#include "core/plan.h"
|
||||||
|
#include "core/policy.h"
|
||||||
#include "core/rules.h"
|
#include "core/rules.h"
|
||||||
#include "core/state.h"
|
#include "core/state.h"
|
||||||
#include "core/wm_desc.h"
|
#include "core/wm_desc.h"
|
||||||
@@ -82,6 +85,8 @@ void runtime_init_desc_cleanup(runtime_init_desc_t *desc) {
|
|||||||
|
|
||||||
void runtime_shutdown(runtime_t *runtime) {
|
void runtime_shutdown(runtime_t *runtime) {
|
||||||
runtime->running = false;
|
runtime->running = false;
|
||||||
|
plan_cleanup(&runtime->plan);
|
||||||
|
command_buffer_cleanup(&runtime->command_buffer);
|
||||||
layout_registry_cleanup(&runtime->layouts);
|
layout_registry_cleanup(&runtime->layouts);
|
||||||
rules_cleanup(&runtime->rules);
|
rules_cleanup(&runtime->rules);
|
||||||
state_cleanup(&runtime->state);
|
state_cleanup(&runtime->state);
|
||||||
@@ -92,10 +97,29 @@ void runtime_shutdown(runtime_t *runtime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void runtime_run(runtime_t *runtime) {
|
void runtime_run(runtime_t *runtime) {
|
||||||
for (;;) {
|
runtime->running = true;
|
||||||
|
|
||||||
|
backend_t *backend = runtime->backend;
|
||||||
|
command_buffer_t *command_buffer = &runtime->command_buffer;
|
||||||
|
plan_t *plan = &runtime->plan;
|
||||||
|
|
||||||
|
while (runtime->running) {
|
||||||
event_t event = {0};
|
event_t event = {0};
|
||||||
if (!backend_next_event(runtime->backend, &event)) {
|
if (!backend_next_event(backend, &event)) break;
|
||||||
break;
|
|
||||||
}
|
command_buffer_reset(command_buffer);
|
||||||
|
plan_reset(plan);
|
||||||
|
|
||||||
|
policy_context_t ctx = {
|
||||||
|
.state = &runtime->state,
|
||||||
|
.rules = &runtime->rules,
|
||||||
|
.event = &event,
|
||||||
|
};
|
||||||
|
|
||||||
|
policy_route_event(&ctx, command_buffer);
|
||||||
|
policy_apply_command(&ctx, command_buffer, plan);
|
||||||
|
if (plan->count) backend_apply_effect(backend, plan->effects, plan->count);
|
||||||
|
|
||||||
|
event_cleanup(&event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "core/backend.h"
|
#include "core/backend.h"
|
||||||
|
#include "core/command_buffer.h"
|
||||||
#include "core/layout.h"
|
#include "core/layout.h"
|
||||||
|
#include "core/plan.h"
|
||||||
#include "core/rules.h"
|
#include "core/rules.h"
|
||||||
#include "core/state.h"
|
#include "core/state.h"
|
||||||
|
|
||||||
@@ -23,6 +25,8 @@ typedef struct runtime_t {
|
|||||||
bool running;
|
bool running;
|
||||||
bool will_restart;
|
bool will_restart;
|
||||||
|
|
||||||
|
plan_t plan;
|
||||||
|
command_buffer_t command_buffer;
|
||||||
state_t state;
|
state_t state;
|
||||||
layout_registry_t layouts;
|
layout_registry_t layouts;
|
||||||
rules_t rules;
|
rules_t rules;
|
||||||
|
|||||||
@@ -41,8 +41,12 @@ add_executable(${RUNTIME_CONFIG_TEST_APP_NAME}
|
|||||||
${SOURCE_DIR}/config/defaults.c
|
${SOURCE_DIR}/config/defaults.c
|
||||||
${SOURCE_DIR}/config/loader.c
|
${SOURCE_DIR}/config/loader.c
|
||||||
${SOURCE_DIR}/config/runtime_config.c
|
${SOURCE_DIR}/config/runtime_config.c
|
||||||
|
${SOURCE_DIR}/core/command_buffer.c
|
||||||
|
${SOURCE_DIR}/core/event.c
|
||||||
${SOURCE_DIR}/core/layer.c
|
${SOURCE_DIR}/core/layer.c
|
||||||
${SOURCE_DIR}/core/layout.c
|
${SOURCE_DIR}/core/layout.c
|
||||||
|
${SOURCE_DIR}/core/plan.c
|
||||||
|
${SOURCE_DIR}/core/policy.c
|
||||||
${SOURCE_DIR}/core/rules.c
|
${SOURCE_DIR}/core/rules.c
|
||||||
${SOURCE_DIR}/core/runtime.c
|
${SOURCE_DIR}/core/runtime.c
|
||||||
${SOURCE_DIR}/core/state.c
|
${SOURCE_DIR}/core/state.c
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ bool backend_next_event(backend_t *backend, event_t *event) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool backend_apply_effect(backend_t *backend, const effect_t *effects,
|
||||||
|
size_t effect_count) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static backend_t *test_backend_create(void) {
|
static backend_t *test_backend_create(void) {
|
||||||
return calloc(1, sizeof(backend_t));
|
return calloc(1, sizeof(backend_t));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,12 @@ add_executable(${TEST_APP_NAME}
|
|||||||
${SOURCE_DIR}/backend/x11/backend.c
|
${SOURCE_DIR}/backend/x11/backend.c
|
||||||
${SOURCE_DIR}/backend/x11/event.c
|
${SOURCE_DIR}/backend/x11/event.c
|
||||||
${SOURCE_DIR}/backend/x11/window.c
|
${SOURCE_DIR}/backend/x11/window.c
|
||||||
|
${SOURCE_DIR}/core/command_buffer.c
|
||||||
|
${SOURCE_DIR}/core/event.c
|
||||||
${SOURCE_DIR}/core/layer.c
|
${SOURCE_DIR}/core/layer.c
|
||||||
${SOURCE_DIR}/core/layout.c
|
${SOURCE_DIR}/core/layout.c
|
||||||
|
${SOURCE_DIR}/core/plan.c
|
||||||
|
${SOURCE_DIR}/core/policy.c
|
||||||
${SOURCE_DIR}/core/rules.c
|
${SOURCE_DIR}/core/rules.c
|
||||||
${SOURCE_DIR}/core/runtime.c
|
${SOURCE_DIR}/core/runtime.c
|
||||||
${SOURCE_DIR}/core/state.c
|
${SOURCE_DIR}/core/state.c
|
||||||
|
|||||||
Reference in New Issue
Block a user