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
|
||||
+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*:
|
||||
-----------------------------------------------
|
||||
hide_edge_borders none|vertical|horizontal|both
|
||||
hide_edge_borders none|vertical|horizontal|both|smart
|
||||
-----------------------------------------------
|
||||
|
||||
*Example*:
|
||||
|
|
|
@ -200,6 +200,13 @@ Con *con_for_window(Con *con, i3Window *window, Match **store_match);
|
|||
*/
|
||||
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).
|
||||
*
|
||||
|
|
|
@ -125,7 +125,7 @@ struct Config {
|
|||
* 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.
|
||||
* 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.
|
||||
* 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_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,
|
||||
MM_ADD } mark_mode_t;
|
||||
|
||||
|
|
|
@ -122,10 +122,10 @@ state NEW_WINDOW_PIXELS_PX:
|
|||
end
|
||||
-> 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
|
||||
state HIDE_EDGE_BORDERS:
|
||||
hide_borders = 'none', 'vertical', 'horizontal', 'both'
|
||||
hide_borders = 'none', 'vertical', 'horizontal', 'both', 'smart'
|
||||
-> call cfg_hide_edge_borders($hide_borders)
|
||||
hide_borders = '1', 'yes', 'true', 'on', 'enable', 'active'
|
||||
-> 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*
|
||||
|
@ -1444,6 +1467,12 @@ Con *con_descend_direction(Con *con, direction_t direction) {
|
|||
*
|
||||
*/
|
||||
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;
|
||||
int border_width = 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) {
|
||||
if (strcmp(borders, "vertical") == 0)
|
||||
config.hide_edge_borders = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE;
|
||||
if (strcmp(borders, "smart") == 0)
|
||||
config.hide_edge_borders = HEBM_SMART;
|
||||
else if (strcmp(borders, "vertical") == 0)
|
||||
config.hide_edge_borders = HEBM_VERTICAL;
|
||||
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)
|
||||
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)
|
||||
config.hide_edge_borders = ADJ_NONE;
|
||||
config.hide_edge_borders = HEBM_NONE;
|
||||
else if (eval_boolstr(borders))
|
||||
config.hide_edge_borders = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE;
|
||||
config.hide_edge_borders = HEBM_VERTICAL;
|
||||
else
|
||||
config.hide_edge_borders = ADJ_NONE;
|
||||
config.hide_edge_borders = HEBM_NONE;
|
||||
}
|
||||
|
||||
CFGFUN(focus_follows_mouse, const char *value) {
|
||||
|
|
|
@ -286,6 +286,7 @@ hide_edge_borders none
|
|||
hide_edge_borders vertical
|
||||
hide_edge_borders horizontal
|
||||
hide_edge_borders both
|
||||
hide_edge_borders smart
|
||||
EOT
|
||||
|
||||
$expected = <<'EOT';
|
||||
|
@ -293,6 +294,7 @@ cfg_hide_edge_borders(none)
|
|||
cfg_hide_edge_borders(vertical)
|
||||
cfg_hide_edge_borders(horizontal)
|
||||
cfg_hide_edge_borders(both)
|
||||
cfg_hide_edge_borders(smart)
|
||||
EOT
|
||||
|
||||
is(parser_calls($config),
|
||||
|
@ -464,7 +466,7 @@ client.focused #4c7899 #285577 #ffffff #2e9ef4
|
|||
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: Line 1: hide_edge_borders FOOBAR
|
||||
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