sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

commit 1070524ac033d6dc18519715a0ddf4fcfef5318c
parent cdab8ad225cd4cbd831a283996ea7402d0da9819
Author: Daniel Bylinka <daniel.bylinka@gmail.com>
Date:   Sun, 19 Apr 2020 18:56:07 +0200

[dwm][patch] statuscmd: add dwmblocks integration and simplify export

Diffstat:
Mdwm.suckless.org/patches/statuscmd/dwm-statuscmd-6.2.diff | 57++++++++++++++++++---------------------------------------
Adwm.suckless.org/patches/statuscmd/dwm-statuscmd-signal-6.2.diff | 157+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/statuscmd/dwmblocks-statuscmd.diff | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdwm.suckless.org/patches/statuscmd/index.md | 17+++++++++++++++++
4 files changed, 272 insertions(+), 39 deletions(-)

diff --git a/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-6.2.diff b/dwm.suckless.org/patches/statuscmd/dwm-statuscmd-6.2.diff @@ -1,16 +1,16 @@ -From b4e7de63bb4d6c711fa8d34fd83c86bfada7236e Mon Sep 17 00:00:00 2001 +From 2761ad72b4b8a80e434e7eba1a24676119ab666d Mon Sep 17 00:00:00 2001 From: Daniel Bylinka <daniel.bylinka@gmail.com> -Date: Sat, 4 Apr 2020 22:54:03 +0200 +Date: Sat, 18 Apr 2020 01:41:03 +0200 Subject: [PATCH] statuscmd: run shell commands based on mouse button and position when clicking statusbar --- config.def.h | 8 +++++++- - dwm.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++--- - 2 files changed, 60 insertions(+), 4 deletions(-) + dwm.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/config.def.h b/config.def.h -index 1c0b587..b85d7a4 100644 +index 1c0b587..5cd7efa 100644 --- a/config.def.h +++ b/config.def.h @@ -59,6 +59,10 @@ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() @@ -18,7 +18,7 @@ index 1c0b587..b85d7a4 100644 static const char *termcmd[] = { "st", NULL }; +/* commands spawned when clicking statusbar, the mouse button pressed is exported as BUTTON */ -+static const char *statuscmds[] = { "notify-send Mouse$BUTTON" }; ++static char *statuscmds[] = { "notify-send Mouse$BUTTON" }; +static char *statuscmd[] = { "/bin/sh", "-c", NULL, NULL }; + static Key keys[] = { @@ -36,7 +36,7 @@ index 1c0b587..b85d7a4 100644 { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, diff --git a/dwm.c b/dwm.c -index 4465af1..29f9f8d 100644 +index 4465af1..d35d173 100644 --- a/dwm.c +++ b/dwm.c @@ -156,6 +156,7 @@ static void clientmessage(XEvent *e); @@ -47,26 +47,25 @@ index 4465af1..29f9f8d 100644 static Monitor *createmon(void); static void destroynotify(XEvent *e); static void detach(Client *c); -@@ -237,6 +238,10 @@ static void zoom(const Arg *arg); +@@ -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 const char statusexport[] = "export BUTTON=-;"; +static int statuscmdn; -+static int lastbutton; ++static char lastbutton[] = "-"; static int screen; static int sw, sh; /* X display screen geometry width, height */ static int bh, blw = 0; /* bar geometry */ -@@ -421,6 +426,7 @@ buttonpress(XEvent *e) +@@ -421,6 +425,7 @@ buttonpress(XEvent *e) Client *c; Monitor *m; XButtonPressedEvent *ev = &e->xbutton; -+ lastbutton = ev->button; ++ *lastbutton = '0' + ev->button; click = ClkRootWin; /* focus monitor if necessary */ -@@ -439,9 +445,26 @@ buttonpress(XEvent *e) +@@ -439,9 +444,26 @@ buttonpress(XEvent *e) arg.ui = 1 << i; } else if (ev->x < x + blw) click = ClkLtSymbol; @@ -95,7 +94,7 @@ index 4465af1..29f9f8d 100644 click = ClkWinTitle; } else if ((c = wintoclient(ev->window))) { focus(c); -@@ -627,6 +650,19 @@ configurerequest(XEvent *e) +@@ -627,6 +649,19 @@ configurerequest(XEvent *e) XSync(dpy, False); } @@ -115,38 +114,18 @@ index 4465af1..29f9f8d 100644 Monitor * createmon(void) { -@@ -1636,11 +1672,22 @@ sigchld(int unused) - while (0 < waitpid(-1, NULL, WNOHANG)); - } - -+ - void - spawn(const Arg *arg) +@@ -1641,6 +1676,10 @@ spawn(const Arg *arg) { -+ char *cmd = NULL; if (arg->v == dmenucmd) dmenumon[0] = '0' + selmon->num; + else if (arg->v == statuscmd) { -+ int len = strlen(statuscmds[statuscmdn]) + 1; -+ if (!(cmd = malloc(sizeof(char)*len + sizeof(statusexport)))) -+ die("malloc:"); -+ strcpy(cmd, statusexport); -+ strcat(cmd, statuscmds[statuscmdn]); -+ cmd[LENGTH(statusexport)-3] = '0' + lastbutton; -+ statuscmd[2] = cmd; ++ statuscmd[2] = statuscmds[statuscmdn]; ++ setenv("BUTTON", lastbutton, 1); + } if (fork() == 0) { if (dpy) close(ConnectionNumber(dpy)); -@@ -1650,6 +1697,7 @@ spawn(const Arg *arg) - perror(" failed"); - exit(EXIT_SUCCESS); - } -+ free(cmd); - } - - void -@@ -1987,8 +2035,10 @@ updatesizehints(Client *c) +@@ -1987,8 +2026,10 @@ updatesizehints(Client *c) void updatestatus(void) { @@ -159,5 +138,5 @@ index 4465af1..29f9f8d 100644 } -- -2.26.0 +2.26.1 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 @@ -0,0 +1,157 @@ +diff --git a/config.def.h b/config.def.h +index 1c0b587..b67825e 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -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 +@@ -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); +@@ -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); +@@ -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); +@@ -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 */ +@@ -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] = '\0'; ++ 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); +@@ -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] = '\0'; ++} ++ + Monitor * + createmon(void) + { +@@ -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) + { +@@ -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) + { +@@ -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/dwmblocks-statuscmd.diff b/dwm.suckless.org/patches/statuscmd/dwmblocks-statuscmd.diff @@ -0,0 +1,80 @@ +diff --git a/dwmblocks.c b/dwmblocks.c +index 2f3b774..ba7dbb5 100644 +--- a/dwmblocks.c ++++ b/dwmblocks.c +@@ -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); +@@ -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[] = "\0"; + 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 = '\0'; ++ unsetenv("BUTTON"); ++ } ++ else ++ { ++ cmdf = popen(cmd,"r"); ++ } + if (!cmdf) + return; + char c; +@@ -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 + +@@ -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 @@ -44,9 +44,26 @@ where having certain unprintable characters such as '\n' 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. + 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) Author ------