From 8c4eaccf16b533cefe34b090e970ff66911a2a7b Mon Sep 17 00:00:00 2001 From: bakkeby Date: Thu, 11 Jun 2020 19:42:00 +0200 Subject: [PATCH] Adding pango patch (ref. #10) Text from original patch: Using pango markup for status text Use a single font. Removed some code utf8 code from drw. Created for pango 1.44. Older versions might not have getter for font height, ascent + descent can be used instead. All texts are rendered with pango but only status is with markup. Increased stext size (in case a lot of markup is used). MIN/MAX is already defined (didn't redefine them). --- README.md | 5 ++ config.def.h | 4 ++ config.mk | 9 ++- drw.c | 168 +++++++++++++++++++++++++++++++++++++++++++ drw.h | 26 +++++++ dwm.c | 94 ++++++++++++++++++++++-- patch/status2d.c | 26 +++++++ patch/statuscolors.c | 4 ++ patches.def.h | 21 ++++++ util.h | 4 ++ 10 files changed, 351 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index fc92429..76cfb1f 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t ### Changelog: +2020-06-11 - Added the pango patch + 2020-06-10 - Added the staticstatus patch 2020-05-31 - Added the keymodes patch @@ -309,6 +311,9 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t - [onlyquitonempty](https://dwm.suckless.org/patches/onlyquitonempty/) - makes it so dwm will only exit via quit() if no windows are open (in order to prevent accidental loss of work) + - [pango](https://dwm.suckless.org/patches/pango/) + - adds simple markup for status messages using pango markup + - [pertag](https://dwm.suckless.org/patches/pertag/) - adds nmaster, mfact, layouts and more per tag rather than per monitor diff --git a/config.def.h b/config.def.h index 89df086..4820f55 100644 --- a/config.def.h +++ b/config.def.h @@ -47,7 +47,11 @@ static const int quit_empty_window_count = 2; /* only allow dwm to quit if no #if EXTRABAR_PATCH static const char statussep = ';'; /* separator between status bars */ #endif // EXTRABAR_PATCH +#if PANGO_PATCH +static const char font[] = "monospace 10"; +#else static const char *fonts[] = { "monospace:size=10" }; +#endif // PANGO_PATCH static const char dmenufont[] = "monospace:size=10"; static char normfgcolor[] = "#bbbbbb"; diff --git a/config.mk b/config.mk index 888fe47..49e5263 100644 --- a/config.mk +++ b/config.mk @@ -26,6 +26,10 @@ FREETYPEINC = /usr/include/freetype2 # Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH #MPDCLIENT = -lmpdclient +# Uncomment for the pango patch / PANGO_PATCH +#PANGOINC = `pkg-config --cflags xft pango pangoxft` +#PANGOLIB = `pkg-config --libs xft pango pangoxft` + # Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH #XEXTLIB = -lXext @@ -33,9 +37,8 @@ FREETYPEINC = /usr/include/freetype2 #XCBLIBS = -lX11-xcb -lxcb -lxcb-res # includes and libs -INCS = -I${X11INC} -I${FREETYPEINC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} - +INCS = -I${X11INC} -I${FREETYPEINC} ${PANGOINC} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${PANGOLIB} # flags CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} diff --git a/drw.c b/drw.c index bc32a50..ea17da9 100644 --- a/drw.c +++ b/drw.c @@ -9,6 +9,7 @@ #include "drw.h" #include "util.h" +#if !PANGO_PATCH #define UTF_INVALID 0xFFFD #define UTF_SIZ 4 @@ -60,6 +61,7 @@ utf8decode(const char *c, long *u, size_t clen) return len; } +#endif // PANGO_PATCH Drw * #if ALPHA_PATCH @@ -116,6 +118,41 @@ drw_free(Drw *drw) free(drw); } +#if PANGO_PATCH +/* This function is an implementation detail. Library users should use + * drw_font_create instead. + */ +static Fnt * +xfont_create(Drw *drw, const char *fontname) +{ + Fnt *font; + PangoFontMap *fontmap; + PangoContext *context; + PangoFontDescription *desc; + PangoFontMetrics *metrics; + + if (!fontname) { + die("no font specified."); + } + + font = ecalloc(1, sizeof(Fnt)); + font->dpy = drw->dpy; + + fontmap = pango_xft_get_font_map(drw->dpy, drw->screen); + context = pango_font_map_create_context(fontmap); + desc = pango_font_description_from_string(fontname); + font->layout = pango_layout_new(context); + pango_layout_set_font_description(font->layout, desc); + + metrics = pango_context_get_metrics(context, desc, pango_language_from_string ("en-us")); + font->h = pango_font_metrics_get_height(metrics) / PANGO_SCALE; + + pango_font_metrics_unref(metrics); + g_object_unref(context); + + return font; +} +#else /* This function is an implementation detail. Library users should use * drw_fontset_create instead. */ @@ -173,18 +210,38 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) return font; } +#endif // PANGO_PATCH static void xfont_free(Fnt *font) { if (!font) return; + #if PANGO_PATCH + if (font->layout) + g_object_unref(font->layout); + #else if (font->pattern) FcPatternDestroy(font->pattern); XftFontClose(font->dpy, font->xfont); + #endif // PANGO_PATCH free(font); } +#if PANGO_PATCH +Fnt* +drw_font_create(Drw* drw, const char font[]) +{ + Fnt *fnt = NULL; + + if (!drw || !font) + return NULL; + + fnt = xfont_create(drw, font); + + return (drw->font = fnt); +} +#else Fnt* drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) { @@ -202,7 +259,16 @@ drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) } return (drw->fonts = ret); } +#endif // PANGO_PATCH +#if PANGO_PATCH +void +drw_font_free(Fnt *font) +{ + if (font) + xfont_free(font); +} +#else void drw_fontset_free(Fnt *font) { @@ -211,6 +277,7 @@ drw_fontset_free(Fnt *font) xfont_free(font); } } +#endif // PANGO_PATCH void drw_clr_create( @@ -279,12 +346,14 @@ drw_scm_create( return ret; } +#if !PANGO_PATCH void drw_setfontset(Drw *drw, Fnt *set) { if (drw) drw->fonts = set; } +#endif // PANGO_PATCH void drw_setscheme(Drw *drw, Clr *scm) @@ -305,6 +374,72 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); } +#if PANGO_PATCH +int +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup) +{ + char buf[1024]; + int ty; + unsigned int ew; + XftDraw *d = NULL; + size_t i, len; + int render = x || y || w || h; + + if (!drw || (render && !drw->scheme) || !text || !drw->font) + return 0; + + if (!render) { + w = ~w; + } else { + XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + #if ALPHA_PATCH + d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); + #else + d = XftDrawCreate(drw->dpy, drw->drawable, + DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen)); + #endif // ALPHA_PATCH + x += lpad; + w -= lpad; + } + + len = strlen(text); + + if (len) { + drw_font_getexts(drw->font, text, len, &ew, NULL, markup); + /* shorten text if necessary */ + for (len = MIN(len, sizeof(buf) - 1); len && ew > w; len--) + drw_font_getexts(drw->font, text, len, &ew, NULL, markup); + + if (len) { + memcpy(buf, text, len); + buf[len] = '\0'; + if (len < strlen(text)) + for (i = len; i && i > len - 3; buf[--i] = '.') + ; /* NOP */ + + if (render) { + ty = y + (h - drw->font->h) / 2; + if (markup) + pango_layout_set_markup(drw->font->layout, buf, len); + else + pango_layout_set_text(drw->font->layout, buf, len); + pango_xft_render_layout(d, &drw->scheme[invert ? ColBg : ColFg], + drw->font->layout, x * PANGO_SCALE, ty * PANGO_SCALE); + if (markup) /* clear markup attributes */ + pango_layout_set_attributes(drw->font->layout, NULL); + } + x += ew; + w -= ew; + } + } + if (d) + XftDrawDestroy(d); + + return x + (render ? w : 0); +} +#else int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) { @@ -439,6 +574,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp return x + (render ? w : 0); } +#endif // PANGO_PATCH void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) @@ -450,6 +586,15 @@ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) XSync(drw->dpy, False); } +#if PANGO_PATCH +unsigned int +drw_font_getwidth(Drw *drw, const char *text, Bool markup) +{ + if (!drw || !drw->font || !text) + return 0; + return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup); +} +#else unsigned int drw_fontset_getwidth(Drw *drw, const char *text) { @@ -457,7 +602,29 @@ drw_fontset_getwidth(Drw *drw, const char *text) return 0; return drw_text(drw, 0, 0, 0, 0, 0, text, 0); } +#endif // PANGO_PATCH +#if PANGO_PATCH +void +drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup) +{ + if (!font || !text) + return; + + PangoRectangle r; + if (markup) + pango_layout_set_markup(font->layout, text, len); + else + pango_layout_set_text(font->layout, text, len); + pango_layout_get_extents(font->layout, 0, &r); + if (markup) /* clear markup attributes */ + pango_layout_set_attributes(font->layout, NULL); + if (w) + *w = r.width / PANGO_SCALE; + if (h) + *h = font->h; +} +#else void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) { @@ -472,6 +639,7 @@ drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, if (h) *h = font->h; } +#endif // PANGO_PATCH Cur * drw_cur_create(Drw *drw, int shape) diff --git a/drw.h b/drw.h index e3934f2..ae46f9a 100644 --- a/drw.h +++ b/drw.h @@ -1,5 +1,10 @@ /* See LICENSE file for copyright and license details. */ +#if PANGO_PATCH +#include +#include +#endif // PANGO_PATCH + typedef struct { Cursor cursor; } Cur; @@ -7,9 +12,13 @@ typedef struct { typedef struct Fnt { Display *dpy; unsigned int h; + #if PANGO_PATCH + PangoLayout *layout; + #else XftFont *xfont; FcPattern *pattern; struct Fnt *next; + #endif // PANGO_PATCH } Fnt; #if FLOAT_BORDER_COLOR_PATCH @@ -32,7 +41,11 @@ typedef struct { Drawable drawable; GC gc; Clr *scheme; + #if PANGO_PATCH + Fnt *font; + #else Fnt *fonts; + #endif // PANGO_PATCH } Drw; /* Drawable abstraction */ @@ -45,10 +58,17 @@ void drw_resize(Drw *drw, unsigned int w, unsigned int h); void drw_free(Drw *drw); /* Fnt abstraction */ +#if PANGO_PATCH +Fnt *drw_font_create(Drw* drw, const char font[]); +void drw_font_free(Fnt* set); +unsigned int drw_font_getwidth(Drw *drw, const char *text, Bool markup); +void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup); +#else Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); void drw_fontset_free(Fnt* set); unsigned int drw_fontset_getwidth(Drw *drw, const char *text); void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); +#endif // PANGO_PATCH /* Colorscheme abstraction */ void drw_clr_create( @@ -83,12 +103,18 @@ Cur *drw_cur_create(Drw *drw, int shape); void drw_cur_free(Drw *drw, Cur *cursor); /* Drawing context manipulation */ +#if !PANGO_PATCH void drw_setfontset(Drw *drw, Fnt *set); +#endif // PANGO_PATCH void drw_setscheme(Drw *drw, Clr *scm); /* Drawing functions */ void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); +#if PANGO_PATCH +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup); +#else int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); +#endif // PANGO_PATCH /* 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 78b29ae..a770804 100644 --- a/dwm.c +++ b/dwm.c @@ -45,6 +45,10 @@ #include "drw.h" #include "util.h" +#if PANGO_PATCH +#include +#endif // PANGO_PATCH + #if SPAWNCMD_PATCH #include #include @@ -83,7 +87,12 @@ #else #define TAGMASK ((1 << LENGTH(tags)) - 1) #endif // SCRATCHPADS_PATCH +#if PANGO_PATCH +#define TEXTW(X) (drw_font_getwidth(drw, (X), False) + lrpad) +#define TEXTWM(X) (drw_font_getwidth(drw, (X), True) + lrpad) +#else #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) +#endif // PANGO_PATCH /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ @@ -444,7 +453,7 @@ static void zoom(const Arg *arg); /* variables */ static const char broken[] = "broken"; -#if STATUS2D_PATCH && !STATUSCOLORS_PATCH +#if PANGO_PATCH || STATUS2D_PATCH && !STATUSCOLORS_PATCH static char stext[1024]; #else static char stext[256]; @@ -847,6 +856,8 @@ buttonpress(XEvent *e) text[i] = '\0'; #if STATUS2D_PATCH && !STATUSCOLORS_PATCH xc += status2dtextlength(text); + #elif PANGO_PATCH + xc += TEXTWM(text) - lrpad; #else xc += TEXTW(text) - lrpad; #endif // STATUS2D_PATCH @@ -960,7 +971,11 @@ cleanup(void) free(scheme[i]); free(scheme); XDestroyWindow(dpy, wmcheckwin); + #if PANGO_PATCH + drw_font_free(drw->font); + #else drw_fontset_free(drw->fonts); + #endif // PANGO_PATCH drw_free(drw); XSync(dpy, False); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); @@ -1429,9 +1444,17 @@ drawbar(Monitor *m) #endif // STATUSPADDING_PATCH #if !HIDEVACANTTAGS_PATCH #if !ACTIVETAGINDICATORBAR_PATCH + #if PANGO_PATCH + int boxs = drw->font->h / 9; + #else int boxs = drw->fonts->h / 9; + #endif // PANGO_PATCH #endif // ACTIVETAGINDICATORBAR_PATCH + #if PANGO_PATCH + int boxw = drw->font->h / 6 + 2; + #else int boxw = drw->fonts->h / 6 + 2; + #endif // PANGO_PATCH #endif // HIDEVACANTTAGS_PATCH unsigned int i, occ = 0, urg = 0; #if STATUSCOLORS_PATCH @@ -1474,8 +1497,13 @@ drawbar(Monitor *m) } ctmp = *ts; *ts = '\0'; + #if PANGO_PATCH + drw_text(drw, m->ww - m->tw - stw + tx, 0, m->tw - tx, bh, stp, tp, 0, True); + tx += TEXTWM(tp) - lrpad; + #else drw_text(drw, m->ww - m->tw - stw + tx, 0, m->tw - tx, bh, stp, tp, 0); tx += TEXTW(tp) - lrpad; + #endif // PANGO_PATCH if (ctmp == '\0') break; drw_setscheme(drw, scheme[(unsigned int)(ctmp-1)]); @@ -1485,12 +1513,20 @@ drawbar(Monitor *m) #elif STATUS2D_PATCH m->tw = m->ww - drawstatusbar(m, bh, stext, stw, stp); #else // STATUSCOLORS_PATCH - #if STATUSPADDING_PATCH + #if STATUSPADDING_PATCH && PANGO_PATCH + m->tw = TEXTWM(stext); + #elif STATUSPADDING_PATCH m->tw = TEXTW(stext); + #elif PANGO_PATCH + m->tw = TEXTWM(stext) - lrpad + 2; /* 2px right padding */ #else m->tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ - #endif // STATUSPADDING_PATCH + #endif // STATUSPADDING_PATCH | PANGO_PATCH + #if PANGO_PATCH + drw_text(drw, m->ww - m->tw - stw, 0, m->tw, bh, stp, stext, 0, True); + #else drw_text(drw, m->ww - m->tw - stw, 0, m->tw, bh, stp, stext, 0); + #endif // PANGO_PATCH #endif // STATUSCOLORS_PATCH #if !STATUSALLMONS_PATCH } @@ -1517,7 +1553,11 @@ drawbar(Monitor *m) #else drw_setscheme(drw, scheme[SchemeNorm]); #endif // VTCOLORS_PATCH + #if PANGO_PATCH + x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0, False); + #else x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); + #endif // PANGO_PATCH #endif // LEFTLAYOUT_PATCH #if TAGGRID_PATCH if (drawtagmask & DRAWCLASSICTAGS) @@ -1555,8 +1595,12 @@ drawbar(Monitor *m) #else // URGENTBORDER_PATCH drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); #endif // URGENTBORDER_PATCH - #if ALTERNATIVE_TAGS_PATCH + #if ALTERNATIVE_TAGS_PATCH && PANGO_PATCH + drw_text(drw, x, 0, w, bh, wdelta + lrpad / 2, (selmon->alttag ? tagsalt[i] : tags[i]), invert, False); + #elif ALTERNATIVE_TAGS_PATCH drw_text(drw, x, 0, w, bh, wdelta + lrpad / 2, (selmon->alttag ? tagsalt[i] : tags[i]), invert); + #elif PANGO_PATCH + drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], invert, False); #else drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], invert); #endif // ALTERNATIVE_TAGS_PATCH @@ -1583,7 +1627,11 @@ drawbar(Monitor *m) #else drw_setscheme(drw, scheme[SchemeNorm]); #endif // VTCOLORS_PATCH + #if PANGO_PATCH + x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0, False); + #else x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); + #endif // PANGO_PATCH #endif // LEFTLAYOUT_PATCH if ((w = m->ww - m->tw - stw - x) > bh) @@ -1618,7 +1666,11 @@ drawbar(Monitor *m) tabw--; remainder--; } + #if PANGO_PATCH + drw_text(drw, x, 0, (1.0 / (double)n) * w, bh, lrpad / 2, c->name, 0, False); + #else drw_text(drw, x, 0, (1.0 / (double)n) * w, bh, lrpad / 2, c->name, 0); + #endif // PANGO_PATCH x += tabw; } } else { @@ -1660,7 +1712,11 @@ drawbar(Monitor *m) drw_setscheme(drw, scheme[m->sel == c ? SchemeSel : SchemeNorm]); #endif // VTCOLORS_PATCH / TITLECOLOR_PATCH if (ftw > 0) /* trap special handling of 0 in drw_text */ + #if PANGO_PATCH + drw_text(drw, x, 0, ftw, bh, lrpad / 2, c->name, 0, False); + #else drw_text(drw, x, 0, ftw, bh, lrpad / 2, c->name, 0); + #endif // PANGO_PATCH #if !HIDEVACANTTAGS_PATCH if (c->isfloating) #if ACTIVETAGINDICATORBAR_PATCH @@ -1693,14 +1749,22 @@ drawbar(Monitor *m) #endif // IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH #if CENTEREDWINDOWNAME_PATCH int mid = (m->ww - TEXTW(m->sel->name)) / 2 - x; - #if BARPADDING_PATCH + #if BARPADDING_PATCH && PANGO_PATCH + drw_text(drw, x, 0, w - 2*sp, bh, mid, m->sel->name, 0, False); + #elif BARPADDING_PATCH drw_text(drw, x, 0, w - 2*sp, bh, mid, m->sel->name, 0); + #elif PANGO_PATCH + drw_text(drw, x, 0, w, bh, mid, m->sel->name, 0, False); #else drw_text(drw, x, 0, w, bh, mid, m->sel->name, 0); #endif // BARPADDING_PATCH #else - #if BARPADDING_PATCH + #if BARPADDING_PATCH && PANGO_PATCH + drw_text(drw, x, 0, w - 2*sp, bh, lrpad / 2, m->sel->name, 0, False); + #elif BARPADDING_PATCH drw_text(drw, x, 0, w - 2*sp, bh, lrpad / 2, m->sel->name, 0); + #elif PANGO_PATCH + drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0, False); #else drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); #endif // BARPADDING_PATCH @@ -1744,7 +1808,11 @@ drawbar(Monitor *m) #else drw_setscheme(drw, scheme[SchemeNorm]); #endif // VTCOLORS_PATCH + #if PANGO_PATCH + drw_text(drw, 0, 0, mons->ww, bh, 0, estext, 0, True); + #else drw_text(drw, 0, 0, mons->ww, bh, 0, estext, 0); + #endif // PANGO_PATCH drw_map(drw, m->extrabarwin, 0, 0, m->ww, bh); } #endif // EXTRABAR_PATCH @@ -2975,11 +3043,21 @@ setup(void) #else drw = drw_create(dpy, screen, root, sw, sh); #endif // ALPHA_PATCH + #if PANGO_PATCH + if (!drw_font_create(drw, font)) + #else if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + #endif // PANGO_PATCH die("no fonts could be loaded."); - #if STATUSPADDING_PATCH + #if STATUSPADDING_PATCH && PANGO_PATCH + lrpad = drw->font->h + horizpadbar; + bh = drw->font->h + vertpadbar; + #elif STATUSPADDING_PATCH lrpad = drw->fonts->h + horizpadbar; bh = drw->fonts->h + vertpadbar; + #elif PANGO_PATCH + lrpad = drw->font->h; + bh = drw->font->h + 2; #else lrpad = drw->fonts->h; bh = drw->fonts->h + 2; @@ -4198,8 +4276,10 @@ main(int argc, char *argv[]) die("dwm-"VERSION); else if (!strcmp("-h", argv[i]) || !strcmp("--help", argv[i])) die(help()); + #if !PANGO_PATCH else if (!strcmp("-fn", argv[i])) /* font set */ fonts[0] = argv[++i]; + #endif // PANGO_PATCH #if !VTCOLORS_PATCH else if (!strcmp("-nb", argv[i])) /* normal background color */ colors[SchemeNorm][1] = argv[++i]; diff --git a/patch/status2d.c b/patch/status2d.c index 261a572..936b21a 100644 --- a/patch/status2d.c +++ b/patch/status2d.c @@ -24,7 +24,11 @@ drawstatusbar(Monitor *m, int bh, char* stext, int stw, int stp) if (!isCode) { isCode = 1; text[i] = '\0'; + #if PANGO_PATCH + w += TEXTWM(text) - lrpad; + #else w += TEXTW(text) - lrpad; + #endif // PANGO_PATCH text[i] = '^'; if (text[++i] == 'f') w += atoi(text + ++i); @@ -36,7 +40,11 @@ drawstatusbar(Monitor *m, int bh, char* stext, int stw, int stp) } } if (!isCode) + #if PANGO_PATCH + w += TEXTWM(text) - lrpad; + #else w += TEXTW(text) - lrpad; + #endif // PANGO_PATCH else isCode = 0; text = p; @@ -57,8 +65,13 @@ drawstatusbar(Monitor *m, int bh, char* stext, int stw, int stp) isCode = 1; text[i] = '\0'; + #if PANGO_PATCH + w = TEXTWM(text) - lrpad; + drw_text(drw, x, 0, w, bh, 0, text, 0, True); + #else w = TEXTW(text) - lrpad; drw_text(drw, x, 0, w, bh, 0, text, 0); + #endif // PANGO_PATCH x += w; @@ -126,8 +139,13 @@ drawstatusbar(Monitor *m, int bh, char* stext, int stw, int stp) } if (!isCode) { + #if PANGO_PATCH + w = TEXTWM(text) - lrpad; + drw_text(drw, x, 0, w, bh, 0, text, 0, True); + #else w = TEXTW(text) - lrpad; drw_text(drw, x, 0, w, bh, 0, text, 0); + #endif // PANGO_PATCH } drw_setscheme(drw, scheme[SchemeNorm]); @@ -161,7 +179,11 @@ status2dtextlength(char* stext) if (!isCode) { isCode = 1; text[i] = '\0'; + #if PANGO_PATCH + w += TEXTWM(text) - lrpad; + #else w += TEXTW(text) - lrpad; + #endif // PANGO_PATCH text[i] = '^'; if (text[++i] == 'f') w += atoi(text + ++i); @@ -173,7 +195,11 @@ status2dtextlength(char* stext) } } if (!isCode) + #if PANGO_PATCH + w += TEXTWM(text) - lrpad; + #else w += TEXTW(text) - lrpad; + #endif // PANGO_PATCH else isCode = 0; return w; diff --git a/patch/statuscolors.c b/patch/statuscolors.c index 2f015ad..ef41735 100644 --- a/patch/statuscolors.c +++ b/patch/statuscolors.c @@ -12,7 +12,11 @@ textw_wosc(char *s) } ctmp = *ts; *ts = '\0'; + #if PANGO_PATCH + sw += drw_font_getwidth(drw, tp, True); + #else sw += drw_fontset_getwidth(drw, tp); + #endif // PANGO_PATCH *ts = ctmp; if (ctmp == '\0') break; diff --git a/patches.def.h b/patches.def.h index 0627a26..4959fa0 100644 --- a/patches.def.h +++ b/patches.def.h @@ -390,6 +390,27 @@ */ #define ONLYQUITONEMPTY_PATCH 0 +/* This patch adds simple markup for status messages using pango markup. + * This depends on the pango library v1.44 or greater. + * You need to uncomment the corresponding lines in config.mk to use the pango libraries + * when including this patch. + * + * Note that the pango patch does not protect against the BadLength error from Xft + * when color glyphs are used, which means that dwm will crash if color emoji is used. + * + * If you need color emoji then you may want to install this patched library from the AUR: + * https://aur.archlinux.org/packages/libxft-bgra/ + * + * A long term fix for the libXft library is pending approval of this pull request: + * https://gitlab.freedesktop.org/xorg/lib/libxft/-/merge_requests/1 + * + * Also see: + * https://developer.gnome.org/pygtk/stable/pango-markup-language.html + * https://lists.suckless.org/hackers/2004/17285.html + * https://dwm.suckless.org/patches/pango/ + */ +#define PANGO_PATCH 0 + /* The pertag patch adds nmaster, mfacts and layouts per tag rather than per * monitor (default). * https://dwm.suckless.org/patches/pertag/ diff --git a/util.h b/util.h index f633b51..531ab25 100644 --- a/util.h +++ b/util.h @@ -1,7 +1,11 @@ /* See LICENSE file for copyright and license details. */ +#ifndef MAX #define MAX(A, B) ((A) > (B) ? (A) : (B)) +#endif +#ifndef MIN #define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif #define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) void die(const char *fmt, ...);