feat(core/policy): 实现 policy_apply_command 命令分发功能
This commit is contained in:
@@ -11,7 +11,6 @@ typedef enum command_type_t {
|
|||||||
typedef struct manage_window_command_t {
|
typedef struct manage_window_command_t {
|
||||||
workspace_id_t workspace;
|
workspace_id_t workspace;
|
||||||
bool floating;
|
bool floating;
|
||||||
bool switch_to_workspace;
|
|
||||||
window_info_t info;
|
window_info_t info;
|
||||||
} manage_window_command_t;
|
} manage_window_command_t;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ typedef uint32_t dirty_mask_t;
|
|||||||
|
|
||||||
typedef enum dirty_flags_t : dirty_mask_t {
|
typedef enum dirty_flags_t : dirty_mask_t {
|
||||||
ZDWM_DIRTY_NONE = 0,
|
ZDWM_DIRTY_NONE = 0,
|
||||||
ZDWM_DIRTY_LAYOUT = 1u << 0,
|
ZDWM_DIRTY_LAYOUT = 1u << 0, /* 需要重新计算布局 */
|
||||||
|
ZDWM_DIRTY_OUTPUT = 1u << 1, /* 当前 output 有变更 */
|
||||||
} dirty_flags_t;
|
} dirty_flags_t;
|
||||||
|
|
||||||
typedef enum effect_type_t {
|
typedef enum effect_type_t {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "core/policy.h"
|
#include "core/policy.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <zdwm/types.h>
|
#include <zdwm/types.h>
|
||||||
|
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
@@ -7,6 +8,7 @@
|
|||||||
#include "core/command_buffer.h"
|
#include "core/command_buffer.h"
|
||||||
#include "core/event.h"
|
#include "core/event.h"
|
||||||
#include "core/layer.h"
|
#include "core/layer.h"
|
||||||
|
#include "core/plan.h"
|
||||||
#include "core/rules.h"
|
#include "core/rules.h"
|
||||||
#include "core/state.h"
|
#include "core/state.h"
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
@@ -98,24 +100,86 @@ bool policy_route_event(
|
|||||||
const event_t *event,
|
const event_t *event,
|
||||||
command_buffer_t *out
|
command_buffer_t *out
|
||||||
) {
|
) {
|
||||||
|
auto state = ctx->state;
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case ZDWM_EVENT_WINDOW_MAP_REQUEST:
|
case ZDWM_EVENT_WINDOW_MAP_REQUEST: {
|
||||||
return route_map_request(
|
auto rules = ctx->rules;
|
||||||
ctx->state,
|
return route_map_request(state, rules, &event->as.window_map_request, out);
|
||||||
ctx->rules,
|
}
|
||||||
&event->as.window_map_request,
|
|
||||||
out
|
|
||||||
);
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool manage_window(
|
||||||
|
const policy_context_t *ctx,
|
||||||
|
const manage_window_command_t *command,
|
||||||
|
plan_t *plan
|
||||||
|
) {
|
||||||
|
auto state = ctx->state;
|
||||||
|
auto window = state_window_add(state, &command->info);
|
||||||
|
auto window_id = window->id;
|
||||||
|
state_window_set_workspace(state, window_id, command->workspace);
|
||||||
|
state_window_set_floating(state, window_id, command->floating);
|
||||||
|
|
||||||
|
if (!state_workspace_show(state, command->workspace)) return false;
|
||||||
|
|
||||||
|
effect_t map_effect = {
|
||||||
|
.type = ZDWM_EFFECT_MAP_WINDOW,
|
||||||
|
.as.map.window = window_id,
|
||||||
|
};
|
||||||
|
plan_push_effect(plan, &map_effect);
|
||||||
|
|
||||||
|
if (window_need_layout(window)) {
|
||||||
|
plan->dirty_flags |= ZDWM_DIRTY_LAYOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool switch_workspace(
|
||||||
|
const state_t *state,
|
||||||
|
const switch_workspace_command_t *command,
|
||||||
|
plan_t *plan
|
||||||
|
) {
|
||||||
|
auto output_id = command->output;
|
||||||
|
auto workspace_id = command->workspace;
|
||||||
|
|
||||||
|
if (state_output_set_current_workspace(state, output_id, workspace_id)) {
|
||||||
|
plan->dirty_flags |= ZDWM_DIRTY_LAYOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state_set_current_output(state, output_id)) {
|
||||||
|
plan->dirty_flags |= ZDWM_DIRTY_OUTPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: 后续考虑加上 ewmh 相关副作用 */
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool policy_apply_command(
|
bool policy_apply_command(
|
||||||
const policy_context_t *ctx,
|
const policy_context_t *ctx,
|
||||||
const command_buffer_t *command_buffer,
|
const command_buffer_t *command_buffer,
|
||||||
plan_t *plan
|
plan_t *plan
|
||||||
) {
|
) {
|
||||||
/* TODO: */
|
bool has_effect = false;
|
||||||
return true;
|
auto state = ctx->state;
|
||||||
|
for (size_t i = 0; i < command_buffer->count; ++i) {
|
||||||
|
auto cmd = &command_buffer->items[i];
|
||||||
|
switch (cmd->type) {
|
||||||
|
case ZDWM_COMMAND_MANAGE_WINDOW:
|
||||||
|
if (manage_window(ctx, &cmd->as.manage_window, plan)) {
|
||||||
|
has_effect = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ZDWM_COMMAND_SWITCH_WORKSPACE:
|
||||||
|
if (switch_workspace(state, &cmd->as.switch_workspace, plan)) {
|
||||||
|
has_effect = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return has_effect;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include "core/state.h"
|
#include "core/state.h"
|
||||||
|
|
||||||
typedef struct policy_context_t {
|
typedef struct policy_context_t {
|
||||||
const state_t *state;
|
state_t *state;
|
||||||
const rules_t *rules;
|
const rules_t *rules;
|
||||||
} policy_context_t;
|
} policy_context_t;
|
||||||
|
|
||||||
|
|||||||
@@ -237,6 +237,12 @@ bool state_workspace_valid(const state_t *state, workspace_id_t id) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool state_workspace_show(const state_t *state, workspace_id_t workspace_id) {
|
||||||
|
auto workspace = state_workspace_get(state, workspace_id);
|
||||||
|
auto output = state_output_get(state, workspace->output_id);
|
||||||
|
return output->current_workspace_id == workspace_id;
|
||||||
|
}
|
||||||
|
|
||||||
const output_t *state_output_get(const state_t *state, output_id_t id) {
|
const output_t *state_output_get(const state_t *state, output_id_t id) {
|
||||||
if (id < state->output_count) return &state->outputs[id];
|
if (id < state->output_count) return &state->outputs[id];
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -256,17 +262,20 @@ void state_output_set_workarea(
|
|||||||
if (output) output->workarea = workarea;
|
if (output) output->workarea = workarea;
|
||||||
}
|
}
|
||||||
|
|
||||||
void state_output_set_current_workspace(
|
bool state_output_set_current_workspace(
|
||||||
state_t *state,
|
state_t *state,
|
||||||
output_id_t output_id,
|
output_id_t output_id,
|
||||||
workspace_id_t workspace_id
|
workspace_id_t workspace_id
|
||||||
) {
|
) {
|
||||||
output_t *output = (output_t *)state_output_get(state, output_id);
|
output_t *output = (output_t *)state_output_get(state, output_id);
|
||||||
if (!output) return;
|
if (!output) return false;
|
||||||
const workspace_t *workspace = state_workspace_get(state, workspace_id);
|
const workspace_t *workspace = state_workspace_get(state, workspace_id);
|
||||||
if (!workspace || workspace->output_id != output_id) return;
|
if (!workspace || workspace->output_id != output_id) return false;
|
||||||
|
|
||||||
|
if (output->current_workspace_id == workspace_id) return false;
|
||||||
|
|
||||||
output->current_workspace_id = workspace_id;
|
output->current_workspace_id = workspace_id;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t state_output_count(const state_t *state) { return state->output_count; }
|
size_t state_output_count(const state_t *state) { return state->output_count; }
|
||||||
@@ -294,6 +303,21 @@ void state_cycle_current_output(state_t *state, int delta) {
|
|||||||
state->current_output_index = (size_t)next;
|
state->current_output_index = (size_t)next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool state_set_current_output(state_t *state, output_id_t output_id) {
|
||||||
|
for (size_t i = 0; i < state->output_count; ++i) {
|
||||||
|
auto output = &state->outputs[i];
|
||||||
|
if (output->id != output_id) continue;
|
||||||
|
|
||||||
|
if (i == state->current_output_index) return false;
|
||||||
|
|
||||||
|
state->current_output_index = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
warn("state_set_current_output: invalid output_id %u", output_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void window_set_geometry_mode(
|
static inline void window_set_geometry_mode(
|
||||||
window_t *window,
|
window_t *window,
|
||||||
window_geometry_mode_t geometry_mode
|
window_geometry_mode_t geometry_mode
|
||||||
@@ -634,3 +658,19 @@ bool state_stack_lower(state_t *state, window_id_t window_id) {
|
|||||||
|
|
||||||
return layer_stack_lower(layer, window_id);
|
return layer_stack_lower(layer, window_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool window_need_layout(const window_t *window) {
|
||||||
|
if (window->sticky || window->floating) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (window->geometry_mode) {
|
||||||
|
case ZDWM_GEOMETRY_FULLSCREEN:
|
||||||
|
case ZDWM_GEOMETRY_MAXIMIZED:
|
||||||
|
case ZDWM_GEOMETRY_MINIMIZED:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -126,6 +126,14 @@ void state_workspace_set_focused_window(
|
|||||||
size_t state_workspace_count(const state_t *state);
|
size_t state_workspace_count(const state_t *state);
|
||||||
bool state_workspace_valid(const state_t *state, workspace_id_t id);
|
bool state_workspace_valid(const state_t *state, workspace_id_t id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 当前 workspace 是否显示
|
||||||
|
*
|
||||||
|
* @return 若 workspace_id 代表的 workspace 是其所属的 output 当前显示的
|
||||||
|
* workspace 则返回 true ,否则返回 false
|
||||||
|
*/
|
||||||
|
bool state_workspace_show(const state_t *state, workspace_id_t workspace_id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* state 持有的 output 集合接口
|
* state 持有的 output 集合接口
|
||||||
*
|
*
|
||||||
@@ -139,7 +147,16 @@ void state_output_set_workarea(
|
|||||||
output_id_t output_id,
|
output_id_t output_id,
|
||||||
rect_t workarea
|
rect_t workarea
|
||||||
);
|
);
|
||||||
void state_output_set_current_workspace(
|
/**
|
||||||
|
* @brief 设置 output 的当前 workspace
|
||||||
|
*
|
||||||
|
* @param state 状态实例指针
|
||||||
|
* @param output_id 需要切换的当前 workspace 的 output 的 id
|
||||||
|
* @param workspace_id 目标 workspace 的 id
|
||||||
|
*
|
||||||
|
* @return 若 workspace 需要切换返回 true ,否则返回 false
|
||||||
|
*/
|
||||||
|
bool state_output_set_current_workspace(
|
||||||
state_t *state,
|
state_t *state,
|
||||||
output_id_t output_id,
|
output_id_t output_id,
|
||||||
workspace_id_t workspace_id
|
workspace_id_t workspace_id
|
||||||
@@ -147,6 +164,15 @@ void state_output_set_current_workspace(
|
|||||||
size_t state_output_count(const state_t *state);
|
size_t state_output_count(const state_t *state);
|
||||||
bool state_output_valid(const state_t *state, output_id_t id);
|
bool state_output_valid(const state_t *state, output_id_t id);
|
||||||
void state_cycle_current_output(state_t *state, int delta);
|
void state_cycle_current_output(state_t *state, int delta);
|
||||||
|
/**
|
||||||
|
* @brief 设置当前 output
|
||||||
|
*
|
||||||
|
* @param state 状态实例指针
|
||||||
|
* @param output_id 目标 output 的 id
|
||||||
|
*
|
||||||
|
* @return 有变更返回 true ,无变更返回 false
|
||||||
|
*/
|
||||||
|
bool state_set_current_output(state_t *state, output_id_t output_id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* state 持有的 window 集合接口
|
* state 持有的 window 集合接口
|
||||||
@@ -262,3 +288,8 @@ bool state_window_set_instance(
|
|||||||
|
|
||||||
bool state_stack_raise(state_t *state, window_id_t window_id);
|
bool state_stack_raise(state_t *state, window_id_t window_id);
|
||||||
bool state_stack_lower(state_t *state, window_id_t window_id);
|
bool state_stack_lower(state_t *state, window_id_t window_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 窗口是否需要参与布局计算
|
||||||
|
*/
|
||||||
|
bool window_need_layout(const window_t *window);
|
||||||
|
|||||||
Reference in New Issue
Block a user