From 47de7375dd50f67c5b6ccc52b1db8b542123a830 Mon Sep 17 00:00:00 2001 From: Deiz Date: Mon, 8 Oct 2012 12:28:08 -0400 Subject: [PATCH] Allow 'focus $dir' to move out of non-global fullscreen containers --- src/tree.c | 19 ++++++++++++++++--- testcases/t/156-fullscreen-focus.t | 25 ++++++++++++++++++------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/tree.c b/src/tree.c index f233fd69..8681a3b9 100644 --- a/src/tree.c +++ b/src/tree.c @@ -463,12 +463,18 @@ void tree_render(void) { * */ static bool _tree_next(Con *con, char way, orientation_t orientation, bool wrap) { + /* When dealing with fullscreen containers, it's necessary to go up to the + * workspace level, because 'focus $dir' will start at the con's real + * position in the tree, and it may not be possible to get to the edge + * normally due to fullscreen focusing restrictions. */ + if (con->fullscreen_mode == CF_OUTPUT && con->type != CT_WORKSPACE) + con = con_get_workspace(con); + /* Stop recursing at workspaces after attempting to switch to next * workspace if possible. */ if (con->type == CT_WORKSPACE) { - if (con_get_fullscreen_con(con, CF_GLOBAL) || - con_get_fullscreen_con(con, CF_OUTPUT)) { - DLOG("Cannot change workspace while in fullscreen mode.\n"); + if (con_get_fullscreen_con(con, CF_GLOBAL)) { + DLOG("Cannot change workspace while in global fullscreen mode.\n"); return false; } Output *current_output = get_output_containing(con->rect.x, con->rect.y); @@ -505,6 +511,13 @@ static bool _tree_next(Con *con, char way, orientation_t orientation, bool wrap) return false; workspace_show(workspace); + + /* If a workspace has an active fullscreen container, one of its + * children should always be focused. The above workspace_show() + * should be adequate for that, so return. */ + if (con_get_fullscreen_con(workspace, CF_OUTPUT)) + return true; + Con *focus = con_descend_direction(workspace, direction); if (focus) { con_focus(focus); diff --git a/testcases/t/156-fullscreen-focus.t b/testcases/t/156-fullscreen-focus.t index 23be014a..170c641d 100644 --- a/testcases/t/156-fullscreen-focus.t +++ b/testcases/t/156-fullscreen-focus.t @@ -125,10 +125,18 @@ is($nodes->[0]->{focused}, 1, 'fullscreen window focused'); cmd 'fullscreen'; +# Focus screen 1 +$x->root->warp_pointer(1025, 0); +sync_with_i3; + $tmp = fresh_workspace; cmd "workspace $tmp"; my $diff_ws = open_window; +# Focus screen 0 +$x->root->warp_pointer(0, 0); +sync_with_i3; + $tmp2 = fresh_workspace; cmd "workspace $tmp2"; cmd 'split h'; @@ -207,21 +215,24 @@ is($x->input_focus, $right1->id, 'allowed focus up'); cmd 'focus down'; is($x->input_focus, $right2->id, 'allowed focus down'); -cmd 'focus left'; -is($x->input_focus, $right2->id, 'prevented focus left'); - -cmd 'focus right'; -is($x->input_focus, $right2->id, 'prevented focus right'); - cmd 'focus down'; 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'; +cmd 'focus left'; +is($x->input_focus, $right2->id, 'focus left wrapped (no-op)'); + +cmd 'focus right'; is($x->input_focus, $diff_ws->id, 'allowed focus change to different ws'); +cmd 'focus left'; +is($x->input_focus, $right2->id, 'focused back into fullscreen container'); + +cmd '[id="' . $diff_ws->id . '"] focus'; +is($x->input_focus, $diff_ws->id, 'allowed focus change to different ws by id'); + ################################################################################ # More testing of the interaction between wrapping and the fullscreen focus # restrictions.