Dmenu-4.0-xft.diff

From HaskellWiki
Jump to navigation Jump to search
diff -r cdaa1062e534 config.h
--- a/config.h	Fri May 22 06:02:00 2009 -0400
+++ b/config.h	Wed May 27 20:39:52 2009 -0400
@@ -5,5 +5,4 @@
 static const char *normbgcolor = "#cccccc";
 static const char *normfgcolor = "#000000";
 static const char *selbgcolor  = "#0066ff";
-static const char *selfgcolor  = "#ffffff";
 static unsigned int spaceitem  = 30; /* px between menu items */
diff -r cdaa1062e534 config.mk
--- a/config.mk	Fri May 22 06:02:00 2009 -0400
+++ b/config.mk	Wed May 27 20:39:52 2009 -0400
@@ -14,12 +14,17 @@
 XINERAMALIBS = -L${X11LIB} -lXinerama
 XINERAMAFLAGS = -DXINERAMA
 
+# Xft, comment if you don't want it
+XFTINCS = `pkg-config --cflags xft`
+XFTLIBS = `pkg-config --libs xft`
+XFTFLAGS = -DXFT
+
 # includes and libs
-INCS = -I. -I/usr/include -I${X11INC}
-LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS}
+INCS = -I. -I/usr/include -I${X11INC} ${XFTINCS}
+LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS} ${XFTLIBS}
 
 # flags
-CPPFLAGS = -D_BSD_SOURCE -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
+CPPFLAGS = -D_BSD_SOURCE -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} ${XFTFLAGS}
 CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
 LDFLAGS = -s ${LIBS}
 
diff -r cdaa1062e534 dmenu.c
--- a/dmenu.c	Fri May 22 06:02:00 2009 -0400
+++ b/dmenu.c	Wed May 27 20:39:52 2009 -0400
@@ -10,6 +10,9 @@
 #include <X11/keysym.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
+#ifdef XFT
+#include <X11/Xft/Xft.h>
+#endif
 #ifdef XINERAMA
 #include <X11/extensions/Xinerama.h>
 #endif
@@ -28,6 +31,11 @@
 	unsigned long norm[ColLast];
 	unsigned long sel[ColLast];
 	Drawable drawable;
+#ifdef XFT
+	XftColor xftnorm[ColLast];
+	XftColor xftsel[ColLast];
+	XftDraw *xftdrawable;
+#endif
 	GC gc;
 	struct {
 		XFontStruct *xfont;
@@ -35,6 +43,10 @@
 		int ascent;
 		int descent;
 		int height;
+#ifdef XFT
+		XftFont *xftfont;
+		XGlyphInfo *extents;
+#endif
 	} font;
 } DC; /* draw context */
 
@@ -54,6 +66,9 @@
 static void drawtext(const char *text, unsigned long col[ColLast]);
 static void eprint(const char *errstr, ...);
 static unsigned long getcolor(const char *colstr);
+#ifdef XFT
+static unsigned long getxftcolor(const char *colstr, XftColor *color);
+#endif
 static Bool grabkeyboard(void);
 static void initfont(const char *fontstr);
 static void kpress(XKeyEvent * e);
@@ -74,7 +89,7 @@
 static int promptw = 0;
 static int ret = 0;
 static int screen;
-static unsigned int mw, mh;
+static unsigned int mw, mh, bh;
 static unsigned int numlockmask = 0;
 static Bool running = True;
 static Display *dpy;
@@ -160,10 +175,12 @@
 		free(allitems);
 		allitems = itm;
 	}
-	if(dc.font.set)
-		XFreeFontSet(dpy, dc.font.set);
-	else
-		XFreeFont(dpy, dc.font.xfont);
+	if(!dc.font.xftfont) {
+		if(dc.font.set)
+			XFreeFontSet(dpy, dc.font.set);
+		else
+			XFreeFont(dpy, dc.font.xfont);
+	}
 	XFreePixmap(dpy, dc.drawable);
 	XFreeGC(dpy, dc.gc);
 	XDestroyWindow(dpy, win);
@@ -232,11 +249,19 @@
 	memcpy(buf, text, len);
 	if(len < olen)
 		for(i = len; i && i > len - 3; buf[--i] = '.');
+#ifdef XFT
+	if(dc.font.xftfont)
+		XftDrawStringUtf8(dc.xftdrawable, &dc.xftnorm[ColFG], dc.font.xftfont, x, y, (unsigned char*) buf, len);
+	else {
+#endif
 	XSetForeground(dpy, dc.gc, col[ColFG]);
 	if(dc.font.set)
 		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
 	else
 		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
+#ifdef XFT
+	}
+#endif
 }
 
 void
@@ -259,6 +284,18 @@
 	return color.pixel;
 }
 
