i3 User’s Guide
===============
Michael Stapelberg <michael@i3wm.org>
-March 2013
This document contains all the information you need to configure and use the i3
window manager. If it does not, please check https://www.reddit.com/r/i3wm/
workspace_layout tabbed
---------------------
-=== Border style for new windows
+=== Default border style for new windows
This option determines which border style new windows will have. The default is
-+normal+. Note that new_float applies only to windows which are starting out as
++normal+. Note that default_floating_border applies only to windows which are starting out as
floating windows, e.g., dialog windows, but not windows that are floated later on.
*Syntax*:
---------------------------------------------
-new_window normal|none|pixel
-new_window normal|pixel <px>
-new_float normal|none|pixel
-new_float normal|pixel <px>
+default_border normal|none|pixel
+default_border normal|pixel <px>
+default_floating_border normal|none|pixel
+default_floating_border normal|pixel <px>
---------------------------------------------
+Please note that +new_window+ and +new_float+ have been deprecated in favor of the above options
+and will be removed in a future release. We strongly recommend using the new options instead.
+
*Example*:
---------------------
-new_window pixel
+default_border pixel
---------------------
The "normal" and "pixel" border styles support an optional border width in
*Example*:
---------------------
-# The same as new_window none
-new_window pixel 0
+# The same as default_border none
+default_border pixel 0
# A 3 px border
-new_window pixel 3
+default_border pixel 3
---------------------
CFGFUN(color, const char *colorclass, const char *border, const char *background, const char *text, const char *indicator, const char *child_border);
CFGFUN(color_single, const char *colorclass, const char *color);
CFGFUN(floating_modifier, const char *modifiers);
-CFGFUN(new_window, const char *windowtype, const char *border, const long width);
+CFGFUN(default_border, const char *windowtype, const char *border, const long width);
CFGFUN(workspace, const char *workspace, const char *output);
CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *exclude_titlebar, const char *command);
'floating_modifier' -> FLOATING_MODIFIER
'default_orientation' -> DEFAULT_ORIENTATION
'workspace_layout' -> WORKSPACE_LAYOUT
- windowtype = 'new_window', 'new_float' -> NEW_WINDOW
+ windowtype = 'default_border', 'new_window', 'default_floating_border', 'new_float'
+ -> DEFAULT_BORDER
'hide_edge_borders' -> HIDE_EDGE_BORDERS
'for_window' -> FOR_WINDOW
'assign' -> ASSIGN
layout = 'default', 'stacking', 'stacked', 'tabbed'
-> call cfg_workspace_layout($layout)
-# new_window <normal|1pixel|none>
-# new_float <normal|1pixel|none>
-state NEW_WINDOW:
+# <default_border|new_window> <normal|1pixel|none>
+# <default_floating_border|new_float> <normal|1pixel|none>
+state DEFAULT_BORDER:
border = 'normal', 'pixel'
- -> NEW_WINDOW_PIXELS
+ -> DEFAULT_BORDER_PIXELS
border = '1pixel', 'none'
- -> call cfg_new_window($windowtype, $border, -1)
+ -> call cfg_default_border($windowtype, $border, -1)
-state NEW_WINDOW_PIXELS:
+state DEFAULT_BORDER_PIXELS:
end
- -> call cfg_new_window($windowtype, $border, 2)
+ -> call cfg_default_border($windowtype, $border, 2)
width = number
- -> NEW_WINDOW_PIXELS_PX
+ -> DEFAULT_BORDER_PIXELS_PX
-state NEW_WINDOW_PIXELS_PX:
+state DEFAULT_BORDER_PIXELS_PX:
'px'
->
end
- -> call cfg_new_window($windowtype, $border, &width)
+ -> call cfg_default_border($windowtype, $border, &width)
# hide_edge_borders <none|vertical|horizontal|both|smart>
# also hide_edge_borders <bool> for compatibility
config.default_layout = L_TABBED;
}
-CFGFUN(new_window, const char *windowtype, const char *border, const long width) {
+CFGFUN(default_border, const char *windowtype, const char *border, const long width) {
int border_style;
int border_width;
border_width = width;
}
- if (strcmp(windowtype, "new_window") == 0) {
+ if ((strcmp(windowtype, "default_border") == 0) ||
+ (strcmp(windowtype, "new_window") == 0)) {
DLOG("default tiled border style = %d and border width = %d (%d physical px)\n",
border_style, border_width, logical_px(border_width));
config.default_border = border_style;
DLOG("parent container killed\n");
}
+ if (ws == con) {
+ DLOG("Closing a workspace container, updating EWMH atoms\n");
+ ewmh_update_number_of_desktops();
+ ewmh_update_desktop_names();
+ ewmh_update_wm_desktop();
+ }
+
con_free(con);
/* in the case of floating windows, we already focused another container
$config = <<'EOT';
floating_minimum_size 80x55
-floating_minimum_size 80 x 55
+floating_minimum_size 80 x 55
floating_maximum_size 73 x 10
EOT
################################################################################
$config = <<'EOT';
-workspace "3" output DP-1
-workspace "3" output VGA-1
+workspace "3" output DP-1
+workspace "3" output VGA-1
EOT
$expected = <<'EOT';
new_window 1pixel
new_window normal
new_window none
+default_border 1pixel
+default_border normal
+default_border none
new_float 1pixel
new_float normal
new_float none
+default_floating_border 1pixel
+default_floating_border normal
+default_floating_border none
EOT
$expected = <<'EOT';
-cfg_new_window(new_window, 1pixel, -1)
-cfg_new_window(new_window, normal, 2)
-cfg_new_window(new_window, none, -1)
-cfg_new_window(new_float, 1pixel, -1)
-cfg_new_window(new_float, normal, 2)
-cfg_new_window(new_float, none, -1)
-EOT
+cfg_default_border(new_window, 1pixel, -1)
+cfg_default_border(new_window, normal, 2)
+cfg_default_border(new_window, none, -1)
+cfg_default_border(default_border, 1pixel, -1)
+cfg_default_border(default_border, normal, 2)
+cfg_default_border(default_border, none, -1)
+cfg_default_border(new_float, 1pixel, -1)
+cfg_default_border(new_float, normal, 2)
+cfg_default_border(new_float, none, -1)
+cfg_default_border(default_floating_border, 1pixel, -1)
+cfg_default_border(default_floating_border, normal, 2)
+cfg_default_border(default_floating_border, none, -1)
+EOT
+
+# TODO: are there no tests for "border pixel 1" etc?
is(parser_calls($config),
$expected,
floating_modifier
default_orientation
workspace_layout
+ default_border
new_window
+ default_floating_border
new_float
hide_edge_borders
for_window
--- /dev/null
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • https://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • https://build.i3wm.org/docs/lib-i3test.html
+# (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • https://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)
+#
+# Verifies _NET_DESKTOP_NAMES, _NET_CURRENT_DESKTOP and _NET_CURRENT_DESKTOP
+# are updated properly when closing an inactive workspace container.
+# See github issue #3126
+
+use i3test;
+
+sub get_desktop_names {
+ sync_with_i3;
+
+ my $cookie = $x->get_property(
+ 0,
+ $x->get_root_window(),
+ $x->atom(name => '_NET_DESKTOP_NAMES')->id,
+ $x->atom(name => 'UTF8_STRING')->id,
+ 0,
+ 4096,
+ );
+
+ my $reply = $x->get_property_reply($cookie->{sequence});
+
+ return 0 if $reply->{value_len} == 0;
+
+ # the property is a null-delimited list of utf8 strings ;;
+ return split /\0/, $reply->{value};
+}
+
+sub get_num_of_desktops {
+ sync_with_i3;
+
+ my $cookie = $x->get_property(
+ 0,
+ $x->get_root_window(),
+ $x->atom(name => '_NET_NUMBER_OF_DESKTOPS')->id,
+ $x->atom(name => 'CARDINAL')->id,
+ 0,
+ 4,
+ );
+
+ my $reply = $x->get_property_reply($cookie->{sequence});
+
+ return undef if $reply->{value_len} != 1;
+ return undef if $reply->{format} != 32;
+ return undef if $reply->{type} != $x->atom(name => 'CARDINAL')->id,;
+
+ return unpack 'L', $reply->{value};
+}
+
+sub get_current_desktop {
+ sync_with_i3;
+
+ my $cookie = $x->get_property(
+ 0,
+ $x->get_root_window(),
+ $x->atom(name => '_NET_CURRENT_DESKTOP')->id,
+ $x->atom(name => 'CARDINAL')->id,
+ 0,
+ 4,
+ );
+
+ my $reply = $x->get_property_reply($cookie->{sequence});
+
+ return undef if $reply->{value_len} != 1;
+ return undef if $reply->{format} != 32;
+ return undef if $reply->{type} != $x->atom(name => 'CARDINAL')->id,;
+
+ return unpack 'L', $reply->{value};
+}
+
+cmd 'workspace 0';
+my $first = open_window;
+
+cmd 'workspace 1';
+my $second = open_window;
+
+cmd 'workspace 2';
+my $third = open_window;
+
+# Sanity check
+is(get_current_desktop, 2);
+is(get_num_of_desktops, 3);
+my @actual_names = get_desktop_names;
+my @expected_names = ('0', '1', '2');
+is_deeply(\@actual_names, \@expected_names);
+
+# Kill first window to close a workspace.
+cmd '[id="' . $second->id . '"] kill';
+
+is(get_current_desktop, 2, '_NET_CURRENT_DESKTOP should be updated');
+is(get_num_of_desktops, 2, '_NET_NUMBER_OF_DESKTOPS should be updated');
+my @actual_names = get_desktop_names;
+my @expected_names = ('0', '2');
+is_deeply(\@actual_names, \@expected_names, '_NET_DESKTOP_NAMES should be updated');
+
+
+done_testing;