sites

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

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:
Mdwm.suckless.org/patches/integrated-status-text/dwm-integrated-status-text-6.3.diff | 605+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Mdwm.suckless.org/patches/integrated-status-text/index.md | 54++++++++++++++++++++++++++++++++++--------------------
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 --------