Add support for a custom separator symbol
This introduces a "separator_symbol" property for the i3bar configuration. If set, the specified string will be used as a separator instead of a vertical line. Since it is an optional configuration, complete backwards compatibility is given. fixes #1472
This commit is contained in:
parent
c0a0b99d86
commit
80da100ac8
|
@ -1249,6 +1249,24 @@ bar {
|
||||||
}
|
}
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
=== Custom separator symbol
|
||||||
|
|
||||||
|
Specifies a custom symbol to be used for the separator as opposed to the vertical,
|
||||||
|
one pixel thick separator. Note that you may have to adjust the +sep_block_width+
|
||||||
|
property.
|
||||||
|
|
||||||
|
*Syntax*:
|
||||||
|
-------------------------
|
||||||
|
separator_symbol <symbol>
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
*Example*:
|
||||||
|
------------------------
|
||||||
|
bar {
|
||||||
|
separator_symbol ":|:"
|
||||||
|
}
|
||||||
|
------------------------
|
||||||
|
|
||||||
=== Workspace buttons
|
=== Workspace buttons
|
||||||
|
|
||||||
Specifies whether workspace buttons should be shown or not. This is useful if
|
Specifies whether workspace buttons should be shown or not. This is useful if
|
||||||
|
|
|
@ -35,6 +35,7 @@ typedef struct config_t {
|
||||||
char *bar_id;
|
char *bar_id;
|
||||||
char *command;
|
char *command;
|
||||||
char *fontname;
|
char *fontname;
|
||||||
|
i3String *separator_symbol;
|
||||||
char *tray_output;
|
char *tray_output;
|
||||||
int num_outputs;
|
int num_outputs;
|
||||||
char **outputs;
|
char **outputs;
|
||||||
|
|
|
@ -144,6 +144,13 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(cur_key, "separator_symbol")) {
|
||||||
|
DLOG("separator = %.*s\n", len, val);
|
||||||
|
I3STRING_FREE(config.separator_symbol);
|
||||||
|
config.separator_symbol = i3string_from_utf8_with_length((const char *)val, len);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(cur_key, "outputs")) {
|
if (!strcmp(cur_key, "outputs")) {
|
||||||
DLOG("+output %.*s\n", len, val);
|
DLOG("+output %.*s\n", len, val);
|
||||||
int new_num_outputs = config.num_outputs + 1;
|
int new_num_outputs = config.num_outputs + 1;
|
||||||
|
|
|
@ -63,6 +63,9 @@ static i3Font font;
|
||||||
/* Overall height of the bar (based on font size) */
|
/* Overall height of the bar (based on font size) */
|
||||||
int bar_height;
|
int bar_height;
|
||||||
|
|
||||||
|
/* Cached width of the custom separator if one was set */
|
||||||
|
int separator_symbol_width;
|
||||||
|
|
||||||
/* These are only relevant for XKB, which we only need for grabbing modifiers */
|
/* These are only relevant for XKB, which we only need for grabbing modifiers */
|
||||||
int xkb_base;
|
int xkb_base;
|
||||||
int mod_pressed = 0;
|
int mod_pressed = 0;
|
||||||
|
@ -155,6 +158,33 @@ int get_tray_width(struct tc_head *trayclients) {
|
||||||
return tray_width;
|
return tray_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draws a separator for the given block if necessary.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void draw_separator(uint32_t x, struct status_block *block) {
|
||||||
|
uint32_t sep_offset = get_sep_offset(block);
|
||||||
|
if (TAILQ_NEXT(block, blocks) == NULL || sep_offset == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t center_x = x - sep_offset;
|
||||||
|
if (config.separator_symbol == NULL) {
|
||||||
|
/* Draw a classic one pixel, vertical separator. */
|
||||||
|
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_LINE_WIDTH;
|
||||||
|
uint32_t values[] = {colors.sep_fg, colors.bar_bg, logical_px(1)};
|
||||||
|
xcb_change_gc(xcb_connection, statusline_ctx, mask, values);
|
||||||
|
xcb_poly_line(xcb_connection, XCB_COORD_MODE_ORIGIN, statusline_pm, statusline_ctx, 2,
|
||||||
|
(xcb_point_t[]){{center_x, logical_px(sep_voff_px)},
|
||||||
|
{center_x, bar_height - logical_px(sep_voff_px)}});
|
||||||
|
} else {
|
||||||
|
/* Draw a custom separator. */
|
||||||
|
uint32_t separator_x = MAX(x - block->sep_block_width, center_x - separator_symbol_width / 2);
|
||||||
|
set_font_colors(statusline_ctx, colors.sep_fg, colors.bar_bg);
|
||||||
|
draw_text(config.separator_symbol, statusline_pm, statusline_ctx,
|
||||||
|
separator_x, logical_px(ws_voff_px), x - separator_x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Redraws the statusline to the buffer
|
* Redraws the statusline to the buffer
|
||||||
*
|
*
|
||||||
|
@ -245,17 +275,8 @@ void refresh_statusline(bool use_short_text) {
|
||||||
draw_text(block->full_text, statusline_pm, statusline_ctx, x + block->x_offset, logical_px(ws_voff_px), block->width);
|
draw_text(block->full_text, statusline_pm, statusline_ctx, x + block->x_offset, logical_px(ws_voff_px), block->width);
|
||||||
x += block->width + block->sep_block_width + block->x_offset + block->x_append;
|
x += block->width + block->sep_block_width + block->x_offset + block->x_append;
|
||||||
|
|
||||||
uint32_t sep_offset = get_sep_offset(block);
|
/* If this is not the last block, draw a separator. */
|
||||||
if (TAILQ_NEXT(block, blocks) != NULL && sep_offset > 0) {
|
draw_separator(x, block);
|
||||||
/* This is not the last block, draw a separator. */
|
|
||||||
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_LINE_WIDTH;
|
|
||||||
uint32_t values[] = {colors.sep_fg, colors.bar_bg, logical_px(1)};
|
|
||||||
xcb_change_gc(xcb_connection, statusline_ctx, mask, values);
|
|
||||||
xcb_poly_line(xcb_connection, XCB_COORD_MODE_ORIGIN, statusline_pm,
|
|
||||||
statusline_ctx, 2,
|
|
||||||
(xcb_point_t[]){{x - sep_offset, logical_px(sep_voff_px)},
|
|
||||||
{x - sep_offset, bar_height - logical_px(sep_voff_px)}});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1198,6 +1219,9 @@ void init_xcb_late(char *fontname) {
|
||||||
DLOG("Calculated font height: %d\n", font.height);
|
DLOG("Calculated font height: %d\n", font.height);
|
||||||
bar_height = font.height + 2 * logical_px(ws_voff_px);
|
bar_height = font.height + 2 * logical_px(ws_voff_px);
|
||||||
|
|
||||||
|
if (config.separator_symbol)
|
||||||
|
separator_symbol_width = predict_text_width(config.separator_symbol);
|
||||||
|
|
||||||
xcb_flush(xcb_connection);
|
xcb_flush(xcb_connection);
|
||||||
|
|
||||||
if (config.hide_on_modifier == M_HIDE)
|
if (config.hide_on_modifier == M_HIDE)
|
||||||
|
|
|
@ -285,6 +285,9 @@ struct Barconfig {
|
||||||
/** Font specification for all text rendered on the bar. */
|
/** Font specification for all text rendered on the bar. */
|
||||||
char *font;
|
char *font;
|
||||||
|
|
||||||
|
/** A custom separator to use instead of a vertical line. */
|
||||||
|
char *separator_symbol;
|
||||||
|
|
||||||
/** Hide workspace buttons? Configuration option is 'workspace_buttons no'
|
/** Hide workspace buttons? Configuration option is 'workspace_buttons no'
|
||||||
* but we invert the bool to get the correct default when initializing with
|
* but we invert the bool to get the correct default when initializing with
|
||||||
* zero. */
|
* zero. */
|
||||||
|
|
|
@ -67,6 +67,7 @@ CFGFUN(enter_mode, const char *mode);
|
||||||
CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command);
|
CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command);
|
||||||
|
|
||||||
CFGFUN(bar_font, const char *font);
|
CFGFUN(bar_font, const char *font);
|
||||||
|
CFGFUN(bar_separator_symbol, const char *separator);
|
||||||
CFGFUN(bar_mode, const char *mode);
|
CFGFUN(bar_mode, const char *mode);
|
||||||
CFGFUN(bar_hidden_state, const char *hidden_state);
|
CFGFUN(bar_hidden_state, const char *hidden_state);
|
||||||
CFGFUN(bar_id, const char *bar_id);
|
CFGFUN(bar_id, const char *bar_id);
|
||||||
|
|
|
@ -370,6 +370,7 @@ state BAR:
|
||||||
'output' -> BAR_OUTPUT
|
'output' -> BAR_OUTPUT
|
||||||
'tray_output' -> BAR_TRAY_OUTPUT
|
'tray_output' -> BAR_TRAY_OUTPUT
|
||||||
'font' -> BAR_FONT
|
'font' -> BAR_FONT
|
||||||
|
'separator_symbol' -> BAR_SEPARATOR_SYMBOL
|
||||||
'binding_mode_indicator' -> BAR_BINDING_MODE_INDICATOR
|
'binding_mode_indicator' -> BAR_BINDING_MODE_INDICATOR
|
||||||
'workspace_buttons' -> BAR_WORKSPACE_BUTTONS
|
'workspace_buttons' -> BAR_WORKSPACE_BUTTONS
|
||||||
'strip_workspace_numbers' -> BAR_STRIP_WORKSPACE_NUMBERS
|
'strip_workspace_numbers' -> BAR_STRIP_WORKSPACE_NUMBERS
|
||||||
|
@ -435,6 +436,10 @@ state BAR_FONT:
|
||||||
font = string
|
font = string
|
||||||
-> call cfg_bar_font($font); BAR
|
-> call cfg_bar_font($font); BAR
|
||||||
|
|
||||||
|
state BAR_SEPARATOR_SYMBOL:
|
||||||
|
separator = string
|
||||||
|
-> call cfg_bar_separator_symbol($separator); BAR
|
||||||
|
|
||||||
state BAR_BINDING_MODE_INDICATOR:
|
state BAR_BINDING_MODE_INDICATOR:
|
||||||
value = word
|
value = word
|
||||||
-> call cfg_bar_binding_mode_indicator($value); BAR
|
-> call cfg_bar_binding_mode_indicator($value); BAR
|
||||||
|
|
|
@ -421,6 +421,11 @@ CFGFUN(bar_font, const char *font) {
|
||||||
current_bar.font = sstrdup(font);
|
current_bar.font = sstrdup(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CFGFUN(bar_separator_symbol, const char *separator) {
|
||||||
|
FREE(current_bar.separator_symbol);
|
||||||
|
current_bar.separator_symbol = sstrdup(separator);
|
||||||
|
}
|
||||||
|
|
||||||
CFGFUN(bar_mode, const char *mode) {
|
CFGFUN(bar_mode, const char *mode) {
|
||||||
current_bar.mode = (strcmp(mode, "dock") == 0 ? M_DOCK : (strcmp(mode, "hide") == 0 ? M_HIDE : M_INVISIBLE));
|
current_bar.mode = (strcmp(mode, "dock") == 0 ? M_DOCK : (strcmp(mode, "hide") == 0 ? M_HIDE : M_INVISIBLE));
|
||||||
}
|
}
|
||||||
|
|
|
@ -594,6 +594,11 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
|
||||||
YSTR_IF_SET(status_command);
|
YSTR_IF_SET(status_command);
|
||||||
YSTR_IF_SET(font);
|
YSTR_IF_SET(font);
|
||||||
|
|
||||||
|
if (config->separator_symbol) {
|
||||||
|
ystr("separator_symbol");
|
||||||
|
ystr(config->separator_symbol);
|
||||||
|
}
|
||||||
|
|
||||||
ystr("workspace_buttons");
|
ystr("workspace_buttons");
|
||||||
y(bool, !config->hide_workspace_buttons);
|
y(bool, !config->hide_workspace_buttons);
|
||||||
|
|
||||||
|
|
|
@ -647,7 +647,7 @@ EOT
|
||||||
|
|
||||||
$expected = <<'EOT';
|
$expected = <<'EOT';
|
||||||
cfg_bar_output(LVDS-1)
|
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', 'position', 'output', 'tray_output', 'font', 'binding_mode_indicator', 'workspace_buttons', 'strip_workspace_numbers', 'verbose', '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', 'position', 'output', 'tray_output', 'font', 'separator_symbol', 'binding_mode_indicator', 'workspace_buttons', 'strip_workspace_numbers', 'verbose', 'colors', '}'
|
||||||
ERROR: CONFIG: (in file <stdin>)
|
ERROR: CONFIG: (in file <stdin>)
|
||||||
ERROR: CONFIG: Line 1: bar {
|
ERROR: CONFIG: Line 1: bar {
|
||||||
ERROR: CONFIG: Line 2: output LVDS-1
|
ERROR: CONFIG: Line 2: output LVDS-1
|
||||||
|
|
Loading…
Reference in New Issue