You are not logged in.

#1401 2015-02-08 20:23:20

ANOKNUSA
Member
Registered: 2010-10-22
Posts: 2,141

Re: DWM Hackers Unite! Share (or request) dwm patches.

spupy wrote:

Anyone heard of patch that introduces a jump list for tags? Similar to vim's jump list where I can press <C-o> to jump backwards in a list of visited positions. Right now I have a key for switching between the current and the last visited tag, but it's a bit uncomfortable to use with too many tags.

There's no patch that I know of, but you don't need a patch. What you're looking for is info on how to properly use tags. wink Tags are just identifiers for windows, which are used to pull windows  into view when needed and hide them from view when not needed. In other words, tags are marks. "Switch to previous tag" is supposed to be used to switch to the previous view, a "view" being a combination of visible tags.

Rather than using tags as separate workspaces and switching between them, the intended behavior is to have two separate views---only one of which is visible at a time---and to dynamically change the combination of windows on the screen by adding and removing tags. This way you could, for example, have a single "sticky" window stay in the master section while switching between different combinations of windows in the stack, or vice versa, or any combination of windows you like.

Offline

#1402 2015-02-08 20:29:01

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,424
Website

Re: DWM Hackers Unite! Share (or request) dwm patches.

<slightly offtopic>I much prefer linking to CLS's original (and uncredited) post on this, fortunately preserved on the Wayback machine: http://web.archive.org/web/201201201619 … nt/dwm-faq


Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#1403 2015-02-08 20:45:56

frank604
Member
From: BC, Canada
Registered: 2011-04-20
Posts: 1,212

Re: DWM Hackers Unite! Share (or request) dwm patches.

I haven't heard of a jump list for tags but then again I've never looked for this feature.  I only have a few tags (5ish) so it is manageable.  I also use run or raise, maybe it'll help you too? http://dwm.suckless.org/patches/runorraise

Offline

#1404 2015-02-19 05:29:00

parazyd
Member
From: Amsterdam
Registered: 2012-10-14
Posts: 259
Website

Re: DWM Hackers Unite! Share (or request) dwm patches.

Is there a patch for the bar that would make it look like this:

1 2 3 4 [] > titleofwindow < dwm-6.0

while the left part (tags) and the right part are of one color and the part where the window title is of another color?
Basically, what I am looking for is this, only in dwm - not bspwm.

Offline

#1405 2015-02-28 21:57:52

jsbennett86
Member
Registered: 2014-09-08
Posts: 4

Re: DWM Hackers Unite! Share (or request) dwm patches.

You don't actually need a patch to change those characters. config.h allows you to change the characters shown for different display modes (e.g., you can change "[]" to "[] >"). The "dwm 6.0" text can be changed using xsetroot via script, which is what people use to set status bars.

You will also need the statuscolors patch if you wanna have colors like that example.

Hope this helps!

Offline

#1406 2015-03-08 07:50:09

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,424
Website

Re: DWM Hackers Unite! Share (or request) dwm patches.

It seems Anslem is going to reintroduce the Xft patch, which is great.

I have been updating all of the patches I use against HEAD just to see what will still work. Using the candidate Xft patch, (which I guess is this one) works fine. Trying to apply holomorph's statuscolors patch over that, however, fails because of changes to drw.c.

The relevant lines from drw_text that cause the error are:

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->pix : &drw->scheme->fg->pix, drw->font->xfont, tx, ty, (XftChar8 *)buf, len);
XftDrawDestroy(d);

and the error is with the invert call:

drw.c: In function ‘drw_text’:
drw.c:154:23: error: ‘invert’ undeclared (first use in this function)
  XftDrawStringUtf8(d, invert ? &drw->scheme->bg->pix : &drw->scheme->fg->pix, drw->font->xfont, tx, ty, (XftChar8 *)buf, len);
                       ^

I have tried playing around with it, but have had no joy. I gather the error is a simple enough one, but I haven't been able to grok what that block is doing.

Has anyone successfully patched Xft and statuscolours against HEAD?


Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#1407 2015-03-08 11:49:52

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: DWM Hackers Unite! Share (or request) dwm patches.

The patch is still undergoing changes, according to these two threads: [1] and the followup [2] (which you linked to as well)

The patch attached to [1] is:

From 62b45075044c75633ceb0d4601f41be435e4b65e Mon Sep 17 00:00:00 2001
From: Eric Pruitt <eric.pruitt@gmail.com>
Date: Sun, Mar 1 15:34:57 2015 -0800
Subject: [PATCH] Add Xft and follback-fonts support to graphics lib

