dwm-dwmfifo-20230714-e81f17d.diff - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
dwm-dwmfifo-20230714-e81f17d.diff (8238B)
---
1 From 898a3f86703be6fb6f3690916797b80bf1d4dbc8 Mon Sep 17 00:00:00 2001
2 From: Santtu Lakkala <inz@inz.fi>
3 Date: Thu, 13 Jul 2023 15:48:14 +0300
4 Subject: [PATCH] Command FIFO for dwm
5
6 Builds on the previous version of dwmfifo, but:
7 - proper buffering and line detection
8 - basic argument parsing
9 - new commands to show a window by xid or name pattern
10 ---
11 config.def.h | 26 +++++++
12 dwm.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++-
13 2 files changed, 223 insertions(+), 3 deletions(-)
14
15 diff --git a/config.def.h b/config.def.h
16 index 9efa774..fc4db01 100644
17 --- a/config.def.h
18 +++ b/config.def.h
19 @@ -114,3 +114,29 @@ static const Button buttons[] = {
20 { ClkTagBar, MODKEY, Button3, toggletag, {0} },
21 };
22
23 +static const char *dwmfifo = "/tmp/dwm.fifo";
24 +static Command commands[] = {
25 + { "dmenu", spawn, {.v = dmenucmd} },
26 + { "term", spawn, {.v = termcmd} },
27 + { "quit", quit, {0} },
28 + { "togglebar", togglebar, {0} },
29 + { "focusstack", focusstack, .parse = parseplusminus },
30 + { "incnmaster", incnmaster, .parse = parseplusminus },
31 + { "setmfact", setmfact, .parse = parseplusminus },
32 + { "zoom", zoom, {0} },
33 + { "killclient", killclient, {0} },
34 + { "setlayout-tiled", setlayout, {.v = &layouts[0]} },
35 + { "setlayout-float", setlayout, {.v = &layouts[1]} },
36 + { "setlayout-mono", setlayout, {.v = &layouts[2]} },
37 + { "togglelayout", setlayout, {0} },
38 + { "togglefloating", togglefloating, {0} },
39 + { "viewwin", viewwin, .parse = parsexid },
40 + { "viewname", viewname, .parse = parsestr },
41 + { "viewall", view, {.ui = ~0} },
42 + { "focusmon", focusmon, .parse = parseplusminus },
43 + { "tagmon", tagmon, .parse = parseplusminus },
44 + { "view", view, .parse = parsetag },
45 + { "toggleview", toggleview, .parse = parsetag },
46 + { "tag", tag, .parse = parsetag },
47 + { "toggletag", toggletag, .parse = parsetag },
48 +};
49 diff --git a/dwm.c b/dwm.c
50 index f1d86b2..13537fc 100644
51 --- a/dwm.c
52 +++ b/dwm.c
53 @@ -21,6 +21,7 @@
54 * To understand everything else, start reading main().
55 */
56 #include <errno.h>
57 +#include <fcntl.h>
58 #include <locale.h>
59 #include <signal.h>
60 #include <stdarg.h>
61 @@ -28,6 +29,8 @@
62 #include <stdlib.h>
63 #include <string.h>
64 #include <unistd.h>
65 +#include <poll.h>
66 +#include <fnmatch.h>
67 #include <sys/types.h>
68 #include <sys/wait.h>
69 #include <X11/cursorfont.h>
70 @@ -141,6 +144,13 @@ typedef struct {
71 int monitor;
72 } Rule;
73
74 +typedef struct {
75 + const char *name;
76 + void (*func)(const Arg *arg);
77 + const Arg arg;
78 + int (*parse)(Arg *arg, const char *s, size_t len);
79 +} Command;
80 +
81 /* function declarations */
82 static void applyrules(Client *c);
83 static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
84 @@ -161,6 +171,7 @@ static void destroynotify(XEvent *e);
85 static void detach(Client *c);
86 static void detachstack(Client *c);
87 static Monitor *dirtomon(int dir);
88 +static void dispatchcmd(void);
89 static void drawbar(Monitor *m);
90 static void drawbars(void);
91 static void enternotify(XEvent *e);
92 @@ -227,6 +238,8 @@ static void updatetitle(Client *c);
93 static void updatewindowtype(Client *c);
94 static void updatewmhints(Client *c);
95 static void view(const Arg *arg);
96 +static void viewwin(const Arg *arg);
97 +static void viewname(const Arg *arg);
98 static Client *wintoclient(Window w);
99 static Monitor *wintomon(Window w);
100 static int xerror(Display *dpy, XErrorEvent *ee);
101 @@ -267,10 +280,63 @@ static Display *dpy;
102 static Drw *drw;
103 static Monitor *mons, *selmon;
104 static Window root, wmcheckwin;
105 +static int fifofd;
106 +
107 +static int parsetag(Arg *a, const char *s, size_t len);
108 +static int parseplusminus(Arg *a, const char *s, size_t len);
109 +static int parsexid(Arg *a, const char *s, size_t len);
110 +static int parsestr(Arg *a, const char *s, size_t len);
111
112 /* configuration, allows nested code to access above variables */
113 #include "config.h"
114
115 +static int parsetag(Arg *a, const char *s, size_t len)
116 +{
117 + char *end;
118 + unsigned int rv = strtoul(s, &end, 10);
119 + if (end == s)
120 + a->ui = 0;
121 + else if (rv > LENGTH(tags))
122 + return 0;
123 + else if (rv == 0)
124 + a->ui = ~0U;
125 + else
126 + a->ui = 1U << (rv - 1);
127 +
128 + return 1;
129 +}
130 +
131 +static int parseplusminus(Arg *a, const char *s, size_t len)
132 +{
133 + if (*s == '+')
134 + a->i = +1;
135 + else if (*s == '-')
136 + a->i = -1;
137 + else
138 + return 0;
139 + return 1;
140 +}
141 +
142 +static int parsexid(Arg *a, const char *s, size_t len)
143 +{
144 + char *end;
145 + unsigned long long sv = strtoull(s, &end, 0);
146 +
147 + if (end == s)
148 + return 0;
149 +
150 + a->v = (void *)(intptr_t)sv;
151 + return 1;
152 +}
153 +
154 +static int parsestr(Arg *a, const char *s, size_t len)
155 +{
156 + while (*s == ' ' || *s == '\t')
157 + s++;
158 + a->v = s;
159 + return 1;
160 +}
161 +
162 /* compile-time check if all tags fit into an unsigned int bit array. */
163 struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
164
165 @@ -494,6 +560,7 @@ cleanup(void)
166 XSync(dpy, False);
167 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
168 XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
169 + close(fifofd);
170 }
171
172 void
173 @@ -695,6 +762,71 @@ dirtomon(int dir)
174 return m;
175 }
176
177 +static const char *
178 +strnprefix(const char *haystack, size_t hlen, const char *needle)
179 +{
180 + while (*needle && hlen--) {
181 + if (*haystack++ != *needle++)
182 + return 0;
183 + }
184 +
185 + if (*needle)
186 + return NULL;
187 + return haystack;
188 +}
189 +
190 +void
191 +dispatchcmd(void)
192 +{
193 + static char buf[BUFSIZ];
194 + static char * const bend = 1[&buf];
195 + static char *bw = buf;
196 + static int longline = 0;
197 + ssize_t n;
198 + char *nl;
199 + char *pl = buf;
200 + char *dend;
201 + Command *i;
202 +
203 + n = read(fifofd, bw, bend - bw);
204 + if (n == -1)
205 + die("Failed to read() from DWM fifo %s:", dwmfifo);
206 + dend = bw + n;
207 +
208 + if (longline) {
209 + if (!(nl = memchr(bw, '\n', dend - bw)))
210 + return;
211 + bw = pl = nl + 1;
212 + longline = 0;
213 + }
214 +
215 + while ((nl = memchr(bw, '\n', dend - bw))) {
216 + for (i = commands; i < 1[&commands]; i++) {
217 + const char *arg;
218 +
219 + if (!(arg = strnprefix(pl, nl - pl, i->name)))
220 + continue;
221 + *nl = '\0';
222 + if (i->parse) {
223 + Arg a;
224 + if (i->parse(&a, arg, nl - arg))
225 + i->func(&a);
226 + } else {
227 + i->func(&i->arg);
228 + }
229 +
230 + break;
231 + }
232 + bw = pl = nl + 1;
233 + }
234 +
235 + memmove(buf, pl, dend - pl);
236 + bw = dend - pl + buf;
237 +
238 + if (bw == bend)
239 + bw = buf;
240 +}
241 +
242 void
243 drawbar(Monitor *m)
244 {
245 @@ -1379,15 +1511,31 @@ restack(Monitor *m)
246 while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
247 }
248
249 +static Bool evpredicate()
250 +{
251 + return True;
252 +}
253 +
254 void
255 run(void)
256 {
257 XEvent ev;
258 + struct pollfd fds[2] = {
259 + { .events = POLLIN },
260 + { .fd = fifofd, .events = POLLIN }
261 + };
262 /* main event loop */
263 XSync(dpy, False);
264 - while (running && !XNextEvent(dpy, &ev))
265 - if (handler[ev.type])
266 - handler[ev.type](&ev); /* call handler */
267 + fds[0].fd = ConnectionNumber(dpy);
268 + while (running) {
269 + (void)poll(fds, 1[&fds] - fds, -1);
270 + if (fds[1].revents & POLLIN)
271 + dispatchcmd();
272 + if (fds[0].revents & POLLIN)
273 + while (XCheckIfEvent(dpy, &ev, evpredicate, NULL))
274 + if (handler[ev.type])
275 + handler[ev.type](&ev); /* call handler */
276 + }
277 }
278
279 void
280 @@ -1611,6 +1759,9 @@ setup(void)
281 XSelectInput(dpy, root, wa.event_mask);
282 grabkeys();
283 focus(NULL);
284 + fifofd = open(dwmfifo, O_RDWR | O_CLOEXEC | O_NONBLOCK);
285 + if (fifofd < 0)
286 + die("Failed to open() DWM fifo %s:", dwmfifo);
287 }
288
289 void
290 @@ -2062,6 +2213,49 @@ view(const Arg *arg)
291 arrange(selmon);
292 }
293
294 +void
295 +viewclient(Client *c)
296 +{
297 + if (!(c->tags & c->mon->tagset[c->mon->seltags]))
298 + view(&(Arg){ .ui = c->tags });
299 + focus(c);
300 +}
301 +
302 +void
303 +viewwin(const Arg *arg)
304 +{
305 + Client *c = wintoclient((Window)(intptr_t)arg->v);
306 +
307 + if (!c)
308 + return;
309 +
310 + viewclient(c);
311 +}
312 +
313 +Client *
314 +pattoclient(const char *pattern)
315 +{
316 + Client *c;
317 + Monitor *m;
318 +
319 + for (m = mons; m; m = m->next)
320 + for (c = m->clients; c; c = c->next)
321 + if (!fnmatch(pattern, c->name, 0))
322 + return c;
323 + return NULL;
324 +}
325 +
326 +void
327 +viewname(const Arg *arg)
328 +{
329 + Client *c = pattoclient(arg->v);
330 +
331 + if (!c)
332 + return;
333 +
334 + viewclient(c);
335 +}
336 +
337 Client *
338 wintoclient(Window w)
339 {
340 --
341 2.25.1
342