You are not logged in.

#1 2009-12-27 09:49:56

orschiro
Member
Registered: 2009-06-04
Posts: 2,136
Website

[dwm] xft support

Hello guys,

I want to use the Inconsolata font in dwm for my statusbar. As dwm has no support for that by default I'm looking for a patch but the homepage doesn't list anyone. Is there no possibility to add xft support in dwm?

Last edited by orschiro (2009-12-27 09:50:12)

Offline

#2 2009-12-27 10:26:08

Runiq
Member
From: Germany
Registered: 2008-10-29
Posts: 1,053

Re: [dwm] xft support

There's a patch for using Pango (a bit more advanced than Xft as they say) in dwm in this E-Mail. I used it a while ago and I believe it worked out of the box.

Offline

#3 2009-12-27 10:36:41

orschiro
Member
Registered: 2009-06-04
Posts: 2,136
Website

Re: [dwm] xft support

Thank you Runiq. I saved the patch into my /var/abs/local/dwm folder and then tried patch -p1 < pango.patch but I get some errors:

[orschiro@thinkpad dwm]$ patch -p1 < pango.patch
patching file config.def.h
Hunk #1 FAILED at 1.
1 out of 1 hunk FAILED -- saving rejects to file config.def.h.rej
patching file config.mk
Hunk #1 FAILED at 15.
1 out of 1 hunk FAILED -- saving rejects to file config.mk.rej
patching file dwm.c
Hunk #1 FAILED at 39.
Hunk #2 FAILED at 49.
Hunk #3 FAILED at 100.
Hunk #4 FAILED at 154.
Hunk #5 FAILED at 348.
Hunk #6 FAILED at 570.
Hunk #7 FAILED at 579.
Hunk #8 FAILED at 671.
Hunk #9 FAILED at 762.
Hunk #10 FAILED at 1325.
Hunk #11 FAILED at 1412.
Hunk #12 FAILED at 1534.
12 out of 12 hunks FAILED -- saving rejects to file dwm.c.rej

Offline

#4 2009-12-27 16:21:31

Runiq
Member
From: Germany
Registered: 2008-10-29
Posts: 1,053

Re: [dwm] xft support

I rewrote the patch for 5.7.2 and changed the PKGBUILD accordingly. You'll have to change the font in your config.h file to something like "Sans 8" (or "Inconsolata 14" in your case) and recalculate the md5sums accordingly.

pango.patch.dwm-5.7.2:

diff -aur dwm-5.7.2.orig/config.def.h dwm-5.7.2.patched/config.def.h
--- dwm-5.7.2.orig/config.def.h    2009-09-27 21:20:23.000000000 +0200
+++ dwm-5.7.2.patched/config.def.h    2009-12-27 16:46:01.751122177 +0100
@@ -1,7 +1,7 @@
 /* See LICENSE file for copyright and license details. */
 
 /* appearance */
-static const char font[]            = "-*-*-medium-*-*-*-14-*-*-*-*-*-*-*";
+static const char font[]            = "Sans 8";
 static const char normbordercolor[] = "#cccccc";
 static const char normbgcolor[]     = "#cccccc";
 static const char normfgcolor[]     = "#000000";
diff -aur dwm-5.7.2.orig/config.mk dwm-5.7.2.patched/config.mk
--- dwm-5.7.2.orig/config.mk    2009-09-27 21:20:23.000000000 +0200
+++ dwm-5.7.2.patched/config.mk    2009-12-27 16:26:27.572088085 +0100
@@ -15,8 +15,8 @@
 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} `pkg-config --cflags xft pango pangoxft`
+LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS} `pkg-config --libs xft pango pangoxft`
 
 # flags
 CPPFLAGS = -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
diff -aur dwm-5.7.2.orig/dwm.c dwm-5.7.2.patched/dwm.c
--- dwm-5.7.2.orig/dwm.c    2009-09-27 21:20:23.000000000 +0200
+++ dwm-5.7.2.patched/dwm.c    2009-12-27 16:51:01.258589745 +0100
@@ -36,6 +36,10 @@
 #include <X11/Xlib.h>
 #include <X11/Xproto.h>
 #include <X11/Xutil.h>
+#include <X11/Xft/Xft.h>
+#include <pango/pango.h>
+#include <pango/pangoxft.h>
+#include <pango/pango-font.h>
 #ifdef XINERAMA
 #include <X11/extensions/Xinerama.h>
 #endif /* XINERAMA */