---
 config.def.h |    9 +-
 config.mk    |    4 +-
 drw.c        |  336 ++++++++++++++++++++++++++++++++++++++++++++--------------
 drw.h        |   19 ++--
 dwm.c        |   20 ++--
 util.h       |    1 +
 6 files changed, 287 insertions(+), 102 deletions(-)

diff --git a/config.def.h b/config.def.h
index 875885b..eaae8f3 100644
--- a/config.def.h
+++ b/config.def.h
@@ -1,7 +1,12 @@
 /* See LICENSE file for copyright and license details. */
 
 /* appearance */
-static const char font[]            = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*";
+static const char *fonts[] = {
+    "Sans:size=10.5",
+    "VL Gothic:size=10.5",
+    "WenQuanYi Micro Hei:size=10.5",
+};
+static const char dmenufont[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*";
 static const char normbordercolor[] = "#444444";
 static const char normbgcolor[]     = "#222222";
 static const char normfgcolor[]     = "#bbbbbb";
@@ -51,7 +56,7 @@ static const Layout layouts[] = {
 
 /* commands */
 static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
-static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
+static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
 static const char *termcmd[]  = { "st", NULL };
 
 static Key keys[] = {
diff --git a/config.mk b/config.mk
index bc3d80e..cf95913 100644
--- a/config.mk
+++ b/config.mk
@@ -15,8 +15,8 @@ XINERAMALIBS  = -lXinerama
 XINERAMAFLAGS = -DXINERAMA
 
 # includes and libs
-INCS = -I${X11INC}
-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS}
+INCS = -I${X11INC} -I/usr/include/freetype2
+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} -lfontconfig -lXft
 
 # flags
 CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
diff --git a/drw.c b/drw.c
index b130405..e4365dd 100644
--- a/drw.c
+++ b/drw.c
@@ -3,10 +3,59 @@
 #include <stdlib.h>
 #include <string.h>
 #include <X11/Xlib.h>
+#include <X11/Xft/Xft.h>
 
 #include "drw.h"
 #include "util.h"
 
+#define UTF_INVALID 0xFFFD
+#define UTF_SIZ 4
+
+static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80,    0, 0xC0, 0xE0, 0xF0};
+static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
+static const long utfmin[UTF_SIZ + 1] = {       0,    0,  0x80,  0x800,  0x10000};
+static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
+
+static long
+utf8decodebyte(const char c, size_t *i) {
+	for(*i = 0; *i < (UTF_SIZ + 1); ++(*i))
+		if(((unsigned char)c & utfmask[*i]) == utfbyte[*i])
+			return (unsigned char)c & ~utfmask[*i];
+	return 0;
+}
+
+static size_t
+utf8validate(long *u, size_t i) {
+	if(!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
+		*u = UTF_INVALID;
+	for(i = 1; *u > utfmax[i]; ++i)
+		;
+	return i;
+}
+
+static size_t
+utf8decode(const char *c, long *u, size_t clen) {
+	size_t i, j, len, type;
+	long udecoded;
+
+	*u = UTF_INVALID;
+	if(!clen)
+		return 0;
+	udecoded = utf8decodebyte(c[0], &len);
+	if(!BETWEEN(len, 1, UTF_SIZ))
+		return 1;
+	for(i = 1, j = 1; i < clen && j < len; ++i, ++j) {
+		udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
+		if(type != 0)
+			return j;
+	}
+	if(j < len)
+		return 0;
+	*u = udecoded;
+	utf8validate(u, len);
+	return len;
+}
+
 Drw *
 drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) {
 	Drw *drw = (Drw *)calloc(1, sizeof(Drw));
@@ -19,6 +68,7 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h
 	drw->h = h;
 	drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
 	drw->gc = XCreateGC(dpy, root, 0, NULL);
+	drw->fontcount = 0;
 	XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
 	return drw;
 }
