Separator color and width via config; separator off via ipc
Patch status: rejected
Patch by Artem Shinkarov
Long description:
This patch adds the following features:
1) Configure a color of the separator via config. It is done like
bar {
colors {
separator #000000
}
}
2) Configure a width of the gap between the items. In the middle of that
gap separating line is being drawn. The syntax is the following:
bar {
separator_block_width 11
}
which would set the width of the gap to 11 pixels. If not specified
the default is 9 pixels.
3) A block can have a boolean entry "separator" and if it is set
to false, then the drawing of the separating line would be disabled.
To apply this patch, use:
curl http://cr.i3wm.org/patch/33/raw.patch | git am
b/docs/i3bar-protocol
| 45 |
@@ -154,7 +154,11 @@ urgent:: |
| 46 |
A boolean which specifies whether the current value is urgent. Examples |
| 47 |
are battery charge values below 1 percent or no more available disk |
| 48 |
space (for non-root users). The presentation of urgency is up to i3bar. |
| 49 |
- |
| 50 |
+separator:: |
| 51 |
+ The boolean value false disables drawing of a separating line after the |
| 52 |
+ block. If the field is not present then the separator will be still |
| 53 |
+ drawn. Keep in mind that absence of a separator is only responsible for |
| 54 |
+ the line itself, the gap between the items would be still present. |
| 55 |
If you want to put in your own entries into a block, prefix the key with an |
| 56 |
underscore (_). i3bar will ignore all keys it doesn’t understand, and prefixing |
| 57 |
them with an underscore makes it clear in every script that they are not part |
b/docs/ipc
| 62 |
@@ -497,6 +497,9 @@ workspace_buttons (boolean):: |
| 63 |
Display workspace buttons or not? Defaults to true. |
| 64 |
verbose (boolean):: |
| 65 |
Should the bar enable verbose output for debugging? Defaults to false. |
| 66 |
+separator_block_width (integer):: |
| 67 |
+ The width of the gap between items. In the middle of the gap separating |
| 68 |
+ line is going to be drawn. |
| 69 |
colors (map):: |
| 70 |
Contains key/value pairs of colors. Each value is a color code in hex, |
| 71 |
formatted #rrggbb (like in HTML). |
| 72 |
@@ -507,6 +510,8 @@ background:: |
| 73 |
Background color of the bar. |
| 74 |
statusline:: |
| 75 |
Text color to be used for the statusline. |
| 76 |
+separator:: |
| 77 |
+ Text color to be used for the separator. |
| 78 |
focused_workspace_text/focused_workspace_bg:: |
| 79 |
Text color/background color for a workspace button when the workspace |
| 80 |
has focus. |
b/docs/userguide
| 85 |
@@ -1145,6 +1145,26 @@ bar {
|
| 86 |
} |
| 87 |
-------------------- |
| 88 |
|
| 89 |
+=== Width of the gap between items |
| 90 |
+ |
| 91 |
+Specifies the width of the gap between the items in the statusline. The number |
| 92 |
+represents the width in pixels, value 0 means no gap. Please keep in mind that |
| 93 |
+the separating line is drawn in the middle of the gap, so it is recommended to |
| 94 |
+keep the value odd. If not specified, the default gap width is 9 pixels. |
| 95 |
+ |
| 96 |
+*Syntax*: |
| 97 |
+-------------------------- |
| 98 |
+separator_block_width <number> |
| 99 |
+-------------------------- |
| 100 |
+ |
| 101 |
+*Example*: |
| 102 |
+-------------------- |
| 103 |
+bar {
|
| 104 |
+ separator_block_width 5 |
| 105 |
+} |
| 106 |
+-------------------- |
| 107 |
+ |
| 108 |
+ |
| 109 |
=== Colors |
| 110 |
|
| 111 |
As with i3, colors are in HTML hex format (#rrggbb). The following colors can |
| 112 |
@@ -1154,6 +1174,8 @@ background:: |
| 113 |
Background color of the bar. |
| 114 |
statusline:: |
| 115 |
Text color to be used for the statusline. |
| 116 |
+separator:: |
| 117 |
+ Text color to be used for the separator. |
| 118 |
focused_workspace:: |
| 119 |
Border, background and text color for a workspace button when the workspace |
| 120 |
has focus. |
| 121 |
@@ -1175,6 +1197,7 @@ urgent_workspace:: |
| 122 |
colors {
|
| 123 |
background <color> |
| 124 |
statusline <color> |
| 125 |
+ separator <color> |
| 126 |
|
| 127 |
colorclass <border> <background> <text> |
| 128 |
} |
| 129 |
@@ -1186,6 +1209,7 @@ bar {
|
| 130 |
colors {
|
| 131 |
background #000000 |
| 132 |
statusline #ffffff |
| 133 |
+ separator #666666 |
| 134 |
|
| 135 |
focused_workspace #4c7899 #285577 #ffffff |
| 136 |
active_workspace #333333 #5f676a #ffffff |
b/i3bar/include/common.h
| 141 |
@@ -43,6 +43,7 @@ struct status_block {
|
| 142 |
blockalign_t align; |
| 143 |
|
| 144 |
bool urgent; |
| 145 |
+ bool no_separator; |
| 146 |
|
| 147 |
/* The amount of pixels necessary to render this block. These variables are |
| 148 |
* only temporarily used in refresh_statusline(). */ |
b/i3bar/include/config.h
| 153 |
@@ -30,6 +30,7 @@ typedef struct config_t {
|
| 154 |
char *fontname; |
| 155 |
char *tray_output; |
| 156 |
int num_outputs; |
| 157 |
+ int sep_block_width; |
| 158 |
char **outputs; |
| 159 |
} config_t; |
| 160 |
|
b/i3bar/include/xcb.h
| 165 |
@@ -28,6 +28,7 @@ |
| 166 |
struct xcb_color_strings_t {
|
| 167 |
char *bar_fg; |
| 168 |
char *bar_bg; |
| 169 |
+ char *sep_fg; |
| 170 |
char *active_ws_fg; |
| 171 |
char *active_ws_bg; |
| 172 |
char *active_ws_border; |
| 173 |
@@ -65,6 +66,13 @@ void init_xcb_late(char *fontname); |
| 174 |
void init_colors(const struct xcb_color_strings_t *colors); |
| 175 |
|
| 176 |
/* |
| 177 |
+ * Initialize the sizes |
| 178 |
+ * |
| 179 |
+ */ |
| 180 |
+void init_sizes(const int32_t sep_block_width); |
| 181 |
+ |
| 182 |
+ |
| 183 |
+/* |
| 184 |
* Cleanup the xcb-stuff. |
| 185 |
* Called once, before the program terminates. |
| 186 |
* |
b/i3bar/src/child.c
| 191 |
@@ -117,6 +117,9 @@ static int stdin_boolean(void *context, int val) {
|
| 192 |
if (strcasecmp(ctx->last_map_key, "urgent") == 0) {
|
| 193 |
ctx->block.urgent = val; |
| 194 |
} |
| 195 |
+ if (strcasecmp(ctx->last_map_key, "separator") == 0) {
|
| 196 |
+ ctx->block.no_separator = !val; |
| 197 |
+ } |
| 198 |
return 1; |
| 199 |
} |
| 200 |
|
b/i3bar/src/config.c
| 205 |
@@ -161,6 +161,7 @@ static int config_string_cb(void *params_, const unsigned char *val, unsigned in |
| 206 |
|
| 207 |
COLOR(statusline, bar_fg); |
| 208 |
COLOR(background, bar_bg); |
| 209 |
+ COLOR(separator, sep_fg); |
| 210 |
COLOR(focused_workspace_border, focus_ws_border); |
| 211 |
COLOR(focused_workspace_bg, focus_ws_bg); |
| 212 |
COLOR(focused_workspace_text, focus_ws_fg); |
| 213 |
@@ -199,11 +200,30 @@ static int config_boolean_cb(void *params_, int val) {
|
| 214 |
return 0; |
| 215 |
} |
| 216 |
|
| 217 |
+/* |
| 218 |
+ * Parse an integer value |
| 219 |
+ * |
| 220 |
+ */ |
| 221 |
+#if YAJL_MAJOR >= 2 |
| 222 |
+static int config_integer_cb(void *params_, long long val) {
|
| 223 |
+#else |
| 224 |
+static int config_integer_cb(void *params_, long val) {
|
| 225 |
+#endif |
| 226 |
+ if (!strcmp(cur_key, "separator_block_width")) {
|
| 227 |
+ DLOG("separator_block_width = %d\n", (int32_t)val);
|
| 228 |
+ config.sep_block_width = (int32_t)val; |
| 229 |
+ return 1; |
| 230 |
+ } |
| 231 |
+ |
| 232 |
+ return 0; |
| 233 |
+} |
| 234 |
+ |
| 235 |
+ |
| 236 |
/* A datastructure to pass all these callbacks to yajl */ |
| 237 |
static yajl_callbacks outputs_callbacks = {
|
| 238 |
&config_null_cb, |
| 239 |
&config_boolean_cb, |
| 240 |
- NULL, |
| 241 |
+ &config_integer_cb, |
| 242 |
NULL, |
| 243 |
NULL, |
| 244 |
&config_string_cb, |
| 245 |
@@ -260,6 +280,7 @@ void free_colors(struct xcb_color_strings_t *colors) {
|
| 246 |
} while (0) |
| 247 |
FREE_COLOR(bar_fg); |
| 248 |
FREE_COLOR(bar_bg); |
| 249 |
+ FREE_COLOR(sep_fg); |
| 250 |
FREE_COLOR(active_ws_fg); |
| 251 |
FREE_COLOR(active_ws_bg); |
| 252 |
FREE_COLOR(active_ws_border); |
b/i3bar/src/ipc.c
| 257 |
@@ -100,6 +100,9 @@ void got_bar_config(char *reply) {
|
| 258 |
/* Resolve color strings to colorpixels and save them, then free the strings. */ |
| 259 |
init_colors(&(config.colors)); |
| 260 |
|
| 261 |
+ /* Initialize sizes from config */ |
| 262 |
+ init_sizes(config.sep_block_width); |
| 263 |
+ |
| 264 |
/* The name of this function is actually misleading. Even if no command is |
| 265 |
* specified, this function initiates the watchers to listen on stdin and |
| 266 |
* react accordingly */ |
b/i3bar/src/xcb.c
| 271 |
@@ -71,6 +71,10 @@ xcb_gcontext_t statusline_clear; |
| 272 |
xcb_pixmap_t statusline_pm; |
| 273 |
uint32_t statusline_width; |
| 274 |
|
| 275 |
+/* Sizes obtained through config */ |
| 276 |
+/* 'sep_block_width' -- width of the gap between items (in px) */ |
| 277 |
+static uint32_t sep_block_width; |
| 278 |
+ |
| 279 |
/* Event-Watchers, to interact with the user */ |
| 280 |
ev_prepare *xcb_prep; |
| 281 |
ev_check *xcb_chk; |
| 282 |
@@ -84,6 +88,7 @@ static mode binding; |
| 283 |
struct xcb_colors_t {
|
| 284 |
uint32_t bar_fg; |
| 285 |
uint32_t bar_bg; |
| 286 |
+ uint32_t sep_fg; |
| 287 |
uint32_t active_ws_fg; |
| 288 |
uint32_t active_ws_bg; |
| 289 |
uint32_t active_ws_border; |
| 290 |
@@ -149,7 +154,8 @@ void refresh_statusline(void) {
|
| 291 |
|
| 292 |
/* If this is not the last block, add some pixels for a separator. */ |
| 293 |
if (TAILQ_NEXT(block, blocks) != NULL) |
| 294 |
- block->width += 9; |
| 295 |
+ block->width += sep_block_width; |
| 296 |
+ |
| 297 |
statusline_width += block->width + block->x_offset + block->x_append; |
| 298 |
} |
| 299 |
|
| 300 |
@@ -174,12 +180,14 @@ void refresh_statusline(void) {
|
| 301 |
draw_text(block->full_text, statusline_pm, statusline_ctx, x + block->x_offset, 1, block->width); |
| 302 |
x += block->width + block->x_offset + block->x_append; |
| 303 |
|
| 304 |
- if (TAILQ_NEXT(block, blocks) != NULL) {
|
| 305 |
+ if (TAILQ_NEXT(block, blocks) != NULL && !block->no_separator && sep_block_width > 0) {
|
| 306 |
/* This is not the last block, draw a separator. */ |
| 307 |
- set_font_colors(statusline_ctx, get_colorpixel("#666666"), colors.bar_bg);
|
| 308 |
+ uint32_t sep_offset = sep_block_width/2 + sep_block_width % 2; |
| 309 |
+ set_font_colors(statusline_ctx, colors.sep_fg, colors.bar_bg); |
| 310 |
xcb_poly_line(xcb_connection, XCB_COORD_MODE_ORIGIN, statusline_pm, |
| 311 |
statusline_ctx, 2, |
| 312 |
- (xcb_point_t[]){ { x - 5, 2 }, { x - 5, font.height - 2 } });
|
| 313 |
+ (xcb_point_t[]){ { x - sep_offset, 2 },
|
| 314 |
+ { x - sep_offset, font.height - 2 } });
|
| 315 |
} |
| 316 |
} |
| 317 |
} |
| 318 |
@@ -259,6 +267,7 @@ void init_colors(const struct xcb_color_strings_t *new_colors) {
|
| 319 |
} while (0) |
| 320 |
PARSE_COLOR(bar_fg, "#FFFFFF"); |
| 321 |
PARSE_COLOR(bar_bg, "#000000"); |
| 322 |
+ PARSE_COLOR(sep_fg, "#666666"); |
| 323 |
PARSE_COLOR(active_ws_fg, "#FFFFFF"); |
| 324 |
PARSE_COLOR(active_ws_bg, "#333333"); |
| 325 |
PARSE_COLOR(active_ws_border, "#333333"); |
| 326 |
@@ -277,6 +286,14 @@ void init_colors(const struct xcb_color_strings_t *new_colors) {
|
| 327 |
xcb_flush(xcb_connection); |
| 328 |
} |
| 329 |
|
| 330 |
+void init_sizes (int32_t sbw) |
| 331 |
+{
|
| 332 |
+ if (sbw < 0) |
| 333 |
+ sep_block_width = 0; |
| 334 |
+ else |
| 335 |
+ sep_block_width = (uint32_t)sbw; |
| 336 |
+} |
| 337 |
+ |
| 338 |
/* |
| 339 |
* Handle a button-press-event (i.e. a mouse click on one of our bars). |
| 340 |
* We determine, whether the click occured on a ws-button or if the scroll- |
b/include/config.h
| 345 |
@@ -256,6 +256,9 @@ struct Barconfig {
|
| 346 |
/** Font specification for all text rendered on the bar. */ |
| 347 |
char *font; |
| 348 |
|
| 349 |
+ /** Width of the gap between the items (in px). */ |
| 350 |
+ int32_t separator_block_width; |
| 351 |
+ |
| 352 |
/** Hide workspace buttons? Configuration option is 'workspace_buttons no' |
| 353 |
* but we invert the bool to get the correct default when initializing with |
| 354 |
* zero. */ |
| 355 |
@@ -267,6 +270,7 @@ struct Barconfig {
|
| 356 |
struct bar_colors {
|
| 357 |
char *background; |
| 358 |
char *statusline; |
| 359 |
+ char *separator; |
| 360 |
|
| 361 |
char *focused_workspace_border; |
| 362 |
char *focused_workspace_bg; |
b/include/config_directives.h
| 367 |
@@ -61,6 +61,7 @@ CFGFUN(enter_mode, const char *mode); |
| 368 |
CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *command); |
| 369 |
|
| 370 |
CFGFUN(bar_font, const char *font); |
| 371 |
+CFGFUN(bar_sep_block_width, const long); |
| 372 |
CFGFUN(bar_mode, const char *mode); |
| 373 |
CFGFUN(bar_output, const char *output); |
| 374 |
CFGFUN(bar_verbose, const char *verbose); |
b/parser-specs/config.spec
| 379 |
@@ -354,6 +354,7 @@ state BAR: |
| 380 |
'output' -> BAR_OUTPUT |
| 381 |
'tray_output' -> BAR_TRAY_OUTPUT |
| 382 |
'font' -> BAR_FONT |
| 383 |
+ 'separator_block_width' -> BAR_SEP_BLOCK_WIDTH |
| 384 |
'workspace_buttons' -> BAR_WORKSPACE_BUTTONS |
| 385 |
'verbose' -> BAR_VERBOSE |
| 386 |
'colors' -> BAR_COLORS_BRACE |
| 387 |
@@ -401,6 +402,11 @@ state BAR_FONT: |
| 388 |
font = string |
| 389 |
-> call cfg_bar_font($font); BAR |
| 390 |
|
| 391 |
+state BAR_SEP_BLOCK_WIDTH: |
| 392 |
+ width = number |
| 393 |
+ -> call cfg_bar_sep_block_width(&width); BAR |
| 394 |
+ |
| 395 |
+ |
| 396 |
state BAR_WORKSPACE_BUTTONS: |
| 397 |
value = word |
| 398 |
-> call cfg_bar_workspace_buttons($value); BAR |
| 399 |
@@ -419,7 +425,7 @@ state BAR_COLORS: |
| 400 |
end -> |
| 401 |
'#' -> BAR_COLORS_IGNORE_LINE |
| 402 |
'set' -> BAR_COLORS_IGNORE_LINE |
| 403 |
- colorclass = 'background', 'statusline' |
| 404 |
+ colorclass = 'background', 'statusline', 'separator' |
| 405 |
-> BAR_COLORS_SINGLE |
| 406 |
colorclass = 'focused_workspace', 'active_workspace', 'inactive_workspace', 'urgent_workspace' |
| 407 |
-> BAR_COLORS_BORDER |
b/src/config_directives.c
| 412 |
@@ -439,13 +439,24 @@ CFGFUN(assign, const char *workspace) {
|
| 413 |
* Bar configuration (i3bar) |
| 414 |
******************************************************************************/ |
| 415 |
|
| 416 |
-static Barconfig current_bar; |
| 417 |
+/* Initialize members that might not be set via config, |
| 418 |
+ but which need default values. */ |
| 419 |
+#define default_bar_config \ |
| 420 |
+{ \
|
| 421 |
+ .separator_block_width = 9 \ |
| 422 |
+} |
| 423 |
+ |
| 424 |
+static Barconfig current_bar = default_bar_config; |
| 425 |
|
| 426 |
CFGFUN(bar_font, const char *font) {
|
| 427 |
FREE(current_bar.font); |
| 428 |
current_bar.font = sstrdup(font); |
| 429 |
} |
| 430 |
|
| 431 |
+CFGFUN(bar_sep_block_width, const long width) {
|
| 432 |
+ current_bar.separator_block_width = width; |
| 433 |
+} |
| 434 |
+ |
| 435 |
CFGFUN(bar_mode, const char *mode) {
|
| 436 |
current_bar.mode = (strcmp(mode, "hide") == 0 ? M_HIDE : M_DOCK); |
| 437 |
} |
| 438 |
@@ -526,7 +537,10 @@ CFGFUN(bar_tray_output, const char *output) {
|
| 439 |
CFGFUN(bar_color_single, const char *colorclass, const char *color) {
|
| 440 |
if (strcmp(colorclass, "background") == 0) |
| 441 |
current_bar.colors.background = sstrdup(color); |
| 442 |
- else current_bar.colors.statusline = sstrdup(color); |
| 443 |
+ else if (strcmp(colorclass, "separator") == 0) |
| 444 |
+ current_bar.colors.separator = sstrdup(color); |
| 445 |
+ else |
| 446 |
+ current_bar.colors.statusline = sstrdup(color); |
| 447 |
} |
| 448 |
|
| 449 |
CFGFUN(bar_status_command, const char *command) {
|
| 450 |
@@ -561,4 +575,5 @@ CFGFUN(bar_finish) {
|
| 451 |
TAILQ_INSERT_TAIL(&barconfigs, bar_config, configs); |
| 452 |
|
| 453 |
memset(¤t_bar, '\0', sizeof(Barconfig)); |
| 454 |
+ current_bar = (Barconfig) default_bar_config; |
| 455 |
} |
b/src/ipc.c
| 460 |
@@ -658,6 +658,9 @@ IPC_HANDLER(get_bar_config) {
|
| 461 |
YSTR_IF_SET(status_command); |
| 462 |
YSTR_IF_SET(font); |
| 463 |
|
| 464 |
+ ystr("separator_block_width");
|
| 465 |
+ y(integer, config->separator_block_width); |
| 466 |
+ |
| 467 |
ystr("workspace_buttons");
|
| 468 |
y(bool, !config->hide_workspace_buttons); |
| 469 |
|
| 470 |
@@ -677,6 +680,7 @@ IPC_HANDLER(get_bar_config) {
|
| 471 |
y(map_open); |
| 472 |
YSTR_IF_SET(background); |
| 473 |
YSTR_IF_SET(statusline); |
| 474 |
+ YSTR_IF_SET(separator); |
| 475 |
YSTR_IF_SET(focused_workspace_border); |
| 476 |
YSTR_IF_SET(focused_workspace_bg); |
| 477 |
YSTR_IF_SET(focused_workspace_text); |
b/testcases/t/201-config-parser.t
| 482 |
@@ -591,7 +591,7 @@ EOT |
| 483 |
|
| 484 |
$expected = <<'EOT'; |
| 485 |
cfg_bar_output(LVDS-1) |
| 486 |
-ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'modifier', 'position', 'output', 'tray_output', 'font', 'workspace_buttons', 'verbose', 'colors', '}' |
| 487 |
+ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'modifier', 'position', 'output', 'tray_output', 'font', 'separator_block_width', 'workspace_buttons', 'verbose', 'colors', '}' |
| 488 |
ERROR: CONFIG: (in file <stdin>) |
| 489 |
ERROR: CONFIG: Line 1: bar {
|
| 490 |
ERROR: CONFIG: Line 2: output LVDS-1 |