feat(action): 实现 focus_window 窗口焦点切换及 raise 命令

This commit is contained in:
2026-05-07 07:20:27 +08:00
parent 9275d14c5f
commit a60d9f31a7
7 changed files with 85 additions and 0 deletions

View File

@@ -36,6 +36,7 @@ typedef struct zdwm_action_api_t {
); );
void (*cycle_layout)(zdwm_runtime_t *runtime, int32_t delta); void (*cycle_layout)(zdwm_runtime_t *runtime, int32_t delta);
void (*cycle_current_output)(zdwm_runtime_t *runtime, int32_t delta); void (*cycle_current_output)(zdwm_runtime_t *runtime, int32_t delta);
void (*focus_window)(zdwm_runtime_t *runtime, int32_t delta);
} zdwm_action_api_t; } zdwm_action_api_t;
typedef void zdwm_action_fn( typedef void zdwm_action_fn(

View File

@@ -67,6 +67,14 @@ static void toggle_floating(
api->toggle_floating(runtime); api->toggle_floating(runtime);
} }
static void focus_window(
zdwm_runtime_t *runtime,
const zdwm_action_api_t *api,
const zdwm_action_arg_t *arg
) {
api->focus_window(runtime, arg->i);
}
bool config_defaults_build( bool config_defaults_build(
const zdwm_api_t *api, const zdwm_api_t *api,
zdwm_config_builder_t *builder, zdwm_config_builder_t *builder,
@@ -143,6 +151,8 @@ bool config_defaults_build(
BIND(default_mode, Super "+f", toggle_fullscreen, {0}); BIND(default_mode, Super "+f", toggle_fullscreen, {0});
BIND(default_mode, Super "+m", toggle_maximize, {0}); BIND(default_mode, Super "+m", toggle_maximize, {0});
BIND(default_mode, Super "+Control+space", toggle_floating, {0}); BIND(default_mode, Super "+Control+space", toggle_floating, {0});
BIND(default_mode, Alt "+j", focus_window, {.i = 1});
BIND(default_mode, Alt "+k", focus_window, {.i = -1});
#undef BIND #undef BIND

View File

@@ -177,3 +177,50 @@ void cycle_current_output(runtime_t *runtime, int32_t delta) {
auto state = &runtime->state; auto state = &runtime->state;
state_cycle_current_output(state, delta); state_cycle_current_output(state, delta);
} }
void focus_window(runtime_t *runtime, int32_t delta) {
auto state = &runtime->state;
auto output = state_output_at(state, state->current_output_index);
auto workspace = state_workspace_get(state, output->current_workspace_id);
size_t count = state_window_count(state);
if (!count) return;
size_t indices[count];
size_t num = 0;
for (size_t i = 0; i < count; ++i) {
auto window = state_window_at(state, i);
if (window->workspace_id == workspace->id) {
indices[num++] = i;
}
}
if (!num) return;
size_t current = 0;
if (!window_id_invalid(workspace->focused_window_id)) {
for (size_t i = 0; i < num; ++i) {
auto window = state_window_at(state, indices[i]);
if (window->id == workspace->focused_window_id) {
current = i;
break;
}
}
}
int64_t next = ((int64_t)current + (int64_t)delta) % (int64_t)num;
if (next < 0) next += (int64_t)num;
auto target = state_window_at(state, indices[next]);
command_t focus_cmd = {
.type = ZDWM_COMMAND_FOCUS_WINDOW,
.as.focus.window = target->id,
};
command_buffer_push(&runtime->command_buffer, &focus_cmd);
command_t raise_cmd = {
.type = ZDWM_COMMAND_RAISE_WINDOW,
.as.raise.window = target->id,
};
command_buffer_push(&runtime->command_buffer, &raise_cmd);
}

View File

@@ -21,3 +21,4 @@ void switch_workspace(
); );
void cycle_layout(zdwm_runtime_t *runtime, int32_t delta); void cycle_layout(zdwm_runtime_t *runtime, int32_t delta);
void cycle_current_output(zdwm_runtime_t *runtime, int32_t delta); void cycle_current_output(zdwm_runtime_t *runtime, int32_t delta);
void focus_window(zdwm_runtime_t *runtime, int32_t delta);

View File

@@ -8,6 +8,7 @@ typedef enum command_type_t {
ZDWM_COMMAND_UNMANAGE_WINDOW, ZDWM_COMMAND_UNMANAGE_WINDOW,
ZDWM_COMMAND_FOCUS_WINDOW, ZDWM_COMMAND_FOCUS_WINDOW,
ZDWM_COMMAND_KILL_WINDOW, ZDWM_COMMAND_KILL_WINDOW,
ZDWM_COMMAND_RAISE_WINDOW,
ZDWM_COMMAND_WITHDRAW_WINDOW, ZDWM_COMMAND_WITHDRAW_WINDOW,
ZDWM_COMMAND_CONFIGURE_WINDOW, ZDWM_COMMAND_CONFIGURE_WINDOW,
ZDWM_COMMAND_CHANGE_WINDOW_STATE, ZDWM_COMMAND_CHANGE_WINDOW_STATE,
@@ -56,6 +57,7 @@ typedef struct command_t {
only_window_data_t unmanage; only_window_data_t unmanage;
only_window_data_t focus; only_window_data_t focus;
only_window_data_t kill; only_window_data_t kill;
only_window_data_t raise;
only_window_data_t withdraw; only_window_data_t withdraw;
configure_data_t configure; configure_data_t configure;
window_state_change_command_t state_change; window_state_change_command_t state_change;

View File

@@ -476,6 +476,26 @@ static void kill_window(state_t *state, window_id_t window, plan_t *plan) {
plan_push_kill_effect(plan, window); plan_push_kill_effect(plan, window);
} }
static void raise_window(state_t *state, window_id_t window, plan_t *plan) {
if (!state_stack_raise(state, window)) return;
window_list_t list = {0};
for (size_t i = 0; i < countof(state->stacks); ++i) {
for (size_t j = 0; j < state->stacks[i].count; ++j) {
auto window_id = state->stacks[i].order[j];
window_list_push(&list, window_id);
}
}
effect_t restack_windows_effect = {
.type = ZDWM_EFFECT_RESTACK_WINDOWS,
.as.restack_windows = {
.windows = list.windows,
.count = list.count,
},
};
plan_push_effect(plan, &restack_windows_effect);
}
static void withdraw_window(state_t *state, window_id_t window, plan_t *plan) { static void withdraw_window(state_t *state, window_id_t window, plan_t *plan) {
auto win = state_window_get(state, window); auto win = state_window_get(state, window);
if (!win) return; if (!win) return;
@@ -846,6 +866,9 @@ void policy_apply_command(
case ZDWM_COMMAND_KILL_WINDOW: case ZDWM_COMMAND_KILL_WINDOW:
kill_window(state, cmd->as.kill.window, plan); kill_window(state, cmd->as.kill.window, plan);
break; break;
case ZDWM_COMMAND_RAISE_WINDOW:
raise_window(state, cmd->as.raise.window, plan);
break;
case ZDWM_COMMAND_WITHDRAW_WINDOW: case ZDWM_COMMAND_WITHDRAW_WINDOW:
withdraw_window(state, cmd->as.withdraw.window, plan); withdraw_window(state, cmd->as.withdraw.window, plan);
break; break;

View File

@@ -276,6 +276,7 @@ policy_context_t policy_context_init(runtime_t *runtime) {
.switch_workspace = switch_workspace, .switch_workspace = switch_workspace,
.cycle_layout = cycle_layout, .cycle_layout = cycle_layout,
.cycle_current_output = cycle_current_output, .cycle_current_output = cycle_current_output,
.focus_window = focus_window,
}, },
}; };
return ctx; return ctx;