diff --git a/include/sway/commands.h b/include/sway/commands.h index 27058587..d758d964 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -155,6 +155,7 @@ sway_cmd cmd_mark; sway_cmd cmd_max_render_time; sway_cmd cmd_mode; sway_cmd cmd_mouse_warping; +sway_cmd cmd_mouse_warping_position; sway_cmd cmd_move; sway_cmd cmd_new_float; sway_cmd cmd_new_window; diff --git a/include/sway/config.h b/include/sway/config.h index f9da1967..453c258e 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -461,6 +461,14 @@ enum mouse_warping_mode { WARP_CONTAINER, }; +enum mouse_warping_position { + WARP_POS_CENTER, + WARP_POS_TOPLEFT, + WARP_POS_TOPRIGHT, + WARP_POS_BOTLEFT, + WARP_POS_BOTRIGHT, +}; + enum alignment { ALIGN_LEFT, ALIGN_CENTER, @@ -524,6 +532,7 @@ struct sway_config { // Flags enum focus_follows_mouse_mode focus_follows_mouse; enum mouse_warping_mode mouse_warping; + enum mouse_warping_position mouse_warping_position; enum focus_wrapping_mode focus_wrapping; bool active; bool failed; diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 527d0350..bd5ea44d 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -127,7 +127,9 @@ void cursor_set_image_surface(struct sway_cursor *cursor, struct wl_client *client); void cursor_warp_to_container(struct sway_cursor *cursor, - struct sway_container *container, bool force); + struct sway_container *container, + enum mouse_warping_position pos, + bool force); void cursor_warp_to_workspace(struct sway_cursor *cursor, struct sway_workspace *workspace); diff --git a/sway/commands.c b/sway/commands.c index 8d003dfa..6f455d95 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -76,6 +76,7 @@ static const struct cmd_handler handlers[] = { { "input", cmd_input }, { "mode", cmd_mode }, { "mouse_warping", cmd_mouse_warping }, + { "mouse_warping_position", cmd_mouse_warping_position }, { "new_float", cmd_new_float }, { "new_window", cmd_new_window }, { "no_focus", cmd_no_focus }, diff --git a/sway/commands/focus.c b/sway/commands/focus.c index facd82de..cfb16946 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -279,7 +279,7 @@ static struct cmd_results *focus_mode(struct sway_workspace *ws, // `seat_consider_warp_to_focus` would decide not to warp, but we need // to anyway. if (config->mouse_warping == WARP_CONTAINER) { - cursor_warp_to_container(seat->cursor, new_focus, true); + cursor_warp_to_container(seat->cursor, new_focus, config->mouse_warping_position, true); } else { seat_consider_warp_to_focus(seat); } diff --git a/sway/commands/mouse_warping.c b/sway/commands/mouse_warping.c index 8b643f62..00ce5914 100644 --- a/sway/commands/mouse_warping.c +++ b/sway/commands/mouse_warping.c @@ -19,3 +19,23 @@ struct cmd_results *cmd_mouse_warping(int argc, char **argv) { return cmd_results_new(CMD_SUCCESS, NULL); } +struct cmd_results *cmd_mouse_warping_position(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "mouse_warping_position", EXPECTED_EQUAL_TO, 1))) { + return error; + } else if (strcasecmp(argv[0], "center") == 0) { + config->mouse_warping_position = WARP_POS_CENTER; + } else if (strcasecmp(argv[0], "topleft") == 0) { + config->mouse_warping_position = WARP_POS_TOPLEFT; + } else if (strcasecmp(argv[0], "topright") == 0) { + config->mouse_warping_position = WARP_POS_TOPRIGHT; + } else if (strcasecmp(argv[0], "bottomleft") == 0) { + config->mouse_warping_position = WARP_POS_BOTLEFT; + } else if (strcasecmp(argv[0], "bottomright") == 0) { + config->mouse_warping_position = WARP_POS_BOTRIGHT; + } else { + return cmd_results_new(CMD_FAILURE, + "Expected 'mouse_warping_position center|topleft|topright|bottomleft|bottomright"); + } + return cmd_results_new(CMD_SUCCESS, NULL); +} diff --git a/sway/config.c b/sway/config.c index 72fc41e7..3dc1b8a4 100644 --- a/sway/config.c +++ b/sway/config.c @@ -270,6 +270,7 @@ static void config_defaults(struct sway_config *config) { // Flags config->focus_follows_mouse = FOLLOWS_YES; config->mouse_warping = WARP_OUTPUT; + config->mouse_warping_position = WARP_POS_CENTER; config->focus_wrapping = WRAP_YES; config->validating = false; config->reloading = false; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 3d04826c..7be83483 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -1162,7 +1162,9 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { * false. If container is NULL, returns without doing anything. */ void cursor_warp_to_container(struct sway_cursor *cursor, - struct sway_container *container, bool force) { + struct sway_container *container, + enum mouse_warping_position pos, + bool force) { if (!container) { return; } @@ -1174,9 +1176,31 @@ void cursor_warp_to_container(struct sway_cursor *cursor, return; } + // Initialize to center double x = container->pending.x + container->pending.width / 2.0; double y = container->pending.y + container->pending.height / 2.0; + switch (pos) { + case WARP_POS_CENTER: + // Already initialized above + break; + case WARP_POS_TOPLEFT: + x = container->pending.x; + y = container->pending.y; + break; + case WARP_POS_TOPRIGHT: + x = container->pending.x + container->pending.width; + y = container->pending.y; + break; + case WARP_POS_BOTLEFT: + x = container->pending.x; + y = container->pending.y + container->pending.height; + break; + case WARP_POS_BOTRIGHT: + x = container->pending.x + container->pending.width; + y = container->pending.y + container->pending.height; + break; + } wlr_cursor_warp(cursor->cursor, NULL, x, y); cursor_unhide(cursor); } diff --git a/sway/input/seat.c b/sway/input/seat.c index 0c5672bc..7ef06509 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1552,7 +1552,7 @@ void seat_consider_warp_to_focus(struct sway_seat *seat) { } if (focus->type == N_CONTAINER) { - cursor_warp_to_container(seat->cursor, focus->sway_container, false); + cursor_warp_to_container(seat->cursor, focus->sway_container, config->mouse_warping_position, false); } else { cursor_warp_to_workspace(seat->cursor, focus->sway_workspace); } diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 7e58b528..0b21d38b 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -791,7 +791,12 @@ The default colors are: *mouse_warping* output|container|none If _output_ is specified, the mouse will be moved to new outputs as you move focus between them. If _container_ is specified, the mouse will be - moved to the middle of the container on switch. Default is _output_. + moved into the container on switch. The mouse warp position can be adjusted + with *mouse_warping_position*. Default is _output_. + +*mouse_warping_position* center|topleft|topright|bottomleft|bottomright + Which corner of the container to move the mouse to when mouse warping occurs. + Default is _center_. *no_focus* Prevents windows matching from being focused automatically when