[wiki] [sites] [dwm][patch][statuscmd] better click regions || Justinas Grigas

From: <git_AT_suckless.org>
Date: Wed, 09 Oct 2024 02:40:10 +0200

commit d32be9143c87a7f8207b22ab52c8953b21f70b66
Author: Justinas Grigas <dev_AT_jstnas.com>
Date: Wed Oct 9 01:37:06 2024 +0100

    [dwm][patch][statuscmd] better click regions
    
    Added and updated version of the patch with support for ending clickable
    regions using matching raw bytes.

diff --git a/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-20241009-8933ebc.diff b/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-20241009-8933ebc.diff
new file mode 100644
index 00000000..70de1bdb
--- /dev/null
+++ b/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-20241009-8933ebc.diff
_AT_@ -0,0 +1,220 @@
+From ca2a2e6386a746ebfc3480787e5d99da11e7abee Mon Sep 17 00:00:00 2001
+From: Justinas Grigas <dev_AT_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
+_AT_@ -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 };
+_AT_@ -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
+_AT_@ -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);
+_AT_@ -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);
+_AT_@ -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 */
+_AT_@ -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 */
+_AT_@ -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 = '++ 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);
+_AT_@ -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 = '++ 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) {
+_AT_@ -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)
+ {
+_AT_@ -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)
+ {
+_AT_@ -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 = '++ 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
index 04d23628..830e96c5 100644
--- a/dwm.suckless.org/patches/statuscmd/index.md
+++ b/dwm.suckless.org/patches/statuscmd/index.md
_AT_@ -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)
_AT_@ -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`.
_AT_@ -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`.
_AT_@ -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
_AT_@ -103,3 +108,4 @@ above ones on top of a build already patched with status2d:
 Author
 ------
 * Daniel Bylinka - <daniel.bylinka_AT_gmail.com>
+* Justinas Grigas - <dev_AT_jstnas.com> (20241009)
Received on Wed Oct 09 2024 - 02:40:10 CEST

This archive was generated by hypermail 2.3.0 : Wed Oct 09 2024 - 02:48:50 CEST