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. 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; }