@@ -36,56 +86,79 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) {
 
 void
 drw_free(Drw *drw) {
+	size_t i;
+	for (i = 0; i < drw->fontcount; i++) {
+		drw_font_free(drw->fonts[i]);
+	}
 	XFreePixmap(drw->dpy, drw->drawable);
 	XFreeGC(drw->dpy, drw->gc);
 	free(drw);
 }
 
 Fnt *
-drw_font_create(Display *dpy, const char *fontname) {
+drw_font_create(Drw *drw, const char *fontname, FcPattern *fontpattern) {
 	Fnt *font;
-	char *def, **missing;
-	int n;
 
-	font = (Fnt *)calloc(1, sizeof(Fnt));
-	if(!font)
+	if (!(fontname || fontpattern))
+		die("No font specified.\n");
+
+	if (!(font = (Fnt *)calloc(1, sizeof(Fnt))))
 		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++;
+
+	if (fontname) {
+		// Using the pattern found at font->xfont->pattern does not yield same
+		// the same substitution results as using the pattern returned by
+		// FcNameParse; using the latter results in the desired fallback
+		// behaviour whereas the former just results in
+		// missing-character-rectangles being drawn, at least with some fonts.
+		if (!(font->xfont = XftFontOpenName(drw->dpy, drw->screen, fontname)) ||
+		    !(font->pattern = FcNameParse((FcChar8 *) fontname))) {
+			if (font->xfont) {
+				XftFontClose(drw->dpy, font->xfont);
+				font->xfont = NULL;
+			}
+			fprintf(stderr, "error, cannot load font: '%s'\n", fontname);
+		}
+	} else if (fontpattern) {
+		if (!(font->xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
+			fprintf(stderr, "error, cannot load font pattern.\n");
+		} else {
+			font->pattern = NULL;
 		}
 	}
-	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) {
+		free(font);
+		return NULL;
 	}
+
+	font->ascent = font->xfont->ascent;
+	font->descent = font->xfont->descent;
 	font->h = font->ascent + font->descent;
+	font->dpy = drw->dpy;
 	return font;
 }
 
 void
-drw_font_free(Display *dpy, Fnt *font) {
+drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount) {
+	size_t i;
+	Fnt *font;
+	for (i = 0; i < fontcount; i++) {
+		if (drw->fontcount >= DRW_FONT_CACHE_SIZE) {
+			die("Font cache exhausted.\n");
+		} else if ((font = drw_font_create(drw, fonts[i], NULL))) {
+			drw->fonts[drw->fontcount++] = font;
+		}
+	}
+}
+
+void
+drw_font_free(Fnt *font) {
 	if(!font)
 		return;
-	if(font->set)
-		XFreeFontSet(dpy, font->set);
-	else
-		XFreeFont(dpy, font->xfont);
+	if(font->pattern)
+		FcPatternDestroy(font->pattern);
+	XftFontClose(font->dpy, font->xfont);
 	free(font);
 }
 
@@ -93,7 +166,7 @@ Clr *
 drw_clr_create(Drw *drw, const char *clrname) {
 	Clr *clr;
 	Colormap cmap;
-	XColor color;
+	Visual *vis;
 
 	if(!drw)
 		return NULL;
@@ -101,9 +174,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;
 }
 
@@ -114,14 +188,8 @@ drw_clr_free(Clr *clr) {
 }
 
 void
-drw_setfont(Drw *drw, Fnt *font) {
-	if(drw)
-		drw->font = font;
-}
-
-void
 drw_setscheme(Drw *drw, ClrScheme *scheme) {
-	if(drw && scheme) 
+	if(drw && scheme)
 		drw->scheme = scheme;
 }
 
@@ -129,46 +197,158 @@ void
 drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert) {
 	int dx;
 
-	if(!drw || !drw->font || !drw->scheme)
+	if(!drw || !drw->fontcount || !drw->scheme)
 		return;
-	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb : drw->scheme->fg->rgb);
-	dx = (drw->font->ascent + drw->font->descent + 2) / 4;
+	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->pix : drw->scheme->fg->pix);
+	dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4;
 	if(filled)
 		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx+1, dx+1);
 	else if(empty)
 		XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx, dx);
 }
 
