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 */
|
||||
#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} },
|
||||
|
116
drw.c
116
drw.c
@ -9,54 +9,40 @@
|
||||
#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)
|
||||
static int
|
||||
utf8decode(const char *s_in, long *u, int *err)
|
||||
{
|
||||
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;
|
||||
static const unsigned char lens[] = {
|
||||
/* 0XXXX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
/* 10XXX */ 0, 0, 0, 0, 0, 0, 0, 0, /* invalid */
|
||||
/* 110XX */ 2, 2, 2, 2,
|
||||
/* 1110X */ 3, 3,
|
||||
/* 11110 */ 4,
|
||||
/* 11111 */ 0, /* invalid */
|
||||
};
|
||||
static const unsigned char leading_mask[] = { 0x7F, 0x1F, 0x0F, 0x07 };
|
||||
static const unsigned int overlong[] = { 0x0, 0x80, 0x0800, 0x10000 };
|
||||
|
||||
const unsigned char *s = (const unsigned char *)s_in;
|
||||
int len = lens[*s >> 3];
|
||||
*u = UTF_INVALID;
|
||||
if (!clen)
|
||||
return 0;
|
||||
udecoded = utf8decodebyte(c[0], &len);
|
||||
if (!BETWEEN(len, 1, UTF_SIZ))
|
||||
*err = 1;
|
||||
if (len == 0)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -238,11 +224,11 @@ 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)
|
||||
{
|
||||
int i, ty, ellipsis_x = 0;
|
||||
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len;
|
||||
int ty, ellipsis_x = 0;
|
||||
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1;
|
||||
XftDraw *d = NULL;
|
||||
Fnt *usedfont, *curfont, *nextfont;
|
||||
int utf8strlen, utf8charlen, render = x || y || w || h;
|
||||
int utf8strlen, utf8charlen, utf8err, render = x || y || w || h;
|
||||
long utf8codepoint = 0;
|
||||
const char *utf8str;
|
||||
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;
|
||||
int charexists = 0, overflow = 0;
|
||||
/* keep track of a couple codepoints for which we have no match. */
|
||||
enum { nomatches_len = 64 };
|
||||
static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches;
|
||||
static unsigned int ellipsis_width = 0;
|
||||
static unsigned int nomatches[128], ellipsis_width, invalid_width;
|
||||
static const char invalid[] = "<EFBFBD>";
|
||||
|
||||
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
|
||||
return 0;
|
||||
@ -263,6 +248,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||
} else {
|
||||
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||
if (w < lpad)
|
||||
return x + w;
|
||||
d = XftDrawCreate(drw->dpy, drw->drawable,
|
||||
DefaultVisual(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;
|
||||
if (!ellipsis_width && render)
|
||||
ellipsis_width = drw_fontset_getwidth(drw, "...");
|
||||
if (!invalid_width && render)
|
||||
invalid_width = drw_fontset_getwidth(drw, invalid);
|
||||
while (1) {
|
||||
ew = ellipsis_len = utf8strlen = 0;
|
||||
ew = ellipsis_len = utf8err = utf8charlen = utf8strlen = 0;
|
||||
utf8str = text;
|
||||
nextfont = NULL;
|
||||
while (*text) {
|
||||
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
|
||||
utf8charlen = utf8decode(text, &utf8codepoint, &utf8err);
|
||||
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
||||
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
||||
if (charexists) {
|
||||
@ -300,9 +289,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||
else
|
||||
utf8strlen = ellipsis_len;
|
||||
} else if (curfont == usedfont) {
|
||||
utf8strlen += utf8charlen;
|
||||
text += utf8charlen;
|
||||
ew += tmpw;
|
||||
utf8strlen += utf8err ? 0 : utf8charlen;
|
||||
ew += utf8err ? 0 : tmpw;
|
||||
} else {
|
||||
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;
|
||||
else
|
||||
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;
|
||||
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)
|
||||
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. */
|
||||
charexists = 1;
|
||||
|
||||
for (i = 0; i < nomatches_len; ++i) {
|
||||
/* avoid calling XftFontMatch if we know we won't find a match */
|
||||
if (utf8codepoint == nomatches.codepoint[i])
|
||||
goto no_match;
|
||||
}
|
||||
hash = (unsigned int)utf8codepoint;
|
||||
hash = ((hash >> 16) ^ hash) * 0x21F0AAAD;
|
||||
hash = ((hash >> 15) ^ hash) * 0xD35A2D97;
|
||||
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();
|
||||
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;
|
||||
} else {
|
||||
xfont_free(usedfont);
|
||||
nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
|
||||
nomatches[nomatches[h0] ? h1 : h0] = utf8codepoint;
|
||||
no_match:
|
||||
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)) \
|
||||
* 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)
|
||||
#define WIDTH(X) ((X)->w + 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 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);
|
||||
@ -205,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);
|
||||
@ -237,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 */
|
||||
@ -423,6 +427,7 @@ buttonpress(XEvent *e)
|
||||
Client *c;
|
||||
Monitor *m;
|
||||
XButtonPressedEvent *ev = &e->xbutton;
|
||||
char *text, *s, ch;
|
||||
|
||||
click = ClkRootWin;
|
||||
/* focus monitor if necessary */
|
||||
@ -441,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);
|
||||
@ -709,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) {
|
||||
@ -877,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)
|
||||
{
|
||||
@ -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
|
||||
spawn(const Arg *arg)
|
||||
{
|
||||
@ -1851,7 +1927,7 @@ updatebarpos(Monitor *m)
|
||||
}
|
||||
|
||||
void
|
||||
updateclientlist()
|
||||
updateclientlist(void)
|
||||
{
|
||||
Client *c;
|
||||
Monitor *m;
|
||||
@ -2005,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);
|
||||
}
|
||||
|
||||
|
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. */
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -10,17 +11,17 @@ void
|
||||
die(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int saved_errno;
|
||||
|
||||
saved_errno = errno;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
|
||||
fputc(' ', stderr);
|
||||
perror(NULL);
|
||||
} else {
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
if (fmt[0] && fmt[strlen(fmt)-1] == ':')
|
||||
fprintf(stderr, " %s", strerror(saved_errno));
|
||||
fputc('\n', stderr);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
Reference in New Issue
Block a user