diff --git a/i3bar/include/xcb.h b/i3bar/include/xcb.h index 754022853..83c65a55b 100644 --- a/i3bar/include/xcb.h +++ b/i3bar/include/xcb.h @@ -9,12 +9,42 @@ #ifndef XCB_H_ #define XCB_H_ +#include + +struct colors_t { + char *bar_fg; + char *bar_bg; + char *active_ws_fg; + char *active_ws_bg; + char *inactive_ws_fg; + char *inactive_ws_bg; + char *urgent_ws_bg; + char *urgent_ws_fg; +}; + +struct parsed_colors_t { + uint32_t bar_fg; + uint32_t bar_bg; + uint32_t active_ws_fg; + uint32_t active_ws_bg; + uint32_t inactive_ws_fg; + uint32_t inactive_ws_bg; + uint32_t urgent_ws_bg; + uint32_t urgent_ws_fg; +}; + /* * Initialize xcb and use the specified fontname for text-rendering * */ void init_xcb(); +/* + * Initialize the colors + * + */ +void init_colors(const struct colors_t *colors); + /* * Cleanup the xcb-stuff. * Called once, before the program terminates. diff --git a/i3bar/src/main.c b/i3bar/src/main.c index 5b6debc50..e081d8801 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -37,6 +37,49 @@ char *expand_path(char *path) { return result; } +static void read_color(char **color) +{ + int len = strlen(optarg); + if (len == 6 || (len == 7 && optarg[0] == '#')) { + int offset = len - 6; + int good = 1, i; + for (i = offset; good && i < 6 + offset; ++i) { + char c = optarg[i]; + if (!(c >= 'a' && c <= 'f') + && !(c >= 'A' && c <= 'F') + && !(c >= '0' && c <= '9')) { + good = 0; + break; + } + } + if (good) { + *color = strdup(optarg + offset); + return; + } + } + + fprintf(stderr, "Bad color value \"%s\"\n", optarg); + exit(EXIT_FAILURE); +} + +static void free_colors(struct colors_t *colors) +{ +#define FREE_COLOR(x) \ + do { \ + if (colors->x) \ + free(colors->x); \ + } while (0) + FREE_COLOR(bar_fg); + FREE_COLOR(bar_bg); + FREE_COLOR(active_ws_fg); + FREE_COLOR(active_ws_bg); + FREE_COLOR(inactive_ws_fg); + FREE_COLOR(inactive_ws_bg); + FREE_COLOR(urgent_ws_fg); + FREE_COLOR(urgent_ws_bg); +#undef FREE_COLOR +} + void print_usage(char *elf_name) { printf("Usage: %s [-s sock_path] [-c command] [-m] [-f font] [-V] [-h]\n", elf_name); printf("-s \tConnect to i3 via \n"); @@ -56,22 +99,31 @@ int main(int argc, char **argv) { char *command = NULL; char *fontname = NULL; char *i3_default_sock_path = "~/.i3/ipc.sock"; + struct colors_t colors = {0,}; /* Definition of the standard-config */ config.hide_on_modifier = 0; static struct option long_opt[] = { - { "socket", required_argument, 0, 's' }, - { "command", required_argument, 0, 'c' }, - { "hide", no_argument, 0, 'm' }, - { "font", required_argument, 0, 'f' }, - { "help", no_argument, 0, 'h' }, - { "version", no_argument, 0, 'v' }, - { "verbose", no_argument, 0, 'V' }, - { NULL, 0, 0, 0} + { "socket", required_argument, 0, 's' }, + { "command", required_argument, 0, 'c' }, + { "hide", no_argument, 0, 'm' }, + { "font", required_argument, 0, 'f' }, + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'v' }, + { "verbose", no_argument, 0, 'V' }, + { "color-bar-fg", required_argument, 0, 'A' }, + { "color-bar-bg", required_argument, 0, 'B' }, + { "color-active-ws-fg", required_argument, 0, 'C' }, + { "color-active-ws-bg", required_argument, 0, 'D' }, + { "color-inactive-ws-fg", required_argument, 0, 'E' }, + { "color-inactive-ws-bg", required_argument, 0, 'F' }, + { "color-urgent-ws-bg", required_argument, 0, 'G' }, + { "color-urgent-ws-fg", required_argument, 0, 'H' }, + { NULL, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "s:c:mf:hvV", long_opt, &option_index)) != -1) { + while ((opt = getopt_long(argc, argv, "s:c:mf:hvV:A:B:C:D:E:F:G:H:", long_opt, &option_index)) != -1) { switch (opt) { case 's': socket_path = expand_path(optarg); @@ -92,6 +144,30 @@ int main(int argc, char **argv) { case 'V': config.verbose = 1; break; + case 'A': + read_color(&colors.bar_fg); + break; + case 'B': + read_color(&colors.bar_bg); + break; + case 'C': + read_color(&colors.active_ws_fg); + break; + case 'D': + read_color(&colors.active_ws_bg); + break; + case 'E': + read_color(&colors.inactive_ws_fg); + break; + case 'F': + read_color(&colors.inactive_ws_bg); + break; + case 'G': + read_color(&colors.urgent_ws_fg); + break; + case 'H': + read_color(&colors.urgent_ws_bg); + break; default: print_usage(argv[0]); exit(EXIT_SUCCESS); @@ -114,6 +190,10 @@ int main(int argc, char **argv) { main_loop = ev_default_loop(0); init_xcb(fontname); + + init_colors(&colors); + free_colors(&colors); + init_outputs(); init_connection(socket_path); diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 38ee5bd97..41f221cf1 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -63,6 +63,9 @@ ev_check *xcb_chk; ev_io *xcb_io; ev_io *xkb_io; +/* The parsed colors */ +struct parsed_colors_t colors; + /* We define xcb_request_failed as a macro to include the relevant line-number */ #define xcb_request_failed(cookie, err_msg) _xcb_request_failed(cookie, err_msg, __LINE__) int _xcb_request_failed(xcb_void_cookie_t cookie, char *err_msg, int line) { @@ -247,6 +250,26 @@ void unhide_bars() { } } +/* + * Parse the colors into a format that we can use + * + */ +void init_colors(const struct colors_t *new_colors) { +#define PARSE_COLOR(name, def) \ + do { \ + colors.name = get_colorpixel(new_colors->name ? new_colors->name : def); \ + } while (0) + PARSE_COLOR(bar_fg, "FFFFFF"); + PARSE_COLOR(bar_bg, "000000"); + PARSE_COLOR(active_ws_fg, "FFFFFF"); + PARSE_COLOR(active_ws_bg, "480000"); + PARSE_COLOR(inactive_ws_fg, "FFFFFF"); + PARSE_COLOR(inactive_ws_bg, "240000"); + PARSE_COLOR(urgent_ws_fg, "FFFFFF"); + PARSE_COLOR(urgent_ws_bg, "002400"); +#undef PARSE_COLOR +} + /* * Handle a button-press-event (i.c. a mouse click on one of our bars). * We determine, wether the click occured on a ws-button or if the scroll- @@ -725,7 +748,7 @@ void draw_bars() { reconfig_windows(); } /* First things first: clear the backbuffer */ - uint32_t color = get_colorpixel("000000"); + uint32_t color = colors.bar_bg; xcb_change_gc(xcb_connection, outputs_walk->bargc, XCB_GC_FOREGROUND, @@ -755,35 +778,37 @@ void draw_bars() { i3_ws *ws_walk; TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) { DLOG("Drawing Button for WS %s at x = %d\n", ws_walk->name, i); - uint32_t color = get_colorpixel("240000"); + uint32_t fg_color = colors.inactive_ws_fg; + uint32_t bg_color = colors.inactive_ws_bg; if (ws_walk->visible) { - color = get_colorpixel("480000"); + fg_color = colors.active_ws_fg; + bg_color = colors.active_ws_bg; } if (ws_walk->urgent) { DLOG("WS %s is urgent!\n", ws_walk->name); - color = get_colorpixel("002400"); + fg_color = colors.urgent_ws_fg; + bg_color = colors.urgent_ws_bg; /* The urgent-hint should get noticed, so we unhide the bars shortly */ unhide_bars(); } xcb_change_gc(xcb_connection, outputs_walk->bargc, XCB_GC_FOREGROUND, - &color); + &bg_color); xcb_change_gc(xcb_connection, outputs_walk->bargc, XCB_GC_BACKGROUND, - &color); + &bg_color); xcb_rectangle_t rect = { i + 1, 1, ws_walk->name_width + 8, font_height + 4 }; xcb_poly_fill_rectangle(xcb_connection, outputs_walk->buffer, outputs_walk->bargc, 1, &rect); - color = get_colorpixel("FFFFFF"); xcb_change_gc(xcb_connection, outputs_walk->bargc, XCB_GC_FOREGROUND, - &color); + &fg_color); xcb_image_text_16(xcb_connection, ws_walk->name_glyphs, outputs_walk->buffer,