-void
+int
 drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert) {
-	char buf[256];
-	int i, tx, ty, th, len, olen;
+	char buf[1024];
+	int tx, ty, th;
 	Extnts tex;
+	Colormap cmap;
+	Visual *vis;
+	XftDraw *d;
+	Fnt *curfont, *nextfont;
+	size_t i, len;
+	int utf8strlen, utf8charlen, render;
+	long utf8codepoint = 0;
+	const char *utf8str;
+	FcCharSet *fccharset;
+	FcPattern *fcpattern;
+	FcPattern *match;
+	XftResult result;
+	int charexists = 0;
 
-	if(!drw || !drw->scheme)
-		return;
-	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->fg->rgb : drw->scheme->bg->rgb);
-	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;
-	ty = y + (h / 2) - (th / 2) + drw->font->ascent;
-	tx = x + (h / 2);
-	/* shorten text if necessary */
-	for(len = MIN(olen, sizeof buf); len && (tex.w > w - tex.h || w < tex.h); len--)
-		drw_font_getexts(drw->font, text, len, &tex);
-	if(!len)
-		return;
-	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);
+	if (!(render = x || y || w || h)) {
+		w = ~w;
+	}
+
+	if (!drw || !drw->scheme) {
+		return 0;
+	} else if (render) {
+		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->fontcount) {
+		return 0;
+	} else if (render) {
+		cmap = DefaultColormap(drw->dpy, drw->screen);
+		vis = DefaultVisual(drw->dpy, drw->screen);
+		d = XftDrawCreate(drw->dpy, drw->drawable, vis, cmap);
+	}
+
+	curfont = drw->fonts[0];
+	while (1) {
+		utf8strlen = 0;
+		utf8str = text;
+		nextfont = NULL;
+		while (*text) {
+			utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
+			for (i = 0; i < drw->fontcount; i++) {
+				charexists = charexists || XftCharExists(drw->dpy, drw->fonts[i]->xfont, utf8codepoint);
+				if (charexists) {
+					if (drw->fonts[i] == curfont) {
+						utf8strlen += utf8charlen;
+						text += utf8charlen;
+					} else {
+						nextfont = drw->fonts[i];
+					}
+					break;
+				}
+			}
+
+			if (!charexists || (nextfont && nextfont != curfont)) {
+				break;
+			} else {
+				charexists = 0;
+			}
+		}
+
+		if (utf8strlen) {
+			drw_font_getexts(curfont, utf8str, utf8strlen, &tex);
+			/* shorten text if necessary */
+			for(len = MIN(utf8strlen, (sizeof buf) - 1); len && (tex.w > w - drw->fonts[0]->h || w < drw->fonts[0]->h); len--)
+				drw_font_getexts(curfont, utf8str, len, &tex);
+
+			if (len) {
+				memcpy(buf, utf8str, len);
+				buf[len] = '\0';
+				if(len < utf8strlen)
+					for(i = len; i && i > len - 3; buf[--i] = '.');
+
+				if (render) {
+					th = curfont->ascent + curfont->descent;
+					ty = y + (h / 2) - (th / 2) + curfont->ascent;
+					tx = x + (h / 2);
+					XftDrawStringUtf8(d, invert ? &drw->scheme->bg->rgb : &drw->scheme->fg->rgb, curfont->xfont, tx, ty, (XftChar8 *)buf, len);
+				}
+
+				x += tex.w;
+				w -= tex.w;
+			}
+		}
+
+		if (!*text) {
+			break;
+		} else if (nextfont) {
+			charexists = 0;
+			curfont = nextfont;
+		} else {
+			// Regardless of whether or not a fallback font is found, the
+			// character must be drawn.
+			charexists = 1;
+
+			if (drw->fontcount >= DRW_FONT_CACHE_SIZE) {
+				continue;
+			}
+
+			fccharset = FcCharSetCreate();
+			FcCharSetAddChar(fccharset, utf8codepoint);
+
+			if (!drw->fonts[0]->pattern) {
+				// Refer to the comment in drw_font_create for more
+				// information.
+				die("The first font in the cache must be loaded from a font string.\n");
+			}
+
+			fcpattern = FcPatternDuplicate(drw->fonts[0]->pattern);
+			FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
+			FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
+
+			FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
+			FcDefaultSubstitute(fcpattern);
+			match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
+
+			FcCharSetDestroy(fccharset);
+			FcPatternDestroy(fcpattern);
+
+			if (match) {
+				curfont = drw_font_create(drw, NULL, match);
+				if (curfont && XftCharExists(drw->dpy, curfont->xfont, utf8codepoint)) {
+					drw->fonts[drw->fontcount++] = curfont;
+				} else {
+					if (curfont) {
+						drw_font_free(curfont);
+					}
+					curfont = drw->fonts[0];
+				}
+			}
+		}
+	}
+
+	if (render) {
+		XftDrawDestroy(d);
+	}
+
+	return x;
 }
 
 void
@@ -182,19 +362,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..02bfefc 100644
--- a/drw.h
+++ b/drw.h
@@ -1,7 +1,9 @@
 /* See LICENSE file for copyright and license details. */
