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.
This commit is contained in:
parent
994a479558
commit
2403c43f7b
|
@ -1250,6 +1250,20 @@ void cmd_focus_direction(I3_CMD, const char *direction) {
|
||||||
ysuccess(true);
|
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'.
|
* 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))
|
(!to_floating && current->type == CT_FLOATING_CON))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
con_focus(con_descend_focused(current));
|
cmd_focus_force_focus(con_descend_focused(current));
|
||||||
success = true;
|
success = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1341,13 +1355,6 @@ void cmd_focus(I3_CMD) {
|
||||||
if (!ws)
|
if (!ws)
|
||||||
continue;
|
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(). */
|
/* In case this is a scratchpad window, call scratchpad_show(). */
|
||||||
if (ws == __i3_scratch) {
|
if (ws == __i3_scratch) {
|
||||||
scratchpad_show(current->con);
|
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
|
* So we focus 'current' to make it the currently focused window of
|
||||||
* the target workspace, then revert focus. */
|
* the target workspace, then revert focus. */
|
||||||
Con *currently_focused = focused;
|
Con *currently_focused = focused;
|
||||||
con_focus(current->con);
|
cmd_focus_force_focus(current->con);
|
||||||
con_focus(currently_focused);
|
con_focus(currently_focused);
|
||||||
|
|
||||||
/* Now switch to the workspace, then focus */
|
/* Now switch to the workspace, then focus */
|
||||||
|
|
|
@ -157,9 +157,6 @@ isnt($x->input_focus, $right2->id, 'bottom right window no longer focused');
|
||||||
cmd 'focus child';
|
cmd 'focus child';
|
||||||
is($x->input_focus, $right2->id, 'bottom right window focused again');
|
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';
|
cmd 'focus up';
|
||||||
is($x->input_focus, $right1->id, 'allowed 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';
|
cmd 'focus up';
|
||||||
is($x->input_focus, $right2->id, 'allowed focus wrap (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
|
# Same tests when we're in non-global fullscreen mode. It should now be possible
|
||||||
# to focus a container in a different workspace.
|
# 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';
|
cmd 'focus child';
|
||||||
is($x->input_focus, $right2->id, 'bottom right window focused again');
|
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';
|
cmd 'focus up';
|
||||||
is($x->input_focus, $right1->id, 'allowed 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";
|
cmd "move to workspace prev";
|
||||||
verify_move(2, 'prevented move to workspace by position');
|
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;
|
done_testing;
|
||||||
|
|
Loading…
Reference in New Issue