| 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 |