feat(policy): 扩展命令并实现窗口迁移、 output/layout/binding_mode 切换功能
- command.h 新增 SEND_TO_WORKSPACE、SET_CURRENT_OUTPUT、SET_LAYOUT、SET_BINDING_MODE 四个命令类型及载荷 - policy.c 实现对应的 apply 逻辑,包含焦点转移、映射/取消映射副作用和 listener 通知 - plan.h 增加 quit/will_restart 标志,为后续优雅退出做准备 - binding.c 对重复设置同一 mode 增加短路返回
This commit is contained in:
@@ -225,7 +225,7 @@ bool binding_table_set_current_mode(
|
||||
binding_table_t *table,
|
||||
zdwm_binding_mode_id_t mode_id
|
||||
) {
|
||||
if (mode_id >= table->count) return false;
|
||||
if (mode_id >= table->count || mode_id == table->current_mode) return false;
|
||||
|
||||
table->current_mode = mode_id;
|
||||
return true;
|
||||
|
||||
@@ -12,12 +12,16 @@ typedef enum command_type_t {
|
||||
ZDWM_COMMAND_WITHDRAW_WINDOW,
|
||||
ZDWM_COMMAND_CONFIGURE_WINDOW,
|
||||
ZDWM_COMMAND_CHANGE_WINDOW_STATE,
|
||||
ZDWM_COMMAND_WINDOW_SEND_TO_WORKSPACE,
|
||||
ZDWM_COMMAND_WINDOW_SET_FLOATING,
|
||||
ZDWM_COMMAND_WINDOW_SET_STICKY,
|
||||
ZDWM_COMMAND_WINDOW_SET_MINIMIZED,
|
||||
ZDWM_COMMAND_WINDOW_SET_MAXIMIZED,
|
||||
ZDWM_COMMAND_WINDOW_SET_FULLSCREEN,
|
||||
ZDWM_COMMAND_SWITCH_WORKSPACE,
|
||||
ZDWM_COMMAND_SET_CURRENT_OUTPUT,
|
||||
ZDWM_COMMAND_SET_LAYOUT,
|
||||
ZDWM_COMMAND_SET_BINDING_MODE,
|
||||
} command_type_t;
|
||||
|
||||
typedef struct manage_window_command_t {
|
||||
@@ -36,11 +40,30 @@ typedef struct window_state_change_command_t {
|
||||
window_state_request_action_t action;
|
||||
} window_state_change_command_t;
|
||||
|
||||
typedef struct window_send_to_workspace_command_t {
|
||||
window_id_t window;
|
||||
workspace_id_t workspace;
|
||||
} window_send_to_workspace_command_t;
|
||||
|
||||
typedef struct window_bool_state_t {
|
||||
window_id_t window;
|
||||
bool state;
|
||||
} window_bool_state_t;
|
||||
|
||||
typedef struct set_current_output_command_t {
|
||||
output_id_t output;
|
||||
} set_current_output_command_t;
|
||||
|
||||
typedef struct set_layout_command_t {
|
||||
workspace_id_t workspace;
|
||||
layout_id_t layout;
|
||||
} set_layout_command_t;
|
||||
|
||||
typedef struct set_binding_mode_command_t {
|
||||
zdwm_binding_mode_id_t mode;
|
||||
} set_binding_mode_command_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 非 owning 的命令值对象
|
||||
* @details
|
||||
@@ -61,11 +84,15 @@ typedef struct command_t {
|
||||
only_window_data_t withdraw;
|
||||
configure_data_t configure;
|
||||
window_state_change_command_t state_change;
|
||||
window_send_to_workspace_command_t send_to_workspace;
|
||||
window_bool_state_t floating;
|
||||
window_bool_state_t sticky;
|
||||
window_bool_state_t minimized;
|
||||
window_bool_state_t maximized;
|
||||
window_bool_state_t fullscreen;
|
||||
switch_workspace_command_t switch_workspace;
|
||||
set_current_output_command_t current_output;
|
||||
set_layout_command_t layout;
|
||||
set_binding_mode_command_t binding_mode;
|
||||
} as;
|
||||
} command_t;
|
||||
|
||||
@@ -77,6 +77,8 @@ typedef struct plan_t {
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
bool need_relayout;
|
||||
bool quit;
|
||||
bool will_restart;
|
||||
} plan_t;
|
||||
|
||||
void plan_reset(plan_t *plan);
|
||||
|
||||
@@ -788,6 +788,82 @@ static void change_window_state(
|
||||
}
|
||||
}
|
||||
|
||||
static void send_window_to_workspace(
|
||||
const policy_context_t *ctx,
|
||||
const window_send_to_workspace_command_t *command,
|
||||
plan_t *plan
|
||||
) {
|
||||
auto state = ctx->state;
|
||||
auto window = state_window_get(state, command->window);
|
||||
if (!window) return;
|
||||
if (!state_workspace_valid(state, command->workspace)) return;
|
||||
if (window->workspace_id == command->workspace) return;
|
||||
|
||||
workspace_id_t src_workspace_id = window->workspace_id;
|
||||
bool src_visible = state_workspace_show(state, src_workspace_id);
|
||||
bool dst_visible = state_workspace_show(state, command->workspace);
|
||||
|
||||
const workspace_t *src_ws = state_workspace_get(state, src_workspace_id);
|
||||
window_id_t src_old_focused =
|
||||
src_ws ? src_ws->focused_window_id : ZDWM_WINDOW_ID_INVALID;
|
||||
|
||||
state_window_set_workspace(state, command->window, command->workspace);
|
||||
|
||||
if (!window->sticky) {
|
||||
if (src_visible) plan_push_unmap_effect(plan, command->window);
|
||||
if (dst_visible) plan_push_map_effect(plan, command->window);
|
||||
}
|
||||
|
||||
if (src_visible) {
|
||||
if (src_ws && src_ws->focused_window_id != src_old_focused) {
|
||||
if (!window_id_invalid(src_old_focused) &&
|
||||
state_window_get(state, src_old_focused)) {
|
||||
plan_push_change_border_color_effect(
|
||||
plan,
|
||||
src_old_focused,
|
||||
&ctx->border->normal_color
|
||||
);
|
||||
}
|
||||
if (!window_id_invalid(src_ws->focused_window_id) &&
|
||||
state_window_get(state, src_ws->focused_window_id)) {
|
||||
plan_push_focus_effect(plan, src_ws->focused_window_id);
|
||||
plan_push_change_border_color_effect(
|
||||
plan,
|
||||
src_ws->focused_window_id,
|
||||
&ctx->border->focused_color
|
||||
);
|
||||
}
|
||||
}
|
||||
adjust_layout_windows_border_width(
|
||||
state,
|
||||
ctx->border->width,
|
||||
src_workspace_id
|
||||
);
|
||||
}
|
||||
|
||||
if (dst_visible) {
|
||||
set_foucs_window(ctx, command->workspace, command->window, plan);
|
||||
adjust_layout_windows_border_width(
|
||||
state,
|
||||
ctx->border->width,
|
||||
command->workspace
|
||||
);
|
||||
}
|
||||
|
||||
plan->need_relayout = true;
|
||||
|
||||
auto listeners = ctx->listeners;
|
||||
listeners_notify_window_updated(listeners, state, command->window);
|
||||
if (src_ws && src_ws->focused_window_id != src_old_focused &&
|
||||
!window_id_invalid(src_ws->focused_window_id)) {
|
||||
listeners_notify_window_updated(
|
||||
listeners,
|
||||
state,
|
||||
src_ws->focused_window_id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void command_window_set_floating(
|
||||
const policy_context_t *ctx,
|
||||
const window_bool_state_t *data,
|
||||
@@ -855,6 +931,37 @@ switch_workspace(state_t *state, workspace_id_t workspace_id, plan_t *plan) {
|
||||
state_set_current_output(state, output_id);
|
||||
}
|
||||
|
||||
static void set_current_output(
|
||||
const policy_context_t *ctx,
|
||||
const set_current_output_command_t *command
|
||||
) {
|
||||
if (!state_set_current_output(ctx->state, command->output)) return;
|
||||
listeners_notify_current_output(ctx->listeners, command->output);
|
||||
}
|
||||
|
||||
static void set_layout(
|
||||
const policy_context_t *ctx,
|
||||
const set_layout_command_t *command,
|
||||
plan_t *plan
|
||||
) {
|
||||
auto state = ctx->state;
|
||||
auto workspace_id = command->workspace;
|
||||
auto layout_id = command->layout;
|
||||
|
||||
if (!state_workspace_set_layout_by_id(state, workspace_id, layout_id)) return;
|
||||
|
||||
plan->need_relayout = true;
|
||||
listeners_notify_layout(ctx->listeners, ctx->layouts, workspace_id, layout_id);
|
||||
}
|
||||
|
||||
static void set_binding_mode(
|
||||
const policy_context_t *ctx,
|
||||
zdwm_binding_mode_id_t binding_mode
|
||||
) {
|
||||
if (!binding_table_set_current_mode(ctx->bind_table, binding_mode)) return;
|
||||
listeners_notify_binding_mode(ctx->listeners, ctx->bind_table);
|
||||
}
|
||||
|
||||
void policy_apply_command(
|
||||
const policy_context_t *ctx,
|
||||
const command_buffer_t *command_buffer,
|
||||
@@ -888,6 +995,9 @@ void policy_apply_command(
|
||||
case ZDWM_COMMAND_CHANGE_WINDOW_STATE:
|
||||
change_window_state(ctx, &cmd->as.state_change, plan);
|
||||
break;
|
||||
case ZDWM_COMMAND_WINDOW_SEND_TO_WORKSPACE:
|
||||
send_window_to_workspace(ctx, &cmd->as.send_to_workspace, plan);
|
||||
break;
|
||||
case ZDWM_COMMAND_WINDOW_SET_FLOATING:
|
||||
command_window_set_floating(ctx, &cmd->as.floating, plan);
|
||||
break;
|
||||
@@ -906,6 +1016,15 @@ void policy_apply_command(
|
||||
case ZDWM_COMMAND_SWITCH_WORKSPACE:
|
||||
switch_workspace(state, cmd->as.switch_workspace.workspace, plan);
|
||||
break;
|
||||
case ZDWM_COMMAND_SET_CURRENT_OUTPUT:
|
||||
set_current_output(ctx, &cmd->as.current_output);
|
||||
break;
|
||||
case ZDWM_COMMAND_SET_LAYOUT:
|
||||
set_layout(ctx, &cmd->as.layout, plan);
|
||||
break;
|
||||
case ZDWM_COMMAND_SET_BINDING_MODE:
|
||||
set_binding_mode(ctx, cmd->as.binding_mode.mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user