+#define DRW_FONT_CACHE_SIZE 32
 
 typedef struct {
-	unsigned long rgb;
+	unsigned long pix;
+	XftColor rgb;
 } Clr;
 
 typedef struct {
@@ -9,11 +11,12 @@ typedef struct {
 } Cur;
 
 typedef struct {
+	Display *dpy;
 	int ascent;
 	int descent;
 	unsigned int h;
-	XFontSet set;
-	XFontStruct *xfont;
+	XftFont *xfont;
+	FcPattern *pattern;
 } Fnt;
 
 typedef struct {
@@ -30,7 +33,8 @@ typedef struct {
 	Drawable drawable;
 	GC gc;
 	ClrScheme *scheme;
-	Fnt *font;
+	size_t fontcount;
+	Fnt *fonts[DRW_FONT_CACHE_SIZE];
 } Drw;
 
 typedef struct {
@@ -44,8 +48,9 @@ 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);
-void drw_font_free(Display *dpy, Fnt *font);
+Fnt *drw_font_create(Drw *drw, const char *fontname, FcPattern *fontpattern);
+void drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount);
+void drw_font_free(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);
 
@@ -63,7 +68,7 @@ void drw_setscheme(Drw *drw, ClrScheme *scheme);
 
 /* Drawing functions */
 void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert);
-void drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert);
+int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert);
 
 /* Map functions */
 void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
diff --git a/dwm.c b/dwm.c
index f896170..169adcb 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"
@@ -54,7 +55,7 @@
 #define WIDTH(X)                ((X)->w + 2 * (X)->bw)
 #define HEIGHT(X)               ((X)->h + 2 * (X)->bw)
 #define TAGMASK                 ((1 << LENGTH(tags)) - 1)
-#define TEXTW(X)                (drw_font_getexts_width(drw->font, X, strlen(X)) + drw->font->h)
+#define TEXTW(X)                (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h)
 
 /* enums */
 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
@@ -263,7 +264,6 @@ static Cur *cursor[CurLast];
 static ClrScheme scheme[SchemeLast];
 static Display *dpy;
 static Drw *drw;
-static Fnt *fnt;
 static Monitor *mons, *selmon;
 static Window root;
 
@@ -474,7 +474,6 @@ cleanup(void) {
 	drw_cur_free(drw, cursor[CurNormal]);
 	drw_cur_free(drw, cursor[CurResize]);
 	drw_cur_free(drw, cursor[CurMove]);
-	drw_font_free(dpy, fnt);
 	drw_clr_free(scheme[SchemeNorm].border);
 	drw_clr_free(scheme[SchemeNorm].bg);
 	drw_clr_free(scheme[SchemeNorm].fg);
@@ -792,7 +791,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 +1039,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);
@@ -1505,13 +1504,14 @@ setup(void) {
 
 	/* init screen */
 	screen = DefaultScreen(dpy);
-	root = RootWindow(dpy, screen);
-	fnt = drw_font_create(dpy, font);
 	sw = DisplayWidth(dpy, screen);
 	sh = DisplayHeight(dpy, screen);
-	bh = fnt->h + 2;
+	root = RootWindow(dpy, screen);
 	drw = drw_create(dpy, screen, root, sw, sh);
-	drw_setfont(drw, fnt);
+	drw_load_fonts(drw, fonts, LENGTH(fonts));
+	if (!drw->fontcount)
+		die("No fonts could be loaded.\n");
+	bh = drw->fonts[0]->h + 2;
 	updategeom();
 	/* init atoms */
 	wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
@@ -1685,7 +1685,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]);
diff --git a/util.h b/util.h
index 033700c..f7ce721 100644
--- a/util.h
+++ b/util.h
@@ -2,5 +2,6 @@
 
 #define MAX(A, B)               ((A) > (B) ? (A) : (B))
 #define MIN(A, B)               ((A) < (B) ? (A) : (B))
+#define BETWEEN(X, A, B)        ((A) <= (X) && (X) <= (B))
 
 void die(const char *errstr, ...);
-- 
1.7.10.4

The statuscolors patch you linked to removes the invert so you can do the same. Unless you want to keep invert, which will require some more changes.


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#1408 2015-03-08 16:30:59

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,424
Website

Re: DWM Hackers Unite! Share (or request) dwm patches.

Thanks Unia: Eric's patch includes fallback fonts, which is an added complexity that I don't require (and I am not convinced will be accepted).

I tried removing invert, but that generates more errors:

XftDrawStringUtf8(d ? &drw->scheme->bg->pix : &drw->scheme->fg->pix, drw->font->xfont, tx, ty, (XftChar8 *)buf, len);

Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#1409 2015-03-08 16:32:55

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: DWM Hackers Unite! Share (or request) dwm patches.

jasonwryan wrote:

I tried removing invert, but that generates more errors:

XftDrawStringUtf8(d ? &drw->scheme->bg->pix : &drw->scheme->fg->pix, drw->font->xfont, tx, ty, (XftChar8 *)buf, len);

This works:

XftDrawStringUtf8(d, &drw->scheme->fg->pix, drw->font->xfont, tx, ty, (XftChar8 *)buf, len);

The invert was part of what is called a ternary operator, if you want to read up on it.

