From dc5edd2863fff1b1f571b0eb9d06b11999d79601 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Wed, 8 Oct 2014 21:47:26 +0200 Subject: [PATCH 01/42] Initial port of xft support to a recent bar version --- Makefile | 7 +- bar.c | 666 ++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 441 insertions(+), 232 deletions(-) diff --git a/Makefile b/Makefile index ff620a8..d77f4f1 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ CC ?= gcc STRIP ?= strip -CFLAGS = -std=c99 -Os -LDFLAGS = -lxcb -lxcb-xinerama -lxcb-randr -CFDEBUG = -g3 -pedantic -Wall -Wunused-parameter -Wlong-long\ +CFLAGS = -std=c99 -I/usr/include/freetype2 +LDFLAGS = -lxcb -lxcb-xinerama -lxcb-randr -lX11 -lX11-xcb -lXft -lfreetype -lz -lfontconfig +CFDEBUG = -g3 -pedantic -Wall -Wextra -Wunused-parameter -Wlong-long\ -Wsign-conversion -Wconversion -Wimplicit-function-declaration EXEC = bar @@ -22,7 +22,6 @@ doc: README.pod ${EXEC}: ${OBJS} ${CC} -o ${EXEC} ${OBJS} ${LDFLAGS} - ${STRIP} -s ${EXEC} debug: ${EXEC} debug: CC += ${CFDEBUG} diff --git a/bar.c b/bar.c index bec8a15..920c23a 100644 --- a/bar.c +++ b/bar.c @@ -12,7 +12,10 @@ #include #include -// Here be dragons +#include +#include + +// Here bet dragons #define max(a,b) ((a) > (b) ? (a) : (b)) #define min(a,b) ((a) < (b) ? (a) : (b)) @@ -20,10 +23,15 @@ typedef struct font_t { xcb_font_t ptr; + xcb_charinfo_t *width_lut; + + XftFont *xft_ft; + + int ascent; + int descent, height; uint16_t char_max; uint16_t char_min; - xcb_charinfo_t *width_lut; } font_t; typedef struct monitor_t { @@ -51,11 +59,10 @@ enum { ATTR_UNDERL = (1<<1), }; -enum { - ALIGN_L = 0, - ALIGN_C, - ALIGN_R -}; +enum { ALIGN_L = 0, + ALIGN_C, + ALIGN_R + }; enum { GC_DRAW = 0, @@ -68,11 +75,15 @@ enum { /* 0 <= FONT_CACHE_SIZE <= 65536 */ #define FONT_CACHE_SIZE 256 +static Display *dpy; static xcb_connection_t *c; static xcb_screen_t *scr; static xcb_gcontext_t gc[GC_MAX]; static xcb_visualid_t visual; static xcb_colormap_t colormap; + + + static monitor_t *monhead, *montail; static font_t *font_list[MAX_FONT_COUNT]; static char *font_names[MAX_FONT_COUNT]; @@ -86,46 +97,112 @@ static uint32_t fgc, bgc, ugc; static uint32_t dfgc, dbgc; static area_stack_t astack; +static XftColor sel_fg; +static XftDraw *xft_draw; + +#define MAX_WIDTHS (1 << 16) +static wchar_t xft_char[MAX_WIDTHS]; +static char xft_width[MAX_WIDTHS]; + void update_gc (void) { - xcb_change_gc(c, gc[GC_DRAW], XCB_GC_BACKGROUND | XCB_GC_FOREGROUND, (const uint32_t []){ fgc, bgc }); - xcb_change_gc(c, gc[GC_CLEAR], XCB_GC_FOREGROUND, (const uint32_t []){ bgc }); - xcb_change_gc(c, gc[GC_ATTR], XCB_GC_FOREGROUND, (const uint32_t []){ ugc }); + xcb_change_gc(c, gc[GC_DRAW], XCB_GC_BACKGROUND | XCB_GC_FOREGROUND, (const uint32_t []) { + fgc, bgc + }); + xcb_change_gc(c, gc[GC_CLEAR], XCB_GC_FOREGROUND, (const uint32_t []) { + bgc + }); + xcb_change_gc(c, gc[GC_ATTR], XCB_GC_FOREGROUND, (const uint32_t []) { + ugc + }); + + XftColorFree(dpy, DefaultVisual(dpy, DefaultScreen(dpy)), DefaultColormap(dpy, DefaultScreen(dpy)), &sel_fg); + char color[8] = "#ffffff"; + snprintf(color, sizeof(color), "#%06X", fgc); + + if (!XftColorAllocName (dpy, DefaultVisual(dpy, DefaultScreen(dpy)), DefaultColormap(dpy, DefaultScreen(dpy)), color, &sel_fg)) { + fprintf(stderr, "Couldn't allocate xft font color '%s'\n", color); + } } void fill_rect (xcb_drawable_t d, xcb_gcontext_t gc, int x, int y, int width, int height) { - xcb_poly_fill_rectangle(c, d, gc, 1, (const xcb_rectangle_t []){ { x, y, width, height } }); + xcb_poly_fill_rectangle(c, d, gc, 1, (const xcb_rectangle_t []) { + { + x, y, width, height + } + }); +} + + +int +xft_char_width_slot (wchar_t ch) +{ + int slot = ch % MAX_WIDTHS; + while (xft_char[slot] != 0 && xft_char[slot] != ch) + { + slot = (slot + 1) % MAX_WIDTHS; + } + return slot; +} + +int xft_char_width (wchar_t ch, font_t *cur_font) +{ + int slot = xft_char_width_slot(ch); + if (!xft_char[slot]) { + XGlyphInfo gi; + FT_UInt glyph = XftCharIndex (dpy, cur_font->xft_ft, ch); + XftFontLoadGlyphs (dpy, cur_font->xft_ft, FcFalse, &glyph, 1); + XftGlyphExtents (dpy, cur_font->xft_ft, &glyph, 1, &gi); + XftFontUnloadGlyphs (dpy, cur_font->xft_ft, &glyph, 1); + xft_char[slot] = ch; + xft_width[slot] = gi.xOff; + return gi.xOff; + } else if (xft_char[slot] == ch) + return xft_width[slot]; + else + return 0; } int -draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) +draw_char (monitor_t *mon, font_t *cur_font, int x, int align, wchar_t ch) { - int ch_width = cur_font->width_lut[ch - cur_font->char_min].character_width; + int ch_width; + + if (cur_font->xft_ft) { + ch_width = xft_char_width(ch, cur_font); + } else { + ch_width = cur_font->width_lut[ch - cur_font->char_min].character_width; + } switch (align) { - case ALIGN_C: - xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], mon->width / 2 - x / 2, 0, - mon->width / 2 - (x + ch_width) / 2, 0, x, bh); - x = mon->width / 2 - (x + ch_width) / 2 + x; - break; - case ALIGN_R: - xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], mon->width - x, 0, - mon->width - x - ch_width, 0, x, bh); - x = mon->width - ch_width; - break; + case ALIGN_C: + xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], mon->width / 2 - x / 2, 0, + mon->width / 2 - (x + ch_width) / 2, 0, x, bh); + x = mon->width / 2 - (x + ch_width) / 2 + x; + break; + case ALIGN_R: + xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], mon->width - x, 0, + mon->width - x - ch_width, 0, x, bh); + x = mon->width - ch_width; + break; } /* Draw the background first */ fill_rect(mon->pixmap, gc[GC_CLEAR], x, by, ch_width, bh); - /* xcb accepts string in UCS-2 BE, so swap */ - ch = (ch >> 8) | (ch << 8); - - /* String baseline coordinates */ - xcb_image_text_16(c, 1, mon->pixmap, gc[GC_DRAW], x, bh / 2 + cur_font->height / 2 - cur_font->descent, (xcb_char2b_t *)&ch); + int y = bh / 2 + cur_font->height / 2- cur_font->descent; + if (cur_font->xft_ft) { + XftDrawString32 (xft_draw, &sel_fg, cur_font->xft_ft, x,y, &ch, 1); + } else { + char c_ = ch > 127 ? ' ' : ch; + /* xcb accepts string in UCS-2 BE, so swap */ + ch = (ch >> 8) | (ch << 8); + /* String baseline coordinates */ + xcb_image_text_8(c, 1, mon->pixmap, gc[GC_DRAW], x,y, &c_); + } /* We can render both at the same time */ if (attrs & ATTR_OVERL) @@ -136,10 +213,50 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) return ch_width; } +int +utf8decode(char *s, wchar_t *u) { + unsigned char c; + int i, n, rtn; + rtn = 1; + c = *s; + if(~c & 0x80) { /* 0xxxxxxx */ + *u = c; + return rtn; + } else if((c & 0xE0) == 0xC0) { /* 110xxxxx */ + *u = c & 0x1F; + n = 1; + } else if((c & 0xF0) == 0xE0) { /* 1110xxxx */ + *u = c & 0x0F; + n = 2; + } else if((c & 0xF8) == 0xF0) { /* 11110xxx */ + *u = c & 0x07; + n = 3; + } else { + goto invalid; + } + for(i = n, ++s; i > 0; --i, ++rtn, ++s) { + c = *s; + if((c & 0xC0) != 0x80) /* 10xxxxxx */ + goto invalid; + *u <<= 6; + *u |= c & 0x3F; + } + if((n == 1 && *u < 0x80) || + (n == 2 && *u < 0x800) || + (n == 3 && *u < 0x10000) || + (*u >= 0xD800 && *u <= 0xDFFF)) { + goto invalid; + } + return rtn; +invalid: + *u = 0xFFFD; + return rtn; +} + uint32_t parse_color (const char *str, char **end, const uint32_t def) { - xcb_alloc_named_color_reply_t *nc_reply; + xcb_alloc_named_color_reply_t *nc_reply = 0; int str_len; uint32_t ret; @@ -177,8 +294,9 @@ parse_color (const char *str, char **end, const uint32_t def) if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; - } else - r = g = b = 0; + } else { + + } return a << 24 | r << 16 | g << 8 | b; } @@ -213,9 +331,15 @@ set_attribute (const char modifier, const char attribute) } switch (modifier) { - case '+': attrs |= (1<begin; switch (align) { - case ALIGN_L: - a->end = x; - break; - case ALIGN_C: - a->begin = mon->width / 2 - size / 2 + a->begin / 2; - a->end = a->begin + size; - break; - case ALIGN_R: - /* The newest is the rightmost one */ - a->begin = mon->width - size; - a->end = mon->width; - break; + case ALIGN_L: + a->end = x; + break; + case ALIGN_C: + a->begin = mon->width / 2 - size / 2 + a->begin / 2; + a->end = a->begin + size; + break; + case ALIGN_R: + /* The newest is the rightmost one */ + a->begin = mon->width - size; + a->end = mon->width; + break; } astack.pos++; @@ -310,15 +434,16 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x /* returns NULL if character cannot be printed */ font_t * -select_drawable_font (const uint16_t c) +select_drawable_font (const wchar_t c) { /* if the end is reached without finding an apropriate font, return NULL. * If the font can draw the character, return it. */ for (int i = 0; font_list[i] != NULL; i++) { font_t *font = font_list[i]; - if (c > font->char_min && c < font->char_max && - font->width_lut[c - font->char_min].character_width != 0) + if ((c > font->char_min && c < font->char_max && + font->width_lut[c - font->char_min].character_width != 0)|| + (font->xft_ft && XftCharExists(dpy, font->xft_ft, c))) return font; } return NULL; @@ -326,7 +451,7 @@ select_drawable_font (const uint16_t c) /* returns NULL if character cannot be printed */ font_t * -select_drawable_font_cache (uint16_t c) +select_drawable_font_cache (wchar_t c) { if (c < FONT_CACHE_SIZE) return font_cache[c]; @@ -352,6 +477,13 @@ parse (char *text) for (monitor_t *m = monhead; m != NULL; m = m->next) fill_rect(m->pixmap, gc[GC_CLEAR], 0, 0, m->width, bh); + /* Create xft drawable */ + int s = DefaultScreen (dpy); + if (!(xft_draw = XftDrawCreate (dpy, cur_mon->pixmap, DefaultVisual(dpy, s), DefaultColormap(dpy, s)))) { + //if (!(xft_draw = XftDrawCreate (dpy, cur_mon->pixmap, visual_ptr, colormap))) { + fprintf(stderr, "Couldn't create xft drawable\n"); + } + for (;;) { if (*p == '\0' || *p == '\n') return; @@ -362,94 +494,117 @@ parse (char *text) p++; switch (*p++) { - case '+': set_attribute('+', *p++); break; - case '-': set_attribute('-', *p++); break; - case '!': set_attribute('!', *p++); break; + case '+': + set_attribute('+', *p++); + break; + case '-': + set_attribute('-', *p++); + break; + case '!': + set_attribute('!', *p++); + break; - case 'R': - tmp = fgc; - fgc = bgc; - bgc = tmp; - update_gc(); - break; + case 'R': + tmp = fgc; + fgc = bgc; + bgc = tmp; + update_gc(); + break; - case 'l': pos_x = 0; align = ALIGN_L; break; - case 'c': pos_x = 0; align = ALIGN_C; break; - case 'r': pos_x = 0; align = ALIGN_R; break; + case 'l': + pos_x = 0; + align = ALIGN_L; + break; + case 'c': + pos_x = 0; + align = ALIGN_C; + break; + case 'r': + pos_x = 0; + align = ALIGN_R; + break; - case 'A': - button = XCB_BUTTON_INDEX_1; - /* The range is 1-5 */ - if (isdigit(*p) && (*p > '0' && *p < '6')) - button = *p++ - '0'; - area_add(p, end, &p, cur_mon, pos_x, align, button); - break; + case 'A': + button = XCB_BUTTON_INDEX_1; + /* The range is 1-5 */ + if (isdigit(*p) && (*p > '0' && *p < '6')) + button = *p++ - '0'; + area_add(p, end, &p, cur_mon, pos_x, align, button); + break; - case 'B': bgc = parse_color(p, &p, dbgc); update_gc(); break; - case 'F': fgc = parse_color(p, &p, dfgc); update_gc(); break; - case 'U': ugc = parse_color(p, &p, dbgc); update_gc(); break; + case 'B': + bgc = parse_color(p, &p, dbgc); + update_gc(); + break; + case 'F': + fgc = parse_color(p, &p, dfgc); + update_gc(); + break; + case 'U': + ugc = parse_color(p, &p, dbgc); + update_gc(); + break; - case 'S': - if (*p == '+' && cur_mon->next) - { cur_mon = cur_mon->next; } - else if (*p == '-' && cur_mon->prev) - { cur_mon = cur_mon->prev; } - else if (*p == 'f') - { cur_mon = monhead; } - else if (*p == 'l') - { cur_mon = montail ? montail : monhead; } - else if (isdigit(*p)) - { cur_mon = monhead; - for (int i = 0; i != *p-'0' && cur_mon->next; i++) - cur_mon = cur_mon->next; - } - else - { p++; continue; } + case 'S': + if (*p == '+' && cur_mon->next) + { + cur_mon = cur_mon->next; + } + else if (*p == '-' && cur_mon->prev) + { + cur_mon = cur_mon->prev; + } + else if (*p == 'f') + { + cur_mon = monhead; + } + else if (*p == 'l') + { + cur_mon = montail ? montail : monhead; + } + else if (isdigit(*p)) + { cur_mon = monhead; + for (int i = 0; i != *p-'0' && cur_mon->next; i++) + cur_mon = cur_mon->next; + } + else + { + p++; + continue; + } - p++; - pos_x = 0; - break; + p++; + pos_x = 0; + break; - /* In case of error keep parsing after the closing } */ - default: - p = end; + /* In case of error keep parsing after the closing } */ + default: + p = end; } } /* Eat the trailing } */ p++; } else { /* utf-8 -> ucs-2 */ - uint8_t *utf = (uint8_t *)p; - uint16_t ucs; - if (utf[0] < 0x80) { - ucs = utf[0]; - p += 1; - } - else if ((utf[0] & 0xe0) == 0xc0) { - ucs = (utf[0] & 0x1f) << 6 | (utf[1] & 0x3f); - p += 2; - } - else if ((utf[0] & 0xf0) == 0xe0) { - ucs = (utf[0] & 0xf) << 12 | (utf[1] & 0x3f) << 6 | (utf[2] & 0x3f); - p += 3; - } - else { /* Handle ascii > 0x80 */ - ucs = utf[0]; - p += 1; - } - cur_font = select_drawable_font(ucs); + wchar_t t; + p += utf8decode(p, &t); + + cur_font = select_drawable_font(t); if (!cur_font) continue; - xcb_change_gc(c, gc[GC_DRAW] , XCB_GC_FONT, (const uint32_t []){ cur_font->ptr }); - - int w = draw_char(cur_mon, cur_font, pos_x, align, ucs); + if(cur_font->ptr) + xcb_change_gc(c, gc[GC_DRAW] , XCB_GC_FONT, (const uint32_t []) { + cur_font->ptr + }); + int w = draw_char(cur_mon, cur_font, pos_x, align, t); pos_x += w; area_shift(cur_mon->window, align, w); } } + XftDrawDestroy (xft_draw); } font_t * @@ -462,26 +617,30 @@ font_load (const char *str) font = xcb_generate_id(c); - cookie = xcb_open_font_checked(c, font, strlen(str), str); - if (xcb_request_check (c, cookie)) { - fprintf(stderr, "Could not load font %s\n", str); - return NULL; - } - font_t *ret = calloc(1, sizeof(font_t)); if (!ret) return NULL; - queryreq = xcb_query_font(c, font); - font_info = xcb_query_font_reply(c, queryreq, NULL); + cookie = xcb_open_font_checked(c, font, strlen(str), str); + if (!xcb_request_check (c, cookie)) { + queryreq = xcb_query_font(c, font); + font_info = xcb_query_font_reply(c, queryreq, NULL); - ret->ptr = font; - ret->descent = font_info->font_descent; - ret->height = font_info->font_ascent + font_info->font_descent; - 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; - ret->width_lut = xcb_query_font_char_infos(font_info); + ret->ptr = font; + ret->descent = font_info->font_descent; + ret->height = font_info->font_ascent + font_info->font_descent; + 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; + ret->width_lut = xcb_query_font_char_infos(font_info); + } else if (ret->xft_ft = XftFontOpenName (dpy, DefaultScreen(dpy), str)) { + ret->ascent = ret->xft_ft->ascent; + ret->descent = ret->xft_ft->descent; + ret->height = ret->ascent + ret->descent; + } else { + fprintf(stderr, "Could not load font %s\n", str); + return NULL; + } return ret; } @@ -544,7 +703,9 @@ set_ewmh_atoms (void) xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_WINDOW_TYPE], XCB_ATOM_ATOM, 32, 1, &atom_list[NET_WM_WINDOW_TYPE_DOCK]); xcb_change_property(c, XCB_PROP_MODE_APPEND, mon->window, atom_list[NET_WM_STATE], XCB_ATOM_ATOM, 32, 2, &atom_list[NET_WM_STATE_STICKY]); - xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_DESKTOP], XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []){ -1 } ); + xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_DESKTOP], XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []) { + -1 + } ); xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_STRUT_PARTIAL], XCB_ATOM_CARDINAL, 32, 12, strut); xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_STRUT], XCB_ATOM_CARDINAL, 32, 4, strut); } @@ -569,14 +730,16 @@ monitor_new (int x, int y, int width, int height) ret->window = xcb_generate_id(c); int depth = (visual == scr->root_visual) ? XCB_COPY_FROM_PARENT : 32; - xcb_create_window(c, depth, ret->window, scr->root, - x, win_y, width, bh, 0, - XCB_WINDOW_CLASS_INPUT_OUTPUT, visual, - XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP, - (const uint32_t []){ bgc, bgc, dock, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS, colormap }); + xcb_create_window(c, XCB_COPY_FROM_PARENT, ret->window, scr->root, + x, win_y, width, bh, 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual, + XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK , + (const uint32_t []) { + bgc, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS + }); ret->pixmap = xcb_generate_id(c); - xcb_create_pixmap(c, depth, ret->pixmap, ret->window, width, bh); + xcb_create_pixmap(c, scr->root_depth, ret->pixmap, ret->window, width, bh); return ret; } @@ -627,7 +790,7 @@ monitor_create_chain (xcb_rectangle_t *rects, const int num) width += rects[i].width; /* Get height of screen from y_offset + height of lowest monitor */ if (h >= height) - height = h; + height = h; } if (bw < 0) @@ -649,10 +812,10 @@ monitor_create_chain (xcb_rectangle_t *rects, const int num) continue; if (rects[i].width > left) { monitor_t *mon = monitor_new( - rects[i].x + left, - rects[i].y, - min(width, rects[i].width - left), - rects[i].height); + rects[i].x + left, + rects[i].y, + min(width, rects[i].width - left), + rects[i].height); monitor_add(mon); @@ -678,7 +841,7 @@ get_randr_monitors (void) int i, j, num, valid = 0; rres_reply = xcb_randr_get_screen_resources_current_reply(c, - xcb_randr_get_screen_resources_current(c, scr->root), NULL); + xcb_randr_get_screen_resources_current(c, scr->root), NULL); if (!rres_reply) { fprintf(stderr, "Failed to get current randr screen resources\n"); @@ -711,7 +874,7 @@ get_randr_monitors (void) } ci_reply = xcb_randr_get_crtc_info_reply(c, - xcb_randr_get_crtc_info(c, oi_reply->crtc, XCB_CURRENT_TIME), NULL); + xcb_randr_get_crtc_info(c, oi_reply->crtc, XCB_CURRENT_TIME), NULL); free(oi_reply); @@ -722,7 +885,9 @@ get_randr_monitors (void) } /* There's no need to handle rotated screens here (see #69) */ - rects[i] = (xcb_rectangle_t){ ci_reply->x, ci_reply->y, ci_reply->width, ci_reply->height }; + rects[i] = (xcb_rectangle_t) { + ci_reply->x, ci_reply->y, ci_reply->width, ci_reply->height + }; free(ci_reply); @@ -741,7 +906,7 @@ get_randr_monitors (void) if (i != j && rects[j].width) { if (rects[j].x >= rects[i].x && rects[j].x + rects[j].width <= rects[i].x + rects[i].width && - rects[j].y >= rects[i].y && rects[j].y + rects[j].height <= rects[i].y + rects[i].height) { + rects[j].y >= rects[i].y && rects[j].y + rects[j].height <= rects[i].y + rects[i].height) { rects[j].width = 0; valid--; } @@ -754,11 +919,11 @@ get_randr_monitors (void) return; } - xcb_rectangle_t r[valid]; + xcb_rectangle_t r[valid]; - for (i = j = 0; i < num && j < valid; i++) - if (rects[i].width != 0) - r[j++] = rects[i]; + for (i = j = 0; i < num && j < valid; i++) + if (rects[i].width != 0) + r[j++] = rects[i]; monitor_create_chain(r, valid); } @@ -771,7 +936,7 @@ get_xinerama_monitors (void) int screens; xqs_reply = xcb_xinerama_query_screens_reply(c, - xcb_xinerama_query_screens_unchecked(c), NULL); + xcb_xinerama_query_screens_unchecked(c), NULL); iter = xcb_xinerama_query_screens_screen_info_iterator(xqs_reply); screens = iter.rem; @@ -795,20 +960,26 @@ get_xinerama_monitors (void) xcb_visualid_t get_visual (void) { - xcb_depth_iterator_t iter; - iter = xcb_screen_allowed_depths_iterator(scr); + visual = scr->root_visual; + return visual; + /* + xcb_depth_iterator_t iter; + iter = xcb_screen_allowed_depths_iterator(scr); + */ /* Try to find a RGBA visual */ - while (iter.rem) { - xcb_visualtype_t *vis = xcb_depth_visuals(iter.data); + /* while (iter.rem) { + xcb_visualtype_t *vis = xcb_depth_visuals(iter.data); - if (iter.data->depth == 32) - return vis->visual_id; - - xcb_depth_next(&iter); - } + if (iter.data->depth == 32) { + visual_ptr = vis; + return vis->visual_id; + } + xcb_depth_next(&iter); + } + */ /* Fallback to the default one */ return scr->root_visual; } @@ -816,21 +987,24 @@ get_visual (void) void xconn (void) { - /* Connect to X */ - c = xcb_connect (NULL, NULL); - if (xcb_connection_has_error(c)) { - fprintf(stderr, "Couldn't connect to X\n"); - exit(EXIT_FAILURE); + if ((dpy = XOpenDisplay(0)) == NULL) { + fprintf (stderr, "Couldnt open display\n"); + } + + if ((c = XGetXCBConnection(dpy)) == NULL) { + fprintf (stderr, "Couldnt connect to X\n"); + exit (EXIT_FAILURE); } /* Grab infos from the first screen */ scr = xcb_setup_roots_iterator(xcb_get_setup(c)).data; + colormap = scr->default_colormap; /* Try to get a RGBA visual and build the colormap for that */ - visual = get_visual(); + // visual = get_visual(); + // colormap = xcb_generate_id(c); + // xcb_create_colormap(c, XCB_COLORMAP_ALLOC_NONE, colormap, scr->root, visual); - colormap = xcb_generate_id(c); - xcb_create_colormap(c, XCB_COLORMAP_ALLOC_NONE, colormap, scr->root, visual); } void @@ -867,25 +1041,25 @@ init (void) /* Initialiaze monitor list head and tail */ monhead = montail = NULL; - /* Check if RandR is present */ - qe_reply = xcb_get_extension_data(c, &xcb_randr_id); + // /* Check if RandR is present */ + //qe_reply = xcb_get_extension_data(c, &xcb_randr_id); - if (qe_reply && qe_reply->present) { - get_randr_monitors(); - } else { - qe_reply = xcb_get_extension_data(c, &xcb_xinerama_id); - - /* Check if Xinerama extension is present and active */ - if (qe_reply && qe_reply->present) { - xcb_xinerama_is_active_reply_t *xia_reply; - xia_reply = xcb_xinerama_is_active_reply(c, xcb_xinerama_is_active(c), NULL); - - if (xia_reply && xia_reply->state) - get_xinerama_monitors(); - - free(xia_reply); - } - } + //if (qe_reply && qe_reply->present) { + //get_randr_monitors(); + //} else { + //qe_reply = xcb_get_extension_data(c, &xcb_xinerama_id); + // + ///* Check if Xinerama extension is present and active */ + //if (qe_reply && qe_reply->present) { + //xcb_xinerama_is_active_reply_t *xia_reply; + //xia_reply = xcb_xinerama_is_active_reply(c, xcb_xinerama_is_active(c), NULL); + // + //if (xia_reply && xia_reply->state) + //get_xinerama_monitors(); + // + //free(xia_reply); + //} + //} if (!monhead) { /* If I fits I sits */ @@ -914,13 +1088,19 @@ init (void) /* Create the gc for drawing */ gc[GC_DRAW] = xcb_generate_id(c); - xcb_create_gc(c, gc[GC_DRAW], monhead->pixmap, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, (const uint32_t []){ fgc, bgc }); + xcb_create_gc(c, gc[GC_DRAW], monhead->pixmap, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, (const uint32_t []) { + fgc, bgc + }); gc[GC_CLEAR] = xcb_generate_id(c); - xcb_create_gc(c, gc[GC_CLEAR], monhead->pixmap, XCB_GC_FOREGROUND, (const uint32_t []){ bgc }); + xcb_create_gc(c, gc[GC_CLEAR], monhead->pixmap, XCB_GC_FOREGROUND, (const uint32_t []) { + bgc + }); gc[GC_ATTR] = xcb_generate_id(c); - xcb_create_gc(c, gc[GC_ATTR], monhead->pixmap, XCB_GC_FOREGROUND, (const uint32_t []){ ugc }); + xcb_create_gc(c, gc[GC_ATTR], monhead->pixmap, XCB_GC_FOREGROUND, (const uint32_t []) { + ugc + }); /* Make the bar visible and clear the pixmap */ for (monitor_t *mon = monhead; mon; mon = mon->next) { @@ -928,6 +1108,12 @@ init (void) xcb_map_window(c, mon->window); } + char color[8] = "#ffffff"; + snprintf(color, sizeof(color), "#%06X", fgc); + + if (!XftColorAllocName (dpy, DefaultVisual(dpy, DefaultScreen(dpy)), DefaultColormap(dpy, DefaultScreen(dpy)), color, &sel_fg)) { + fprintf(stderr, "Couldn't allocate xft font color '%s'\n", color); + } xcb_flush(c); } @@ -935,7 +1121,12 @@ void cleanup (void) { for (int i = 0; font_list[i]; i++) { - xcb_close_font(c, font_list[i]->ptr); + if (font_list[i]->xft_ft) { + XftFontClose (dpy, font_list[i]->xft_ft); + } + else { + xcb_close_font(c, font_list[i]->ptr); + } free(font_list[i]); font_list[i] = NULL; } @@ -948,7 +1139,8 @@ cleanup (void) monhead = next; } - xcb_free_colormap(c, colormap); + XftColorFree(dpy, DefaultVisual(dpy, DefaultScreen(dpy)), DefaultColormap(dpy, DefaultScreen(dpy)), &sel_fg); + //xcb_free_colormap(c, colormap); if (gc[GC_DRAW]) xcb_free_gc(c, gc[GC_DRAW]); @@ -991,14 +1183,17 @@ parse_geometry_string (char *str, int *tmp) if (*p == 'x') { if (i > 0) /* The 'x' must precede '+' */ break; - i++; p++; continue; + i++; + p++; + continue; } if (*p == '+') { if (i < 1) /* Stray '+', skip the first two fields */ i = 2; else i++; - p++; continue; + p++; + continue; } /* A digit must follow */ if (!isdigit(*p)) { @@ -1038,7 +1233,6 @@ parse_font_list (char *str) tok = strtok(NULL, ","); } } - int main (int argc, char **argv) { @@ -1070,26 +1264,42 @@ main (int argc, char **argv) char ch; while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:")) != -1) { switch (ch) { - case 'h': - printf ("usage: %s [-h | -g | -b | -d | -f | -a | -p | -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 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-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" - "\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 'b': topbar = false; break; - case 'd': dock = true; break; - case 'f': parse_font_list(optarg); break; - case 'u': bu = strtoul(optarg, NULL, 10); break; - case 'B': dbgc = bgc = parse_color(optarg, NULL, scr->black_pixel); break; - case 'F': dfgc = fgc = parse_color(optarg, NULL, scr->white_pixel); break; + case 'h': + printf ("usage: %s [-h | -g | -b | -d | -f | -a | -p | -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 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-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" + "\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 'b': + topbar = false; + break; + case 'd': + dock = true; + break; + case 'f': + parse_font_list(optarg); + break; + case 'u': + bu = strtoul(optarg, NULL, 10); + break; + case 'B': + dbgc = bgc = parse_color(optarg, NULL, scr->black_pixel); + break; + case 'F': + dfgc = fgc = parse_color(optarg, NULL, scr->white_pixel); + break; } } @@ -1124,21 +1334,21 @@ main (int argc, char **argv) expose_ev = (xcb_expose_event_t *)ev; switch (ev->response_type & 0x7F) { - case XCB_EXPOSE: - if (expose_ev->count == 0) - redraw = true; - break; - case XCB_BUTTON_PRESS: - press_ev = (xcb_button_press_event_t *)ev; - { - area_t *area = area_get(press_ev->event, press_ev->event_x); - /* Respond to the click */ - if (area && area->button == press_ev->detail) { - write(STDOUT_FILENO, area->cmd, strlen(area->cmd)); - write(STDOUT_FILENO, "\n", 1); - } + case XCB_EXPOSE: + if (expose_ev->count == 0) + redraw = true; + break; + case XCB_BUTTON_PRESS: + press_ev = (xcb_button_press_event_t *)ev; + { + area_t *area = area_get(press_ev->event, press_ev->event_x); + /* Respond to the click */ + if (area && area->button == press_ev->detail) { + write(STDOUT_FILENO, area->cmd, strlen(area->cmd)); + write(STDOUT_FILENO, "\n", 1); } - break; + } + break; } free(ev); From 2c0ea87587316b3d5cc2122edbaaee50e37b08ff Mon Sep 17 00:00:00 2001 From: krypt-n Date: Wed, 8 Oct 2014 23:00:19 +0200 Subject: [PATCH 02/42] Reenables Xrandr and Xinerama support. Untested --- Makefile | 2 +- bar.c | 81 ++++++++++++++++++++++++++++++++------------------------ 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index d77f4f1..e0be572 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC ?= gcc STRIP ?= strip -CFLAGS = -std=c99 -I/usr/include/freetype2 +CFLAGS = -std=c99 -I/usr/include/freetype2 -Os LDFLAGS = -lxcb -lxcb-xinerama -lxcb-randr -lX11 -lX11-xcb -lXft -lfreetype -lz -lfontconfig CFDEBUG = -g3 -pedantic -Wall -Wextra -Wunused-parameter -Wlong-long\ -Wsign-conversion -Wconversion -Wimplicit-function-declaration diff --git a/bar.c b/bar.c index 920c23a..6682e72 100644 --- a/bar.c +++ b/bar.c @@ -77,9 +77,13 @@ enum { static Display *dpy; static xcb_connection_t *c; + static xcb_screen_t *scr; +static int scr_nbr = 0; + static xcb_gcontext_t gc[GC_MAX]; static xcb_visualid_t visual; +static struct Visual *visual_ptr; static xcb_colormap_t colormap; @@ -117,11 +121,11 @@ update_gc (void) ugc }); - XftColorFree(dpy, DefaultVisual(dpy, DefaultScreen(dpy)), DefaultColormap(dpy, DefaultScreen(dpy)), &sel_fg); + XftColorFree(dpy, visual_ptr, colormap , &sel_fg); char color[8] = "#ffffff"; snprintf(color, sizeof(color), "#%06X", fgc); - if (!XftColorAllocName (dpy, DefaultVisual(dpy, DefaultScreen(dpy)), DefaultColormap(dpy, DefaultScreen(dpy)), color, &sel_fg)) { + if (!XftColorAllocName (dpy, visual_ptr, colormap, color, &sel_fg)) { fprintf(stderr, "Couldn't allocate xft font color '%s'\n", color); } } @@ -478,9 +482,8 @@ parse (char *text) fill_rect(m->pixmap, gc[GC_CLEAR], 0, 0, m->width, bh); /* Create xft drawable */ - int s = DefaultScreen (dpy); - if (!(xft_draw = XftDrawCreate (dpy, cur_mon->pixmap, DefaultVisual(dpy, s), DefaultColormap(dpy, s)))) { - //if (!(xft_draw = XftDrawCreate (dpy, cur_mon->pixmap, visual_ptr, colormap))) { + int s = scr_nbr; + if (!(xft_draw = XftDrawCreate (dpy, cur_mon->pixmap, visual_ptr , colormap ))) { fprintf(stderr, "Couldn't create xft drawable\n"); } @@ -633,7 +636,7 @@ font_load (const char *str) 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; ret->width_lut = xcb_query_font_char_infos(font_info); - } else if (ret->xft_ft = XftFontOpenName (dpy, DefaultScreen(dpy), str)) { + } else if (ret->xft_ft = XftFontOpenName (dpy, scr_nbr, str)) { ret->ascent = ret->xft_ft->ascent; ret->descent = ret->xft_ft->descent; ret->height = ret->ascent + ret->descent; @@ -961,8 +964,22 @@ xcb_visualid_t get_visual (void) { - visual = scr->root_visual; - return visual; + xcb_depth_iterator_t depth_iter; + + depth_iter = xcb_screen_allowed_depths_iterator (scr); + for (; depth_iter.rem; xcb_depth_next (&depth_iter)) { + xcb_visualtype_iterator_t visual_iter; + + visual_iter = xcb_depth_visuals_iterator (depth_iter.data); + for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) { + if (scr->root_visual == visual_iter.data->visual_id) { + visual_ptr = visual_iter.data; + break; + } + } + } + visual_ptr = DefaultVisual(dpy, scr_nbr); + return scr->root_visual; //scr->root_visual; /* xcb_depth_iterator_t iter; @@ -981,7 +998,6 @@ get_visual (void) } */ /* Fallback to the default one */ - return scr->root_visual; } void @@ -999,11 +1015,9 @@ xconn (void) /* Grab infos from the first screen */ scr = xcb_setup_roots_iterator(xcb_get_setup(c)).data; - colormap = scr->default_colormap; /* Try to get a RGBA visual and build the colormap for that */ - // visual = get_visual(); - // colormap = xcb_generate_id(c); - // xcb_create_colormap(c, XCB_COLORMAP_ALLOC_NONE, colormap, scr->root, visual); + visual = get_visual(); + colormap = DefaultColormap(dpy, scr_nbr); } @@ -1041,25 +1055,25 @@ init (void) /* Initialiaze monitor list head and tail */ monhead = montail = NULL; - // /* Check if RandR is present */ - //qe_reply = xcb_get_extension_data(c, &xcb_randr_id); + /* Check if RandR is present */ + qe_reply = xcb_get_extension_data(c, &xcb_randr_id); - //if (qe_reply && qe_reply->present) { - //get_randr_monitors(); - //} else { - //qe_reply = xcb_get_extension_data(c, &xcb_xinerama_id); - // - ///* Check if Xinerama extension is present and active */ - //if (qe_reply && qe_reply->present) { - //xcb_xinerama_is_active_reply_t *xia_reply; - //xia_reply = xcb_xinerama_is_active_reply(c, xcb_xinerama_is_active(c), NULL); - // - //if (xia_reply && xia_reply->state) - //get_xinerama_monitors(); - // - //free(xia_reply); - //} - //} + if (qe_reply && qe_reply->present) { + get_randr_monitors(); + } else { + qe_reply = xcb_get_extension_data(c, &xcb_xinerama_id); + + /* Check if Xinerama extension is present and active */ + if (qe_reply && qe_reply->present) { + xcb_xinerama_is_active_reply_t *xia_reply; + xia_reply = xcb_xinerama_is_active_reply(c, xcb_xinerama_is_active(c), NULL); + + if (xia_reply && xia_reply->state) + get_xinerama_monitors(); + + free(xia_reply); + } + } if (!monhead) { /* If I fits I sits */ @@ -1111,7 +1125,7 @@ init (void) char color[8] = "#ffffff"; snprintf(color, sizeof(color), "#%06X", fgc); - if (!XftColorAllocName (dpy, DefaultVisual(dpy, DefaultScreen(dpy)), DefaultColormap(dpy, DefaultScreen(dpy)), color, &sel_fg)) { + if (!XftColorAllocName (dpy, visual_ptr, colormap, color, &sel_fg)) { fprintf(stderr, "Couldn't allocate xft font color '%s'\n", color); } xcb_flush(c); @@ -1139,8 +1153,7 @@ cleanup (void) monhead = next; } - XftColorFree(dpy, DefaultVisual(dpy, DefaultScreen(dpy)), DefaultColormap(dpy, DefaultScreen(dpy)), &sel_fg); - //xcb_free_colormap(c, colormap); + XftColorFree(dpy, visual_ptr, colormap, &sel_fg); if (gc[GC_DRAW]) xcb_free_gc(c, gc[GC_DRAW]); From 6d7e66a887e657ba435cac80670170eec1c3488f Mon Sep 17 00:00:00 2001 From: krypt-n Date: Wed, 8 Oct 2014 23:04:34 +0200 Subject: [PATCH 03/42] Removed unused code --- bar.c | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/bar.c b/bar.c index 6682e72..14d988d 100644 --- a/bar.c +++ b/bar.c @@ -963,41 +963,8 @@ get_xinerama_monitors (void) xcb_visualid_t get_visual (void) { - - xcb_depth_iterator_t depth_iter; - - depth_iter = xcb_screen_allowed_depths_iterator (scr); - for (; depth_iter.rem; xcb_depth_next (&depth_iter)) { - xcb_visualtype_iterator_t visual_iter; - - visual_iter = xcb_depth_visuals_iterator (depth_iter.data); - for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) { - if (scr->root_visual == visual_iter.data->visual_id) { - visual_ptr = visual_iter.data; - break; - } - } - } visual_ptr = DefaultVisual(dpy, scr_nbr); return scr->root_visual; //scr->root_visual; - /* - xcb_depth_iterator_t iter; - - iter = xcb_screen_allowed_depths_iterator(scr); - */ - /* Try to find a RGBA visual */ - /* while (iter.rem) { - xcb_visualtype_t *vis = xcb_depth_visuals(iter.data); - - if (iter.data->depth == 32) { - visual_ptr = vis; - return vis->visual_id; - } - - xcb_depth_next(&iter); - } - */ - /* Fallback to the default one */ } void From 15c668905c0be5ec92b21b96edac742f02396288 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Wed, 8 Oct 2014 23:12:50 +0200 Subject: [PATCH 04/42] Removes unused variables, fixes pointer warning --- bar.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bar.c b/bar.c index 14d988d..828d016 100644 --- a/bar.c +++ b/bar.c @@ -83,7 +83,7 @@ static int scr_nbr = 0; static xcb_gcontext_t gc[GC_MAX]; static xcb_visualid_t visual; -static struct Visual *visual_ptr; +static Visual *visual_ptr; static xcb_colormap_t colormap; @@ -482,7 +482,6 @@ parse (char *text) fill_rect(m->pixmap, gc[GC_CLEAR], 0, 0, m->width, bh); /* Create xft drawable */ - int s = scr_nbr; if (!(xft_draw = XftDrawCreate (dpy, cur_mon->pixmap, visual_ptr , colormap ))) { fprintf(stderr, "Couldn't create xft drawable\n"); } @@ -636,7 +635,7 @@ font_load (const char *str) 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; ret->width_lut = xcb_query_font_char_infos(font_info); - } else if (ret->xft_ft = XftFontOpenName (dpy, scr_nbr, str)) { + } else if ((ret->xft_ft = XftFontOpenName (dpy, scr_nbr, str))) { ret->ascent = ret->xft_ft->ascent; ret->descent = ret->xft_ft->descent; ret->height = ret->ascent + ret->descent; @@ -732,7 +731,6 @@ monitor_new (int x, int y, int width, int height) int win_y = (topbar ? by : height - bh - by) + y; ret->window = xcb_generate_id(c); - int depth = (visual == scr->root_visual) ? XCB_COPY_FROM_PARENT : 32; xcb_create_window(c, XCB_COPY_FROM_PARENT, ret->window, scr->root, x, win_y, width, bh, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual, From 16b0aa81d15ccb02b22b84d75bc0542cab2bc2da Mon Sep 17 00:00:00 2001 From: krypt-n Date: Wed, 8 Oct 2014 23:16:48 +0200 Subject: [PATCH 05/42] XCB owns evenqueue --- bar.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bar.c b/bar.c index 828d016..c8d3b18 100644 --- a/bar.c +++ b/bar.c @@ -977,6 +977,8 @@ xconn (void) exit (EXIT_FAILURE); } + XSetEventQueueOwner(dpy, XCBOwnsEventQueue); + /* Grab infos from the first screen */ scr = xcb_setup_roots_iterator(xcb_get_setup(c)).data; From 3e2e54af90752b75f8063323d1fa1a7a2bf4fff4 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Wed, 8 Oct 2014 23:45:25 +0200 Subject: [PATCH 06/42] Restores all xcb_create_window parameters --- bar.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bar.c b/bar.c index c8d3b18..7fea3c7 100644 --- a/bar.c +++ b/bar.c @@ -733,10 +733,10 @@ monitor_new (int x, int y, int width, int height) xcb_create_window(c, XCB_COPY_FROM_PARENT, ret->window, scr->root, x, win_y, width, bh, 0, - XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual, - XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK , + XCB_WINDOW_CLASS_INPUT_OUTPUT, visual, + XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP, (const uint32_t []) { - bgc, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS + bgc, bgc, dock, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS, colormap }); ret->pixmap = xcb_generate_id(c); From f834c13ea02b621e0de797b55913e40c86a39e33 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Thu, 9 Oct 2014 12:58:12 +0200 Subject: [PATCH 07/42] Fixes parse-memory leak --- bar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bar.c b/bar.c index 7fea3c7..abdd1d7 100644 --- a/bar.c +++ b/bar.c @@ -104,6 +104,7 @@ static area_stack_t astack; static XftColor sel_fg; static XftDraw *xft_draw; +//char width lookuptable #define MAX_WIDTHS (1 << 16) static wchar_t xft_char[MAX_WIDTHS]; static char xft_width[MAX_WIDTHS]; @@ -488,7 +489,7 @@ parse (char *text) for (;;) { if (*p == '\0' || *p == '\n') - return; + break; if (*p == '%' && p++ && *p == '{' && (end = strchr(p++, '}'))) { while (p < end) { From 6be47235d47110f569155dae39dc05904a780f97 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Thu, 9 Oct 2014 22:01:23 +0200 Subject: [PATCH 08/42] Fixes multi-monitor drawing --- bar.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bar.c b/bar.c index abdd1d7..5365b0a 100644 --- a/bar.c +++ b/bar.c @@ -575,6 +575,10 @@ parse (char *text) p++; continue; } + XftDrawDestroy (xft_draw); + if (!(xft_draw = XftDrawCreate (dpy, cur_mon->pixmap, visual_ptr , colormap ))) { + fprintf(stderr, "Couldn't create xft drawable\n"); + } p++; pos_x = 0; From 2f7408e848155bcf81a674f63acfb10123323018 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Thu, 9 Oct 2014 22:22:28 +0200 Subject: [PATCH 09/42] Fixes problem with y offset and right/center alignment --- bar.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bar.c b/bar.c index 5365b0a..6bd780e 100644 --- a/bar.c +++ b/bar.c @@ -181,7 +181,6 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, wchar_t ch) } else { ch_width = cur_font->width_lut[ch - cur_font->char_min].character_width; } - switch (align) { case ALIGN_C: xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], mon->width / 2 - x / 2, 0, @@ -196,7 +195,7 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, wchar_t ch) } /* Draw the background first */ - fill_rect(mon->pixmap, gc[GC_CLEAR], x, by, ch_width, bh); + fill_rect(mon->pixmap, gc[GC_CLEAR], x, 0, ch_width, bh); int y = bh / 2 + cur_font->height / 2- cur_font->descent; if (cur_font->xft_ft) { From f87c249d213fe36be3fc487ce85352e9b1ae7f60 Mon Sep 17 00:00:00 2001 From: "Timothy M. Schaeffer" Date: Thu, 30 Oct 2014 21:58:19 -0400 Subject: [PATCH 10/42] Allow colors in the form #RRGGBB (ie w/o alpha). --- bar.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/bar.c b/bar.c index bec8a15..1b3b4cb 100644 --- a/bar.c +++ b/bar.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -168,19 +169,24 @@ parse_color (const char *str, char **end, const uint32_t def) unsigned int g = (tmp&0x0000ff00) >> 8; unsigned int b = (tmp&0x000000ff); - if (a) { - r = (r * 255) / a; - g = (g * 255) / a; - b = (b * 255) / a; + ptrdiff_t len = *end - str; + if (len == 8) { + if (a == 0) { + r = g = b = 0; + } else { + r = (r * 255) / a; + g = (g * 255) / a; + b = (b * 255) / a; - /* Clamp on overflow */ - if (r > 255) r = 255; - if (g > 255) g = 255; - if (b > 255) b = 255; - } else - r = g = b = 0; + /* Clamp on overflow */ + if (r > 255) r = 255; + if (g > 255) g = 255; + if (b > 255) b = 255; + } + } - return a << 24 | r << 16 | g << 8 | b; + uint32_t c = a << 24 | r << 16 | g << 8 | b; + return c; } /* Actual color name, resolve it */ From f07aa2db6f1945c13f2a74a7a14cc47c48af5a6c Mon Sep 17 00:00:00 2001 From: "Timothy M. Schaeffer" Date: Thu, 30 Oct 2014 21:59:51 -0400 Subject: [PATCH 11/42] On input, ignore % w/o a { after. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows eg “Battery 88%” in the input w/o messing up the colors. --- bar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bar.c b/bar.c index 1b3b4cb..d7e4c56 100644 --- a/bar.c +++ b/bar.c @@ -362,7 +362,8 @@ parse (char *text) if (*p == '\0' || *p == '\n') return; - if (*p == '%' && p++ && *p == '{' && (end = strchr(p++, '}'))) { + if (*p == '%' && *(p+1) == '{' && (end = strchr(p+2, '}'))) { + p += 2; while (p < end) { while (isspace(*p)) p++; From 7d17fa5040b0f1ea0a75bb315272b49a9356bc7d Mon Sep 17 00:00:00 2001 From: "Timothy M. Schaeffer" Date: Thu, 30 Oct 2014 22:00:24 -0400 Subject: [PATCH 12/42] Avoid compiler warning about ignore return from write. --- bar.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bar.c b/bar.c index d7e4c56..047b6bd 100644 --- a/bar.c +++ b/bar.c @@ -1141,8 +1141,9 @@ main (int argc, char **argv) area_t *area = area_get(press_ev->event, press_ev->event_x); /* Respond to the click */ if (area && area->button == press_ev->detail) { - write(STDOUT_FILENO, area->cmd, strlen(area->cmd)); - write(STDOUT_FILENO, "\n", 1); + ssize_t n; + n = write(STDOUT_FILENO, area->cmd, strlen(area->cmd)); + n = write(STDOUT_FILENO, "\n", 1); } } break; From bb5bc232569a7340948974bc2b973ac617415df8 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Wed, 5 Nov 2014 20:11:17 +0100 Subject: [PATCH 13/42] Fixes merging mistake --- bar.c | 1 - 1 file changed, 1 deletion(-) diff --git a/bar.c b/bar.c index 51a7863..7f7e87f 100644 --- a/bar.c +++ b/bar.c @@ -1339,7 +1339,6 @@ main (int argc, char **argv) n = write(STDOUT_FILENO, "\n", 1); } } - } break; } From 0aa0bbf6ff3b3b5d86bb96362ff535bc52bda7c6 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Wed, 5 Nov 2014 21:04:50 +0100 Subject: [PATCH 14/42] Fixes all non-Wconversion warnings --- bar.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/bar.c b/bar.c index 7f7e87f..44f9222 100644 --- a/bar.c +++ b/bar.c @@ -159,7 +159,7 @@ int xft_char_width (wchar_t ch, font_t *cur_font) int slot = xft_char_width_slot(ch); if (!xft_char[slot]) { XGlyphInfo gi; - FT_UInt glyph = XftCharIndex (dpy, cur_font->xft_ft, ch); + FT_UInt glyph = XftCharIndex (dpy, cur_font->xft_ft, (FcChar32) ch); XftFontLoadGlyphs (dpy, cur_font->xft_ft, FcFalse, &glyph, 1); XftGlyphExtents (dpy, cur_font->xft_ft, &glyph, 1, &gi); XftFontUnloadGlyphs (dpy, cur_font->xft_ft, &glyph, 1); @@ -200,7 +200,7 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, wchar_t ch) int y = bh / 2 + cur_font->height / 2- cur_font->descent; if (cur_font->xft_ft) { - XftDrawString32 (xft_draw, &sel_fg, cur_font->xft_ft, x,y, &ch, 1); + XftDrawString32 (xft_draw, &sel_fg, cur_font->xft_ft, x,y,(const FcChar32*) &ch, 1); } else { char c_ = ch > 127 ? ' ' : ch; /* xcb accepts string in UCS-2 BE, so swap */ @@ -220,7 +220,7 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, wchar_t ch) int utf8decode(char *s, wchar_t *u) { - unsigned char c; + char c; int i, n, rtn; rtn = 1; c = *s; @@ -341,13 +341,13 @@ set_attribute (const char modifier, const char attribute) switch (modifier) { case '+': - attrs |= (1< font->char_min && c < font->char_max && font->width_lut[c - font->char_min].character_width != 0)|| - (font->xft_ft && XftCharExists(dpy, font->xft_ft, c))) + (font->xft_ft && XftCharExists(dpy, font->xft_ft, (FcChar32) c))) return font; } return NULL; @@ -716,7 +716,7 @@ set_ewmh_atoms (void) xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_WINDOW_TYPE], XCB_ATOM_ATOM, 32, 1, &atom_list[NET_WM_WINDOW_TYPE_DOCK]); xcb_change_property(c, XCB_PROP_MODE_APPEND, mon->window, atom_list[NET_WM_STATE], XCB_ATOM_ATOM, 32, 2, &atom_list[NET_WM_STATE_STICKY]); xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_DESKTOP], XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []) { - -1 + 0u - 1u } ); xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_STRUT_PARTIAL], XCB_ATOM_CARDINAL, 32, 12, strut); xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_STRUT], XCB_ATOM_CARDINAL, 32, 4, strut); @@ -793,7 +793,7 @@ monitor_create_chain (xcb_rectangle_t *rects, const int num) int left = bx; /* Sort before use */ - qsort(rects, num, sizeof(xcb_rectangle_t), rect_sort_cb); + qsort(rects, (size_t) num, sizeof(xcb_rectangle_t), rect_sort_cb); for (i = 0; i < num; i++) { int h = rects[i].y + rects[i].height; @@ -930,6 +930,7 @@ get_randr_monitors (void) return; } + xcb_rectangle_t r[valid]; for (i = j = 0; i < num && j < valid; i++) @@ -1334,9 +1335,8 @@ main (int argc, char **argv) area_t *area = area_get(press_ev->event, press_ev->event_x); /* Respond to the click */ if (area && area->button == press_ev->detail) { - ssize_t n; - n = write(STDOUT_FILENO, area->cmd, strlen(area->cmd)); - n = write(STDOUT_FILENO, "\n", 1); + write(STDOUT_FILENO, area->cmd, strlen(area->cmd)); + write(STDOUT_FILENO, "\n", 1); } } break; From 86af874c0b011cc34e49ecf36bc3e0ca3223d5f5 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Mon, 10 Nov 2014 20:33:07 +0100 Subject: [PATCH 15/42] Fixes segfault on color params --- bar.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bar.c b/bar.c index 44f9222..a720f12 100644 --- a/bar.c +++ b/bar.c @@ -1252,6 +1252,7 @@ main (int argc, char **argv) ugc = fgc; + char* end_ptr = NULL; char ch; while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:")) != -1) { switch (ch) { @@ -1286,10 +1287,10 @@ main (int argc, char **argv) bu = strtoul(optarg, NULL, 10); break; case 'B': - dbgc = bgc = parse_color(optarg, NULL, scr->black_pixel); + dbgc = bgc = parse_color(optarg, &end_ptr, scr->black_pixel); break; case 'F': - dfgc = fgc = parse_color(optarg, NULL, scr->white_pixel); + dfgc = fgc = parse_color(optarg, &end_ptr, scr->white_pixel); break; } } From 4e43c3563b4527e612898ca52d8f749b1aef27b2 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Thu, 20 Nov 2014 22:00:11 +0100 Subject: [PATCH 16/42] Fixes crash related to last fix --- bar.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bar.c b/bar.c index 9607cf2..3625533 100644 --- a/bar.c +++ b/bar.c @@ -450,7 +450,7 @@ select_drawable_font (const wchar_t c) */ for (int i = 0; font_list[i] != NULL; i++) { font_t *font = font_list[i]; - if ((c >= font->char_min && c <= font->char_max && + if ((font->ptr && c >= font->char_min && c <= font->char_max && font->width_lut[c - font->char_min].character_width != 0)|| (font->xft_ft && XftCharExists(dpy, font->xft_ft, (FcChar32) c))) return font; @@ -639,6 +639,7 @@ font_load (const char *str) queryreq = xcb_query_font(c, font); font_info = xcb_query_font_reply(c, queryreq, NULL); + ret->xft_ft = NULL; ret->ptr = font; ret->descent = font_info->font_descent; ret->height = font_info->font_ascent + font_info->font_descent; @@ -646,6 +647,7 @@ font_load (const char *str) ret->char_min = font_info->min_byte1 << 8 | font_info->min_char_or_byte2; ret->width_lut = xcb_query_font_char_infos(font_info); } else if ((ret->xft_ft = XftFontOpenName (dpy, scr_nbr, str))) { + ret->ptr = 0; ret->ascent = ret->xft_ft->ascent; ret->descent = ret->xft_ft->descent; ret->height = ret->ascent + ret->descent; From 585d1633fb67f69eff7fb72d7cd29c58991da20f Mon Sep 17 00:00:00 2001 From: krypt-n Date: Tue, 25 Nov 2014 13:16:01 +0100 Subject: [PATCH 17/42] Fixes everything being red --- bar.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/bar.c b/bar.c index 3625533..3690afe 100644 --- a/bar.c +++ b/bar.c @@ -124,9 +124,9 @@ update_gc (void) }); XftColorFree(dpy, visual_ptr, colormap , &sel_fg); - char color[8] = "#ffffff"; - snprintf(color, sizeof(color), "#%06X", fgc); - + char color[] = "#ffffff"; + uint32_t nfgc = fgc & 0x00ffffff; + snprintf(color, sizeof(color), "#%06X", nfgc); if (!XftColorAllocName (dpy, visual_ptr, colormap, color, &sel_fg)) { fprintf(stderr, "Couldn't allocate xft font color '%s'\n", color); } @@ -1102,8 +1102,9 @@ init (void) xcb_map_window(c, mon->window); } - char color[8] = "#ffffff"; - snprintf(color, sizeof(color), "#%06X", fgc); + char color[] = "#ffffff"; + uint32_t nfgc = fgc & 0x00ffffff; + snprintf(color, sizeof(color), "#%06X", nfgc); if (!XftColorAllocName (dpy, visual_ptr, colormap, color, &sel_fg)) { fprintf(stderr, "Couldn't allocate xft font color '%s'\n", color); @@ -1296,7 +1297,6 @@ main (int argc, char **argv) break; } } - /* Copy the geometry values in place */ bw = geom_v[0]; bh = geom_v[1]; @@ -1307,7 +1307,6 @@ main (int argc, char **argv) init(); /* Get the fd to Xserver */ pollin[1].fd = xcb_get_file_descriptor(c); - for (;;) { bool redraw = false; From 3d64addd455d86888f79266d49ea29bf4b222c59 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Tue, 25 Nov 2014 13:17:48 +0100 Subject: [PATCH 18/42] Manually applies latest commit from master --- bar.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bar.c b/bar.c index 3690afe..e80dfd7 100644 --- a/bar.c +++ b/bar.c @@ -295,9 +295,9 @@ parse_color (const char *str, char **end, const uint32_t def) if (a == 0) { r = g = b = 0; } else { - r = (r * 255) / a; - g = (g * 255) / a; - b = (b * 255) / a; + r = (r * a) / 255; + g = (g * a) / 255; + b = (b * a) / 255; /* Clamp on overflow */ if (r > 255) r = 255; From ab6fa4c74a4b1353d2b0d36b0d9b7eaa119b4c85 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Tue, 24 Feb 2015 14:05:38 +0100 Subject: [PATCH 19/42] Ignore % if not followed by { --- bar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bar.c b/bar.c index 365a7d4..d7a510e 100644 --- a/bar.c +++ b/bar.c @@ -602,7 +602,8 @@ parse (char *text) if (*p == '\0' || *p == '\n') break; - if (*p == '%' && p++ && *p == '{' && (block_end = strchr(p++, '}'))) { + if (*p == '%' && *(p+1) == '{' && (block_end = strchr(p+2, '}'))) { + p += 2; while (p < block_end) { while (isspace(*p)) p++; From bcc4d97a1f203c1928298b97394b4d7d99db326f Mon Sep 17 00:00:00 2001 From: krypt-n Date: Tue, 24 Feb 2015 14:09:23 +0100 Subject: [PATCH 20/42] Removes old utf handling --- bar.c | 47 ++--------------------------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/bar.c b/bar.c index d7a510e..0462ec8 100644 --- a/bar.c +++ b/bar.c @@ -215,7 +215,7 @@ xcb_void_cookie_t xcb_poly_text_16_simple(xcb_connection_t * c, int -xft_char_width_slot (wchar_t ch) +xft_char_width_slot (uint16_t ch) { int slot = ch % MAX_WIDTHS; while (xft_char[slot] != 0 && xft_char[slot] != ch) @@ -225,7 +225,7 @@ xft_char_width_slot (wchar_t ch) return slot; } -int xft_char_width (wchar_t ch, font_t *cur_font) +int xft_char_width (uint16_t ch, font_t *cur_font) { int slot = xft_char_width_slot(ch); if (!xft_char[slot]) { @@ -297,46 +297,6 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) return ch_width; } -int -utf8decode(char *s, wchar_t *u) { - char c; - int i, n, rtn; - rtn = 1; - c = *s; - if(~c & 0x80) { /* 0xxxxxxx */ - *u = c; - return rtn; - } else if((c & 0xE0) == 0xC0) { /* 110xxxxx */ - *u = c & 0x1F; - n = 1; - } else if((c & 0xF0) == 0xE0) { /* 1110xxxx */ - *u = c & 0x0F; - n = 2; - } else if((c & 0xF8) == 0xF0) { /* 11110xxx */ - *u = c & 0x07; - n = 3; - } else { - goto invalid; - } - for(i = n, ++s; i > 0; --i, ++rtn, ++s) { - c = *s; - if((c & 0xC0) != 0x80) /* 10xxxxxx */ - goto invalid; - *u <<= 6; - *u |= c & 0x3F; - } - if((n == 1 && *u < 0x80) || - (n == 2 && *u < 0x800) || - (n == 3 && *u < 0x10000) || - (*u >= 0xD800 && *u <= 0xDFFF)) { - goto invalid; - } - return rtn; -invalid: - *u = 0xFFFD; - return rtn; -} - rgba_t parse_color (const char *str, char **end, const rgba_t def) { @@ -717,9 +677,6 @@ parse (char *text) p += 1; } -// wchar_t t; -// p += utf8decode(p, &t); - cur_font = select_drawable_font(ucs); if (!cur_font) continue; From ca190220b4167111b96a91e86f0b7603e0d6016b Mon Sep 17 00:00:00 2001 From: krypt-n Date: Wed, 4 Mar 2015 20:06:09 +0100 Subject: [PATCH 21/42] Adds background transparency --- bar.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/bar.c b/bar.c index 49326b1..8e8f53b 100644 --- a/bar.c +++ b/bar.c @@ -553,7 +553,7 @@ parse (char *text) fill_rect(m->pixmap, gc[GC_CLEAR], 0, 0, m->width, bh); /* Create xft drawable */ - if (!(xft_draw = XftDrawCreate (dpy, cur_mon->pixmap, visual_ptr , colormap ))) { + if (!(xft_draw = XftDrawCreate (dpy, cur_mon->pixmap, visual_ptr , colormap))) { fprintf(stderr, "Couldn't create xft drawable\n"); } @@ -822,8 +822,8 @@ monitor_new (int x, int y, int width, int height) ret->width = width; ret->next = ret->prev = NULL; ret->window = xcb_generate_id(c); - - xcb_create_window(c, XCB_COPY_FROM_PARENT, ret->window, scr->root, + int depth = (visual == scr->root_visual) ? XCB_COPY_FROM_PARENT : 32; + xcb_create_window(c, depth, ret->window, scr->root, ret->x, ret->y, width, bh, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visual, XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP, @@ -832,7 +832,7 @@ monitor_new (int x, int y, int width, int height) }); ret->pixmap = xcb_generate_id(c); - xcb_create_pixmap(c, scr->root_depth, ret->pixmap, ret->window, width, bh); + xcb_create_pixmap(c, depth, ret->pixmap, ret->window, width, bh); return ret; } @@ -917,7 +917,6 @@ monitor_create_chain (xcb_rectangle_t *rects, const int num) monitor_add(mon); width -= rects[i].width - left; - // No need to check for other monitors if (width <= 0) break; @@ -1056,8 +1055,21 @@ get_xinerama_monitors (void) xcb_visualid_t get_visual (void) { - visual_ptr = DefaultVisual(dpy, scr_nbr); - return scr->root_visual; //scr->root_visual; + + XVisualInfo xv; + xv.depth = 32; + int result = 0; + XVisualInfo* result_ptr = NULL; + result_ptr = XGetVisualInfo(dpy, VisualDepthMask, &xv, &result); + + if (result > 0) { + visual_ptr = result_ptr->visual; + return result_ptr->visualid; + } + + //Fallback + visual_ptr = DefaultVisual(dpy, scr_nbr); + return scr->root_visual; } // Parse an X-styled geometry string, we don't support signed offsets tho. @@ -1177,7 +1189,8 @@ xconn (void) /* Try to get a RGBA visual and build the colormap for that */ visual = get_visual(); - colormap = DefaultColormap(dpy, scr_nbr); + colormap = xcb_generate_id(c); + xcb_create_colormap(c, XCB_COLORMAP_ALLOC_NONE, colormap, scr->root, visual); } void From a683a72a5bf18469e690dbd7577038936285d2ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Luis=20Boya=20Garc=C3=ADa?= Date: Mon, 30 Mar 2015 15:31:52 +0200 Subject: [PATCH 22/42] Allow to add a vertical offset to the text --- lemonbar.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index f93a92c..99afea9 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -108,6 +108,7 @@ static bool dock = false; static bool topbar = true; static int bw = -1, bh = -1, bx = 0, by = 0; static int bu = 1; // Underline height +static int offset_y = 0; static rgba_t fgc, bgc, ugc; static rgba_t dfgc, dbgc; static area_stack_t astack; @@ -273,7 +274,7 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) /* Draw the background first */ fill_rect(mon->pixmap, gc[GC_CLEAR], x, 0, ch_width, bh); - int y = bh / 2 + cur_font->height / 2- cur_font->descent; + int y = bh / 2 + cur_font->height / 2- cur_font->descent + offset_y; if (cur_font->xft_ft) { XftDrawString16 (xft_draw, &sel_fg, cur_font->xft_ft, x,y, &ch, 1); } else { @@ -1369,11 +1370,11 @@ main (int argc, char **argv) ugc = fgc; - while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:")) != -1) { + while ((ch = getopt(argc, argv, "hg:bdf:a:pu:o:B:F:")) != -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 | -u | -o | -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" @@ -1381,6 +1382,7 @@ main (int argc, char **argv) "\t-f Bar font list, comma separated\n" "\t-p Don't close after the data ends\n" "\t-u Set the underline/overline height in pixels\n" + "\t-o Add a vertical offset to the text, it can be negative.\n" "\t-B Set background color in #AARRGGBB\n" "\t-F Set foreground color in #AARRGGBB\n", argv[0]); exit (EXIT_SUCCESS); @@ -1390,6 +1392,7 @@ main (int argc, char **argv) case 'd': dock = true; break; case 'f': parse_font_list(optarg); break; case 'u': bu = strtoul(optarg, NULL, 10); break; + case 'o': offset_y = strtol(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 4f60256cd10cd606f893cdc040eb1efc8f24f6e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Luis=20Boya=20Garc=C3=ADa?= Date: Mon, 30 Mar 2015 15:38:04 +0200 Subject: [PATCH 23/42] Allow to add a vertical offset to the text --- README.pod | 6 +++++- lemonbar.c | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/README.pod b/README.pod index afbed83..a1eb7f8 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 | -u I | -B I | -F I | -o I] =head1 DESCRIPTION @@ -52,6 +52,10 @@ Set the background color of the bar. I might be either in hex format (#aa Set the foreground color of the bar. Accepts the same color formats as B<-B>. +=item B<-o> I + +Add a vertical offset to the text. I must be a number and can be negative. I<-o -3> will push the text 3 pixels up. + =back =head1 FORMATTING diff --git a/lemonbar.c b/lemonbar.c index 99afea9..87858df 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -1374,7 +1374,7 @@ main (int argc, char **argv) switch (ch) { case 'h': printf ("lemonbar version %s\n", VERSION); - printf ("usage: %s [-h | -g | -b | -d | -f | -a | -p | -u | -o | -B | -F]\n" + printf ("usage: %s [-h | -g | -b | -d | -f | -a | -p | -u | -B | -F | -o]\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" @@ -1382,9 +1382,9 @@ main (int argc, char **argv) "\t-f Bar font list, comma separated\n" "\t-p Don't close after the data ends\n" "\t-u Set the underline/overline height in pixels\n" - "\t-o Add a vertical offset to the text, it can be negative.\n" "\t-B Set background color in #AARRGGBB\n" - "\t-F Set foreground color in #AARRGGBB\n", argv[0]); + "\t-F Set foreground color in #AARRGGBB\n" + "\t-o Add a vertical offset to the text, it can be negative\n", argv[0]); exit (EXIT_SUCCESS); case 'g': (void)parse_geometry_string(optarg, geom_v); break; case 'p': permanent = true; break; From 7708d363d7327f7da0641ee6e3d6b5b011109a88 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Mon, 30 Mar 2015 18:44:37 +0200 Subject: [PATCH 24/42] Updates binary name in gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 519ae3a..7ffbb48 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ config.h -bar +lemonbar *.o *.swp *~ From b95a7dfc88202e7fe7d224d299c52f44f78b732a Mon Sep 17 00:00:00 2001 From: krypt-n Date: Mon, 30 Mar 2015 18:53:53 +0200 Subject: [PATCH 25/42] Makes -o work with bitmap fonts --- lemonbar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemonbar.c b/lemonbar.c index 87858df..76e74c0 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -283,7 +283,7 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) // The coordinates here are those of the baseline xcb_poly_text_16_simple(c, mon->pixmap, gc[GC_DRAW], - x, bh / 2 + cur_font->height / 2 - cur_font->descent, + x, y, 1, &ch); } From c9f1425cac40546f54ae5694892de2e13f228cc4 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Tue, 2 Jun 2015 09:03:55 +0200 Subject: [PATCH 26/42] Adds per font -o --- lemonbar.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index 83d6978..8d6b72f 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -103,12 +103,15 @@ static monitor_t *monhead, *montail; static font_t *font_list[MAX_FONT_COUNT]; static int font_count = 0; static int font_index = -1; +static int offsets_y[MAX_FONT_COUNT]; +static int offset_y_count = 0; +static int offset_y_index = 0; + static uint32_t attrs = 0; static bool dock = false; static bool topbar = true; static int bw = -1, bh = -1, bx = 0, by = 0; static int bu = 1; // Underline height -static int offset_y = 0; static rgba_t fgc, bgc, ugc; static rgba_t dfgc, dbgc; static area_stack_t astack; @@ -277,7 +280,7 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) /* Draw the background first */ fill_rect(mon->pixmap, gc[GC_CLEAR], x, 0, ch_width, bh); - int y = bh / 2 + cur_font->height / 2- cur_font->descent + offset_y; + int y = bh / 2 + cur_font->height / 2- cur_font->descent + offsets_y[offset_y_index]; if (cur_font->xft_ft) { XftDrawString16 (xft_draw, &sel_fg, cur_font->xft_ft, x,y, &ch, 1); } else { @@ -534,14 +537,18 @@ font_t * select_drawable_font (const uint16_t c) { // If the user has specified a font to use, try that first. - if (font_index != -1 && font_has_glyph(font_list[font_index - 1], c)) + if (font_index != -1 && font_has_glyph(font_list[font_index - 1], c)) { + offset_y_index = font_index - 1; return font_list[font_index - 1]; + } // If the end is reached without finding an appropriate font, return NULL. // If the font can draw the character, return it. for (int i = 0; i < font_count; i++) { - if (font_has_glyph(font_list[i], c)) + if (font_has_glyph(font_list[i], c)) { + offset_y_index = i; return font_list[i]; + } } return NULL; } @@ -1359,7 +1366,14 @@ 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 'o': offset_y = strtol(optarg, NULL, 10); break; + case 'o': offsets_y[offset_y_count] = strtol(optarg, NULL, 10); + if (offset_y_count == 0) { + for (int i = 1; i < MAX_FONT_COUNT; ++i) { + offsets_y[i] = offsets_y[0]; + } + } + ++offset_y_count; + 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 088ddb6b51403bdae3483132db68ae0ff0043c6b Mon Sep 17 00:00:00 2001 From: krypt-n Date: Tue, 2 Jun 2015 09:38:31 +0200 Subject: [PATCH 27/42] Implements same check for offsets, moves offset adding to seperate function --- lemonbar.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index 620649e..66df6d8 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -765,6 +765,22 @@ font_load (const char *pattern) font_list[font_count++] = ret; } +void add_y_offset(int offset) { + if (offset_y_count >= MAX_FONT_COUNT) { + fprintf(stderr, "Max offset count reached. Could not set offset \"%d\"\n", offset); + return; + } + + offsets_y[offset_y_count] = strtol(optarg, NULL, 10); + if (offset_y_count == 0) { + for (int i = 1; i < MAX_FONT_COUNT; ++i) { + offsets_y[i] = offsets_y[0]; + } + } + ++offset_y_count; +} + + enum { NET_WM_WINDOW_TYPE, NET_WM_WINDOW_TYPE_DOCK, @@ -1371,14 +1387,7 @@ 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 'o': offsets_y[offset_y_count] = strtol(optarg, NULL, 10); - if (offset_y_count == 0) { - for (int i = 1; i < MAX_FONT_COUNT; ++i) { - offsets_y[i] = offsets_y[0]; - } - } - ++offset_y_count; - break; + case 'o': add_y_offset(strtol(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 4d164f3083b6269dc1e2afa9dca77994ae909ad9 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Sun, 15 Nov 2015 22:31:05 +0100 Subject: [PATCH 28/42] Remove return NULL from function returning void gcc didnt catch that. clang did --- lemonbar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemonbar.c b/lemonbar.c index 764cc51..08883e5 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -772,7 +772,7 @@ font_load (const char *pattern) ret->height = ret->ascent + ret->descent; } else { fprintf(stderr, "Could not load font %s\n", pattern); - return NULL; + return; } font_list[font_count++] = ret; From fd8a33c8a4cac03c85aed66578c1a2eea3153d78 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Sun, 15 Nov 2015 22:41:53 +0100 Subject: [PATCH 29/42] Fix memoryleak on failure to load font --- lemonbar.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lemonbar.c b/lemonbar.c index 08883e5..d6cf9cf 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -772,6 +772,7 @@ font_load (const char *pattern) ret->height = ret->ascent + ret->descent; } else { fprintf(stderr, "Could not load font %s\n", pattern); + free(ret); return; } From 578faf271e12d24a7dfdd49bcce1153147a7624a Mon Sep 17 00:00:00 2001 From: krypt-n Date: Fri, 15 Jan 2016 12:44:15 +0100 Subject: [PATCH 30/42] Add mention of XFT support in help message --- lemonbar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemonbar.c b/lemonbar.c index ea494cc..351eb13 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -1395,7 +1395,7 @@ main (int argc, char **argv) while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:n:o:")) != -1) { switch (ch) { case 'h': - printf ("lemonbar version %s\n", VERSION); + printf ("lemonbar version %s patched with XFT support\n", VERSION); 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" From 3b3e3d5a919bb05c2a9e548b3774a4f8c1716ea2 Mon Sep 17 00:00:00 2001 From: krypt-n Date: Fri, 15 Jan 2016 12:47:21 +0100 Subject: [PATCH 31/42] Add mention of XFT support in README and Manpage --- README.pod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.pod b/README.pod index 7aa0bf1..3145a02 100644 --- a/README.pod +++ b/README.pod @@ -35,7 +35,7 @@ Force docking without asking the window manager. This is needed if the window ma =item B<-f> I 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). +changing the MAX_FONT_COUNT parameter in the source code). This version supports fontconfig font specifiers and anti-aliased fonts. =item B<-a> I From 892e43a3bc25b78af44b366996532da7f44abc20 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sat, 1 Mar 2014 13:31:27 -0500 Subject: [PATCH 32/42] Add pixel offset Add a formatting command to offset the text position by a pixel amount. --- README.pod | 4 ++++ lemonbar.c | 54 ++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/README.pod b/README.pod index 509cfd6..9fbba94 100644 --- a/README.pod +++ b/README.pod @@ -89,6 +89,10 @@ Aligns the following text to the center of the screen. Aligns the following text to the right side of the screen. +=item BI + +Offset the current position by I pixels in the alignment direction. + =item BI Set the text background color. The parameter I can be I<-> or a color in one of the formats mentioned before. The special value I<-> resets the color to the default one. diff --git a/lemonbar.c b/lemonbar.c index 2198731..08e4704 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -186,14 +186,8 @@ xcb_void_cookie_t xcb_poly_text_16_simple(xcb_connection_t * c, } int -draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) +shift (monitor_t *mon, int x, int align, int ch_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: xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], @@ -213,6 +207,34 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) // Draw the background first fill_rect(mon->pixmap, gc[GC_CLEAR], x, 0, ch_width, bh); + return x; +} + +void +draw_lines (monitor_t *mon, int x, int w) +{ + /* We can render both at the same time */ + if (attrs & ATTR_OVERL) + fill_rect(mon->pixmap, gc[GC_ATTR], x, 0, w, bu); + if (attrs & ATTR_UNDERL) + fill_rect(mon->pixmap, gc[GC_ATTR], x, bh - bu, w, bu); +} + +void +draw_shift (monitor_t *mon, int x, int align, int w) +{ + x = shift(mon, x, align, w); + draw_lines(mon, x, w); +} + +int +draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) +{ + int ch_width = (cur_font->width_lut) ? + cur_font->width_lut[ch - cur_font->char_min].character_width: + cur_font->width; + + x = shift(mon, x, align, ch_width); // xcb accepts string in UCS-2 BE, so swap ch = (ch >> 8) | (ch << 8); @@ -222,11 +244,7 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) x, bh / 2 + cur_font->height / 2 - cur_font->descent, 1, &ch); - // We can render both at the same time - if (attrs & ATTR_OVERL) - fill_rect(mon->pixmap, gc[GC_ATTR], x, 0, ch_width, bu); - if (attrs & ATTR_UNDERL) - fill_rect(mon->pixmap, gc[GC_ATTR], x, bh - bu, ch_width, bu); + draw_lines(mon, x, ch_width); return ch_width; } @@ -490,6 +508,7 @@ parse (char *text) if (p[0] == '%' && p[1] == '{' && (block_end = strchr(p++, '}'))) { p++; while (p < block_end) { + int w; while (isspace(*p)) p++; @@ -542,6 +561,17 @@ parse (char *text) p++; pos_x = 0; break; + case 'O': + errno = 0; + w = (int) strtoul(p, &p, 10); + if (errno) + continue; + + draw_shift(cur_mon, pos_x, align, w); + + pos_x += w; + area_shift(cur_mon->window, align, w); + break; case 'T': if (*p == '-') { //Reset to automatic font selection From b64dd42f309dcb2ba1a07bcd06df74573c5239ba Mon Sep 17 00:00:00 2001 From: Bernd Busse Date: Wed, 8 Jun 2016 11:41:58 +0200 Subject: [PATCH 33/42] Add WM_CLASS atom --- lemonbar.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lemonbar.c b/lemonbar.c index f1b7886..8044b41 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -765,6 +765,7 @@ set_ewmh_atoms (void) xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_STRUT_PARTIAL], XCB_ATOM_CARDINAL, 32, 12, strut); xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_STRUT], XCB_ATOM_CARDINAL, 32, 4, strut); xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 3, "bar"); + xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, 3, "bar"); } } From d7520a659e58991b9c21b14387afff66121be98e Mon Sep 17 00:00:00 2001 From: Bernd Busse Date: Wed, 8 Jun 2016 23:02:10 +0200 Subject: [PATCH 34/42] Change WM_CLASS atom to "instance", "class" Set WM_CLASS class to "bar" and WM_CLASS instance to executable name (defaults to "lemonbar"). --- lemonbar.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index 8044b41..2c2bd9b 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -765,7 +765,7 @@ set_ewmh_atoms (void) xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_STRUT_PARTIAL], XCB_ATOM_CARDINAL, 32, 12, strut); xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_STRUT], XCB_ATOM_CARDINAL, 32, 4, strut); xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 3, "bar"); - xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, 3, "bar"); + xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, 12, "lemonbar\0bar"); } } @@ -1115,7 +1115,7 @@ xconn (void) } void -init (char *wm_name) +init (char *wm_name, char *wm_instance) { // Try to load a default font if (!font_count) @@ -1210,6 +1210,24 @@ init (char *wm_name) // Set the WM_NAME atom to the user specified value if (wm_name) xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8 ,strlen(wm_name), wm_name); + + // set the WM_CLASS atom instance to the executable name + if (wm_instance) { + char *wm_class; + int wm_class_offset, wm_class_len; + + // WM_CLASS is nullbyte seperated: wm_instance + "\0bar\0" + wm_class_offset = strlen(wm_instance) + 1; + wm_class_len = wm_class_offset + 4; + + wm_class = calloc(1, wm_class_len + 1); + strcpy(wm_class, wm_instance); + strcpy(wm_class+wm_class_offset, "bar"); + + xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, wm_class_len, wm_class); + + free(wm_class); + } } xcb_flush(c); @@ -1246,6 +1264,21 @@ cleanup (void) xcb_disconnect(c); } +char* +strip_path(char *path) +{ + char *slash; + + if (path == NULL || *path == '\0') + return strdup("lemonbar"); + + slash = strrchr(path, '/'); + if (slash != NULL) + return strndup(slash + 1, 31); + + return strndup(path, 31); +} + void sighandle (int signal) { @@ -1268,6 +1301,7 @@ main (int argc, char **argv) int geom_v[4] = { -1, -1, 0, 0 }; int ch, areas; char *wm_name; + char *instance_name; // Install the parachute! atexit(cleanup); @@ -1283,6 +1317,8 @@ main (int argc, char **argv) areas = 10; wm_name = NULL; + instance_name = strip_path(argv[0]); + // Connect to the Xserver and initialize scr xconn(); @@ -1339,9 +1375,11 @@ main (int argc, char **argv) by = geom_v[3]; // Do the heavy lifting - init(wm_name); + init(wm_name, instance_name); // The string is strdup'd when the command line arguments are parsed free(wm_name); + // The string is strdup'd when stripping argv[0] + free(instance_name); // Get the fd to Xserver pollin[1].fd = xcb_get_file_descriptor(c); From 49b2cc55aed73e0b8acaebfc627b93d065cdbb11 Mon Sep 17 00:00:00 2001 From: Bernd Busse Date: Sun, 16 Oct 2016 21:39:17 +0200 Subject: [PATCH 35/42] Changed WM_CLASS class from "bar" to "Bar" Follow convention of capitalized WM_CLASS class name. --- lemonbar.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index 2c2bd9b..4c94139 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -765,7 +765,7 @@ set_ewmh_atoms (void) xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_STRUT_PARTIAL], XCB_ATOM_CARDINAL, 32, 12, strut); xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_STRUT], XCB_ATOM_CARDINAL, 32, 4, strut); xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 3, "bar"); - xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, 12, "lemonbar\0bar"); + xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, 12, "lemonbar\0Bar"); } } @@ -1216,13 +1216,13 @@ init (char *wm_name, char *wm_instance) char *wm_class; int wm_class_offset, wm_class_len; - // WM_CLASS is nullbyte seperated: wm_instance + "\0bar\0" + // WM_CLASS is nullbyte seperated: wm_instance + "\0Bar\0" wm_class_offset = strlen(wm_instance) + 1; wm_class_len = wm_class_offset + 4; wm_class = calloc(1, wm_class_len + 1); strcpy(wm_class, wm_instance); - strcpy(wm_class+wm_class_offset, "bar"); + strcpy(wm_class+wm_class_offset, "Bar"); xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, wm_class_len, wm_class); From 0ff78b6c421f58ced46e22754b7c53aea5cfed61 Mon Sep 17 00:00:00 2001 From: Bastien Dejean Date: Wed, 16 Nov 2016 10:14:27 +0100 Subject: [PATCH 36/42] Fix {top,bottom}_end_x strut value The maximum x coordinate of a pixel inside the rectangle (x, y, w, h) is x+w-1. The specs (https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html#idm140130317564416) provides an example that corroborates the fact that the range is inclusive: bottom_end_x is 2303. This value can be interpreted as 1280+1024-1. --- lemonbar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index 9286dd7..0e8c41b 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -879,11 +879,11 @@ set_ewmh_atoms (void) if (topbar) { strut[2] = bh; strut[8] = mon->x; - strut[9] = mon->x + mon->width; + strut[9] = mon->x + mon->width - 1; } else { strut[3] = bh; strut[10] = mon->x; - strut[11] = mon->x + mon->width; + strut[11] = mon->x + mon->width - 1; } xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_WINDOW_TYPE], XCB_ATOM_ATOM, 32, 1, &atom_list[NET_WM_WINDOW_TYPE_DOCK]); From 89010c508da3a6cc7f5ecec30eaf319c2d90cb39 Mon Sep 17 00:00:00 2001 From: Thomas Adam Date: Sun, 26 Jul 2015 16:04:03 +0100 Subject: [PATCH 37/42] %{S}: don't clear other outputs When asking lemonbar to display text to a given ouput with %{S}, don't clear all outputs first in order to render the text. The output will persist on the other outputs until other text is rendered there. --- lemonbar.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lemonbar.c b/lemonbar.c index 0e8c41b..1914fd8 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -666,6 +666,7 @@ parse (char *text) p++; pos_x = 0; + fill_rect(cur_mon->pixmap, gc[GC_CLEAR], 0, 0, cur_mon->width, bh); break; case 'O': errno = 0; From 170a7261fa8c61d1becf0ea31d491fc10303f6f7 Mon Sep 17 00:00:00 2001 From: jvvv Date: Sun, 2 Apr 2017 14:32:16 +0100 Subject: [PATCH 38/42] Add support for named rand outputs --- README.pod | 9 +++ lemonbar.c | 173 +++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 138 insertions(+), 44 deletions(-) diff --git a/README.pod b/README.pod index 170fd67..2500456 100644 --- a/README.pod +++ b/README.pod @@ -24,6 +24,10 @@ Display the help and exit. Set the window geometry. If a parameter is omitted it's filled with the default value. If the I parameter is specified along with the B<-b> switch then the position is relative to the bottom of the screen. +=item B<-o> I + +Set next output to I. May be used multiple times; order is significant. If any B<-o> options are given, only B<-o> specified monitors will be used. Invalid output names are silently ignored. (only supported on randr configurations at this time) + =item B<-b> Dock the bar at the bottom of the screen. @@ -143,6 +147,11 @@ First/last monitor. Nth monitor. +=item IB + +Named monitor. +Eg. I<%{SnHDMI-0} This text will show up on the HDMI-0 output> + =back =back diff --git a/lemonbar.c b/lemonbar.c index 1914fd8..4dbe531 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -41,7 +41,8 @@ typedef struct font_t { } font_t; typedef struct monitor_t { - int x, y, width; + char *name; + int x, y, width, height; xcb_window_t window; xcb_pixmap_t pixmap; struct monitor_t *prev, *next; @@ -127,6 +128,8 @@ static XftDraw *xft_draw; #define MAX_WIDTHS (1 << 16) static wchar_t xft_char[MAX_WIDTHS]; static char xft_width[MAX_WIDTHS]; +static int num_outputs = 0; +static char **output_names = NULL; void update_gc (void) @@ -652,6 +655,15 @@ parse (char *text) { cur_mon = monhead; } else if (*p == 'l') { cur_mon = montail ? montail : monhead; } + else if (*p == 'n') + { cur_mon = monhead; + while (cur_mon->next) { + if (cur_mon->name && !strncmp(cur_mon->name, p+1, (block_end-p)-1)) { + break; + } + cur_mon = cur_mon->next; + } + } else if (isdigit(*p)) { cur_mon = monhead; for (int i = 0; i != *p-'0' && cur_mon->next; i++) @@ -900,7 +912,7 @@ set_ewmh_atoms (void) } monitor_t * -monitor_new (int x, int y, int width, int height) +monitor_new (int x, int y, int width, int height, char *name) { monitor_t *ret; @@ -910,6 +922,7 @@ monitor_new (int x, int y, int width, int height) exit(EXIT_FAILURE); } + ret->name = name; ret->x = x; ret->y = (topbar ? by : height - bh - by) + y; ret->width = width; @@ -947,17 +960,17 @@ monitor_add (monitor_t *mon) } int -rect_sort_cb (const void *p1, const void *p2) +mon_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; + const monitor_t *m1 = (monitor_t *)p1; + const monitor_t *m2 = (monitor_t *)p2; - if (r1->x < r2->x || r1->y + r1->height <= r2->y) + if (m1->x < m2->x || m1->y + m1->height <= m2->y) { return -1; } - if (r1->x > r2->x || r1->y + r1->height > r2->y) + if (m1->x > m2->x || m1->y + m1->height > m2->y) { return 1; } @@ -966,19 +979,20 @@ rect_sort_cb (const void *p1, const void *p2) } void -monitor_create_chain (xcb_rectangle_t *rects, const int num) +monitor_create_chain (monitor_t *mons, const int num) { int i; int width = 0, height = 0; int left = bx; // Sort before use - qsort(rects, num, sizeof(xcb_rectangle_t), rect_sort_cb); + if (!num_outputs) + qsort(mons, num, sizeof(monitor_t), mon_sort_cb); for (i = 0; i < num; i++) { - int h = rects[i].y + rects[i].height; + int h = mons[i].y + mons[i].height; // Accumulated width of all monitors - width += rects[i].width; + width += mons[i].width; // Get height of screen from y_offset + height of lowest monitor if (h >= height) height = h; @@ -1000,27 +1014,29 @@ monitor_create_chain (xcb_rectangle_t *rects, const int num) // Left is a positive number or zero therefore monitors with zero width are excluded width = bw; for (i = 0; i < num; i++) { - if (rects[i].y + rects[i].height < by) + if (mons[i].y + mons[i].height < by) continue; - if (rects[i].width > left) { + if (mons[i].width > left) { monitor_t *mon = monitor_new( - rects[i].x + left, - rects[i].y, - min(width, rects[i].width - left), - rects[i].height); + mons[i].x + left, + mons[i].y, + min(width, mons[i].width - left), + mons[i].height, + mons[i].name); if (!mon) break; monitor_add(mon); - width -= rects[i].width - left; + width -= mons[i].width - left; + // No need to check for other monitors if (width <= 0) break; } - left -= rects[i].width; + left -= mons[i].width; if (left < 0) left = 0; @@ -1052,7 +1068,7 @@ get_randr_monitors (void) return; } - xcb_rectangle_t rects[num]; + monitor_t mons[num]; // Get all outputs for (i = 0; i < num; i++) { @@ -1064,24 +1080,65 @@ get_randr_monitors (void) // Output disconnected or not attached to any CRTC ? if (!oi_reply || oi_reply->crtc == XCB_NONE || oi_reply->connection != XCB_RANDR_CONNECTION_CONNECTED) { free(oi_reply); - rects[i].width = 0; + mons[i].width = 0; continue; } ci_reply = xcb_randr_get_crtc_info_reply(c, xcb_randr_get_crtc_info(c, oi_reply->crtc, XCB_CURRENT_TIME), NULL); - free(oi_reply); - if (!ci_reply) { fprintf(stderr, "Failed to get RandR ctrc info\n"); free(rres_reply); return; } - // There's no need to handle rotated screens here (see #69) - rects[i] = (xcb_rectangle_t){ ci_reply->x, ci_reply->y, ci_reply->width, ci_reply->height }; + if (num_outputs) { + for (j = 0; j < num_outputs; j++) { + int namelen; + uint8_t *str; + char *name; + fprintf(stderr, "output_names: %s\n", output_names[j]); + + // if this output name has been allocated, skip it + if (!output_names[j]) + continue; + + namelen = xcb_randr_get_output_info_name_length(oi_reply); + name = malloc(namelen+1); + + if (!name) { + fprintf(stderr, "Failed to allocate randr output name\n"); + exit(EXIT_FAILURE); + } + + str = xcb_randr_get_output_info_name(oi_reply); + memcpy(name, str, namelen); + name[namelen] = '\0'; + + if (!memcmp(output_names[j], name, namelen)) { + mons[j] = (monitor_t){ name, ci_reply->x, ci_reply->y, ci_reply->width, ci_reply->height, 0, 0, NULL, NULL }; + output_names[j] = NULL; + break; + } + else + free(name); + } + // if this output is not in the list, skip it + if (j == num_outputs) { + mons[i].width = 0; + free(oi_reply); + continue; + } + } + else { + // There's no need to handle rotated screens here (see #69) + mons[i] = (monitor_t){ NULL, ci_reply->x, ci_reply->y, ci_reply->width, ci_reply->height, 0, 0, NULL, NULL }; + } + + + free(oi_reply); free(ci_reply); valid++; @@ -1089,18 +1146,21 @@ get_randr_monitors (void) free(rres_reply); + if (num_outputs) + free(output_names); + // Check for clones and inactive outputs for (i = 0; i < num; i++) { - if (rects[i].width == 0) + if (mons[i].width == 0) continue; for (j = 0; j < num; j++) { // Does I contain J ? - if (i != j && rects[j].width) { - if (rects[j].x >= rects[i].x && rects[j].x + rects[j].width <= rects[i].x + rects[i].width && - rects[j].y >= rects[i].y && rects[j].y + rects[j].height <= rects[i].y + rects[i].height) { - rects[j].width = 0; + if (i != j && mons[j].width && !mons[j].name) { + if (mons[j].x >= mons[i].x && mons[j].x + mons[j].width <= mons[i].x + mons[i].width && + mons[j].y >= mons[i].y && mons[j].y + mons[j].height <= mons[i].y + mons[i].height) { + mons[j].width = 0; valid--; } } @@ -1112,13 +1172,13 @@ get_randr_monitors (void) return; } - xcb_rectangle_t r[valid]; + monitor_t m[valid]; for (i = j = 0; i < num && j < valid; i++) - if (rects[i].width != 0) - r[j++] = rects[i]; + if (mons[i].width != 0) + m[j++] = mons[i]; - monitor_create_chain(r, valid); + monitor_create_chain(m, valid); } #ifdef WITH_XINERAMA @@ -1129,26 +1189,32 @@ get_xinerama_monitors (void) xcb_xinerama_screen_info_iterator_t iter; int screens; + if (num_outputs) { + fprintf(stderr, "Using output names with Xinerama is not yet supported\n"); + return; + } + xqs_reply = xcb_xinerama_query_screens_reply(c, xcb_xinerama_query_screens_unchecked(c), NULL); iter = xcb_xinerama_query_screens_screen_info_iterator(xqs_reply); screens = iter.rem; - xcb_rectangle_t rects[screens]; + monitor_t mons[screens]; // Fetch all the screens first for (int i = 0; iter.rem; i++) { - rects[i].x = iter.data->x_org; - rects[i].y = iter.data->y_org; - rects[i].width = iter.data->width; - rects[i].height = iter.data->height; + mons[i].name = NULL; + mons[i].x = iter.data->x_org; + mons[i].y = iter.data->y_org; + mons[i].width = iter.data->width; + mons[i].height = iter.data->height; xcb_xinerama_screen_info_next(&iter); } free(xqs_reply); - monitor_create_chain(rects, screens); + monitor_create_chain(mons, screens); } #endif @@ -1223,6 +1289,20 @@ parse_geometry_string (char *str, int *tmp) return true; } +void +parse_output_string(char *str) +{ + if (!str || !*str) + return; + num_outputs++; + output_names = realloc(output_names, num_outputs * sizeof(char *)); + if (!output_names) { + fprintf(stderr, "failed to allocate output name\n"); + exit(EXIT_FAILURE); + } + output_names[num_outputs-1] = str; +} + void xconn (void) { @@ -1301,6 +1381,10 @@ init (char *wm_name, char *wm_instance) #endif if (!monhead) { + if (num_outputs) { + fprintf(stderr, "Failed to find any specified outputs\n"); + exit(EXIT_FAILURE); + } // If I fits I sits if (bw < 0) bw = scr->width_in_pixels - bx; @@ -1316,7 +1400,7 @@ init (char *wm_name, char *wm_instance) } // If no RandR outputs or Xinerama screens, fall back to using whole screen - monhead = monitor_new(0, 0, bw, scr->height_in_pixels); + monhead = monitor_new(0, 0, bw, scr->height_in_pixels, NULL); } if (!monhead) @@ -1472,11 +1556,11 @@ main (int argc, char **argv) // Connect to the Xserver and initialize scr xconn(); - while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:U:n:o:")) != -1) { + while ((ch = getopt(argc, argv, "hg:o:bdf:a:pu:B:F:U:n:")) != -1) { switch (ch) { case 'h': - printf ("lemonbar version %s patched with XFT support\n", VERSION); - printf ("usage: %s [-h | -g | -b | -d | -f | -a | -p | -n | -u | -B | -F]\n" + printf ("lemonbar version %s\n", VERSION); + printf ("usage: %s [-h | -o | -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" @@ -1491,6 +1575,7 @@ main (int argc, char **argv) "\t-o Add a vertical offset to the text, it can be negative\n", argv[0]); exit (EXIT_SUCCESS); case 'g': (void)parse_geometry_string(optarg, geom_v); break; + case 'o': (void)parse_output_string(optarg); break; case 'p': permanent = true; break; case 'n': wm_name = strdup(optarg); break; case 'b': topbar = false; break; From 3f20ba0541015b0023fef978631537509a131b3a Mon Sep 17 00:00:00 2001 From: Thomas Adam Date: Sun, 2 Apr 2017 14:48:35 +0100 Subject: [PATCH 39/42] %{Sn<..>}: Don't rely on "-o" for output names Rather than up-front declare which outputs lemonbar can use, instead infer this based on scanning the outputs from RandR. --- lemonbar.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index 4dbe531..88ce080 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -131,6 +131,8 @@ static char xft_width[MAX_WIDTHS]; static int num_outputs = 0; static char **output_names = NULL; +static void parse_output_string(char *); + void update_gc (void) { @@ -1074,6 +1076,9 @@ get_randr_monitors (void) for (i = 0; i < num; i++) { xcb_randr_get_output_info_reply_t *oi_reply; xcb_randr_get_crtc_info_reply_t *ci_reply; + int namelen; + uint8_t *str; + char *name; oi_reply = xcb_randr_get_output_info_reply(c, xcb_randr_get_output_info(c, outputs[i], XCB_CURRENT_TIME), NULL); @@ -1093,30 +1098,29 @@ get_randr_monitors (void) return; } + namelen = xcb_randr_get_output_info_name_length(oi_reply); + name = malloc(namelen+1); + + if (!name) { + fprintf(stderr, "Failed to allocate randr output name\n"); + exit(EXIT_FAILURE); + } + + str = xcb_randr_get_output_info_name(oi_reply); + memcpy(name, str, namelen); + name[namelen] = '\0'; + + if (!name || name[0] == '\0') + continue; + + parse_output_string(name); + if (num_outputs) { for (j = 0; j < num_outputs; j++) { - int namelen; - uint8_t *str; - char *name; - - fprintf(stderr, "output_names: %s\n", output_names[j]); - // if this output name has been allocated, skip it if (!output_names[j]) continue; - namelen = xcb_randr_get_output_info_name_length(oi_reply); - name = malloc(namelen+1); - - if (!name) { - fprintf(stderr, "Failed to allocate randr output name\n"); - exit(EXIT_FAILURE); - } - - str = xcb_randr_get_output_info_name(oi_reply); - memcpy(name, str, namelen); - name[namelen] = '\0'; - if (!memcmp(output_names[j], name, namelen)) { mons[j] = (monitor_t){ name, ci_reply->x, ci_reply->y, ci_reply->width, ci_reply->height, 0, 0, NULL, NULL }; output_names[j] = NULL; From bd6cb2edc175312aa74717db07bd2f2f17a58625 Mon Sep 17 00:00:00 2001 From: Thomas Adam Date: Sat, 13 May 2017 19:41:41 +0100 Subject: [PATCH 40/42] Remove -o option --- lemonbar.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lemonbar.c b/lemonbar.c index 88ce080..dca2297 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -1579,7 +1579,6 @@ main (int argc, char **argv) "\t-o Add a vertical offset to the text, it can be negative\n", argv[0]); exit (EXIT_SUCCESS); case 'g': (void)parse_geometry_string(optarg, geom_v); break; - case 'o': (void)parse_output_string(optarg); break; case 'p': permanent = true; break; case 'n': wm_name = strdup(optarg); break; case 'b': topbar = false; break; From 7ba502869797c476bae7c7638d6ab9f30527a7c2 Mon Sep 17 00:00:00 2001 From: Thomas Adam Date: Thu, 8 Jun 2017 11:54:30 +0100 Subject: [PATCH 41/42] Don't clear output on all screens When parsing information into lemonbar, assume per-screen means that -- don't clear all the screens at once. Let individual requests to be drawn on screen to be for that specified monitor. --- lemonbar.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index dca2297..6d4cd6a 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -600,9 +600,6 @@ parse (char *text) // 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); - /* Create xft drawable */ if (!(xft_draw = XftDrawCreate (dpy, cur_mon->pixmap, visual_ptr , colormap))) { fprintf(stderr, "Couldn't create xft drawable\n"); From 482a383afa237a22351a908fa0fbb1e54432a015 Mon Sep 17 00:00:00 2001 From: Thomas Adam Date: Thu, 8 Jun 2017 11:55:29 +0100 Subject: [PATCH 42/42] Don't ignore valid monitors Rather than assume monitors are valid based on their width, just let the usual RandR detection handle that. This addresses the problem of lemonbar "missing" certain monitors. There's still more work to do here, but this is a stop-gap measure for now. --- lemonbar.c | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index 6d4cd6a..7478a47 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -1126,12 +1126,6 @@ get_randr_monitors (void) else free(name); } - // if this output is not in the list, skip it - if (j == num_outputs) { - mons[i].width = 0; - free(oi_reply); - continue; - } } else { // There's no need to handle rotated screens here (see #69) @@ -1150,36 +1144,12 @@ get_randr_monitors (void) if (num_outputs) free(output_names); - // Check for clones and inactive outputs - for (i = 0; i < num; i++) { - if (mons[i].width == 0) - continue; - - for (j = 0; j < num; j++) { - // Does I contain J ? - - if (i != j && mons[j].width && !mons[j].name) { - if (mons[j].x >= mons[i].x && mons[j].x + mons[j].width <= mons[i].x + mons[i].width && - mons[j].y >= mons[i].y && mons[j].y + mons[j].height <= mons[i].y + mons[i].height) { - mons[j].width = 0; - valid--; - } - } - } - } - - if (valid < 1) { + if (valid == 0) { fprintf(stderr, "No usable RandR output found\n"); return; } - monitor_t m[valid]; - - for (i = j = 0; i < num && j < valid; i++) - if (mons[i].width != 0) - m[j++] = mons[i]; - - monitor_create_chain(m, valid); + monitor_create_chain(mons, valid); } #ifdef WITH_XINERAMA