commit 307963264c4f839883562c07b6fbfc8e3ebac7fa
parent 5dc49ea1bb3cdf8e3088eac5e818febc6e578446
Author: Santtu Lakkala <inz@inz.fi>
Date: Fri, 14 Jul 2023 13:39:32 +0300
[dwm][patch][dwmfifo] Fix busyloop
Diffstat:
3 files changed, 343 insertions(+), 343 deletions(-)
diff --git a/dwm.suckless.org/patches/dwmfifo/dwm-dwmfifo-20230713-e81f17d.diff b/dwm.suckless.org/patches/dwmfifo/dwm-dwmfifo-20230713-e81f17d.diff
@@ -1,342 +0,0 @@
-From a37879a10bbca1591a2677ddecd641a4bcb8ffbd Mon Sep 17 00:00:00 2001
-From: Santtu Lakkala <inz@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
-@@ -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
-@@ -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>
-@@ -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>
-@@ -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);
-@@ -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);
-@@ -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);
-@@ -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 == '\t')
-+ 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]; };
-
-@@ -494,6 +560,7 @@ cleanup(void)
- XSync(dpy, False);
- XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
- XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
-+ close(fifofd);
- }
-
- void
-@@ -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, '\n', dend - bw)))
-+ return;
-+ bw = pl = nl + 1;
-+ longline = 0;
-+ }
-+
-+ while ((nl = memchr(bw, '\n', dend - bw))) {
-+ for (i = commands; i < 1[&commands]; i++) {
-+ const char *arg;
-+
-+ if (!(arg = strnprefix(pl, nl - pl, i->name)))
-+ continue;
-+ *nl = '\0';
-+ 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)
- {
-@@ -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
-@@ -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
-@@ -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/dwm-dwmfifo-20230714-e81f17d.diff b/dwm.suckless.org/patches/dwmfifo/dwm-dwmfifo-20230714-e81f17d.diff
@@ -0,0 +1,342 @@
+From 898a3f86703be6fb6f3690916797b80bf1d4dbc8 Mon Sep 17 00:00:00 2001
+From: Santtu Lakkala <inz@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
+@@ -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..13537fc 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -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>
+@@ -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>
+@@ -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);
+@@ -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);
+@@ -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);
+@@ -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 == '\t')
++ 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]; };
+
+@@ -494,6 +560,7 @@ cleanup(void)
+ XSync(dpy, False);
+ XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
+ XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
++ close(fifofd);
+ }
+
+ void
+@@ -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, '\n', dend - bw)))
++ return;
++ bw = pl = nl + 1;
++ longline = 0;
++ }
++
++ while ((nl = memchr(bw, '\n', dend - bw))) {
++ for (i = commands; i < 1[&commands]; i++) {
++ const char *arg;
++
++ if (!(arg = strnprefix(pl, nl - pl, i->name)))
++ continue;
++ *nl = '\0';
++ 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)
+ {
+@@ -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
+@@ -1611,6 +1759,9 @@ setup(void)
+ XSelectInput(dpy, root, wa.event_mask);
+ grabkeys();
+ focus(NULL);
++ fifofd = open(dwmfifo, O_RDWR | O_CLOEXEC | O_NONBLOCK);
++ if (fifofd < 0)
++ die("Failed to open() DWM fifo %s:", dwmfifo);
+ }
+
+ void
+@@ -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
@@ -28,7 +28,7 @@ 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)
+* [dwm-dwmfifo-20230713-e81f17d.diff](dwm-dwmfifo-20230714-e81f17d.diff) (8.1k) (2023-07-14)
Author
------