Compare commits

..

1 Commits

Author SHA1 Message Date
1aa2f720a6 patched statuscmd 2025-04-18 21:48:01 +09:30
7 changed files with 339 additions and 52 deletions

View File

@ -1,6 +1,5 @@
MIT/X Consortium License
© 2010-2026 Hiltjo Posthuma <hiltjo@codemadness.org>
© 2006-2019 Anselm R Garbe <anselm@garbe.ca>
© 2006-2009 Jukka Salmi <jukka at salmi dot ch>
© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
@ -12,6 +11,7 @@ MIT/X Consortium License
© 2008 Martin Hurton <martin dot hurton at gmail dot com>
© 2008 Neale Pickett <neale dot woozle dot org>
© 2009 Mate Nagy <mnagy at port70 dot net>
© 2010-2016 Hiltjo Posthuma <hiltjo@codemadness.org>
© 2010-2012 Connor Lane Smith <cls@lubutu.com>
© 2011 Christoph Lohmann <20h@r-36.net>
© 2015-2016 Quentin Rameau <quinq@fifth.space>

View File

@ -36,7 +36,6 @@ static const float mfact = 0.55; /* factor of master area size [0.05..0.95]
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
static const int refreshrate = 120; /* refresh rate (per second) for client move/resize */
static const Layout layouts[] = {
/* symbol arrange function */

View File

@ -1,5 +1,5 @@
# dwm version
VERSION = 6.8
VERSION = 6.5
# Customize below to fit your system

29
drw.c
View File

@ -178,7 +178,8 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
die("error, cannot allocate color '%s'", clrname);
}
/* Create color schemes. */
/* Wrapper to create color schemes. The caller has to call free(3) on the
* returned color scheme when done using it. */
Clr *
drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
{
@ -186,7 +187,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
Clr *ret;
/* need at least two colors for a scheme */
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(Clr))))
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
return NULL;
for (i = 0; i < clrcount; i++)
@ -194,30 +195,6 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
return ret;
}
void
drw_clr_free(Drw *drw, Clr *c)
{
if (!drw || !c)
return;
/* c is typedef XftColor Clr */
XftColorFree(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
DefaultColormap(drw->dpy, drw->screen), c);
}
void
drw_scm_free(Drw *drw, Clr *scm, size_t clrcount)
{
size_t i;
if (!drw || !scm)
return;
for (i = 0; i < clrcount; i++)
drw_clr_free(drw, &scm[i]);
free(scm);
}
void
drw_setfontset(Drw *drw, Fnt *set)
{

2
drw.h
View File

@ -40,9 +40,7 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in
/* Colorscheme abstraction */
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
void drw_clr_free(Drw *drw, Clr *c);
Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
void drw_scm_free(Drw *drw, Clr *scm, size_t clrcount);
/* Cursor abstraction */
Cur *drw_cur_create(Drw *drw, int shape);

View 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

133
dwm.c
View File

@ -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) + lrpad - 2)
else if (ev->x > selmon->ww - statusw) {
x = selmon->ww - statusw;
click = ClkStatusText;
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);
@ -486,7 +510,7 @@ cleanup(void)
for (i = 0; i < CurLast; i++)
drw_cur_free(drw, cursor[i]);
for (i = 0; i < LENGTH(colors); i++)
drw_scm_free(drw, scheme[i], 3);
free(scheme[i]);
free(scheme);
XDestroyWindow(dpy, wmcheckwin);
drw_free(drw);
@ -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) {
@ -863,20 +902,43 @@ focusstack(const Arg *arg)
Atom
getatomprop(Client *c, Atom prop)
{
int format;
unsigned long nitems, dl;
int di;
unsigned long dl;
unsigned char *p = NULL;
Atom da, atom = None;
if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
&da, &format, &nitems, &dl, &p) == Success && p) {
if (nitems > 0 && format == 32)
atom = *(long *)p;
&da, &di, &dl, &dl, &p) == Success && p) {
atom = *(Atom *)p;
XFree(p);
}
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)
{
@ -897,10 +959,10 @@ getstate(Window w)
Atom real;
if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
&real, &format, &n, &extra, &p) != Success)
&real, &format, &n, &extra, (unsigned char **)&p) != Success)
return -1;
if (n != 0 && format == 32)
result = *(long *)p;
if (n != 0)
result = *p;
XFree(p);
return result;
}
@ -1172,7 +1234,7 @@ movemouse(const Arg *arg)
handler[ev.type](&ev);
break;
case MotionNotify:
if ((ev.xmotion.time - lasttime) <= (1000 / refreshrate))
if ((ev.xmotion.time - lasttime) <= (1000 / 60))
continue;
lasttime = ev.xmotion.time;
@ -1326,7 +1388,7 @@ resizemouse(const Arg *arg)
handler[ev.type](&ev);
break;
case MotionNotify:
if ((ev.xmotion.time - lasttime) <= (1000 / refreshrate))
if ((ev.xmotion.time - lasttime) <= (1000 / 60))
continue;
lasttime = ev.xmotion.time;
@ -1429,8 +1491,6 @@ sendmon(Client *c, Monitor *m)
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
attach(c);
attachstack(c);
if (c->isfullscreen)
resizeclient(c, m->mx, m->my, m->mw, m->mh);
focus(NULL);
arrange(NULL);
}
@ -1472,10 +1532,12 @@ sendevent(Client *c, Atom proto)
void
setfocus(Client *c)
{
if (!c->neverfocus)
if (!c->neverfocus) {
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
XChangeProperty(dpy, root, netatom[NetActiveWindow], XA_WINDOW, 32,
PropModeReplace, (unsigned char *)&c->win, 1);
XChangeProperty(dpy, root, netatom[NetActiveWindow],
XA_WINDOW, 32, PropModeReplace,
(unsigned char *) &(c->win), 1);
}
sendevent(c, wmatom[WMTakeFocus]);
}
@ -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)
{
@ -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);
}