Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
e42bd55e46 | |||
cfb8627a80 | |||
fcb2476b69 | |||
8933ebcf50 | |||
5687f46964 |
@ -55,6 +55,8 @@ static const Layout layouts[] = {
|
|||||||
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
||||||
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||||
|
|
||||||
|
#define STATUSBAR "dwmblocks"
|
||||||
|
|
||||||
/* commands */
|
/* commands */
|
||||||
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
||||||
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
|
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
|
||||||
@ -104,7 +106,9 @@ static const Button buttons[] = {
|
|||||||
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
||||||
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
||||||
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
||||||
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
|
{ ClkStatusText, 0, Button1, sigstatusbar, {.i = 1} },
|
||||||
|
{ ClkStatusText, 0, Button2, sigstatusbar, {.i = 2} },
|
||||||
|
{ ClkStatusText, 0, Button3, sigstatusbar, {.i = 3} },
|
||||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
||||||
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
||||||
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
||||||
|
116
drw.c
116
drw.c
@ -9,54 +9,40 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#define UTF_INVALID 0xFFFD
|
#define UTF_INVALID 0xFFFD
|
||||||
#define UTF_SIZ 4
|
|
||||||
|
|
||||||
static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
|
static int
|
||||||
static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
|
utf8decode(const char *s_in, long *u, int *err)
|
||||||
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))
|
static const unsigned char lens[] = {
|
||||||
if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
|
/* 0XXXX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
return (unsigned char)c & ~utfmask[*i];
|
/* 10XXX */ 0, 0, 0, 0, 0, 0, 0, 0, /* invalid */
|
||||||
return 0;
|
/* 110XX */ 2, 2, 2, 2,
|
||||||
}
|
/* 1110X */ 3, 3,
|
||||||
|
/* 11110 */ 4,
|
||||||
static size_t
|
/* 11111 */ 0, /* invalid */
|
||||||
utf8validate(long *u, size_t i)
|
};
|
||||||
{
|
static const unsigned char leading_mask[] = { 0x7F, 0x1F, 0x0F, 0x07 };
|
||||||
if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
|
static const unsigned int overlong[] = { 0x0, 0x80, 0x0800, 0x10000 };
|
||||||
*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;
|
|
||||||
|
|
||||||
|
const unsigned char *s = (const unsigned char *)s_in;
|
||||||
|
int len = lens[*s >> 3];
|
||||||
*u = UTF_INVALID;
|
*u = UTF_INVALID;
|
||||||
if (!clen)
|
*err = 1;
|
||||||
return 0;
|
if (len == 0)
|
||||||
udecoded = utf8decodebyte(c[0], &len);
|
|
||||||
if (!BETWEEN(len, 1, UTF_SIZ))
|
|
||||||
return 1;
|
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);
|
|
||||||
|
|
||||||
|
long cp = s[0] & leading_mask[len - 1];
|
||||||
|
for (int i = 1; i < len; ++i) {
|
||||||
|
if (s[i] == '\0' || (s[i] & 0xC0) != 0x80)
|
||||||
|
return i;
|
||||||
|
cp = (cp << 6) | (s[i] & 0x3F);
|
||||||
|
}
|
||||||
|
/* out of range, surrogate, overlong encoding */
|
||||||
|
if (cp > 0x10FFFF || (cp >> 11) == 0x1B || cp < overlong[len - 1])
|
||||||
|
return len;
|
||||||
|
|
||||||
|
*err = 0;
|
||||||
|
*u = cp;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,11 +224,11 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
|
|||||||
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)
|
||||||
{
|
{
|
||||||
int i, ty, ellipsis_x = 0;
|
int ty, ellipsis_x = 0;
|
||||||
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len;
|
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1;
|
||||||
XftDraw *d = NULL;
|
XftDraw *d = NULL;
|
||||||
Fnt *usedfont, *curfont, *nextfont;
|
Fnt *usedfont, *curfont, *nextfont;
|
||||||
int utf8strlen, utf8charlen, render = x || y || w || h;
|
int utf8strlen, utf8charlen, utf8err, render = x || y || w || h;
|
||||||
long utf8codepoint = 0;
|
long utf8codepoint = 0;
|
||||||
const char *utf8str;
|
const char *utf8str;
|
||||||
FcCharSet *fccharset;
|
FcCharSet *fccharset;
|
||||||
@ -251,9 +237,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
|||||||
XftResult result;
|
XftResult result;
|
||||||
int charexists = 0, overflow = 0;
|
int charexists = 0, overflow = 0;
|
||||||
/* keep track of a couple codepoints for which we have no match. */
|
/* keep track of a couple codepoints for which we have no match. */
|
||||||
enum { nomatches_len = 64 };
|
static unsigned int nomatches[128], ellipsis_width, invalid_width;
|
||||||
static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches;
|
static const char invalid[] = "<EFBFBD>";
|
||||||
static unsigned int ellipsis_width = 0;
|
|
||||||
|
|
||||||
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
|
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
|
||||||
return 0;
|
return 0;
|
||||||
@ -263,6 +248,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
|||||||
} else {
|
} else {
|
||||||
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
||||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||||
|
if (w < lpad)
|
||||||
|
return x + w;
|
||||||
d = XftDrawCreate(drw->dpy, drw->drawable,
|
d = XftDrawCreate(drw->dpy, drw->drawable,
|
||||||
DefaultVisual(drw->dpy, drw->screen),
|
DefaultVisual(drw->dpy, drw->screen),
|
||||||
DefaultColormap(drw->dpy, drw->screen));
|
DefaultColormap(drw->dpy, drw->screen));
|
||||||
@ -273,12 +260,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
|||||||
usedfont = drw->fonts;
|
usedfont = drw->fonts;
|
||||||
if (!ellipsis_width && render)
|
if (!ellipsis_width && render)
|
||||||
ellipsis_width = drw_fontset_getwidth(drw, "...");
|
ellipsis_width = drw_fontset_getwidth(drw, "...");
|
||||||
|
if (!invalid_width && render)
|
||||||
|
invalid_width = drw_fontset_getwidth(drw, invalid);
|
||||||
while (1) {
|
while (1) {
|
||||||
ew = ellipsis_len = utf8strlen = 0;
|
ew = ellipsis_len = utf8err = utf8charlen = utf8strlen = 0;
|
||||||
utf8str = text;
|
utf8str = text;
|
||||||
nextfont = NULL;
|
nextfont = NULL;
|
||||||
while (*text) {
|
while (*text) {
|
||||||
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
|
utf8charlen = utf8decode(text, &utf8codepoint, &utf8err);
|
||||||
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
||||||
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
||||||
if (charexists) {
|
if (charexists) {
|
||||||
@ -300,9 +289,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
|||||||
else
|
else
|
||||||
utf8strlen = ellipsis_len;
|
utf8strlen = ellipsis_len;
|
||||||
} else if (curfont == usedfont) {
|
} else if (curfont == usedfont) {
|
||||||
utf8strlen += utf8charlen;
|
|
||||||
text += utf8charlen;
|
text += utf8charlen;
|
||||||
ew += tmpw;
|
utf8strlen += utf8err ? 0 : utf8charlen;
|
||||||
|
ew += utf8err ? 0 : tmpw;
|
||||||
} else {
|
} else {
|
||||||
nextfont = curfont;
|
nextfont = curfont;
|
||||||
}
|
}
|
||||||
@ -310,7 +299,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overflow || !charexists || nextfont)
|
if (overflow || !charexists || nextfont || utf8err)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
charexists = 0;
|
charexists = 0;
|
||||||
@ -325,6 +314,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
|||||||
x += ew;
|
x += ew;
|
||||||
w -= ew;
|
w -= ew;
|
||||||
}
|
}
|
||||||
|
if (utf8err && (!render || invalid_width < w)) {
|
||||||
|
if (render)
|
||||||
|
drw_text(drw, x, y, w, h, 0, invalid, invert);
|
||||||
|
x += invalid_width;
|
||||||
|
w -= invalid_width;
|
||||||
|
}
|
||||||
if (render && overflow)
|
if (render && overflow)
|
||||||
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
|
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
|
||||||
|
|
||||||
@ -338,11 +333,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
|||||||
* character must be drawn. */
|
* character must be drawn. */
|
||||||
charexists = 1;
|
charexists = 1;
|
||||||
|
|
||||||
for (i = 0; i < nomatches_len; ++i) {
|
hash = (unsigned int)utf8codepoint;
|
||||||
/* avoid calling XftFontMatch if we know we won't find a match */
|
hash = ((hash >> 16) ^ hash) * 0x21F0AAAD;
|
||||||
if (utf8codepoint == nomatches.codepoint[i])
|
hash = ((hash >> 15) ^ hash) * 0xD35A2D97;
|
||||||
goto no_match;
|
h0 = ((hash >> 15) ^ hash) % LENGTH(nomatches);
|
||||||
}
|
h1 = (hash >> 17) % LENGTH(nomatches);
|
||||||
|
/* avoid expensive XftFontMatch call when we know we won't find a match */
|
||||||
|
if (nomatches[h0] == utf8codepoint || nomatches[h1] == utf8codepoint)
|
||||||
|
goto no_match;
|
||||||
|
|
||||||
fccharset = FcCharSetCreate();
|
fccharset = FcCharSetCreate();
|
||||||
FcCharSetAddChar(fccharset, utf8codepoint);
|
FcCharSetAddChar(fccharset, utf8codepoint);
|
||||||
@ -371,7 +369,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
|||||||
curfont->next = usedfont;
|
curfont->next = usedfont;
|
||||||
} else {
|
} else {
|
||||||
xfont_free(usedfont);
|
xfont_free(usedfont);
|
||||||
nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
|
nomatches[nomatches[h0] ? h1 : h0] = utf8codepoint;
|
||||||
no_match:
|
no_match:
|
||||||
usedfont = drw->fonts;
|
usedfont = drw->fonts;
|
||||||
}
|
}
|
||||||
|
107
dwm.c
107
dwm.c
@ -50,7 +50,6 @@
|
|||||||
#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
|
#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 ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
|
||||||
#define LENGTH(X) (sizeof X / sizeof X[0])
|
|
||||||
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
|
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
|
||||||
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
|
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
|
||||||
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
|
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
|
||||||
@ -172,6 +171,7 @@ static void focusstack(const Arg *arg);
|
|||||||
static Atom getatomprop(Client *c, Atom prop);
|
static Atom getatomprop(Client *c, Atom prop);
|
||||||
static int getrootptr(int *x, int *y);
|
static int getrootptr(int *x, int *y);
|
||||||
static long getstate(Window w);
|
static long getstate(Window w);
|
||||||
|
static pid_t getstatusbarpid();
|
||||||
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
|
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
|
||||||
static void grabbuttons(Client *c, int focused);
|
static void grabbuttons(Client *c, int focused);
|
||||||
static void grabkeys(void);
|
static void grabkeys(void);
|
||||||
@ -205,6 +205,7 @@ static void setmfact(const Arg *arg);
|
|||||||
static void setup(void);
|
static void setup(void);
|
||||||
static void seturgent(Client *c, int urg);
|
static void seturgent(Client *c, int urg);
|
||||||
static void showhide(Client *c);
|
static void showhide(Client *c);
|
||||||
|
static void sigstatusbar(const Arg *arg);
|
||||||
static void spawn(const Arg *arg);
|
static void spawn(const Arg *arg);
|
||||||
static void tag(const Arg *arg);
|
static void tag(const Arg *arg);
|
||||||
static void tagmon(const Arg *arg);
|
static void tagmon(const Arg *arg);
|
||||||
@ -237,6 +238,9 @@ static void zoom(const Arg *arg);
|
|||||||
/* variables */
|
/* variables */
|
||||||
static const char broken[] = "broken";
|
static const char broken[] = "broken";
|
||||||
static char stext[256];
|
static char stext[256];
|
||||||
|
static int statusw;
|
||||||
|
static int statussig;
|
||||||
|
static pid_t statuspid = -1;
|
||||||
static int screen;
|
static int screen;
|
||||||
static int sw, sh; /* X display screen geometry width, height */
|
static int sw, sh; /* X display screen geometry width, height */
|
||||||
static int bh; /* bar height */
|
static int bh; /* bar height */
|
||||||
@ -423,6 +427,7 @@ buttonpress(XEvent *e)
|
|||||||
Client *c;
|
Client *c;
|
||||||
Monitor *m;
|
Monitor *m;
|
||||||
XButtonPressedEvent *ev = &e->xbutton;
|
XButtonPressedEvent *ev = &e->xbutton;
|
||||||
|
char *text, *s, ch;
|
||||||
|
|
||||||
click = ClkRootWin;
|
click = ClkRootWin;
|
||||||
/* focus monitor if necessary */
|
/* focus monitor if necessary */
|
||||||
@ -441,9 +446,27 @@ buttonpress(XEvent *e)
|
|||||||
arg.ui = 1 << i;
|
arg.ui = 1 << i;
|
||||||
} else if (ev->x < x + TEXTW(selmon->ltsymbol))
|
} else if (ev->x < x + TEXTW(selmon->ltsymbol))
|
||||||
click = ClkLtSymbol;
|
click = ClkLtSymbol;
|
||||||
else if (ev->x > selmon->ww - (int)TEXTW(stext))
|
else if (ev->x > selmon->ww - statusw) {
|
||||||
|
x = selmon->ww - statusw;
|
||||||
click = ClkStatusText;
|
click = ClkStatusText;
|
||||||
else
|
statussig = 0;
|
||||||
|
for (text = s = stext; *s && x <= ev->x; s++) {
|
||||||
|
if ((unsigned char)(*s) < ' ') {
|
||||||
|
ch = *s;
|
||||||
|
*s = '\0';
|
||||||
|
x += TEXTW(text) - lrpad;
|
||||||
|
*s = ch;
|
||||||
|
text = s + 1;
|
||||||
|
if (x >= ev->x)
|
||||||
|
break;
|
||||||
|
/* reset on matching signal raw byte */
|
||||||
|
if (ch == statussig)
|
||||||
|
statussig = 0;
|
||||||
|
else
|
||||||
|
statussig = ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
click = ClkWinTitle;
|
click = ClkWinTitle;
|
||||||
} else if ((c = wintoclient(ev->window))) {
|
} else if ((c = wintoclient(ev->window))) {
|
||||||
focus(c);
|
focus(c);
|
||||||
@ -709,9 +732,24 @@ drawbar(Monitor *m)
|
|||||||
|
|
||||||
/* draw status first so it can be overdrawn by tags later */
|
/* draw status first so it can be overdrawn by tags later */
|
||||||
if (m == selmon) { /* status is only drawn on selected monitor */
|
if (m == selmon) { /* status is only drawn on selected monitor */
|
||||||
|
char *text, *s, ch;
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
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);
|
x = 0;
|
||||||
|
for (text = s = stext; *s; s++) {
|
||||||
|
if ((unsigned char)(*s) < ' ') {
|
||||||
|
ch = *s;
|
||||||
|
*s = '\0';
|
||||||
|
tw = TEXTW(text) - lrpad;
|
||||||
|
drw_text(drw, m->ww - statusw + x, 0, tw, bh, 0, text, 0);
|
||||||
|
x += tw;
|
||||||
|
*s = ch;
|
||||||
|
text = s + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tw = TEXTW(text) - lrpad + 2;
|
||||||
|
drw_text(drw, m->ww - statusw + x, 0, tw, bh, 0, text, 0);
|
||||||
|
tw = statusw;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (c = m->clients; c; c = c->next) {
|
for (c = m->clients; c; c = c->next) {
|
||||||
@ -877,6 +915,30 @@ getatomprop(Client *c, Atom prop)
|
|||||||
return atom;
|
return atom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pid_t
|
||||||
|
getstatusbarpid()
|
||||||
|
{
|
||||||
|
char buf[32], *str = buf, *c;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if (statuspid > 0) {
|
||||||
|
snprintf(buf, sizeof(buf), "/proc/%u/cmdline", statuspid);
|
||||||
|
if ((fp = fopen(buf, "r"))) {
|
||||||
|
fgets(buf, sizeof(buf), fp);
|
||||||
|
while ((c = strchr(str, '/')))
|
||||||
|
str = c + 1;
|
||||||
|
fclose(fp);
|
||||||
|
if (!strcmp(str, STATUSBAR))
|
||||||
|
return statuspid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(fp = popen("pidof -s "STATUSBAR, "r")))
|
||||||
|
return -1;
|
||||||
|
fgets(buf, sizeof(buf), fp);
|
||||||
|
pclose(fp);
|
||||||
|
return strtol(buf, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
getrootptr(int *x, int *y)
|
getrootptr(int *x, int *y)
|
||||||
{
|
{
|
||||||
@ -1644,6 +1706,20 @@ showhide(Client *c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sigstatusbar(const Arg *arg)
|
||||||
|
{
|
||||||
|
union sigval sv;
|
||||||
|
|
||||||
|
if (!statussig)
|
||||||
|
return;
|
||||||
|
sv.sival_int = arg->i;
|
||||||
|
if ((statuspid = getstatusbarpid()) <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sigqueue(statuspid, SIGRTMIN+statussig, sv);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
spawn(const Arg *arg)
|
spawn(const Arg *arg)
|
||||||
{
|
{
|
||||||
@ -1851,7 +1927,7 @@ updatebarpos(Monitor *m)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
updateclientlist()
|
updateclientlist(void)
|
||||||
{
|
{
|
||||||
Client *c;
|
Client *c;
|
||||||
Monitor *m;
|
Monitor *m;
|
||||||
@ -2005,8 +2081,25 @@ updatesizehints(Client *c)
|
|||||||
void
|
void
|
||||||
updatestatus(void)
|
updatestatus(void)
|
||||||
{
|
{
|
||||||
if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
|
if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) {
|
||||||
strcpy(stext, "dwm-"VERSION);
|
strcpy(stext, "dwm-"VERSION);
|
||||||
|
statusw = TEXTW(stext) - lrpad + 2;
|
||||||
|
} else {
|
||||||
|
char *text, *s, ch;
|
||||||
|
|
||||||
|
statusw = 0;
|
||||||
|
for (text = s = stext; *s; s++) {
|
||||||
|
if ((unsigned char)(*s) < ' ') {
|
||||||
|
ch = *s;
|
||||||
|
*s = '\0';
|
||||||
|
statusw += TEXTW(text) - lrpad;
|
||||||
|
*s = ch;
|
||||||
|
text = s + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statusw += TEXTW(text) - lrpad + 2;
|
||||||
|
|
||||||
|
}
|
||||||
drawbar(selmon);
|
drawbar(selmon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
220
patches/dwm-statuscmd-20241009-8933ebc.diff
Normal file
220
patches/dwm-statuscmd-20241009-8933ebc.diff
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
From ca2a2e6386a746ebfc3480787e5d99da11e7abee Mon Sep 17 00:00:00 2001
|
||||||
|
From: Justinas Grigas <dev@jstnas.com>
|
||||||
|
Date: Wed, 9 Oct 2024 01:00:20 +0100
|
||||||
|
Subject: [PATCH] [dwm][statuscmd] better click regions
|
||||||
|
|
||||||
|
The main improvement of this patch over the previous version 20210405 is that
|
||||||
|
the click region now ends on a matching signal raw byte.
|
||||||
|
|
||||||
|
The matching byte is optional, and without it dwm will behave as before.
|
||||||
|
|
||||||
|
To take advantage of this feature, scripts need to be modified to print the raw
|
||||||
|
byte at the end as well.
|
||||||
|
|
||||||
|
In addition, this patch cleanly applies onto master branch.
|
||||||
|
---
|
||||||
|
config.def.h | 6 ++-
|
||||||
|
dwm.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||||
|
2 files changed, 104 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index 9efa774..d008275 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -55,6 +55,8 @@ static const Layout layouts[] = {
|
||||||
|
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
||||||
|
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||||
|
|
||||||
|
+#define STATUSBAR "dwmblocks"
|
||||||
|
+
|
||||||
|
/* commands */
|
||||||
|
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
||||||
|
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
|
||||||
|
@@ -104,7 +106,9 @@ static const Button buttons[] = {
|
||||||
|
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
||||||
|
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
||||||
|
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
||||||
|
- { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
|
||||||
|
+ { ClkStatusText, 0, Button1, sigstatusbar, {.i = 1} },
|
||||||
|
+ { ClkStatusText, 0, Button2, sigstatusbar, {.i = 2} },
|
||||||
|
+ { ClkStatusText, 0, Button3, sigstatusbar, {.i = 3} },
|
||||||
|
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
||||||
|
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
||||||
|
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
||||||
|
diff --git a/dwm.c b/dwm.c
|
||||||
|
index 1443802..94ee0c7 100644
|
||||||
|
--- a/dwm.c
|
||||||
|
+++ b/dwm.c
|
||||||
|
@@ -171,6 +171,7 @@ static void focusstack(const Arg *arg);
|
||||||
|
static Atom getatomprop(Client *c, Atom prop);
|
||||||
|
static int getrootptr(int *x, int *y);
|
||||||
|
static long getstate(Window w);
|
||||||
|
+static pid_t getstatusbarpid();
|
||||||
|
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
|
||||||
|
static void grabbuttons(Client *c, int focused);
|
||||||
|
static void grabkeys(void);
|
||||||
|
@@ -204,6 +205,7 @@ static void setmfact(const Arg *arg);
|
||||||
|
static void setup(void);
|
||||||
|
static void seturgent(Client *c, int urg);
|
||||||
|
static void showhide(Client *c);
|
||||||
|
+static void sigstatusbar(const Arg *arg);
|
||||||
|
static void spawn(const Arg *arg);
|
||||||
|
static void tag(const Arg *arg);
|
||||||
|
static void tagmon(const Arg *arg);
|
||||||
|
@@ -236,6 +238,9 @@ static void zoom(const Arg *arg);
|
||||||
|
/* variables */
|
||||||
|
static const char broken[] = "broken";
|
||||||
|
static char stext[256];
|
||||||
|
+static int statusw;
|
||||||
|
+static int statussig;
|
||||||
|
+static pid_t statuspid = -1;
|
||||||
|
static int screen;
|
||||||
|
static int sw, sh; /* X display screen geometry width, height */
|
||||||
|
static int bh; /* bar height */
|
||||||
|
@@ -422,6 +427,7 @@ buttonpress(XEvent *e)
|
||||||
|
Client *c;
|
||||||
|
Monitor *m;
|
||||||
|
XButtonPressedEvent *ev = &e->xbutton;
|
||||||
|
+ char *text, *s, ch;
|
||||||
|
|
||||||
|
click = ClkRootWin;
|
||||||
|
/* focus monitor if necessary */
|
||||||
|
@@ -440,9 +446,27 @@ buttonpress(XEvent *e)
|
||||||
|
arg.ui = 1 << i;
|
||||||
|
} else if (ev->x < x + TEXTW(selmon->ltsymbol))
|
||||||
|
click = ClkLtSymbol;
|
||||||
|
- else if (ev->x > selmon->ww - (int)TEXTW(stext))
|
||||||
|
+ else if (ev->x > selmon->ww - statusw) {
|
||||||
|
+ x = selmon->ww - statusw;
|
||||||
|
click = ClkStatusText;
|
||||||
|
- else
|
||||||
|
+ statussig = 0;
|
||||||
|
+ for (text = s = stext; *s && x <= ev->x; s++) {
|
||||||
|
+ if ((unsigned char)(*s) < ' ') {
|
||||||
|
+ ch = *s;
|
||||||
|
+ *s = '\0';
|
||||||
|
+ x += TEXTW(text) - lrpad;
|
||||||
|
+ *s = ch;
|
||||||
|
+ text = s + 1;
|
||||||
|
+ if (x >= ev->x)
|
||||||
|
+ break;
|
||||||
|
+ /* reset on matching signal raw byte */
|
||||||
|
+ if (ch == statussig)
|
||||||
|
+ statussig = 0;
|
||||||
|
+ else
|
||||||
|
+ statussig = ch;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ } else
|
||||||
|
click = ClkWinTitle;
|
||||||
|
} else if ((c = wintoclient(ev->window))) {
|
||||||
|
focus(c);
|
||||||
|
@@ -708,9 +732,24 @@ drawbar(Monitor *m)
|
||||||
|
|
||||||
|
/* draw status first so it can be overdrawn by tags later */
|
||||||
|
if (m == selmon) { /* status is only drawn on selected monitor */
|
||||||
|
+ char *text, *s, ch;
|
||||||
|
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);
|
||||||
|
+
|
||||||
|
+ x = 0;
|
||||||
|
+ for (text = s = stext; *s; s++) {
|
||||||
|
+ if ((unsigned char)(*s) < ' ') {
|
||||||
|
+ ch = *s;
|
||||||
|
+ *s = '\0';
|
||||||
|
+ tw = TEXTW(text) - lrpad;
|
||||||
|
+ drw_text(drw, m->ww - statusw + x, 0, tw, bh, 0, text, 0);
|
||||||
|
+ x += tw;
|
||||||
|
+ *s = ch;
|
||||||
|
+ text = s + 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ tw = TEXTW(text) - lrpad + 2;
|
||||||
|
+ drw_text(drw, m->ww - statusw + x, 0, tw, bh, 0, text, 0);
|
||||||
|
+ tw = statusw;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (c = m->clients; c; c = c->next) {
|
||||||
|
@@ -876,6 +915,30 @@ getatomprop(Client *c, Atom prop)
|
||||||
|
return atom;
|
||||||
|
}
|
||||||
|
|
||||||
|
+pid_t
|
||||||
|
+getstatusbarpid()
|
||||||
|
+{
|
||||||
|
+ char buf[32], *str = buf, *c;
|
||||||
|
+ FILE *fp;
|
||||||
|
+
|
||||||
|
+ if (statuspid > 0) {
|
||||||
|
+ snprintf(buf, sizeof(buf), "/proc/%u/cmdline", statuspid);
|
||||||
|
+ if ((fp = fopen(buf, "r"))) {
|
||||||
|
+ fgets(buf, sizeof(buf), fp);
|
||||||
|
+ while ((c = strchr(str, '/')))
|
||||||
|
+ str = c + 1;
|
||||||
|
+ fclose(fp);
|
||||||
|
+ if (!strcmp(str, STATUSBAR))
|
||||||
|
+ return statuspid;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (!(fp = popen("pidof -s "STATUSBAR, "r")))
|
||||||
|
+ return -1;
|
||||||
|
+ fgets(buf, sizeof(buf), fp);
|
||||||
|
+ pclose(fp);
|
||||||
|
+ return strtol(buf, NULL, 10);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
getrootptr(int *x, int *y)
|
||||||
|
{
|
||||||
|
@@ -1643,6 +1706,20 @@ showhide(Client *c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+sigstatusbar(const Arg *arg)
|
||||||
|
+{
|
||||||
|
+ union sigval sv;
|
||||||
|
+
|
||||||
|
+ if (!statussig)
|
||||||
|
+ return;
|
||||||
|
+ sv.sival_int = arg->i;
|
||||||
|
+ if ((statuspid = getstatusbarpid()) <= 0)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ sigqueue(statuspid, SIGRTMIN+statussig, sv);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
spawn(const Arg *arg)
|
||||||
|
{
|
||||||
|
@@ -2004,8 +2081,25 @@ updatesizehints(Client *c)
|
||||||
|
void
|
||||||
|
updatestatus(void)
|
||||||
|
{
|
||||||
|
- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
|
||||||
|
+ if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) {
|
||||||
|
strcpy(stext, "dwm-"VERSION);
|
||||||
|
+ statusw = TEXTW(stext) - lrpad + 2;
|
||||||
|
+ } else {
|
||||||
|
+ char *text, *s, ch;
|
||||||
|
+
|
||||||
|
+ statusw = 0;
|
||||||
|
+ for (text = s = stext; *s; s++) {
|
||||||
|
+ if ((unsigned char)(*s) < ' ') {
|
||||||
|
+ ch = *s;
|
||||||
|
+ *s = '\0';
|
||||||
|
+ statusw += TEXTW(text) - lrpad;
|
||||||
|
+ *s = ch;
|
||||||
|
+ text = s + 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ statusw += TEXTW(text) - lrpad + 2;
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
drawbar(selmon);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.46.2
|
||||||
|
|
13
util.c
13
util.c
@ -1,4 +1,5 @@
|
|||||||
/* See LICENSE file for copyright and license details. */
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
#include <errno.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -10,17 +11,17 @@ void
|
|||||||
die(const char *fmt, ...)
|
die(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
int saved_errno;
|
||||||
|
|
||||||
|
saved_errno = errno;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
|
if (fmt[0] && fmt[strlen(fmt)-1] == ':')
|
||||||
fputc(' ', stderr);
|
fprintf(stderr, " %s", strerror(saved_errno));
|
||||||
perror(NULL);
|
fputc('\n', stderr);
|
||||||
} else {
|
|
||||||
fputc('\n', stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
1
util.h
1
util.h
@ -3,6 +3,7 @@
|
|||||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||||
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
|
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
|
||||||
|
#define LENGTH(X) (sizeof (X) / sizeof (X)[0])
|
||||||
|
|
||||||
void die(const char *fmt, ...);
|
void die(const char *fmt, ...);
|
||||||
void *ecalloc(size_t nmemb, size_t size);
|
void *ecalloc(size_t nmemb, size_t size);
|
||||||
|
Reference in New Issue
Block a user