Fixes #2352.
=== Focus wrapping
-When in a container with several windows or child containers, the opposite
-window will be focused when trying to move the focus over the edge of a
-container (and there are no other containers in that direction) -- the focus
-wraps. If however there is another window or container in that direction, focus
-will be set on that window or container. This is the default behavior so you
-can navigate to all your windows without having to use +focus parent+.
+By default, when in a container with several windows or child containers, the
+opposite window will be focused when trying to move the focus over the edge of
+a container (and there are no other containers in that direction) -- the focus
+wraps.
+
+If desired, you can disable this behavior using the +focus_wrapping+
+configuration directive:
+
+*Syntax*:
+---------------------
+focus_wrapping yes|no
+---------------------
+
+*Example*:
+-----------------
+focus_wrapping no
+-----------------
+
+By default, focus wrapping does not occur if there is another window or
+container in the specified direction, and focus will instead be set on that
+window or container. This is the default behavior so you can navigate to all
+your windows without having to use +focus parent+.
If you want the focus to *always* wrap and you are aware of using +focus
parent+ to switch to different containers, you can use the
CFGFUN(workspace_back_and_forth, const char *value);
CFGFUN(focus_follows_mouse, const char *value);
CFGFUN(mouse_warping, const char *value);
+CFGFUN(focus_wrapping, const char *value);
CFGFUN(force_focus_wrapping, const char *value);
CFGFUN(force_xinerama, const char *value);
CFGFUN(disable_randr15, const char *value);
* comes with i3. Thus, you can turn it off entirely. */
bool disable_workspace_bar;
+ /** When focus wrapping is enabled (the default), attempting to
+ * move focus past the edge of the screen (in other words, in a
+ * direction in which there are no more containers to focus) will
+ * cause the focus to wrap to the opposite edge of the current
+ * container. When it is disabled, nothing happens; the current
+ * focus is preserved. */
+ bool focus_wrapping;
+
/** Think of the following layout: Horizontal workspace with a tabbed
* con on the left of the screen and a terminal on the right of the
* screen. You are in the second container in the tabbed container and
'no_focus' -> NO_FOCUS
'focus_follows_mouse' -> FOCUS_FOLLOWS_MOUSE
'mouse_warping' -> MOUSE_WARPING
+ 'focus_wrapping' -> FOCUS_WRAPPING
'force_focus_wrapping' -> FORCE_FOCUS_WRAPPING
'force_xinerama', 'force-xinerama' -> FORCE_XINERAMA
'disable_randr15', 'disable-randr15' -> DISABLE_RANDR15
value = 'none', 'output'
-> call cfg_mouse_warping($value)
+# focus_wrapping
+state FOCUS_WRAPPING:
+ value = word
+ -> call cfg_focus_wrapping($value)
+
# force_focus_wrapping
state FORCE_FOCUS_WRAPPING:
value = word
if (config.workspace_urgency_timer == 0)
config.workspace_urgency_timer = 0.5;
+ config.focus_wrapping = true;
+
parse_configuration(override_configpath, true);
if (reload) {
config.disable_randr15 = eval_boolstr(value);
}
+CFGFUN(focus_wrapping, const char *value) {
+ config.focus_wrapping = eval_boolstr(value);
+}
+
CFGFUN(force_focus_wrapping, const char *value) {
config.force_focus_wrapping = eval_boolstr(value);
}
*
*/
void tree_next(char way, orientation_t orientation) {
- _tree_next(focused, way, orientation, true);
+ _tree_next(focused, way, orientation, config.focus_wrapping);
}
/*
no_focus
focus_follows_mouse
mouse_warping
+ focus_wrapping
force_focus_wrapping
force_xinerama
force-xinerama
--- /dev/null
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • http://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • http://build.i3wm.org/docs/lib-i3test.html
+# (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • http://build.i3wm.org/docs/ipc.html
+# (or docs/ipc)
+#
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# (unless you are already familiar with Perl)
+#
+# Tests that focus does not wrap when focus_wrapping is disabled in
+# the configuration.
+# Ticket: #2352
+# Bug still in: 4.14-72-g6411130c
+use i3test i3_config => <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+focus_wrapping no
+EOT
+
+sub test_orientation {
+ my ($orientation, $prev, $next) = @_;
+ my $tmp = fresh_workspace;
+
+ cmd "split $orientation";
+
+ my $win1 = open_window;
+ my $win2 = open_window;
+
+ is($x->input_focus, $win2->id, "Second window focused initially");
+ cmd "focus $prev";
+ is($x->input_focus, $win1->id, "First window focused");
+ cmd "focus $prev";
+ is($x->input_focus, $win1->id, "First window still focused");
+ cmd "focus $next";
+ is($x->input_focus, $win2->id, "Second window focused");
+ cmd "focus $next";
+ is($x->input_focus, $win2->id, "Second window still focused");
+}
+
+test_orientation('v', 'up', 'down');
+test_orientation('h', 'left', 'right');
+
+done_testing;