diff --git a/src/commands.c b/src/commands.c index 6a6ea5a3..5ddcc176 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1299,7 +1299,16 @@ void cmd_focus_sibling(I3_CMD, const char *direction_str) { } Con *next = get_tree_next_sibling(current->con, direction); if (next) { - con_activate(next); + if (next->type == CT_WORKSPACE) { + /* On the workspace level, we need to make sure that the + * workspace change happens properly. However, workspace_show + * descends focus so we also have to put focus on the workspace + * itself to maintain consistency. See #3997. */ + workspace_show(next); + con_focus(next); + } else { + con_activate(next); + } } } diff --git a/testcases/t/307-focus-next-prev.t b/testcases/t/307-focus-next-prev.t index c7f06589..4f8a8ecd 100644 --- a/testcases/t/307-focus-next-prev.t +++ b/testcases/t/307-focus-next-prev.t @@ -69,4 +69,16 @@ cmp_tree( cmd 'focus parent, focus next sibling'; }); +# See #3997 +cmd 'workspace 2'; +open_window; +cmd 'workspace 1'; +open_window; +cmd 'focus parent, focus parent, focus next sibling, focus prev sibling'; +does_i3_live; +is(focused_ws, '1', 'Back and forth between workspaces'); + +cmd 'focus parent, focus parent, focus next sibling'; +is(focused_ws, '2', "Workspace 2 focused with 'focus next sibling'"); + done_testing;