implement bar { padding } config directive

related to https://github.com/i3/i3/issues/3724
related to https://github.com/i3/i3/pull/4288
fixes https://github.com/i3/i3/issues/3721
This commit is contained in:
Michael Stapelberg 2022-10-30 22:04:05 +01:00 committed by Michael Stapelberg
parent 327bca26d8
commit 0b89d4b2a7
12 changed files with 296 additions and 10 deletions

View File

@ -1980,6 +1980,49 @@ while +#000000FF+ will be a fully opaque black (the same as +#000000+).
Please note that due to the way the tray specification works, enabling this
flag will cause all tray icons to have a transparent background.
[[i3bar_padding]]
=== Padding
To make i3bar higher (without increasing the font size), and/or add padding to
the left and right side of i3bar, you can use the +padding+ directive:
*Syntax*:
--------------------------------------
bar {
# 2px left/right and 2px top/bottom padding
padding 2px
# 2px top/bottom padding, no left/right padding
padding 2px 0
# 2px top padding, no left/right padding, 4px bottom padding
padding 2px 0 4px
# four value syntax
padding top[px] right[px] bottom[px] left[px]
}
--------------------------------------
*Examples*:
--------------------------------------
bar {
# 2px left/right and 2px top/bottom padding
padding 2px
# 2px top/bottom padding, no left/right padding
padding 2px 0
# 2px top padding, no left/right padding, 4px bottom padding
padding 2px 0 4px
# 2px top padding, 6px right padding, 4px bottom padding, 1px left padding
padding 2px 6px 4px 1px
}
--------------------------------------
Note: As a convenience for users who migrate from i3-gaps to i3, the +height+
directive from i3-gaps is supported by i3, but should be changed to +padding+.
[[list_of_commands]]
== List of commands

View File

