Hi Eric! First of all, I'm making my glorious debut in the mailing lists. I'm in love with the philosophy and the software that suckless produce. It simply rocks.
Now the real thing, thanks you for the patch! It works like a charm, after correcting some things: - The diff has DOS line endings everywhere, including the source. It was pretty hard to spot the difference. - There are laking some libs in config.mk to link with Xft support. I'm sending a new iteration of the patch, correcting line endings and adding the necesary libs to config.mk . main(l,V){while(V=l==l++){while( ++V*V<l/* # ~ .lV ! */&&l%V); printf(l%V||V==l?"%i\n":!V,l);}} 2015-02-17 1:56 GMT-03:00 Eric Pruitt <eric.pru...@gmail.com>: > A while back, [this](http://lists.suckless.org/dev/1311/18279.html) Xft > patch was posted to the mailing list. I split out the Xft changes from > the window creation semantics, and I use that to patch Xft support into > my copy of dwm; the patch I use is attached to this email. Given that st > uses Xft, is there any reason for dwm and dmenu to not use it as well > since there were / are plans for a unified "drw.[ch]" library shared > between the suckless projects? Quentin's changes to the dwm drw library > are straightforward, and I'm considering porting st's font-fallback code > to his Xft-supporting drw library, but I would also hate to put the > effort into doing that only to have the API changed underneath me. I > think the Quentin's patch would make a nice addition to the official dwm > repo. > > Eric >
diff --git a/config.mk b/config.mk index bc3d80e..9615858 100644 --- a/config.mk +++ b/config.mk @@ -4,7 +4,7 @@ VERSION = 6.1 # Customize below to fit your system # paths PREFIX = /usr/local MANPREFIX = ${PREFIX}/share/man X11INC = /usr/X11R6/include @@ -15,8 +15,12 @@ XINERAMALIBS = -lXinerama XINERAMAFLAGS = -DXINERAMA # includes and libs -INCS = -I${X11INC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} +INCS = -I${X11INC} \ + `pkg-config --cflags fontconfig` \ + `pkg-config --cflags freetype2` +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} -lXft \ + `pkg-config --libs fontconfig` \ + `pkg-config --libs freetype2` # flags CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} diff --git a/drw.c b/drw.c index b130405..7057a34 100644 --- a/drw.c +++ b/drw.c @@ -3,6 +3,7 @@ #include <stdlib.h> #include <string.h> #include <X11/Xlib.h> +#include <X11/Xft/Xft.h> #include "drw.h" #include "util.h" @@ -42,39 +43,19 @@ drw_free(Drw *drw) { } Fnt * -drw_font_create(Display *dpy, const char *fontname) { +drw_font_create(Display *dpy, int screen, const char *fontname) { Fnt *font; - char *def, **missing; - int n; font = (Fnt *)calloc(1, sizeof(Fnt)); if(!font) return NULL; - font->set = XCreateFontSet(dpy, fontname, &missing, &n, &def); - if(missing) { - while(n--) - fprintf(stderr, "drw: missing fontset: %s\n", missing[n]); - XFreeStringList(missing); - } - if(font->set) { - XFontStruct **xfonts; - char **font_names; - XExtentsOfFontSet(font->set); - n = XFontsOfFontSet(font->set, &xfonts, &font_names); - while(n--) { - font->ascent = MAX(font->ascent, (*xfonts)->ascent); - font->descent = MAX(font->descent,(*xfonts)->descent); - xfonts++; - } - } - else { - if(!(font->xfont = XLoadQueryFont(dpy, fontname)) - && !(font->xfont = XLoadQueryFont(dpy, "fixed"))) - die("error, cannot load font: '%s'\n", fontname); - font->ascent = font->xfont->ascent; - font->descent = font->xfont->descent; - } + if(!(font->xfont = XftFontOpenName(dpy,screen,fontname)) + && !(font->xfont = XftFontOpenName(dpy,screen,"fixed"))) + die("error, cannot load font: '%s'\n", fontname); + font->ascent = font->xfont->ascent; + font->descent = font->xfont->descent; font->h = font->ascent + font->descent; + font->dpy = dpy; return font; } @@ -82,10 +63,7 @@ void drw_font_free(Display *dpy, Fnt *font) { if(!font) return; - if(font->set) - XFreeFontSet(dpy, font->set); - else - XFreeFont(dpy, font->xfont); + XftFontClose(dpy, font->xfont); free(font); } @@ -93,7 +71,7 @@ Clr * drw_clr_create(Drw *drw, const char *clrname) { Clr *clr; Colormap cmap; - XColor color; + Visual *vis; if(!drw) return NULL; @@ -101,9 +79,10 @@ drw_clr_create(Drw *drw, const char *clrname) { if(!clr) return NULL; cmap = DefaultColormap(drw->dpy, drw->screen); - if(!XAllocNamedColor(drw->dpy, cmap, clrname, &color, &color)) + vis = DefaultVisual(drw->dpy, drw->screen); + if(!XftColorAllocName(drw->dpy, vis, cmap, clrname, &clr->rgb)) die("error, cannot allocate color '%s'\n", clrname); - clr->rgb = color.pixel; + clr->pix = clr->rgb.pixel; return clr; } @@ -121,7 +100,7 @@ drw_setfont(Drw *drw, Fnt *font) { void drw_setscheme(Drw *drw, ClrScheme *scheme) { - if(drw && scheme) + if(drw && scheme) drw->scheme = scheme; } @@ -131,7 +110,7 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int if(!drw || !drw->font || !drw->scheme) return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb : drw->scheme->fg->rgb); + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->pix : drw->scheme->fg->pix); dx = (drw->font->ascent + drw->font->descent + 2) / 4; if(filled) XFillRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx+1, dx+1); @@ -144,13 +123,17 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex char buf[256]; int i, tx, ty, th, len, olen; Extnts tex; + Colormap cmap; + Visual *vis; + XftDraw *d; if(!drw || !drw->scheme) return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->fg->rgb : drw->scheme->bg->rgb); + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->fg->pix : drw->scheme->bg->pix); XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); if(!text || !drw->font) return; + olen = strlen(text); drw_font_getexts(drw->font, text, olen, &tex); th = drw->font->ascent + drw->font->descent; @@ -164,11 +147,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex memcpy(buf, text, len); if(len < olen) for(i = len; i && i > len - 3; buf[--i] = '.'); - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb : drw->scheme->fg->rgb); - if(drw->font->set) - XmbDrawString(drw->dpy, drw->drawable, drw->font->set, drw->gc, tx, ty, buf, len); - else - XDrawString(drw->dpy, drw->drawable, drw->gc, tx, ty, buf, len); + + cmap = DefaultColormap(drw->dpy, drw->screen); + vis = DefaultVisual(drw->dpy, drw->screen); + d = XftDrawCreate(drw->dpy, drw->drawable, vis, cmap); + XftDrawStringUtf8(d, invert ? &drw->scheme->bg->rgb : &drw->scheme->fg->rgb, drw->font->xfont, tx, ty, (XftChar8 *)buf, len); + XftDrawDestroy(d); } void @@ -182,19 +166,13 @@ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) { void drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex) { - XRectangle r; + XGlyphInfo ext; if(!font || !text) return; - if(font->set) { - XmbTextExtents(font->set, text, len, NULL, &r); - tex->w = r.width; - tex->h = r.height; - } - else { - tex->h = font->ascent + font->descent; - tex->w = XTextWidth(font->xfont, text, len); - } + XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); + tex->h = font->h; + tex->w = ext.xOff; } unsigned int diff --git a/drw.h b/drw.h index a5f34e0..503e764 100644 --- a/drw.h +++ b/drw.h @@ -1,7 +1,8 @@ /* See LICENSE file for copyright and license details. */ typedef struct { - unsigned long rgb; + unsigned long pix; + XftColor rgb; } Clr; typedef struct { @@ -9,11 +10,11 @@ typedef struct { } Cur; typedef struct { + Display *dpy; int ascent; int descent; unsigned int h; - XFontSet set; - XFontStruct *xfont; + XftFont *xfont; } Fnt; typedef struct { @@ -44,7 +45,7 @@ void drw_resize(Drw *drw, unsigned int w, unsigned int h); void drw_free(Drw *drw); /* Fnt abstraction */ -Fnt *drw_font_create(Display *dpy, const char *fontname); +Fnt *drw_font_create(Display *dpy, int screen, const char *fontname); void drw_font_free(Display *dpy, Fnt *font); void drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *extnts); unsigned int drw_font_getexts_width(Fnt *font, const char *text, unsigned int len); diff --git a/dwm.c b/dwm.c index f896170..e018bb1 100644 --- a/dwm.c +++ b/dwm.c @@ -39,6 +39,7 @@ #ifdef XINERAMA #include <X11/extensions/Xinerama.h> #endif /* XINERAMA */ +#include <X11/Xft/Xft.h> #include "drw.h" #include "util.h" @@ -792,7 +793,7 @@ focus(Client *c) { detachstack(c); attachstack(c); grabbuttons(c, True); - XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->rgb); + XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->pix); setfocus(c); } else { @@ -1040,7 +1041,7 @@ manage(Window w, XWindowAttributes *wa) { wc.border_width = c->bw; XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->rgb); + XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->pix); configure(c); /* propagates border_width, if size doesn't change */ updatewindowtype(c); updatesizehints(c); @@ -1506,7 +1507,7 @@ setup(void) { /* init screen */ screen = DefaultScreen(dpy); root = RootWindow(dpy, screen); - fnt = drw_font_create(dpy, font); + fnt = drw_font_create(dpy, screen, font); sw = DisplayWidth(dpy, screen); sh = DisplayHeight(dpy, screen); bh = fnt->h + 2; @@ -1685,7 +1686,7 @@ unfocus(Client *c, Bool setfocus) { if(!c) return; grabbuttons(c, False); - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->rgb); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->pix); if(setfocus) { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); @@ -1739,7 +1740,7 @@ updatebars(void) { .event_mask = ButtonPressMask|ExposureMask }; for(m = mons; m; m = m->next) { - if (m->barwin) + if(m->barwin) continue; m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen),