sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

commit d32be9143c87a7f8207b22ab52c8953b21f70b66
parent b56acc51c310aec0464ba6e12ce039a4c23ff14c
Author: Justinas Grigas <dev@jstnas.com>
Date:   Wed,  9 Oct 2024 01:37:06 +0100

[dwm][patch][statuscmd] better click regions

Added and updated version of the patch with support for ending clickable
regions using matching raw bytes.

Diffstat:
Adwm.suckless.org/patches/statuscmd/dwm-statuscmd-20241009-8933ebc.diff | 220+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdwm.suckless.org/patches/statuscmd/index.md | 8+++++++-
2 files changed, 227 insertions(+), 1 deletion(-)

diff --git a/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-20241009-8933ebc.diff b/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-20241009-8933ebc.diff @@ -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 + diff --git a/dwm.suckless.org/patches/statuscmd/index.md b/dwm.suckless.org/patches/statuscmd/index.md @@ -26,6 +26,8 @@ status monitors. * Associate each section with a signal number in the range of 1-31. * When setting the status text, print each section's respective signal number as a raw byte before its text. +* With the 20241009 patch, printing the raw byte again at the end of block + output will end the clickable region. * Create a signal handler: void sighandler(int signum, siginfo_t *si, void *ucontext) @@ -59,7 +61,7 @@ For example, with `statuscmds` defined as such: And root name set like this: - xsetroot -name "$(printf '\x01Volume |\x02 CPU |\x03 Battery')" + xsetroot -name "$(printf '\x01 Volume \x01|\x02 CPU \x02|\x03 Battery\x03')" Clicking on 'Volume |' would run `volume`, clicking on ' CPU |' would run `cpu` and clicking on ' Battery' would run `battery`. @@ -75,6 +77,8 @@ A script run from dwm or dwmblocks with this patch might look like this: 3) st -e htop ;; esac + printf '\x01Click Me!\x01' + Notes ----- The signal version is not compatible with OpenBSD since it relies on `sigqueue`. @@ -88,6 +92,7 @@ Download -------- ### dwm patches * [dwm-statuscmd-20210405-67d76bd.diff](dwm-statuscmd-20210405-67d76bd.diff) +* [dwm-statuscmd-20241009-8933ebc.diff](./dwm-statuscmd-20241009-8933ebc.diff) * [dwm-statuscmd-nosignal-20210402-67d76bd.diff](dwm-statuscmd-nosignal-20210402-67d76bd.diff) If using [status2d](https://dwm.suckless.org/patches/status2d/), use these patches instead of the @@ -103,3 +108,4 @@ above ones on top of a build already patched with status2d: Author ------ * Daniel Bylinka - <daniel.bylinka@gmail.com> +* Justinas Grigas - <dev@jstnas.com> (20241009)