[wiki] [sites] [dwm][patch] integrated status text || explosion-mental

From: <git_AT_suckless.org>
Date: Sun, 27 Feb 2022 23:33:33 +0100

commit 16019480fe6123e0d57d9a4b3ec7d6dd293beaf9
Author: explosion-mental <explosion0mental_AT_gmail.com>
Date: Sun Feb 27 17:32:54 2022 -0500

    [dwm][patch] integrated status text

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
new file mode 100644
index 00000000..f2a9278b
--- /dev/null
+++ b/dwm.suckless.org/patches/integrated-status-text/dwm-integrated-status-text-6.3.diff
_AT_@ -0,0 +1,420 @@
+From f3a9dd0222319d72303be37ae5268831582fe487 Mon Sep 17 00:00:00 2001
+From: explosion-mental <explosion0mental_AT_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.
+
+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.
+---
+ config.def.h | 53 +++++++++++++++
+ dwm.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 227 insertions(+), 12 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index a2ac963..99d6b3d 100644
+--- a/config.def.h
++++ b/config.def.h
+_AT_@ -18,6 +18,49 @@ static const char *colors[][3] = {
+ [SchemeSel] = { col_gray4, col_cyan, col_cyan },
+ };
+
++/* 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},
++};
++
++/* inverse the order of the blocks, comment to disable */
++#define INVERSED
++/* delimeter between blocks commands. NULL character ('++static char delimiter[] = " ";
++/* max number of character that one block command can output */
++#define CMDLENGTH 50
++
+ /* tagging */
+ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
+_AT_@ -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} },
+_AT_@ -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 */
++ { ClkStatusText, 0, Button1, sendstatusbar, {.i = 1 } },
++ { ClkStatusText, 0, Button2, sendstatusbar, {.i = 2 } },
++ { ClkStatusText, 0, Button3, sendstatusbar, {.i = 3 } },
++ { ClkStatusText, 0, Button4, sendstatusbar, {.i = 4 } },
++ { 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} },
+diff --git a/dwm.c b/dwm.c
+index a96f33c..6e79e5f 100644
+--- a/dwm.c
++++ b/dwm.c
+_AT_@ -141,6 +141,12 @@ typedef struct {
+ int monitor;
+ } Rule;
+
++typedef struct {
++ const char *command;
++ const unsigned int interval;
++ const unsigned int signal;
++} Block;
++
+ /* function declarations */
+ static void applyrules(Client *c);
+ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
+_AT_@ -172,6 +178,9 @@ 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 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);
+_AT_@ -197,6 +206,7 @@ static void run(void);
+ static void scan(void);
+ static int sendevent(Client *c, Atom proto);
+ static void sendmon(Client *c, Monitor *m);
++static void sendstatusbar(const Arg *arg);
+ static void setclientstate(Client *c, long state);
+ static void setfocus(Client *c);
+ static void setfullscreen(Client *c, int fullscreen);
+_AT_@ -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);
+_AT_@ -237,7 +248,7 @@ 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 */
+_AT_@ -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;
+_AT_@ -272,6 +283,8 @@ static Window root, wmcheckwin;
+ /* configuration, allows nested code to access above variables */
+ #include "config.h"
+
++static char blockoutput[LENGTH(blocks)][CMDLENGTH] = {0};
++
+ /* compile-time check if all tags fit into an unsigned int bit array. */
+ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
+
+_AT_@ -440,9 +453,25 @@ 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 > (x = selmon->ww - stsw)) {
+ click = ClkStatusText;
+- else
++ int len, i;
++ #ifdef INVERSED
++ for (i = LENGTH(blocks) - 1; i >= 0; i--)
++ #else
++ for (i = 0; i < LENGTH(blocks); i++)
++ #endif /* INVERSED */
++ {
++ if (*blockoutput[i] == '++ continue;
++ len = TEXTW(blockoutput[i]) - lrpad + TEXTW(delimiter) - lrpad;
++ x += len;
++ if (ev->x <= x && ev->x >= x - len) { /* if the mouse is between the block area */
++ blocknum = i; /* store what block the mouse is clicking */
++ break;
++ }
++ }
++ } else
+ click = ClkWinTitle;
+ } else if ((c = wintoclient(ev->window))) {
+ focus(c);
+_AT_@ -706,11 +735,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]);
+- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
+- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
+- }
++ 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;
+_AT_@ -903,6 +929,81 @@ 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)
++{
++ FILE *cmdf = popen(blocks[i].command, "r");
++ if (!cmdf)
++ 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);
++
++ pclose(cmdf);
++
++ strcpy(output, tmpstr);
++ remove_all(output, '
'); /* chop off newline */
++}
++
++void
++getsigcmds(unsigned int signal)
++{
++ 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]);
++ }
++}
++
++int
++getstatus(int width)
++{
++ int i, len, all = width, delimlen = TEXTW(delimiter) - lrpad;
++
++ drw_setscheme(drw, scheme[SchemeNorm]); /* 're-set' the scheme */
++#ifdef INVERSED
++ for (i = 0; i < LENGTH(blocks); i++)
++#else
++ for (i = LENGTH(blocks) - 1; i >= 0; i--)
++#endif /* INVERSED */
++ {
++ if (*blockoutput[i] == '++ continue;
++ len = TEXTW(blockoutput[i]) - lrpad;
++ all -= len;
++ drw_text(drw, all, 0, len, bh, 0, blockoutput[i], 0);
++ /* draw delimiter */
++ if (delimiter == '++ continue;
++ all -= delimlen;
++ drw_text(drw, all, 0, delimlen, bh, 0, delimiter, 0);
++ }
++
++ return stsw = width - all;
++}
++
+ int
+ gettextprop(Window w, Atom atom, char *text, unsigned int size)
+ {
+_AT_@ -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 */
+_AT_@ -1427,6 +1528,19 @@ sendmon(Client *c, Monitor *m)
+ arrange(NULL);
+ }
+
++void
++sendstatusbar(const Arg *arg)
++{
++ if (fork() == 0) {
++ char button[2] = { '0' + arg->i & 0xff, '++ 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);
++ }
++}
++
+ void
+ setclientstate(Client *c, long state)
+ {
+_AT_@ -1530,6 +1644,27 @@ setmfact(const Arg *arg)
+ arrange(selmon);
+ }
+
++void
++sighandler(int signum)
++{
++ XEvent event;
++
++ getsigcmds(signum-SIGRTMIN);
++
++ /* 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);
++}
++
++void
++dummysighandler(int unused)
++{
++ return;
++}
++
+ void
+ setup(void)
+ {
+_AT_@ -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);
++
++ /* init blocks */
++#ifdef INVERSED
++ for (i = LENGTH(blocks) - 1; i >= 0; i--)
++#else
++ 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]);
++ }
++
++ /* 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);
+_AT_@ -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);
+_AT_@ -1839,6 +1996,13 @@ updatebarpos(Monitor *m)
+ m->by = -bh;
+ }
+
++void
++updateblock(const Arg *arg)
++{
++ getsigcmds(arg->ui);
++ updatestatus();
++}
++
+ void
+ updateclientlist()
+ {
+_AT_@ -1993,8 +2157,6 @@ updatesizehints(Client *c)
+ void
+ updatestatus(void)
+ {
+- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
+- strcpy(stext, "dwm-"VERSION);
+ drawbar(selmon);
+ }
+
+--
+2.35.1
+
diff --git a/dwm.suckless.org/patches/integrated-status-text/index.md b/dwm.suckless.org/patches/integrated-status-text/index.md
new file mode 100644
index 00000000..bb07ee43
--- /dev/null
+++ b/dwm.suckless.org/patches/integrated-status-text/index.md
_AT_@ -0,0 +1,35 @@
+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://github.com/explosion-mental/Dwm, which is were I'm extracting
+this patch.
+
+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.
+
+Download
+--------
+* [dwm-integrated-status-text-6.3.diff](dwm-integrated-status-text-6.3.diff)
+* [github mirror](https://github.com/explosion-mental/Dwm/blob/main/Patches/dwm-integrated-status-text-6.3.diff)
+
+Authors
+-------
+* explosion-mental - <explosion0mental_AT_gmail.com>
Received on Sun Feb 27 2022 - 23:33:33 CET

This archive was generated by hypermail 2.3.0 : Sun Feb 27 2022 - 23:36:49 CET