From 96578aa91e9856bfb3e2d26fb7a625ff7c9b79e3 Mon Sep 17 00:00:00 2001 From: Tamir Zahavi-Brunner Date: Mon, 7 Sep 2020 01:44:13 +0300 Subject: [PATCH 1/4] hide_cursor: Add an option to hide when typing Add an option for the `hide_cursor` command to hide the cursor when typing, i.e. whenever a key is pressed. --- include/sway/config.h | 7 ++++++ include/sway/input/cursor.h | 6 +++++ sway/commands/seat/hide_cursor.c | 42 ++++++++++++++++++++++++-------- sway/config/seat.c | 5 ++++ sway/input/cursor.c | 26 ++++++++++++++++++++ sway/input/keyboard.c | 5 ++++ sway/sway-input.5.scd | 15 ++++++++---- 7 files changed, 91 insertions(+), 15 deletions(-) diff --git a/include/sway/config.h b/include/sway/config.h index 473f723b0..59f22ae2b 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -181,6 +181,12 @@ struct seat_attachment_config { // TODO other things are configured here for some reason }; +enum seat_config_hide_cursor_when_typing { + HIDE_WHEN_TYPING_DEFAULT, // the default is currently disabled + HIDE_WHEN_TYPING_ENABLE, + HIDE_WHEN_TYPING_DISABLE, +}; + enum seat_config_allow_constrain { CONSTRAIN_DEFAULT, // the default is currently enabled CONSTRAIN_ENABLE, @@ -216,6 +222,7 @@ struct seat_config { int fallback; // -1 means not set list_t *attachments; // list of seat_attachment configs int hide_cursor_timeout; + enum seat_config_hide_cursor_when_typing hide_cursor_when_typing; enum seat_config_allow_constrain allow_constrain; enum seat_config_shortcuts_inhibit shortcuts_inhibit; enum seat_keyboard_grouping keyboard_grouping; diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 4c130fafc..ca3c6f4b5 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -6,6 +6,7 @@ #include #include #include "sway/input/seat.h" +#include "config.h" #define SWAY_CURSOR_PRESSED_BUTTONS_CAP 32 @@ -68,6 +69,10 @@ struct sway_cursor { struct wl_event_source *hide_source; bool hidden; + // This field is just a cache of the field in seat_config in order to avoid + // costly seat_config lookups on every keypress. HIDE_WHEN_TYPING_DEFAULT + // indicates that there is no cached value. + enum seat_config_hide_cursor_when_typing hide_when_typing; size_t pressed_button_count; }; @@ -94,6 +99,7 @@ void cursor_handle_activity(struct sway_cursor *cursor, struct wlr_input_device *device); void cursor_unhide(struct sway_cursor *cursor); int cursor_get_timeout(struct sway_cursor *cursor); +void cursor_notify_key_press(struct sway_cursor *cursor); void dispatch_cursor_button(struct sway_cursor *cursor, struct wlr_input_device *device, uint32_t time_msec, uint32_t button, diff --git a/sway/commands/seat/hide_cursor.c b/sway/commands/seat/hide_cursor.c index 3bfce6977..e09b82d99 100644 --- a/sway/commands/seat/hide_cursor.c +++ b/sway/commands/seat/hide_cursor.c @@ -3,26 +3,48 @@ #include "sway/commands.h" #include "sway/config.h" #include "sway/input/seat.h" +#include "sway/input/cursor.h" +#include "sway/server.h" #include "stringop.h" +#include "util.h" struct cmd_results *seat_cmd_hide_cursor(int argc, char **argv) { struct cmd_results *error = NULL; - if ((error = checkarg(argc, "hide_cursor", EXPECTED_EQUAL_TO, 1))) { + if ((error = checkarg(argc, "hide_cursor", EXPECTED_AT_LEAST, 1))) { return error; } - if (!config->handler_context.seat_config) { + if ((error = checkarg(argc, "hide_cursor", EXPECTED_AT_MOST, 2))) { + return error; + } + struct seat_config *seat_config = config->handler_context.seat_config; + if (!seat_config) { return cmd_results_new(CMD_FAILURE, "No seat defined"); } - char *end; - int timeout = strtol(argv[0], &end, 10); - if (*end) { - return cmd_results_new(CMD_INVALID, "Expected an integer timeout"); + if (argc == 1) { + char *end; + int timeout = strtol(argv[0], &end, 10); + if (*end) { + return cmd_results_new(CMD_INVALID, "Expected an integer timeout"); + } + if (timeout < 100 && timeout != 0) { + timeout = 100; + } + seat_config->hide_cursor_timeout = timeout; + } else { + if (strcmp(argv[0], "when-typing") != 0) { + return cmd_results_new(CMD_INVALID, + "Expected 'hide_cursor |when-typing [enable|disable]'"); + } + seat_config->hide_cursor_when_typing = parse_boolean(argv[1], true) ? + HIDE_WHEN_TYPING_ENABLE : HIDE_WHEN_TYPING_DISABLE; + + // Invalidate all the caches for this config + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &server.input->seats, link) { + seat->cursor->hide_when_typing = HIDE_WHEN_TYPING_DEFAULT; + } } - if (timeout < 100 && timeout != 0) { - timeout = 100; - } - config->handler_context.seat_config->hide_cursor_timeout = timeout; return cmd_results_new(CMD_SUCCESS, NULL); } diff --git a/sway/config/seat.c b/sway/config/seat.c index e2702de5d..84260aa39 100644 --- a/sway/config/seat.c +++ b/sway/config/seat.c @@ -29,6 +29,7 @@ struct seat_config *new_seat_config(const char* name) { return NULL; } seat->hide_cursor_timeout = -1; + seat->hide_cursor_when_typing = HIDE_WHEN_TYPING_DEFAULT; seat->allow_constrain = CONSTRAIN_DEFAULT; seat->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT; seat->keyboard_grouping = KEYBOARD_GROUP_DEFAULT; @@ -151,6 +152,10 @@ void merge_seat_config(struct seat_config *dest, struct seat_config *source) { dest->hide_cursor_timeout = source->hide_cursor_timeout; } + if (source->hide_cursor_when_typing != HIDE_WHEN_TYPING_DEFAULT) { + dest->hide_cursor_when_typing = source->hide_cursor_when_typing; + } + if (source->allow_constrain != CONSTRAIN_DEFAULT) { dest->allow_constrain = source->allow_constrain; } diff --git a/sway/input/cursor.c b/sway/input/cursor.c index e47410a5a..b168afc5d 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -253,6 +253,32 @@ int cursor_get_timeout(struct sway_cursor *cursor) { return timeout; } +void cursor_notify_key_press(struct sway_cursor *cursor) { + if (cursor->hidden) { + return; + } + + if (cursor->hide_when_typing == HIDE_WHEN_TYPING_DEFAULT) { + // No cached value, need to lookup in the seat_config + const struct seat_config *seat_config = seat_get_config(cursor->seat); + if (!seat_config) { + seat_config = seat_get_config_by_name("*"); + if (!seat_config) { + return; + } + } + cursor->hide_when_typing = seat_config->hide_cursor_when_typing; + // The default is currently disabled + if (cursor->hide_when_typing == HIDE_WHEN_TYPING_DEFAULT) { + cursor->hide_when_typing = HIDE_WHEN_TYPING_DISABLE; + } + } + + if (cursor->hide_when_typing == HIDE_WHEN_TYPING_ENABLE) { + cursor_hide(cursor); + } +} + static enum sway_input_idle_source idle_source_from_device( struct wlr_input_device *device) { switch (device->type) { diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 541fc90d7..ae30e83ad 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -13,6 +13,7 @@ #include "sway/input/input-manager.h" #include "sway/input/keyboard.h" #include "sway/input/seat.h" +#include "sway/input/cursor.h" #include "sway/ipc-server.h" #include "log.h" @@ -392,6 +393,10 @@ static void handle_key_event(struct sway_keyboard *keyboard, keyboard_shortcuts_inhibitor_get_for_focused_surface(seat); bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active; + if (event->state == WLR_KEY_PRESSED) { + cursor_notify_key_press(seat->cursor); + } + // Identify new keycode, raw keysym(s), and translated keysym(s) struct key_info keyinfo; update_keyboard_state(keyboard, event->keycode, event->state, &keyinfo); diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index d8180c1c8..dbf21d93d 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -229,11 +229,16 @@ correct seat. Set this seat as the fallback seat. A fallback seat will attach any device not explicitly attached to another seat (similar to a "default" seat). -*seat* hide_cursor - Hides the cursor image after the specified _timeout_ (in milliseconds) - has elapsed with no activity on that cursor. A timeout of 0 (default) - disables hiding the cursor. The minimal timeout is 100 and any value less - than that (aside from 0), will be increased to 100. +*seat* hide_cursor |when-typing [enable|disable] + Hides the cursor image after the specified event occured. + + If _timeout_ is specified, then the cursor will be hidden after _timeout_ + (in milliseconds) has elapsed with no activity on the cursor. A timeout of 0 + (default) disables hiding the cursor. The minimal timeout is 100 and any + value less than that (aside from 0), will be increased to 100. + + If _when-typing_ is enabled, then the cursor will be hidden whenever a key + is pressed. *seat* idle_inhibit Sets the set of input event sources which can prevent the seat from From 8c12e71a66feb1cac545dc8746f817772eb77d2f Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sat, 31 Oct 2020 17:56:21 -0400 Subject: [PATCH 2/4] input: remove motion deltas from seatop callbacks Straightforward cleanup, they haven't been used for a while. --- include/sway/input/seat.h | 13 ++++--------- sway/input/cursor.c | 4 ++-- sway/input/seat.c | 11 +++++------ sway/input/seatop_default.c | 5 ++--- sway/input/seatop_down.c | 5 ++--- sway/input/seatop_move_floating.c | 3 +-- sway/input/seatop_move_tiling.c | 3 +-- sway/input/seatop_resize_floating.c | 3 +-- sway/input/seatop_resize_tiling.c | 3 +-- 9 files changed, 19 insertions(+), 31 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 2256fff18..4118df665 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -16,13 +16,12 @@ struct sway_seatop_impl { void (*button)(struct sway_seat *seat, uint32_t time_msec, struct wlr_input_device *device, uint32_t button, enum wlr_button_state state); - void (*pointer_motion)(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy); + void (*pointer_motion)(struct sway_seat *seat, uint32_t time_msec); void (*pointer_axis)(struct sway_seat *seat, struct wlr_event_pointer_axis *event); void (*rebase)(struct sway_seat *seat, uint32_t time_msec); void (*tablet_tool_motion)(struct sway_seat *seat, - struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy); + struct sway_tablet_tool *tool, uint32_t time_msec); void (*tablet_tool_tip)(struct sway_seat *seat, struct sway_tablet_tool *tool, uint32_t time_msec, enum wlr_tablet_tool_tip_state state); void (*end)(struct sway_seat *seat); @@ -269,11 +268,7 @@ void seatop_button(struct sway_seat *seat, uint32_t time_msec, struct wlr_input_device *device, uint32_t button, enum wlr_button_state state); -/** - * dx and dy are distances relative to previous position. - */ -void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy); +void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec); void seatop_pointer_axis(struct sway_seat *seat, struct wlr_event_pointer_axis *event); @@ -283,7 +278,7 @@ void seatop_tablet_tool_tip(struct sway_seat *seat, enum wlr_tablet_tool_tip_state state); void seatop_tablet_tool_motion(struct sway_seat *seat, - struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy); + struct sway_tablet_tool *tool, uint32_t time_msec); void seatop_rebase(struct sway_seat *seat, uint32_t time_msec); diff --git a/sway/input/cursor.c b/sway/input/cursor.c index b168afc5d..9ad4900bb 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -359,7 +359,7 @@ static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, wlr_cursor_move(cursor->cursor, device, dx, dy); - seatop_pointer_motion(cursor->seat, time_msec, dx, dy); + seatop_pointer_motion(cursor->seat, time_msec); } static void handle_pointer_motion_relative( @@ -621,7 +621,7 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor, if (!cursor->simulating_pointer_from_tool_tip && ((surface && wlr_surface_accepts_tablet_v2(tablet->tablet_v2, surface)) || wlr_tablet_tool_v2_has_implicit_grab(tool->tablet_v2_tool))) { - seatop_tablet_tool_motion(seat, tool, time_msec, dx, dy); + seatop_tablet_tool_motion(seat, tool, time_msec); } else { wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool); pointer_motion(cursor, time_msec, input_device->wlr_device, dx, dy, dx, dy); diff --git a/sway/input/seat.c b/sway/input/seat.c index 04b480d8e..e178c08aa 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1500,10 +1500,9 @@ void seatop_button(struct sway_seat *seat, uint32_t time_msec, } } -void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy) { +void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { if (seat->seatop_impl->pointer_motion) { - seat->seatop_impl->pointer_motion(seat, time_msec, dx, dy); + seat->seatop_impl->pointer_motion(seat, time_msec); } } @@ -1523,11 +1522,11 @@ void seatop_tablet_tool_tip(struct sway_seat *seat, } void seatop_tablet_tool_motion(struct sway_seat *seat, - struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy) { + struct sway_tablet_tool *tool, uint32_t time_msec) { if (seat->seatop_impl->tablet_tool_motion) { - seat->seatop_impl->tablet_tool_motion(seat, tool, time_msec, dx, dy); + seat->seatop_impl->tablet_tool_motion(seat, tool, time_msec); } else { - seatop_pointer_motion(seat, time_msec, dx, dy); + seatop_pointer_motion(seat, time_msec); } } diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index ae593f5ce..2bee389e9 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -557,8 +557,7 @@ static void check_focus_follows_mouse(struct sway_seat *seat, } } -static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy) { +static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_default_event *e = seat->seatop_data; struct sway_cursor *cursor = seat->cursor; @@ -592,7 +591,7 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, } static void handle_tablet_tool_motion(struct sway_seat *seat, - struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy) { + struct sway_tablet_tool *tool, uint32_t time_msec) { struct seatop_default_event *e = seat->seatop_data; struct sway_cursor *cursor = seat->cursor; diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index 0d24f480d..17f619e32 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c @@ -37,8 +37,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, } } -static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy) { +static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_down_event *e = seat->seatop_data; struct sway_container *con = e->con; if (seat_is_input_allowed(seat, con->view->surface)) { @@ -60,7 +59,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, } static void handle_tablet_tool_motion(struct sway_seat *seat, - struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy) { + struct sway_tablet_tool *tool, uint32_t time_msec) { struct seatop_down_event *e = seat->seatop_data; struct sway_container *con = e->con; if (seat_is_input_allowed(seat, con->view->surface)) { diff --git a/sway/input/seatop_move_floating.c b/sway/input/seatop_move_floating.c index b9a20402a..7f501fc9a 100644 --- a/sway/input/seatop_move_floating.c +++ b/sway/input/seatop_move_floating.c @@ -34,8 +34,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, finalize_move(seat); } } -static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy) { +static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_move_floating_event *e = seat->seatop_data; struct wlr_cursor *cursor = seat->cursor->cursor; desktop_damage_whole_container(e->con); diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index 2d3abc9a6..c7285becc 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -207,8 +207,7 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { desktop_damage_box(&e->drop_box); } -static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy) { +static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_move_tiling_event *e = seat->seatop_data; if (e->threshold_reached) { handle_motion_postthreshold(seat); diff --git a/sway/input/seatop_resize_floating.c b/sway/input/seatop_resize_floating.c index 10af06fed..5da22e47b 100644 --- a/sway/input/seatop_resize_floating.c +++ b/sway/input/seatop_resize_floating.c @@ -31,8 +31,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, } } -static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy) { +static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_resize_floating_event *e = seat->seatop_data; struct sway_container *con = e->con; enum wlr_edges edge = e->edge; diff --git a/sway/input/seatop_resize_tiling.c b/sway/input/seatop_resize_tiling.c index 05be6e701..2cca805d3 100644 --- a/sway/input/seatop_resize_tiling.c +++ b/sway/input/seatop_resize_tiling.c @@ -71,8 +71,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, } } -static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy) { +static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_resize_tiling_event *e = seat->seatop_data; int amount_x = 0; int amount_y = 0; From 60d95414d4a7ff163099c9e551ec435cb0cb7eca Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sat, 31 Oct 2020 19:56:40 -0400 Subject: [PATCH 3/4] commands/focus: force container warp when fulfilling `focus mode_toggle` This commit switches focusing behavior to force a warp when executing `focus mode_toggle`. Fixes #5772. --- include/sway/input/cursor.h | 2 +- sway/commands/focus.c | 11 ++++++++++- sway/input/cursor.c | 17 ++++++++++++----- sway/input/seat.c | 5 +---- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index ca3c6f4b5..55e2ce8ef 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -116,7 +116,7 @@ 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); + struct sway_container *container, bool force); void cursor_warp_to_workspace(struct sway_cursor *cursor, struct sway_workspace *workspace); diff --git a/sway/commands/focus.c b/sway/commands/focus.c index 56c3d981c..79b7aed54 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -268,7 +268,16 @@ static struct cmd_results *focus_mode(struct sway_workspace *ws, } if (new_focus) { seat_set_focus_container(seat, new_focus); - seat_consider_warp_to_focus(seat); + + // If we're on the floating layer and the floating container area + // overlaps the position on the tiling layer that would be warped to, + // `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); + } else { + seat_consider_warp_to_focus(seat); + } } else { return cmd_results_new(CMD_FAILURE, "Failed to find a %s container in workspace", diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 9ad4900bb..5c8839241 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -306,12 +306,16 @@ void cursor_handle_activity(struct sway_cursor *cursor, enum sway_input_idle_source idle_source = idle_source_from_device(device); seat_idle_notify_activity(cursor->seat, idle_source); - if (cursor->hidden && idle_source != IDLE_SOURCE_TOUCH) { + if (idle_source != IDLE_SOURCE_TOUCH) { cursor_unhide(cursor); } } void cursor_unhide(struct sway_cursor *cursor) { + if (!cursor->hidden) { + return; + } + cursor->hidden = false; if (cursor->image_surface) { cursor_set_image_surface(cursor, @@ -1141,18 +1145,19 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { /** * Warps the cursor to the middle of the container argument. - * Does nothing if the cursor is already inside the container. - * If container is NULL, returns without doing anything. + * Does nothing if the cursor is already inside the container and `force` is + * false. If container is NULL, returns without doing anything. */ void cursor_warp_to_container(struct sway_cursor *cursor, - struct sway_container *container) { + struct sway_container *container, bool force) { if (!container) { return; } struct wlr_box box; container_get_box(container, &box); - if (wlr_box_contains_point(&box, cursor->cursor->x, cursor->cursor->y)) { + if (!force && wlr_box_contains_point(&box, cursor->cursor->x, + cursor->cursor->y)) { return; } @@ -1160,6 +1165,7 @@ void cursor_warp_to_container(struct sway_cursor *cursor, double y = container->y + container->height / 2.0; wlr_cursor_warp(cursor->cursor, NULL, x, y); + cursor_unhide(cursor); } /** @@ -1176,6 +1182,7 @@ void cursor_warp_to_workspace(struct sway_cursor *cursor, double y = workspace->y + workspace->height / 2.0; wlr_cursor_warp(cursor->cursor, NULL, x, y); + cursor_unhide(cursor); } uint32_t get_mouse_bindsym(const char *name, char **error) { diff --git a/sway/input/seat.c b/sway/input/seat.c index e178c08aa..24d7e903e 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1477,13 +1477,10 @@ void seat_consider_warp_to_focus(struct sway_seat *seat) { } if (focus->type == N_CONTAINER) { - cursor_warp_to_container(seat->cursor, focus->sway_container); + cursor_warp_to_container(seat->cursor, focus->sway_container, false); } else { cursor_warp_to_workspace(seat->cursor, focus->sway_workspace); } - if (seat->cursor->hidden){ - cursor_unhide(seat->cursor); - } } void seatop_unref(struct sway_seat *seat, struct sway_container *con) { From c523aa623bc5e5b5897c0f337058aa7308871fef Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sun, 25 Oct 2020 13:17:47 -0400 Subject: [PATCH 4/4] input: fully change focus when scrolling tabs/stacks When scrolling on a tabbed/stacked container, i3 focuses its inactive-focused focused child. Sway does the same, but then resets the focus to whatever was focused previously. Ref https://github.com/i3/i3/blob/e5992eed163179f5cd2715c2c212d3d757f04b31/src/click.c#L207-L219 --- sway/input/seatop_default.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 2bee389e9..e6d6c11b3 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -703,19 +703,14 @@ static void handle_pointer_axis(struct sway_seat *seat, } else if (desired >= siblings->length) { desired = siblings->length - 1; } - struct sway_node *old_focus = seat_get_focus(seat); + struct sway_container *new_sibling_con = siblings->items[desired]; struct sway_node *new_sibling = &new_sibling_con->node; struct sway_node *new_focus = seat_get_focus_inactive(seat, new_sibling); - if (node_has_ancestor(old_focus, tabcontainer)) { - seat_set_focus(seat, new_focus); - } else { - // Scrolling when focus is not in the tabbed container at all - seat_set_raw_focus(seat, new_sibling); - seat_set_raw_focus(seat, new_focus); - seat_set_raw_focus(seat, old_focus); - } + // Use the focused child of the tabbed/stacked container, not the + // container the user scrolled on. + seat_set_focus(seat, new_focus); handled = true; } }