@ -38,12 +38,21 @@ typedef struct tray_output_t {
TAILQ_ENTRY(tray_output_t) tray_outputs;
} tray_output_t;
/* Matches i3/include/data.h */
struct Rect {
uint32_t x;
uint32_t y;
uint32_t width;
uint32_t height;
};
typedef struct config_t {
uint32_t modifier;
TAILQ_HEAD(bindings_head, binding_t) bindings;
position_t position;
bool verbose;
uint32_t bar_height;
struct Rect padding;
bool transparency;
struct xcb_color_strings_t colors;
bool disable_binding_mode_indicator;

View File

@ -19,6 +19,7 @@ config_t config;
static char *cur_key;
static bool parsing_bindings;
static bool parsing_tray_outputs;
static bool parsing_padding;
/*
* Parse a key.
@ -38,12 +39,17 @@ static int config_map_key_cb(void *params_, const unsigned char *keyVal, size_t
parsing_tray_outputs = true;
}
if (strcmp(cur_key, "padding") == 0) {
parsing_padding = true;
}
return 1;
}
static int config_end_array_cb(void *params_) {
parsing_bindings = false;
parsing_tray_outputs = false;
parsing_padding = false;
return 1;
}
@ -329,8 +335,31 @@ static int config_integer_cb(void *params_, long long val) {
return 0;
}
if (parsing_padding) {
if (strcmp(cur_key, "x") == 0) {
DLOG("padding.x = %lld\n", val);
config.padding.x = (uint32_t)val;
return 1;
}
if (strcmp(cur_key, "y") == 0) {
DLOG("padding.y = %lld\n", val);
config.padding.y = (uint32_t)val;
return 1;
}
if (strcmp(cur_key, "width") == 0) {
DLOG("padding.width = %lld\n", val);
config.padding.width = (uint32_t)val;
return 1;
}
if (strcmp(cur_key, "height") == 0) {
DLOG("padding.height = %lld\n", val);
config.padding.height = (uint32_t)val;
return 1;
}
}
if (!strcmp(cur_key, "bar_height")) {
DLOG("bar_height = %lld", val);
DLOG("bar_height = %lld\n", val);
config.bar_height = (uint32_t)val;
return 1;
}

View File

@ -59,7 +59,7 @@ xcb_visualtype_t *visual_type;
uint8_t depth;
xcb_colormap_t colormap;
/* Overall height of the size */
/* Overall height of the bar */
int bar_height;
/* These are only relevant for XKB, which we only need for grabbing modifiers */
@ -1357,13 +1357,24 @@ void init_xcb_late(char *fontname) {
DLOG("Calculated font-height: %d\n", font.height);
/*
* If the bar height was explicitly set, use it. Otherwise, calculate it
* based on the font size.
* If the bar height was explicitly set (but padding was not set), use
* it. Otherwise, calculate it based on the font size.
*/
if (config.bar_height <= 0)
bar_height = font.height + 2 * logical_px(ws_voff_px);
else
bar_height = config.bar_height;
const int default_px = font.height + 2 * logical_px(ws_voff_px);
int padding_scaled =
logical_px(config.padding.y) +
logical_px(config.padding.height);
if (config.bar_height > 0 &&
config.padding.x == 0 &&
config.padding.y == 0 &&
config.padding.width == 0 &&
config.padding.height == 0) {
padding_scaled = config.bar_height - default_px;
DLOG("setting padding_scaled=%d based on bar_height=%d\n", padding_scaled, config.bar_height);
} else {
DLOG("padding: x=%d, y=%d -> padding_scaled=%d\n", config.padding.x, config.padding.y, padding_scaled);
}
bar_height = default_px + padding_scaled;
icon_size = bar_height - 2 * logical_px(config.tray_padding);
if (config.separator_symbol)
@ -2006,7 +2017,7 @@ void draw_bars(bool unhide) {
i3_output *outputs_walk;
SLIST_FOREACH (outputs_walk, outputs, slist) {
int workspace_width = 0;
int workspace_width = logical_px(config.padding.x);
if (!outputs_walk->active) {
DLOG("Output %s inactive, skipping...\n", outputs_walk->name);
@ -2090,6 +2101,7 @@ void draw_bars(bool unhide) {
int16_t visible_statusline_width = MIN(statusline_width, max_statusline_width);
int x_dest = outputs_walk->rect.w - tray_width - logical_px((tray_width > 0) * sb_hoff_px) - visible_statusline_width;
x_dest -= logical_px(config.padding.width);
draw_statusline(outputs_walk, clip_left, use_focus_colors, use_short_text);
draw_util_copy_surface(&outputs_walk->statusline_buffer, &outputs_walk->buffer, 0, 0,

View File

@ -86,6 +86,10 @@ CFGFUN(bar_id, const char *bar_id);
CFGFUN(bar_output, const char *output);
CFGFUN(bar_verbose, const char *verbose);
CFGFUN(bar_height, const long height);
CFGFUN(bar_padding_one, const long all);
CFGFUN(bar_padding_two, const long top_and_bottom, const long right_and_left);
CFGFUN(bar_padding_three, const long top, const long right_and_left, const long bottom);
CFGFUN(bar_padding_four, const long top, const long right, const long bottom, const long left);
CFGFUN(bar_modifier, const char *modifiers);
CFGFUN(bar_wheel_up_cmd, const char *command);
CFGFUN(bar_wheel_down_cmd, const char *command);

View File

@ -358,6 +358,8 @@ struct Barconfig {
/** Defines the height of the bar in pixels. */
uint32_t bar_height;
struct Rect padding;
struct bar_colors {
char *background;
char *statusline;

View File

@ -511,6 +511,7 @@ state BAR:
'strip_workspace_name' -> BAR_STRIP_WORKSPACE_NAME
'verbose' -> BAR_VERBOSE
'height' -> BAR_HEIGHT
'padding' -> BAR_PADDING
'colors' -> BAR_COLORS_BRACE
'}'
-> call cfg_bar_finish(); INITIAL
@ -638,6 +639,40 @@ state BAR_HEIGHT:
value = number
-> call cfg_bar_height(&value); BAR
state BAR_PADDING:
top_or_all = number
-> BAR_PADDING_TOP
state BAR_PADDING_TOP:
'px'
->
right_or_right_and_left = number
-> BAR_PADDING_RIGHT
end
-> call cfg_bar_padding_one(&top_or_all); BAR
state BAR_PADDING_RIGHT:
'px'
->
bottom = number
-> BAR_PADDING_BOTTOM
end
-> call cfg_bar_padding_two(&top_or_all, &right_or_right_and_left); BAR
state BAR_PADDING_BOTTOM:
'px'
->
left = number
-> BAR_PADDING_LEFT
end
-> call cfg_bar_padding_three(&top_or_all, &right_or_right_and_left, &bottom); BAR
state BAR_PADDING_LEFT:
'px'
->
end
-> call cfg_bar_padding_four(&top_or_all, &right_or_right_and_left, &bottom, &left); BAR
state BAR_COLORS_BRACE:
end
->

View File

@ -0,0 +1 @@
i3bar: bar { padding } config directive now implemented (supports bar { height } from i3-gaps)

View File

@ -617,6 +617,46 @@ CFGFUN(bar_height, const long height) {
current_bar->bar_height = (uint32_t)height;
}
static void dlog_padding(void) {
DLOG("padding now: x=%d, y=%d, w=%d, h=%d\n",
current_bar->padding.x,
current_bar->padding.y,
current_bar->padding.width,
current_bar->padding.height);
}
CFGFUN(bar_padding_one, const long all) {
current_bar->padding.x = (uint32_t)all;
current_bar->padding.y = (uint32_t)all;
current_bar->padding.width = (uint32_t)all;
current_bar->padding.height = (uint32_t)all;
dlog_padding();
}
CFGFUN(bar_padding_two, const long top_and_bottom, const long right_and_left) {
current_bar->padding.x = (uint32_t)right_and_left;
current_bar->padding.y = (uint32_t)top_and_bottom;
current_bar->padding.width = (uint32_t)right_and_left;
current_bar->padding.height = (uint32_t)top_and_bottom;
dlog_padding();
}
CFGFUN(bar_padding_three, const long top, const long right_and_left, const long bottom) {
current_bar->padding.x = (uint32_t)right_and_left;
current_bar->padding.y = (uint32_t)top;
current_bar->padding.width = (uint32_t)right_and_left;
current_bar->padding.height = (uint32_t)bottom;
dlog_padding();
}
CFGFUN(bar_padding_four, const long top, const long right, const long bottom, const long left) {
current_bar->padding.x = (uint32_t)left;
current_bar->padding.y = (uint32_t)top;
current_bar->padding.width = (uint32_t)right;
current_bar->padding.height = (uint32_t)bottom;
dlog_padding();
}
CFGFUN(bar_modifier, const char *modifiers) {
current_bar->modifier = modifiers ? event_state_from_str(modifiers) : XCB_NONE;
}

View File

@ -802,6 +802,8 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
y(integer, config->bar_height);
}
dump_rect(gen, "padding", config->padding);
if (config->separator_symbol) {
ystr("separator_symbol");
ystr(config->separator_symbol);

View File

@ -124,6 +124,9 @@ bar {
# old syntax for compatibility with i3-gaps
height 50
# new syntax: top right bottom left
# y width height x
padding 4px 2px 4px 2px
}
EOT
@ -149,6 +152,13 @@ is($bar_config->{tray_padding}, 0, 'tray_padding ok');
is($bar_config->{font}, 'Terminus', 'font ok');
is($bar_config->{socket_path}, '/tmp/foobar', 'socket_path ok');
is($bar_config->{bar_height}, 50, 'bar_height ok');
is_deeply($bar_config->{padding},
{
x => 2,
y => 4,
width => 2,
height => 4,
}, 'padding ok');
is_deeply($bar_config->{colors},
{
background => '#ff0000',
@ -175,6 +185,105 @@ is_deeply($bar_config->{colors},
exit_gracefully($pid);
#####################################################################
# validate one-value padding directive
#####################################################################
$config = <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
bar {
# all padding is 25px
padding 25px
}
EOT
$pid = launch_with_config($config);
$i3 = i3(get_socket_path(0));
$bars = $i3->get_bar_config()->recv;
is(@$bars, 1, 'one bar configured');
$bar_id = shift @$bars;
$bar_config = $i3->get_bar_config($bar_id)->recv;
is_deeply($bar_config->{padding},
{
x => 25,
y => 25,
width => 25,
height => 25,
}, 'padding ok');
exit_gracefully($pid);
#####################################################################
# validate two-value padding directive
#####################################################################
$config = <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
bar {
# top and bottom padding is 25px, right and left padding is 50px
padding 25px 50px
}
EOT
$pid = launch_with_config($config);
$i3 = i3(get_socket_path(0));
$bars = $i3->get_bar_config()->recv;
is(@$bars, 1, 'one bar configured');
$bar_id = shift @$bars;
$bar_config = $i3->get_bar_config($bar_id)->recv;
is_deeply($bar_config->{padding},
{
x => 50,
y => 25,
width => 50,
height => 25,
}, 'padding ok');
exit_gracefully($pid);
#####################################################################
# validate three-value padding directive
#####################################################################
$config = <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
bar {
# top padding is 25px, right and left padding is 50px, bottom padding is 75px
padding 25px 50px 75px
}
EOT
$pid = launch_with_config($config);
$i3 = i3(get_socket_path(0));
$bars = $i3->get_bar_config()->recv;
is(@$bars, 1, 'one bar configured');
$bar_id = shift @$bars;
$bar_config = $i3->get_bar_config($bar_id)->recv;
is_deeply($bar_config->{padding},
{
x => 50,
y => 25,
width => 50,
height => 75,
}, 'padding ok');
exit_gracefully($pid);
#####################################################################
# ensure that multiple bars get different IDs
#####################################################################

View File

@ -773,7 +773,7 @@ EOT
$expected = <<'EOT';
cfg_bar_start()
cfg_bar_output(LVDS-1)
ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'wheel_up_cmd', 'wheel_down_cmd', 'bindsym', 'position', 'output', 'tray_output', 'tray_padding', 'font', 'separator_symbol', 'binding_mode_indicator', 'workspace_buttons', 'workspace_min_width', 'strip_workspace_numbers', 'strip_workspace_name', 'verbose', 'height', 'colors', '}'
ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'wheel_up_cmd', 'wheel_down_cmd', 'bindsym', 'position', 'output', 'tray_output', 'tray_padding', 'font', 'separator_symbol', 'binding_mode_indicator', 'workspace_buttons', 'workspace_min_width', 'strip_workspace_numbers', 'strip_workspace_name', 'verbose', 'height', 'padding', 'colors', '}'
ERROR: CONFIG: (in file <stdin>)
ERROR: CONFIG: Line 1: bar {
ERROR: CONFIG: Line 2: output LVDS-1