diff options
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | config.def.h | 10 | ||||
-rw-r--r-- | drw.c | 1 | ||||
-rw-r--r-- | dwm.1 | 33 | ||||
-rw-r--r-- | dwm.c | 293 | ||||
-rw-r--r-- | patches/barheight.diff | 25 | ||||
-rw-r--r-- | patches/pango.diff | 755 | ||||
-rw-r--r-- | patches/uselessgap.diff | 67 | ||||
-rw-r--r-- | patches/xfce-plugins.diff | 125 |
10 files changed, 1284 insertions, 32 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..236bde9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +/patches +dwm +*.orig +*.rej @@ -1,3 +1,5 @@ +This build of dwm by Bryson Steck is incredibly simple, nothing is visually overhauled. + dwm - dynamic window manager ============================ dwm is an extremely fast, small, and dynamic window manager for X. diff --git a/config.def.h b/config.def.h index d9ebdba..aa60e84 100644 --- a/config.def.h +++ b/config.def.h @@ -2,9 +2,17 @@ /* appearance */ static const unsigned int borderpx = 1; /* border pixel of windows */ +static const unsigned int gappx = 6; /* gaps between windows */ static const unsigned int snap = 32; /* snap pixel */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ +/* Display modes of the tab bar: never shown, always shown, shown only in */ +/* monocle mode in the presence of several windows. */ +/* Modes after showtab_nmodes are disabled. */ +enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; +static const int showtab = showtab_auto; /* Default tab bar show mode */ +static const int toptab = False; /* False means bottom tab bar */ + static const char *fonts[] = { "monospace:size=10" }; static const char dmenufont[] = "monospace:size=10"; static const char col_gray1[] = "#222222"; @@ -66,6 +74,7 @@ static Key keys[] = { { MODKEY, XK_p, spawn, {.v = dmenucmd } }, { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, { MODKEY, XK_b, togglebar, {0} }, + { MODKEY, XK_w, tabmode, {-1} }, { MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_k, focusstack, {.i = -1 } }, { MODKEY, XK_i, incnmaster, {.i = +1 } }, @@ -114,5 +123,6 @@ static Button buttons[] = { { ClkTagBar, 0, Button3, toggleview, {0} }, { ClkTagBar, MODKEY, Button1, tag, {0} }, { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + { ClkTabBar, 0, Button1, focuswin, {0} }, }; @@ -203,6 +203,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname) DefaultColormap(drw->dpy, drw->screen), clrname, dest)) die("error, cannot allocate color '%s'", clrname); + dest->pixel |= 0xff << 24; } /* Wrapper to create color schemes. The caller has to call free(3) on the @@ -20,14 +20,22 @@ layout applied. Windows are grouped by tags. Each window can be tagged with one or multiple tags. Selecting certain tags displays all windows with these tags. .P -Each screen contains a small status bar which displays all available tags, the -layout, the title of the focused window, and the text read from the root window -name property, if the screen is focused. A floating window is indicated with an -empty square and a maximised floating window is indicated with a filled square -before the windows title. The selected tags are indicated with a different -color. The tags of the focused window are indicated with a filled square in the -top left corner. The tags which are applied to one or more windows are -indicated with an empty square in the top left corner. +Each screen contains two small status bars. +.P +One bar displays all available tags, the layout, the title of the focused +window, and the text read from the root window name property, if the screen is +focused. A floating window is indicated with an empty square and a maximised +floating window is indicated with a filled square before the windows title. The +selected tags are indicated with a different color. The tags of the focused +window are indicated with a filled square in the top left corner. The tags +which are applied to one or more windows are indicated with an empty square in +the top left corner. +.P +Another bar contains a tab for each window of the current view and allows +navigation between windows, especially in the monocle mode. The different +display modes of this bar are described under the Mod1\-w Keybord command +section. When a single tag is selected, this tag is indicated in the left corner +of the tab bar. .P dwm draws a small border around windows to indicate the focus state. .SH OPTIONS @@ -44,7 +52,8 @@ command. .TP .B Button1 click on a tag label to display all windows with that tag, click on the layout -label toggles between tiled and floating layout. +label toggles between tiled and floating layout, click on a window name in the +tab bar brings focus to that window. .TP .B Button3 click on a tag label adds/removes all windows with that tag to/from the view. @@ -110,6 +119,12 @@ Increase master area size. .B Mod1\-h Decrease master area size. .TP +.B Mod1\-w +Cycle over the tab bar display modes: never displayed, always displayed, +displayed only in monocle mode when the view contains more than one window (auto +mode). Some display modes can be disabled in the configuration, config.h. In +the default configuration only "never" and "auto" display modes are enabled. +.TP .B Mod1\-Return Zooms/cycles focused window to/from master area (tiled layouts only). .TP @@ -52,8 +52,8 @@ #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) #define LENGTH(X) (sizeof X / sizeof X[0]) #define MOUSEMASK (BUTTONMASK|PointerMotionMask) -#define WIDTH(X) ((X)->w + 2 * (X)->bw) -#define HEIGHT(X) ((X)->h + 2 * (X)->bw) +#define WIDTH(X) ((X)->w + 2 * (X)->bw + gappx) +#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx) #define TAGMASK ((1 << LENGTH(tags)) - 1) #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) @@ -64,7 +64,7 @@ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, NetWMFullscreen, NetActiveWindow, NetWMWindowType, NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, +enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ typedef union { @@ -93,6 +93,7 @@ struct Client { int bw, oldbw; unsigned int tags; int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + int issteam; Client *next; Client *snext; Monitor *mon; @@ -111,12 +112,15 @@ typedef struct { void (*arrange)(Monitor *); } Layout; +#define MAXTABS 50 + struct Monitor { char ltsymbol[16]; float mfact; int nmaster; int num; int by; /* bar geometry */ + int ty; /* tab bar geometry */ int mx, my, mw, mh; /* screen size */ int wx, wy, ww, wh; /* window area */ int gappx; /* gaps between windows */ @@ -124,12 +128,17 @@ struct Monitor { unsigned int sellt; unsigned int tagset[2]; int showbar; + int showtab; int topbar; + int toptab; Client *clients; Client *sel; Client *stack; Monitor *next; Window barwin; + Window tabwin; + int ntabs; + int tab_widths[MAXTABS]; const Layout *lt[2]; }; @@ -167,10 +176,13 @@ static void drawbar(Monitor *m); static void drawbars(void); static void enternotify(XEvent *e); static void expose(XEvent *e); +static void drawtab(Monitor *m); +static void drawtabs(void); static void focus(Client *c); static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); +static void focuswin(const Arg* arg); static Atom getatomprop(Client *c, Atom prop); static int getrootptr(int *x, int *y); static long getstate(Window w); @@ -210,6 +222,7 @@ static void seturgent(Client *c, int urg); static void showhide(Client *c); static void sigchld(int unused); static void spawn(const Arg *arg); +static void tabmode(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); static void tile(Monitor *); @@ -237,6 +250,8 @@ static int xerror(Display *dpy, XErrorEvent *ee); static int xerrordummy(Display *dpy, XErrorEvent *ee); static int xerrorstart(Display *dpy, XErrorEvent *ee); static void zoom(const Arg *arg); +static void bstack(Monitor *m); +static void bstackhoriz(Monitor *m); /* variables */ static const char broken[] = "broken"; @@ -244,6 +259,7 @@ static char stext[256]; static int screen; static int sw, sh; /* X display screen geometry width, height */ static int bh, blw = 0; /* bar geometry */ +static int th = 0; /* tab bar geometry */ static int lrpad; /* sum of left and right padding for text */ static int (*xerrorxlib)(Display *, XErrorEvent *); static unsigned int numlockmask = 0; @@ -295,6 +311,9 @@ applyrules(Client *c) class = ch.res_class ? ch.res_class : broken; instance = ch.res_name ? ch.res_name : broken; + if (strstr(class, "Steam") || strstr(class, "steam_app_")) + c->issteam = 1; + for (i = 0; i < LENGTH(rules); i++) { r = &rules[i]; if ((!r->title || strstr(c->name, r->title)) @@ -398,8 +417,9 @@ arrange(Monitor *m) } void -arrangemon(Monitor *m) -{ +arrangemon(Monitor *m) { + updatebarpos(m); + XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); if (m->lt[m->sellt]->arrange) m->lt[m->sellt]->arrange(m); @@ -449,7 +469,24 @@ buttonpress(XEvent *e) click = ClkStatusText; else click = ClkWinTitle; - } else if ((c = wintoclient(ev->window))) { + } + if(ev->window == selmon->tabwin) { + i = 0; x = 0; + for(c = selmon->clients; c; c = c->next){ + if(!ISVISIBLE(c)) continue; + x += selmon->tab_widths[i]; + if (ev->x > x) + ++i; + else + break; + if(i >= m->ntabs) break; + } + if(c) { + click = ClkTabBar; + arg.ui = i; + } + } + else if((c = wintoclient(ev->window))) { focus(c); restack(selmon); XAllowEvents(dpy, ReplayPointer, CurrentTime); @@ -457,8 +494,9 @@ buttonpress(XEvent *e) } for (i = 0; i < LENGTH(buttons); i++) if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button - && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ + buttons[i].func(((click == ClkTagBar || click == ClkTabBar) && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); + } } void @@ -513,6 +551,8 @@ cleanupmon(Monitor *mon) } XUnmapWindow(dpy, mon->barwin); XDestroyWindow(dpy, mon->barwin); + XUnmapWindow(dpy, mon->tabwin); + XDestroyWindow(dpy, mon->tabwin); free(mon); } @@ -595,13 +635,15 @@ configurerequest(XEvent *e) c->bw = ev->border_width; else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { m = c->mon; - if (ev->value_mask & CWX) { - c->oldx = c->x; - c->x = m->mx + ev->x; - } - if (ev->value_mask & CWY) { - c->oldy = c->y; - c->y = m->my + ev->y; + if (!c->issteam) { + if (ev->value_mask & CWX) { + c->oldx = c->x; + c->x = m->mx + ev->x; + } + if (ev->value_mask & CWY) { + c->oldy = c->y; + c->y = m->my + ev->y; + } } if (ev->value_mask & CWWidth) { c->oldw = c->w; @@ -644,6 +686,7 @@ createmon(void) m->mfact = mfact; m->nmaster = nmaster; m->showbar = showbar; + m->showtab = showtab; m->topbar = topbar; m->gappx = gappx; m->lt[0] = &layouts[0]; @@ -763,6 +806,105 @@ drawbars(void) } void +drawtabs(void) { + Monitor *m; + + for(m = mons; m; m = m->next) + drawtab(m); +} + +static int +cmpint(const void *p1, const void *p2) { + /* The actual arguments to this function are "pointers to + pointers to char", but strcmp(3) arguments are "pointers + to char", hence the following cast plus dereference */ + return *((int*) p1) > * (int*) p2; +} + + +void +drawtab(Monitor *m) { + Client *c; + int i; + int itag = -1; + char view_info[50]; + int view_info_w = 0; + int sorted_label_widths[MAXTABS]; + int tot_width; + int maxsize = bh; + int x = 0; + int w = 0; + + //view_info: indicate the tag which is displayed in the view + for(i = 0; i < LENGTH(tags); ++i){ + if((selmon->tagset[selmon->seltags] >> i) & 1) { + if(itag >=0){ //more than one tag selected + itag = -1; + break; + } + itag = i; + } + } + + if(0 <= itag && itag < LENGTH(tags)){ + snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); + } else { + strncpy(view_info, "[...]", sizeof view_info); + } + view_info[sizeof(view_info) - 1 ] = 0; + view_info_w = TEXTW(view_info); + tot_width = view_info_w; + + /* Calculates number of labels and their width */ + m->ntabs = 0; + for(c = m->clients; c; c = c->next){ + if(!ISVISIBLE(c)) continue; + m->tab_widths[m->ntabs] = TEXTW(c->name); + tot_width += m->tab_widths[m->ntabs]; + ++m->ntabs; + if(m->ntabs >= MAXTABS) break; + } + + if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated + memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); + qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); + tot_width = view_info_w; + for(i = 0; i < m->ntabs; ++i){ + if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) + break; + tot_width += sorted_label_widths[i]; + } + maxsize = (m->ww - tot_width) / (m->ntabs - i); + } else{ + maxsize = m->ww; + } + i = 0; + for(c = m->clients; c; c = c->next){ + if(!ISVISIBLE(c)) continue; + if(i >= m->ntabs) break; + if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; + w = m->tab_widths[i]; + drw_setscheme(drw, scheme[(c == m->sel) ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, th, 0, c->name, 0); + x += w; + ++i; + } + + drw_setscheme(drw, scheme[SchemeNorm]); + + /* cleans interspace between window names and current viewed tag label */ + w = m->ww - view_info_w - x; + drw_text(drw, x, 0, w, th, 0, "", 0); + + /* view info */ + x += w; + w = view_info_w; + drw_text(drw, x, 0, w, th, 0, view_info, 0); + + drw_map(drw, m->tabwin, 0, 0, m->ww, th); +} + +void enternotify(XEvent *e) { Client *c; @@ -787,8 +929,10 @@ expose(XEvent *e) Monitor *m; XExposeEvent *ev = &e->xexpose; - if (ev->count == 0 && (m = wintomon(ev->window))) + if(ev->count == 0 && (m = wintomon(ev->window))){ drawbar(m); + drawtab(m); + } } void @@ -814,6 +958,7 @@ focus(Client *c) } selmon->sel = c; drawbars(); + drawtabs(); } /* there are some broken focus acquiring clients needing extra handling */ @@ -1247,12 +1392,14 @@ propertynotify(XEvent *e) case XA_WM_HINTS: updatewmhints(c); drawbars(); + drawtabs(); break; } if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { updatetitle(c); if (c == c->mon->sel) drawbar(c->mon); + drawtab(c->mon); } if (ev->atom == netatom[NetWMWindowType]) updatewindowtype(c); @@ -1291,11 +1438,12 @@ resizeclient(Client *c, int x, int y, int w, int h) { XWindowChanges wc; - c->oldx = c->x; c->x = wc.x = x; - c->oldy = c->y; c->y = wc.y = y; - c->oldw = c->w; c->w = wc.width = w; - c->oldh = c->h; c->h = wc.height = h; + c->oldx = c->x; c->x = wc.x = x; + c->oldy = c->y; c->y = wc.y = y; + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; wc.border_width = c->bw; + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); configure(c); XSync(dpy, False); @@ -1366,6 +1514,7 @@ restack(Monitor *m) XWindowChanges wc; drawbar(m); + drawtab(m); if (!m->sel) return; if (m->sel->isfloating || !m->lt[m->sellt]->arrange) @@ -1570,6 +1719,7 @@ setup(void) die("no fonts could be loaded."); lrpad = drw->fonts->h; bh = drw->fonts->h + 2; + th = bh; updategeom(); /* init atoms */ utf8string = XInternAtom(dpy, "UTF8_STRING", False); @@ -1756,6 +1906,17 @@ togglebar(const Arg *arg) } void +tabmode(const Arg *arg) +{ + if(arg && arg->i >= 0) + selmon->showtab = arg->ui % showtab_nmodes; + else + selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; + arrange(selmon); +} + + +void togglefloating(const Arg *arg) { if (!selmon->sel) @@ -1866,6 +2027,11 @@ updatebars(void) CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); XMapRaised(dpy, m->barwin); + m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->tabwin); XSetClassHint(dpy, m->barwin, &ch); } } @@ -1873,16 +2039,35 @@ updatebars(void) void updatebarpos(Monitor *m) { + Client *c; + int nvis = 0; + m->wy = m->my; m->wh = m->mh; if (m->showbar) { m->wh -= bh; m->by = m->topbar ? m->wy : m->wy + m->wh; - m->wy = m->topbar ? m->wy + bh : m->wy; - } else + if ( m->topbar ) + m->wy += bh; + } else { m->by = -bh; } + for(c = m->clients; c; c = c->next) { + if(ISVISIBLE(c)) ++nvis; + } + + if(m->showtab == showtab_always + || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))) { + m->wh -= th; + m->ty = m->toptab ? m->wy : m->wy + m->wh; + if ( m->toptab ) + m->wy += th; + } else { + m->ty = -th; + } +} + void updateclientlist() { @@ -2118,7 +2303,7 @@ wintomon(Window w) if (w == root && getrootptr(&x, &y)) return recttomon(x, y, 1, 1); for (m = mons; m; m = m->next) - if (w == m->barwin) + if (w == m->barwin || w == m->tabwin) return m; if ((c = wintoclient(w))) return c->mon; @@ -2198,3 +2383,65 @@ main(int argc, char *argv[]) XCloseDisplay(dpy); return EXIT_SUCCESS; } + +static void +bstack(Monitor *m) { + int w, h, mh, mx, tx, ty, tw; + unsigned int i, n; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 0) + return; + if (n > m->nmaster) { + mh = m->nmaster ? m->mfact * m->wh : 0; + tw = m->ww / (n - m->nmaster); + ty = m->wy + mh; + } else { + mh = m->wh; + tw = m->ww; + ty = m->wy; + } + for (i = mx = 0, tx = m->wx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + if (i < m->nmaster) { + w = (m->ww - mx) / (MIN(n, m->nmaster) - i); + resize(c, m->wx + mx, m->wy, w - (2 * c->bw), mh - (2 * c->bw), 0); + mx += WIDTH(c); + } else { + h = m->wh - mh; + resize(c, tx, ty, tw - (2 * c->bw), h - (2 * c->bw), 0); + if (tw != m->ww) + tx += WIDTH(c); + } + } +} + +static void +bstackhoriz(Monitor *m) { + int w, mh, mx, tx, ty, th; + unsigned int i, n; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 0) + return; + if (n > m->nmaster) { + mh = m->nmaster ? m->mfact * m->wh : 0; + th = (m->wh - mh) / (n - m->nmaster); + ty = m->wy + mh; + } else { + th = mh = m->wh; + ty = m->wy; + } + for (i = mx = 0, tx = m->wx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + if (i < m->nmaster) { + w = (m->ww - mx) / (MIN(n, m->nmaster) - i); + resize(c, m->wx + mx, m->wy, w - (2 * c->bw), mh - (2 * c->bw), 0); + mx += WIDTH(c); + } else { + resize(c, tx, ty, m->ww - (2 * c->bw), th - (2 * c->bw), 0); + if (th != m->wh) + ty += HEIGHT(c); + } + } +} diff --git a/patches/barheight.diff b/patches/barheight.diff new file mode 100644 index 0000000..a576111 --- /dev/null +++ b/patches/barheight.diff @@ -0,0 +1,25 @@ +diff --git a/config.def.h b/config.def.h +index 1c0b587..9814500 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -5,6 +5,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ ++static const int user_bh = 0; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */ + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; +diff --git a/dwm.c b/dwm.c +index 4465af1..2c27cb3 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1545,7 +1545,7 @@ setup(void) + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; +- bh = drw->fonts->h + 2; ++ bh = user_bh ? user_bh : drw->fonts->h + 2; + updategeom(); + /* init atoms */ + utf8string = XInternAtom(dpy, "UTF8_STRING", False); diff --git a/patches/pango.diff b/patches/pango.diff new file mode 100644 index 0000000..b64fdbe --- /dev/null +++ b/patches/pango.diff @@ -0,0 +1,755 @@ +From 986b03fee484ecc98c0913ee3678318bc8c29d65 Mon Sep 17 00:00:00 2001 +From: Marius Iacob <themariusus@gmail.com> +Date: Mon, 11 May 2020 12:17:20 +0300 +Subject: [PATCH 1/4] pango support + +--- + config.def.h | 2 +- + config.mk | 4 +- + drw.c | 303 +++++++++++++-------------------------------------- + drw.h | 17 ++- + dwm.c | 28 ++--- + util.h | 4 + + 6 files changed, 106 insertions(+), 252 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..d201ae6 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -5,7 +5,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ +-static const char *fonts[] = { "monospace:size=10" }; ++static const char font[] = "monospace 10"; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; + static const char col_gray2[] = "#444444"; +diff --git a/config.mk b/config.mk +index 7084c33..b5c7e12 100644 +--- a/config.mk ++++ b/config.mk +@@ -21,8 +21,8 @@ FREETYPEINC = /usr/include/freetype2 + #FREETYPEINC = ${X11INC}/freetype2 + + # includes and libs +-INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++INCS = -I${X11INC} -I${FREETYPEINC} `pkg-config --cflags xft pango pangoxft` ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} `pkg-config --libs xft pango pangoxft` + + # 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 8fd1ca4..6d1b64e 100644 +--- a/drw.c ++++ b/drw.c +@@ -4,62 +4,12 @@ + #include <string.h> + #include <X11/Xlib.h> + #include <X11/Xft/Xft.h> ++#include <pango/pango.h> ++#include <pango/pangoxft.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) +- 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) + { +@@ -99,58 +49,37 @@ drw_free(Drw *drw) + } + + /* This function is an implementation detail. Library users should use +- * drw_fontset_create instead. ++ * drw_font_create instead. + */ + static Fnt * +-xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) ++xfont_create(Drw *drw, const char *fontname) + { + Fnt *font; +- XftFont *xfont = NULL; +- FcPattern *pattern = NULL; +- +- if (fontname) { +- /* Using the pattern found at font->xfont->pattern does not yield 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 (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { +- fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); +- return NULL; +- } +- if (!(pattern = FcNameParse((FcChar8 *) fontname))) { +- fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); +- XftFontClose(drw->dpy, xfont); +- return NULL; +- } +- } else if (fontpattern) { +- if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { +- fprintf(stderr, "error, cannot load font from pattern.\n"); +- return NULL; +- } +- } else { +- die("no font specified."); +- } ++ PangoFontMap *fontmap; ++ PangoContext *context; ++ PangoFontDescription *desc; ++ PangoFontMetrics *metrics; + +- /* Do not allow using color fonts. This is a workaround for a BadLength +- * error from Xft with color glyphs. Modelled on the Xterm workaround. See +- * https://bugzilla.redhat.com/show_bug.cgi?id=1498269 +- * https://lists.suckless.org/dev/1701/30932.html +- * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349 +- * and lots more all over the internet. +- */ +- FcBool iscol; +- if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { +- XftFontClose(drw->dpy, xfont); +- return NULL; ++ ++ if (!fontname) { ++ die("no font specified."); + } + + font = ecalloc(1, sizeof(Fnt)); +- font->xfont = xfont; +- font->pattern = pattern; +- font->h = xfont->ascent + xfont->descent; + 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; + } + +@@ -159,35 +88,28 @@ xfont_free(Fnt *font) + { + if (!font) + return; +- if (font->pattern) +- FcPatternDestroy(font->pattern); +- XftFontClose(font->dpy, font->xfont); ++ if (font->layout) ++ g_object_unref(font->layout); + free(font); + } + + Fnt* +-drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) ++drw_font_create(Drw* drw, const char font[]) + { +- Fnt *cur, *ret = NULL; +- size_t i; ++ Fnt *fnt = NULL; + +- if (!drw || !fonts) ++ if (!drw || !font) + return NULL; + +- for (i = 1; i <= fontcount; i++) { +- if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { +- cur->next = ret; +- ret = cur; +- } +- } +- return (drw->fonts = ret); ++ fnt = xfont_create(drw, font); ++ ++ return (drw->font = fnt); + } + + void +-drw_fontset_free(Fnt *font) ++drw_font_free(Fnt *font) + { + if (font) { +- drw_fontset_free(font->next); + xfont_free(font); + } + } +@@ -221,13 +143,6 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) + return ret; + } + +-void +-drw_setfontset(Drw *drw, Fnt *set) +-{ +- if (drw) +- drw->fonts = set; +-} +- + void + drw_setscheme(Drw *drw, Clr *scm) + { +@@ -248,24 +163,16 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int + } + + int +-drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) ++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; +- Fnt *usedfont, *curfont, *nextfont; + size_t i, len; +- int utf8strlen, utf8charlen, render = x || y || w || h; +- long utf8codepoint = 0; +- const char *utf8str; +- FcCharSet *fccharset; +- FcPattern *fcpattern; +- FcPattern *match; +- XftResult result; +- int charexists = 0; +- +- if (!drw || (render && !drw->scheme) || !text || !drw->fonts) ++ int render = x || y || w || h; ++ ++ if (!drw || (render && !drw->scheme) || !text || !drw->font) + return 0; + + if (!render) { +@@ -280,98 +187,37 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + w -= lpad; + } + +- usedfont = drw->fonts; +- while (1) { +- utf8strlen = 0; +- utf8str = text; +- nextfont = NULL; +- while (*text) { +- utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); +- for (curfont = drw->fonts; curfont; curfont = curfont->next) { +- charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); +- if (charexists) { +- if (curfont == usedfont) { +- utf8strlen += utf8charlen; +- text += utf8charlen; +- } else { +- nextfont = curfont; +- } +- break; +- } +- } +- +- if (!charexists || nextfont) +- break; +- else +- charexists = 0; +- } +- +- if (utf8strlen) { +- drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); +- /* shorten text if necessary */ +- for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) +- drw_font_getexts(usedfont, utf8str, len, &ew, NULL); +- +- if (len) { +- memcpy(buf, utf8str, len); +- buf[len] = '\0'; +- if (len < utf8strlen) +- for (i = len; i && i > len - 3; buf[--i] = '.') +- ; /* NOP */ +- +- if (render) { +- ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; +- XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], +- usedfont->xfont, x, ty, (XftChar8 *)buf, len); +- } +- x += ew; +- w -= ew; +- } +- } +- +- if (!*text) { +- break; +- } else if (nextfont) { +- charexists = 0; +- usedfont = nextfont; +- } else { +- /* Regardless of whether or not a fallback font is found, the +- * character must be drawn. */ +- charexists = 1; +- +- fccharset = FcCharSetCreate(); +- FcCharSetAddChar(fccharset, utf8codepoint); +- +- if (!drw->fonts->pattern) { +- /* Refer to the comment in xfont_create for more information. */ +- die("the first font in the cache must be loaded from a font string."); +- } +- +- fcpattern = FcPatternDuplicate(drw->fonts->pattern); +- FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); +- FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); +- FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); +- +- FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); +- FcDefaultSubstitute(fcpattern); +- match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); +- +- FcCharSetDestroy(fccharset); +- FcPatternDestroy(fcpattern); +- +- if (match) { +- usedfont = xfont_create(drw, NULL, match); +- if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { +- for (curfont = drw->fonts; curfont->next; curfont = curfont->next) +- ; /* NOP */ +- curfont->next = usedfont; +- } else { +- xfont_free(usedfont); +- usedfont = drw->fonts; +- } ++ 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); + +@@ -389,24 +235,29 @@ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) + } + + unsigned int +-drw_fontset_getwidth(Drw *drw, const char *text) ++drw_font_getwidth(Drw *drw, const char *text, Bool markup) + { +- if (!drw || !drw->fonts || !text) ++ if (!drw || !drw->font || !text) + return 0; +- return drw_text(drw, 0, 0, 0, 0, 0, text, 0); ++ return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup); + } + + void +-drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) ++drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup) + { +- XGlyphInfo ext; +- + if (!font || !text) + return; + +- XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); ++ 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 = ext.xOff; ++ *w = r.width / PANGO_SCALE; + if (h) + *h = font->h; + } +diff --git a/drw.h b/drw.h +index 4bcd5ad..3d3a906 100644 +--- a/drw.h ++++ b/drw.h +@@ -7,9 +7,7 @@ typedef struct { + typedef struct Fnt { + Display *dpy; + unsigned int h; +- XftFont *xfont; +- FcPattern *pattern; +- struct Fnt *next; ++ PangoLayout *layout; + } Fnt; + + enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */ +@@ -23,7 +21,7 @@ typedef struct { + Drawable drawable; + GC gc; + Clr *scheme; +- Fnt *fonts; ++ Fnt *font; + } Drw; + + /* Drawable abstraction */ +@@ -32,10 +30,10 @@ void drw_resize(Drw *drw, unsigned int w, unsigned int h); + void drw_free(Drw *drw); + + /* Fnt abstraction */ +-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); ++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); + + /* Colorscheme abstraction */ + void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); +@@ -46,12 +44,11 @@ Cur *drw_cur_create(Drw *drw, int shape); + void drw_cur_free(Drw *drw, Cur *cursor); + + /* Drawing context manipulation */ +-void drw_setfontset(Drw *drw, Fnt *set); + 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); +-int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); ++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); + + /* 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 9fd0286..cc180c4 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -40,6 +40,7 @@ + #include <X11/extensions/Xinerama.h> + #endif /* XINERAMA */ + #include <X11/Xft/Xft.h> ++#include <pango/pango.h> + + #include "drw.h" + #include "util.h" +@@ -55,7 +56,8 @@ + #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_fontset_getwidth(drw, (X)) + lrpad) ++#define TEXTW(X) (drw_font_getwidth(drw, (X), False) + lrpad) ++#define TEXTWM(X) (drw_font_getwidth(drw, (X), True) + lrpad) + + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +@@ -237,7 +239,7 @@ static void zoom(const Arg *arg); + + /* variables */ + static const char broken[] = "broken"; +-static char stext[256]; ++static char stext[512]; + static int screen; + static int sw, sh; /* X display screen geometry width, height */ + static int bh, blw = 0; /* bar geometry */ +@@ -440,7 +442,7 @@ buttonpress(XEvent *e) + arg.ui = 1 << i; + } else if (ev->x < x + blw) + click = ClkLtSymbol; +- else if (ev->x > selmon->ww - TEXTW(stext)) ++ else if (ev->x > selmon->ww - TEXTWM(stext)) + click = ClkStatusText; + else + click = ClkWinTitle; +@@ -697,16 +699,16 @@ void + drawbar(Monitor *m) + { + int x, w, tw = 0; +- int boxs = drw->fonts->h / 9; +- int boxw = drw->fonts->h / 6 + 2; ++ int boxs = drw->font->h / 9; ++ int boxw = drw->font->h / 6 + 2; + unsigned int i, occ = 0, urg = 0; + Client *c; + + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ + drw_setscheme(drw, scheme[SchemeNorm]); +- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ +- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); ++ tw = TEXTWM(stext) - lrpad + 2; /* 2px right padding */ ++ drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0, True); + } + + for (c = m->clients; c; c = c->next) { +@@ -718,7 +720,7 @@ drawbar(Monitor *m) + for (i = 0; i < LENGTH(tags); i++) { + w = TEXTW(tags[i]); + drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); +- drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); ++ drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i, False); + if (occ & 1 << i) + drw_rect(drw, x + boxs, boxs, boxw, boxw, + m == selmon && selmon->sel && selmon->sel->tags & 1 << i, +@@ -727,12 +729,12 @@ drawbar(Monitor *m) + } + w = blw = TEXTW(m->ltsymbol); + drw_setscheme(drw, scheme[SchemeNorm]); +- x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); ++ x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0, False); + + if ((w = m->ww - tw - x) > bh) { + if (m->sel) { + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); +- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); ++ drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0, False); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + } else { +@@ -1543,10 +1545,10 @@ setup(void) + sh = DisplayHeight(dpy, screen); + root = RootWindow(dpy, screen); + drw = drw_create(dpy, screen, root, sw, sh); +- if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) ++ if (!drw_font_create(drw, font)) + die("no fonts could be loaded."); +- lrpad = drw->fonts->h; +- bh = drw->fonts->h + 2; ++ lrpad = drw->font->h; ++ bh = drw->font->h + 2; + updategeom(); + /* init atoms */ + utf8string = XInternAtom(dpy, "UTF8_STRING", False); +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, ...); +-- +2.28.0 + + +From 62b46168970345a67cce6afb7bddb3c4eddbde8c Mon Sep 17 00:00:00 2001 +From: Marius Iacob <themariusus@gmail.com> +Date: Wed, 20 May 2020 17:04:34 +0300 +Subject: [PATCH 2/4] removed some blank lines + +--- + drw.c | 1 - + dwm.c | 1 - + 2 files changed, 2 deletions(-) + +diff --git a/drw.c b/drw.c +index 6d1b64e..30543f2 100644 +--- a/drw.c ++++ b/drw.c +@@ -60,7 +60,6 @@ xfont_create(Drw *drw, const char *fontname) + PangoFontDescription *desc; + PangoFontMetrics *metrics; + +- + if (!fontname) { + die("no font specified."); + } +diff --git a/dwm.c b/dwm.c +index cc180c4..d63ebb4 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1599,7 +1599,6 @@ setup(void) + focus(NULL); + } + +- + void + seturgent(Client *c, int urg) + { +-- +2.28.0 + + +From 1d3a8696e884317c7eab0cc47c2a2e4fca1d1685 Mon Sep 17 00:00:00 2001 +From: Marius Iacob <themariusus@gmail.com> +Date: Wed, 22 Jul 2020 09:48:32 +0300 +Subject: [PATCH 3/4] Fixed patch after update + +--- + drw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drw.c b/drw.c +index b834cef..34bda61 100644 +--- a/drw.c ++++ b/drw.c +@@ -45,7 +45,7 @@ drw_free(Drw *drw) + { + XFreePixmap(drw->dpy, drw->drawable); + XFreeGC(drw->dpy, drw->gc); +- drw_fontset_free(drw->fonts); ++ drw_font_free(drw->font); + free(drw); + } + +-- +2.28.0 + + +From 63d0a5e4a8fb109c5a032e76d5e2410fa792e45f Mon Sep 17 00:00:00 2001 +From: Marius Iacob <themariusus@gmail.com> +Date: Tue, 20 Oct 2020 21:06:48 +0300 +Subject: [PATCH 4/4] font rendering fixes + +removed hardcoded locale, should use system defined in env vars + +get height of text on a case by case basis, helps with CJK fonts +--- + drw.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/drw.c b/drw.c +index 34bda61..1795a13 100644 +--- a/drw.c ++++ b/drw.c +@@ -74,7 +74,7 @@ xfont_create(Drw *drw, const char *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")); ++ metrics = pango_context_get_metrics(context, desc, NULL); + font->h = pango_font_metrics_get_height(metrics) / PANGO_SCALE; + + pango_font_metrics_unref(metrics); +@@ -166,8 +166,8 @@ 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; ++ int ty, th; ++ unsigned int ew, eh; + XftDraw *d = NULL; + size_t i, len; + int render = x || y || w || h; +@@ -190,10 +190,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + len = strlen(text); + + if (len) { +- drw_font_getexts(drw->font, text, len, &ew, NULL, markup); ++ drw_font_getexts(drw->font, text, len, &ew, &eh, markup); ++ th = eh; + /* 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); ++ for (len = MIN(len, sizeof(buf) - 1); len && ew > w; len--) { ++ drw_font_getexts(drw->font, text, len, &ew, &eh, markup); ++ if (eh > th) ++ th = eh; ++ } + + if (len) { + memcpy(buf, text, len); +@@ -203,7 +207,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + ; /* NOP */ + + if (render) { +- ty = y + (h - drw->font->h) / 2; ++ ty = y + (h - th) / 2; + if(markup) + pango_layout_set_markup(drw->font->layout, buf, len); + else +@@ -259,7 +263,7 @@ drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, + if (w) + *w = r.width / PANGO_SCALE; + if (h) +- *h = font->h; ++ *h = r.height / PANGO_SCALE; + } + + Cur * +-- +2.28.0 + diff --git a/patches/uselessgap.diff b/patches/uselessgap.diff new file mode 100644 index 0000000..1bf2ea0 --- /dev/null +++ b/patches/uselessgap.diff @@ -0,0 +1,67 @@ +From 58a5ece9406ca6c90dc362617c065e4aac19417f Mon Sep 17 00:00:00 2001 +From: Cyril Cressent <cyril@cressent.org> +Date: Wed, 3 Jul 2019 21:33:45 -0700 +Subject: [PATCH] Port the uselessgap patch to 6.2 + +--- + dwm.c | 36 ++++++++++++++++++++++++++++++------ + 2 files changed, 31 insertions(+), 6 deletions(-) +diff --git a/dwm.c b/dwm.c +index 4465af1..4545e05 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -52,8 +52,8 @@ + #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define MOUSEMASK (BUTTONMASK|PointerMotionMask) +-#define WIDTH(X) ((X)->w + 2 * (X)->bw) +-#define HEIGHT(X) ((X)->h + 2 * (X)->bw) ++#define WIDTH(X) ((X)->w + 2 * (X)->bw + gappx) ++#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx) + #define TAGMASK ((1 << LENGTH(tags)) - 1) + #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + +@@ -1276,12 +1276,36 @@ void + resizeclient(Client *c, int x, int y, int w, int h) + { + XWindowChanges wc; ++ unsigned int n; ++ unsigned int gapoffset; ++ unsigned int gapincr; ++ Client *nbc; + +- c->oldx = c->x; c->x = wc.x = x; +- c->oldy = c->y; c->y = wc.y = y; +- c->oldw = c->w; c->w = wc.width = w; +- c->oldh = c->h; c->h = wc.height = h; + wc.border_width = c->bw; ++ ++ /* Get number of clients for the selected monitor */ ++ for (n = 0, nbc = nexttiled(selmon->clients); nbc; nbc = nexttiled(nbc->next), n++); ++ ++ /* Do nothing if layout is floating */ ++ if (c->isfloating || selmon->lt[selmon->sellt]->arrange == NULL) { ++ gapincr = gapoffset = 0; ++ } else { ++ /* Remove border and gap if layout is monocle or only one client */ ++ if (selmon->lt[selmon->sellt]->arrange == monocle || n == 1) { ++ gapoffset = 0; ++ gapincr = -2 * borderpx; ++ wc.border_width = 0; ++ } else { ++ gapoffset = gappx; ++ gapincr = 2 * gappx; ++ } ++ } ++ ++ c->oldx = c->x; c->x = wc.x = x + gapoffset; ++ c->oldy = c->y; c->y = wc.y = y + gapoffset; ++ c->oldw = c->w; c->w = wc.width = w - gapincr; ++ c->oldh = c->h; c->h = wc.height = h - gapincr; ++ + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); + XSync(dpy, False); +-- +2.22.0 + diff --git a/patches/xfce-plugins.diff b/patches/xfce-plugins.diff new file mode 100644 index 0000000..c789daf --- /dev/null +++ b/patches/xfce-plugins.diff @@ -0,0 +1,125 @@ +From 4e33fe0d465fb24f6b42d4a1fb63d4d7902f1986 Mon Sep 17 00:00:00 2001 +From: Gunther Klessinger <gunther.klessinger@axiros.com> +Date: Thu, 1 Jul 2021 09:19:07 +0200 +Subject: [PATCH] Supporting xfce4-panel in dwm + +We treat the panel as special window which +- never has borders +- never has focus +- always has y=0 +- is never shown as active window in the indicators +- is shown on all tags (via config rule) +- is ignored on focusstack (MOD+j, MOD+k) + +Which window? "xfce4-panel" - configurable in config.h +--- + config.def.h | 2 ++ + dwm.c | 28 +++++++++++++++++++++------- + 2 files changed, 23 insertions(+), 7 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..3b9e7d6 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -3,6 +3,7 @@ + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ ++static const char panel[][20] = { "xfce4-panel", "Xfce4-panel" }; /* name & cls of panel win */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ + static const char *fonts[] = { "monospace:size=10" }; + + + /* layout(s) */ +diff --git a/dwm.c b/dwm.c +index b0b3466..956d402 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -175,6 +175,7 @@ static long getstate(Window w); + static int gettextprop(Window w, Atom atom, char *text, unsigned int size); + static void grabbuttons(Client *c, int focused); + static void grabkeys(void); ++static int ispanel(Client *c); + static void incnmaster(const Arg *arg); + static void keypress(XEvent *e); + static void killclient(const Arg *arg); +@@ -710,6 +711,8 @@ drawbar(Monitor *m) + } + + for (c = m->clients; c; c = c->next) { ++ // prevent showing the panel as active application: ++ if (ispanel(c)) continue; + occ |= c->tags; + if (c->isurgent) + urg |= c->tags; +@@ -793,11 +796,14 @@ focus(Client *c) + selmon = c->mon; + if (c->isurgent) + seturgent(c, 0); +- detachstack(c); +- attachstack(c); +- grabbuttons(c, 1); +- XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); +- setfocus(c); ++ // prevents the panel getting focus when tag switching: ++ if (!ispanel(c)) { ++ detachstack(c); ++ attachstack(c); ++ grabbuttons(c, 1); ++ XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); ++ setfocus(c); ++ } + } else { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); +@@ -853,6 +859,7 @@ focusstack(const Arg *arg) + if (c) { + focus(c); + restack(selmon); ++ if (ispanel(c)) focusstack(arg); + } + } + +@@ -964,6 +971,11 @@ grabkeys(void) + } + } + ++int ++ispanel(Client *c) { ++ return !strcmp(c->name, panel[0]); ++} ++ + void + incnmaster(const Arg *arg) + { +@@ -1049,7 +1061,8 @@ manage(Window w, XWindowAttributes *wa) + c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) + && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); + c->bw = borderpx; +- ++ // no border - even when active ++ if (ispanel(c)) c->bw = c->oldbw = 0; + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); +@@ -1283,6 +1296,7 @@ resizeclient(Client *c, int x, int y, int w, int h) + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; + wc.border_width = c->bw; ++ if (ispanel(c)) c->y = c->oldy = c->bw = wc.y = wc.border_width = 0; + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); + XSync(dpy, False); +@@ -1991,7 +2005,7 @@ void + updatestatus(void) + { + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) +- strcpy(stext, "dwm-"VERSION); ++ strcpy(stext, " "); // no shining of dwm version thru panel, when transparent + drawbar(selmon); + } + +-- +2.31.1 + |