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