]> git.sur5r.net Git - i3/i3/commitdiff
Add support for a custom separator symbol 1578/head
authorIngo Bürk <ingo.buerk@tngtech.com>
Tue, 24 Mar 2015 22:07:25 +0000 (23:07 +0100)
committerIngo Bürk <ingo.buerk@tngtech.com>
Wed, 25 Mar 2015 20:38:55 +0000 (21:38 +0100)
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

docs/userguide
i3bar/include/config.h
i3bar/src/config.c
i3bar/src/xcb.c
include/config.h
include/config_directives.h
parser-specs/config.spec
src/config_directives.c
src/ipc.c
testcases/t/201-config-parser.t

index 45b05a062fcbaf020521fee55a0362cca997bc5f..d60eefb2103e1ed9d222608797ced5343be27ae4 100644 (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
index fe04bf31aa9e2dc48fa478c795279e0e93957da2..fdc37445ab4944549742ca7c580fa4f488e51de0 100644 (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;
index c568ac5b9c5a6f28426daa22348104ba63186175..a83ca0aabdd59979b060633cc3009be11d9690b7 100644 (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;
index d87e56e49e7ce590b363937c5cfcc89c7679db10..85efd88b08dfa4848e8d7ca59f0cac747ee8df82 100644 (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)
index afafb64be0cb8da35017684d0ec354e7cd03f50c..9a0af0e6cd6b8119e1a5ae4a4bd5fcef915cb66e 100644 (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. */
index 0f1a6620ef1200f47b2f8b0738a7ab4589a4b24e..6c960b1f8c765771c2fd6d340872a76d7ea4fae6 100644 (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);
index dbdf83c2808aa076fce039a0a27313c8cb7c6953..25be5cf107e2bef2eebdba243980ee04085c9efa 100644 (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
index 80d7876b927f573d080a52a5b5c1aa259d593a1a..c8b25c7645f6cfc7e8c2d8ab210101138719957d 100644 (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));
 }
index acd2267bdb61f761f34511d3adaf3bec7afcff50..ea6a7de941dfa5aae2a6a4c35038636b0cb731d7 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -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);
 
index 9643aa42f5f5678536a181e481cc1a1da00f1fdf..1e91d47f9cf5cdcb71f9ccf350aefd1f61f2e364 100644 (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