commit aa1472ed71a388a0061db7b9cf9695799ccc7534
parent 5dd79652e958600a6567126fc2715fa1f9b19bfa
Author: explosion-mental <explosion0mental@gmail.com>
Date: Thu, 26 May 2022 23:02:53 -0500
[patch][dwm] update integrated-status-text patch
Diffstat:
2 files changed, 396 insertions(+), 263 deletions(-)
diff --git a/dwm.suckless.org/patches/integrated-status-text/dwm-integrated-status-text-6.3.diff b/dwm.suckless.org/patches/integrated-status-text/dwm-integrated-status-text-6.3.diff
@@ -1,100 +1,94 @@
-From f3a9dd0222319d72303be37ae5268831582fe487 Mon Sep 17 00:00:00 2001
+From 02f1f07ee4460787c971bd28e934cb5fc319253d Mon Sep 17 00:00:00 2001
From: explosion-mental <explosion0mental@gmail.com>
-Date: Sun, 27 Feb 2022 17:08:53 -0500
-Subject: [PATCH] [PATCH] Allows dwm to handle the text by itself This is a
- dwmblocks integration into dwm itself. You can update the blocks only with
- signals of with mouseclicks. The 'interval' value does nothing and is meant
- to be there to 're-use' on future patches. You can checkout my build with
- more features like 'async' updates https://github.com/explosion-mental/Dwm,
- which is were I'm extracting this patch.
+Date: Thu, 26 May 2022 22:34:14 -0500
+Subject: [PATCH] [PATCH] Allows dwm to handle the text by itself. You can
+ think of it like a dwmblocks integration into dwm itself. This is extracted
+ from my dwm build[0] in which you can find even more information.
-What you need to know:
-- dwm sets a enviromental variable with the PID of itself to be more
- 'friendly'. With this you can do `kill -35 $STATUSBAR`, which updates
- block with signal 1 (34 + signal of the block)
-- other way to update a block is inside dwm itself, with the
- `updateblock` function. It accepts an unsigned int (non negative)
- number which value indicates the signal of the block you want to
- update.
-- mouse clicks are handled with `sendstatusbar` (a mouse function only!)
- which accepts the value that you want to pass to the block command
- as a 'variable' called `BLOCK_BUTTON`, which should be handled in the
- script (block command)
-- since this uses real time signals to handle the updates, shouldn't
- work in openbsd, but I could be wrong.
+Example:
+```
+/* fg command interval signal */
+{ "#000000", "echo 'dwm block!", 10, 3},
+```
+
+- fg: the foreground color of the individual block, for the background it
+uses the bg of SchemeStatus.
+
+- command: it uses the output of the commands for the status text
+interval: in seconds, how much does it have to pass before updating the
+block.
+
+- interval: in seconds, how many seconds until the block it's updated
+
+- signal: have to be less than 30. This lets you update the block with
+`kill` by adding 35 to this value.
+For the block above it would be 34 + 3 = 37 -> `kill -37 $(pidof dwm)`.
+These signals are linux dependant.
+
+You can change `$(pidof dwm)` with `$STATUSBAR` to 'fix' signaling
+multiple instances of dwm, since this patch also wraps the PID of dwm
+into the `$STATUSBAR` enviromental variable.
+
+Last thing, mouse actions. For this you need to handle the env variable
+`$BLOCK_BUTTON` in a script, this is so you can easily reuse the scripts
+used in dwmblocks. And remember that mouse actions update the block.
+
+[0] https://github.com/explosion-mental/Dwm or
+https://codeberg.org/explosion-mental/Dwm
---
- config.def.h | 53 +++++++++++++++
- dwm.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++----
- 2 files changed, 227 insertions(+), 12 deletions(-)
+ config.def.h | 39 ++++++-
+ dwm.c | 298 +++++++++++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 318 insertions(+), 19 deletions(-)
diff --git a/config.def.h b/config.def.h
-index a2ac963..99d6b3d 100644
+index a2ac963..cad178c 100644
--- a/config.def.h
+++ b/config.def.h
-@@ -18,6 +18,49 @@ static const char *colors[][3] = {
+@@ -16,8 +16,38 @@ static const char *colors[][3] = {
+ /* fg bg border */
+ [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
++ [SchemeStatus]={ col_cyan, col_gray1, NULL },
};
-
+
++
+/* status bar */
+static const Block blocks[] = {
-+ /* command interval signal */
-+ { "sb-clock", 30, 1},
-+ { "sb-disk", 9000, 2},
-+ { "sb-battery", 10, 3},
-+ { "sb-internet", 10, 4},
-+ { "sb-mailbox", 0, 5},
-+ { "sb-moonphase", 18000, 6},
-+ { "sb-forecast", 18000, 7},
-+ { "sb-volume", 0, 8},
-+// { "sb-price btc Bitcoin 💰", 9000, 21},
-+// { "sb-price eth Ethereum 🍸", 9000, 23},
-+// { "sb-price xmr \"Monero\" 🔒", 9000, 24},
-+// { "sb-price link \"Chainlink\" 🔗", 300, 25},
-+// { "sb-price bat \"Basic Attention Token\" 🦁",9000, 20},
-+// { "sb-price lbc \"LBRY Token\" 📚", 9000, 22},
-+// { "sb-cpu", 10, 18},
-+// { "sb-kbselect", 0, 30},
-+// { "sb-memory", 10, 14},
-+// { "sb-torrent", 20, 7},
-+// { "sb-crypto", 0, 13},
-+// { "sb-help-icon", 0, 15},
-+// { "sb-nettraf", 1, 16},
-+// { "sb-news", 0, 6},
-+// { "sb-xbpsup", 18000, 8},
-+ { "sb-pacpackages", 0, 9},
-+ { "sb-sync", 0, 10},
-+// { "sb-mpc", 0, 26},
-+ { "sb-music", 0, 11},
-+// { "sb-tasks", 10, 12},
-+ { "sb-notes", 0, 13},
-+ { "cat /tmp/recordingicon 2>/dev/null", 0, 14},
-+// { "sb-count", 0, 21},
++ /* fg command interval signal */
++ { col_gray3, "sb-clock", 20, 1},
++ { col_gray1, "sb-disk", 9000, 2},
++ { col_gray2, "sb-battery", 10, 3},
++ { col_gray3, "sb-internet", 10, 4},
++ { col_cyan, "sb-mailbox", 0, 5},
++ { "#000001", "sb-moonphase", 0, 6},
++ { "#1F0077", "sb-forecast", 0, 7},
++ { "#000077", "sb-volume", 0, 8},
++ { "#F77000", "sb-pacpackages", 0, 9},
++ { "#177000", "sb-sync", 0, 10},
++// { col_gray1, "sb-mpc", 0, 26},
++ { col_gray2, "sb-music", 0, 11},
++// { col_gray3, "sb-tasks", 10, 12},
++ { col_gray4, "sb-notes", 0, 13},
++ { col_cyan, "echo '';cat /tmp/recordingicon", 0, 14},
+};
+
+/* inverse the order of the blocks, comment to disable */
-+#define INVERSED
++#define INVERSED 1
+/* delimeter between blocks commands. NULL character ('\0') means no delimeter. */
+static char delimiter[] = " ";
+/* max number of character that one block command can output */
-+#define CMDLENGTH 50
++#define CMDLENGTH 50
++
+
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
-
-@@ -62,6 +105,9 @@ static const char *termcmd[] = { "st", NULL };
-
- static Key keys[] = {
- /* modifier key function argument */
-+ { MODKEY, XK_minus, spawn, SHCMD("pamixer --allow-boost -d 3; kill -42 $STATUSBAR")},
-+ { MODKEY, XK_equal, spawn, SHCMD("pamixer --allow-boost -i 3")},
-+ { MODKEY, XK_equal, updateblock, { .ui = 8 } },
- { MODKEY, XK_p, spawn, {.v = dmenucmd } },
- { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
- { MODKEY, XK_b, togglebar, {0} },
-@@ -101,6 +147,13 @@ static Key keys[] = {
- /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
- static Button buttons[] = {
- /* click event mask button function argument */
+
+@@ -104,7 +134,14 @@ 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, sendstatusbar, {.i = 1 } },
+ { ClkStatusText, 0, Button2, sendstatusbar, {.i = 2 } },
+ { ClkStatusText, 0, Button3, sendstatusbar, {.i = 3 } },
@@ -102,18 +96,36 @@ index a2ac963..99d6b3d 100644
+ { ClkStatusText, 0, Button5, sendstatusbar, {.i = 5 } },
+ { ClkStatusText, ShiftMask, Button1, sendstatusbar, {.i = 6 } },
+
- { ClkLtSymbol, 0, Button1, setlayout, {0} },
- { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
- { ClkWinTitle, 0, Button2, zoom, {0} },
+ { ClkClientWin, MODKEY, Button1, movemouse, {0} },
+ { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
+ { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
diff --git a/dwm.c b/dwm.c
-index a96f33c..6e79e5f 100644
+index a96f33c..5789f72 100644
--- a/dwm.c
+++ b/dwm.c
-@@ -141,6 +141,12 @@ typedef struct {
+@@ -28,6 +28,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
++#include <poll.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+ #include <X11/cursorfont.h>
+@@ -59,7 +60,7 @@
+
+ /* enums */
+ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
+-enum { SchemeNorm, SchemeSel }; /* color schemes */
++enum { SchemeNorm, SchemeSel, SchemeStatus }; /* color schemes */
+ enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
+ NetWMFullscreen, NetActiveWindow, NetWMWindowType,
+ NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
+@@ -141,6 +142,13 @@ typedef struct {
int monitor;
} Rule;
-
+
+typedef struct {
++ const char *color;
+ const char *command;
+ const unsigned int interval;
+ const unsigned int signal;
@@ -122,17 +134,19 @@ index a96f33c..6e79e5f 100644
/* function declarations */
static void applyrules(Client *c);
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
-@@ -172,6 +178,9 @@ static void focusstack(const Arg *arg);
+@@ -172,6 +180,11 @@ 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 void getcmd(int i, char *output);
-+static void getsigcmds(unsigned int signal);
++static void getcmd(int i, char *button);
++static void getcmds(int time);
++static void getsigcmds(int signal);
++static int gcd(int a, int b);
+static int getstatus(int width);
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, int focused);
static void grabkeys(void);
-@@ -197,6 +206,7 @@ static void run(void);
+@@ -197,14 +210,17 @@ static void run(void);
static void scan(void);
static int sendevent(Client *c, Atom proto);
static void sendmon(Client *c, Monitor *m);
@@ -140,42 +154,45 @@ index a96f33c..6e79e5f 100644
static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
static void setfullscreen(Client *c, int fullscreen);
-@@ -219,6 +229,7 @@ static void unmanage(Client *c, int destroyed);
- static void unmapnotify(XEvent *e);
- static void updatebarpos(Monitor *m);
- static void updatebars(void);
-+static void updateblock(const Arg *arg);
- static void updateclientlist(void);
- static int updategeom(void);
- static void updatenumlockmask(void);
-@@ -237,7 +248,7 @@ static void zoom(const Arg *arg);
-
+ static void setlayout(const Arg *arg);
+ static void setmfact(const Arg *arg);
+ static void setup(void);
++static void setsignal(int sig, void (*handler)(int sig));
+ static void seturgent(Client *c, int urg);
+ static void showhide(Client *c);
++static void sigalrm(int unused);
+ static void sigchld(int unused);
+ static void spawn(const Arg *arg);
+ static void tag(const Arg *arg);
+@@ -237,13 +253,16 @@ static void zoom(const Arg *arg);
+
/* variables */
static const char broken[] = "broken";
-static char stext[256];
-+static unsigned int stsw = 0, blocknum;
static int screen;
static int sw, sh; /* X display screen geometry width, height */
static int bh, blw = 0; /* bar geometry */
-@@ -260,7 +271,7 @@ static void (*handler[LASTEvent]) (XEvent *) = {
- [PropertyNotify] = propertynotify,
- [UnmapNotify] = unmapnotify
- };
--static Atom wmatom[WMLast], netatom[NetLast];
-+static Atom wmatom[WMLast], netatom[NetLast], dwmstatus;
- static int running = 1;
- static Cur *cursor[CurLast];
- static Clr **scheme;
-@@ -272,6 +283,8 @@ static Window root, wmcheckwin;
+ static int lrpad; /* sum of left and right padding for text */
+ static int (*xerrorxlib)(Display *, XErrorEvent *);
++static unsigned int blocknum; /* blocks idx in mouse click */
++static unsigned int stsw = 0; /* status width */
+ static unsigned int numlockmask = 0;
++static unsigned int sleepinterval = 0, maxinterval = 0, count = 0;
++static unsigned int execlock = 0; /* ensure only one child process exists per block at an instance */
+ static void (*handler[LASTEvent]) (XEvent *) = {
+ [ButtonPress] = buttonpress,
+ [ClientMessage] = clientmessage,
+@@ -272,6 +291,9 @@ static Window root, wmcheckwin;
/* configuration, allows nested code to access above variables */
#include "config.h"
-
-+static char blockoutput[LENGTH(blocks)][CMDLENGTH] = {0};
+
++static char blockoutput[LENGTH(blocks)][CMDLENGTH + 1] = {0};
++static int pipes[LENGTH(blocks)][2];
+
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
-
-@@ -440,9 +453,25 @@ buttonpress(XEvent *e)
+
+@@ -440,9 +462,26 @@ buttonpress(XEvent *e)
arg.ui = 1 << i;
} else if (ev->x < x + blw)
click = ClkLtSymbol;
@@ -184,13 +201,14 @@ index a96f33c..6e79e5f 100644
click = ClkStatusText;
- else
+ int len, i;
-+ #ifdef INVERSED
++
++ #if INVERSED
+ for (i = LENGTH(blocks) - 1; i >= 0; i--)
-+ #else
++ #else
+ for (i = 0; i < LENGTH(blocks); i++)
-+ #endif /* INVERSED */
++ #endif /* INVERSED */
+ {
-+ if (*blockoutput[i] == '\0') //ignore command that output NULL or '\0'
++ if (*blockoutput[i] == '\0') /* ignore command that output NULL or '\0' */
+ continue;
+ len = TEXTW(blockoutput[i]) - lrpad + TEXTW(delimiter) - lrpad;
+ x += len;
@@ -203,9 +221,9 @@ index a96f33c..6e79e5f 100644
click = ClkWinTitle;
} else if ((c = wintoclient(ev->window))) {
focus(c);
-@@ -706,11 +735,8 @@ drawbar(Monitor *m)
+@@ -706,11 +745,8 @@ drawbar(Monitor *m)
return;
-
+
/* draw status first so it can be overdrawn by tags later */
- if (m == selmon) { /* status is only drawn on selected monitor */
- drw_setscheme(drw, scheme[SchemeNorm]);
@@ -214,81 +232,91 @@ index a96f33c..6e79e5f 100644
- }
+ if (m == selmon) /* status is only drawn on selected monitor */
+ tw = getstatus(m->ww);
-
+
for (c = m->clients; c; c = c->next) {
occ |= c->tags;
-@@ -903,6 +929,81 @@ getstate(Window w)
+@@ -903,6 +939,106 @@ getstate(Window w)
return result;
}
-
-+static void
-+remove_all(char *str, char to_remove)
-+{
-+ char *read = str, *write = str;
-+ do {
-+ while (*read == to_remove) read++;
-+ *write++ = *read;
-+ read++;
-+ } while (*(read-1));
-+}
-+
+
+void
-+getcmd(int i, char *output)
++getcmd(int i, char *button)
+{
-+ FILE *cmdf = popen(blocks[i].command, "r");
-+ if (!cmdf)
++ if (!selmon->showbar)
+ return;
+
-+ /* keep trying while (even if) the interrupt error */
-+ char tmpstr[CMDLENGTH] = "", *s;
-+ int e;
-+ do {
-+ errno = 0;
-+ s = fgets(tmpstr, CMDLENGTH - (strlen(delimiter) + 1), cmdf);
-+ e = errno;
-+ } while (!s && e == EINTR);
++ if (execlock & 1 << i) { /* block is already running */
++ //fprintf(stderr, "dwm: ignoring block %d, command %s\n", i, blocks[i].command);
++ return;
++ }
+
-+ pclose(cmdf);
++ /* lock execution of block until current instance finishes execution */
++ execlock |= 1 << i;
+
-+ strcpy(output, tmpstr);
-+ remove_all(output, '\n'); /* chop off newline */
++ if (fork() == 0) {
++ if (dpy)
++ close(ConnectionNumber(dpy));
++ dup2(pipes[i][1], STDOUT_FILENO);
++ close(pipes[i][0]);
++ close(pipes[i][1]);
++
++ if (button)
++ setenv("BLOCK_BUTTON", button, 1);
++ execlp("/bin/sh", "sh", "-c", blocks[i].command, (char *) NULL);
++ fprintf(stderr, "dwm: block %d, execlp %s", i, blocks[i].command);
++ perror(" failed");
++ exit(EXIT_SUCCESS);
++ }
+}
+
+void
-+getsigcmds(unsigned int signal)
++getcmds(int time)
+{
+ int i;
-+#ifdef INVERSED
-+ for (i = LENGTH(blocks) - 1; i >= 0; i--)
-+#else
+ for (i = 0; i < LENGTH(blocks); i++)
-+#endif /* INVERSED */
-+ {
-+ if (blocks[i].signal == signal)
-+ getcmd(i, blockoutput[i]);
-+ }
++ if ((blocks[i].interval != 0 && time % blocks[i].interval == 0) || time == -1)
++ getcmd(i, NULL);
++}
++
++void
++getsigcmds(int signal)
++{
++ int i;
++ unsigned int sig = signal - SIGRTMIN;
++ for (i = 0; i < LENGTH(blocks); i++)
++ if (blocks[i].signal == sig)
++ getcmd(i, NULL);
+}
+
+int
+getstatus(int width)
+{
+ int i, len, all = width, delimlen = TEXTW(delimiter) - lrpad;
++ char fgcol[8];
++ /* fg bg */
++ const char *cols[8] = { fgcol, colors[SchemeStatus][ColBg] };
++ //uncomment to inverse the colors
++ //const char *cols[8] = { colors[SchemeStatus][ColBg], fgcol };
+
-+ drw_setscheme(drw, scheme[SchemeNorm]); /* 're-set' the scheme */
-+#ifdef INVERSED
++ #if INVERSED
+ for (i = 0; i < LENGTH(blocks); i++)
-+#else
++ #else
+ for (i = LENGTH(blocks) - 1; i >= 0; i--)
-+#endif /* INVERSED */
++ #endif /* INVERSED */
+ {
+ if (*blockoutput[i] == '\0') /* ignore command that output NULL or '\0' */
+ continue;
++ strncpy(fgcol, blocks[i].color, 8);
++ /* re-load the scheme with the new colors */
++ scheme[SchemeStatus] = drw_scm_create(drw, cols, 3);
++ drw_setscheme(drw, scheme[SchemeStatus]); /* 're-set' the scheme */
+ len = TEXTW(blockoutput[i]) - lrpad;
+ all -= len;
+ drw_text(drw, all, 0, len, bh, 0, blockoutput[i], 0);
+ /* draw delimiter */
-+ if (delimiter == '\0') /* ignore no delimiter */
++ if (*delimiter == '\0') /* ignore no delimiter */
+ continue;
++ drw_setscheme(drw, scheme[SchemeNorm]);
+ all -= delimlen;
+ drw_text(drw, all, 0, delimlen, bh, 0, delimiter, 0);
+ }
@@ -296,117 +324,208 @@ index a96f33c..6e79e5f 100644
+ return stsw = width - all;
+}
+
- int
- gettextprop(Window w, Atom atom, char *text, unsigned int size)
- {
-@@ -1219,7 +1320,7 @@ propertynotify(XEvent *e)
- Window trans;
- XPropertyEvent *ev = &e->xproperty;
-
-- if ((ev->window == root) && (ev->atom == XA_WM_NAME))
-+ if ((ev->window == root) && ((ev->atom == XA_WM_NAME) || (ev->atom == dwmstatus)))
- updatestatus();
- else if (ev->state == PropertyDelete)
- return; /* ignore */
-@@ -1427,6 +1528,19 @@ sendmon(Client *c, Monitor *m)
- arrange(NULL);
- }
-
-+void
-+sendstatusbar(const Arg *arg)
++int
++gcd(int a, int b)
+{
-+ if (fork() == 0) {
-+ char button[2] = { '0' + arg->i & 0xff, '\0' };
-+ char shcmd[CMDLENGTH + 20];
-+ snprintf(shcmd, LENGTH(shcmd), "%s && kill -%d %d", blocks[blocknum].command, blocks[blocknum].signal + 34, getppid());
-+ setenv("BLOCK_BUTTON", button, 1);
-+ execlp("/bin/sh", "sh", "-c", shcmd, (char*)NULL);
-+ exit(EXIT_SUCCESS);
++ int temp;
++
++ while (b > 0) {
++ temp = a % b;
++ a = b;
++ b = temp;
+ }
++
++ return a;
+}
+
++
+ int
+ gettextprop(Window w, Atom atom, char *text, unsigned int size)
+ {
+@@ -1376,12 +1512,99 @@ restack(Monitor *m)
void
- setclientstate(Client *c, long state)
+ run(void)
{
-@@ -1530,6 +1644,27 @@ setmfact(const Arg *arg)
- arrange(selmon);
- }
-
-+void
-+sighandler(int signum)
-+{
-+ XEvent event;
++ int i;
+ XEvent ev;
++ struct pollfd fds[LENGTH(blocks) + 1] = {0};
+
-+ getsigcmds(signum-SIGRTMIN);
++ fds[0].fd = ConnectionNumber(dpy);
++ fds[0].events = POLLIN;
+
-+ /* send a custom Atom in PropertyNotify event to the root window */
-+ event.type = PropertyNotify;
-+ event.xproperty.atom = dwmstatus;
-+ event.xproperty.window = root;
-+ XSendEvent(dpy, root, False, PropertyNotify, &event);
-+ XFlush(dpy);
-+}
++ #if INVERSED
++ for (i = LENGTH(blocks) - 1; i >= 0; i--)
++ #else
++ for (i = 0; i < LENGTH(blocks); i++)
++ #endif /* INVERSED */
++ {
++ pipe(pipes[i]);
++ fds[i + 1].fd = pipes[i][0];
++ fds[i + 1].events = POLLIN;
++ getcmd(i, NULL);
++ if (blocks[i].interval) {
++ maxinterval = MAX(blocks[i].interval, maxinterval);
++ sleepinterval = gcd(blocks[i].interval, sleepinterval);
++ }
++ }
++
++ alarm(sleepinterval);
+ /* main event loop */
+ XSync(dpy, False);
+- while (running && !XNextEvent(dpy, &ev))
+- if (handler[ev.type])
+- handler[ev.type](&ev); /* call handler */
++ while (running) {
++
++ /* bar hidden, then skip poll */
++ if (!selmon->showbar) {
++ XNextEvent(dpy, &ev);
++ if (handler[ev.type])
++ handler[ev.type](&ev); /* call handler */
++ continue;
++ }
++
++ if ((poll(fds, LENGTH(blocks) + 1, -1)) == -1) {
++ /* FIXME other than SIGALRM and the real time signals,
++ * there seems to be a signal being que if using
++ * 'xsetroot -name' sutff */
++ if (errno == EINTR) /* signal caught */
++ continue;
++ fprintf(stderr, "dwm: poll ");
++ perror("failed");
++ exit(EXIT_FAILURE);
++ }
++
++ /* handle display fd */
++ if (fds[0].revents & POLLIN) {
++ while (running && XPending(dpy)) {
++ XNextEvent(dpy, &ev);
++ if (handler[ev.type])
++ handler[ev.type](&ev); /* call handler */
++ }
++ } else if (fds[0].revents & POLLHUP) {
++ fprintf(stderr, "dwm: main event loop, hang up");
++ perror(" failed");
++ exit(EXIT_FAILURE);
++ }
++
++ /* handle blocks */
++ for (i = 0; i < LENGTH(blocks); i++) {
++ if (fds[i + 1].revents & POLLIN) {
++ /* empty buffer with CMDLENGTH + 1 byte for the null terminator */
++ int bt = read(fds[i + 1].fd, blockoutput[i], CMDLENGTH);
++ /* remove lock for the current block */
++ execlock &= ~(1 << i);
++
++ if (bt == -1) { /* if read failed */
++ fprintf(stderr, "dwm: read failed in block %s\n", blocks[i].command);
++ perror(" failed");
++ continue;
++ }
+
++ if (blockoutput[i][bt - 1] == '\n') /* chop off ending new line, if one is present */
++ blockoutput[i][bt - 1] = '\0';
++ else /* NULL terminate the string */
++ blockoutput[i][bt++] = '\0';
++
++ drawbar(selmon);
++ } else if (fds[i + 1].revents & POLLHUP) {
++ fprintf(stderr, "dwm: block %d hangup", i);
++ perror(" failed");
++ exit(EXIT_FAILURE);
++ }
++ }
++ }
++
++ /* close the pipes after running */
++ for (i = 0; i < LENGTH(blocks); i++) {
++ close(pipes[i][0]);
++ close(pipes[i][1]);
++ }
+ }
+
+ void
+@@ -1427,6 +1650,13 @@ sendmon(Client *c, Monitor *m)
+ arrange(NULL);
+ }
+
+void
-+dummysighandler(int unused)
++sendstatusbar(const Arg *arg)
+{
-+ return;
++ char button[2] = { '0' + arg->i & 0xff, '\0' };
++ getcmd(blocknum, button);
+}
+
void
- setup(void)
+ setclientstate(Client *c, long state)
{
-@@ -1540,6 +1675,27 @@ setup(void)
- /* clean up any zombies immediately */
- sigchld(0);
-
-+ /* ignore all real time signals */
-+ for (i = SIGRTMIN; i <= SIGRTMAX; i++)
-+ signal(i, dummysighandler);
+@@ -1537,8 +1767,20 @@ setup(void)
+ XSetWindowAttributes wa;
+ Atom utf8string;
+
+- /* clean up any zombies immediately */
+- sigchld(0);
++ setsignal(SIGCHLD, sigchld); /* zombies */
++ setsignal(SIGALRM, sigalrm); /* timer */
+
-+ /* init blocks */
-+#ifdef INVERSED
-+ for (i = LENGTH(blocks) - 1; i >= 0; i--)
-+#else
++ #ifdef __linux__
++ /* handle defined real time signals (linux only) */
+ for (i = 0; i < LENGTH(blocks); i++)
-+#endif /* INVERSED */
-+ {
-+ if (blocks[i].signal) /* init signals */
-+ signal(SIGRTMIN+blocks[i].signal, sighandler);
-+ getcmd(i, blockoutput[i]);
-+ }
++ if (blocks[i].signal)
++ setsignal(SIGRTMIN + blocks[i].signal, getsigcmds);
++ #endif /* __linux__ */
+
+ /* pid as an enviromental variable */
+ char envpid[16];
+ snprintf(envpid, LENGTH(envpid), "%d", getpid());
+ setenv("STATUSBAR", envpid, 1);
-+
+
/* init screen */
screen = DefaultScreen(dpy);
- sw = DisplayWidth(dpy, screen);
-@@ -1552,6 +1708,7 @@ setup(void)
- bh = drw->fonts->h + 2;
- updategeom();
- /* init atoms */
-+ dwmstatus = XInternAtom(dpy, "UPDATE_DWM_STATUSBAR", False);
- utf8string = XInternAtom(dpy, "UTF8_STRING", False);
- wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
- wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
-@@ -1839,6 +1996,13 @@ updatebarpos(Monitor *m)
- m->by = -bh;
+@@ -1600,6 +1842,21 @@ setup(void)
+ focus(NULL);
}
-
+
++void
++setsignal(int sig, void (*handler)(int unused))
++{
++ struct sigaction sa;
++
++ sa.sa_handler = handler;
++ sigemptyset(&sa.sa_mask);
++ sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
++
++ if (sigaction(sig, &sa, 0) == -1) {
++ fprintf(stderr, "signal %d ", sig);
++ perror("failed to setup");
++ exit(EXIT_FAILURE);
++ }
++}
+
+ void
+ seturgent(Client *c, int urg)
+@@ -1632,11 +1889,18 @@ showhide(Client *c)
+ }
+ }
+
++
+void
-+updateblock(const Arg *arg)
++sigalrm(int unused)
+{
-+ getsigcmds(arg->ui);
-+ updatestatus();
++ getcmds(count);
++ alarm(sleepinterval);
++ count = (count + sleepinterval - 1) % maxinterval + 1;
+}
+
void
- updateclientlist()
+ sigchld(int unused)
{
-@@ -1993,8 +2157,6 @@ updatesizehints(Client *c)
+- if (signal(SIGCHLD, sigchld) == SIG_ERR)
+- die("can't install SIGCHLD handler:");
+ while (0 < waitpid(-1, NULL, WNOHANG));
+ }
+
+@@ -1993,8 +2257,6 @@ updatesizehints(Client *c)
void
updatestatus(void)
{
@@ -414,7 +533,7 @@ index a96f33c..6e79e5f 100644
- strcpy(stext, "dwm-"VERSION);
drawbar(selmon);
}
-
---
-2.35.1
+
+--
+2.36.1
diff --git a/dwm.suckless.org/patches/integrated-status-text/index.md b/dwm.suckless.org/patches/integrated-status-text/index.md
@@ -3,26 +3,40 @@ integrated status text
Description
-----------
-Allows dwm to handle the text by itself This is a dwmblocks integration into
-dwm itself. You can update the blocks only with signals of with mouseclicks.
-The 'interval' value does nothing and is meant to be there to 're-use' on
-future patches. You can checkout my build with more features like 'async'
-updates
-[https://codeberg.org/explosion-mental/Dwm](https://codeberg.org/explosion-mental/Dwm),
-which is were I'm extracting this patch, if you want a much better experience.
-
-What you need to know:
-- This patch makes dwm sets a enviromental variable with the PID of itself to
- be more 'friendly'. With this you can do `kill -35 $STATUSBAR`, which updates
- block with signal 1 (34 + signal of the block)
-- Other way to update a block is inside dwm itself, with the `updateblock`
- function. It accepts an unsigned int (non negative) number which value
- indicates the signal of the block you want to update.
-- Mouse clicks are handled with `sendstatusbar` (a mouse function only!) which
- accepts the value that you want to pass to the block command as a 'variable'
- called `BLOCK_BUTTON`, which should be handled in the script (block command)
-- Since this uses real time signals to handle the updates, shouldn't work in
- openbsd, but I could be wrong.
+Allows dwm to handle the text by itself. You can
+ think of it like a dwmblocks integration into dwm itself. This is extracted
+ from my dwm build[0] in which you can find even more information.
+
+Example:
+```
+/* fg command interval signal */
+{ "#000000", "echo 'dwm block!", 10, 3},
+```
+
+- fg: the foreground color of the individual block, for the background it uses
+ the bg of SchemeStatus. You can swap behaviour uncommenting a comment in
+ dwm.c (search for 'uncomment to inverse the colors')
+
+- command: it uses the output of the commands for the status text interval: in
+ seconds, how much does it have to pass before updating the block.
+
+- interval: in seconds, how many seconds until the block it's updated
+
+- signal: have to be less than 30. This lets you update the block with `kill`
+ by adding 35 to this value.
+ For the block above it would be 34 + 3 = 37 -> `kill -37 $(pidof dwm)`.
+ These signals are linux dependant.
+
+You can change `$(pidof dwm)` with `$STATUSBAR` to 'fix' signaling multiple
+instances of dwm, since this patch also wraps the PID of dwm into the
+`$STATUSBAR` enviromental variable.
+
+Last thing, mouse actions. For this you need to handle the env variable
+`$BLOCK_BUTTON` in a script, this is so you can easily reuse the scripts used
+in dwmblocks. And remember that mouse actions update the block.
+
+[0] https://github.com/explosion-mental/Dwm or
+https://codeberg.org/explosion-mental/Dwm
Download
--------