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 |