Introduction
Introduction Statistics Contact Development Disclaimer Help
dwm-dwmfifo-20230714-e81f17d.diff - sites - public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log
Files
Refs
---
dwm-dwmfifo-20230714-e81f17d.diff (8238B)
---
1 From 898a3f86703be6fb6f3690916797b80bf1d4dbc8 Mon Sep 17 00:00:00 2001
2 From: Santtu Lakkala <[email protected]>
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, togglet…
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, in…
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, CurrentTi…
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, NUL…
274 + if (handler[ev.type])
275 + handler[ev.type](&ev); /* call …
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
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.