feat: 添加 MOD4 + 鼠标右键调整窗口大小功能

This commit is contained in:
2026-06-22 00:48:14 +08:00
parent 4e7ab45864
commit 9a1e015fc1
6 changed files with 95 additions and 9 deletions

View File

@@ -538,15 +538,15 @@ static void backend_grab_button(
}
}
static void backend_start_move_window(backend_t *backend, xcb_window_t window) {
static void backend_grab_pointer(backend_t *backend, cursor_t cursor) {
auto conn = backend->conn;
auto root = backend->screen->root;
auto mask = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
XCB_EVENT_MASK_POINTER_MOTION;
auto mode = XCB_GRAB_MODE_ASYNC;
auto cursor = cursor_get_xcb_cursor(backend, ZDWM_CURSOR_MOVE);
auto xcursor = cursor_get_xcb_cursor(backend, cursor);
auto time = XCB_TIME_CURRENT_TIME;
xcb_grab_pointer(conn, false, root, mask, mode, mode, root, cursor, time);
xcb_grab_pointer(conn, false, root, mask, mode, mode, root, xcursor, time);
}
static void backend_merge_effects(
@@ -578,7 +578,10 @@ static void backend_merge_effects(
);
break;
case ZDWM_EFFECT_START_MOVE_WINDOW:
backend_start_move_window(backend, e->as.move.window);
backend_grab_pointer(backend, ZDWM_CURSOR_MOVE);
break;
case ZDWM_EFFECT_START_RESIZE_WINDOW:
backend_grab_pointer(backend, ZDWM_CURSOR_RESIZE);
break;
case ZDWM_EFFECT_MINIMIZE_WINDOW: {
auto window = e->as.minimize.window;

View File

@@ -14,6 +14,8 @@ typedef enum command_type_t {
ZDWM_COMMAND_CHANGE_WINDOW_STATE,
ZDWM_COMMAND_START_MOVE_WINDOW,
ZDWM_COMMAND_STOP_MOVE_WINDOW,
ZDWM_COMMAND_START_RESIZE_WINDOW,
ZDWM_COMMAND_STOP_RESIZE_WINDOW,
ZDWM_COMMAND_WINDOW_SEND_TO_WORKSPACE,
ZDWM_COMMAND_WINDOW_SET_FLOATING,
ZDWM_COMMAND_WINDOW_SET_STICKY,
@@ -47,7 +49,7 @@ typedef struct window_state_change_command_t {
typedef struct window_start_move_command_t {
window_id_t window;
point_t pointer_coordinate;
} window_start_move_command_t;
} start_interaction_command_t;
typedef struct window_send_to_workspace_command_t {
window_id_t window;
@@ -100,7 +102,8 @@ typedef struct command_t {
only_window_data_t withdraw;
configure_data_t configure;
window_state_change_command_t state_change;
window_start_move_command_t move;
start_interaction_command_t move;
start_interaction_command_t resize;
window_send_to_workspace_command_t send_to_workspace;
window_bool_state_t floating;
window_bool_state_t sticky;

View File

@@ -110,6 +110,16 @@ void plan_push_move_effect(plan_t *plan, window_id_t window_id) {
plan_push_effect(plan, &effect);
}
void plan_push_resize_effect(plan_t *plan, window_id_t window_id) {
if (window_id_invalid(window_id)) return;
effect_t effect = {
.type = ZDWM_EFFECT_START_RESIZE_WINDOW,
.as.resize.window = window_id,
};
plan_push_effect(plan, &effect);
}
void plan_push_fullscreen_effect(
plan_t *plan,
window_id_t window_id,

View File

@@ -13,6 +13,7 @@ typedef enum effect_type_t {
ZDWM_EFFECT_KILL_WINDOW,
ZDWM_EFFECT_WITHDRAW_WINDOW,
ZDWM_EFFECT_START_MOVE_WINDOW,
ZDWM_EFFECT_START_RESIZE_WINDOW,
ZDWM_EFFECT_MINIMIZE_WINDOW,
ZDWM_EFFECT_MAXIMIZE_WINDOW,
ZDWM_EFFECT_FULLSCREEN_WINDOW,
@@ -71,6 +72,7 @@ typedef struct effect_t {
only_window_data_t kill;
only_window_data_t withdraw;
only_window_data_t move;
only_window_data_t resize;
effect_bool_window_t minimize;
effect_bool_window_t maximize;
effect_bool_window_t fullscreen;
@@ -102,6 +104,7 @@ void plan_push_focus_effect(plan_t *plan, window_id_t window_id);
void plan_push_kill_effect(plan_t *plan, window_id_t window_id);
void plan_push_withdraw_effect(plan_t *plan, window_id_t window_id);
void plan_push_move_effect(plan_t *plan, window_id_t window_id);
void plan_push_resize_effect(plan_t *plan, window_id_t window_id);
void plan_push_fullscreen_effect(
plan_t *plan,
window_id_t window_id,

View File

@@ -480,6 +480,16 @@ static void route_pointer_press(
};
command_buffer_push(out, &start_move_cmd);
}
if (data->button == ZDWM_BUTTON_RIGHT && data->modifiers == ZDWM_MOD_4) {
command_t start_resize_cmd = {
.type = ZDWM_COMMAND_START_RESIZE_WINDOW,
.as.resize = {
.window = window_id,
.pointer_coordinate = data->root,
}
};
command_buffer_push(out, &start_resize_cmd);
}
}
static void route_pointer_release(
@@ -494,6 +504,10 @@ static void route_pointer_release(
command_t stop_move_cmd = {.type = ZDWM_COMMAND_STOP_MOVE_WINDOW};
command_buffer_push(out, &stop_move_cmd);
} break;
case ZDWM_WINDOW_INTERACTION_RESIZE: {
command_t stop_resize_cmd = {.type = ZDWM_COMMAND_STOP_RESIZE_WINDOW};
command_buffer_push(out, &stop_resize_cmd);
} break;
}
}
@@ -523,6 +537,28 @@ static void route_pointer_motion(
};
command_buffer_push(out, &configure);
} break;
case ZDWM_WINDOW_INTERACTION_RESIZE: {
auto rect = interaction->origin_rect;
auto start = interaction->start_coordinate;
auto end = data->root;
auto width = rect.width + (end.x - start.x);
auto height = rect.height + (end.y - start.y);
width = MAX(width, 10);
height = MAX(height, 10);
command_t configure_cmd = {
.type = ZDWM_COMMAND_CONFIGURE_WINDOW,
.as.configure = {
.window = interaction->window,
.changed_fields =
ZDWM_CONFIGURE_FIELD_WIDTH | ZDWM_CONFIGURE_FIELD_HEIGHT,
.width = width,
.height = height,
}
};
command_buffer_push(out, &configure_cmd);
} break;
}
}
@@ -1297,7 +1333,7 @@ static void change_window_state(
static void start_window_move(
const policy_context_t *ctx,
const window_start_move_command_t *command,
const start_interaction_command_t *command,
plan_t *plan
) {
auto window_id = command->window;
@@ -1314,6 +1350,32 @@ static void start_window_move(
};
}
static void start_window_resize(
const policy_context_t *ctx,
const start_interaction_command_t *command,
plan_t *plan
) {
auto window_id = command->window;
auto window = state_window_get(ctx->state, window_id);
if (!window) return;
auto frame_rect = window->frame_rect;
point_t pointer_position = {
.x = frame_rect.x + frame_rect.width,
.y = frame_rect.y + frame_rect.height,
};
plan_push_resize_effect(plan, window_id);
*ctx->interaction = (window_interaction_state_t){
.mode = ZDWM_WINDOW_INTERACTION_RESIZE,
.window = window_id,
.start_coordinate = pointer_position,
.origin_rect = frame_rect,
};
}
static void send_window_to_workspace(
const policy_context_t *ctx,
const window_send_to_workspace_command_t *command,
@@ -1589,7 +1651,11 @@ void policy_apply_command(
case ZDWM_COMMAND_START_MOVE_WINDOW:
start_window_move(ctx, &cmd->as.move, plan);
break;
case ZDWM_COMMAND_START_RESIZE_WINDOW:
start_window_resize(ctx, &cmd->as.resize, plan);
break;
case ZDWM_COMMAND_STOP_MOVE_WINDOW:
case ZDWM_COMMAND_STOP_RESIZE_WINDOW:
plan_push_ungrab_pointer(plan);
p_clear(ctx->interaction, 1);
break;

View File

@@ -117,6 +117,7 @@ typedef struct only_window_data_t {
typedef enum window_interaction_mode_t {
ZDWM_WINDOW_INTERACTION_NONE,
ZDWM_WINDOW_INTERACTION_MOVE,
ZDWM_WINDOW_INTERACTION_RESIZE,
} window_interaction_mode_t;
typedef struct window_interaction_state_t {