@@ -46,8 +50,12 @@
 #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
 #define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
 #define LENGTH(X)               (sizeof X / sizeof X[0])
-#define MAX(A, B)               ((A) > (B) ? (A) : (B))
+#ifndef MAX
+#define MAX(A, B)        ((A) > (B) ? (A) : (B))
+#endif
+#ifndef MIN
 #define MIN(A, B)               ((A) < (B) ? (A) : (B))
+#endif
 #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
 #define WIDTH(X)                ((X)->w + 2 * (X)->bw)
 #define HEIGHT(X)               ((X)->h + 2 * (X)->bw)
@@ -99,12 +107,19 @@
     unsigned long sel[ColLast];
     Drawable drawable;
     GC gc;
+
+    XftColor  xftnorm[ColLast];
+    XftColor  xftsel[ColLast];
+    XftDraw  *xftdrawable;
+
+    PangoContext *pgc;
+    PangoLayout  *plo;
+    PangoFontDescription *pfd;
+
     struct {
         int ascent;
         int descent;
         int height;
-        XFontSet set;
-        XFontStruct *xfont;
     } font;
 } DC; /* draw context */
 
@@ -180,7 +195,7 @@
 static void focusin(XEvent *e);
 static void focusmon(const Arg *arg);
 static void focusstack(const Arg *arg);
-static unsigned long getcolor(const char *colstr);
+//static unsigned long getcolor(const char *colstr);
 static Bool getrootptr(int *x, int *y);
 static long getstate(Window w);
 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
@@ -477,10 +492,6 @@
     for(m = mons; m; m = m->next)
         while(m->stack)
             unmanage(m->stack, False);
-    if(dc.font.set)
-        XFreeFontSet(dpy, dc.font.set);
-    else
-        XFreeFont(dpy, dc.font.xfont);
     XUngrabKey(dpy, AnyKey, AnyModifier, root);
     XFreePixmap(dpy, dc.drawable);
     XFreeGC(dpy, dc.gc);
@@ -550,6 +561,7 @@
             if(dc.drawable != 0)
                 XFreePixmap(dpy, dc.drawable);
             dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
+            XftDrawChange(dc.xftdrawable, dc.drawable);
             updatebars();
             for(m = mons; m; m = m->next)
                 XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
@@ -767,7 +779,7 @@
         return;
     olen = strlen(text);
     h = dc.font.ascent + dc.font.descent;
-    y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
+    y = dc.y;
     x = dc.x + (h / 2);
     /* shorten text if necessary */
     for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--);
@@ -776,11 +788,8 @@
     memcpy(buf, text, len);
     if(len < olen)
         for(i = len; i && i > len - 3; buf[--i] = '.');
-    XSetForeground(dpy, dc.gc, col[invert ? ColBG : 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);
+    pango_layout_set_text(dc.plo, text, len);
+    pango_xft_render_layout(dc.xftdrawable, (col==dc.norm?dc.xftnorm:dc.xftsel)+(invert?ColBG:ColFG), dc.plo, x * PANGO_SCALE, y * PANGO_SCALE);
 }
 
 void
@@ -880,13 +889,13 @@
 }
 
 unsigned long
-getcolor(const char *colstr) {
+getcolor(const char *colstr, XftColor *color) {
     Colormap cmap = DefaultColormap(dpy, screen);
-    XColor color;
+    Visual *vis = DefaultVisual(dpy, screen);
 
-    if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
+    if(!XftColorAllocName(dpy,vis,cmap,colstr, color))
         die("error, cannot allocate color '%s'\n", colstr);
-    return color.pixel;
+    return color->pixel;
 }
 
 Bool
@@ -983,37 +992,19 @@
 
 void
 initfont(const char *fontstr) {
-    char *def, **missing;
-    int i, n;
+    PangoFontMetrics *metrics;
 
-    missing = NULL;
-    dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
-    if(missing) {
-        while(n--)
-            fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]);
-        XFreeStringList(missing);
-    }
-    if(dc.font.set) {
-        XFontSetExtents *font_extents;
-        XFontStruct **xfonts;
-        char **font_names;
-
-        dc.font.ascent = dc.font.descent = 0;
-        font_extents = XExtentsOfFontSet(dc.font.set);
-        n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
-        for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
-            dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent);
-            dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent);
-            xfonts++;
-        }
-    }
-    else {
-        if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
-        && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
-            die("error, cannot load font: '%s'\n", fontstr);
-        dc.font.ascent = dc.font.xfont->ascent;
-        dc.font.descent = dc.font.xfont->descent;
-    }
+    dc.pgc = pango_xft_get_context(dpy, screen);
+    dc.pfd = pango_font_description_from_string(fontstr);
+
+    metrics = pango_context_get_metrics(dc.pgc, dc.pfd, pango_language_from_string(setlocale(LC_CTYPE, "")));
+    dc.font.ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
+    dc.font.descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
+
+    pango_font_metrics_unref(metrics);
+
+    dc.plo = pango_layout_new(dc.pgc);
+    pango_layout_set_font_description(dc.plo, dc.pfd);
     dc.font.height = dc.font.ascent + dc.font.descent;
 }
 
