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
#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");
ok(@{$content->{nodes}} == 0, 'no tiling cons');
ok(@{$content->{floating_nodes}} == 1, 'one floating con');
-$window->destroy;
+kill_all_windows;
+exit_gracefully($pid);
+
+#####################################################################
+# test assignments to named outputs
+#####################################################################
+$config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+fake-outputs 1024x768+0+0,1024x768+1024+0,1024x768+1024+768,1024x768+0+768
+
+workspace ws-0 output fake-0
+workspace ws-1 output fake-1
+workspace ws-2 output fake-2
+workspace ws-3 output fake-3
+
+assign [class="special-0"] → output fake-0
+assign [class="special-1"] → output fake-1
+assign [class="special-2"] → output fake-2
+assign [class="special-3"] → output fake-3
+assign [class="special-4"] → output invalid
+
+EOT
+
+$pid = launch_with_config($config);
+
+sub open_in_output {
+ my ($num, $expected_count) = @_;
+ my $ws = "ws-$num";
+ my $class = "special-$num";
+ my $output = "fake-$num";
+
+ is_num_children($ws, $expected_count - 1,
+ "before: " . ($expected_count - 1) . " containers on output $output");
+ $window = open_special(wm_class => $class);
+ sync_with_i3;
+ is_num_children($ws, $expected_count,
+ "after: $expected_count containers on output $output");
+}
+
+cmd "workspace ws-0";
+open_in_output(0, 1);
+my $focused = $x->input_focus;
+
+open_in_output(1, 1);
+is($x->input_focus, $focused, 'focus remains on output fake-0');
+
+open_in_output(2, 1);
+is($x->input_focus, $focused, 'focus remains on output fake-0');
+
+for my $i (1 .. 5){
+ open_in_output(3, $i);
+ is($x->input_focus, $focused, 'focus remains on output fake-0');
+}
+
+# Check invalid output
+$tmp = fresh_workspace;
+open_special(wm_class => "special-4");
+sync_with_i3;
+is_num_children($tmp, 1, 'window assigned to invalid output opened in current workspace');
+open_special(wm_class => "special-3");
+sync_with_i3;
+is_num_children($tmp, 1, 'but window assigned to valid output did not');
+
+kill_all_windows;
+exit_gracefully($pid);
+
+#####################################################################
+# Test assignments to outputs with relative names
+#####################################################################
+$config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+fake-outputs 1024x768+0+0,1024x768+1024+0,1024x768+1024+768,1024x768+0+768
+
+workspace left-top output fake-0
+workspace right-top output fake-1
+workspace right-bottom output fake-2
+workspace left-bottom output fake-3
+
+assign [class="current"] → output current
+assign [class="left"] → output left
+assign [class="right"] → output right
+assign [class="up"] → output up
+assign [class="down"] → output down
+EOT
+
+$pid = launch_with_config($config);
+
+cmd 'workspace left-top';
+
+is_num_children('left-top', 0, 'no childreon on left-top');
+for my $i (1 .. 5){
+ open_special(wm_class => 'current');
+}
+sync_with_i3;
+is_num_children('left-top', 5, 'windows opened in current workspace');
+
+is_num_children('right-top', 0, 'no children on right-top');
+open_special(wm_class => 'right');
+sync_with_i3;
+is_num_children('right-top', 1, 'one child on right-top');
+
+is_num_children('left-bottom', 0, 'no children on left-bottom');
+open_special(wm_class => 'down');
+sync_with_i3;
+is_num_children('left-bottom', 1, 'one child on left-bottom');
+
+cmd 'workspace right-bottom';
+
+open_special(wm_class => 'up');
+sync_with_i3;
+is_num_children('right-top', 2, 'two children on right-top');
+
+open_special(wm_class => 'left');
+sync_with_i3;
+is_num_children('left-bottom', 2, 'two children on left-bottom');
+kill_all_windows;
exit_gracefully($pid);
#####################################################################