Last edited by Unia (2015-03-08 16:33:46)


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#1410 2015-03-08 17:22:26

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,424
Website

Re: DWM Hackers Unite! Share (or request) dwm patches.

Thanks Unia. I am familiar with the ternary operator from Awk, but the preceding block and the d, are way outside my comfort range.

I'm still getting errors, but I can track those down over time.


Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#1411 2015-03-11 02:52:11

JLloyd13
Member
Registered: 2012-06-24
Posts: 107

Re: DWM Hackers Unite! Share (or request) dwm patches.

Hi, I've having a few problems getting my DWM set up patched with useless gap on DWM 6.0. Going to be upfront, this is on Debian, not Arch, so I'm not sure if I'm allowed to ask, but I will and this can be deleted/moved no hard feelings if I'm not. I'm posting here because most of the stuff I found was on this thread. I tried manually patching in the patch on the website for 5.9 but it doesn't make horizontal gaps. I did the googleing work and find some stuff on pages 24 and 25 of this thread- but most of the links are broken. What I was able to find was Unia's patch, so I tried to patch that in my hand. I couldn't find the last hunk in my dwm.c- I assumed it was because the patch is made for his setup and mine didn't have it. But it won't compile as is. 

cleaning
rm -f dwm dwm.o dwm-6.0.tar.gz
dwm build options:
CFLAGS   = -std=c99 -pedantic -Wall -DVERSION="6.0" -DXINERAMA
LDFLAGS  = -s -lc -lX11 -lXinerama
CC       = cc
CC dwm.c
cc -c -std=c99 -pedantic -Wall -DVERSION=\"6.0\" -DXINERAMA dwm.c
In file included from dwm.c:291:0:
config.h:35:2: warning: initialization makes integer from pointer without a cast
  { "[]=",      tile },    /* first entry is default */
  ^
config.h:35:2: warning: (near initialization for ‘layouts[0].addgaps’)
config.h:35:2: error: initializer element is not computable at load time
config.h:35:2: error: (near initialization for ‘layouts[0].addgaps’)
config.h:36:2: warning: initialization makes integer from pointer without a cast
  { "><>",      NULL },    /* no layout function means floating behavior */
  ^
config.h:36:2: warning: (near initialization for ‘layouts[1].addgaps’)
config.h:37:2: warning: initialization makes integer from pointer without a cast
  { "[M]",      monocle },
  ^
config.h:37:2: warning: (near initialization for ‘layouts[2].addgaps’)
config.h:37:2: error: initializer element is not computable at load time
config.h:37:2: error: (near initialization for ‘layouts[2].addgaps’)
config.h:38:2: warning: initialization makes integer from pointer without a cast
  { "TTT",      bstack },
  ^
config.h:38:2: warning: (near initialization for ‘layouts[3].addgaps’)
config.h:38:2: error: initializer element is not computable at load time
config.h:38:2: error: (near initialization for ‘layouts[3].addgaps’)
config.h:39:2: warning: initialization makes integer from pointer without a cast
  { "===",      bstackhoriz },
  ^
config.h:39:2: warning: (near initialization for ‘layouts[4].addgaps’)
config.h:39:2: error: initializer element is not computable at load time
config.h:39:2: error: (near initialization for ‘layouts[4].addgaps’)
config.h:40:2: warning: initialization makes integer from pointer without a cast
  { "+++",      gaplessgrid },
  ^
config.h:40:2: warning: (near initialization for ‘layouts[5].addgaps’)
config.h:40:2: error: initializer element is not computable at load time
config.h:40:2: error: (near initialization for ‘layouts[5].addgaps’)
dwm.c: In function ‘keypress’:
dwm.c:1090:2: warning: ‘XKeycodeToKeysym’ is deprecated (declared at /usr/include/X11/Xlib.h:1699) [-Wdeprecated-declarations]
  keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
  ^
Makefile:18: recipe for target 'dwm.o' failed
make: *** [dwm.o] Error 1
jlloyd13@a880gz:~/dwm-6.0$ 

Should I post my dwm.c or would that be excessive/ unwanted?

Offline

#1412 2015-03-11 10:24:31

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: DWM Hackers Unite! Share (or request) dwm patches.

Update your config.h, each layout now requires a boolean whether gaps should be used:

{ "[]=", True, tile },
....

Last edited by Unia (2015-03-11 10:25:14)


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#1413 2015-03-11 23:27:36

va7sdf
Member
From: Victoria, BC, Canada
Registered: 2012-06-17
Posts: 6

Re: DWM Hackers Unite! Share (or request) dwm patches.

