| dwm-6.1-xft-with-fallback-font.diff - sites - public wiki contents of suckless.… | |
| git clone git://git.suckless.org/sites | |
| Log | |
| Files | |
| Refs | |
| --- | |
| dwm-6.1-xft-with-fallback-font.diff (19598B) | |
| --- | |
| 1 Author: Eric Pruitt, https://github.com/ericpruitt/ | |
| 2 Description: Xft with fallback font support built on top of the Xft patch | |
| 3 written by Quentin (http://lists.suckless.org/dev/1311/18279.html). The … | |
| 4 functions were written by Damian Okrasa for the MIT/X licensed | |
| 5 (http://opensource.org/licenses/MIT) terminal emulator st | |
| 6 (http://st.suckless.org/). | |
| 7 | |
| 8 With this patch, the "font" variable in config.h is superseded by the "f… | |
| 9 variable which is a priority-ordered list of fonts that should be used to | |
| 10 render text. Here's an example "fonts" definition: | |
| 11 | |
| 12 static const char *fonts[] = { | |
| 13 "Sans:size=10.5", | |
| 14 "VL Gothic:size=10.5", | |
| 15 "WenQuanYi Micro Hei:size=10.5", | |
| 16 }; | |
| 17 | |
| 18 At least one font must be specified, and a maximum of DRW_FONT_CACHE_SIZ… | |
| 19 can be used. | |
| 20 | |
| 21 diff --git a/config.def.h b/config.def.h | |
| 22 index 875885b..eaae8f3 100644 | |
| 23 --- a/config.def.h | |
| 24 +++ b/config.def.h | |
| 25 @@ -1,7 +1,12 @@ | |
| 26 /* See LICENSE file for copyright and license details. */ | |
| 27 | |
| 28 /* appearance */ | |
| 29 -static const char font[] = "-*-terminus-medium-r-*-*-16-*-*-… | |
| 30 +static const char *fonts[] = { | |
| 31 + "Sans:size=10.5", | |
| 32 + "VL Gothic:size=10.5", | |
| 33 + "WenQuanYi Micro Hei:size=10.5", | |
| 34 +}; | |
| 35 +static const char dmenufont[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-… | |
| 36 static const char normbordercolor[] = "#444444"; | |
| 37 static const char normbgcolor[] = "#222222"; | |
| 38 static const char normfgcolor[] = "#bbbbbb"; | |
| 39 @@ -51,7 +56,7 @@ static const Layout layouts[] = { | |
| 40 | |
| 41 /* commands */ | |
| 42 static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in… | |
| 43 -static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", f… | |
| 44 +static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", d… | |
| 45 static const char *termcmd[] = { "st", NULL }; | |
| 46 | |
| 47 static Key keys[] = { | |
| 48 diff --git a/config.mk b/config.mk | |
| 49 index bc3d80e..50b2175 100644 | |
| 50 --- a/config.mk | |
| 51 +++ b/config.mk | |
| 52 @@ -11,12 +11,12 @@ X11INC = /usr/X11R6/include | |
| 53 X11LIB = /usr/X11R6/lib | |
| 54 | |
| 55 # Xinerama, comment if you don't want it | |
| 56 -XINERAMALIBS = -lXinerama | |
| 57 -XINERAMAFLAGS = -DXINERAMA | |
| 58 +#XINERAMALIBS = -lXinerama | |
| 59 +#XINERAMAFLAGS = -DXINERAMA | |
| 60 | |
| 61 # includes and libs | |
| 62 -INCS = -I${X11INC} | |
| 63 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} | |
| 64 +INCS = -I${X11INC} -I/usr/include/freetype2 | |
| 65 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} -lfontconfig -lXft | |
| 66 | |
| 67 # flags | |
| 68 CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" $… | |
| 69 diff --git a/drw.c b/drw.c | |
| 70 index b130405..36cf992 100644 | |
| 71 --- a/drw.c | |
| 72 +++ b/drw.c | |
| 73 @@ -3,10 +3,59 @@ | |
| 74 #include <stdlib.h> | |
| 75 #include <string.h> | |
| 76 #include <X11/Xlib.h> | |
| 77 +#include <X11/Xft/Xft.h> | |
| 78 | |
| 79 #include "drw.h" | |
| 80 #include "util.h" | |
| 81 | |
| 82 +#define UTF_INVALID 0xFFFD | |
| 83 +#define UTF_SIZ 4 | |
| 84 + | |
| 85 +static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0x… | |
| 86 +static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0x… | |
| 87 +static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800,… | |
| 88 +static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF,… | |
| 89 + | |
| 90 +static long | |
| 91 +utf8decodebyte(const char c, size_t *i) { | |
| 92 + for(*i = 0; *i < (UTF_SIZ + 1); ++(*i)) | |
| 93 + if(((unsigned char)c & utfmask[*i]) == utfbyte[*i]) | |
| 94 + return (unsigned char)c & ~utfmask[*i]; | |
| 95 + return 0; | |
| 96 +} | |
| 97 + | |
| 98 +static size_t | |
| 99 +utf8validate(long *u, size_t i) { | |
| 100 + if(!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0x… | |
| 101 + *u = UTF_INVALID; | |
| 102 + for(i = 1; *u > utfmax[i]; ++i) | |
| 103 + ; | |
| 104 + return i; | |
| 105 +} | |
| 106 + | |
| 107 +static size_t | |
| 108 +utf8decode(const char *c, long *u, size_t clen) { | |
| 109 + size_t i, j, len, type; | |
| 110 + long udecoded; | |
| 111 + | |
| 112 + *u = UTF_INVALID; | |
| 113 + if(!clen) | |
| 114 + return 0; | |
| 115 + udecoded = utf8decodebyte(c[0], &len); | |
| 116 + if(!BETWEEN(len, 1, UTF_SIZ)) | |
| 117 + return 1; | |
| 118 + for(i = 1, j = 1; i < clen && j < len; ++i, ++j) { | |
| 119 + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type… | |
| 120 + if(type != 0) | |
| 121 + return j; | |
| 122 + } | |
| 123 + if(j < len) | |
| 124 + return 0; | |
| 125 + *u = udecoded; | |
| 126 + utf8validate(u, len); | |
| 127 + return len; | |
| 128 +} | |
| 129 + | |
| 130 Drw * | |
| 131 drw_create(Display *dpy, int screen, Window root, unsigned int w, unsig… | |
| 132 Drw *drw = (Drw *)calloc(1, sizeof(Drw)); | |
| 133 @@ -19,6 +68,7 @@ drw_create(Display *dpy, int screen, Window root, unsi… | |
| 134 drw->h = h; | |
| 135 drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy… | |
| 136 drw->gc = XCreateGC(dpy, root, 0, NULL); | |
| 137 + drw->fontcount = 0; | |
| 138 XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMit… | |
| 139 return drw; | |
| 140 } | |
| 141 @@ -36,56 +86,79 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h)… | |
| 142 | |
| 143 void | |
| 144 drw_free(Drw *drw) { | |
| 145 + size_t i; | |
| 146 + for (i = 0; i < drw->fontcount; i++) { | |
| 147 + drw_font_free(drw->fonts[i]); | |
| 148 + } | |
| 149 XFreePixmap(drw->dpy, drw->drawable); | |
| 150 XFreeGC(drw->dpy, drw->gc); | |
| 151 free(drw); | |
| 152 } | |
| 153 | |
| 154 Fnt * | |
| 155 -drw_font_create(Display *dpy, const char *fontname) { | |
| 156 +drw_font_create(Drw *drw, const char *fontname, FcPattern *fontpattern)… | |
| 157 Fnt *font; | |
| 158 - char *def, **missing; | |
| 159 - int n; | |
| 160 | |
| 161 - font = (Fnt *)calloc(1, sizeof(Fnt)); | |
| 162 - if(!font) | |
| 163 + if (!(fontname || fontpattern)) | |
| 164 + die("No font specified.\n"); | |
| 165 + | |
| 166 + if (!(font = (Fnt *)calloc(1, sizeof(Fnt)))) | |
| 167 return NULL; | |
| 168 - font->set = XCreateFontSet(dpy, fontname, &missing, &n, &def); | |
| 169 - if(missing) { | |
| 170 - while(n--) | |
| 171 - fprintf(stderr, "drw: missing fontset: %s\n", m… | |
| 172 - XFreeStringList(missing); | |
| 173 - } | |
| 174 - if(font->set) { | |
| 175 - XFontStruct **xfonts; | |
| 176 - char **font_names; | |
| 177 - XExtentsOfFontSet(font->set); | |
| 178 - n = XFontsOfFontSet(font->set, &xfonts, &font_names); | |
| 179 - while(n--) { | |
| 180 - font->ascent = MAX(font->ascent, (*xfonts)->asc… | |
| 181 - font->descent = MAX(font->descent,(*xfonts)->de… | |
| 182 - xfonts++; | |
| 183 + | |
| 184 + if (fontname) { | |
| 185 + // Using the pattern found at font->xfont->pattern does… | |
| 186 + // the same substitution results as using the pattern r… | |
| 187 + // FcNameParse; using the latter results in the desired… | |
| 188 + // behaviour whereas the former just results in | |
| 189 + // missing-character-rectangles being drawn, at least w… | |
| 190 + if (!(font->xfont = XftFontOpenName(drw->dpy, drw->scre… | |
| 191 + !(font->pattern = FcNameParse((FcChar8 *) fontname)… | |
| 192 + if (font->xfont) | |
| 193 + XftFontClose(font->dpy, font->xfont); | |
| 194 + fprintf(stderr, "error, cannot load font: '%s'\… | |
| 195 + } | |
| 196 + } else if (fontpattern) { | |
| 197 + if (!(font->xfont = XftFontOpenPattern(drw->dpy, fontpa… | |
| 198 + fprintf(stderr, "error, cannot load font patter… | |
| 199 + } else { | |
| 200 + font->pattern = NULL; | |
| 201 } | |
| 202 } | |
| 203 - else { | |
| 204 - if(!(font->xfont = XLoadQueryFont(dpy, fontname)) | |
| 205 - && !(font->xfont = XLoadQueryFont(dpy, "fixed"))) | |
| 206 - die("error, cannot load font: '%s'\n", fontname… | |
| 207 - font->ascent = font->xfont->ascent; | |
| 208 - font->descent = font->xfont->descent; | |
| 209 + | |
| 210 + if (!font->xfont) { | |
| 211 + free(font); | |
| 212 + return NULL; | |
| 213 } | |
| 214 + | |
| 215 + font->ascent = font->xfont->ascent; | |
| 216 + font->descent = font->xfont->descent; | |
| 217 font->h = font->ascent + font->descent; | |
| 218 + font->dpy = drw->dpy; | |
| 219 return font; | |
| 220 } | |
| 221 | |
| 222 void | |
| 223 -drw_font_free(Display *dpy, Fnt *font) { | |
| 224 +drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount) { | |
| 225 + size_t i; | |
| 226 + Fnt *font; | |
| 227 + for (i = 0; i < fontcount && drw->fontcount < DRW_FONT_CACHE_SI… | |
| 228 + if ((font = drw_font_create(drw, fonts[i], NULL))) { | |
| 229 + drw->fonts[drw->fontcount++] = font; | |
| 230 + } | |
| 231 + } | |
| 232 + | |
| 233 + if (i != fontcount) { | |
| 234 + die("Font cache exhausted.\n"); | |
| 235 + } | |
| 236 +} | |
| 237 + | |
| 238 +void | |
| 239 +drw_font_free(Fnt *font) { | |
| 240 if(!font) | |
| 241 return; | |
| 242 - if(font->set) | |
| 243 - XFreeFontSet(dpy, font->set); | |
| 244 - else | |
| 245 - XFreeFont(dpy, font->xfont); | |
| 246 + if(font->pattern) | |
| 247 + FcPatternDestroy(font->pattern); | |
| 248 + XftFontClose(font->dpy, font->xfont); | |
| 249 free(font); | |
| 250 } | |
| 251 | |
| 252 @@ -93,7 +166,7 @@ Clr * | |
| 253 drw_clr_create(Drw *drw, const char *clrname) { | |
| 254 Clr *clr; | |
| 255 Colormap cmap; | |
| 256 - XColor color; | |
| 257 + Visual *vis; | |
| 258 | |
| 259 if(!drw) | |
| 260 return NULL; | |
| 261 @@ -101,9 +174,10 @@ drw_clr_create(Drw *drw, const char *clrname) { | |
| 262 if(!clr) | |
| 263 return NULL; | |
| 264 cmap = DefaultColormap(drw->dpy, drw->screen); | |
| 265 - if(!XAllocNamedColor(drw->dpy, cmap, clrname, &color, &color)) | |
| 266 + vis = DefaultVisual(drw->dpy, drw->screen); | |
| 267 + if(!XftColorAllocName(drw->dpy, vis, cmap, clrname, &clr->rgb)) | |
| 268 die("error, cannot allocate color '%s'\n", clrname); | |
| 269 - clr->rgb = color.pixel; | |
| 270 + clr->pix = clr->rgb.pixel; | |
| 271 return clr; | |
| 272 } | |
| 273 | |
| 274 @@ -114,14 +188,8 @@ drw_clr_free(Clr *clr) { | |
| 275 } | |
| 276 | |
| 277 void | |
| 278 -drw_setfont(Drw *drw, Fnt *font) { | |
| 279 - if(drw) | |
| 280 - drw->font = font; | |
| 281 -} | |
| 282 - | |
| 283 -void | |
| 284 drw_setscheme(Drw *drw, ClrScheme *scheme) { | |
| 285 - if(drw && scheme) | |
| 286 + if(drw && scheme) | |
| 287 drw->scheme = scheme; | |
| 288 } | |
| 289 | |
| 290 @@ -129,46 +197,158 @@ void | |
| 291 drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int fi… | |
| 292 int dx; | |
| 293 | |
| 294 - if(!drw || !drw->font || !drw->scheme) | |
| 295 + if(!drw || !drw->fontcount || !drw->scheme) | |
| 296 return; | |
| 297 - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb… | |
| 298 - dx = (drw->font->ascent + drw->font->descent + 2) / 4; | |
| 299 + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->pix… | |
| 300 + dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4; | |
| 301 if(filled) | |
| 302 XFillRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y… | |
| 303 else if(empty) | |
| 304 XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y… | |
| 305 } | |
| 306 | |
| 307 -void | |
| 308 +int | |
| 309 drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const … | |
| 310 - char buf[256]; | |
| 311 - int i, tx, ty, th, len, olen; | |
| 312 + char buf[1024]; | |
| 313 + int tx, ty, th; | |
| 314 Extnts tex; | |
| 315 + Colormap cmap; | |
| 316 + Visual *vis; | |
| 317 + XftDraw *d; | |
| 318 + Fnt *curfont, *nextfont; | |
| 319 + size_t i, len; | |
| 320 + int utf8strlen, utf8charlen, render; | |
| 321 + long utf8codepoint = 0; | |
| 322 + const char *utf8str; | |
| 323 + FcCharSet *fccharset; | |
| 324 + FcPattern *fcpattern; | |
| 325 + FcPattern *match; | |
| 326 + XftResult result; | |
| 327 + int charexists = 0; | |
| 328 | |
| 329 - if(!drw || !drw->scheme) | |
| 330 - return; | |
| 331 - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->fg->rgb… | |
| 332 - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); | |
| 333 - if(!text || !drw->font) | |
| 334 - return; | |
| 335 - olen = strlen(text); | |
| 336 - drw_font_getexts(drw->font, text, olen, &tex); | |
| 337 - th = drw->font->ascent + drw->font->descent; | |
| 338 - ty = y + (h / 2) - (th / 2) + drw->font->ascent; | |
| 339 - tx = x + (h / 2); | |
| 340 - /* shorten text if necessary */ | |
| 341 - for(len = MIN(olen, sizeof buf); len && (tex.w > w - tex.h || w… | |
| 342 - drw_font_getexts(drw->font, text, len, &tex); | |
| 343 - if(!len) | |
| 344 - return; | |
| 345 - memcpy(buf, text, len); | |
| 346 - if(len < olen) | |
| 347 - for(i = len; i && i > len - 3; buf[--i] = '.'); | |
| 348 - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb… | |
| 349 - if(drw->font->set) | |
| 350 - XmbDrawString(drw->dpy, drw->drawable, drw->font->set, … | |
| 351 - else | |
| 352 - XDrawString(drw->dpy, drw->drawable, drw->gc, tx, ty, b… | |
| 353 + if (!(render = x || y || w || h)) { | |
| 354 + w = ~w; | |
| 355 + } | |
| 356 + | |
| 357 + if (!drw || !drw->scheme) { | |
| 358 + return 0; | |
| 359 + } else if (render) { | |
| 360 + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme-… | |
| 361 + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, … | |
| 362 + } | |
| 363 + | |
| 364 + if (!text || !drw->fontcount) { | |
| 365 + return 0; | |
| 366 + } else if (render) { | |
| 367 + cmap = DefaultColormap(drw->dpy, drw->screen); | |
| 368 + vis = DefaultVisual(drw->dpy, drw->screen); | |
| 369 + d = XftDrawCreate(drw->dpy, drw->drawable, vis, cmap); | |
| 370 + } | |
| 371 + | |
| 372 + curfont = drw->fonts[0]; | |
| 373 + while (1) { | |
| 374 + utf8strlen = 0; | |
| 375 + utf8str = text; | |
| 376 + nextfont = NULL; | |
| 377 + while (*text) { | |
| 378 + utf8charlen = utf8decode(text, &utf8codepoint, … | |
| 379 + for (i = 0; i < drw->fontcount; i++) { | |
| 380 + charexists = charexists || XftCharExist… | |
| 381 + if (charexists) { | |
| 382 + if (drw->fonts[i] == curfont) { | |
| 383 + utf8strlen += utf8charl… | |
| 384 + text += utf8charlen; | |
| 385 + } else { | |
| 386 + nextfont = drw->fonts[i… | |
| 387 + } | |
| 388 + break; | |
| 389 + } | |
| 390 + } | |
| 391 + | |
| 392 + if (!charexists || (nextfont && nextfont != cur… | |
| 393 + break; | |
| 394 + } else { | |
| 395 + charexists = 0; | |
| 396 + } | |
| 397 + } | |
| 398 + | |
| 399 + if (utf8strlen) { | |
| 400 + drw_font_getexts(curfont, utf8str, utf8strlen, … | |
| 401 + /* shorten text if necessary */ | |
| 402 + for(len = MIN(utf8strlen, (sizeof buf) - 1); le… | |
| 403 + drw_font_getexts(curfont, utf8str, len,… | |
| 404 + | |
| 405 + if (len) { | |
| 406 + memcpy(buf, utf8str, len); | |
| 407 + buf[len] = '\0'; | |
| 408 + if(len < utf8strlen) | |
| 409 + for(i = len; i && i > len - 3; … | |
| 410 + | |
| 411 + if (render) { | |
| 412 + th = curfont->ascent + curfont-… | |
| 413 + ty = y + (h / 2) - (th / 2) + c… | |
| 414 + tx = x + (h / 2); | |
| 415 + XftDrawStringUtf8(d, invert ? &… | |
| 416 + } | |
| 417 + | |
| 418 + x += tex.w; | |
| 419 + w -= tex.w; | |
| 420 + } | |
| 421 + } | |
| 422 + | |
| 423 + if (!*text) { | |
| 424 + break; | |
| 425 + } else if (nextfont) { | |
| 426 + charexists = 0; | |
| 427 + curfont = nextfont; | |
| 428 + } else { | |
| 429 + // Regardless of whether or not a fallback font… | |
| 430 + // character must be drawn. | |
| 431 + charexists = 1; | |
| 432 + | |
| 433 + if (drw->fontcount >= DRW_FONT_CACHE_SIZE) { | |
| 434 + continue; | |
| 435 + } | |
| 436 + | |
| 437 + fccharset = FcCharSetCreate(); | |
| 438 + FcCharSetAddChar(fccharset, utf8codepoint); | |
| 439 + | |
| 440 + if (!drw->fonts[0]->pattern) { | |
| 441 + // Refer to the comment in drw_font_cre… | |
| 442 + // information. | |
| 443 + die("The first font in the cache must b… | |
| 444 + } | |
| 445 + | |
| 446 + fcpattern = FcPatternDuplicate(drw->fonts[0]->p… | |
| 447 + FcPatternAddCharSet(fcpattern, FC_CHARSET, fcch… | |
| 448 + FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue… | |
| 449 + | |
| 450 + FcConfigSubstitute(NULL, fcpattern, FcMatchPatt… | |
| 451 + FcDefaultSubstitute(fcpattern); | |
| 452 + match = XftFontMatch(drw->dpy, drw->screen, fcp… | |
| 453 + | |
| 454 + FcCharSetDestroy(fccharset); | |
| 455 + FcPatternDestroy(fcpattern); | |
| 456 + | |
| 457 + if (match) { | |
| 458 + curfont = drw_font_create(drw, NULL, ma… | |
| 459 + if (curfont && XftCharExists(drw->dpy, … | |
| 460 + drw->fonts[drw->fontcount++] = … | |
| 461 + } else { | |
| 462 + if (curfont) { | |
| 463 + drw_font_free(curfont); | |
| 464 + } | |
| 465 + curfont = drw->fonts[0]; | |
| 466 + } | |
| 467 + } | |
| 468 + } | |
| 469 + } | |
| 470 + | |
| 471 + if (render) { | |
| 472 + XftDrawDestroy(d); | |
| 473 + } | |
| 474 + | |
| 475 + return x; | |
| 476 } | |
| 477 | |
| 478 void | |
| 479 @@ -182,19 +362,13 @@ drw_map(Drw *drw, Window win, int x, int y, unsign… | |
| 480 | |
| 481 void | |
| 482 drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts … | |
| 483 - XRectangle r; | |
| 484 + XGlyphInfo ext; | |
| 485 | |
| 486 if(!font || !text) | |
| 487 return; | |
| 488 - if(font->set) { | |
| 489 - XmbTextExtents(font->set, text, len, NULL, &r); | |
| 490 - tex->w = r.width; | |
| 491 - tex->h = r.height; | |
| 492 - } | |
| 493 - else { | |
| 494 - tex->h = font->ascent + font->descent; | |
| 495 - tex->w = XTextWidth(font->xfont, text, len); | |
| 496 - } | |
| 497 + XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, le… | |
| 498 + tex->h = font->h; | |
| 499 + tex->w = ext.xOff; | |
| 500 } | |
| 501 | |
| 502 unsigned int | |
| 503 diff --git a/drw.h b/drw.h | |
| 504 index a5f34e0..02bfefc 100644 | |
| 505 --- a/drw.h | |
| 506 +++ b/drw.h | |
| 507 @@ -1,7 +1,9 @@ | |
| 508 /* See LICENSE file for copyright and license details. */ | |
| 509 +#define DRW_FONT_CACHE_SIZE 32 | |
| 510 | |
| 511 typedef struct { | |
| 512 - unsigned long rgb; | |
| 513 + unsigned long pix; | |
| 514 + XftColor rgb; | |
| 515 } Clr; | |
| 516 | |
| 517 typedef struct { | |
| 518 @@ -9,11 +11,12 @@ typedef struct { | |
| 519 } Cur; | |
| 520 | |
| 521 typedef struct { | |
| 522 + Display *dpy; | |
| 523 int ascent; | |
| 524 int descent; | |
| 525 unsigned int h; | |
| 526 - XFontSet set; | |
| 527 - XFontStruct *xfont; | |
| 528 + XftFont *xfont; | |
| 529 + FcPattern *pattern; | |
| 530 } Fnt; | |
| 531 | |
| 532 typedef struct { | |
| 533 @@ -30,7 +33,8 @@ typedef struct { | |
| 534 Drawable drawable; | |
| 535 GC gc; | |
| 536 ClrScheme *scheme; | |
| 537 - Fnt *font; | |
| 538 + size_t fontcount; | |
| 539 + Fnt *fonts[DRW_FONT_CACHE_SIZE]; | |
| 540 } Drw; | |
| 541 | |
| 542 typedef struct { | |
| 543 @@ -44,8 +48,9 @@ void drw_resize(Drw *drw, unsigned int w, unsigned int… | |
| 544 void drw_free(Drw *drw); | |
| 545 | |
| 546 /* Fnt abstraction */ | |
| 547 -Fnt *drw_font_create(Display *dpy, const char *fontname); | |
| 548 -void drw_font_free(Display *dpy, Fnt *font); | |
| 549 +Fnt *drw_font_create(Drw *drw, const char *fontname, FcPattern *fontpat… | |
| 550 +void drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount); | |
| 551 +void drw_font_free(Fnt *font); | |
| 552 void drw_font_getexts(Fnt *font, const char *text, unsigned int len, Ex… | |
| 553 unsigned int drw_font_getexts_width(Fnt *font, const char *text, unsign… | |
| 554 | |
| 555 @@ -63,7 +68,7 @@ void drw_setscheme(Drw *drw, ClrScheme *scheme); | |
| 556 | |
| 557 /* Drawing functions */ | |
| 558 void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, i… | |
| 559 -void drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, c… | |
| 560 +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, co… | |
| 561 | |
| 562 /* Map functions */ | |
| 563 void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsign… | |
| 564 diff --git a/dwm.c b/dwm.c | |
| 565 index f896170..169adcb 100644 | |
| 566 --- a/dwm.c | |
| 567 +++ b/dwm.c | |
| 568 @@ -39,6 +39,7 @@ | |
| 569 #ifdef XINERAMA | |
| 570 #include <X11/extensions/Xinerama.h> | |
| 571 #endif /* XINERAMA */ | |
| 572 +#include <X11/Xft/Xft.h> | |
| 573 | |
| 574 #include "drw.h" | |
| 575 #include "util.h" | |
| 576 @@ -54,7 +55,7 @@ | |
| 577 #define WIDTH(X) ((X)->w + 2 * (X)->bw) | |
| 578 #define HEIGHT(X) ((X)->h + 2 * (X)->bw) | |
| 579 #define TAGMASK ((1 << LENGTH(tags)) - 1) | |
| 580 -#define TEXTW(X) (drw_font_getexts_width(drw->font, X, s… | |
| 581 +#define TEXTW(X) (drw_text(drw, 0, 0, 0, 0, (X), 0) + dr… | |
| 582 | |
| 583 /* enums */ | |
| 584 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ | |
| 585 @@ -263,7 +264,6 @@ static Cur *cursor[CurLast]; | |
| 586 static ClrScheme scheme[SchemeLast]; | |
| 587 static Display *dpy; | |
| 588 static Drw *drw; | |
| 589 -static Fnt *fnt; | |
| 590 static Monitor *mons, *selmon; | |
| 591 static Window root; | |
| 592 | |
| 593 @@ -474,7 +474,6 @@ cleanup(void) { | |
| 594 drw_cur_free(drw, cursor[CurNormal]); | |
| 595 drw_cur_free(drw, cursor[CurResize]); | |
| 596 drw_cur_free(drw, cursor[CurMove]); | |
| 597 - drw_font_free(dpy, fnt); | |
| 598 drw_clr_free(scheme[SchemeNorm].border); | |
| 599 drw_clr_free(scheme[SchemeNorm].bg); | |
| 600 drw_clr_free(scheme[SchemeNorm].fg); | |
| 601 @@ -792,7 +791,7 @@ focus(Client *c) { | |
| 602 detachstack(c); | |
| 603 attachstack(c); | |
| 604 grabbuttons(c, True); | |
| 605 - XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border-… | |
| 606 + XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border-… | |
| 607 setfocus(c); | |
| 608 } | |
| 609 else { | |
| 610 @@ -1040,7 +1039,7 @@ manage(Window w, XWindowAttributes *wa) { | |
| 611 | |
| 612 wc.border_width = c->bw; | |
| 613 XConfigureWindow(dpy, w, CWBorderWidth, &wc); | |
| 614 - XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->rgb); | |
| 615 + XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->pix); | |
| 616 configure(c); /* propagates border_width, if size doesn't chang… | |
| 617 updatewindowtype(c); | |
| 618 updatesizehints(c); | |
| 619 @@ -1505,13 +1504,14 @@ setup(void) { | |
| 620 | |
| 621 /* init screen */ | |
| 622 screen = DefaultScreen(dpy); | |
| 623 - root = RootWindow(dpy, screen); | |
| 624 - fnt = drw_font_create(dpy, font); | |
| 625 sw = DisplayWidth(dpy, screen); | |
| 626 sh = DisplayHeight(dpy, screen); | |
| 627 - bh = fnt->h + 2; | |
| 628 + root = RootWindow(dpy, screen); | |
| 629 drw = drw_create(dpy, screen, root, sw, sh); | |
| 630 - drw_setfont(drw, fnt); | |
| 631 + drw_load_fonts(drw, fonts, LENGTH(fonts)); | |
| 632 + if (!drw->fontcount) | |
| 633 + die("No fonts could be loaded.\n"); | |
| 634 + bh = drw->fonts[0]->h + 2; | |
| 635 updategeom(); | |
| 636 /* init atoms */ | |
| 637 wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); | |
| 638 @@ -1685,7 +1685,7 @@ unfocus(Client *c, Bool setfocus) { | |
| 639 if(!c) | |
| 640 return; | |
| 641 grabbuttons(c, False); | |
| 642 - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->rgb); | |
| 643 + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->pix); | |
| 644 if(setfocus) { | |
| 645 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentT… | |
| 646 XDeleteProperty(dpy, root, netatom[NetActiveWindow]); | |
| 647 diff --git a/util.h b/util.h | |
| 648 index 033700c..f7ce721 100644 | |
| 649 --- a/util.h | |
| 650 +++ b/util.h | |
| 651 @@ -2,5 +2,6 @@ | |
| 652 | |
| 653 #define MAX(A, B) ((A) > (B) ? (A) : (B)) | |
| 654 #define MIN(A, B) ((A) < (B) ? (A) : (B)) | |
| 655 +#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) | |
| 656 | |
| 657 void die(const char *errstr, ...); |