Only in dmenu-4.0: .dmenu.c.swp diff -up dmenu-4.0/config.h dmenu-4.0-xft/config.h --- dmenu-4.0/config.h 2009-04-18 07:50:04.000000000 -0400 +++ dmenu-4.0-xft/config.h 2009-11-08 05:07:40.028951847 -0500 @@ -7,3 +7,4 @@ static const char *normfgcolor = "#00000 static const char *selbgcolor = "#0066ff"; static const char *selfgcolor = "#ffffff"; static unsigned int spaceitem = 30; /* px between menu items */ +static const char *fontxft = "Monospace-10:normal"; /*if set xft is used */ diff -up dmenu-4.0/config.mk dmenu-4.0-xft/config.mk --- dmenu-4.0/config.mk 2009-04-18 07:50:04.000000000 -0400 +++ dmenu-4.0-xft/config.mk 2009-11-08 05:07:40.028951847 -0500 @@ -15,8 +15,8 @@ XINERAMALIBS = -L${X11LIB} -lXinerama XINERAMAFLAGS = -DXINERAMA # 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} -I/usr/include -I/usr/include/freetype2 +LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS} -lXft -lX11 -lXrender -lfreetype -lz -lfontconfig -lXrender -lX11 # flags CPPFLAGS = -D_BSD_SOURCE -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} diff -up dmenu-4.0/dmenu.1 dmenu-4.0-xft/dmenu.1 --- dmenu-4.0/dmenu.1 2009-04-18 07:50:04.000000000 -0400 +++ dmenu-4.0-xft/dmenu.1 2009-11-08 05:07:40.028951847 -0500 @@ -6,6 +6,7 @@ dmenu \- dynamic menu .RB [ \-i ] .RB [ \-b ] .RB [ \-fn " "] +.RB [ \-fa " "] .RB [ \-nb " "] .RB [ \-nf " "] .RB [ \-p " "] @@ -29,6 +30,9 @@ defines that dmenu appears at the bottom .B \-fn defines the font. .TP +.B \-fa +defines the xft font. +.TP .B \-nb defines the normal background color (#RGB, #RRGGBB, and color names are supported). .TP diff -up dmenu-4.0/dmenu.c dmenu-4.0-xft/dmenu.c --- dmenu-4.0/dmenu.c 2009-04-18 07:50:04.000000000 -0400 +++ dmenu-4.0-xft/dmenu.c 2009-11-08 05:50:32.962034661 -0500 @@ -13,6 +13,7 @@ #ifdef XINERAMA #include #endif +#include /* macros */ #define CLEANMASK(mask) (mask & ~(numlockmask | LockMask)) @@ -27,6 +28,7 @@ typedef struct { int x, y, w, h; unsigned long norm[ColLast]; unsigned long sel[ColLast]; + Bool selected; Drawable drawable; GC gc; struct { @@ -36,6 +38,16 @@ typedef struct { int descent; int height; } font; + XftDraw *xftdraw; + XftColor xftselcolor; + XftColor xftcolor; + XGlyphInfo gi; + struct { + XftFont *xft_font; + int ascent; + int descent; + int height; + } xftfont; } DC; /* draw context */ typedef struct Item Item; @@ -160,9 +172,14 @@ cleanup(void) { free(allitems); allitems = itm; } + if(fontxft) { + XftColorFree (dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), &dc.xftcolor); + XftFontClose (dpy, dc.xftfont.xft_font); + XftDrawDestroy(dc.xftdraw); + } if(dc.font.set) XFreeFontSet(dpy, dc.font.set); - else + else if(!fontxft) XFreeFont(dpy, dc.font.xfont); XFreePixmap(dpy, dc.drawable); XFreeGC(dpy, dc.gc); @@ -182,7 +199,9 @@ drawmenu(void) { /* print prompt? */ if(promptw) { dc.w = promptw; + dc.selected = True; drawtext(prompt, dc.sel); + dc.selected = False; } dc.x += promptw; dc.w = mw - promptw; @@ -200,7 +219,13 @@ drawmenu(void) { dc.w = textw(i->text); if(dc.w > mw / 3) dc.w = mw / 3; - drawtext(i->text, (sel == i) ? dc.sel : dc.norm); + if(sel == i) { + dc.selected = True; + drawtext(i->text, dc.sel); + dc.selected = False; + } else { + drawtext(i->text, dc.norm); + } dc.x += dc.w; } dc.x = mw - spaceitem; @@ -224,7 +249,11 @@ drawtext(const char *text, unsigned long olen = strlen(text); h = dc.font.ascent + dc.font.descent; y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; - x = dc.x + (h / 2); + if(dc.xftfont.xft_font) { + h = dc.xftfont.ascent + dc.xftfont.descent; + y = dc.y + (dc.h / 2) - (h / 2) + dc.xftfont.ascent; + } + x = dc.x + (h / 2); /* shorten text if necessary */ for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--); if(!len) @@ -233,7 +262,15 @@ drawtext(const char *text, unsigned long if(len < olen) for(i = len; i && i > len - 3; buf[--i] = '.'); XSetForeground(dpy, dc.gc, col[ColFG]); - if(dc.font.set) + if(fontxft) { + if (!dc.xftdraw) + eprint("error, creating xft drawable failed"); + if(dc.selected) { + XftDrawString8(dc.xftdraw, &dc.xftselcolor, dc.xftfont.xft_font, x, y, (unsigned char*)buf, len); + } else { + XftDrawString8(dc.xftdraw, &dc.xftcolor, dc.xftfont.xft_font, x, y, (unsigned char*)buf, len); + } + } else 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); @@ -253,7 +290,6 @@ unsigned long getcolor(const char *colstr) { Colormap cmap = DefaultColormap(dpy, screen); XColor color; - if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) eprint("error, cannot allocate color '%s'\n", colstr); return color.pixel; @@ -309,6 +345,15 @@ initfont(const char *fontstr) { } void +initxft() { + if(!(dc.xftfont.xft_font = XftFontOpenName (dpy, screen, fontxft))) + eprint("error, cannot load xft font\n" ); + dc.xftfont.ascent = dc.xftfont.xft_font->ascent; + dc.xftfont.descent = dc.xftfont.xft_font->descent; + dc.xftfont.height = dc.xftfont.ascent + dc.xftfont.descent; +} + +void kpress(XKeyEvent * e) { char buf[32]; int i, num; @@ -589,7 +634,15 @@ setup(Bool topbar) { dc.norm[ColFG] = getcolor(normfgcolor); dc.sel[ColBG] = getcolor(selbgcolor); dc.sel[ColFG] = getcolor(selfgcolor); - initfont(font); + dc.selected = False; + if(fontxft){ + if(!XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), (const char*)normfgcolor, &dc.xftcolor)) + eprint("error, cannot allocate xft font color '%s'\n", normfgcolor); + if(!XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), (const char*)selfgcolor, &dc.xftselcolor)) + eprint("error, cannot allocate xft font color '%s'\n", normfgcolor); + else + initxft(); + } else initfont(font); /* menu window */ wa.override_redirect = True; @@ -597,6 +650,9 @@ setup(Bool topbar) { wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask; /* menu window geometry */ + if(fontxft) + mh = dc.xftfont.height + 2; + else mh = dc.font.height + 2; #if XINERAMA if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) { @@ -632,7 +688,7 @@ setup(Bool topbar) { 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); - if(!dc.font.set) + if(!dc.font.set && !fontxft) XSetFont(dpy, dc.gc, dc.font.xfont->fid); if(maxname) cmdw = textw(maxname); @@ -645,13 +701,20 @@ setup(Bool topbar) { text[0] = 0; match(text); XMapRaised(dpy, win); + if(fontxft) { + dc.xftdraw = XftDrawCreate(dpy, dc.drawable, DefaultVisual(dpy,screen), DefaultColormap(dpy,screen)); + if(!dc.xftdraw) + eprint("error, cannot create xft drawable\n"); + } } int textnw(const char *text, unsigned int len) { - XRectangle r; - - if(dc.font.set) { + if(fontxft) { + XftTextExtents8(dpy, dc.xftfont.xft_font, (const FcChar8*)text, len, &dc.gi); + return dc.gi.width; + } else if(dc.font.set) { + XRectangle r; XmbTextExtents(dc.font.set, text, len, NULL, &r); return r.width; } @@ -660,6 +723,8 @@ textnw(const char *text, unsigned int le int textw(const char *text) { + if(fontxft) + return textnw(text, strlen(text)) + dc.xftfont.height; return textnw(text, strlen(text)) + dc.font.height; } @@ -679,6 +744,9 @@ main(int argc, char *argv[]) { else if(!strcmp(argv[i], "-fn")) { if(++i < argc) font = argv[i]; } + else if(!strcmp(argv[i], "-fa")) { + if(++i < argc) fontxft = argv[i]; + } else if(!strcmp(argv[i], "-nb")) { if(++i < argc) normbgcolor = argv[i]; } @@ -697,7 +765,7 @@ main(int argc, char *argv[]) { 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 ] [-nb ] [-nf ]\n" + eprint("usage: dmenu [-i] [-b] [-fn ] [-fa ] [-nb ] [-nf ]\n" " [-p ] [-sb ] [-sf ] [-v]\n"); if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) fprintf(stderr, "warning: no locale support\n");