On Fri, Nov 23 2018, Joel Carnat <j...@carnat.net> wrote: > Hi, Hi,
> On a journey to find a statusbar for cwm, I found that x11/lemonbar > didn't support XFT. I used sources from https://github.com/krypt-n/bar > to compile on OpenBSD 6.4/amd64 and it seems to work. So far, it > compiles, lemonbar starts and renders text using xft:Sans:size=11. > > Find the relevant patches attached. Make sure you at least Cc the port maintainer. You should probably have discussed this diff with Ingo first, it looks a bit intrusive. > Regards, > Jo > > --- Makefile.orig Fri Nov 23 00:26:08 2018 > +++ Makefile Fri Nov 23 00:35:00 2018 > @@ -1,4 +1,4 @@ > # This snippet has been shmelessly stol^Hborrowed from thestinger's repose > Makefile > -VERSION = 1.2 > +VERSION = 1.3 > GIT_DESC=$(shell test -d .git && git describe --always 2>/dev/null) > > @@ -8,6 +8,8 @@ > > CC ?= gcc > -CFLAGS += -Wall -std=c99 -DVERSION="\"$(VERSION)\"" > -LDFLAGS += -lxcb -lxcb-xinerama -lxcb-randr > +CFLAGS += -Wall -std=c99 -DVERSION="\"$(VERSION)\"" \ > + -I/usr/X11R6/include/freetype2 > +LDFLAGS += -lxcb -lxcb-xinerama -lxcb-randr \ > + -lX11 -lX11-xcb -lXft -lfreetype -lz > -lfontconfig > CFDEBUG = -g3 -pedantic -Wall -Wunused-parameter -Wlong-long \ > -Wsign-conversion -Wconversion -Wimplicit-function-declaration > > --- lemonbar.c.orig Mon Nov 20 11:47:43 2017 > +++ lemonbar.c Fri Nov 23 00:30:26 2018 > @@ -2,4 +2,5 @@ > #define _POSIX_C_SOURCE 200809L > #include <stdbool.h> > +#include <stddef.h> > #include <stdio.h> > #include <stdlib.h> > @@ -8,4 +9,5 @@ > #include <signal.h> > #include <poll.h> > +#include <fcntl.h> > #include <getopt.h> > #include <unistd.h> > @@ -18,6 +20,9 @@ > #include <xcb/randr.h> > > -// Here be dragons > +#include <X11/Xft/Xft.h> > +#include <X11/Xlib-xcb.h> > > +// Here bet dragons > + > #define max(a,b) ((a) > (b) ? (a) : (b)) > #define min(a,b) ((a) < (b) ? (a) : (b)) > @@ -26,8 +31,13 @@ > typedef struct font_t { > xcb_font_t ptr; > + xcb_charinfo_t *width_lut; > + > + XftFont *xft_ft; > + > + int ascent; > + > int descent, height, width; > uint16_t char_max; > uint16_t char_min; > - xcb_charinfo_t *width_lut; > } font_t; > > @@ -69,9 +79,8 @@ > }; > > -enum { > - ALIGN_L = 0, > - ALIGN_C, > - ALIGN_R > -}; > +enum { ALIGN_L = 0, > + ALIGN_C, > + ALIGN_R > + }; > > enum { > @@ -84,13 +93,24 @@ > #define MAX_FONT_COUNT 5 > > +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 Visual *visual_ptr; > static xcb_colormap_t colormap; > + > + > 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; > @@ -102,4 +122,12 @@ > static area_stack_t area_stack; > > +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]; > + > void > update_gc (void) > @@ -108,4 +136,11 @@ > xcb_change_gc(c, gc[GC_CLEAR], XCB_GC_FOREGROUND, (const uint32_t []){ > bgc.v }); > xcb_change_gc(c, gc[GC_ATTR], XCB_GC_FOREGROUND, (const uint32_t []){ > ugc.v }); > + XftColorFree(dpy, visual_ptr, colormap , &sel_fg); > + char color[] = "#ffffff"; > + uint32_t nfgc = fgc.v & 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); > + } > } > > @@ -189,5 +224,35 @@ > } > > + > int > +xft_char_width_slot (uint16_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 (uint16_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, (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); > + 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 > shift (monitor_t *mon, int x, int align, int ch_width) > { > @@ -208,6 +273,6 @@ > break; > } > - > - // Draw the background first > + > + /* Draw the background first */ > fill_rect(mon->pixmap, gc[GC_CLEAR], x, 0, ch_width, bh); > return x; > @@ -234,17 +299,28 @@ > 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; > + int ch_width; > > + if (cur_font->xft_ft) { > + ch_width = xft_char_width(ch, cur_font); > + } else { > + 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); > - > - // 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, > + 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 { > + /* xcb accepts string in UCS-2 BE, so swap */ > + ch = (ch >> 8) | (ch << 8); > + > + // The coordinates here are those of the baseline > + xcb_poly_text_16_simple(c, mon->pixmap, gc[GC_DRAW], > + x, y, > 1, &ch); > + } > > draw_lines(mon, x, ch_width); > @@ -337,7 +413,13 @@ > > switch (modifier) { > - case '+': attrs |= (1<<pos); break; > - case '-': attrs &=~(1<<pos); break; > - case '!': attrs ^= (1<<pos); break; > + case '+': > + attrs |= (1u<<pos); > + break; > + case '-': > + attrs &=~(1u<<pos); > + break; > + case '!': > + attrs ^= (1u<<pos); > + break; > } > } > @@ -460,4 +542,13 @@ > font_has_glyph (font_t *font, const uint16_t c) > { > + if (font->xft_ft) { > + if (XftCharExists(dpy, font->xft_ft, (FcChar32) c)) { > + return true; > + } else { > + return false; > + } > + > + } > + > if (c < font->char_min || c > font->char_max) > return false; > @@ -469,21 +560,25 @@ > } > > -// returns NULL if character cannot be printed > 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; > } > > + > void > parse (char *text) > @@ -505,7 +600,12 @@ > 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"); > + } > + > for (;;) { > if (*p == '\0' || *p == '\n') > - return; > + break; > > if (p[0] == '%' && p[1] == '{' && (block_end = strchr(p++, '}'))) { > @@ -561,4 +661,8 @@ > else > { 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++; > @@ -603,8 +707,4 @@ > p++; > } else { // utf-8 -> ucs-2 > - // Escaped % symbol, eat the first one > - if (p[0] == '%' && p[1] == '%') > - p++; > - > uint8_t *utf = (uint8_t *)p; > uint16_t ucs; > @@ -650,6 +750,8 @@ > continue; > > - xcb_change_gc(c, gc[GC_DRAW] , XCB_GC_FONT, (const uint32_t []){ > cur_font->ptr }); > - > + 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, ucs); > > @@ -658,4 +760,5 @@ > } > } > + XftDrawDestroy (xft_draw); > } > > @@ -675,10 +778,4 @@ > font = xcb_generate_id(c); > > - cookie = xcb_open_font_checked(c, font, strlen(pattern), pattern); > - if (xcb_request_check (c, cookie)) { > - fprintf(stderr, "Could not load font \"%s\"\n", pattern); > - return; > - } > - > font_t *ret = calloc(1, sizeof(font_t)); > > @@ -686,26 +783,53 @@ > return; > > - queryreq = xcb_query_font(c, font); > - font_info = xcb_query_font_reply(c, queryreq, NULL); > + cookie = xcb_open_font_checked(c, font, strlen(pattern), pattern); > + 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->width = font_info->max_bounds.character_width; > - ret->char_max = font_info->max_byte1 << 8 | font_info->max_char_or_byte2; > - ret->char_min = font_info->min_byte1 << 8 | font_info->min_char_or_byte2; > - > - // Copy over the width lut as it's part of font_info > - int lut_size = sizeof(xcb_charinfo_t) * > xcb_query_font_char_infos_length(font_info); > - if (lut_size) { > - ret->width_lut = malloc(lut_size); > - memcpy(ret->width_lut, xcb_query_font_char_infos(font_info), > lut_size); > + ret->xft_ft = NULL; > + ret->ptr = font; > + ret->descent = font_info->font_descent; > + ret->height = font_info->font_ascent + font_info->font_descent; > + ret->width = font_info->max_bounds.character_width; > + ret->char_max = font_info->max_byte1 << 8 | > font_info->max_char_or_byte2; > + ret->char_min = font_info->min_byte1 << 8 | > font_info->min_char_or_byte2; > + // Copy over the width lut as it's part of font_info > + int lut_size = sizeof(xcb_charinfo_t) * > xcb_query_font_char_infos_length(font_info); > + if (lut_size) { > + ret->width_lut = malloc(lut_size); > + memcpy(ret->width_lut, xcb_query_font_char_infos(font_info), > lut_size); > + } > + free(font_info); > + } else if ((ret->xft_ft = XftFontOpenName (dpy, scr_nbr, pattern))) { > + ret->ptr = 0; > + 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", pattern); > + free(ret); > + return; > } > > - free(font_info); > - > 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, > @@ -757,17 +881,20 @@ > strut[2] = bh; > strut[8] = mon->x; > - strut[9] = mon->x + mon->width - 1; > + strut[9] = mon->x + mon->width; > } else { > strut[3] = bh; > strut[10] = mon->x; > - strut[11] = mon->x + mon->width - 1; > + strut[11] = mon->x + mon->width; > } > > 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 []) { > + 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); > 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"); > } > } > @@ -789,11 +916,12 @@ > ret->next = ret->prev = NULL; > 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, > - 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, > - (const uint32_t []){ bgc.v, bgc.v, dock, XCB_EVENT_MASK_EXPOSURE > | XCB_EVENT_MASK_BUTTON_PRESS, colormap }); > + 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, > + (const uint32_t []) { > + bgc.v, bgc.v, dock, XCB_EVENT_MASK_EXPOSURE | > XCB_EVENT_MASK_BUTTON_PRESS, colormap > + }); > > ret->pixmap = xcb_generate_id(c); > @@ -854,5 +982,5 @@ > // Get height of screen from y_offset + height of lowest monitor > if (h >= height) > - height = h; > + height = h; > } > > @@ -877,8 +1005,8 @@ > 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); > > if (!mon) > @@ -888,5 +1016,4 @@ > > width -= rects[i].width - left; > - > // No need to check for other monitors > if (width <= 0) > @@ -909,5 +1036,5 @@ > > 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) { > @@ -943,5 +1070,5 @@ > > 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); > @@ -973,5 +1100,5 @@ > 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--; > @@ -1004,5 +1131,5 @@ > > 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); > @@ -1029,20 +1156,19 @@ > get_visual (void) > { > - xcb_depth_iterator_t iter; > > - iter = xcb_screen_allowed_depths_iterator(scr); > + XVisualInfo xv; > + xv.depth = 32; > + int result = 0; > + XVisualInfo* result_ptr = NULL; > + result_ptr = XGetVisualInfo(dpy, VisualDepthMask, &xv, &result); > > - // Try to find a RGBA visual > - 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 (result > 0) { > + visual_ptr = result_ptr->visual; > + return result_ptr->visualid; > } > - > - // Fallback to the default one > - return scr->root_visual; > + > + //Fallback > + visual_ptr = DefaultVisual(dpy, scr_nbr); > + return scr->root_visual; > } > > @@ -1101,6 +1227,15 @@ > xconn (void) > { > - // Connect to X > - c = xcb_connect (NULL, NULL); > + 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); > + } > + > + XSetEventQueueOwner(dpy, XCBOwnsEventQueue); > + > if (xcb_connection_has_error(c)) { > fprintf(stderr, "Couldn't connect to X\n"); > @@ -1108,10 +1243,9 @@ > } > > - // Grab infos from the first screen > + /* Grab infos from the first screen */ > scr = xcb_setup_roots_iterator(xcb_get_setup(c)).data; > > - // Try to get a RGBA visual and build the colormap for that > - visual = get_visual(); > - > + /* 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); > @@ -1119,5 +1253,5 @@ > > void > -init (char *wm_name) > +init (char *wm_name, char *wm_instance) > { > // Try to load a default font > @@ -1214,6 +1348,31 @@ > 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); > + } > } > > + char color[] = "#ffffff"; > + uint32_t nfgc = fgc.v & 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); > + } > xcb_flush(c); > } > @@ -1223,8 +1382,12 @@ > { > free(area_stack.area); > - > - for (int i = 0; i < font_count; i++) { > - xcb_close_font(c, font_list[i]->ptr); > - free(font_list[i]->width_lut); > + for (int i = 0; font_list[i]; i++) { > + 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]->width_lut); > + } > free(font_list[i]); > } > @@ -1238,5 +1401,5 @@ > } > > - xcb_free_colormap(c, colormap); > + XftColorFree(dpy, visual_ptr, colormap, &sel_fg); > > if (gc[GC_DRAW]) > @@ -1250,4 +1413,19 @@ > } > > +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) > @@ -1257,4 +1435,5 @@ > } > > + > int > main (int argc, char **argv) > @@ -1272,4 +1451,5 @@ > int ch, areas; > char *wm_name; > + char *instance_name; > > // Install the parachute! > @@ -1281,4 +1461,5 @@ > dbgc = bgc = (rgba_t)0x00000000U; > dfgc = fgc = (rgba_t)0xffffffffU; > + > dugc = ugc = fgc; > > @@ -1287,11 +1468,13 @@ > wm_name = NULL; > > + instance_name = strip_path(argv[0]); > + > // Connect to the Xserver and initialize scr > xconn(); > > - while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:U:n:")) != -1) { > + while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:U: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" > @@ -1305,5 +1488,6 @@ > "\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]); > + "\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; > @@ -1314,4 +1498,5 @@ > case 'f': font_load(optarg); break; > case 'u': bu = strtoul(optarg, NULL, 10); break; > + case 'o': add_y_offset(strtol(optarg, NULL, 10)); break; > case 'B': dbgc = bgc = parse_color(optarg, NULL, > (rgba_t)0x00000000U); break; > case 'F': dfgc = fgc = parse_color(optarg, NULL, > (rgba_t)0xffffffffU); break; > @@ -1343,10 +1528,15 @@ > > // 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); > > + // Prevent fgets to block > + fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); > + > for (;;) { > bool redraw = false; > @@ -1362,7 +1552,7 @@ > } > if (pollin[0].revents & POLLIN) { // New input, process it > - if (fgets(input, sizeof(input), stdin) == NULL) > - break; // EOF received > - > + input[0] = '\0'; > + while (fgets(input, sizeof(input), stdin) != NULL) > + ; // Drain the buffer, the last line is actually used > parse(input); > redraw = true; > @@ -1387,5 +1577,5 @@ > } > } > - break; > + break; > } > > -- jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE