]> git.sur5r.net Git - i3/i3/commitdiff
Optionally change i3bar color on focused output, implements #2020 2030/head
authorDavid Simon <david.mike.simon@gmail.com>
Mon, 26 Oct 2015 20:55:01 +0000 (16:55 -0400)
committerDavid Simon <david.mike.simon@gmail.com>
Tue, 27 Oct 2015 13:12:57 +0000 (09:12 -0400)
13 files changed:
docs/ipc
docs/userguide
i3bar/include/outputs.h
i3bar/include/xcb.h
i3bar/src/config.c
i3bar/src/outputs.c
i3bar/src/xcb.c
include/config.h
parser-specs/config.spec
src/config.c
src/config_directives.c
src/ipc.c
testcases/t/177-bar-config.t

index 1813e53a863e2a2561599cb62be0ee1324f4e138..5231c5ec692492e9a65734493a771b5f0439cf1a 100644 (file)
--- a/docs/ipc
+++ b/docs/ipc
@@ -520,6 +520,14 @@ statusline::
        Text color to be used for the statusline.
 separator::
        Text color to be used for the separator.
+focused_background::
+       Background color of the bar on the currently focused monitor output.
+focused_statusline::
+       Text color to be used for the statusline on the currently focused
+       monitor output.
+focused_separator::
+       Text color to be used for the separator on the currently focused
+       monitor output.
 focused_workspace_text/focused_workspace_bg/focused_workspace_border::
        Text/background/border color for a workspace button when the workspace
        has focus.
index e866dfb13514d286e3f0b7498083f47e0690c8df..ca39757aca41de2ce6100e35a62baa7003d466fe 100644 (file)
@@ -1529,6 +1529,15 @@ statusline::
        Text color to be used for the statusline.
 separator::
        Text color to be used for the separator.
+focused_background::
+       Background color of the bar on the currently focused monitor output. If
+       not used, the color will be taken from +background+.
+focused_statusline::
+       Text color to be used for the statusline on the currently focused
+       monitor output. If not used, the color will be taken from +statusline+.
+focused_separator::
+       Text color to be used for the separator on the currently focused
+       monitor output. If not used, the color will be taken from +separator+.
 focused_workspace::
        Border, background and text color for a workspace button when the workspace
        has focus.
index ec09e764725d84b756543842ce67d04d2aea26cb..08adefd9742f8ced77e035325caed4fc565c3db4 100644 (file)
@@ -38,6 +38,12 @@ void init_outputs(void);
  */
 i3_output* get_output_by_name(char* name);
 
