From b82d96a68e4a4d14dff5c79c7ebd1da95ef85241 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 15 Apr 2015 10:21:52 +0200 Subject: [PATCH 01/25] Use the maximum width reported by the font if the attributes table isn't found --- lemonbar.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index 5f36f41..c7a53ba 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -22,7 +22,7 @@ typedef struct font_t { xcb_font_t ptr; - int descent, height; + int descent, height, width; uint16_t char_max; uint16_t char_min; xcb_charinfo_t *width_lut; @@ -180,13 +180,18 @@ xcb_void_cookie_t xcb_poly_text_16_simple(xcb_connection_t * c, xcb_parts[6].iov_len = -(xcb_parts[4].iov_len + xcb_parts[5].iov_len) & 3; xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req); + return xcb_ret; } int draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) { - int ch_width = cur_font->width_lut[ch - cur_font->char_min].character_width; + int ch_width; + + ch_width = (cur_font->width_lut) ? + cur_font->width_lut[ch - cur_font->char_min].character_width: + cur_font->width; switch (align) { case ALIGN_C: @@ -432,10 +437,13 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x bool font_has_glyph (font_t *font, const uint16_t c) { - return (c >= font->char_min && - c <= font->char_max && - font->width_lut && - font->width_lut[c - font->char_min].character_width); + if (c < font->char_min || c > font->char_max) + return false; + + if (font->width_lut && font->width_lut[c - font->char_min].character_width == 0) + return false; + + return true; } // returns NULL if character cannot be printed @@ -628,6 +636,7 @@ font_load (const char *str) ret->ptr = font; ret->descent = font_info->font_descent; ret->height = font_info->font_ascent + font_info->font_descent; + ret->width = font_info->max_bounds.character_width; ret->char_max = font_info->max_byte1 << 8 | font_info->max_char_or_byte2; ret->char_min = font_info->min_byte1 << 8 | font_info->min_char_or_byte2; From 25c3441925272978596df7964aeec68c295ad0b5 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 15 Apr 2015 11:04:53 +0200 Subject: [PATCH 02/25] travis: Run a apt-get update before installing the needed packages --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index be842ec..fb22eea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,5 +3,6 @@ compiler: - clang - gcc before_install: - - sudo apt-get install -qq libx11-xcb-dev libxcb-randr0-dev libxcb-xinerama0-dev + - sudo apt-get update -qq + - sudo apt-get install -y libx11-xcb-dev libxcb-randr0-dev libxcb-xinerama0-dev script: make From 7880eac8c9b15810a2089ca8636b3d51d433a4b4 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 23 Apr 2015 23:07:42 +0200 Subject: [PATCH 03/25] Minor change to -f handling Remove the ability of the -f switch to accept a comma-separated list of fonts. The user is expected to use multiple times -f whenever he wants to specify one or more fonts. This has the side effect of enabling the user to use fonts whose name contains a comma. --- README.pod | 3 ++- lemonbar.c | 64 ++++++++---------------------------------------------- 2 files changed, 11 insertions(+), 56 deletions(-) diff --git a/README.pod b/README.pod index afbed83..5cadd5e 100644 --- a/README.pod +++ b/README.pod @@ -34,7 +34,8 @@ Force docking without asking the window manager. This is needed if the window ma =item B<-f> I -Comma separated list of fonts, lemonbar supports a maximum of five fonts (the limit can be tweaked by changing the MAX_FONT_COUNT parameter in the source). +Define the font to load into one of the five slots (the number of slots is hardcoded and can be tweaked by +changing the MAX_FONT_COUNT parameter in the source code). =item B<-p> diff --git a/lemonbar.c b/lemonbar.c index c7a53ba..929f90d 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -609,8 +609,8 @@ parse (char *text) } } -font_t * -font_load (const char *str) +void +font_load (const char *pattern) { xcb_query_font_cookie_t queryreq; xcb_query_font_reply_t *font_info; @@ -619,16 +619,16 @@ font_load (const char *str) font = xcb_generate_id(c); - cookie = xcb_open_font_checked(c, font, strlen(str), str); + cookie = xcb_open_font_checked(c, font, strlen(pattern), pattern); if (xcb_request_check (c, cookie)) { - fprintf(stderr, "Could not load font \"%s\"\n", str); - return NULL; + fprintf(stderr, "Could not load font \"%s\"\n", pattern); + return; } font_t *ret = calloc(1, sizeof(font_t)); if (!ret) - return NULL; + return; queryreq = xcb_query_font(c, font); font_info = xcb_query_font_reply(c, queryreq, NULL); @@ -649,7 +649,7 @@ font_load (const char *str) free(font_info); - return ret; + font_list[font_count++] = ret; } enum { @@ -1035,48 +1035,6 @@ parse_geometry_string (char *str, int *tmp) return true; } -void -parse_font_list (char *str) -{ - char *tok, *end; - - if (!str) - return; - - tok = strtok(str, ","); - - while (tok) { - if (font_count > MAX_FONT_COUNT - 1) { - fprintf(stderr, "Too many fonts; maximum %i\n", MAX_FONT_COUNT); - return; - } - - // Strip the leading and trailing whitespaces - while (isspace(*tok) || iscntrl(*tok)) - tok++; - - end = tok + strlen(tok) - 1; - - while ((end > tok && isspace(*end)) || iscntrl(*end)) - end--; - - *(end + 1) = '\0'; - - if (tok[0]) { - // Load the selected font - font_t *font = font_load(tok); - if (font) - font_list[font_count++] = font; - } - else - fprintf(stderr, "Empty font name, skipping...\n"); - - tok = strtok(NULL, ","); - } -} - - - void xconn (void) { @@ -1100,13 +1058,9 @@ xconn (void) void init (void) { - // This has to be declared as an array because otherwise the compiler would turn it into a const - // string, making strtok choke very hard on this - char fallback_font[] = "fixed"; - // Try to load a default font if (!font_count) - parse_font_list(fallback_font); + font_load("fixed"); // We tried and failed hard, there's something wrong if (!font_count) @@ -1279,7 +1233,7 @@ main (int argc, char **argv) case 'p': permanent = true; break; case 'b': topbar = false; break; case 'd': dock = true; break; - case 'f': parse_font_list(optarg); break; + case 'f': font_load(optarg); break; case 'u': bu = strtoul(optarg, NULL, 10); break; case 'B': dbgc = bgc = parse_color(optarg, NULL, (rgba_t)scr->black_pixel); break; case 'F': dfgc = fgc = parse_color(optarg, NULL, (rgba_t)scr->white_pixel); break; From a9f285fd2866ab3451b8dd7468853c141691024f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 3 May 2015 17:06:36 +0200 Subject: [PATCH 04/25] Update the usage text The -f option doesn't accept a comma separated list of font names anymore --- lemonbar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemonbar.c b/lemonbar.c index 929f90d..c956115 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -1223,7 +1223,7 @@ main (int argc, char **argv) "\t-g Set the bar geometry {width}x{height}+{xoffset}+{yoffset}\n" "\t-b Put the bar at the bottom of the screen\n" "\t-d Force docking (use this if your WM isn't EWMH compliant)\n" - "\t-f Bar font list, comma separated\n" + "\t-f Set the font name to use\n" "\t-p Don't close after the data ends\n" "\t-u Set the underline/overline height in pixels\n" "\t-B Set background color in #AARRGGBB\n" From a8fa2766fb25d36c0e3bd161f8a37775031f3801 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Tue, 2 Jun 2015 09:27:53 +0200 Subject: [PATCH 05/25] Check force_count to be lower than MAX_FONT_COUNT --- lemonbar.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lemonbar.c b/lemonbar.c index c956115..5f640d2 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -612,6 +612,11 @@ parse (char *text) void font_load (const char *pattern) { + if (font_count >= MAX_FONT_COUNT) { + fprintf(stderr, "Max font count reached. Could not load font \"%s\"\n", pattern); + return; + } + xcb_query_font_cookie_t queryreq; xcb_query_font_reply_t *font_info; xcb_void_cookie_t cookie; From 49fdc25f377481f0897ea10bd7943127cf5b721f Mon Sep 17 00:00:00 2001 From: Jesper Jensen Date: Wed, 22 Jul 2015 17:39:31 +0200 Subject: [PATCH 06/25] Fixed font selection Font selection now correctly handles - as a special case. This change is also reflected in the documentation. --- README.pod | 2 +- lemonbar.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/README.pod b/README.pod index 5cadd5e..44f09f0 100644 --- a/README.pod +++ b/README.pod @@ -87,7 +87,7 @@ Set the text foreground color. The parameter I can be I<-> or a color in =item BI -Set the font used to draw the following text. The parameter I is a 1-based index of the font list supplied to bar. Any other value (for example I<->) resets the bar to normal behaviour (matching the first font that can be used for that character). If the selected font can't be used to draw a character, lemonbar will fall back to normal behaviour for that character. +Set the font used to draw the following text. The parameter I can either be I<-> or the 1-based index of the slot which contains the desired font. If the parameter is I<-> lemonbar resets to the normal behavior (matching the first font that can be used for the character). If the selected font can't be used to draw a character, lemonbar will fall back to normal behavior for that character =item BI diff --git a/lemonbar.c b/lemonbar.c index c956115..4d61120 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -540,6 +540,11 @@ parse (char *text) break; case 'T': + if(*p == '-') { //Reset to automatic font selection + font_index = -1; + p++; + break; + } font_index = (int)strtoul(p, &ep, 10); // User-specified 'font_index' ∊ (0,font_count] // Otherwise just fallback to the automatic font selection From 73d8c58286bdd599ff1bf94d11a8ad5a8e07372a Mon Sep 17 00:00:00 2001 From: Jesper Jensen Date: Wed, 22 Jul 2015 22:46:30 +0200 Subject: [PATCH 07/25] Conform to coding standard and errors An error will not be printed if the parameter to `T` is not valid (- or a number) and the token will be eaten (just like when an invalid attribute is found) --- lemonbar.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index 4d61120..316804b 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -540,18 +540,22 @@ parse (char *text) break; case 'T': - if(*p == '-') { //Reset to automatic font selection + if (*p == '-') { //Reset to automatic font selection font_index = -1; p++; break; - } - font_index = (int)strtoul(p, &ep, 10); - // User-specified 'font_index' ∊ (0,font_count] - // Otherwise just fallback to the automatic font selection - if (!font_index || font_index > font_count) + } else if (isdigit(*p)) { + font_index = (int)strtoul(p, &ep, 10); + // User-specified 'font_index' ∊ (0,font_count] + // Otherwise just fallback to the automatic font selection + if (!font_index || font_index > font_count) font_index = -1; - p = ep; - break; + p = ep; + break; + } else { + fprintf(stderr, "Invalid font slot \"%c\"\n", *p++); //Swallow the token + break; + } // In case of error keep parsing after the closing } default: From 63a55dd06cb98e8b00a232ad8ae7b4ac133c4d6e Mon Sep 17 00:00:00 2001 From: Chad Voegele Date: Tue, 14 Jul 2015 10:47:49 -0700 Subject: [PATCH 08/25] Keep percent signs if not followed by {} block. The before code would skip a percent sign even if it was not followed by a {} block. The after code checks the same condition but only advances p if a {} block is found and otherwise passes it through as text. --- lemonbar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lemonbar.c b/lemonbar.c index 794d815..ec00e6d 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -485,7 +485,8 @@ parse (char *text) if (*p == '\0' || *p == '\n') return; - if (*p == '%' && p++ && *p == '{' && (block_end = strchr(p++, '}'))) { + if (*p == '%' && *(p+1) == '{' && (block_end = strchr(p++, '}'))) { + p++; while (p < block_end) { while (isspace(*p)) p++; From 71ed0d3375a4ed317b427478d0a96db9db71d2a9 Mon Sep 17 00:00:00 2001 From: chad Date: Sun, 27 Sep 2015 15:21:49 -0500 Subject: [PATCH 09/25] Rewrite *p, *(p+1) as p[0], p[1] for readability. --- lemonbar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemonbar.c b/lemonbar.c index ec00e6d..065ecd6 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -485,7 +485,7 @@ parse (char *text) if (*p == '\0' || *p == '\n') return; - if (*p == '%' && *(p+1) == '{' && (block_end = strchr(p++, '}'))) { + if (p[0] == '%' && p[1] == '{' && (block_end = strchr(p++, '}'))) { p++; while (p < block_end) { while (isspace(*p)) From 177deb0860c3e6ac443f3560978f31672e31ed05 Mon Sep 17 00:00:00 2001 From: neeasade Date: Sun, 12 Apr 2015 08:07:57 -0500 Subject: [PATCH 10/25] bar -> lemonbar in .gitignore, remove config.h in .gitignore --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 519ae3a..01a163f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ -config.h -bar +lemonbar *.o *.swp *~ From 7f8a79131b39ff63d2b91eacc252417dca3211bd Mon Sep 17 00:00:00 2001 From: Nathan Isom Date: Wed, 21 Oct 2015 00:22:52 -0500 Subject: [PATCH 11/25] Account for height of monitors in sorting. --- lemonbar.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index 065ecd6..39c4975 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -541,7 +541,7 @@ parse (char *text) break; case 'T': - if (*p == '-') { //Reset to automatic font selection + if (*p == '-') { //Reset to automatic font selection font_index = -1; p++; break; @@ -784,10 +784,15 @@ rect_sort_cb (const void *p1, const void *p2) const xcb_rectangle_t *r1 = (xcb_rectangle_t *)p1; const xcb_rectangle_t *r2 = (xcb_rectangle_t *)p2; - if (r1->x < r2->x || r1->y < r2->y) + if (r1->x < r2->x || r1->y + r1->height <= r2->y) + { return -1; - if (r1->x > r2->x || r1->y > r2->y) - return 1; + } + + if (r1->x > r2->x || r1->y + r1->height > r2->y) + { + return 1; + } return 0; } From 38422c5014e63afd3981b3518b5e09b96aab1448 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 24 Oct 2015 14:04:37 +0200 Subject: [PATCH 12/25] Don't parse named colors. Expand #rgb format. --- README.pod | 2 +- lemonbar.c | 98 ++++++++++++++++++++++++++---------------------------- 2 files changed, 49 insertions(+), 51 deletions(-) diff --git a/README.pod b/README.pod index 44f09f0..a38a7df 100644 --- a/README.pod +++ b/README.pod @@ -47,7 +47,7 @@ Sets the underline width in pixels. The default is 1. =item B<-B> I -Set the background color of the bar. I might be either in hex format (#aarrggbb) or in the symbolic name format (eg. white, indianred, darkgray). If no compositor such as compton or xcompmgr is running the alpha channel is silently ignored. +Set the background color of the bar. I must be specified in the hex format (#aarrggbb, #rrggbb, #rgb). If no compositor such as compton or xcompmgr is running the alpha channel is silently ignored. =item B<-F> I diff --git a/lemonbar.c b/lemonbar.c index 39c4975..5764537 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -233,9 +233,7 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) rgba_t parse_color (const char *str, char **end, const rgba_t def) { - xcb_alloc_named_color_reply_t *nc_reply; int string_len; - rgba_t ret; char *ep; if (!str) @@ -250,61 +248,61 @@ parse_color (const char *str, char **end, const rgba_t def) } // Hex representation - if (str[0] == '#') { - errno = 0; - rgba_t tmp = (rgba_t)(uint32_t)strtoul(str + 1, &ep, 16); - + if (str[0] != '#') { if (end) - *end = ep; + *end = (char *)str; - // Some error checking is definitely good - if (errno) { - fprintf(stderr, "Invalid color specified\n"); - return def; - } - - string_len = ep - (str + 1); - - // If the code is in #rrggbb form then assume it's opaque - if (string_len <= 6) - tmp.a = 255; - - // Premultiply the alpha in - if (tmp.a) { - // The components are clamped automagically as the rgba_t is made of uint8_t - return (rgba_t){ - .r = (tmp.r * tmp.a) / 255, - .g = (tmp.g * tmp.a) / 255, - .b = (tmp.b * tmp.a) / 255, - .a = tmp.a, - }; - } - - return (rgba_t)0U; + fprintf(stderr, "Invalid color specified\n"); + return def; } - // Actual color name, resolve it - for (string_len = 0; isalpha(str[string_len]); string_len++) - ; - - nc_reply = xcb_alloc_named_color_reply(c, xcb_alloc_named_color(c, colormap, string_len, str), NULL); - - if (!nc_reply) - fprintf(stderr, "Could not allocate the color \"%.*s\"\n", string_len, str); - - ret = nc_reply? - (rgba_t)nc_reply->pixel: - def; - - free(nc_reply); + errno = 0; + rgba_t tmp = (rgba_t)(uint32_t)strtoul(str + 1, &ep, 16); if (end) - *end = (char *)str + string_len; + *end = ep; - return ret; + // Some error checking is definitely good + if (errno) { + fprintf(stderr, "Invalid color specified\n"); + return def; + } + + string_len = ep - (str + 1); + + switch (string_len) { + case 3: + // Expand the #rgb format into #rrggbb (aa is set to 0xff) + tmp.v = (tmp.v & 0xf00) * 0x1100 + | (tmp.v & 0x0f0) * 0x0110 + | (tmp.v & 0x00f) * 0x0011; + case 6: + // If the code is in #rrggbb form then assume it's opaque + tmp.a = 255; + break; + case 7: + case 8: + // Colors in #aarrggbb format, those need no adjustments + break; + default: + fprintf(stderr, "Invalid color specified\n"); + return def; + } + + // Premultiply the alpha in + if (tmp.a) { + // The components are clamped automagically as the rgba_t is made of uint8_t + return (rgba_t){ + .r = (tmp.r * tmp.a) / 255, + .g = (tmp.g * tmp.a) / 255, + .b = (tmp.b * tmp.a) / 255, + .a = tmp.a, + }; + } + + return (rgba_t)0U; } - void set_attribute (const char modifier, const char attribute) { @@ -1229,8 +1227,8 @@ main (int argc, char **argv) xconn(); // B/W combo - dbgc = bgc = parse_color("black", NULL, (rgba_t)scr->black_pixel); - dfgc = fgc = parse_color("white", NULL, (rgba_t)scr->white_pixel); + dbgc = bgc = (rgba_t)scr->black_pixel; + dfgc = fgc = (rgba_t)scr->white_pixel; ugc = fgc; From 255c93dc7a58d8c7bbc0c7c32d46c0fa9e6cb723 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 24 Oct 2015 14:28:51 +0200 Subject: [PATCH 13/25] Make the number of clickable areas configurable. --- lemonbar.c | 80 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 27 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index 5764537..ef3b3cf 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -29,15 +29,18 @@ typedef struct font_t { } font_t; typedef struct monitor_t { - int x, y, width; + int x:16, y:16, width:16; xcb_window_t window; xcb_pixmap_t pixmap; struct monitor_t *prev, *next; } monitor_t; typedef struct area_t { - bool active; - int begin, end, align, button; + unsigned int begin:16; + unsigned int end:16; + bool active:1; + int align:3; + int button:3; xcb_window_t window; char *cmd; } area_t; @@ -52,11 +55,9 @@ typedef union rgba_t { uint32_t v; } rgba_t; -#define N 20 - typedef struct area_stack_t { - int pos; - area_t slot[N]; + int at, max; + area_t *area; } area_stack_t; enum { @@ -95,7 +96,7 @@ static int bw = -1, bh = -1, bx = 0, by = 0; static int bu = 1; // Underline height static rgba_t fgc, bgc, ugc; static rgba_t dfgc, dbgc; -static area_stack_t astack; +static area_stack_t area_stack; void update_gc (void) @@ -325,8 +326,8 @@ area_t * area_get (xcb_window_t win, const int btn, const int x) { // Looping backwards ensures that we get the innermost area first - for (int i = astack.pos; i >= 0; i--) { - area_t *a = &astack.slot[i]; + for (int i = area_stack.at; i >= 0; i--) { + area_t *a = &area_stack.area[i]; if (a->window == win && a->button == btn && x >= a->begin && x < a->end) return a; @@ -342,8 +343,8 @@ area_shift (xcb_window_t win, const int align, int delta) if (align == ALIGN_C) delta /= 2; - for (int i = 0; i < astack.pos; i++) { - area_t *a = &astack.slot[i]; + for (int i = 0; i < area_stack.at; i++) { + area_t *a = &area_stack.area[i]; if (a->window == win && a->align == align && !a->active) { a->begin -= delta; a->end -= delta; @@ -363,9 +364,9 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x *end = str; // Find most recent unclosed area. - for (i = astack.pos - 1; i >= 0 && !astack.slot[i].active; i--) + for (i = area_stack.at - 1; i >= 0 && !area_stack.area[i].active; i--) ; - a = &astack.slot[i]; + a = &area_stack.area[i]; // Basic safety checks if (!a->cmd || a->align != align || a->window != mon->window) @@ -392,11 +393,12 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x return true; } - if (astack.pos >= N) { - fprintf(stderr, "astack overflow!\n"); + if (area_stack.at + 1 > area_stack.max) { + fprintf(stderr, "Cannot add any more clickable areas (used %d/%d)\n", + area_stack.at, area_stack.max); return false; } - a = &astack.slot[astack.pos++]; + a = &area_stack.area[area_stack.at++]; // Found the closing : and check if it's just an escaped one for (trail = strchr(++str, ':'); trail && trail[-1] == '\\'; trail = strchr(trail + 1, ':')) @@ -474,7 +476,8 @@ parse (char *text) align = ALIGN_L; cur_mon = monhead; - memset(&astack, 0, sizeof(area_stack_t)); + // Reset the stack position + area_stack.at = 0; for (monitor_t *m = monhead; m != NULL; m = m->next) fill_rect(m->pixmap, gc[GC_CLEAR], 0, 0, m->width, bh); @@ -510,7 +513,8 @@ parse (char *text) // The range is 1-5 if (isdigit(*p) && (*p > '0' && *p < '6')) button = *p++ - '0'; - area_add(p, block_end, &p, cur_mon, pos_x, align, button); + if (!area_add(p, block_end, &p, cur_mon, pos_x, align, button)) + return; break; case 'B': bgc = parse_color(p, &p, dbgc); update_gc(); break; @@ -1170,6 +1174,8 @@ init (void) void cleanup (void) { + free(area_stack.area); + for (int i = 0; i < font_count; i++) { xcb_close_font(c, font_list[i]->ptr); free(font_list[i]->width_lut); @@ -1216,22 +1222,22 @@ main (int argc, char **argv) char input[4096] = {0, }; bool permanent = false; int geom_v[4] = { -1, -1, 0, 0 }; - int ch; + int ch, areas; // Install the parachute! atexit(cleanup); signal(SIGINT, sighandle); signal(SIGTERM, sighandle); - // Connect to the Xserver and initialize scr - xconn(); - // B/W combo - dbgc = bgc = (rgba_t)scr->black_pixel; - dfgc = fgc = (rgba_t)scr->white_pixel; + dbgc = bgc = (rgba_t)0x00000000U; + dfgc = fgc = (rgba_t)0xffffffffU; ugc = fgc; + // A safe default + areas = 10; + while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:")) != -1) { switch (ch) { case 'h': @@ -1242,6 +1248,7 @@ main (int argc, char **argv) "\t-b Put the bar at the bottom of the screen\n" "\t-d Force docking (use this if your WM isn't EWMH compliant)\n" "\t-f Set the font name to use\n" + "\t-a Number of clickable areas available (default is 10)\n" "\t-p Don't close after the data ends\n" "\t-u Set the underline/overline height in pixels\n" "\t-B Set background color in #AARRGGBB\n" @@ -1253,17 +1260,36 @@ main (int argc, char **argv) case 'd': dock = true; break; case 'f': font_load(optarg); break; case 'u': bu = strtoul(optarg, NULL, 10); break; - case 'B': dbgc = bgc = parse_color(optarg, NULL, (rgba_t)scr->black_pixel); break; - case 'F': dfgc = fgc = parse_color(optarg, NULL, (rgba_t)scr->white_pixel); break; + case 'B': dbgc = bgc = parse_color(optarg, NULL, (rgba_t)0x00000000U); break; + case 'F': dfgc = fgc = parse_color(optarg, NULL, (rgba_t)0xffffffffU); break; + case 'a': areas = strtoul(optarg, NULL, 10); break; } } + // Initialize the stack holding the clickable areas + area_stack.at = 0; + area_stack.max = areas; + if (areas) { + area_stack.area = calloc(areas, sizeof(area_t)); + + if (!area_stack.area) { + fprintf(stderr, "Could not allocate enough memory for %d clickable areas, try lowering the number\n", areas); + return EXIT_FAILURE; + } + } + else + area_stack.area = NULL; + + // Copy the geometry values in place bw = geom_v[0]; bh = geom_v[1]; bx = geom_v[2]; by = geom_v[3]; + // Connect to the Xserver and initialize scr + xconn(); + // Do the heavy lifting init(); // Get the fd to Xserver From 6580e2d4f760fc3b69a03aa3179ce80b2b3d9d55 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 24 Oct 2015 14:35:36 +0200 Subject: [PATCH 14/25] Warn the user when the area geometry is invalid --- lemonbar.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index ef3b3cf..73d3ff1 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -29,7 +29,7 @@ typedef struct font_t { } font_t; typedef struct monitor_t { - int x:16, y:16, width:16; + int x, y, width; xcb_window_t window; xcb_pixmap_t pixmap; struct monitor_t *prev, *next; @@ -369,8 +369,10 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x a = &area_stack.area[i]; // Basic safety checks - if (!a->cmd || a->align != align || a->window != mon->window) + if (!a->cmd || a->align != align || a->window != mon->window) { + fprintf(stderr, "Invalid geometry for the clickable area\n"); return false; + } const int size = x - a->begin; From 531c575575e04fd7d6bd34b8347f420497e017a4 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 24 Oct 2015 14:44:41 +0200 Subject: [PATCH 15/25] Allow the user to set the WM_NAME atom value --- README.pod | 6 +++++- lemonbar.c | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/README.pod b/README.pod index a38a7df..ea7eb7f 100644 --- a/README.pod +++ b/README.pod @@ -6,7 +6,7 @@ lemonbar - Featherweight lemon-scented bar =head1 SYNOPSIS -I [-h | -g IBIB<+>IB<+>I | -b | -d | -f I | -p | -u I | -B I | -F I] +I [-h | -g IBIB<+>IB<+>I | -b | -d | -f I | -p | -n | -u I | -B I | -F I] =head1 DESCRIPTION @@ -41,6 +41,10 @@ changing the MAX_FONT_COUNT parameter in the source code). Make the bar permanent, don't exit after the standard input is closed. +=item B<-n> + +Set the WM_NAME atom value for the bar. + =item B<-u> I Sets the underline width in pixels. The default is 1. diff --git a/lemonbar.c b/lemonbar.c index 73d3ff1..6582160 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -1080,7 +1080,7 @@ xconn (void) } void -init (void) +init (char *wm_name) { // Try to load a default font if (!font_count) @@ -1168,6 +1168,10 @@ init (void) // Make sure that the window really gets in the place it's supposed to be // Some WM such as Openbox need this xcb_configure_window(c, mon->window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, (const uint32_t []){ mon->x, mon->y }); + + // Set the WM_NAME atom to the user specified value + if (wm_name) + xcb_change_property(c, XCB_PROP_MODE_REPLACE, monhead->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8 ,strlen(wm_name), wm_name); } xcb_flush(c); @@ -1225,6 +1229,7 @@ main (int argc, char **argv) bool permanent = false; int geom_v[4] = { -1, -1, 0, 0 }; int ch, areas; + char *wm_name; // Install the parachute! atexit(cleanup); @@ -1239,12 +1244,13 @@ main (int argc, char **argv) // A safe default areas = 10; + wm_name = NULL; - while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:")) != -1) { + while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:n:")) != -1) { switch (ch) { case 'h': printf ("lemonbar version %s\n", VERSION); - printf ("usage: %s [-h | -g | -b | -d | -f | -a | -p | -u | -B | -F]\n" + printf ("usage: %s [-h | -g | -b | -d | -f | -a | -p | -n | -u | -B | -F]\n" "\t-h Show this help\n" "\t-g Set the bar geometry {width}x{height}+{xoffset}+{yoffset}\n" "\t-b Put the bar at the bottom of the screen\n" @@ -1252,12 +1258,14 @@ main (int argc, char **argv) "\t-f Set the font name to use\n" "\t-a Number of clickable areas available (default is 10)\n" "\t-p Don't close after the data ends\n" + "\t-n Set the WM_NAME atom to the specified value for this bar\n" "\t-u Set the underline/overline height in pixels\n" "\t-B Set background color in #AARRGGBB\n" "\t-F Set foreground color in #AARRGGBB\n", argv[0]); exit (EXIT_SUCCESS); case 'g': (void)parse_geometry_string(optarg, geom_v); break; case 'p': permanent = true; break; + case 'n': wm_name = optarg; break; case 'b': topbar = false; break; case 'd': dock = true; break; case 'f': font_load(optarg); break; @@ -1293,7 +1301,7 @@ main (int argc, char **argv) xconn(); // Do the heavy lifting - init(); + init(wm_name); // Get the fd to Xserver pollin[1].fd = xcb_get_file_descriptor(c); From 3b5baa93b172a28179c4de0557e438daf0f6619a Mon Sep 17 00:00:00 2001 From: Bastien Dejean Date: Wed, 28 Oct 2015 11:48:15 +0100 Subject: [PATCH 16/25] The WM_NAME option takes an argument --- README.pod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.pod b/README.pod index ea7eb7f..d0adc1b 100644 --- a/README.pod +++ b/README.pod @@ -6,7 +6,7 @@ lemonbar - Featherweight lemon-scented bar =head1 SYNOPSIS -I [-h | -g IBIB<+>IB<+>I | -b | -d | -f I | -p | -n | -u I | -B I | -F I] +I [-h | -g IBIB<+>IB<+>I | -b | -d | -f I | -p | -n I | -u I | -B I | -F I] =head1 DESCRIPTION @@ -41,7 +41,7 @@ changing the MAX_FONT_COUNT parameter in the source code). Make the bar permanent, don't exit after the standard input is closed. -=item B<-n> +=item B<-n> I Set the WM_NAME atom value for the bar. From 2c0f57c5846e34b3576c58808a296266e9f8a30b Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 28 Oct 2015 22:41:15 +0100 Subject: [PATCH 17/25] Prevent load_font calls before connecting to X --- lemonbar.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index 6582160..11aabb3 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -1246,6 +1246,9 @@ main (int argc, char **argv) areas = 10; wm_name = NULL; + // Connect to the Xserver and initialize scr + xconn(); + while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:n:")) != -1) { switch (ch) { case 'h': @@ -1297,9 +1300,6 @@ main (int argc, char **argv) bx = geom_v[2]; by = geom_v[3]; - // Connect to the Xserver and initialize scr - xconn(); - // Do the heavy lifting init(wm_name); // Get the fd to Xserver From da2620901319974c5acac98583b8a26edf40ece2 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Sun, 15 Nov 2015 13:24:36 +0100 Subject: [PATCH 18/25] Fix LemonBoy/bar#154 and krypt-n/bar#18 Widening the bitfield by 1 would be a solution aswell. Problem was that an int:3 has a range of -4 to 3, buttons 4 and 5 did not fit into it --- lemonbar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemonbar.c b/lemonbar.c index 11aabb3..c6e0b29 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -40,7 +40,7 @@ typedef struct area_t { unsigned int end:16; bool active:1; int align:3; - int button:3; + int button; xcb_window_t window; char *cmd; } area_t; From e0aee14533d7a341c29643d8f3831d834cf88b11 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Sun, 15 Nov 2015 23:06:19 +0100 Subject: [PATCH 19/25] Saving 4 byte of memory on 32-Bit systems --- lemonbar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemonbar.c b/lemonbar.c index c6e0b29..4f2ce26 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -40,7 +40,7 @@ typedef struct area_t { unsigned int end:16; bool active:1; int align:3; - int button; + unsigned int button:3; xcb_window_t window; char *cmd; } area_t; From e4ea4071ab91163eff7411d16a2913b7eec44bf5 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 16 Nov 2015 11:00:22 -0500 Subject: [PATCH 20/25] Added -a to README.pod (and, therefore, the man page) --- README.pod | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.pod b/README.pod index d0adc1b..053bbff 100644 --- a/README.pod +++ b/README.pod @@ -37,6 +37,10 @@ Force docking without asking the window manager. This is needed if the window ma Define the font to load into one of the five slots (the number of slots is hardcoded and can be tweaked by changing the MAX_FONT_COUNT parameter in the source code). +=item B<-a> I + +Set number of clickable areas (default is 10) + =item B<-p> Make the bar permanent, don't exit after the standard input is closed. From 214ad6392583f573035377ee0511db7008ece998 Mon Sep 17 00:00:00 2001 From: Adam Niederer Date: Thu, 10 Dec 2015 17:59:58 -0500 Subject: [PATCH 21/25] Fix Typo Siz -> Six in comment --- lemonbar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemonbar.c b/lemonbar.c index 4f2ce26..4e33ce4 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -598,7 +598,7 @@ parse (char *text) ucs = 0xfffd; p += 5; } - // Siz byte utf8 sequence + // Six byte utf8 sequence else if ((utf[0] & 0xfe) == 0xfc) { ucs = 0xfffd; p += 6; From 7c8eb7495bd3594d461125e2c99818eb155ff6ef Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 15 Dec 2015 19:05:39 +0100 Subject: [PATCH 22/25] Fix an off-by-one error in 'area_get'. Fixes #160. --- lemonbar.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index 4e33ce4..cfd4d9b 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -326,10 +326,9 @@ area_t * area_get (xcb_window_t win, const int btn, const int x) { // Looping backwards ensures that we get the innermost area first - for (int i = area_stack.at; i >= 0; i--) { + for (int i = area_stack.at - 1; i >= 0; i--) { area_t *a = &area_stack.area[i]; - if (a->window == win && a->button == btn - && x >= a->begin && x < a->end) + if (a->window == win && a->button == btn && x >= a->begin && x < a->end) return a; } return NULL; From d3d7a87b664b99d0cff7d4d772aa2ad00068a59d Mon Sep 17 00:00:00 2001 From: Bastien Dejean Date: Wed, 23 Dec 2015 11:59:53 +0100 Subject: [PATCH 23/25] Commands in clickable areas aren't executed --- README.pod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.pod b/README.pod index 053bbff..8173b4a 100644 --- a/README.pod +++ b/README.pod @@ -103,7 +103,7 @@ Set the text underline color. The parameter I can be I<-> or a color in o =item BI