+#ifdef XFT
+unsigned long
+getxftcolor(const char *colstr, XftColor *color) {
+	Colormap cmap = DefaultColormap(dpy, screen);
+	Visual *vis = DefaultVisual(dpy, screen);
+
+	if(!XftColorAllocName(dpy, vis, cmap, colstr, color))
+		eprint("error, cannot allocate color '%s'\n", colstr);
+	return color->pixel;
+}
+#endif
+
 Bool
 grabkeyboard(void) {
 	unsigned int len;
@@ -274,6 +311,22 @@
 
 void
 initfont(const char *fontstr) {
+#ifdef XFT
+	dc.font.xftfont = 0;
+	if(cistrstr(fontstr,"xft:")) {
+		dc.font.xftfont = XftFontOpenXlfd(dpy, screen, fontstr+4);
+		if(!dc.font.xftfont)
+			dc.font.xftfont = XftFontOpenName(dpy, screen, fontstr+4);
+		if(!dc.font.xftfont)
+			eprint("error, cannot load font: '%s'\n", fontstr+4);
+		dc.font.extents = malloc(sizeof(XGlyphInfo));
+		XftTextExtentsUtf8(dpy, dc.font.xftfont, (unsigned const char *) fontstr+4, strlen(fontstr+4), dc.font.extents);
+		dc.font.height = dc.font.xftfont->ascent + dc.font.xftfont->descent;
+		dc.font.ascent = dc.font.xftfont->ascent;
+		dc.font.descent = dc.font.xftfont->descent;
+	}
+	else {
+#endif
 	char *def, **missing;
 	int i, n;
 
@@ -306,6 +359,9 @@
 		dc.font.descent = dc.font.xfont->descent;
 	}
 	dc.font.height = dc.font.ascent + dc.font.descent;
+#ifdef XFT
+	}
+#endif
 }
 
 void
@@ -585,11 +641,21 @@
 	XFreeModifiermap(modmap);
 
 	/* style */
+	initfont(font);
+#ifdef XFT
+	if(dc.font.xftfont) {
+		dc.norm[ColBG] = getxftcolor(normbgcolor, &dc.xftnorm[ColBG]);
+		dc.norm[ColFG] = getxftcolor(normfgcolor, &dc.xftnorm[ColFG]);
+		dc.sel[ColBG] = getxftcolor(selbgcolor, &dc.xftsel[ColBG]);
+	}
+	else {
+#endif
 	dc.norm[ColBG] = getcolor(normbgcolor);
 	dc.norm[ColFG] = getcolor(normfgcolor);
 	dc.sel[ColBG] = getcolor(selbgcolor);
-	dc.sel[ColFG] = getcolor(selfgcolor);
-	initfont(font);
+#ifdef XFT
+	}
+#endif
 
 	/* menu window */
 	wa.override_redirect = True;
@@ -598,6 +664,8 @@
 
 	/* menu window geometry */
 	mh = dc.font.height + 2;
+	if(mh < bh)
+		mh = bh;
 #if XINERAMA
 	if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) {
 		i = 0;
@@ -632,8 +700,19 @@
 	dc.drawable = XCreatePixmap(dpy, root, mw, mh, DefaultDepth(dpy, screen));
 	dc.gc = XCreateGC(dpy, root, 0, NULL);
 	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
+#ifdef XFT
+	if(dc.font.xftfont) {
+		dc.xftdrawable = XftDrawCreate(dpy, dc.drawable, DefaultVisual(dpy,screen), DefaultColormap(dpy,screen));
+		if(!dc.xftdrawable)
+			eprint("error, cannot create drawable\n");
+	}
+	else {
+#endif
 	if(!dc.font.set)
 		XSetFont(dpy, dc.gc, dc.font.xfont->fid);
+#ifdef XFT
+	}
+#endif
 	if(maxname)
 		cmdw = textw(maxname);
 	if(cmdw > mw / 3)
@@ -649,6 +728,15 @@
 
 int
 textnw(const char *text, unsigned int len) {
+#ifdef XFT
+	if (dc.font.xftfont) {
+		XftTextExtentsUtf8(dpy, dc.font.xftfont, (unsigned const char *) text, strlen(text), dc.font.extents);
+		if(dc.font.extents->height > dc.font.height)
+			dc.font.height = dc.font.extents->height;
+		return dc.font.extents->xOff;
+	}
+	else {
+#endif
 	XRectangle r;
 
 	if(dc.font.set) {
@@ -656,6 +744,9 @@
 		return r.width;
 	}
 	return XTextWidth(dc.font.xfont, text, len);
+#ifdef XFT
+	}
+#endif
 }
 
 int
@@ -691,14 +782,14 @@
 		else if(!strcmp(argv[i], "-sb")) {
 			if(++i < argc) selbgcolor = argv[i];
 		}
-		else if(!strcmp(argv[i], "-sf")) {
-			if(++i < argc) selfgcolor = argv[i];
+		else if(!strcmp(argv[i], "-bh")) {
+			if(++i < argc) bh = atoi(argv[i]);
 		}
 		else if(!strcmp(argv[i], "-v"))
 			eprint("dmenu-"VERSION", © 2006-2008 dmenu engineers, see LICENSE for details\n");
 		else
 			eprint("usage: dmenu [-i] [-b] [-fn <font>] [-nb <color>] [-nf <color>]\n"
-			       "             [-p <prompt>] [-sb <color>] [-sf <color>] [-v]\n");
+ 			       "             [-sb <color>] [-bh <height>] [-p <prompt>] [-v]\n");
 	if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
 		fprintf(stderr, "warning: no locale support\n");
 	if(!(dpy = XOpenDisplay(NULL)))