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
next
Ingo Bürk 2015-03-24 23:07:25 +01:00
parent c0a0b99d86
commit 80da100ac8
10 changed files with 81 additions and 12 deletions

View File

@ -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
Specifies whether workspace buttons should be shown or not. This is useful if

View File

@ -35,6 +35,7 @@ typedef struct config_t {
char *bar_id;
char *command;
char *fontname;
i3String *separator_symbol;
char *tray_output;
int num_outputs;
char **outputs;

View File

@ -144,6 +144,13 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len
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")) {
DLOG("+output %.*s\n", len, val);
int new_num_outputs = config.num_outputs + 1;

View File

@ -63,6 +63,9 @@ static i3Font font;
/* Overall height of the bar (based on font size) */
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 */
int xkb_base;
int mod_pressed = 0;
@ -155,6 +158,33 @@ int get_tray_width(struct tc_head *trayclients) {
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
*
@ -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);
x += block->width + block->sep_block_width + block->x_offset + block->x_append;
uint32_t sep_offset = get_sep_offset(block);
if (TAILQ_NEXT(block, blocks) != NULL && sep_offset > 0) {
/* 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)}});
}
/* If this is not the last block, draw a separator. */
draw_separator(x, block);
}
}
@ -1198,6 +1219,9 @@ void init_xcb_late(char *fontname) {
DLOG("Calculated font height: %d\n", font.height);
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);
if (config.hide_on_modifier == M_HIDE)

View File

@ -285,6 +285,9 @@ struct Barconfig {
/** Font specification for all text rendered on the bar. */
char *font;
/** A custom separator to use instead of a vertical line. */
char *separator_symbol;
/** Hide workspace buttons? Configuration option is 'workspace_buttons no'
* but we invert the bool to get the correct default when initializing with
* zero. */

View File

@ -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(bar_font, const char *font);
CFGFUN(bar_separator_symbol, const char *separator);
CFGFUN(bar_mode, const char *mode);
CFGFUN(bar_hidden_state, const char *hidden_state);
CFGFUN(bar_id, const char *bar_id);

View File

@ -370,6 +370,7 @@ state BAR:
'output' -> BAR_OUTPUT
'tray_output' -> BAR_TRAY_OUTPUT
'font' -> BAR_FONT
'separator_symbol' -> BAR_SEPARATOR_SYMBOL
'binding_mode_indicator' -> BAR_BINDING_MODE_INDICATOR
'workspace_buttons' -> BAR_WORKSPACE_BUTTONS
'strip_workspace_numbers' -> BAR_STRIP_WORKSPACE_NUMBERS
@ -435,6 +436,10 @@ state BAR_FONT:
font = string
-> call cfg_bar_font($font); BAR
state BAR_SEPARATOR_SYMBOL:
separator = string
-> call cfg_bar_separator_symbol($separator); BAR
state BAR_BINDING_MODE_INDICATOR:
value = word
-> call cfg_bar_binding_mode_indicator($value); BAR

View File

@ -421,6 +421,11 @@ CFGFUN(bar_font, const char *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) {
current_bar.mode = (strcmp(mode, "dock") == 0 ? M_DOCK : (strcmp(mode, "hide") == 0 ? M_HIDE : M_INVISIBLE));
}

View File

@ -594,6 +594,11 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
YSTR_IF_SET(status_command);
YSTR_IF_SET(font);
if (config->separator_symbol) {
ystr("separator_symbol");
ystr(config->separator_symbol);
}
ystr("workspace_buttons");
y(bool, !config->hide_workspace_buttons);

View File

@ -647,7 +647,7 @@ EOT
$expected = <<'EOT';
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: Line 1: bar {
ERROR: CONFIG: Line 2: output LVDS-1