commit d32be9143c87a7f8207b22ab52c8953b21f70b66
Author: Justinas Grigas <[email protected]>
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
@@ -0,0 +1,220 @@
+From ca2a2e6386a746ebfc3480787e5d99da11e7abee Mon Sep 17 00:00:00 2001
+From: Justinas Grigas <[email protected]>
+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 = '++                                
        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 = '++                                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 = '++                                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
@@ -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 - <[email protected]>
+* Justinas Grigas - <[email protected]> (20241009)


Reply via email to