feat: 添加 MOD4 + 鼠标左键移动窗口功能
This commit is contained in:
@@ -538,6 +538,17 @@ static void backend_grab_button(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void backend_start_move_window(backend_t *backend, xcb_window_t window) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
static void backend_merge_effects(
|
static void backend_merge_effects(
|
||||||
backend_t *backend,
|
backend_t *backend,
|
||||||
const effect_t *effects,
|
const effect_t *effects,
|
||||||
@@ -566,6 +577,9 @@ static void backend_merge_effects(
|
|||||||
XCB_ICCCM_WM_STATE_WITHDRAWN
|
XCB_ICCCM_WM_STATE_WITHDRAWN
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case ZDWM_EFFECT_START_MOVE_WINDOW:
|
||||||
|
backend_start_move_window(backend, e->as.move.window);
|
||||||
|
break;
|
||||||
case ZDWM_EFFECT_MINIMIZE_WINDOW: {
|
case ZDWM_EFFECT_MINIMIZE_WINDOW: {
|
||||||
auto window = e->as.minimize.window;
|
auto window = e->as.minimize.window;
|
||||||
xcb_icccm_wm_state_t state = XCB_ICCCM_WM_STATE_NORMAL;
|
xcb_icccm_wm_state_t state = XCB_ICCCM_WM_STATE_NORMAL;
|
||||||
@@ -619,6 +633,10 @@ static void backend_merge_effects(
|
|||||||
break;
|
break;
|
||||||
case ZDWM_EFFECT_GRAB_BUTTON:
|
case ZDWM_EFFECT_GRAB_BUTTON:
|
||||||
backend_grab_button(backend, &e->as.grab_button);
|
backend_grab_button(backend, &e->as.grab_button);
|
||||||
|
break;
|
||||||
|
case ZDWM_EFFECT_UNGRAB_POINTER:
|
||||||
|
xcb_ungrab_pointer(backend->conn, XCB_CURRENT_TIME);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -271,7 +271,8 @@ static bool handle_button_press(
|
|||||||
event_t *event,
|
event_t *event,
|
||||||
const xcb_button_press_event_t *xcb_event
|
const xcb_button_press_event_t *xcb_event
|
||||||
) {
|
) {
|
||||||
auto handled = fill_button_event(xcb_event, &event->as.pointer_button_press);
|
auto press = &event->as.pointer_button_press;
|
||||||
|
auto handled = fill_button_event(xcb_event, press);
|
||||||
if (handled) event->type = ZDWM_EVENT_POINTER_BUTTON_PRESS;
|
if (handled) event->type = ZDWM_EVENT_POINTER_BUTTON_PRESS;
|
||||||
|
|
||||||
return handled;
|
return handled;
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ typedef enum command_type_t {
|
|||||||
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,
|
||||||
|
ZDWM_COMMAND_START_MOVE_WINDOW,
|
||||||
|
ZDWM_COMMAND_STOP_MOVE_WINDOW,
|
||||||
ZDWM_COMMAND_WINDOW_SEND_TO_WORKSPACE,
|
ZDWM_COMMAND_WINDOW_SEND_TO_WORKSPACE,
|
||||||
ZDWM_COMMAND_WINDOW_SET_FLOATING,
|
ZDWM_COMMAND_WINDOW_SET_FLOATING,
|
||||||
ZDWM_COMMAND_WINDOW_SET_STICKY,
|
ZDWM_COMMAND_WINDOW_SET_STICKY,
|
||||||
@@ -42,6 +44,11 @@ typedef struct window_state_change_command_t {
|
|||||||
window_state_request_action_t action;
|
window_state_request_action_t action;
|
||||||
} window_state_change_command_t;
|
} 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;
|
||||||
|
|
||||||
typedef struct window_send_to_workspace_command_t {
|
typedef struct window_send_to_workspace_command_t {
|
||||||
window_id_t window;
|
window_id_t window;
|
||||||
workspace_id_t workspace;
|
workspace_id_t workspace;
|
||||||
@@ -93,6 +100,7 @@ typedef struct command_t {
|
|||||||
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;
|
||||||
|
window_start_move_command_t move;
|
||||||
window_send_to_workspace_command_t send_to_workspace;
|
window_send_to_workspace_command_t send_to_workspace;
|
||||||
window_bool_state_t floating;
|
window_bool_state_t floating;
|
||||||
window_bool_state_t sticky;
|
window_bool_state_t sticky;
|
||||||
|
|||||||
@@ -100,6 +100,16 @@ void plan_push_withdraw_effect(plan_t *plan, window_id_t window_id) {
|
|||||||
plan_push_effect(plan, &effect);
|
plan_push_effect(plan, &effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void plan_push_move_effect(plan_t *plan, window_id_t window_id) {
|
||||||
|
if (window_id_invalid(window_id)) return;
|
||||||
|
|
||||||
|
effect_t effect = {
|
||||||
|
.type = ZDWM_EFFECT_START_MOVE_WINDOW,
|
||||||
|
.as.move.window = window_id,
|
||||||
|
};
|
||||||
|
plan_push_effect(plan, &effect);
|
||||||
|
}
|
||||||
|
|
||||||
void plan_push_fullscreen_effect(
|
void plan_push_fullscreen_effect(
|
||||||
plan_t *plan,
|
plan_t *plan,
|
||||||
window_id_t window_id,
|
window_id_t window_id,
|
||||||
@@ -167,3 +177,8 @@ void plan_push_change_border_color_effect(
|
|||||||
};
|
};
|
||||||
plan_push_effect(plan, &effect);
|
plan_push_effect(plan, &effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void plan_push_ungrab_pointer(plan_t *plan) {
|
||||||
|
effect_t effect = {.type = ZDWM_EFFECT_UNGRAB_POINTER};
|
||||||
|
plan_push_effect(plan, &effect);
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ typedef enum effect_type_t {
|
|||||||
ZDWM_EFFECT_FOCUS_WINDOW,
|
ZDWM_EFFECT_FOCUS_WINDOW,
|
||||||
ZDWM_EFFECT_KILL_WINDOW,
|
ZDWM_EFFECT_KILL_WINDOW,
|
||||||
ZDWM_EFFECT_WITHDRAW_WINDOW,
|
ZDWM_EFFECT_WITHDRAW_WINDOW,
|
||||||
|
ZDWM_EFFECT_START_MOVE_WINDOW,
|
||||||
ZDWM_EFFECT_MINIMIZE_WINDOW,
|
ZDWM_EFFECT_MINIMIZE_WINDOW,
|
||||||
ZDWM_EFFECT_MAXIMIZE_WINDOW,
|
ZDWM_EFFECT_MAXIMIZE_WINDOW,
|
||||||
ZDWM_EFFECT_FULLSCREEN_WINDOW,
|
ZDWM_EFFECT_FULLSCREEN_WINDOW,
|
||||||
@@ -21,6 +22,7 @@ typedef enum effect_type_t {
|
|||||||
ZDWM_EFFECT_RESTACK_WINDOWS,
|
ZDWM_EFFECT_RESTACK_WINDOWS,
|
||||||
ZDWM_EFFECT_BIND_KEY,
|
ZDWM_EFFECT_BIND_KEY,
|
||||||
ZDWM_EFFECT_GRAB_BUTTON,
|
ZDWM_EFFECT_GRAB_BUTTON,
|
||||||
|
ZDWM_EFFECT_UNGRAB_POINTER,
|
||||||
} effect_type_t;
|
} effect_type_t;
|
||||||
|
|
||||||
typedef struct effect_move_window_t {
|
typedef struct effect_move_window_t {
|
||||||
@@ -68,6 +70,7 @@ typedef struct effect_t {
|
|||||||
only_window_data_t focus;
|
only_window_data_t focus;
|
||||||
only_window_data_t kill;
|
only_window_data_t kill;
|
||||||
only_window_data_t withdraw;
|
only_window_data_t withdraw;
|
||||||
|
only_window_data_t move;
|
||||||
effect_bool_window_t minimize;
|
effect_bool_window_t minimize;
|
||||||
effect_bool_window_t maximize;
|
effect_bool_window_t maximize;
|
||||||
effect_bool_window_t fullscreen;
|
effect_bool_window_t fullscreen;
|
||||||
@@ -98,6 +101,7 @@ void plan_push_unmap_effect(plan_t *plan, window_id_t window_id);
|
|||||||
void plan_push_focus_effect(plan_t *plan, window_id_t window_id);
|
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_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_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_fullscreen_effect(
|
void plan_push_fullscreen_effect(
|
||||||
plan_t *plan,
|
plan_t *plan,
|
||||||
window_id_t window_id,
|
window_id_t window_id,
|
||||||
@@ -110,3 +114,4 @@ void plan_push_change_border_color_effect(
|
|||||||
window_id_t window_id,
|
window_id_t window_id,
|
||||||
const color_t *color
|
const color_t *color
|
||||||
);
|
);
|
||||||
|
void plan_push_ungrab_pointer(plan_t *plan);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
#include <zdwm/action.h>
|
#include <zdwm/action.h>
|
||||||
#include <zdwm/types.h>
|
#include <zdwm/types.h>
|
||||||
|
|
||||||
@@ -459,6 +460,72 @@ static void route_key_press(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void route_pointer_press(
|
||||||
|
const policy_context_t *ctx,
|
||||||
|
const pointer_button_event_t *data,
|
||||||
|
command_buffer_t *out
|
||||||
|
) {
|
||||||
|
auto window_id = data->window;
|
||||||
|
auto window = state_window_get(ctx->state, window_id);
|
||||||
|
if (!window) return;
|
||||||
|
|
||||||
|
/* TODO: 后续改为配置 */
|
||||||
|
if (data->button == ZDWM_BUTTON_LEFT && data->modifiers == ZDWM_MOD_4) {
|
||||||
|
command_t start_move_cmd = {
|
||||||
|
.type = ZDWM_COMMAND_START_MOVE_WINDOW,
|
||||||
|
.as.move = {
|
||||||
|
.window = window_id,
|
||||||
|
.pointer_coordinate = data->root,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
command_buffer_push(out, &start_move_cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void route_pointer_release(
|
||||||
|
const policy_context_t *ctx,
|
||||||
|
const pointer_button_event_t *data,
|
||||||
|
command_buffer_t *out
|
||||||
|
) {
|
||||||
|
switch (ctx->interaction->mode) {
|
||||||
|
case ZDWM_WINDOW_INTERACTION_NONE:
|
||||||
|
break;
|
||||||
|
case ZDWM_WINDOW_INTERACTION_MOVE: {
|
||||||
|
command_t stop_move_cmd = {.type = ZDWM_COMMAND_STOP_MOVE_WINDOW};
|
||||||
|
command_buffer_push(out, &stop_move_cmd);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void route_pointer_motion(
|
||||||
|
const policy_context_t *ctx,
|
||||||
|
const pointer_motion_event_t *data,
|
||||||
|
command_buffer_t *out
|
||||||
|
) {
|
||||||
|
auto interaction = ctx->interaction;
|
||||||
|
|
||||||
|
switch (interaction->mode) {
|
||||||
|
case ZDWM_WINDOW_INTERACTION_NONE:
|
||||||
|
break;
|
||||||
|
case ZDWM_WINDOW_INTERACTION_MOVE: {
|
||||||
|
auto rect = interaction->origin_rect;
|
||||||
|
auto start = interaction->start_coordinate;
|
||||||
|
auto end = data->root;
|
||||||
|
|
||||||
|
command_t configure = {
|
||||||
|
.type = ZDWM_COMMAND_CONFIGURE_WINDOW,
|
||||||
|
.as.configure = {
|
||||||
|
.window = interaction->window,
|
||||||
|
.changed_fields = ZDWM_CONFIGURE_FIELD_X | ZDWM_CONFIGURE_FIELD_Y,
|
||||||
|
.x = rect.x + (end.x - start.x),
|
||||||
|
.y = rect.y + (end.y - start.y),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
command_buffer_push(out, &configure);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
route_pointer_enter(state_t *state, window_id_t window, command_buffer_t *out) {
|
route_pointer_enter(state_t *state, window_id_t window, command_buffer_t *out) {
|
||||||
add_focus_window_command(out, window);
|
add_focus_window_command(out, window);
|
||||||
@@ -676,6 +743,15 @@ void policy_route_event(
|
|||||||
case ZDWM_EVENT_KEY_PRESS:
|
case ZDWM_EVENT_KEY_PRESS:
|
||||||
route_key_press(ctx, &event->as.key_press, out);
|
route_key_press(ctx, &event->as.key_press, out);
|
||||||
break;
|
break;
|
||||||
|
case ZDWM_EVENT_POINTER_BUTTON_PRESS:
|
||||||
|
route_pointer_press(ctx, &event->as.pointer_button_press, out);
|
||||||
|
break;
|
||||||
|
case ZDWM_EVENT_POINTER_BUTTON_RELEASE:
|
||||||
|
route_pointer_release(ctx, &event->as.pointer_button_release, out);
|
||||||
|
break;
|
||||||
|
case ZDWM_EVENT_POINTER_MOTION:
|
||||||
|
route_pointer_motion(ctx, &event->as.pointer_motion, out);
|
||||||
|
break;
|
||||||
case ZDWM_EVENT_POINTER_ENTER:
|
case ZDWM_EVENT_POINTER_ENTER:
|
||||||
route_pointer_enter(state, event->as.pointer_enter.window, out);
|
route_pointer_enter(state, event->as.pointer_enter.window, out);
|
||||||
break;
|
break;
|
||||||
@@ -1219,6 +1295,25 @@ static void change_window_state(
|
|||||||
listeners_notify_window_updated(ctx->listeners, state, command->window);
|
listeners_notify_window_updated(ctx->listeners, state, command->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void start_window_move(
|
||||||
|
const policy_context_t *ctx,
|
||||||
|
const window_start_move_command_t *command,
|
||||||
|
plan_t *plan
|
||||||
|
) {
|
||||||
|
auto window_id = command->window;
|
||||||
|
auto window = state_window_get(ctx->state, window_id);
|
||||||
|
if (!window) return;
|
||||||
|
|
||||||
|
plan_push_move_effect(plan, window_id);
|
||||||
|
|
||||||
|
*ctx->interaction = (window_interaction_state_t){
|
||||||
|
.mode = ZDWM_WINDOW_INTERACTION_MOVE,
|
||||||
|
.window = window_id,
|
||||||
|
.start_coordinate = command->pointer_coordinate,
|
||||||
|
.origin_rect = window->frame_rect,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static void send_window_to_workspace(
|
static void send_window_to_workspace(
|
||||||
const policy_context_t *ctx,
|
const policy_context_t *ctx,
|
||||||
const window_send_to_workspace_command_t *command,
|
const window_send_to_workspace_command_t *command,
|
||||||
@@ -1491,6 +1586,13 @@ void policy_apply_command(
|
|||||||
case ZDWM_COMMAND_CHANGE_WINDOW_STATE:
|
case ZDWM_COMMAND_CHANGE_WINDOW_STATE:
|
||||||
change_window_state(ctx, &cmd->as.state_change, plan);
|
change_window_state(ctx, &cmd->as.state_change, plan);
|
||||||
break;
|
break;
|
||||||
|
case ZDWM_COMMAND_START_MOVE_WINDOW:
|
||||||
|
start_window_move(ctx, &cmd->as.move, plan);
|
||||||
|
break;
|
||||||
|
case ZDWM_COMMAND_STOP_MOVE_WINDOW:
|
||||||
|
plan_push_ungrab_pointer(plan);
|
||||||
|
p_clear(ctx->interaction, 1);
|
||||||
|
break;
|
||||||
case ZDWM_COMMAND_WINDOW_SEND_TO_WORKSPACE:
|
case ZDWM_COMMAND_WINDOW_SEND_TO_WORKSPACE:
|
||||||
send_window_to_workspace(ctx, &cmd->as.send_to_workspace, plan);
|
send_window_to_workspace(ctx, &cmd->as.send_to_workspace, plan);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ typedef struct policy_bar_t {
|
|||||||
} policy_bar_t;
|
} policy_bar_t;
|
||||||
|
|
||||||
typedef struct policy_context_t {
|
typedef struct policy_context_t {
|
||||||
|
window_interaction_state_t *interaction;
|
||||||
binding_table_t *bind_table;
|
binding_table_t *bind_table;
|
||||||
state_t *state;
|
state_t *state;
|
||||||
const rules_t *rules;
|
const rules_t *rules;
|
||||||
|
|||||||
@@ -114,6 +114,18 @@ typedef struct only_window_data_t {
|
|||||||
window_id_t window;
|
window_id_t window;
|
||||||
} only_window_data_t;
|
} only_window_data_t;
|
||||||
|
|
||||||
|
typedef enum window_interaction_mode_t {
|
||||||
|
ZDWM_WINDOW_INTERACTION_NONE,
|
||||||
|
ZDWM_WINDOW_INTERACTION_MOVE,
|
||||||
|
} window_interaction_mode_t;
|
||||||
|
|
||||||
|
typedef struct window_interaction_state_t {
|
||||||
|
window_interaction_mode_t mode;
|
||||||
|
window_id_t window;
|
||||||
|
point_t start_coordinate;
|
||||||
|
rect_t origin_rect;
|
||||||
|
} window_interaction_state_t;
|
||||||
|
|
||||||
static inline bool window_id_invalid(window_id_t window_id) {
|
static inline bool window_id_invalid(window_id_t window_id) {
|
||||||
return window_id == ZDWM_WINDOW_ID_INVALID;
|
return window_id == ZDWM_WINDOW_ID_INVALID;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ typedef struct runtime_t {
|
|||||||
void *config_module_handle;
|
void *config_module_handle;
|
||||||
binding_table_t *binding_table;
|
binding_table_t *binding_table;
|
||||||
listeners_t listeners;
|
listeners_t listeners;
|
||||||
|
window_interaction_state_t interaction;
|
||||||
|
|
||||||
bar_t bar;
|
bar_t bar;
|
||||||
window_list_t bar_windows;
|
window_list_t bar_windows;
|
||||||
@@ -197,6 +198,7 @@ static void runtime_shutdown(runtime_t *runtime) {
|
|||||||
binding_table_destroy(runtime->binding_table);
|
binding_table_destroy(runtime->binding_table);
|
||||||
runtime->binding_table = nullptr;
|
runtime->binding_table = nullptr;
|
||||||
listeners_cleanup(&runtime->listeners);
|
listeners_cleanup(&runtime->listeners);
|
||||||
|
p_clear(&runtime->interaction, 1);
|
||||||
window_list_cleanup(&runtime->bar_windows);
|
window_list_cleanup(&runtime->bar_windows);
|
||||||
backend_destroy(runtime->backend);
|
backend_destroy(runtime->backend);
|
||||||
runtime->backend = nullptr;
|
runtime->backend = nullptr;
|
||||||
@@ -402,6 +404,8 @@ static void runtime_arrange(runtime_t *runtime) {
|
|||||||
|
|
||||||
static policy_context_t policy_context_init(runtime_t *runtime) {
|
static policy_context_t policy_context_init(runtime_t *runtime) {
|
||||||
policy_context_t ctx = {
|
policy_context_t ctx = {
|
||||||
|
.interaction = &runtime->interaction,
|
||||||
|
|
||||||
.bind_table = runtime->binding_table,
|
.bind_table = runtime->binding_table,
|
||||||
.state = &runtime->state,
|
.state = &runtime->state,
|
||||||
.rules = &runtime->rules,
|
.rules = &runtime->rules,
|
||||||
|
|||||||
Reference in New Issue
Block a user