From 9a1e015fc18f0336ff1de8198190377f47697824 Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Mon, 22 Jun 2026 00:48:14 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20MOD4=20+=20?= =?UTF-8?q?=E9=BC=A0=E6=A0=87=E5=8F=B3=E9=94=AE=E8=B0=83=E6=95=B4=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E5=A4=A7=E5=B0=8F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/x11/backend.c | 15 +++++---- src/core/command.h | 7 ++-- src/core/plan.c | 10 ++++++ src/core/plan.h | 3 ++ src/core/policy.c | 68 ++++++++++++++++++++++++++++++++++++++- src/core/types.h | 1 + 6 files changed, 95 insertions(+), 9 deletions(-) diff --git a/src/backend/x11/backend.c b/src/backend/x11/backend.c index f11b701..2aa36f3 100644 --- a/src/backend/x11/backend.c +++ b/src/backend/x11/backend.c @@ -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 time = XCB_TIME_CURRENT_TIME; - xcb_grab_pointer(conn, false, root, mask, mode, mode, root, cursor, time); + auto mode = XCB_GRAB_MODE_ASYNC; + auto xcursor = cursor_get_xcb_cursor(backend, cursor); + auto time = XCB_TIME_CURRENT_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; diff --git a/src/core/command.h b/src/core/command.h index 2c622f9..a99dbb1 100644 --- a/src/core/command.h +++ b/src/core/command.h @@ -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; diff --git a/src/core/plan.c b/src/core/plan.c index 9a26751..f257065 100644 --- a/src/core/plan.c +++ b/src/core/plan.c @@ -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, diff --git a/src/core/plan.h b/src/core/plan.h index 11f3f22..016e874 100644 --- a/src/core/plan.h +++ b/src/core/plan.h @@ -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, diff --git a/src/core/policy.c b/src/core/policy.c index 14b68cf..ec3545c 100644 --- a/src/core/policy.c +++ b/src/core/policy.c @@ -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; diff --git a/src/core/types.h b/src/core/types.h index aacbd83..a7fffc4 100644 --- a/src/core/types.h +++ b/src/core/types.h @@ -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 {