Use case: * When managing multiple terminals in a workspace, the borders makes it easier to know where the focus is, but when there is only one it's obvious where the focus is. * When there's only a web browser for example, the borders are actually counter- productive since it makes clicking a side scrollbar or a tab a bit harder (if I smash my cursor to the side or the top of the workspace, I have to move it in the other direction by just a few pixels to be able to grab it) Behaviour: * No borders when there's a single window in a workspace * Borders when there are multiple windows in a workspace fixes #2188
This commit is contained in:
parent
47562b4143
commit
4bec3b9d24
|
@ -610,11 +610,13 @@ new_window pixel 3
|
||||||
|
|
||||||
You can hide container borders adjacent to the screen edges using
|
You can hide container borders adjacent to the screen edges using
|
||||||
+hide_edge_borders+. This is useful if you are using scrollbars, or do not want
|
+hide_edge_borders+. This is useful if you are using scrollbars, or do not want
|
||||||
to waste even two pixels in displayspace. Default is none.
|
to waste even two pixels in displayspace. The "smart" setting hides borders on
|
||||||
|
workspaces with only one window visible, but keeps them on workspaces with
|
||||||
|
multiple windows visible. Default is none.
|
||||||
|
|
||||||
*Syntax*:
|
*Syntax*:
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
hide_edge_borders none|vertical|horizontal|both
|
hide_edge_borders none|vertical|horizontal|both|smart
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
|
||||||
*Example*:
|
*Example*:
|
||||||
|
|
|
@ -200,6 +200,13 @@ Con *con_for_window(Con *con, i3Window *window, Match **store_match);
|
||||||
*/
|
*/
|
||||||
int con_num_children(Con *con);
|
int con_num_children(Con *con);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of visible non-floating children of this container.
|
||||||
|
* For example, if the container contains a hsplit which has two children,
|
||||||
|
* this will return 2 instead of 1.
|
||||||
|
*/
|
||||||
|
int con_num_visible_children(Con *con);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count the number of windows (i.e., leaf containers).
|
* Count the number of windows (i.e., leaf containers).
|
||||||
*
|
*
|
||||||
|
|
|
@ -125,7 +125,7 @@ struct Config {
|
||||||
* This is useful if you are reaching scrollbar on the edge of the
|
* This is useful if you are reaching scrollbar on the edge of the
|
||||||
* screen or do not want to waste a single pixel of displayspace.
|
* screen or do not want to waste a single pixel of displayspace.
|
||||||
* By default, this is disabled. */
|
* By default, this is disabled. */
|
||||||
adjacent_t hide_edge_borders;
|
hide_edge_borders_mode_t hide_edge_borders;
|
||||||
|
|
||||||
/** By default, a workspace bar is drawn at the bottom of the screen.
|
/** By default, a workspace bar is drawn at the bottom of the screen.
|
||||||
* If you want to have a more fancy bar, it is recommended to replace
|
* If you want to have a more fancy bar, it is recommended to replace
|
||||||
|
|
|
@ -75,6 +75,12 @@ typedef enum { ADJ_NONE = 0,
|
||||||
ADJ_UPPER_SCREEN_EDGE = (1 << 2),
|
ADJ_UPPER_SCREEN_EDGE = (1 << 2),
|
||||||
ADJ_LOWER_SCREEN_EDGE = (1 << 4) } adjacent_t;
|
ADJ_LOWER_SCREEN_EDGE = (1 << 4) } adjacent_t;
|
||||||
|
|
||||||
|
typedef enum { HEBM_NONE = ADJ_NONE,
|
||||||
|
HEBM_VERTICAL = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE,
|
||||||
|
HEBM_HORIZONTAL = ADJ_UPPER_SCREEN_EDGE | ADJ_LOWER_SCREEN_EDGE,
|
||||||
|
HEBM_BOTH = HEBM_VERTICAL | HEBM_HORIZONTAL,
|
||||||
|
HEBM_SMART = (1 << 5) } hide_edge_borders_mode_t;
|
||||||
|
|
||||||
typedef enum { MM_REPLACE,
|
typedef enum { MM_REPLACE,
|
||||||
MM_ADD } mark_mode_t;
|
MM_ADD } mark_mode_t;
|
||||||
|
|
||||||
|
|
|
@ -122,10 +122,10 @@ state NEW_WINDOW_PIXELS_PX:
|
||||||
end
|
end
|
||||||
-> call cfg_new_window($windowtype, $border, &width)
|
-> call cfg_new_window($windowtype, $border, &width)
|
||||||
|
|
||||||
# hide_edge_borders <none|vertical|horizontal|both>
|
# hide_edge_borders <none|vertical|horizontal|both|smart>
|
||||||
# also hide_edge_borders <bool> for compatibility
|
# also hide_edge_borders <bool> for compatibility
|
||||||
state HIDE_EDGE_BORDERS:
|
state HIDE_EDGE_BORDERS:
|
||||||
hide_borders = 'none', 'vertical', 'horizontal', 'both'
|
hide_borders = 'none', 'vertical', 'horizontal', 'both', 'smart'
|
||||||
-> call cfg_hide_edge_borders($hide_borders)
|
-> call cfg_hide_edge_borders($hide_borders)
|
||||||
hide_borders = '1', 'yes', 'true', 'on', 'enable', 'active'
|
hide_borders = '1', 'yes', 'true', 'on', 'enable', 'active'
|
||||||
-> call cfg_hide_edge_borders($hide_borders)
|
-> call cfg_hide_edge_borders($hide_borders)
|
||||||
|
|
29
src/con.c
29
src/con.c
|
@ -727,6 +727,29 @@ int con_num_children(Con *con) {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of visible non-floating children of this container.
|
||||||
|
* For example, if the container contains a hsplit which has two children,
|
||||||
|
* this will return 2 instead of 1.
|
||||||
|
*/
|
||||||
|
int con_num_visible_children(Con *con) {
|
||||||
|
if (con == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int children = 0;
|
||||||
|
Con *current = NULL;
|
||||||
|
TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
|
||||||
|
/* Visible leaf nodes are a child. */
|
||||||
|
if (!con_is_hidden(current) && con_is_leaf(current))
|
||||||
|
children++;
|
||||||
|
/* All other containers need to be recursed. */
|
||||||
|
else
|
||||||
|
children += con_num_visible_children(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Count the number of windows (i.e., leaf containers).
|
* Count the number of windows (i.e., leaf containers).
|
||||||
*
|
*
|
||||||
|
@ -1444,6 +1467,12 @@ Con *con_descend_direction(Con *con, direction_t direction) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Rect con_border_style_rect(Con *con) {
|
Rect con_border_style_rect(Con *con) {
|
||||||
|
if (config.hide_edge_borders == HEBM_SMART && con_num_visible_children(con_get_workspace(con)) <= 1) {
|
||||||
|
if (!con_is_floating(con)) {
|
||||||
|
return (Rect){0, 0, 0, 0};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
adjacent_t borders_to_hide = ADJ_NONE;
|
adjacent_t borders_to_hide = ADJ_NONE;
|
||||||
int border_width = con->current_border_width;
|
int border_width = con->current_border_width;
|
||||||
DLOG("The border width for con is set to: %d\n", con->current_border_width);
|
DLOG("The border width for con is set to: %d\n", con->current_border_width);
|
||||||
|
|
|
@ -223,18 +223,20 @@ CFGFUN(new_window, const char *windowtype, const char *border, const long width)
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(hide_edge_borders, const char *borders) {
|
CFGFUN(hide_edge_borders, const char *borders) {
|
||||||
if (strcmp(borders, "vertical") == 0)
|
if (strcmp(borders, "smart") == 0)
|
||||||
config.hide_edge_borders = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE;
|
config.hide_edge_borders = HEBM_SMART;
|
||||||
|
else if (strcmp(borders, "vertical") == 0)
|
||||||
|
config.hide_edge_borders = HEBM_VERTICAL;
|
||||||
else if (strcmp(borders, "horizontal") == 0)
|
else if (strcmp(borders, "horizontal") == 0)
|
||||||
config.hide_edge_borders = ADJ_UPPER_SCREEN_EDGE | ADJ_LOWER_SCREEN_EDGE;
|
config.hide_edge_borders = HEBM_HORIZONTAL;
|
||||||
else if (strcmp(borders, "both") == 0)
|
else if (strcmp(borders, "both") == 0)
|
||||||
config.hide_edge_borders = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE | ADJ_UPPER_SCREEN_EDGE | ADJ_LOWER_SCREEN_EDGE;
|
config.hide_edge_borders = HEBM_BOTH;
|
||||||
else if (strcmp(borders, "none") == 0)
|
else if (strcmp(borders, "none") == 0)
|
||||||
config.hide_edge_borders = ADJ_NONE;
|
config.hide_edge_borders = HEBM_NONE;
|
||||||
else if (eval_boolstr(borders))
|
else if (eval_boolstr(borders))
|
||||||
config.hide_edge_borders = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE;
|
config.hide_edge_borders = HEBM_VERTICAL;
|
||||||
else
|
else
|
||||||
config.hide_edge_borders = ADJ_NONE;
|
config.hide_edge_borders = HEBM_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(focus_follows_mouse, const char *value) {
|
CFGFUN(focus_follows_mouse, const char *value) {
|
||||||
|
|
|
@ -286,6 +286,7 @@ hide_edge_borders none
|
||||||
hide_edge_borders vertical
|
hide_edge_borders vertical
|
||||||
hide_edge_borders horizontal
|
hide_edge_borders horizontal
|
||||||
hide_edge_borders both
|
hide_edge_borders both
|
||||||
|
hide_edge_borders smart
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
$expected = <<'EOT';
|
$expected = <<'EOT';
|
||||||
|
@ -293,6 +294,7 @@ cfg_hide_edge_borders(none)
|
||||||
cfg_hide_edge_borders(vertical)
|
cfg_hide_edge_borders(vertical)
|
||||||
cfg_hide_edge_borders(horizontal)
|
cfg_hide_edge_borders(horizontal)
|
||||||
cfg_hide_edge_borders(both)
|
cfg_hide_edge_borders(both)
|
||||||
|
cfg_hide_edge_borders(smart)
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
is(parser_calls($config),
|
is(parser_calls($config),
|
||||||
|
@ -464,7 +466,7 @@ client.focused #4c7899 #285577 #ffffff #2e9ef4
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
$expected = <<'EOT';
|
$expected = <<'EOT';
|
||||||
ERROR: CONFIG: Expected one of these tokens: 'none', 'vertical', 'horizontal', 'both', '1', 'yes', 'true', 'on', 'enable', 'active'
|
ERROR: CONFIG: Expected one of these tokens: 'none', 'vertical', 'horizontal', 'both', 'smart', '1', 'yes', 'true', 'on', 'enable', 'active'
|
||||||
ERROR: CONFIG: (in file <stdin>)
|
ERROR: CONFIG: (in file <stdin>)
|
||||||
ERROR: CONFIG: Line 1: hide_edge_borders FOOBAR
|
ERROR: CONFIG: Line 1: hide_edge_borders FOOBAR
|
||||||
ERROR: CONFIG: ^^^^^^
|
ERROR: CONFIG: ^^^^^^
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
#!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 the hide_edge_borders smart option works
|
||||||
|
# Ticket: #2188
|
||||||
|
|
||||||
|
use i3test i3_autostart => 0;
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
# 1: check that the borders are present on a floating windows
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
my $config = <<EOT;
|
||||||
|
# i3 config file (v4)
|
||||||
|
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
|
||||||
|
|
||||||
|
new_window pixel 2
|
||||||
|
new_float pixel 2
|
||||||
|
hide_edge_borders smart
|
||||||
|
EOT
|
||||||
|
|
||||||
|
my $pid = launch_with_config($config);
|
||||||
|
|
||||||
|
my $tmp = fresh_workspace;
|
||||||
|
|
||||||
|
ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
|
||||||
|
|
||||||
|
my $floatwindow = open_floating_window;
|
||||||
|
|
||||||
|
my $wscontent = get_ws($tmp);
|
||||||
|
|
||||||
|
my @floating = @{$wscontent->{floating_nodes}};
|
||||||
|
ok(@floating == 1, 'one floating container opened');
|
||||||
|
is($floating[0]->{nodes}[0]->{current_border_width}, 2, 'floating current border width set to 2');
|
||||||
|
is($floatwindow->rect->width, $floating[0]->{rect}->{width} - 2*2, 'floating border width 2');
|
||||||
|
|
||||||
|
exit_gracefully($pid);
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# 2: check that the borders are present on a workspace with two tiled
|
||||||
|
# windows visible
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
$config = <<EOT;
|
||||||
|
# i3 config file (v4)
|
||||||
|
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
|
||||||
|
|
||||||
|
new_window pixel 2
|
||||||
|
new_float pixel 2
|
||||||
|
hide_edge_borders smart
|
||||||
|
EOT
|
||||||
|
|
||||||
|
$pid = launch_with_config($config);
|
||||||
|
|
||||||
|
$tmp = fresh_workspace;
|
||||||
|
|
||||||
|
ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
|
||||||
|
|
||||||
|
my $tilewindow = open_window;
|
||||||
|
my $tilewindow2 = open_window;
|
||||||
|
|
||||||
|
$wscontent = get_ws($tmp);
|
||||||
|
|
||||||
|
my @tiled = @{$wscontent->{nodes}};
|
||||||
|
ok(@tiled == 2, 'two tiled container opened');
|
||||||
|
is($tiled[0]->{current_border_width}, 2, 'first tiled current border width set to 2');
|
||||||
|
is($tilewindow->rect->width, $tiled[0]->{rect}->{width} - 2*2, 'first tiled border width 2');
|
||||||
|
is($tiled[1]->{current_border_width}, 2, 'second tiled current border width set to 2');
|
||||||
|
is($tilewindow2->rect->width, $tiled[1]->{rect}->{width} - 2*2, 'second tiled border width 2');
|
||||||
|
|
||||||
|
exit_gracefully($pid);
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# 3: check that the borders are hidden on a workspace with one tiled
|
||||||
|
# window visible
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
$config = <<EOT;
|
||||||
|
# i3 config file (v4)
|
||||||
|
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
|
||||||
|
|
||||||
|
new_window pixel 2
|
||||||
|
new_float pixel 2
|
||||||
|
hide_edge_borders smart
|
||||||
|
EOT
|
||||||
|
|
||||||
|
$pid = launch_with_config($config);
|
||||||
|
|
||||||
|
$tmp = fresh_workspace;
|
||||||
|
|
||||||
|
ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
|
||||||
|
|
||||||
|
$tilewindow = open_window;
|
||||||
|
|
||||||
|
$wscontent = get_ws($tmp);
|
||||||
|
|
||||||
|
@tiled = @{$wscontent->{nodes}};
|
||||||
|
ok(@tiled == 1, 'one tiled container opened');
|
||||||
|
is($tiled[0]->{current_border_width}, 2, 'tiled current border width set to 2');
|
||||||
|
is($tilewindow->rect->width, $tiled[0]->{rect}->{width} - 2*0, 'single tiled border width 0');
|
||||||
|
|
||||||
|
exit_gracefully($pid);
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# 4: check that the borders are present on a workspace with two tiled
|
||||||
|
# windows visible, recursively
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
$config = <<EOT;
|
||||||
|
# i3 config file (v4)
|
||||||
|
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
|
||||||
|
|
||||||
|
new_window pixel 2
|
||||||
|
new_float pixel 2
|
||||||
|
hide_edge_borders smart
|
||||||
|
EOT
|
||||||
|
|
||||||
|
$pid = launch_with_config($config);
|
||||||
|
|
||||||
|
$tmp = fresh_workspace;
|
||||||
|
|
||||||
|
ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
|
||||||
|
|
||||||
|
$tilewindow = open_window;
|
||||||
|
$tilewindow2 = open_window;
|
||||||
|
ok(@{get_ws_content($tmp)} == 2, 'two containers opened');
|
||||||
|
|
||||||
|
cmd 'layout tabbed';
|
||||||
|
ok(@{get_ws_content($tmp)} == 1, 'layout tabbed -> back to one container');
|
||||||
|
|
||||||
|
cmd 'focus parent';
|
||||||
|
my $tilewindow3 = open_window;
|
||||||
|
ok(@{get_ws_content($tmp)} == 2, 'after split & new window, two containers');
|
||||||
|
|
||||||
|
$wscontent = get_ws($tmp);
|
||||||
|
|
||||||
|
@tiled = @{$wscontent->{nodes}};
|
||||||
|
ok(@tiled == 2, 'two tiled container opened in another container');
|
||||||
|
is($tiled[0]->{current_border_width}, -1, 'first tiled current border width set to -1');
|
||||||
|
is($tilewindow->rect->width, $tiled[0]->{rect}->{width} - 2*2, 'first tiled border width 2');
|
||||||
|
is($tiled[1]->{current_border_width}, 2, 'second tiled current border width set to 2');
|
||||||
|
is($tilewindow2->rect->width, $tiled[1]->{rect}->{width} - 2*2, 'second tiled border width 2');
|
||||||
|
|
||||||
|
exit_gracefully($pid);
|
||||||
|
|
||||||
|
done_testing;
|
Loading…
Reference in New Issue