window (mapping means actually displaying it on the screen), you’d need to have
to match on 'Firefox' in this case.
+You can also assign a window to show up on a specific output. You can use RandR
+names such as +VGA1+ or names relative to the output with the currently focused
+workspace such as +left+ and +down+.
+
Assignments are processed by i3 in the order in which they appear in the config
file. The first one which matches the window wins and later assignments are not
considered.
*Syntax*:
------------------------------------------------------------
assign <criteria> [→] [workspace] [number] <workspace>
+assign <criteria> [→] output left|right|up|down|primary|<output>
------------------------------------------------------------
*Examples*:
# Start urxvt -name irssi
assign [class="^URxvt$" instance="^irssi$"] → 3
+
+# Assign urxvt to the output right of the current one
+assign [class="^URxvt$"] → output right
+
+# Assign urxvt to the primary output
+assign [class="^URxvt$"] → output primary
----------------------
-Note that the arrow is not required, it just looks good :-). If you decide to
+Note that you might not have a primary output configured yet. To do so, run:
+-------------------------
+xrandr --output <output> --primary
+-------------------------
+
+Also, the arrow is not required, it just looks good :-). If you decide to
use it, it has to be a UTF-8 encoded arrow, not `->` or something like that.
To get the class and instance, you can use +xprop+. After clicking on the
second part is the class ("URxvt" in this example).
Should you have any problems with assignments, make sure to check the i3
-logfile first (see http://i3wm.org/docs/debugging.html). It includes more
+logfile first (see https://i3wm.org/docs/debugging.html). It includes more
details about the matching process and the window’s actual class, instance and
title when starting up.
=== Focus wrapping
- When being in a tabbed or stacked container, the first container will be
- focused when you use +focus down+ on the last container -- the focus wraps. If
- however there is another stacked/tabbed container in that direction, focus will
- be set on that 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 by setting the +focus_wrapping+
+ configuration directive to the value +no+.
+
+ When enabled, focus wrapping does not occur by default 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
- +force_focus_wrapping+ configuration directive. After enabling it, the focus
- will always wrap.
+ parent+ to switch to different containers, you can instead set +focus_wrapping+
+ to the value +force+.
*Syntax*:
---------------------------
- force_focus_wrapping yes|no
- ---------------------------
+ focus_wrapping yes|no|force
- *Example*:
- ------------------------
+ # Legacy syntax, equivalent to "focus_wrapping force"
force_focus_wrapping yes
- ------------------------
+ ---------------------------
+
+ *Examples*:
+ -----------------
+ # Disable focus wrapping
+ focus_wrapping no
+
+ # Force focus wrapping
+ focus_wrapping force
+ -----------------
=== Forcing Xinerama
-As explained in-depth in <http://i3wm.org/docs/multi-monitor.html>, some X11
+As explained in-depth in <https://i3wm.org/docs/multi-monitor.html>, some X11
video drivers (especially the nVidia binary driver) only provide support for
Xinerama instead of RandR. In such a situation, i3 must be told to use the
inferior Xinerama API explicitly and therefore don’t provide support for
bindsym $mod+x move container to output primary
--------------------------------------------------------
--------------------------------
Note that you might not have a primary output configured yet. To do so, run:
-------------------------
xrandr --output <output> --primary
[[shmlog]]
=== Enabling shared memory logging
-As described in http://i3wm.org/docs/debugging.html, i3 can log to a shared
+As described in https://i3wm.org/docs/debugging.html, i3 can log to a shared
memory buffer, which you can dump using +i3-dump-log+. The +shmlog+ command
allows you to enable or disable the shared memory logging at runtime.
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);
CFGFUN(focus_on_window_activation, const char *mode);
CFGFUN(show_marks, const char *value);
CFGFUN(hide_edge_borders, const char *borders);
+CFGFUN(assign_output, const char *output);
CFGFUN(assign, const char *workspace, bool is_number);
CFGFUN(no_focus);
CFGFUN(ipc_socket, const char *path);
POINTER_WARPING_OUTPUT = 0,
POINTER_WARPING_NONE = 1
} warping_t;
+
+ /**
+ * Focus wrapping modes.
+ */
+ typedef enum {
+ FOCUS_WRAPPING_OFF = 0,
+ FOCUS_WRAPPING_ON = 1,
+ FOCUS_WRAPPING_FORCE = 2
+ } focus_wrapping_t;
/**
* Stores a rectangle, for example the size of a window, the child window etc.
A_COMMAND = (1 << 0),
A_TO_WORKSPACE = (1 << 1),
A_NO_FOCUS = (1 << 2),
- A_TO_WORKSPACE_NUMBER = (1 << 3)
+ A_TO_WORKSPACE_NUMBER = (1 << 3),
+ A_TO_OUTPUT = (1 << 4)
} type;
/** the criteria to check if a window matches */
union {
char *command;
char *workspace;
+ char *output;
} dest;
TAILQ_ENTRY(Assignment)
'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
command = string
-> call cfg_for_window($command)
-# assign <criteria> [→] workspace
+# assign <criteria> [→] [workspace | output] <name>
state ASSIGN:
'['
-> call cfg_criteria_init(ASSIGN_WORKSPACE); CRITERIA
state ASSIGN_WORKSPACE:
'→'
->
+ 'output'
+ -> ASSIGN_OUTPUT
'workspace'
->
'number'
workspace = string
-> call cfg_assign($workspace, 0)
+state ASSIGN_OUTPUT:
+ output = string
+ -> call cfg_assign_output($output)
+
state ASSIGN_WORKSPACE_NUMBER:
number = string
-> call cfg_assign($number, 1)
value = 'none', 'output'
-> call cfg_mouse_warping($value)
+ # focus_wrapping
+ state FOCUS_WRAPPING:
+ value = '1', 'yes', 'true', 'on', 'enable', 'active', '0', 'no', 'false', 'off', 'disable', 'inactive', 'force'
+ -> call cfg_focus_wrapping($value)
+
# force_focus_wrapping
state FORCE_FOCUS_WRAPPING:
value = word
config.disable_randr15 = eval_boolstr(value);
}
+ CFGFUN(focus_wrapping, const char *value) {
+ if (strcmp(value, "force") == 0) {
+ config.focus_wrapping = FOCUS_WRAPPING_FORCE;
+ } else if (eval_boolstr(value)) {
+ config.focus_wrapping = FOCUS_WRAPPING_ON;
+ } else {
+ config.focus_wrapping = FOCUS_WRAPPING_OFF;
+ }
+ }
+
CFGFUN(force_focus_wrapping, const char *value) {
- config.force_focus_wrapping = eval_boolstr(value);
+ /* Legacy syntax. */
+ if (eval_boolstr(value)) {
+ config.focus_wrapping = FOCUS_WRAPPING_FORCE;
+ } else {
+ /* For "force_focus_wrapping off", don't enable or disable
+ * focus wrapping, just ensure it's not forced. */
+ if (config.focus_wrapping == FOCUS_WRAPPING_FORCE) {
+ config.focus_wrapping = FOCUS_WRAPPING_ON;
+ }
+ }
}
CFGFUN(workspace_back_and_forth, const char *value) {
#undef APPLY_COLORS
}
+CFGFUN(assign_output, const char *output) {
+ if (match_is_empty(current_match)) {
+ ELOG("Match is empty, ignoring this assignment\n");
+ return;
+ }
+
+ DLOG("New assignment, using above criteria, to output \"%s\".\n", output);
+ Assignment *assignment = scalloc(1, sizeof(Assignment));
+ match_copy(&(assignment->match), current_match);
+ assignment->type = A_TO_OUTPUT;
+ assignment->dest.output = sstrdup(output);
+ TAILQ_INSERT_TAIL(&assignments, assignment, assignments);
+}
+
CFGFUN(assign, const char *workspace, bool is_number) {
if (match_is_empty(current_match)) {
ELOG("Match is empty, ignoring this assignment\n");
* will be mapped when i3 closes its connection (e.g. when
* restarting). This is not what we want, since some apps keep
* unmapped windows around and don’t expect them to suddenly be
- * mapped. See http://bugs.i3wm.org/1617 */
+ * mapped. See https://bugs.i3wm.org/1617 */
xcb_change_save_set(conn, XCB_SET_MODE_DELETE, con->window->id);
/* Ignore X11 errors for the ReparentWindow request.
next = TAILQ_PREV(current, nodes_head, nodes);
if (!next) {
- if (!config.force_focus_wrapping) {
+ if (config.focus_wrapping != FOCUS_WRAPPING_FORCE) {
/* If there is no next/previous container, we check if we can focus one
* when going higher (without wrapping, though). If so, we are done, if
* not, we wrap */
*
*/
void tree_next(char way, orientation_t orientation) {
- _tree_next(focused, way, orientation, true);
+ _tree_next(focused, way, orientation,
+ config.focus_wrapping != FOCUS_WRAPPING_OFF);
}
/*
# vim:ts=4:sw=4:expandtab
#
# Please read the following documents before working on tests:
-# • http://build.i3wm.org/docs/testsuite.html
+# • https://build.i3wm.org/docs/testsuite.html
# (or docs/testsuite)
#
-# • http://build.i3wm.org/docs/lib-i3test.html
+# • https://build.i3wm.org/docs/lib-i3test.html
# (alternatively: perldoc ./testcases/lib/i3test.pm)
#
-# • http://build.i3wm.org/docs/ipc.html
+# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
no_focus
focus_follows_mouse
mouse_warping
+ focus_wrapping
force_focus_wrapping
force_xinerama
force-xinerama