[wiki] [sites] [dwm][patch][dwmfifo] Add new version of dwmfifo patch || Santtu Lakkala

From: <git_AT_suckless.org>
Date: Thu, 13 Jul 2023 15:03:17 +0200

commit 77a71712f0d34efdd594addd4f4dd1058b8a3f30
Author: Santtu Lakkala <inz_AT_inz.fi>
Date: Thu Jul 13 16:02:41 2023 +0300

    [dwm][patch][dwmfifo] Add new version of dwmfifo patch

diff --git a/dwm.suckless.org/patches/dwmfifo/dwm-dwmfifo-20230713-e81f17d.diff b/dwm.suckless.org/patches/dwmfifo/dwm-dwmfifo-20230713-e81f17d.diff
new file mode 100644
index 00000000..fd3e911d
--- /dev/null
+++ b/dwm.suckless.org/patches/dwmfifo/dwm-dwmfifo-20230713-e81f17d.diff
_AT_@ -0,0 +1,342 @@
+From a37879a10bbca1591a2677ddecd641a4bcb8ffbd Mon Sep 17 00:00:00 2001
+From: Santtu Lakkala <inz_AT_inz.fi>
+Date: Thu, 13 Jul 2023 15:48:14 +0300
+Subject: [PATCH] Command FIFO for dwm
+
+Builds on the previous version of dwmfifo, but:
+ - proper buffering and line detection
+ - basic argument parsing
+ - new commands to show a window by xid or name pattern
+---
+ config.def.h | 26 +++++++
+ dwm.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 223 insertions(+), 3 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 9efa774..fc4db01 100644
+--- a/config.def.h
++++ b/config.def.h
+_AT_@ -114,3 +114,29 @@ static const Button buttons[] = {
+ { ClkTagBar, MODKEY, Button3, toggletag, {0} },
+ };
+
++static const char *dwmfifo = "/tmp/dwm.fifo";
++static Command commands[] = {
++ { "dmenu", spawn, {.v = dmenucmd} },
++ { "term", spawn, {.v = termcmd} },
++ { "quit", quit, {0} },
++ { "togglebar", togglebar, {0} },
++ { "focusstack", focusstack, .parse = parseplusminus },
++ { "incnmaster", incnmaster, .parse = parseplusminus },
++ { "setmfact", setmfact, .parse = parseplusminus },
++ { "zoom", zoom, {0} },
++ { "killclient", killclient, {0} },
++ { "setlayout-tiled", setlayout, {.v = &layouts[0]} },
++ { "setlayout-float", setlayout, {.v = &layouts[1]} },
++ { "setlayout-mono", setlayout, {.v = &layouts[2]} },
++ { "togglelayout", setlayout, {0} },
++ { "togglefloating", togglefloating, {0} },
++ { "viewwin", viewwin, .parse = parsexid },
++ { "viewname", viewname, .parse = parsestr },
++ { "viewall", view, {.ui = ~0} },
++ { "focusmon", focusmon, .parse = parseplusminus },
++ { "tagmon", tagmon, .parse = parseplusminus },
++ { "view", view, .parse = parsetag },
++ { "toggleview", toggleview, .parse = parsetag },
++ { "tag", tag, .parse = parsetag },
++ { "toggletag", toggletag, .parse = parsetag },
++};
+diff --git a/dwm.c b/dwm.c
+index f1d86b2..202ed6a 100644
+--- a/dwm.c
++++ b/dwm.c
+_AT_@ -21,6 +21,7 @@
+ * To understand everything else, start reading main().
+ */
+ #include <errno.h>
++#include <fcntl.h>
+ #include <locale.h>
+ #include <signal.h>
+ #include <stdarg.h>
+_AT_@ -28,6 +29,8 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
++#include <poll.h>
++#include <fnmatch.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+ #include <X11/cursorfont.h>
+_AT_@ -141,6 +144,13 @@ typedef struct {
+ int monitor;
+ } Rule;
+
++typedef struct {
++ const char *name;
++ void (*func)(const Arg *arg);
++ const Arg arg;
++ int (*parse)(Arg *arg, const char *s, size_t len);
++} Command;
++
+ /* function declarations */
+ static void applyrules(Client *c);
+ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
+_AT_@ -161,6 +171,7 @@ static void destroynotify(XEvent *e);
+ static void detach(Client *c);
+ static void detachstack(Client *c);
+ static Monitor *dirtomon(int dir);
++static void dispatchcmd(void);
+ static void drawbar(Monitor *m);
+ static void drawbars(void);
+ static void enternotify(XEvent *e);
+_AT_@ -227,6 +238,8 @@ static void updatetitle(Client *c);
+ static void updatewindowtype(Client *c);
+ static void updatewmhints(Client *c);
+ static void view(const Arg *arg);
++static void viewwin(const Arg *arg);
++static void viewname(const Arg *arg);
+ static Client *wintoclient(Window w);
+ static Monitor *wintomon(Window w);
+ static int xerror(Display *dpy, XErrorEvent *ee);
+_AT_@ -267,10 +280,63 @@ static Display *dpy;
+ static Drw *drw;
+ static Monitor *mons, *selmon;
+ static Window root, wmcheckwin;
++static int fifofd;
++
++static int parsetag(Arg *a, const char *s, size_t len);
++static int parseplusminus(Arg *a, const char *s, size_t len);
++static int parsexid(Arg *a, const char *s, size_t len);
++static int parsestr(Arg *a, const char *s, size_t len);
+
+ /* configuration, allows nested code to access above variables */
+ #include "config.h"
+
++static int parsetag(Arg *a, const char *s, size_t len)
++{
++ char *end;
++ unsigned int rv = strtoul(s, &end, 10);
++ if (end == s)
++ a->ui = 0;
++ else if (rv > LENGTH(tags))
++ return 0;
++ else if (rv == 0)
++ a->ui = ~0U;
++ else
++ a->ui = 1U << (rv - 1);
++
++ return 1;
++}
++
++static int parseplusminus(Arg *a, const char *s, size_t len)
++{
++ if (*s == '+')
++ a->i = +1;
++ else if (*s == '-')
++ a->i = -1;
++ else
++ return 0;
++ return 1;
++}
++
++static int parsexid(Arg *a, const char *s, size_t len)
++{
++ char *end;
++ unsigned long long sv = strtoull(s, &end, 0);
++
++ if (end == s)
++ return 0;
++
++ a->v = (void *)(intptr_t)sv;
++ return 1;
++}
++
++static int parsestr(Arg *a, const char *s, size_t len)
++{
++ while (*s == ' ' || *s == ' ')
++ s++;
++ a->v = s;
++ return 1;
++}
++
+ /* compile-time check if all tags fit into an unsigned int bit array. */
+ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
+
+_AT_@ -494,6 +560,7 @@ cleanup(void)
+ XSync(dpy, False);
+ XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
+ XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
++ close(fifofd);
+ }
+
+ void
+_AT_@ -695,6 +762,71 @@ dirtomon(int dir)
+ return m;
+ }
+
++static const char *
++strnprefix(const char *haystack, size_t hlen, const char *needle)
++{
++ while (*needle && hlen--) {
++ if (*haystack++ != *needle++)
++ return 0;
++ }
++
++ if (*needle)
++ return NULL;
++ return haystack;
++}
++
++void
++dispatchcmd(void)
++{
++ static char buf[BUFSIZ];
++ static char * const bend = 1[&buf];
++ static char *bw = buf;
++ static int longline = 0;
++ ssize_t n;
++ char *nl;
++ char *pl = buf;
++ char *dend;
++ Command *i;
++
++ n = read(fifofd, bw, bend - bw);
++ if (n == -1)
++ die("Failed to read() from DWM fifo %s:", dwmfifo);
++ dend = bw + n;
++
++ if (longline) {
++ if (!(nl = memchr(bw, '
', dend - bw)))
++ return;
++ bw = pl = nl + 1;
++ longline = 0;
++ }
++
++ while ((nl = memchr(bw, '
', dend - bw))) {
++ for (i = commands; i < 1[&commands]; i++) {
++ const char *arg;
++
++ if (!(arg = strnprefix(pl, nl - pl, i->name)))
++ continue;
++ *nl = '++ if (i->parse) {
++ Arg a;
++ if (i->parse(&a, arg, nl - arg))
++ i->func(&a);
++ } else {
++ i->func(&i->arg);
++ }
++
++ break;
++ }
++ bw = pl = nl + 1;
++ }
++
++ memmove(buf, pl, dend - pl);
++ bw = dend - pl + buf;
++
++ if (bw == bend)
++ bw = buf;
++}
++
+ void
+ drawbar(Monitor *m)
+ {
+_AT_@ -1379,15 +1511,31 @@ restack(Monitor *m)
+ while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
+ }
+
++static Bool evpredicate()
++{
++ return True;
++}
++
+ void
+ run(void)
+ {
+ XEvent ev;
++ struct pollfd fds[2] = {
++ { .events = POLLIN },
++ { .fd = fifofd, .events = POLLIN }
++ };
+ /* main event loop */
+ XSync(dpy, False);
+- while (running && !XNextEvent(dpy, &ev))
+- if (handler[ev.type])
+- handler[ev.type](&ev); /* call handler */
++ fds[0].fd = ConnectionNumber(dpy);
++ while (running) {
++ (void)poll(fds, 1[&fds] - fds, -1);
++ if (fds[1].revents & POLLIN)
++ dispatchcmd();
++ if (fds[0].revents & POLLIN)
++ while (XCheckIfEvent(dpy, &ev, evpredicate, NULL))
++ if (handler[ev.type])
++ handler[ev.type](&ev); /* call handler */
++ }
+ }
+
+ void
+_AT_@ -1611,6 +1759,9 @@ setup(void)
+ XSelectInput(dpy, root, wa.event_mask);
+ grabkeys();
+ focus(NULL);
++ fifofd = open(dwmfifo, O_RDONLY | O_CLOEXEC | O_NONBLOCK);
++ if (fifofd < 0)
++ die("Failed to open() DWM fifo %s:", dwmfifo);
+ }
+
+ void
+_AT_@ -2062,6 +2213,49 @@ view(const Arg *arg)
+ arrange(selmon);
+ }
+
++void
++viewclient(Client *c)
++{
++ if (!(c->tags & c->mon->tagset[c->mon->seltags]))
++ view(&(Arg){ .ui = c->tags });
++ focus(c);
++}
++
++void
++viewwin(const Arg *arg)
++{
++ Client *c = wintoclient((Window)(intptr_t)arg->v);
++
++ if (!c)
++ return;
++
++ viewclient(c);
++}
++
++Client *
++pattoclient(const char *pattern)
++{
++ Client *c;
++ Monitor *m;
++
++ for (m = mons; m; m = m->next)
++ for (c = m->clients; c; c = c->next)
++ if (!fnmatch(pattern, c->name, 0))
++ return c;
++ return NULL;
++}
++
++void
++viewname(const Arg *arg)
++{
++ Client *c = pattoclient(arg->v);
++
++ if (!c)
++ return;
++
++ viewclient(c);
++}
++
+ Client *
+ wintoclient(Window w)
+ {
+--
+2.25.1
+
diff --git a/dwm.suckless.org/patches/dwmfifo/index.md b/dwm.suckless.org/patches/dwmfifo/index.md
index 55d1434c..844c3ae1 100644
--- a/dwm.suckless.org/patches/dwmfifo/index.md
+++ b/dwm.suckless.org/patches/dwmfifo/index.md
_AT_@ -19,7 +19,8 @@ terminals on each of the 2 monitors.
         echo term > /tmp/dwm.fifo
 
 The sleep in between is currently needed to avoid buffering up more than a
-single command. You may experiment with the actual sleep value.
+single command. You may experiment with the actual sleep value. Sleeps are no
+longer needed with the 20230713 version.
 
 Similarly you can modify your config.h and add more commands that you may want
 to execute (like tabbed-surf or similar).
_AT_@ -27,7 +28,9 @@ to execute (like tabbed-surf or similar).
 Download
 --------
 * [dwm-dwmfifo-6.1.diff](dwm-dwmfifo-6.1.diff) (6.9k) (2014-01-29)
+* [dwm-dwmfifo-20230713-e81f17d.diff](dwm-dwmfifo-20230713-e81f17d.diff) (8.1k) (2023-07-13)
 
 Author
 ------
 * sin - <sin_AT_2f30.org>
+* inz - <inz_AT_inz.fi>
Received on Thu Jul 13 2023 - 15:03:17 CEST

This archive was generated by hypermail 2.3.0 : Thu Jul 13 2023 - 15:12:52 CEST