From df437aa87e39abeded78aa3671df8720b9ca2741 Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Mon, 18 Sep 2017 13:22:01 +0300 Subject: [PATCH 1/5] Use con_has_parent in con_fullscreen_permits_focusing --- src/con.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/con.c b/src/con.c index 1de91d00..c9e2b6cf 100644 --- a/src/con.c +++ b/src/con.c @@ -2070,14 +2070,7 @@ bool con_fullscreen_permits_focusing(Con *con) { /* Allow it only if the container to be focused is contained within the * current fullscreen container. */ - do { - if (con->parent == fs) - return true; - con = con->parent; - } while (con); - - /* Focusing con would hide it behind a fullscreen window, disallow it. */ - return false; + return con_has_parent(con, fs); } /* From 2592c63603081dd44c7bccf6014b55a253e14003 Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Tue, 19 Sep 2017 14:52:02 +0300 Subject: [PATCH 2/5] Add error reply to cmd_focus_window_mode --- src/commands.c | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/commands.c b/src/commands.c index a9187866..264cd04f 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1257,28 +1257,34 @@ void cmd_focus_direction(I3_CMD, const char *direction) { void cmd_focus_window_mode(I3_CMD, const char *window_mode) { DLOG("window_mode = %s\n", window_mode); - Con *ws = con_get_workspace(focused); - if (ws != NULL) { - if (strcmp(window_mode, "mode_toggle") == 0) { - if (con_inside_floating(focused)) - window_mode = "tiling"; - else - window_mode = "floating"; - } - Con *current; - TAILQ_FOREACH(current, &(ws->focus_head), focused) { - if ((strcmp(window_mode, "floating") == 0 && current->type != CT_FLOATING_CON) || - (strcmp(window_mode, "tiling") == 0 && current->type == CT_FLOATING_CON)) - continue; - - con_focus(con_descend_focused(current)); - break; - } + bool to_floating = false; + if (strcmp(window_mode, "mode_toggle") == 0) { + to_floating = !con_inside_floating(focused); + } else if (strcmp(window_mode, "floating") == 0) { + to_floating = true; + } else if (strcmp(window_mode, "tiling") == 0) { + to_floating = false; } - cmd_output->needs_tree_render = true; - // XXX: default reply for now, make this a better reply - ysuccess(true); + Con *ws = con_get_workspace(focused); + Con *current; + bool success = false; + TAILQ_FOREACH(current, &(ws->focus_head), focused) { + if ((to_floating && current->type != CT_FLOATING_CON) || + (!to_floating && current->type == CT_FLOATING_CON)) + continue; + + con_focus(con_descend_focused(current)); + success = true; + break; + } + + if (success) { + cmd_output->needs_tree_render = true; + ysuccess(true); + } else { + yerror("Failed to find a %s container in workspace.", to_floating ? "floating" : "tiling"); + } } /* From 759e05137467c6f768a3164de9fe783e1a37aece Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Tue, 19 Sep 2017 09:56:53 +0300 Subject: [PATCH 3/5] Move is_num_fullscreen to Test.pm --- testcases/lib/i3test/Test.pm | 20 ++++++++ testcases/t/100-fullscreen.t | 65 +++++++++++-------------- testcases/t/206-fullscreen-scratchpad.t | 17 ++----- testcases/t/291-swap.t | 21 +++----- 4 files changed, 60 insertions(+), 63 deletions(-) diff --git a/testcases/lib/i3test/Test.pm b/testcases/lib/i3test/Test.pm index 0253bc2d..552ae8b4 100644 --- a/testcases/lib/i3test/Test.pm +++ b/testcases/lib/i3test/Test.pm @@ -5,6 +5,7 @@ use base 'Test::Builder::Module'; our @EXPORT = qw( is_num_children + is_num_fullscreen cmp_float does_i3_live ); @@ -59,6 +60,25 @@ sub is_num_children { $tb->is_num($got_num_children, $num_children, $name); } +=head2 is_num_fullscreen($workspace, $expected, $test_name) + +Gets the number of fullscreen containers on the given workspace and verifies that +they match the expected amount. + + is_num_fullscreen('1', 0, 'no fullscreen containers on workspace 1'); + +=cut +sub is_num_fullscreen { + my ($workspace, $num_fullscreen, $name) = @_; + my $workspace_content = i3test::get_ws($workspace); + my $tb = $CLASS->builder; + + my $nodes = scalar grep { $_->{fullscreen_mode} != 0 } @{$workspace_content->{nodes}->[0]->{nodes}}; + my $cons = scalar grep { $_->{fullscreen_mode} != 0 } @{$workspace_content->{nodes}}; + my $floating = scalar grep { $_->{fullscreen_mode} != 0 } @{$workspace_content->{floating_nodes}->[0]->{nodes}}; + $tb->is_num($nodes + $cons + $floating, $num_fullscreen, $name); +} + =head2 cmp_float($a, $b) Compares floating point numbers C<$a> and C<$b> and returns true if they differ diff --git a/testcases/t/100-fullscreen.t b/testcases/t/100-fullscreen.t index f0d0b4c6..d817bee0 100644 --- a/testcases/t/100-fullscreen.t +++ b/testcases/t/100-fullscreen.t @@ -21,13 +21,6 @@ my $i3 = i3(get_socket_path()); my $tmp = fresh_workspace; -sub fullscreen_windows { - my $ws = $tmp; - $ws = shift if @_; - - scalar grep { $_->{fullscreen_mode} != 0 } @{get_ws_content($ws)} -} - # get the output of this workspace my $tree = $i3->get_tree->recv; my @outputs = @{$tree->{nodes}}; @@ -143,11 +136,11 @@ ok(!eq_hash($new_rect, $original_rect), "Window got repositioned"); $swindow->fullscreen(1); sync_with_i3; -is(fullscreen_windows(), 1, 'amount of fullscreen windows'); +is_num_fullscreen($tmp, 1, 'amount of fullscreen windows'); $window->fullscreen(0); sync_with_i3; -is(fullscreen_windows(), 1, 'amount of fullscreen windows'); +is_num_fullscreen($tmp, 1, 'amount of fullscreen windows'); ok($swindow->mapped, 'window mapped after other fullscreen ended'); @@ -160,15 +153,15 @@ ok($swindow->mapped, 'window mapped after other fullscreen ended'); $swindow->fullscreen(0); sync_with_i3; -is(fullscreen_windows(), 0, 'amount of fullscreen windows after disabling'); +is_num_fullscreen($tmp, 0, 'amount of fullscreen windows after disabling'); cmd 'fullscreen'; -is(fullscreen_windows(), 1, 'amount of fullscreen windows after fullscreen command'); +is_num_fullscreen($tmp, 1, 'amount of fullscreen windows after fullscreen command'); cmd 'fullscreen'; -is(fullscreen_windows(), 0, 'amount of fullscreen windows after fullscreen command'); +is_num_fullscreen($tmp, 0, 'amount of fullscreen windows after fullscreen command'); # clean up the workspace so that it will be cleaned when switching away cmd 'kill' for (@{get_ws_content($tmp)}); @@ -221,18 +214,18 @@ $swindow = open_window; cmd 'fullscreen'; -is(fullscreen_windows($tmp2), 1, 'one fullscreen window on second ws'); +is_num_fullscreen($tmp2, 1, 'one fullscreen window on second ws'); cmd "move workspace $tmp"; -is(fullscreen_windows($tmp2), 0, 'no fullscreen windows on second ws'); -is(fullscreen_windows($tmp), 1, 'one fullscreen window on first ws'); +is_num_fullscreen($tmp2, 0, 'no fullscreen windows on second ws'); +is_num_fullscreen($tmp, 1, 'one fullscreen window on first ws'); $swindow->fullscreen(0); sync_with_i3; # Verify that $swindow was the one that initially remained fullscreen. -is(fullscreen_windows($tmp), 0, 'no fullscreen windows on first ws'); +is_num_fullscreen($tmp, 0, 'no fullscreen windows on first ws'); ################################################################################ # Verify that opening a window with _NET_WM_STATE_FULLSCREEN unfullscreens any @@ -245,14 +238,14 @@ $window = open_window(); cmd "fullscreen"; -is(fullscreen_windows($tmp), 1, 'one fullscreen window on ws'); +is_num_fullscreen($tmp, 1, 'one fullscreen window on ws'); is($x->input_focus, $window->id, 'fullscreen window focused'); $swindow = open_window({ fullscreen => 1 }); -is(fullscreen_windows($tmp), 1, 'one fullscreen window on ws'); +is_num_fullscreen($tmp, 1, 'one fullscreen window on ws'); is($x->input_focus, $swindow->id, 'fullscreen window focused'); ################################################################################ @@ -263,19 +256,19 @@ $tmp = fresh_workspace; $window = open_window; is($x->input_focus, $window->id, 'window focused'); -is(fullscreen_windows($tmp), 0, 'no fullscreen window on workspace'); +is_num_fullscreen($tmp, 0, 'no fullscreen window on workspace'); cmd 'fullscreen enable'; is($x->input_focus, $window->id, 'window still focused'); -is(fullscreen_windows($tmp), 1, 'one fullscreen window on workspace'); +is_num_fullscreen($tmp, 1, 'one fullscreen window on workspace'); cmd 'fullscreen enable'; is($x->input_focus, $window->id, 'window still focused'); -is(fullscreen_windows($tmp), 1, 'still one fullscreen window on workspace'); +is_num_fullscreen($tmp, 1, 'still one fullscreen window on workspace'); $window->fullscreen(0); sync_with_i3; -is(fullscreen_windows($tmp), 0, 'no fullscreen window on workspace'); +is_num_fullscreen($tmp, 0, 'no fullscreen window on workspace'); ################################################################################ # Verify that command ‘fullscreen enable global’ works and is idempotent. @@ -285,19 +278,19 @@ $tmp = fresh_workspace; $window = open_window; is($x->input_focus, $window->id, 'window focused'); -is(fullscreen_windows($tmp), 0, 'no fullscreen window on workspace'); +is_num_fullscreen($tmp, 0, 'no fullscreen window on workspace'); cmd 'fullscreen enable global'; is($x->input_focus, $window->id, 'window still focused'); -is(fullscreen_windows($tmp), 1, 'one fullscreen window on workspace'); +is_num_fullscreen($tmp, 1, 'one fullscreen window on workspace'); cmd 'fullscreen enable global'; is($x->input_focus, $window->id, 'window still focused'); -is(fullscreen_windows($tmp), 1, 'still one fullscreen window on workspace'); +is_num_fullscreen($tmp, 1, 'still one fullscreen window on workspace'); $window->fullscreen(0); sync_with_i3; -is(fullscreen_windows($tmp), 0, 'no fullscreen window on workspace'); +is_num_fullscreen($tmp, 0, 'no fullscreen window on workspace'); ################################################################################ # Verify that command ‘fullscreen disable’ works and is idempotent. @@ -307,19 +300,19 @@ $tmp = fresh_workspace; $window = open_window; is($x->input_focus, $window->id, 'window focused'); -is(fullscreen_windows($tmp), 0, 'no fullscreen window on workspace'); +is_num_fullscreen($tmp, 0, 'no fullscreen window on workspace'); $window->fullscreen(1); sync_with_i3; -is(fullscreen_windows($tmp), 1, 'one fullscreen window on workspace'); +is_num_fullscreen($tmp, 1, 'one fullscreen window on workspace'); cmd 'fullscreen disable'; is($x->input_focus, $window->id, 'window still focused'); -is(fullscreen_windows($tmp), 0, 'no fullscreen window on workspace'); +is_num_fullscreen($tmp, 0, 'no fullscreen window on workspace'); cmd 'fullscreen disable'; is($x->input_focus, $window->id, 'window still focused'); -is(fullscreen_windows($tmp), 0, 'still no fullscreen window on workspace'); +is_num_fullscreen($tmp, 0, 'still no fullscreen window on workspace'); ################################################################################ # Verify that command ‘fullscreen toggle’ works. @@ -328,15 +321,15 @@ is(fullscreen_windows($tmp), 0, 'still no fullscreen window on workspace'); $tmp = fresh_workspace; $window = open_window; -is(fullscreen_windows($tmp), 0, 'no fullscreen window on workspace'); +is_num_fullscreen($tmp, 0, 'no fullscreen window on workspace'); cmd 'fullscreen toggle'; is($x->input_focus, $window->id, 'window still focused'); -is(fullscreen_windows($tmp), 1, 'one fullscreen window on workspace'); +is_num_fullscreen($tmp, 1, 'one fullscreen window on workspace'); cmd 'fullscreen toggle'; is($x->input_focus, $window->id, 'window still focused'); -is(fullscreen_windows($tmp), 0, 'no fullscreen window on workspace'); +is_num_fullscreen($tmp, 0, 'no fullscreen window on workspace'); ################################################################################ # Verify that a window’s fullscreen is disabled when another one is enabled @@ -349,15 +342,15 @@ $window = open_window; $other = open_window; is($x->input_focus, $other->id, 'other window focused'); -is(fullscreen_windows($tmp), 0, 'no fullscreen window on workspace'); +is_num_fullscreen($tmp, 0, 'no fullscreen window on workspace'); cmd 'fullscreen enable'; is($x->input_focus, $other->id, 'other window focused'); -is(fullscreen_windows($tmp), 1, 'one fullscreen window on workspace'); +is_num_fullscreen($tmp, 1, 'one fullscreen window on workspace'); cmd '[id="' . $window->id . '"] fullscreen enable'; is($x->input_focus, $window->id, 'window focused'); -is(fullscreen_windows($tmp), 1, 'one fullscreen window on workspace'); +is_num_fullscreen($tmp, 1, 'one fullscreen window on workspace'); ################################################################################ # Verify that when a global fullscreen is enabled the window is focused and diff --git a/testcases/t/206-fullscreen-scratchpad.t b/testcases/t/206-fullscreen-scratchpad.t index c098f23f..95245099 100644 --- a/testcases/t/206-fullscreen-scratchpad.t +++ b/testcases/t/206-fullscreen-scratchpad.t @@ -21,15 +21,6 @@ use i3test; my $tmp = fresh_workspace; -sub fullscreen_windows { - my $ws = $tmp; - $ws = shift if @_; - - my $nodes = scalar grep { $_->{fullscreen_mode} != 0 } @{get_ws_content($ws)->[0]->{nodes}}; - my $cons = scalar grep { $_->{fullscreen_mode} != 0 } @{get_ws_content($ws)}; - return $nodes + $cons; -} - ########################################################################################## # map two windows in one container, fullscreen one of them and then move it to scratchpad ########################################################################################## @@ -41,7 +32,7 @@ my $second_win = open_window; cmd 'fullscreen'; # see if the window really is in fullscreen mode -is(fullscreen_windows(), 1, 'amount of fullscreen windows after enabling fullscreen'); +is_num_fullscreen($tmp, 1, 'amount of fullscreen windows after enabling fullscreen'); # move window to scratchpad cmd 'move scratchpad'; @@ -57,7 +48,7 @@ cmd 'scratchpad show'; cmd 'floating toggle'; # see if no window is in fullscreen mode -is(fullscreen_windows(), 0, 'amount of fullscreen windows after showing previously fullscreened scratchpad window'); +is_num_fullscreen($tmp, 0, 'amount of fullscreen windows after showing previously fullscreened scratchpad window'); ######################################################################################## # move a window to scratchpad, focus parent container, make it fullscreen, focus a child @@ -79,7 +70,7 @@ cmd 'fullscreen'; cmd 'focus child'; # see if the window really is in fullscreen mode -is(fullscreen_windows(), 1, 'amount of fullscreen windows after enabling fullscreen on parent'); +is_num_fullscreen($tmp, 1, 'amount of fullscreen windows after enabling fullscreen on parent'); ########################################################################## # show a scratchpad window; no window should be in fullscreen mode anymore @@ -89,6 +80,6 @@ is(fullscreen_windows(), 1, 'amount of fullscreen windows after enabling fullscr cmd 'scratchpad show'; # see if no window is in fullscreen mode -is(fullscreen_windows(), 0, 'amount of fullscreen windows after showing a scratchpad window while a parent container was in fullscreen mode'); +is_num_fullscreen($tmp, 0, 'amount of fullscreen windows after showing a scratchpad window while a parent container was in fullscreen mode'); done_testing; diff --git a/testcases/t/291-swap.t b/testcases/t/291-swap.t index d4a43bfb..3b61fdab 100644 --- a/testcases/t/291-swap.t +++ b/testcases/t/291-swap.t @@ -30,12 +30,6 @@ my ($result); my @fullscreen_permutations = ([], ["A"], ["B"], ["A", "B"]); my @urgent; -sub fullscreen_windows { - my $ws = shift if @_; - - scalar grep { $_->{fullscreen_mode} != 0 } @{get_ws_content($ws)} -} - ############################################################################### # Invalid con_id should not crash i3 # See issue #2895. @@ -191,14 +185,14 @@ for my $fullscreen (@fullscreen_permutations){ $nodes = get_ws_content($ws1); $node = $nodes->[0]; is($node->{window}, $B->{id}, 'B is on ws1:left'); - is(fullscreen_windows($ws1), $A_fullscreen, 'amount of fullscreen windows in ws1'); + is_num_fullscreen($ws1, $A_fullscreen, 'amount of fullscreen windows in ws1'); is($node->{fullscreen_mode}, $A_fullscreen, 'B got A\'s fullscreen mode'); $nodes = get_ws_content($ws2); $node = $nodes->[1]; is($node->{window}, $A->{id}, 'A is on ws2:right'); is(get_focused($ws2), $expected_focus, 'A is focused'); - is(fullscreen_windows($ws2), $B_fullscreen, 'amount of fullscreen windows in ws2'); + is_num_fullscreen($ws2, $B_fullscreen, 'amount of fullscreen windows in ws2'); is($node->{fullscreen_mode}, $B_fullscreen, 'A got B\'s fullscreen mode'); kill_all_windows; @@ -232,7 +226,7 @@ cmd '[con_mark=B] swap container with mark A'; $nodes = get_ws_content($ws1); is($nodes->[0]->{window}, $B->{id}, 'B is on ws1:left'); -is(fullscreen_windows($ws1), 1, 'F still fullscreen in ws1'); +is_num_fullscreen($ws1, 1, 'F still fullscreen in ws1'); is(get_focused($ws1), $expected_focus, 'F is still focused'); $nodes = get_ws_content($ws2); @@ -258,7 +252,6 @@ cmd "split v"; open_window; cmd "focus parent"; cmd "fullscreen enable"; -$F = fullscreen_windows($ws1); $expected_focus = get_focused($ws1); $ws2 = fresh_workspace; @@ -274,11 +267,11 @@ does_i3_live; $nodes = get_ws_content($ws1); is($nodes->[1]->{nodes}->[0]->{window}, $B->{id}, 'B is on top right in ws1'); is(get_focused($ws1), $expected_focus, 'The container of the stacked windows remains focused in ws1'); -is(fullscreen_windows($ws1), $F, 'Same amount of fullscreen windows in ws1'); +is_num_fullscreen($ws1, 1, 'Same amount of fullscreen windows in ws1'); $nodes = get_ws_content($ws2); is($nodes->[0]->{window}, $A->{id}, 'A is on ws2'); -is(fullscreen_windows($ws2), 1, 'A is in fullscreen mode'); +is_num_fullscreen($ws2, 1, 'A is in fullscreen mode'); ############################################################################### # Swap two non-focused containers within the same workspace. @@ -351,13 +344,13 @@ for my $fullscreen (@fullscreen_permutations){ $nodes = get_ws_content($ws1); $node = $nodes->[0]; is($node->{window}, $B->{id}, 'B is on the first workspace'); - is(fullscreen_windows($ws1), $A_fullscreen, 'amount of fullscreen windows in ws1'); + is_num_fullscreen($ws1, $A_fullscreen, 'amount of fullscreen windows in ws1'); is($node->{fullscreen_mode}, $A_fullscreen, 'B got A\'s fullscreen mode'); $nodes = get_ws_content($ws2); $node = $nodes->[0]; is($node->{window}, $A->{id}, 'A is on the second workspace'); - is(fullscreen_windows($ws2), $B_fullscreen, 'amount of fullscreen windows in ws2'); + is_num_fullscreen($ws2, $B_fullscreen, 'amount of fullscreen windows in ws2'); is($node->{fullscreen_mode}, $B_fullscreen, 'A got B\'s fullscreen mode'); is(get_focused($ws3), $expected_focus, 'F is still focused'); From 994a479558a6b93e286ce03d6f00db3a3a9c6fcf Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Sat, 23 Sep 2017 13:09:08 +0300 Subject: [PATCH 4/5] userguide: mention in focus --- docs/userguide | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/userguide b/docs/userguide index 0258e2ab..98242a9b 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1951,6 +1951,9 @@ bindsym $mod+t floating toggle To change focus, you can use the +focus+ command. The following options are available: +:: + Sets focus to the container that matches the specified criteria. + See <>. left|right|up|down:: Sets focus to the nearest container in the given direction. parent:: @@ -1970,6 +1973,7 @@ output:: *Syntax*: ---------------------------------------------- + focus focus left|right|down|up focus parent|child|floating|tiling|mode_toggle focus output left|right|up|down|primary| @@ -1977,6 +1981,9 @@ focus output left|right|up|down|primary| *Examples*: ------------------------------------------------- +# Focus firefox +bindsym $mod+F1 [class="Firefox"] focus + # Focus container on the left, bottom, top, right bindsym $mod+j focus left bindsym $mod+k focus down From 2403c43f7b72c0a5230ff7aa0dd67c687fc9ba5e Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Sun, 17 Sep 2017 02:20:48 +0300 Subject: [PATCH 5/5] Make 'focus' disable blocking fullscreen windows The problem here is that con_fullscreen_permits_focusing() does not check if there is a blocking fullscreen container in the workspace that the container to be focused belongs. This makes it possible to focus a container behind a fullscreen window if it's in an unfocused workspace. This commit introduces a change in the 'focus' command behaviour. When focusing a container blocked by a fullscreen container, either CF_OUTPUT or CF_GLOBAL, the blocking container loses its fullscreen mode and the target container is focused like normal. This should not affect directional focus commands: left, right, up, down, parent, child. Fixes issue #1819. --- src/commands.c | 25 ++++--- testcases/t/156-fullscreen-focus.t | 110 ++++++++++++++++++++++++++--- 2 files changed, 116 insertions(+), 19 deletions(-) diff --git a/src/commands.c b/src/commands.c index 264cd04f..162f0892 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1250,6 +1250,20 @@ void cmd_focus_direction(I3_CMD, const char *direction) { ysuccess(true); } +/* + * Focus a container and disable any other fullscreen container not permitting the focus. + * + */ +static void cmd_focus_force_focus(Con *con) { + /* Disable fullscreen container in workspace with container to be focused. */ + Con *ws = con_get_workspace(con); + Con *fullscreen_on_ws = (focused && focused->fullscreen_mode == CF_GLOBAL) ? focused : con_get_fullscreen_con(ws, CF_OUTPUT); + if (fullscreen_on_ws && fullscreen_on_ws != con && !con_has_parent(con, fullscreen_on_ws)) { + con_disable_fullscreen(fullscreen_on_ws); + } + con_focus(con); +} + /* * Implementation of 'focus tiling|floating|mode_toggle'. * @@ -1274,7 +1288,7 @@ void cmd_focus_window_mode(I3_CMD, const char *window_mode) { (!to_floating && current->type == CT_FLOATING_CON)) continue; - con_focus(con_descend_focused(current)); + cmd_focus_force_focus(con_descend_focused(current)); success = true; break; } @@ -1341,13 +1355,6 @@ void cmd_focus(I3_CMD) { if (!ws) continue; - /* Check the fullscreen focus constraints. */ - if (!con_fullscreen_permits_focusing(current->con)) { - LOG("Cannot change focus while in fullscreen mode (fullscreen rules).\n"); - ysuccess(false); - return; - } - /* In case this is a scratchpad window, call scratchpad_show(). */ if (ws == __i3_scratch) { scratchpad_show(current->con); @@ -1371,7 +1378,7 @@ void cmd_focus(I3_CMD) { * So we focus 'current' to make it the currently focused window of * the target workspace, then revert focus. */ Con *currently_focused = focused; - con_focus(current->con); + cmd_focus_force_focus(current->con); con_focus(currently_focused); /* Now switch to the workspace, then focus */ diff --git a/testcases/t/156-fullscreen-focus.t b/testcases/t/156-fullscreen-focus.t index 7a5e38ca..cfa2405e 100644 --- a/testcases/t/156-fullscreen-focus.t +++ b/testcases/t/156-fullscreen-focus.t @@ -157,9 +157,6 @@ isnt($x->input_focus, $right2->id, 'bottom right window no longer focused'); cmd 'focus child'; is($x->input_focus, $right2->id, 'bottom right window focused again'); -cmd '[id="' . $left->id . '"] focus'; -is($x->input_focus, $right2->id, 'prevented focus change to left window'); - cmd 'focus up'; is($x->input_focus, $right1->id, 'allowed focus up'); @@ -178,9 +175,6 @@ is($x->input_focus, $right1->id, 'allowed focus wrap (down)'); cmd 'focus up'; is($x->input_focus, $right2->id, 'allowed focus wrap (up)'); -cmd '[id="' . $diff_ws->id . '"] focus'; -is($x->input_focus, $right2->id, 'prevented focus change to different ws'); - ################################################################################ # Same tests when we're in non-global fullscreen mode. It should now be possible # to focus a container in a different workspace. @@ -202,9 +196,6 @@ isnt($x->input_focus, $right2->id, 'bottom right window no longer focused'); cmd 'focus child'; is($x->input_focus, $right2->id, 'bottom right window focused again'); -cmd '[id="' . $left->id . '"] focus'; -is($x->input_focus, $right2->id, 'prevented focus change to left window'); - cmd 'focus up'; is($x->input_focus, $right1->id, 'allowed focus up'); @@ -323,6 +314,105 @@ verify_move(2, 'prevented move to workspace by name'); cmd "move to workspace prev"; verify_move(2, 'prevented move to workspace by position'); -# TODO: Tests for "move to output" and "move workspace to output". +################################################################################ +# Ensure it's possible to focus a window using the focus command despite +# fullscreen window blocking it. Fullscreen window should lose its fullscreen +# mode. +################################################################################ +# first & second tiling, focus using id +kill_all_windows; + +$tmp = fresh_workspace; +my $first = open_window; +my $second = open_window; +cmd 'fullscreen'; +is($x->input_focus, $second->id, 'fullscreen window focused'); +is_num_fullscreen($tmp, 1, '1 fullscreen window'); + +cmd '[id="'. $first->id .'"] focus'; +sync_with_i3; + +is($x->input_focus, $first->id, 'correctly focused using id'); +is_num_fullscreen($tmp, 0, 'no fullscreen windows'); + +# first floating, second tiling, focus using 'focus floating' +kill_all_windows; + +$tmp = fresh_workspace; +my $first = open_floating_window; +my $second = open_window; +cmd 'fullscreen'; +is($x->input_focus, $second->id, 'fullscreen window focused'); +is_num_fullscreen($tmp, 1, '1 fullscreen window'); + +cmd 'focus floating'; +sync_with_i3; + +is($x->input_focus, $first->id, 'correctly focused using focus floating'); +is_num_fullscreen($tmp, 0, 'no fullscreen windows'); + +# first tiling, second floating, focus using 'focus tiling' +kill_all_windows; + +$tmp = fresh_workspace; +my $first = open_window; +my $second = open_floating_window; +cmd 'fullscreen'; +is($x->input_focus, $second->id, 'fullscreen window focused'); +is_num_fullscreen($tmp, 1, '1 fullscreen window'); + +cmd 'focus tiling'; +sync_with_i3; + +is($x->input_focus, $first->id, 'correctly focused using focus tiling'); +is_num_fullscreen($tmp, 0, 'no fullscreen windows'); + +################################################################################ +# When the fullscreen window is in an other workspace it should maintain its +# fullscreen mode since it's not blocking the window to be focused. +################################################################################ + +kill_all_windows; + +$tmp = fresh_workspace; +my $first = open_window; + +$tmp2 = fresh_workspace; +my $second = open_window; +cmd 'fullscreen'; +is($x->input_focus, $second->id, 'fullscreen window focused'); +is_num_fullscreen($tmp2, 1, '1 fullscreen window'); + +cmd '[id="'. $first->id .'"] focus'; +sync_with_i3; + +is($x->input_focus, $first->id, 'correctly focused using focus id'); +is_num_fullscreen($tmp, 0, 'no fullscreen windows on first workspace'); +is_num_fullscreen($tmp2, 1, 'still one fullscreen window on second workspace'); + +################################################################################ +# But a global window in another workspace is blocking the window to be focused. +# Ensure that it loses its fullscreen mode. +################################################################################ + +kill_all_windows; + +$tmp = fresh_workspace; +$first = open_window; + +$tmp2 = fresh_workspace; +$second = open_window; +cmd 'fullscreen global'; +is($x->input_focus, $second->id, 'global window focused'); +is_num_fullscreen($tmp2, 1, '1 fullscreen window'); + +cmd '[id="'. $first->id .'"] focus'; +sync_with_i3; + +is($x->input_focus, $first->id, 'correctly focused using focus id'); +is_num_fullscreen($tmp2, 0, 'no fullscreen windows'); + + +# TODO: Tests for "move to output" and "move workspace to output". done_testing;