sites

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

commit 16019480fe6123e0d57d9a4b3ec7d6dd293beaf9
parent dfd8c535b4a2e82b584325c3e97831b46f34cacd
Author: explosion-mental <explosion0mental@gmail.com>
Date:   Sun, 27 Feb 2022 17:32:54 -0500

[dwm][patch] integrated status text

Diffstat:
Adwm.suckless.org/patches/integrated-status-text/dwm-integrated-status-text-6.3.diff | 420+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/integrated-status-text/index.md | 35+++++++++++++++++++++++++++++++++++
2 files changed, 455 insertions(+), 0 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 @@ -0,0 +1,420 @@ +From f3a9dd0222319d72303be37ae5268831582fe487 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. + +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 +@@ -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 ('\0') means no delimeter. */ ++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" }; + +@@ -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 */ ++ { 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 +@@ -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); +@@ -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); +@@ -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); +@@ -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); + + /* 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; + /* 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]; }; + +@@ -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] == '\0') //ignore command that output NULL or '\0' ++ 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); +@@ -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; +@@ -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, '\n'); /* 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] == '\0') /* ignore command that output NULL or '\0' */ ++ continue; ++ 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 */ ++ 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) + { +@@ -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) ++{ ++ 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); ++ } ++} ++ + void + setclientstate(Client *c, long state) + { +@@ -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) + { +@@ -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); +@@ -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; + } + ++void ++updateblock(const Arg *arg) ++{ ++ getsigcmds(arg->ui); ++ updatestatus(); ++} ++ + void + updateclientlist() + { +@@ -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 @@ -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@gmail.com>