@@ -1497,19 +1488,24 @@
     cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
     cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
     cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
+
     /* init appearance */
-    dc.norm[ColBorder] = getcolor(normbordercolor);
-    dc.norm[ColBG] = getcolor(normbgcolor);
-    dc.norm[ColFG] = getcolor(normfgcolor);
-    dc.sel[ColBorder] = getcolor(selbordercolor);
-    dc.sel[ColBG] = getcolor(selbgcolor);
-    dc.sel[ColFG] = getcolor(selfgcolor);
+        dc.norm[ColBorder] = getcolor(normbordercolor, dc.xftnorm+ColBorder);
+        dc.norm[ColBG] = getcolor(normbgcolor, dc.xftnorm+ColBG);
+        dc.norm[ColFG] = getcolor(normfgcolor, dc.xftnorm+ColFG);
+        dc.sel[ColBorder] = getcolor(selbordercolor, dc.xftsel+ColBorder);
+        dc.sel[ColBG] = getcolor(selbgcolor, dc.xftsel+ColBG);
+        dc.sel[ColFG] = getcolor(selfgcolor, dc.xftsel+ColFG);
+
     dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen));
     dc.gc = XCreateGC(dpy, root, 0, NULL);
     XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
-    if(!dc.font.set)
-        XSetFont(dpy, dc.gc, dc.font.xfont->fid);
-    /* init bars */
+
+        dc.xftdrawable = XftDrawCreate(dpy, dc.drawable, DefaultVisual(dpy,screen), DefaultColormap(dpy,screen));
+        if(!dc.xftdrawable)
+            printf("error, cannot create drawable\n");
+
+    /* init bar */
     updatebars();
     updatestatus();
     /* EWMH support per view */
@@ -1579,13 +1575,10 @@
 
 int
 textnw(const char *text, unsigned int len) {
-    XRectangle r;
-
-    if(dc.font.set) {
-        XmbTextExtents(dc.font.set, text, len, NULL, &r);
-        return r.width;
-    }
-    return XTextWidth(dc.font.xfont, text, len);
+    PangoRectangle r;
+    pango_layout_set_text(dc.plo, text, len);
+    pango_layout_get_extents(dc.plo, &r, 0);
+    return r.width / PANGO_SCALE;
 }
 
 void

PKGBUILD taken straight from the abs tree (/var/abs/community/x11/dwm):

# $Id: PKGBUILD 3138 2009-09-28 09:21:30Z spupykin $
# Maintainer: Sergej Pupykin <pupykin.s+arch@gmail.com>
# Contributor: Dag Odenhall <dag.odenhall@gmail.com>
# Contributor: Grigorios Bouzakis <grbzks@gmail.com>
# Contributor: Patrice Peterson <runiq@archlinux.us>

pkgname=dwm-xft
pkgver=5.7.2
pkgrel=1
pkgdesc="A dynamic window manager for X - with Pango support"
url="http://dwm.suckless.org"
arch=('i686' 'x86_64')
license=('MIT')
options=(zipman)
provides=(dwm=5.7.2)
conflicts=(dwm)
install=dwm.install
source=(http://code.suckless.org/dl/dwm/dwm-$pkgver.tar.gz \
    config.h
    pango.patch.dwm-5.7.2)
md5sums=('a0b8a799ddc5034dd8a818c9bd76f3a3'
         '50231ae0636093533b6824c1dfebc537'
         '12b6c450507febb48092bda4af12d7d5')

