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
Author: Quentin <q...@c9x.me>
Description: From http://lists.suckless.org/dev/1311/18279.html: "For my
personal use of dwm I have written a small patch to support Xft---it actually
decreases the line count of dwm. I thought it would be useful to share it with
you." This patch has been modified to remove the change in window attachment
semantics as well as the config.mk patching. To compile dwm with this patch,
ensure that "-I/usr/include/freetype2" is added to the "INC" variable in
config.mk and "-lXft" added to the "LIBS" variable in the same file.

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 1bbb4b3..f9ae316 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 +797,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 +1045,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);
@@ -1497,7 +1502,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;
@@ -1676,7 +1681,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]);
@@ -1730,7 +1735,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),

Reply via email to