I've been using Arch and dwm for a few years now and finally decided to try my hand at creating a patch.  It's inspired by the drop-down game console or drawer like terminals, such as tilda and guake, and borrows much of its code from Jokerboy's scratchpad patch.  My motivation was to have an unobtrusive terminal, like scratchpad, in which I could run things like a Jekyll and check on the build periodically.  I've seen other similar solutions for dwm (and other wm's), from using tilda or guake with rules to scripts that rely on other tools, but wanted something native with minimal eyecandy.  I also prefer the window appear at the bottom of the screen rather than top so that's why my patch is named popupterm.

The patch, 01-dwm-6.1-popupterm.diff, is available at Bitbucket and here's a screenshot of a vanilla dwm with the patch installed:

thumb_popupterm-20150310.png

  • This patch assumes the terminal should be the width of the monitor and there is a variable in the config.h that controls the relative height;

  • If you set resizehints to false, then you won't get a jagged right edge like the screenshot shows;

  • I use the st terminal but the patch spawns xterm; that's why the differences between console fonts in the screenshot;

  • I created the patch against the latest pull from suckless' dwm repo.  I trust the patch will work on 6.0 as well;

  • I only have one monitor so hopefully things don't go sideways if trying the patch in a multi-monitor setup; and

  • I've also tried it on my patched dwm and it works with the following: moveresize, three column, selfrestart, viewontag, gridmode, nametag, push, and pertag.

Last edited by va7sdf (2015-03-12 03:39:27)


Arch64/DWM
SDF asciimap

Offline

#1414 2015-03-11 23:31:05

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: DWM Hackers Unite! Share (or request) dwm patches.

Very nice!


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#1415 2015-03-15 13:26:33

parazyd
Member
From: Amsterdam
Registered: 2012-10-14
Posts: 259
Website

Re: DWM Hackers Unite! Share (or request) dwm patches.

When in tiled mode - it possible to resize one window and make others rezise according to that one in real time?

Because now,when I try to resize a window, it just becomes a floating window and other windows resize to fit the screen while ignoring the resized window.

Last edited by parazyd (2015-03-15 13:30:29)

Offline

#1416 2015-03-15 16:01:50

ANOKNUSA
Member
Registered: 2010-10-22
Posts: 2,141

Re: DWM Hackers Unite! Share (or request) dwm patches.

parazyd wrote:

When in tiled mode - it possible to resize one window and make others rezise according to that one in real time?

Because now,when I try to resize a window, it just becomes a floating window and other windows resize to fit the screen while ignoring the resized window.

This isn't a support thread. The short answer is "Stop using the mouse." The slightly longer answer is that one does not resize windows in dwm, but the two regions of the screen that are filled by windows. You can have a look at the cfacts patch, but even with that patch windows will continue to switch to floating if you manipulate them with the mouse.

Offline

#1417 2015-03-15 16:14:41

wildfowl
Banned
Registered: 2014-10-16
Posts: 82

Re: DWM Hackers Unite! Share (or request) dwm patches.

I originally started with AWM but I found all the extensions and LUA scripting somewhat unnecessary. I since switched to dwm and the baseline improvment in the performance factor was immediately evident. I've only just recently gained a tiny bit of confidence to change and/or add a few custom functions.

dwm has alot going for it and a fair bit that still needs doing.
dwm crashes often and the overall experience is rather rigid and less than fluidic.

Offline

#1418 2015-03-15 16:46:35

ANOKNUSA
Member
Registered: 2010-10-22
Posts: 2,141

Re: DWM Hackers Unite! Share (or request) dwm patches.

wildfowl wrote:

dwm crashes often...

Open a separate support thread. I know this is a rather grandiose statement, but dwm doesn't crash or freeze. It just doesn't. Ever. I've had it fail to start after improperly applying a patch, but in the years I've used it I've never seen it crash.

dwm has alot going for it and a fair bit that still needs doing.

dwm is effectively feature-complete. That's why so many patches exist---as far as the project lead (and much of the suckless community) is concerned dwm has and does everything it's supposed to. Xft support just got added to the development HEAD a couple days ago, making it the first "new" feature in maybe four years (I think nmaster was the last major feature, added back in 2011) and the first commit to the code since November. What you see is what you get. That's the beauty of it. wink

Offline

#1419 2015-03-15 17:08:06

parazyd
Member
From: Amsterdam
Registered: 2012-10-14
Posts: 259
Website

Re: DWM Hackers Unite! Share (or request) dwm patches.

ANOKNUSA wrote:
parazyd wrote:

When in tiled mode - it possible to resize one window and make others rezise according to that one in real time?

Because now,when I try to resize a window, it just becomes a floating window and other windows resize to fit the screen while ignoring the resized window.

This isn't a support thread. The short answer is "Stop using the mouse." The slightly longer answer is that one does not resize windows in dwm, but the two regions of the screen that are filled by windows. You can have a look at the cfacts patch, but even with that patch windows will continue to switch to floating if you manipulate them with the mouse.

This will do. Thanks.
On a side note: The thread title clearly states "Share or request dwm patches". That's what I did. I don't see why you're telling me that this isn't a support thread...

Offline

#1420 2015-03-15 17:46:40

ANOKNUSA
Member
Registered: 2010-10-22
Posts: 2,141

Re: DWM Hackers Unite! Share (or request) dwm patches.

This thread is where people can announce new patches they've made and get feedback from people trying them, or ask if a patch offering particular functionality exists. It's part of the "Community Contributions" sub-forum. It's not a place for questions about how to use basic dwm features.

Offline

#1421 2015-03-21 01:34:09

timebomb
Member
Registered: 2015-03-21
Posts: 1

Re: DWM Hackers Unite! Share (or request) dwm patches.

i've taken the dwm-patches repo and added the following to it:

- pertag2 - to allow for configuring tags in the config.h
- systray
- focusurgent
- a scratchpad for popup terminals
- runorraise
- status2d for allowing drawings in the status bar
- fancybar for showing all windows in a tag
- an im layout for having the pidgin buddylist on the right

https://github.com/fishman/dwm-patches
https://github.com/fishman/dwmstatus

it's probably a smart idea to replace dwmstatus with a python script or something, but i'm probably going to try adding mpd_async for it just for the sake of it.

https://raw.githubusercontent.com/fishm … screen.png

--mod note: replaced img with url, please see forum guidelines on image sizes.  Trilby --

Last edited by Trilby (2015-03-21 01:45:50)

Offline

#1422 2015-03-24 17:26:18

KOMON
Member
Registered: 2013-01-25
Posts: 13

Re: DWM Hackers Unite! Share (or request) dwm patches.

Hey all, I spent an hour or two hand patching the statuscolors patch to work with the latest commit to HEAD on the Suckless repo.

The Xft support that got added in is basically the same as the usual xft patch, but a lot of function names were changed and since they got rid of the old DC struct there was quite a few manual changes to make to make the patch work.

Here's a gist with the patch https://gist.github.com/KOMON/0a4819f030e4d6f84ebe

I don't really know much about Xft, so please inform me if I've made any glaring omissions (everything seems to work so far for me)

Many thanks to Unia, whose 6.0 xft statuscolors patch I used to make this one

EDIT: Also, does anybody know how I can get ahold of the usual maintainer for ther statuscolors patch so I can make this workaround known to him?

Last edited by KOMON (2015-03-24 17:41:24)

Offline

#1423 2015-03-24 17:53:32

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: DWM Hackers Unite! Share (or request) dwm patches.

You can push it to the Suckless wiki: http://suckless.org/wiki


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#1424 2015-04-21 17:50:46

holomorph
Member
Registered: 2012-10-19
Posts: 6

Re: DWM Hackers Unite! Share (or request) dwm patches.

Here are my lame attempts at new pango (markup) and statuscolours patches against master (Xft support)

https://gist.github.com/holomorph/c3e3097fbe9f738530b5
https://gist.github.com/holomorph/d99905acf73a2c44c061

Offline

#1425 2015-05-14 10:04:09

mkredz
Member
Registered: 2015-05-14
Posts: 1

Re: DWM Hackers Unite! Share (or request) dwm patches.

KOMON wrote:

Hey all, I spent an hour or two hand patching the statuscolors patch to work with the latest commit to HEAD on the Suckless repo.

The Xft support that got added in is basically the same as the usual xft patch, but a lot of function names were changed and since they got rid of the old DC struct there was quite a few manual changes to make to make the patch work.

Here's a gist with the patch https://gist.github.com/KOMON/0a4819f030e4d6f84ebe

I don't really know much about Xft, so please inform me if I've made any glaring omissions (everything seems to work so far for me)

Many thanks to Unia, whose 6.0 xft statuscolors patch I used to make this one

EDIT: Also, does anybody know how I can get ahold of the usual maintainer for ther statuscolors patch so I can make this workaround known to him?

Could you put your config.h to see how it works? Because if I try to add "static const char colors[NUMCOLORS][ColLast][8]" like in the patches of previous versions, it says "error: ‘ColLast’ undeclared here (not in a function)"

Offline

Board footer

Powered by FluxBB