build() {
  cd $srcdir/dwm-$pkgver
  patch -Np1 -i ../pango.patch.dwm-5.7.2 || return 1

  cp $srcdir/config.h config.h

  make X11INC=/usr/include/X11 X11LIB=/usr/lib/X11 || return 1
  make PREFIX=/usr DESTDIR=$pkgdir install || return 1

  install -m644 -D LICENSE $pkgdir/usr/share/licenses/$pkgname/LICENSE && \
  install -m644 -D README $pkgdir/usr/share/doc/$pkgname/README
}

Hope this works for you. I'd put it up in the AUR, but I'm not much of a coder and can't guarantee I'll be able to maintain this as the dwm source changes. Plus, I don't use dwm ATM hmm

Edit: Corrected typo in patch (forgot semicolon after font specification).

Last edited by Runiq (2009-12-27 16:27:20)

Offline

#5 2009-12-27 17:03:26

orschiro
Member
Registered: 2009-06-04
Posts: 2,136
Website

Re: [dwm] xft support

Wow thank you for that patch.

I copied both files into a new test folder, included my config.h and the dwm.install and tried to build it with makepkg -efi.

But I get the following error:

patching file config.def.h
patching file config.mk
patching file dwm.c
Hunk #3 FAILED at 107.
Hunk #5 FAILED at 485.
Hunk #6 FAILED at 558.
Hunk #7 FAILED at 775.
patch: **** malformed patch at line 125: PANGO_SCALE, y * PANGO_SCALE);

Last edited by orschiro (2009-12-27 17:22:41)

Offline

#6 2009-12-27 18:36:38

Runiq
Member
From: Germany
Registered: 2008-10-29
Posts: 1,053

Re: [dwm] xft support

What dwm version are you using? The patch works for me using a pristine dwm-5.7.2 package taken from the abs tree (/var/abs/community/dwm/) and changing only the two files above.

I've uploaded the whole package, could you try compiling it without changing anything?

Offline

#7 2009-12-27 21:17:36

orschiro
Member
Registered: 2009-06-04
Posts: 2,136
Website

Re: [dwm] xft support

I'm using dwm-5.7.2, so it should work for me.

I tried to install your package with pacman -U and that's the error message. As you're from Germany too you should understand it. wink

[root@thinkpad dwm_xft]# pacman -U dwm-xft.pkg.tar.gz 
Lade Paketdaten...
Fehler: Fehlende Paket-Metadaten in dwm-xft.pkg.tar.gz
Fehler: 'dwm-xft.pkg.tar.gz': Ungültiges oder beschädigtes Paket

Offline

#8 2009-12-27 23:08:23

Runiq
Member
From: Germany
Registered: 2008-10-29
Posts: 1,053

Re: [dwm] xft support

Oops, I accidentally gave it a pkg.tar.gz extension, my bad - it's not a compiled package yet, just the PKGBUILD, dwm.install, pango.patch.dwm-5.7.2 and a basic config.h. Just extract and makepkg -src it to get an installable actual pkg.tar.gz package. hmm

Offline

#9 2009-12-27 23:17:28

flamelab
Member
From: Athens, Hellas (Greece)
Registered: 2007-12-26
Posts: 2,160

Re: [dwm] xft support

It would be better to upload it (the PKGBUILD + patch) on AUR smile

Offline

#10 2009-12-27 23:53:08

Runiq
Member
From: Germany
Registered: 2008-10-29
Posts: 1,053

Re: [dwm] xft support

flamelab wrote:

It would be better to upload it (the PKGBUILD + patch) on AUR smile

Okay, done.

Offline

#11 2009-12-28 07:37:15

orschiro
Member
Registered: 2009-06-04
Posts: 2,136
Website

Re: [dwm] xft support

Well Runiq,

your package works like a charme. Thank you for your great work. smile

And by the way, great idea to put it in AUR. I hope you could maintain it as long as possible.

Best regards

orschiro

Last edited by orschiro (2009-12-28 07:37:51)

Offline

#12 2009-12-28 19:48:05

ataraxia
Member
From: Pittsburgh
Registered: 2007-05-06
Posts: 1,553

Re: [dwm] xft support

There's also a dmenu-xft package in AUR, if you want to use Inconsolata with dmenu also.

Note that unlike this dwm patch, it does not use pango, but only "raw" xft, so it won't solve any encoding problems you might have.