+/*
+ * Returns true if the output has the currently focused workspace
+ *
+ */
+bool output_has_focus(i3_output* output);
+
 struct i3_output {
     char* name;   /* Name of the output */
     bool active;  /* If the output is active */
index 3746204ca33ef7c9a40bc85066d49ee465505d1e..0a9bd7e41d67e175d984481d326ff3e971fb0042 100644 (file)
@@ -34,6 +34,9 @@ struct xcb_color_strings_t {
     char *bar_fg;
     char *bar_bg;
     char *sep_fg;
+    char *focus_bar_fg;
+    char *focus_bar_bg;
+    char *focus_sep_fg;
     char *active_ws_fg;
     char *active_ws_bg;
     char *active_ws_border;
index f3412719b7f9a52b19e46616108f590cd3d1792b..6476d15f44f6c34023612ff4de184a04e268ef3d 100644 (file)
@@ -214,6 +214,9 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len
     COLOR(statusline, bar_fg);
     COLOR(background, bar_bg);
     COLOR(separator, sep_fg);
+    COLOR(focused_statusline, focus_bar_fg);
+    COLOR(focused_background, focus_bar_bg);
+    COLOR(focused_separator, focus_sep_fg);
     COLOR(focused_workspace_border, focus_ws_border);
     COLOR(focused_workspace_bg, focus_ws_bg);
     COLOR(focused_workspace_text, focus_ws_fg);
@@ -343,6 +346,9 @@ void free_colors(struct xcb_color_strings_t *colors) {
     FREE_COLOR(bar_fg);
     FREE_COLOR(bar_bg);
     FREE_COLOR(sep_fg);
+    FREE_COLOR(focus_bar_fg);
+    FREE_COLOR(focus_bar_bg);
+    FREE_COLOR(focus_sep_fg);
     FREE_COLOR(active_ws_fg);
     FREE_COLOR(active_ws_bg);
     FREE_COLOR(active_ws_border);
index df3bc69b81b8a39069408d306cb04b8bb358b904..841a7565c6e8257d2d79fe53b5e9d23ba57aeea2 100644 (file)
@@ -302,3 +302,17 @@ i3_output *get_output_by_name(char *name) {
 
     return walk;
 }
+
+/*
+ * Returns true if the output has the currently focused workspace
+ *
+ */
+bool output_has_focus(i3_output *output) {
+    i3_ws *ws_walk;
+    TAILQ_FOREACH(ws_walk, output->workspaces, tailq) {
+        if (ws_walk->focused) {
+            return true;
+        }
+    }
+    return false;
+}
index 841570e260fa3c29dc91f5bf31111e2a146ea6f9..20206c8bb556ec4a42d96b200e374a35d35c10a0 100644 (file)
@@ -91,6 +91,9 @@ struct xcb_colors_t {
     color_t bar_fg;
     color_t bar_bg;
     color_t sep_fg;
+    color_t focus_bar_fg;
+    color_t focus_bar_bg;
+    color_t focus_sep_fg;
     color_t active_ws_fg;
     color_t active_ws_bg;
     color_t active_ws_border;
@@ -160,7 +163,10 @@ int get_tray_width(struct tc_head *trayclients) {
  * Draws a separator for the given block if necessary.
  *
  */
-static void draw_separator(i3_output *output, uint32_t x, struct status_block *block) {
+static void draw_separator(i3_output *output, uint32_t x, struct status_block *block, bool use_focus_colors) {
+    color_t sep_fg = (use_focus_colors ? colors.focus_sep_fg : colors.sep_fg);
+    color_t bar_bg = (use_focus_colors ? colors.focus_bar_bg : colors.bar_bg);
+
     uint32_t sep_offset = get_sep_offset(block);
     if (TAILQ_NEXT(block, blocks) == NULL || sep_offset == 0)
         return;
@@ -168,7 +174,7 @@ static void draw_separator(i3_output *output, uint32_t x, struct status_block *b
     uint32_t center_x = x - sep_offset;
     if (config.separator_symbol == NULL) {
         /* Draw a classic one pixel, vertical separator. */
-        draw_util_rectangle(&output->statusline_buffer, colors.sep_fg,
+        draw_util_rectangle(&output->statusline_buffer, sep_fg,
                             center_x,
                             logical_px(sep_voff_px),
                             logical_px(1),
@@ -176,7 +182,7 @@ static void draw_separator(i3_output *output, uint32_t x, struct status_block *b
     } else {
         /* Draw a custom separator. */
         uint32_t separator_x = MAX(x - block->sep_block_width, center_x - separator_symbol_width / 2);
-        draw_util_text(config.separator_symbol, &output->statusline_buffer, colors.sep_fg, colors.bar_bg,
+        draw_util_text(config.separator_symbol, &output->statusline_buffer, sep_fg, bar_bg,
                        separator_x, logical_px(ws_voff_px), x - separator_x);
     }
 }
@@ -233,10 +239,11 @@ uint32_t predict_statusline_length(bool use_short_text) {
 /*
  * Redraws the statusline to the output's statusline_buffer
  */
-void draw_statusline(i3_output *output, uint32_t clip_left, bool use_short_text) {
+void draw_statusline(i3_output *output, uint32_t clip_left, bool use_focus_colors, bool use_short_text) {
     struct status_block *block;
 
-    draw_util_clear_surface(&output->statusline_buffer, colors.bar_bg);
+    color_t bar_color = (use_focus_colors ? colors.focus_bar_bg : colors.bar_bg);
+    draw_util_clear_surface(&output->statusline_buffer, bar_color);
 
     /* Use unsigned integer wraparound to clip off the left side.
      * For example, if clip_left is 75, then x will start at the very large
@@ -263,17 +270,19 @@ void draw_statusline(i3_output *output, uint32_t clip_left, bool use_short_text)
             fg_color = colors.urgent_ws_fg;
         } else if (block->color) {
             fg_color = draw_util_hex_to_color(block->color);
+        } else if (use_focus_colors) {
+            fg_color = colors.focus_bar_fg;
         } else {
             fg_color = colors.bar_fg;
         }
 
-        color_t bg_color = colors.bar_bg;
+        color_t bg_color = bar_color;
 
         int border_width = (block->border) ? logical_px(1) : 0;
         int full_render_width = render->width + render->x_offset + render->x_append;
         if (block->border || block->background || block->urgent) {
             /* Let's determine the colors first. */
-            color_t border_color = colors.bar_bg;
+            color_t border_color = bar_color;
             if (block->urgent) {
                 border_color = colors.urgent_ws_border;
                 bg_color = colors.urgent_ws_bg;
@@ -306,7 +315,7 @@ void draw_statusline(i3_output *output, uint32_t clip_left, bool use_short_text)
         /* If this is not the last block, draw a separator. */
         if (TAILQ_NEXT(block, blocks) != NULL) {
             x += block->sep_block_width;
-            draw_separator(output, x, block);
+            draw_separator(output, x, block, use_focus_colors);
         }
     }
 }
@@ -412,6 +421,12 @@ void init_colors(const struct xcb_color_strings_t *new_colors) {
     PARSE_COLOR_FALLBACK(binding_mode_fg, urgent_ws_fg);
     PARSE_COLOR_FALLBACK(binding_mode_bg, urgent_ws_bg);
     PARSE_COLOR_FALLBACK(binding_mode_border, urgent_ws_border);
+
+    /* Similarly, for unspecified focused bar colors, we fall back to the
+     * regular bar colors. */
+    PARSE_COLOR_FALLBACK(focus_bar_fg, bar_fg);
+    PARSE_COLOR_FALLBACK(focus_bar_bg, bar_bg);
+    PARSE_COLOR_FALLBACK(focus_sep_fg, sep_fg);
 #undef PARSE_COLOR_FALLBACK
 
     init_tray_colors();
@@ -1826,8 +1841,11 @@ void draw_bars(bool unhide) {
             reconfig_windows(false);
         }
 
+        bool use_focus_colors = output_has_focus(outputs_walk);
+
         /* First things first: clear the backbuffer */
-        draw_util_clear_surface(&(outputs_walk->buffer), colors.bar_bg);
+        draw_util_clear_surface(&(outputs_walk->buffer),
+                                (use_focus_colors ? colors.focus_bar_bg : colors.bar_bg));
 
         if (!config.disable_ws) {
             i3_ws *ws_walk;
@@ -1928,7 +1946,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(sb_hoff_px) - visible_statusline_width;
 
-            draw_statusline(outputs_walk, clip_left, use_short_text);
+            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,
                                    x_dest, 0, visible_statusline_width, (int16_t)bar_height);
 
index 6312d3d2dc13cf2873181427f6430de52ad2127d..1c4ccce6905c68b8b6dd678b97e78b622b9648d1 100644 (file)
@@ -323,6 +323,10 @@ struct Barconfig {
         char *statusline;
         char *separator;
 
+        char *focused_background;
+        char *focused_statusline;
+        char *focused_separator;
+
         char *focused_workspace_border;
         char *focused_workspace_bg;
         char *focused_workspace_text;
index 2170ace32d6da3f6dc14c7acadd2e668d0f01c34..882e81fb83e491405d4385e2733613848ceae0c7 100644 (file)
@@ -520,7 +520,7 @@ state BAR_COLORS:
   end ->
   '#' -> BAR_COLORS_IGNORE_LINE
   'set' -> BAR_COLORS_IGNORE_LINE
-  colorclass = 'background', 'statusline', 'separator'
+  colorclass = 'background', 'statusline', 'separator', 'focused_background', 'focused_statusline', 'focused_separator'
       -> BAR_COLORS_SINGLE
   colorclass = 'focused_workspace', 'active_workspace', 'inactive_workspace', 'urgent_workspace', 'binding_mode'
       -> BAR_COLORS_BORDER
index d8db85e63c0c630aa433f780a3ade29045bfc9ee..c1c31e30a358168ecca5b053c0c8a41f6648633d 100644 (file)
@@ -118,6 +118,10 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
             FREE(barconfig->font);
             FREE(barconfig->colors.background);
             FREE(barconfig->colors.statusline);
+            FREE(barconfig->colors.separator);
+            FREE(barconfig->colors.focused_background);
+            FREE(barconfig->colors.focused_statusline);
+            FREE(barconfig->colors.focused_separator);
             FREE(barconfig->colors.focused_workspace_border);
             FREE(barconfig->colors.focused_workspace_bg);
             FREE(barconfig->colors.focused_workspace_text);
index 99b70db8998ceacad69b4d1ccc10818656870687..960dee5bfdde70f6aaa227f511f2230bb6b57478 100644 (file)
@@ -533,8 +533,14 @@ CFGFUN(bar_color_single, const char *colorclass, const char *color) {
         current_bar.colors.background = sstrdup(color);
     else if (strcmp(colorclass, "separator") == 0)
         current_bar.colors.separator = sstrdup(color);
-    else
+    else if (strcmp(colorclass, "statusline") == 0)
         current_bar.colors.statusline = sstrdup(color);
+    else if (strcmp(colorclass, "focused_background") == 0)
+        current_bar.colors.focused_background = sstrdup(color);
+    else if (strcmp(colorclass, "focused_separator") == 0)
+        current_bar.colors.focused_separator = sstrdup(color);
+    else
+        current_bar.colors.focused_statusline = sstrdup(color);
 }
 
 CFGFUN(bar_status_command, const char *command) {
index 68cc417a86383aec4773ba95d2c2dcb98f651164..8e448c7ce22f379a00121d12474ef88e894b7ea0 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -663,6 +663,9 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
     YSTR_IF_SET(background);
     YSTR_IF_SET(statusline);
     YSTR_IF_SET(separator);
+    YSTR_IF_SET(focused_background);
+    YSTR_IF_SET(focused_statusline);
+    YSTR_IF_SET(focused_separator);
     YSTR_IF_SET(focused_workspace_border);
     YSTR_IF_SET(focused_workspace_bg);
     YSTR_IF_SET(focused_workspace_text);
index cc4826c15766be171d652b4a102e813001d52da6..8ef94e57f15b800faf0024e61baba21ffc50fbe0 100644 (file)
@@ -109,6 +109,9 @@ bar {
     colors {
         background #ff0000
         statusline   #00ff00
+        focused_background #cc0000
+        focused_statusline #cccc00
+        focused_separator  #0000cc
 
         focused_workspace   #4c7899 #285577 #ffffff
         active_workspace    #333333 #222222 #888888
@@ -143,6 +146,9 @@ is_deeply($bar_config->{colors},
     {
         background => '#ff0000',
         statusline => '#00ff00',
+        focused_background => '#cc0000',
+        focused_statusline=> '#cccc00',
+        focused_separator => '#0000cc',
         focused_workspace_border => '#4c7899',
         focused_workspace_text => '#ffffff',
         focused_workspace_bg => '#285577',