dwm-statuscmd-20241009-8933ebc.diff (6623B)
1 From ca2a2e6386a746ebfc3480787e5d99da11e7abee Mon Sep 17 00:00:00 2001 2 From: Justinas Grigas <dev@jstnas.com> 3 Date: Wed, 9 Oct 2024 01:00:20 +0100 4 Subject: [PATCH] [dwm][statuscmd] better click regions 5 6 The main improvement of this patch over the previous version 20210405 is that 7 the click region now ends on a matching signal raw byte. 8 9 The matching byte is optional, and without it dwm will behave as before. 10 11 To take advantage of this feature, scripts need to be modified to print the raw 12 byte at the end as well. 13 14 In addition, this patch cleanly applies onto master branch. 15 --- 16 config.def.h | 6 ++- 17 dwm.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++--- 18 2 files changed, 104 insertions(+), 6 deletions(-) 19 20 diff --git a/config.def.h b/config.def.h 21 index 9efa774..d008275 100644 22 --- a/config.def.h 23 +++ b/config.def.h 24 @@ -55,6 +55,8 @@ static const Layout layouts[] = { 25 /* helper for spawning shell commands in the pre dwm-5.0 fashion */ 26 #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } 27 28 +#define STATUSBAR "dwmblocks" 29 + 30 /* commands */ 31 static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ 32 static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; 33 @@ -104,7 +106,9 @@ static const Button buttons[] = { 34 { ClkLtSymbol, 0, Button1, setlayout, {0} }, 35 { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, 36 { ClkWinTitle, 0, Button2, zoom, {0} }, 37 - { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, 38 + { ClkStatusText, 0, Button1, sigstatusbar, {.i = 1} }, 39 + { ClkStatusText, 0, Button2, sigstatusbar, {.i = 2} }, 40 + { ClkStatusText, 0, Button3, sigstatusbar, {.i = 3} }, 41 { ClkClientWin, MODKEY, Button1, movemouse, {0} }, 42 { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, 43 { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, 44 diff --git a/dwm.c b/dwm.c 45 index 1443802..94ee0c7 100644 46 --- a/dwm.c 47 +++ b/dwm.c 48 @@ -171,6 +171,7 @@ static void focusstack(const Arg *arg); 49 static Atom getatomprop(Client *c, Atom prop); 50 static int getrootptr(int *x, int *y); 51 static long getstate(Window w); 52 +static pid_t getstatusbarpid(); 53 static int gettextprop(Window w, Atom atom, char *text, unsigned int size); 54 static void grabbuttons(Client *c, int focused); 55 static void grabkeys(void); 56 @@ -204,6 +205,7 @@ static void setmfact(const Arg *arg); 57 static void setup(void); 58 static void seturgent(Client *c, int urg); 59 static void showhide(Client *c); 60 +static void sigstatusbar(const Arg *arg); 61 static void spawn(const Arg *arg); 62 static void tag(const Arg *arg); 63 static void tagmon(const Arg *arg); 64 @@ -236,6 +238,9 @@ static void zoom(const Arg *arg); 65 /* variables */ 66 static const char broken[] = "broken"; 67 static char stext[256]; 68 +static int statusw; 69 +static int statussig; 70 +static pid_t statuspid = -1; 71 static int screen; 72 static int sw, sh; /* X display screen geometry width, height */ 73 static int bh; /* bar height */ 74 @@ -422,6 +427,7 @@ buttonpress(XEvent *e) 75 Client *c; 76 Monitor *m; 77 XButtonPressedEvent *ev = &e->xbutton; 78 + char *text, *s, ch; 79 80 click = ClkRootWin; 81 /* focus monitor if necessary */ 82 @@ -440,9 +446,27 @@ buttonpress(XEvent *e) 83 arg.ui = 1 << i; 84 } else if (ev->x < x + TEXTW(selmon->ltsymbol)) 85 click = ClkLtSymbol; 86 - else if (ev->x > selmon->ww - (int)TEXTW(stext)) 87 + else if (ev->x > selmon->ww - statusw) { 88 + x = selmon->ww - statusw; 89 click = ClkStatusText; 90 - else 91 + statussig = 0; 92 + for (text = s = stext; *s && x <= ev->x; s++) { 93 + if ((unsigned char)(*s) < ' ') { 94 + ch = *s; 95 + *s = '\0'; 96 + x += TEXTW(text) - lrpad; 97 + *s = ch; 98 + text = s + 1; 99 + if (x >= ev->x) 100 + break; 101 + /* reset on matching signal raw byte */ 102 + if (ch == statussig) 103 + statussig = 0; 104 + else 105 + statussig = ch; 106 + } 107 + } 108 + } else 109 click = ClkWinTitle; 110 } else if ((c = wintoclient(ev->window))) { 111 focus(c); 112 @@ -708,9 +732,24 @@ drawbar(Monitor *m) 113 114 /* draw status first so it can be overdrawn by tags later */ 115 if (m == selmon) { /* status is only drawn on selected monitor */ 116 + char *text, *s, ch; 117 drw_setscheme(drw, scheme[SchemeNorm]); 118 - tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ 119 - drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); 120 + 121 + x = 0; 122 + for (text = s = stext; *s; s++) { 123 + if ((unsigned char)(*s) < ' ') { 124 + ch = *s; 125 + *s = '\0'; 126 + tw = TEXTW(text) - lrpad; 127 + drw_text(drw, m->ww - statusw + x, 0, tw, bh, 0, text, 0); 128 + x += tw; 129 + *s = ch; 130 + text = s + 1; 131 + } 132 + } 133 + tw = TEXTW(text) - lrpad + 2; 134 + drw_text(drw, m->ww - statusw + x, 0, tw, bh, 0, text, 0); 135 + tw = statusw; 136 } 137 138 for (c = m->clients; c; c = c->next) { 139 @@ -876,6 +915,30 @@ getatomprop(Client *c, Atom prop) 140 return atom; 141 } 142 143 +pid_t 144 +getstatusbarpid() 145 +{ 146 + char buf[32], *str = buf, *c; 147 + FILE *fp; 148 + 149 + if (statuspid > 0) { 150 + snprintf(buf, sizeof(buf), "/proc/%u/cmdline", statuspid); 151 + if ((fp = fopen(buf, "r"))) { 152 + fgets(buf, sizeof(buf), fp); 153 + while ((c = strchr(str, '/'))) 154 + str = c + 1; 155 + fclose(fp); 156 + if (!strcmp(str, STATUSBAR)) 157 + return statuspid; 158 + } 159 + } 160 + if (!(fp = popen("pidof -s "STATUSBAR, "r"))) 161 + return -1; 162 + fgets(buf, sizeof(buf), fp); 163 + pclose(fp); 164 + return strtol(buf, NULL, 10); 165 +} 166 + 167 int 168 getrootptr(int *x, int *y) 169 { 170 @@ -1643,6 +1706,20 @@ showhide(Client *c) 171 } 172 } 173 174 +void 175 +sigstatusbar(const Arg *arg) 176 +{ 177 + union sigval sv; 178 + 179 + if (!statussig) 180 + return; 181 + sv.sival_int = arg->i; 182 + if ((statuspid = getstatusbarpid()) <= 0) 183 + return; 184 + 185 + sigqueue(statuspid, SIGRTMIN+statussig, sv); 186 +} 187 + 188 void 189 spawn(const Arg *arg) 190 { 191 @@ -2004,8 +2081,25 @@ updatesizehints(Client *c) 192 void 193 updatestatus(void) 194 { 195 - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) 196 + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) { 197 strcpy(stext, "dwm-"VERSION); 198 + statusw = TEXTW(stext) - lrpad + 2; 199 + } else { 200 + char *text, *s, ch; 201 + 202 + statusw = 0; 203 + for (text = s = stext; *s; s++) { 204 + if ((unsigned char)(*s) < ' ') { 205 + ch = *s; 206 + *s = '\0'; 207 + statusw += TEXTW(text) - lrpad; 208 + *s = ch; 209 + text = s + 1; 210 + } 211 + } 212 + statusw += TEXTW(text) - lrpad + 2; 213 + 214 + } 215 drawbar(selmon); 216 } 217 218 -- 219 2.46.2 220