Offline

#13 2009-12-29 07:08:36

orschiro
Member
Registered: 2009-06-04
Posts: 2,136
Website

Re: [dwm] xft support

Thanks ataraxia, nice to know about that.

But just one question. I want to apply another patch into that dwm-pango package. It is the pertag.patch. Could I simply include this patch too into the PKGBUILD and build it?

Because I tried that but I get some HUNK FAILED messages.

Offline

#14 2009-12-29 15:44:16

Runiq
Member
From: Germany
Registered: 2008-10-29
Posts: 1,053

Re: [dwm] xft support

I'm afraid you'll probably have to go through the rejected hunks yourself and look what's gone wrong. Apparently the pango patch changed some lines, but the pertag patch needed them in the original unpatched form.

I'll try applying it as soon as I have time, which will probably be around the new year. sad

Last edited by Runiq (2009-12-29 15:45:55)

Offline

#15 2009-12-29 16:41:45

orschiro
Member
Registered: 2009-06-04
Posts: 2,136
Website

Re: [dwm] xft support

I'll try applying it as soon as I have time, which will probably be around the new year. sad

No problem. It's not that necessary. But as I have no experience with coding in C I'll better wait for your package.

Thank you in advance. smile

Offline

#16 2009-12-29 17:28:13

Runiq
Member
From: Germany
Registered: 2008-10-29
Posts: 1,053

Re: [dwm] xft support

orschiro wrote:

But as I have no experience with coding in C I'll better wait for your package.

Neither have I. I basically just took the patch and fiddled with it, trying to make sense of what errors occured, and somehow managed to get the whole thing compiled. big_smile

orschiro wrote:

I want to apply another patch into that dwm-pango package. It is the pertag.patch. Could I simply include this patch too into the PKGBUILD and build it? I tried that but I get some HUNK FAILED messages.

Yeah, you just copy the patch line in the PKGBUILD and change the filename. It should compile fine - unless, of course, the two patches have conflicting lines, which seems to be the case with pango and pertag.

Offline

#17 2009-12-30 20:56:07

falconindy
Developer
From: New York, USA
Registered: 2009-10-22
Posts: 4,111
Website

Re: [dwm] xft support

Pango and pertag don't share any of the same lines, but pertag moves the code around enough that most of the chunks fail. I was feeling a little braindead after work today so I just manually patched in the rejects after the initial patch. Tastes great, less filling.

Offline

#18 2009-12-31 07:55:57

orschiro
Member
Registered: 2009-06-04
Posts: 2,136
Website

Re: [dwm] xft support

Hello falconindy,

I'm not sure whether I understand it the right way. So you took the dwm-pango package and added the pertag lines manually into dwm.c? Or first the pertag patch and then pango?

Offline

#19 2009-12-31 19:05:35

falconindy
Developer
From: New York, USA
Registered: 2009-10-22
Posts: 4,111
Website

Re: [dwm] xft support

orschiro wrote:

Hello falconindy,

I'm not sure whether I understand it the right way. So you took the dwm-pango package and added the pertag lines manually into dwm.c? Or first the pertag patch and then pango?

I've had pertag patched in for a few weeks now. It was just a matter of applying the pango patch over it.

And since Git is win, here's the patch (sans the config.mk change)

http://dpaste.com/139708/

Last edited by falconindy (2009-12-31 19:09:56)

Offline

#20 2010-01-01 18:46:31

orschiro
Member
Registered: 2009-06-04
Posts: 2,136
Website

Re: [dwm] xft support

Sorry but I still don't get it. What exactly do I have to do with your patch?

Just patch a default dwm build with it? I tried that but the only adjustment that is done, is the following:

patching file config.h
patch: **** malformed patch at line 9: "-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*";

It would give me great pleasure If you explain it detailed. Thank you. smile

Last edited by orschiro (2010-01-01 18:46:55)

Offline

#21 2010-01-01 20:24:38

ataraxia
Member
From: Pittsburgh
Registered: 2007-05-06
Posts: 1,553

Re: [dwm] xft support

Open the code with a text editor and make the changes from the patch file(s) by hand.

Really, if you don't know how to hand-patch, and especially, don't know C well enough to understand what's going on inside dwm, you should probably pick a different WM. dwm is targeted for code-understanding users.

Offline

Board footer

Powered by FluxBB