From e48168fbfa734d4af61ca47af139b1c4b6d9145f Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sun, 19 Jul 2020 17:53:47 +0200 Subject: [PATCH] Powerline patch - adds arrows for tags and status https://gitlab.com/udiboy1209-suckless/dwm/-/commit/071f5063e8ac4280666828179f92788d893eea40 --- config.def.h | 16 +++++-- drw.c | 51 +++++++++++++++++++-- drw.h | 2 + dwm.c | 126 +++++++++++++++++++++++++++++++++++++++------------ 4 files changed, 159 insertions(+), 36 deletions(-) diff --git a/config.def.h b/config.def.h index 1c0b587..9f5b028 100644 --- a/config.def.h +++ b/config.def.h @@ -13,9 +13,19 @@ static const char col_gray3[] = "#bbbbbb"; static const char col_gray4[] = "#eeeeee"; static const char col_cyan[] = "#005577"; static const char *colors[][3] = { - /* fg bg border */ - [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, - [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + /* fg bg border */ + [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + [SchemeTitle] = { "#554433", "#FF4444", "#44FF44" }, + [SchemeTitleSel] = { "#4444FF", "#884400", "#440044" }, +}; + +static const char *statuscolors[][3] = { + /* fg bg border */ + [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + [SchemeTitle] = { "#554433", "#FF4444", "#44FF44" }, + [SchemeTitleSel] = { "#4444FF", "#884400", "#440044" }, }; /* tagging */ diff --git a/drw.c b/drw.c index 8fd1ca4..e9b6003 100644 --- a/drw.c +++ b/drw.c @@ -15,6 +15,7 @@ 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}; +Clr transcheme[3]; static long utf8decodebyte(const char c, size_t *i) @@ -199,8 +200,8 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname) return; if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen), - clrname, dest)) + DefaultColormap(drw->dpy, drw->screen), + clrname, dest)) die("error, cannot allocate color '%s'", clrname); } @@ -235,6 +236,15 @@ drw_setscheme(Drw *drw, Clr *scm) drw->scheme = scm; } +void +drw_settrans(Drw *drw, Clr *psc, Clr *nsc) +{ + if (drw) { + transcheme[0] = psc[ColBg]; transcheme[1] = nsc[ColBg]; transcheme[2] = psc[ColBorder]; + drw->scheme = transcheme; + } +} + void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) { @@ -274,8 +284,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); d = XftDrawCreate(drw->dpy, drw->drawable, - DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen)); + DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen)); x += lpad; w -= lpad; } @@ -322,7 +332,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp 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); + usedfont->xfont, x, ty, (XftChar8 *)buf, len); } x += ew; w -= ew; @@ -378,6 +388,37 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp return x + (render ? w : 0); } +void +drw_arrow(Drw *drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash) +{ + if (!drw || !drw->scheme) + return; + + /* direction=1 draws right arrow */ + x = direction ? x : x + w; + w = direction ? w : -w; + /* slash=1 draws slash instead of arrow */ + unsigned int hh = slash ? (direction ? 0 : h) : h/2; + + XPoint points[] = { + {x , y }, + {x + w, y + hh }, + {x , y + h }, + }; + + XPoint bg[] = { + {x , y }, + {x + w, y }, + {x + w, y + h}, + {x , y + h}, + }; + + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillPolygon(drw->dpy, drw->drawable, drw->gc, bg, 4, Convex, CoordModeOrigin); + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColFg].pixel); + XFillPolygon(drw->dpy, drw->drawable, drw->gc, points, 3, Nonconvex, CoordModeOrigin); +} + void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) { diff --git a/drw.h b/drw.h index 4bcd5ad..fc4f3bb 100644 --- a/drw.h +++ b/drw.h @@ -48,10 +48,12 @@ 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); +void drw_settrans(Drw *drw, Clr *psc, Clr *nsc); /* 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); +void drw_arrow(Drw* drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash); /* 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 4465af1..0604315 100644 --- a/dwm.c +++ b/dwm.c @@ -48,7 +48,7 @@ #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) + * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) #define LENGTH(X) (sizeof X / sizeof X[0]) #define MOUSEMASK (BUTTONMASK|PointerMotionMask) @@ -59,13 +59,13 @@ /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -enum { SchemeNorm, SchemeSel }; /* color schemes */ +enum { SchemeNorm, SchemeSel, SchemeTitle, SchemeTitleSel }; /* color schemes */ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ typedef union { int i; @@ -162,6 +162,7 @@ static void detach(Client *c); static void detachstack(Client *c); static Monitor *dirtomon(int dir); static void drawbar(Monitor *m); +static int drawstatus(Monitor *m); static void drawbars(void); static void enternotify(XEvent *e); static void expose(XEvent *e); @@ -239,7 +240,7 @@ static const char broken[] = "broken"; 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 bh, plw, blw = 0; /* bar geometry */ static int lrpad; /* sum of left and right padding for text */ static int (*xerrorxlib)(Display *, XErrorEvent *); static unsigned int numlockmask = 0; @@ -263,6 +264,7 @@ static Atom wmatom[WMLast], netatom[NetLast]; static int running = 1; static Cur *cursor[CurLast]; static Clr **scheme; +static Clr **statusscheme; static Display *dpy; static Drw *drw; static Monitor *mons, *selmon; @@ -430,9 +432,9 @@ buttonpress(XEvent *e) focus(NULL); } if (ev->window == selmon->barwin) { - i = x = 0; + i = 0; x = plw; do - x += TEXTW(tags[i]); + x += TEXTW(tags[i]) + plw; while (ev->x >= x && ++i < LENGTH(tags)); if (i < LENGTH(tags)) { click = ClkTagBar; @@ -695,53 +697,118 @@ dirtomon(int dir) void drawbar(Monitor *m) { - int x, w, sw = 0; - int boxs = drw->fonts->h / 9; - int boxw = drw->fonts->h / 6 + 2; - unsigned int i, occ = 0, urg = 0; + int x, w, wt, sw = 0; + unsigned int i, occ = 0, urg = 0, n = 0; + plw = drw->fonts->h / 2 + 1; Client *c; + Clr *prevscheme, *nxtscheme; /* 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]); - sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ - drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); + sw = drawstatus(m); } for (c = m->clients; c; c = c->next) { + if (ISVISIBLE(c)) n++; occ |= c->tags; if (c->isurgent) urg |= c->tags; } x = 0; + + prevscheme = scheme[SchemeNorm]; for (i = 0; i < LENGTH(tags); i++) { w = TEXTW(tags[i]); - drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); + drw_settrans(drw, prevscheme, (nxtscheme = scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm])); + drw_arrow(drw, x, 0, plw, bh, 1, 0); + x += plw; + + drw_setscheme(drw, nxtscheme); drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); - if (occ & 1 << i) - drw_rect(drw, x + boxs, boxs, boxw, boxw, - m == selmon && selmon->sel && selmon->sel->tags & 1 << i, - urg & 1 << i); x += w; + + prevscheme = nxtscheme; + } + nxtscheme = scheme[SchemeNorm]; + + drw_settrans(drw, prevscheme, nxtscheme); + drw_arrow(drw, x, 0, plw, bh, 1, 0); + x += plw; + w = blw = TEXTW(m->ltsymbol); drw_setscheme(drw, scheme[SchemeNorm]); x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); - if ((w = m->ww - sw - 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); - if (m->sel->isfloating) - drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); - } else { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x, 0, w, bh, 1, 1); + if ((m->ww - sw - x) > bh && n > 0) { + wt = (m->ww - sw - x) / n - 2 * plw; + for (c = m->clients; c; c = c->next) { + if (!ISVISIBLE(c)) continue; /* only show titles of windows on current tag */ + drw_setscheme(drw, c == m->sel ? scheme[SchemeTitleSel] : scheme[SchemeTitle]); + drw_text(drw, x + plw, 0, wt, bh, lrpad / 2, c->name, 0); + + drw_settrans(drw, c == m->sel ? scheme[SchemeTitleSel] : scheme[SchemeTitle], scheme[SchemeNorm]); + drw_arrow(drw, x, 0, plw, bh, 0, 1); + drw_arrow(drw, x + wt + plw, 0, plw, bh, 1, 1); + + x += wt + 2 * plw; } } + + if (x < m->ww - sw) { /* when empty or not enough space to draw, clear out the title space */ + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x, 0, m->ww - sw - x, bh, 1, 1); + } drw_map(drw, m->barwin, 0, 0, m->ww, bh); } +int +drawstatus(Monitor* m) +{ + char status[256]; + int i, n = strlen(stext), cn = 0; + int x = m->ww, w = 0; + char *bs, bp = '|'; + Clr *prevscheme = statusscheme[0], *nxtscheme; + + strcpy(status, stext); + + for (i = n, bs = &status[n-1]; i >= 0; i--, bs--) { + if (*bs == '<' || *bs == '/' || *bs == '\\' || *bs == '|') { /* block start */ + cn = ((int) *(bs+1)) - 1; + + if (cn < LENGTH(statuscolors)) { + drw_settrans(drw, prevscheme, (nxtscheme = statusscheme[cn])); + } else { + drw_settrans(drw, prevscheme, (nxtscheme = statusscheme[0])); + } + + if (bp != '|') { + drw_arrow(drw, x - plw, 0, plw, bh, bp == '\\' ? 1 : 0, bp == '<' ? 0 : 1); + x -= plw; + } + + drw_setscheme(drw, nxtscheme); + w = TEXTW(bs+2); + drw_text(drw, x - w, 0, w, bh, lrpad / 2, bs+2, 0); + x -= w; + + bp = *bs; + *bs = 0; + prevscheme = nxtscheme; + } + } + if (bp != '|') { + drw_settrans(drw, prevscheme, scheme[SchemeNorm]); + drw_arrow(drw, x - plw, 0, plw, bh, bp == '\\' ? 1 : 0, bp == '<' ? 0 : 1); + drw_rect(drw, x - 2 * plw, 0, plw, bh, 1, 1); + x -= plw * 2; + } + + return m->ww - x; +} + void drawbars(void) { @@ -1570,6 +1637,9 @@ setup(void) scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); for (i = 0; i < LENGTH(colors); i++) scheme[i] = drw_scm_create(drw, colors[i], 3); + statusscheme = ecalloc(LENGTH(statuscolors), sizeof(Clr *)); + for (i = 0; i < LENGTH(statuscolors); i++) + statusscheme[i] = drw_scm_create(drw, statuscolors[i], 3); /* init bars */ updatebars(); updatestatus(); -- 2.19.1