---- - config.def.h | 8 +++++++- - dwm.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- - 2 files changed, 51 insertions(+), 4 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 1c0b587..5cd7efa 100644 ---- a/config.def.h -+++ b/config.def.h -_AT_@ -59,6 +59,10 @@ 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 }; - static const char *termcmd[] = { "st", NULL }; - -+/* commands spawned when clicking statusbar, the mouse button pressed is exported as BUTTON */ -+static char *statuscmds[] = { "notify-send Mouse$BUTTON" }; -+static char *statuscmd[] = { "/bin/sh", "-c", NULL, NULL }; -+ - static Key keys[] = { - /* modifier key function argument */ - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, -_AT_@ -103,7 +107,9 @@ static 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, spawn, {.v = statuscmd } }, -+ { ClkStatusText, 0, Button2, spawn, {.v = statuscmd } }, -+ { ClkStatusText, 0, Button3, spawn, {.v = statuscmd } }, - { ClkClientWin, MODKEY, Button1, movemouse, {0} }, - { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, - { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, -diff --git a/dwm.c b/dwm.c -index 4465af1..d35d173 100644 ---- a/dwm.c -+++ b/dwm.c -_AT_@ -156,6 +156,7 @@ static void clientmessage(XEvent *e); - static void configure(Client *c); - static void configurenotify(XEvent *e); - static void configurerequest(XEvent *e); -+static void copyvalidchars(char *text, char *rawtext); - static Monitor *createmon(void); - static void destroynotify(XEvent *e); - static void detach(Client *c); -_AT_@ -237,6 +238,9 @@ static void zoom(const Arg *arg); - /* variables */ - static const char broken[] = "broken"; - static char stext[256]; -+static char rawstext[256]; -+static int statuscmdn; -+static char lastbutton[] = "-"; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -_AT_@ -421,6 +425,7 @@ buttonpress(XEvent *e) - Client *c; - Monitor *m; - XButtonPressedEvent *ev = &e->xbutton; -+ *lastbutton = '0' + ev->button; - - click = ClkRootWin; - /* focus monitor if necessary */ -_AT_@ -439,9 +444,26 @@ buttonpress(XEvent *e) - arg.ui = 1 << i; - } else if (ev->x < x + blw) - click = ClkLtSymbol; -- else if (ev->x > selmon->ww - TEXTW(stext)) -+ else if (ev->x > (x = selmon->ww - TEXTW(stext) + lrpad)) { - click = ClkStatusText; -- else -+ -+ char *text = rawstext; -+ int i = -1; -+ char ch; -+ statuscmdn = 0; -+ while (text[++i]) { -+ if ((unsigned char)text[i] < ' ') { -+ ch = text[i]; -+ text[i] = '-+ x += TEXTW(text) - lrpad; -+ text[i] = ch; -+ text += i+1; -+ i = -1; -+ if (x >= ev->x) break; -+ if (ch <= LENGTH(statuscmds)) statuscmdn = ch - 1; -+ } -+ } -+ } else - click = ClkWinTitle; - } else if ((c = wintoclient(ev->window))) { - focus(c); -_AT_@ -627,6 +649,19 @@ configurerequest(XEvent *e) - XSync(dpy, False); - } - -+void -+copyvalidchars(char *text, char *rawtext) -+{ -+ int i = -1, j = 0; -+ -+ while(rawtext[++i]) { -+ if ((unsigned char)rawtext[i] >= ' ') { -+ text[j++] = rawtext[i]; -+ } -+ } -+ text[j] = '-+} -+ - Monitor * - createmon(void) - { -_AT_@ -1641,6 +1676,10 @@ spawn(const Arg *arg) - { - if (arg->v == dmenucmd) - dmenumon[0] = '0' + selmon->num; -+ else if (arg->v == statuscmd) { -+ statuscmd[2] = statuscmds[statuscmdn]; -+ setenv("BUTTON", lastbutton, 1); -+ } - if (fork() == 0) { - if (dpy) - close(ConnectionNumber(dpy)); -_AT_@ -1987,8 +2026,10 @@ updatesizehints(Client *c) - void - updatestatus(void) - { -- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) -+ if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext))) - strcpy(stext, "dwm-"VERSION); -+ else -+ copyvalidchars(stext, rawstext); - drawbar(selmon); - } - --- -2.26.1 - diff --git a/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-nosignal-20210402-67d76bd.diff b/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-nosignal-20210402-67d76bd.diff new file mode 100644 index 00000000..1dc5c538 --- /dev/null +++ b/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-nosignal-20210402-67d76bd.diff _AT_@ -0,0 +1,167 @@ +From 02c4a28dd7f3a88eef3a4e533ace35f79cf09d57 Mon Sep 17 00:00:00 2001 +From: Daniel Bylinka <daniel.bylinka_AT_gmail.com> +Date: Fri, 2 Apr 2021 19:34:38 +0200 +Subject: [PATCH] [statuscmd] Run shell commands based on mouse location and + button + +--- + config.def.h | 10 ++++++- + dwm.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 81 insertions(+), 5 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..8f88366 100644 +--- a/config.def.h ++++ b/config.def.h +_AT_@ -59,6 +59,12 @@ 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 }; + static const char *termcmd[] = { "st", NULL }; + ++/* commands spawned when clicking statusbar, the mouse button pressed is exported as BUTTON */ ++static const StatusCmd statuscmds[] = { ++ { "notify-send Mouse$BUTTON", 1 }, ++}; ++static const char *statuscmd[] = { "/bin/sh", "-c", NULL, NULL }; ++ + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, +_AT_@ -103,7 +109,9 @@ static 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, spawn, {.v = statuscmd } }, ++ { ClkStatusText, 0, Button2, spawn, {.v = statuscmd } }, ++ { ClkStatusText, 0, Button3, spawn, {.v = statuscmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, +diff --git a/dwm.c b/dwm.c +index b0b3466..eb478a5 100644 +--- a/dwm.c ++++ b/dwm.c +_AT_@ -141,6 +141,11 @@ typedef struct { + int monitor; + } Rule; + ++typedef struct { ++ const char *cmd; ++ int id; ++} StatusCmd; ++ + /* function declarations */ + static void applyrules(Client *c); + static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); +_AT_@ -238,6 +243,9 @@ static void zoom(const Arg *arg); + /* variables */ + static const char broken[] = "broken"; + static char stext[256]; ++static int statusw; ++static int statuscmdn; ++static char lastbutton[] = "-"; + static int screen; + static int sw, sh; /* X display screen geometry width, height */ + static int bh, blw = 0; /* bar geometry */ +_AT_@ -440,8 +448,27 @@ buttonpress(XEvent *e) + arg.ui = 1 << i; + } else if (ev->x < x + blw) + click = ClkLtSymbol; +- else if (ev->x > selmon->ww - (int)TEXTW(stext)) ++ else if (ev->x > selmon->ww - statusw) { ++ char *text, *s, ch; ++ *lastbutton = '0' + ev->button; ++ ++ x = selmon->ww - statusw; + click = ClkStatusText; ++ ++ statuscmdn = 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; ++ statuscmdn = ch; ++ } ++ } ++ } + else + click = ClkWinTitle; + } else if ((c = wintoclient(ev->window))) { +_AT_@ -704,9 +731,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_@ -1645,6 +1687,17 @@ spawn(const Arg *arg) + if (fork() == 0) { + if (dpy) + close(ConnectionNumber(dpy)); ++ if (arg->v == statuscmd) { ++ for (int i = 0; i < LENGTH(statuscmds); i++) { ++ if (statuscmdn == statuscmds[i].id) { ++ statuscmd[2] = statuscmds[i].cmd; ++ setenv("BUTTON", lastbutton, 1); ++ break; ++ } ++ } ++ if (!statuscmd[2]) ++ exit(EXIT_SUCCESS); ++ } + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); + fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); +_AT_@ -1990,8 +2043,23 @@ 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.31.0 + diff --git a/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-nosignal-status2d-20210402-60bb3df.diff b/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-nosignal-status2d-20210402-60bb3df.diff new file mode 100644 index 00000000..75a7bc0a --- /dev/null +++ b/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-nosignal-status2d-20210402-60bb3df.diff _AT_@ -0,0 +1,171 @@ +From df16de3b4457fd6537e6efaa1785183770056ed6 Mon Sep 17 00:00:00 2001 +From: Daniel Bylinka <daniel.bylinka_AT_gmail.com> +Date: Fri, 2 Apr 2021 19:33:35 +0200 +Subject: [PATCH] [statuscmd] status2d compatibility for statuscmd-nosignal + +--- + config.def.h | 10 +++++++- + dwm.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 72 insertions(+), 6 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..8f88366 100644 +--- a/config.def.h ++++ b/config.def.h +_AT_@ -59,6 +59,12 @@ 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 }; + static const char *termcmd[] = { "st", NULL }; + ++/* commands spawned when clicking statusbar, the mouse button pressed is exported as BUTTON */ ++static const StatusCmd statuscmds[] = { ++ { "notify-send Mouse$BUTTON", 1 }, ++}; ++static const char *statuscmd[] = { "/bin/sh", "-c", NULL, NULL }; ++ + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, +_AT_@ -103,7 +109,9 @@ static 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, spawn, {.v = statuscmd } }, ++ { ClkStatusText, 0, Button2, spawn, {.v = statuscmd } }, ++ { ClkStatusText, 0, Button3, spawn, {.v = statuscmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, +diff --git a/dwm.c b/dwm.c +index acbe6c9..851b0ed 100644 +--- a/dwm.c ++++ b/dwm.c +_AT_@ -141,6 +141,11 @@ typedef struct { + int monitor; + } Rule; + ++typedef struct { ++ const char *cmd; ++ int id; ++} StatusCmd; ++ + /* function declarations */ + static void applyrules(Client *c); + static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); +_AT_@ -239,6 +244,9 @@ static void zoom(const Arg *arg); + /* variables */ + static const char broken[] = "broken"; + static char stext[1024]; ++static int statusw; ++static int statuscmdn; ++static char lastbutton[] = "-"; + static int screen; + static int sw, sh; /* X display screen geometry width, height */ + static int bh, blw = 0; /* bar geometry */ +_AT_@ -441,8 +449,27 @@ buttonpress(XEvent *e) + arg.ui = 1 << i; + } else if (ev->x < x + blw) + click = ClkLtSymbol; +- else if (ev->x > selmon->ww - (int)TEXTW(stext)) ++ else if (ev->x > selmon->ww - statusw) { ++ char *text, *s, ch; ++ *lastbutton = '0' + ev->button; ++ ++ x = selmon->ww - statusw; + click = ClkStatusText; ++ ++ statuscmdn = 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; ++ statuscmdn = ch; ++ } ++ } ++ } + else + click = ClkWinTitle; + } else if ((c = wintoclient(ev->window))) { +_AT_@ -696,7 +723,7 @@ dirtomon(int dir) + + int + drawstatusbar(Monitor *m, int bh, char* stext) { +- int ret, i, w, x, len; ++ int ret, i, j, w, x, len; + short isCode = 0; + char *text; + char *p; +_AT_@ -705,7 +732,12 @@ drawstatusbar(Monitor *m, int bh, char* stext) { + if (!(text = (char*) malloc(sizeof(char)*len))) + die("malloc"); + p = text; +- memcpy(text, stext, len); ++ ++ i = -1, j = 0; ++ while (stext[++i]) ++ if ((unsigned char)stext[i] >= ' ') ++ text[j++] = stext[i]; ++ text[j] = '+ + /* compute width of the status text */ + w = 0; +_AT_@ -813,7 +845,7 @@ drawbar(Monitor *m) + + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ +- tw = m->ww - drawstatusbar(m, bh, stext); ++ tw = statusw = m->ww - drawstatusbar(m, bh, stext); + } + + for (c = m->clients; c; c = c->next) { +_AT_@ -1753,6 +1785,17 @@ spawn(const Arg *arg) + if (fork() == 0) { + if (dpy) + close(ConnectionNumber(dpy)); ++ if (arg->v == statuscmd) { ++ for (int i = 0; i < LENGTH(statuscmds); i++) { ++ if (statuscmdn == statuscmds[i].id) { ++ statuscmd[2] = statuscmds[i].cmd; ++ setenv("BUTTON", lastbutton, 1); ++ break; ++ } ++ } ++ if (!statuscmd[2]) ++ exit(EXIT_SUCCESS); ++ } + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); + fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); +_AT_@ -2098,8 +2141,23 @@ 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.31.0 + diff --git a/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-signal-6.2.diff b/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-signal-6.2.diff deleted file mode 100644 index 97fda1bb..00000000 --- a/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-signal-6.2.diff +++ /dev/null _AT_@ -1,157 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 1c0b587..b67825e 100644 ---- a/config.def.h -+++ b/config.def.h -_AT_@ -103,7 +103,9 @@ static 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, sigdwmblocks, {.i = 1} }, -+ { ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2} }, -+ { ClkStatusText, 0, Button3, sigdwmblocks, {.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 4465af1..c600131 100644 ---- a/dwm.c -+++ b/dwm.c -_AT_@ -156,6 +156,7 @@ static void clientmessage(XEvent *e); - static void configure(Client *c); - static void configurenotify(XEvent *e); - static void configurerequest(XEvent *e); -+static void copyvalidchars(char *text, char *rawtext); - static Monitor *createmon(void); - static void destroynotify(XEvent *e); - static void detach(Client *c); -_AT_@ -169,6 +170,7 @@ static void focus(Client *c); - static void focusin(XEvent *e); - static void focusmon(const Arg *arg); - static void focusstack(const Arg *arg); -+static int getdwmblockspid(); - static int getrootptr(int *x, int *y); - static long getstate(Window w); - static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -_AT_@ -205,6 +207,7 @@ static void setup(void); - static void seturgent(Client *c, int urg); - static void showhide(Client *c); - static void sigchld(int unused); -+static void sigdwmblocks(const Arg *arg); - static void spawn(const Arg *arg); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); -_AT_@ -237,6 +240,9 @@ static void zoom(const Arg *arg); - /* variables */ - static const char broken[] = "broken"; - static char stext[256]; -+static char rawstext[256]; -+static int dwmblockssig; -+pid_t dwmblockspid = 0; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -_AT_@ -439,9 +445,26 @@ buttonpress(XEvent *e) - arg.ui = 1 << i; - } else if (ev->x < x + blw) - click = ClkLtSymbol; -- else if (ev->x > selmon->ww - TEXTW(stext)) -+ else if (ev->x > (x = selmon->ww - TEXTW(stext) + lrpad)) { - click = ClkStatusText; -- else -+ -+ char *text = rawstext; -+ int i = -1; -+ char ch; -+ dwmblockssig = 0; -+ while (text[++i]) { -+ if ((unsigned char)text[i] < ' ') { -+ ch = text[i]; -+ text[i] = '-+ x += TEXTW(text) - lrpad; -+ text[i] = ch; -+ text += i+1; -+ i = -1; -+ if (x >= ev->x) break; -+ dwmblockssig = ch; -+ } -+ } -+ } else - click = ClkWinTitle; - } else if ((c = wintoclient(ev->window))) { - focus(c); -_AT_@ -627,6 +650,19 @@ configurerequest(XEvent *e) - XSync(dpy, False); - } - -+void -+copyvalidchars(char *text, char *rawtext) -+{ -+ int i = -1, j = 0; -+ -+ while(rawtext[++i]) { -+ if ((unsigned char)rawtext[i] >= ' ') { -+ text[j++] = rawtext[i]; -+ } -+ } -+ text[j] = '-+} -+ - Monitor * - createmon(void) - { -_AT_@ -871,6 +907,18 @@ getatomprop(Client *c, Atom prop) - return atom; - } - -+int -+getdwmblockspid() -+{ -+ char buf[16]; -+ FILE *fp = popen("pidof -s dwmblocks", "r"); -+ fgets(buf, sizeof(buf), fp); -+ pid_t pid = strtoul(buf, NULL, 10); -+ pclose(fp); -+ dwmblockspid = pid; -+ return pid != 0 ? 0 : -1; -+} -+ - int - getrootptr(int *x, int *y) - { -_AT_@ -1636,6 +1684,23 @@ sigchld(int unused) - while (0 < waitpid(-1, NULL, WNOHANG)); - } - -+void -+sigdwmblocks(const Arg *arg) -+{ -+ union sigval sv; -+ sv.sival_int = (dwmblockssig << 8) | arg->i; -+ if (!dwmblockspid) -+ if (getdwmblockspid() == -1) -+ return; -+ -+ if (sigqueue(dwmblockspid, SIGUSR1, sv) == -1) { -+ if (errno == ESRCH) { -+ if (!getdwmblockspid()) -+ sigqueue(dwmblockspid, SIGUSR1, sv); -+ } -+ } -+} -+ - void - spawn(const Arg *arg) - { -_AT_@ -1987,8 +2052,10 @@ updatesizehints(Client *c) - void - updatestatus(void) - { -- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) -+ if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext))) - strcpy(stext, "dwm-"VERSION); -+ else -+ copyvalidchars(stext, rawstext); - drawbar(selmon); - } - diff --git a/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-status2d-20210402-60bb3df.diff b/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-status2d-20210402-60bb3df.diff new file mode 100644 index 00000000..6160f52a --- /dev/null +++ b/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-status2d-20210402-60bb3df.diff _AT_@ -0,0 +1,187 @@ +From 9e7935657bdea456db3eb858ac44bb0a671c2b7a Mon Sep 17 00:00:00 2001 +From: Daniel Bylinka <daniel.bylinka_AT_gmail.com> +Date: Fri, 2 Apr 2021 19:04:58 +0200 +Subject: [PATCH] [statuscmd] status2d compatibility + +--- + config.def.h | 6 +++- + dwm.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 82 insertions(+), 6 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..154a59b 100644 +--- a/config.def.h ++++ b/config.def.h +_AT_@ -54,6 +54,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_@ -103,7 +105,9 @@ static 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 acbe6c9..da746a1 100644 +--- a/dwm.c ++++ b/dwm.c +_AT_@ -173,6 +173,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_@ -207,6 +208,7 @@ static void setup(void); + static void seturgent(Client *c, int urg); + static void showhide(Client *c); + static void sigchld(int unused); ++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_@ -239,6 +241,9 @@ static void zoom(const Arg *arg); + /* variables */ + static const char broken[] = "broken"; + static char stext[1024]; ++static int statussig; ++static int statusw; ++static pid_t statuspid = -1; + static int screen; + static int sw, sh; /* X display screen geometry width, height */ + static int bh, blw = 0; /* bar geometry */ +_AT_@ -441,9 +446,34 @@ buttonpress(XEvent *e) + arg.ui = 1 << i; + } else if (ev->x < x + blw) + 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 ++ ++ char *text, *s, ch; ++ 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; ++ statussig = ch; ++ } else if (*s == '^') { ++ *s = '++ x += TEXTW(text) - lrpad; ++ *s = '^'; ++ if (*(++s) == 'f') ++ x += atoi(++s); ++ while (*(s++) != '^'); ++ text = s; ++ s--; ++ } ++ } ++ } else + click = ClkWinTitle; + } else if ((c = wintoclient(ev->window))) { + focus(c); +_AT_@ -696,7 +726,7 @@ dirtomon(int dir) + + int + drawstatusbar(Monitor *m, int bh, char* stext) { +- int ret, i, w, x, len; ++ int ret, i, j, w, x, len; + short isCode = 0; + char *text; + char *p; +_AT_@ -705,7 +735,12 @@ drawstatusbar(Monitor *m, int bh, char* stext) { + if (!(text = (char*) malloc(sizeof(char)*len))) + die("malloc"); + p = text; +- memcpy(text, stext, len); ++ ++ i = -1, j = 0; ++ while (stext[++i]) ++ if ((unsigned char)stext[i] >= ' ') ++ text[j++] = stext[i]; ++ text[j] = '+ + /* compute width of the status text */ + w = 0; +_AT_@ -813,7 +848,7 @@ drawbar(Monitor *m) + + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ +- tw = m->ww - drawstatusbar(m, bh, stext); ++ tw = statusw = m->ww - drawstatusbar(m, bh, stext); + } + + for (c = m->clients; c; c = c->next) { +_AT_@ -979,6 +1014,29 @@ 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); ++ return pclose(fp) == 0 ? strtoul(buf, NULL, 10) : -1; ++} ++ + int + getrootptr(int *x, int *y) + { +_AT_@ -1745,6 +1803,20 @@ sigchld(int unused) + while (0 < waitpid(-1, NULL, WNOHANG)); + } + ++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) + { +-- +2.31.0 + diff --git a/dwm.suckless.org/patches/statuscmd/dwmblocks-statuscmd-20210402-96cbb45.diff b/dwm.suckless.org/patches/statuscmd/dwmblocks-statuscmd-20210402-96cbb45.diff new file mode 100644 index 00000000..bb2cbb65 --- /dev/null +++ b/dwm.suckless.org/patches/statuscmd/dwmblocks-statuscmd-20210402-96cbb45.diff _AT_@ -0,0 +1,127 @@ +From 1669878c08607f481e3f879d6914fc4d3c9d7206 Mon Sep 17 00:00:00 2001 +From: Daniel Bylinka <daniel.bylinka_AT_gmail.com> +Date: Fri, 2 Apr 2021 19:20:17 +0200 +Subject: [PATCH] [statuscmd] Format status text and handle button signals + +--- + dwmblocks.c | 48 +++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 41 insertions(+), 7 deletions(-) + +diff --git a/dwmblocks.c b/dwmblocks.c +index ded717c..78fdeb5 100644 +--- a/dwmblocks.c ++++ b/dwmblocks.c +_AT_@ -3,6 +3,7 @@ + #include<string.h> + #include<unistd.h> + #include<signal.h> ++#include<sys/wait.h> + #ifndef NO_X + #include<X11/Xlib.h> + #endif +_AT_@ -27,14 +28,14 @@ typedef struct { + #ifndef __OpenBSD__ + void dummysighandler(int num); + #endif +-void sighandler(int num); + void getcmds(int time); + void getsigcmds(unsigned int signal); + void setupsignals(); +-void sighandler(int signum); ++void sighandler(int signum, siginfo_t *si, void *ucontext); + int getstatus(char *str, char *last); + void statusloop(); + void termhandler(); ++void chldhandler(); + void pstdout(); + #ifndef NO_X + void setroot(); +_AT_@ -58,6 +59,8 @@ static int returnStatus = 0; + //opens process *cmd and stores output in *output + void getcmd(const Block *block, char *output) + { ++ if (block->signal) ++ *output++ = block->signal; + strcpy(output, block->icon); + FILE *cmdf = popen(block->command, "r"); + if (!cmdf) +_AT_@ -102,15 +105,18 @@ void getsigcmds(unsigned int signal) + + void setupsignals() + { ++ struct sigaction sa = { .sa_sigaction = sighandler, .sa_flags = SA_SIGINFO }; + #ifndef __OpenBSD__ + /* initialize all real time signals with dummy handler */ +- for (int i = SIGRTMIN; i <= SIGRTMAX; i++) ++ for (int i = SIGRTMIN; i <= SIGRTMAX; i++) { + signal(i, dummysighandler); ++ sigaddset(&sa.sa_mask, i); ++ } + #endif + + for (unsigned int i = 0; i < LENGTH(blocks); i++) { + if (blocks[i].signal > 0) +- signal(SIGMINUS+blocks[i].signal, sighandler); ++ sigaction(SIGMINUS+blocks[i].signal, &sa, NULL); + } + + } +_AT_@ -178,10 +184,32 @@ void dummysighandler(int signum) + } + #endif + +-void sighandler(int signum) ++void sighandler(int signum, siginfo_t *si, void *ucontext) + { +- getsigcmds(signum-SIGPLUS); +- writestatus(); ++ if (si->si_value.sival_int) { ++ pid_t parent = getpid(); ++ if (fork() == 0) { ++#ifndef NO_X ++ if (dpy) ++ close(ConnectionNumber(dpy)); ++#endif ++ int i; ++ for (i = 0; i < LENGTH(blocks) && blocks[i].signal != signum-SIGRTMIN; i++); ++ ++ char shcmd[1024]; ++ sprintf(shcmd, "%s; kill -%d %d", blocks[i].command, SIGRTMIN+blocks[i].signal, parent); ++ char *cmd[] = { "/bin/sh", "-c", shcmd, NULL }; ++ char button[2] = { '0' + si->si_value.sival_int, '++ setenv("BUTTON", button, 1); ++ setsid(); ++ execvp(cmd[0], cmd); ++ perror(cmd[0]); ++ exit(EXIT_SUCCESS); ++ } ++ } else { ++ getsigcmds(signum-SIGPLUS); ++ writestatus(); ++ } + } + + void termhandler() +_AT_@ -189,6 +217,11 @@ void termhandler() + statusContinue = 0; + } + ++void chldhandler() ++{ ++ while (0 < waitpid(-1, NULL, WNOHANG)); ++} ++ + int main(int argc, char** argv) + { + for (int i = 0; i < argc; i++) {//Handle command line arguments +_AT_@ -205,6 +238,7 @@ int main(int argc, char** argv) + delim[delimLen++] = '+ signal(SIGTERM, termhandler); + signal(SIGINT, termhandler); ++ signal(SIGCHLD, chldhandler); + statusloop(); + #ifndef NO_X + XCloseDisplay(dpy); +-- +2.31.0 + diff --git a/dwm.suckless.org/patches/statuscmd/dwmblocks-statuscmd.diff b/dwm.suckless.org/patches/statuscmd/dwmblocks-statuscmd.diff deleted file mode 100644 index 961f22a4..00000000 --- a/dwm.suckless.org/patches/statuscmd/dwmblocks-statuscmd.diff +++ /dev/null _AT_@ -1,80 +0,0 @@ -diff --git a/dwmblocks.c b/dwmblocks.c -index 2f3b774..ba7dbb5 100644 ---- a/dwmblocks.c -+++ b/dwmblocks.c -_AT_@ -14,6 +14,7 @@ typedef struct { - unsigned int signal; - } Block; - void sighandler(int num); -+void buttonhandler(int sig, siginfo_t *si, void *ucontext); - void getcmds(int time); - #ifndef __OpenBSD__ - void getsigcmds(int signal); -_AT_@ -33,15 +34,32 @@ static int screen; - static Window root; - static char statusbar[LENGTH(blocks)][CMDLENGTH] = {0}; - static char statusstr[2][256]; -+static char button[] = "- static int statusContinue = 1; - static void (*writestatus) () = setroot; - - //opens process *cmd and stores output in *output - void getcmd(const Block *block, char *output) - { -+ if (block->signal) -+ { -+ output[0] = block->signal; -+ output++; -+ } - strcpy(output, block->icon); - char *cmd = block->command; -- FILE *cmdf = popen(cmd,"r"); -+ FILE *cmdf; -+ if (*button) -+ { -+ setenv("BUTTON", button, 1); -+ cmdf = popen(cmd,"r"); -+ *button = '-+ unsetenv("BUTTON"); -+ } -+ else -+ { -+ cmdf = popen(cmd,"r"); -+ } - if (!cmdf) - return; - char c; -_AT_@ -79,12 +97,18 @@ void getsigcmds(int signal) - - void setupsignals() - { -+ struct sigaction sa; - for(int i = 0; i < LENGTH(blocks); i++) - { - if (blocks[i].signal > 0) -+ { - signal(SIGRTMIN+blocks[i].signal, sighandler); -+ sigaddset(&sa.sa_mask, SIGRTMIN+blocks[i].signal); // ignore signal when handling SIGUSR1 -+ } - } -- -+ sa.sa_sigaction = buttonhandler; -+ sa.sa_flags = SA_SIGINFO; -+ sigaction(SIGUSR1, &sa, NULL); - } - #endif - -_AT_@ -143,6 +167,13 @@ void sighandler(int signum) - getsigcmds(signum-SIGRTMIN); - writestatus(); - } -+ -+void buttonhandler(int sig, siginfo_t *si, void *ucontext) -+{ -+ *button = '0' + si->si_value.sival_int & 0xff; -+ getsigcmds(si->si_value.sival_int >> 8); -+ writestatus(); -+} - #endif - - void termhandler(int signum) diff --git a/dwm.suckless.org/patches/statuscmd/index.md b/dwm.suckless.org/patches/statuscmd/index.md index c320d3ce..c4e5d2b4 100644 --- a/dwm.suckless.org/patches/statuscmd/index.md +++ b/dwm.suckless.org/patches/statuscmd/index.md _AT_@ -3,67 +3,101 @@ statuscmd Description ----------- -This patch adds the ability to execute shell commands based on the mouse -button and position when clicking the status bar. +This patch adds the ability to signal a status monitor program such as +[dwmblocks](https://github.com/torrinfail/dwmblocks) the location and button +when clicking on the status bar. Alternatively, there is a version that +executes shell commands defined in config.h instead of using signals. Usage ----- -Fill 'statuscmds' with commands. Choose which command to run by prefixing -the status text with a raw byte of the command's index in 'statuscmds', -offset by +1 since '-if there is no index to the left of the mouse position. The mouse button -clicked is exported as $BUTTON. +Both the nosignal version and the dwmblocks version will run their respective +shell commands/scripts with the environment variable BUTTON set to the button +that was pressed. -Example -------- -With these commands: +### With signals +Apply the statuscmd patch and set the `STATUSBAR` macro in config.h +to the name of the status monitor. + +Apply the corresponding statuscmd patch to your status monitor if there is +one, or extend the program on your own. Feel free to add patches for other +status monitors. + +#### Patching status monitors +* Assosiate 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. +* Create a signal handler: + + void sighandler(int signum, siginfo_t *si, void *ucontext) + { + int signal = signum - SIGRTMIN; + int button = si->si_value.sival_int; /* if button is zero, the signal is not from a button press */ + ... /* do whatever you want */ + } + +* Register the signal handler for each section in the following way, with + 'signal' being the same signal from the first step: + + struct sigaction sa = { .sa_sigaction = sighandler, .sa_flags = SA_SIGINFO }; + sigaction(SIGRTMIN+signal, &sa, NULL); + +### Without signals +Apply the statuscmd-nosignal patch and fill the `statuscmds` array in config.h +with `StatusCmd` structs, which take a shell command string and an integer +identifier. - static const char *statuscmds[] = { "volume", "cpu", "battery" }; +When setting the status, print the integer identifier as a raw byte before its +respective text. + +For example, with `statuscmds` defined as such: + + static const StatusCmd statuscmds[] = { + { "volume", 1 }, + { "cpu", 2 }, + { "battery", 3 }, + }; And root name set like this: - xsetroot -name "$(echo -e 'volume |\x02 cpu |\x03 battery')" + xsetroot -name "$(printf '\x01Volume |\x02 CPU |\x03 Battery')" -Clicking on 'volume |' would run `volume`, clicking on ' cpu |' -would run `cpu` and clicking on ' battery' would run `battery`. +Clicking on 'Volume |' would run `volume`, clicking on ' CPU |' +would run `cpu` and clicking on ' Battery' would run `battery`. -The `cpu` script could look like this: +Example +------- +A script run from dwm or dwmblocks with this patch might look like this: #!/bin/sh case $BUTTON in - 1) notify-send "CPU usage" "$(ps axch -o cmd,%cpu --sort=-%cpu | head)";; - 3) st -e htop;; + 1) notify-send "CPU usage" "$(ps axch -o cmd,%cpu --sort=-%cpu | head)" ;; + 3) st -e htop ;; esac Notes ----- -If you have 10 or more commands, make sure to be careful when adding or -removing newline characters since ' ' is equal to '\x0a'. The problem -where having certain unprintable characters such as ' ' in the status -string can make dwm laggy is "fixed", since they are not copied to the -string that is actually drawn. - -dwmblocks integration ---------------------- -A program that sets the status for dwm such as -[dwmblocks](https://github.com/torrinfail/dwmblocks) can be patched to manage -the commands while dwm only finds the location clicked in the status bar. -This way, no changes are needed in dwm when adding or reordering modules. - -Instead of running a command from within dwm using the control character -as an index, the dwm-statuscmd-signal patch sends a SIGUSR1 signal to -dwmblocks with the button and control character encoded into the signal value. - -The dwmblocks-statuscmd patch makes dwmblocks put each block's signal in -front of its output text and handles the SIGUSR1 signal by running the -block's command with $BUTTON exported. +The signal version is not compatible with OpenBSD since it relies on `sigqueue`. + +Be careful with newline characters in the status text since ' ' is equal to +'\x0a', which is a valid signal number. The problem where having certain +undrawable characters in the status bar can make dwm laggy is fixed since dwm +will not attempt to draw them with this patch. Download -------- -* [dwm-statuscmd-6.2.diff](dwm-statuscmd-6.2.diff) -* [dwm-statuscmd-signal-6.2.diff](dwm-statuscmd-signal-6.2.diff) -* [dwmblocks-statuscmd.diff](dwmblocks-statuscmd.diff) +### dwm patches +* [dwm-statuscmd-20210402-67d76bd.diff](dwm-statuscmd-20210402-67d76bd.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 +above ones on top of a build already patched with status2d: + +* [dwm-statuscmd-status2d-20210402-60bb3df.diff](dwm-statuscmd-status2d-20210402-60bb3df.diff) +* [dwm-statuscmd-nosignal-status2d-20210402-60bb3df.diff](dwm-statuscmd-nosignal-status2d-20210402-60bb3df.diff) + +### Status monitor patches +* [dwmblocks-statuscmd-20210402-96cbb45.diff](dwmblocks-statuscmd-20210402-96cbb45.diff) Author ------Received on Fri Apr 02 2021 - 20:21:26 CEST
This archive was generated by hypermail 2.3.0 : Fri Apr 02 2021 - 20:24:35 CEST