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

Reply via email to