void tree_split(Con *con, orientation_t orientation);
/**
- * Moves focus one level up.
+ * Moves focus one level up. Returns true if focus changed.
*
*/
-void level_up(void);
+bool level_up(void);
/**
- * Moves focus one level down.
+ * Moves focus one level down. Returns true if focus changed.
*
*/
-void level_down(void);
+bool level_down(void);
/**
* Renders the tree, that is rendering all outputs using render_con() and
*
*/
void cmd_focus_level(I3_CMD, char *level) {
- if (focused &&
- focused->type != CT_WORKSPACE &&
- focused->fullscreen_mode != CF_NONE) {
- LOG("Cannot change focus while in fullscreen mode.\n");
- ysuccess(false);
- return;
- }
-
DLOG("level = %s\n", level);
+ bool success = false;
+
+ /* Focusing the parent can only be allowed if the newly
+ * focused container won't escape the fullscreen container. */
+ if (strcmp(level, "parent") == 0) {
+ if (focused && focused->parent) {
+ if (con_fullscreen_permits_focusing(focused->parent))
+ success = level_up();
+ else
+ LOG("Currently in fullscreen, not going up\n");
+ }
+ }
- if (strcmp(level, "parent") == 0)
- level_up();
- else level_down();
+ /* Focusing a child should always be allowed. */
+ else success = level_down();
- cmd_output->needs_tree_render = true;
+ cmd_output->needs_tree_render = success;
// XXX: default reply for now, make this a better reply
- ysuccess(true);
+ ysuccess(success);
}
/*
if (fs->type == CT_WORKSPACE)
return true;
+ /* Allow it if the container itself is the fullscreen container. */
+ if (con == fs)
+ return true;
+
/* If fullscreen is per-output, the focus being in a different workspace is
* sufficient to guarantee that change won't leave fullscreen in bad shape. */
if (fs->fullscreen_mode == CF_OUTPUT &&
}
/*
- * Moves focus one level up.
+ * Moves focus one level up. Returns true if focus changed.
*
*/
-void level_up(void) {
- /* We cannot go up when we are in fullscreen mode at the moment, that would
- * be totally not intuitive */
- if (focused->fullscreen_mode != CF_NONE) {
- LOG("Currently in fullscreen, not going up\n");
- return;
- }
+bool level_up(void) {
/* We can focus up to the workspace, but not any higher in the tree */
if ((focused->parent->type != CT_CON &&
focused->parent->type != CT_WORKSPACE) ||
focused->type == CT_WORKSPACE) {
LOG("Cannot go up any further\n");
- return;
+ return false;
}
con_focus(focused->parent);
+ return true;
}
/*
- * Moves focus one level down.
+ * Moves focus one level down. Returns true if focus changed.
*
*/
-void level_down(void) {
+bool level_down(void) {
/* Go down the focus stack of the current node */
Con *next = TAILQ_FIRST(&(focused->focus_head));
if (next == TAILQ_END(&(focused->focus_head))) {
printf("cannot go down\n");
- return;
+ return false;
}
con_focus(next);
+ return true;
}
static void mark_unmapped(Con *con) {
cmd '[id="' . $right2->id . '"] focus';
is($x->input_focus, $right2->id, 'bottom right window focused');
+cmd 'focus parent';
+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');
is($x->input_focus, $right2->id, 'prevented focus change to different ws');
################################################################################
-# Same tests when we're in non-global fullscreen mode. We toggle fullscreen on
-# and off to avoid testing whether focus level works in fullscreen for now. It
-# should now be possible to focus a container in a different workspace.
+# Same tests when we're in non-global fullscreen mode. It should now be possible
+# to focus a container in a different workspace.
################################################################################
-cmd 'fullscreen global';
-cmd 'fullscreen global';
-
-cmd '[id="' . $right1->id . '"] focus';
-is($x->input_focus, $right1->id, 'upper right window focused');
-
cmd 'focus parent';
+cmd 'fullscreen global';
cmd 'fullscreen';
cmd '[id="' . $right1->id . '"] focus';
-is($x->input_focus, $right1->id, 'upper right window still focused');
+is($x->input_focus, $right1->id, 'upper right window focused');
cmd '[id="' . $right2->id . '"] focus';
is($x->input_focus, $right2->id, 'bottom right window focused');
+cmd 'focus parent';
+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');
+++ /dev/null
-#!perl
-# vim:ts=4:sw=4:expandtab
-#
-# Regression test: level up should be a noop during fullscreen mode
-#
-use i3test;
-
-my $tmp = fresh_workspace;
-
-#####################################################################
-# open a window, verify it’s not in fullscreen mode
-#####################################################################
-
-my $win = open_window;
-
-my $nodes = get_ws_content $tmp;
-is(@$nodes, 1, 'exactly one client');
-is($nodes->[0]->{fullscreen_mode}, 0, 'client not fullscreen');
-
-#####################################################################
-# make it fullscreen
-#####################################################################
-
-cmd 'nop making fullscreen';
-cmd 'fullscreen';
-
-$nodes = get_ws_content $tmp;
-is($nodes->[0]->{fullscreen_mode}, 1, 'client fullscreen now');
-
-#####################################################################
-# send level up, try to un-fullscreen
-#####################################################################
-cmd 'focus parent';
-cmd 'fullscreen';
-
-$nodes = get_ws_content $tmp;
-is($nodes->[0]->{fullscreen_mode}, 0, 'client not fullscreen any longer');
-
-does_i3_live;
-
-done_testing;