Hi all, This is my first journey into the DWM code. I've added a FIFO control file that you can use to simulate any of the existing keybinds.
The command names are similar to the functions implementing them. A simple example would be: echo -n term > /tmp/dwm.fifo echo -n focusmon+ > /tmp/dwm.fifo echo -n term > /tmp/dwm.fifo This will spawn a terminal on the first monitor, then move to the second and spawn one there. It is possible to script simple layouts like this. Let me know if this is of interest to anyone and I will post it to the patches section on the wiki. One command that is missing but would be nice is "exec <cmd>". cheers, sin
>From de46334b2342368e5d1fbb1900291994deaca35f Mon Sep 17 00:00:00 2001 From: sin <s...@2f30.org> Date: Wed, 29 Jan 2014 11:58:56 +0000 Subject: [PATCH] Add DWM control FIFO I've added the corresponding commands for all assigned keybinds. To use simply create the fifo in your .xinitrc, the default path is at /tmp/dwm.fifo. A simple command sequence would be: echo -n term > /tmp/dwm.fifo echo -n focusmon+ > /tmp/dwm.fifo echo -n term > /tmp/dwm.fifo --- config.def.h | 62 ++++++++++++++++++++ dwm.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 238 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index 875885b..9264465 100644 --- a/config.def.h +++ b/config.def.h @@ -108,3 +108,65 @@ static Button buttons[] = { { ClkTagBar, MODKEY, Button3, toggletag, {0} }, }; +static const char *dwmfifo = "/tmp/dwm.fifo"; +static Command commands[] = { + { "dmenu", dodmenu, {.v = dmenucmd} }, + { "term", doterm, {.v = termcmd} }, + { "togglebar", dotogglebar, {0} }, + { "focusstack+", dofocusstack, {.i = +1} }, + { "focusstack-", dofocusstack, {.i = -1} }, + { "incnmaster+", doincnmaster, {.i = +1} }, + { "incnmaster-", doincnmaster, {.i = -1} }, + { "setmfact+", dosetmfact, {.f = +0.05} }, + { "setmfact-", dosetmfact, {.f = -0.05} }, + { "zoom", dozoom, {0} }, + { "view", doview, {0} }, + { "killclient", dokillclient, {0} }, + { "setlayout-tiled", dosetlayout, {.v = &layouts[0]} }, + { "setlayout-float", dosetlayout, {.v = &layouts[1]} }, + { "setlayout-mono", dosetlayout, {.v = &layouts[2]} }, + { "togglelayout", dosetlayout, {0} }, + { "togglefloating", dotogglefloating, {0} }, + { "viewall", doview, {.ui = ~0} }, + { "tag", dotag, {.ui = ~0} }, + { "focusmon+", dofocusmon, {.i = +1} }, + { "focusmon-", dofocusmon, {.i = -1} }, + { "tagmon+", dotagmon, {.i = +1} }, + { "tagmon-", dotagmon, {.i = -1} }, + { "view1", doview, {.ui = 1 << 0} }, + { "view2", doview, {.ui = 1 << 1} }, + { "view3", doview, {.ui = 1 << 2} }, + { "view4", doview, {.ui = 1 << 3} }, + { "view5", doview, {.ui = 1 << 4} }, + { "view6", doview, {.ui = 1 << 5} }, + { "view7", doview, {.ui = 1 << 6} }, + { "view8", doview, {.ui = 1 << 7} }, + { "view9", doview, {.ui = 1 << 8} }, + { "toggleview1", dotoggleview, {.ui = 1 << 0} }, + { "toggleview2", dotoggleview, {.ui = 1 << 1} }, + { "toggleview3", dotoggleview, {.ui = 1 << 2} }, + { "toggleview4", dotoggleview, {.ui = 1 << 3} }, + { "toggleview5", dotoggleview, {.ui = 1 << 4} }, + { "toggleview6", dotoggleview, {.ui = 1 << 5} }, + { "toggleview7", dotoggleview, {.ui = 1 << 6} }, + { "toggleview8", dotoggleview, {.ui = 1 << 7} }, + { "toggleview9", dotoggleview, {.ui = 1 << 8} }, + { "tag1", dotag, {.ui = 1 << 0} }, + { "tag2", dotag, {.ui = 1 << 1} }, + { "tag3", dotag, {.ui = 1 << 2} }, + { "tag4", dotag, {.ui = 1 << 3} }, + { "tag5", dotag, {.ui = 1 << 4} }, + { "tag6", dotag, {.ui = 1 << 5} }, + { "tag7", dotag, {.ui = 1 << 6} }, + { "tag8", dotag, {.ui = 1 << 7} }, + { "tag9", dotag, {.ui = 1 << 8} }, + { "toggletag1", dotoggletag, {.ui = 1 << 0} }, + { "toggletag2", dotoggletag, {.ui = 1 << 1} }, + { "toggletag3", dotoggletag, {.ui = 1 << 2} }, + { "toggletag4", dotoggletag, {.ui = 1 << 3} }, + { "toggletag5", dotoggletag, {.ui = 1 << 4} }, + { "toggletag6", dotoggletag, {.ui = 1 << 5} }, + { "toggletag7", dotoggletag, {.ui = 1 << 6} }, + { "toggletag8", dotoggletag, {.ui = 1 << 7} }, + { "toggletag9", dotoggletag, {.ui = 1 << 8} }, +}; diff --git a/dwm.c b/dwm.c index 1bbb4b3..7b1b8af 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 <stdarg.h> #include <signal.h> @@ -28,6 +29,8 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <sys/select.h> +#include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #include <X11/cursorfont.h> @@ -140,6 +143,12 @@ typedef struct { int monitor; } Rule; +typedef struct { + const char *name; + void (*func)(const Arg *arg); + const Arg arg; +} Command; + /* function declarations */ static void applyrules(Client *c); static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact); @@ -161,9 +170,27 @@ 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 dodmenu(const Arg *arg); +static void dofocusmon(const Arg *arg); +static void dofocusstack(const Arg *arg); +static void doincnmaster(const Arg *arg); +static void dokillclient(const Arg *arg); +static void dosetlayout(const Arg *arg); +static void dosetmfact(const Arg *arg); +static void dotag(const Arg *arg); +static void dotagmon(const Arg *arg); +static void doterm(const Arg *arg); +static void dotogglebar(const Arg *arg); +static void dotogglefloating(const Arg *arg); +static void dotoggletag(const Arg *arg); +static void dotoggleview(const Arg *arg); +static void doview(const Arg *arg); +static void dozoom(const Arg *arg); static void drawbar(Monitor *m); static void drawbars(void); static void enternotify(XEvent *e); +static Bool evpredicate(); static void expose(XEvent *e); static void focus(Client *c); static void focusin(XEvent *e); @@ -266,6 +293,7 @@ static Drw *drw; static Fnt *fnt; static Monitor *mons, *selmon; static Window root; +static int fifofd; /* configuration, allows nested code to access above variables */ #include "config.h" @@ -485,6 +513,8 @@ cleanup(void) { XSync(dpy, False); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + if (fifofd != -1) + close(fifofd); } void @@ -691,6 +721,121 @@ dirtomon(int dir) { } void +dispatchcmd(void) +{ + int i; + char buf[BUFSIZ]; + ssize_t n; + + n = read(fifofd, buf, sizeof(buf) - 1); + if (n == -1) + die("Failed to read from DWM fifo\n"); + buf[n] = '\0'; + for (i = 0; i < LENGTH(commands); i++) { + if (strcmp(commands[i].name, buf) == 0) { + commands[i].func(&commands[i].arg); + break; + } + } +} + +void +dodmenu(const Arg *arg) +{ + spawn(arg); +} + +static void +dofocusmon(const Arg *arg) +{ + focusmon(arg); +} + +void +dofocusstack(const Arg *arg) +{ + focusstack(arg); +} + +void +doincnmaster(const Arg *arg) +{ + incnmaster(arg); +} + +void +dokillclient(const Arg *arg) +{ + killclient(arg); +} + +void +dosetlayout(const Arg *arg) +{ + setlayout(arg); +} + +void +dosetmfact(const Arg *arg) +{ + setmfact(arg); +} + +static void +dotag(const Arg *arg) +{ + tag(arg); +} + +static void +dotagmon(const Arg *arg) +{ + tagmon(arg); +} + +void +doterm(const Arg *arg) +{ + spawn(arg); +} + +void +dotogglebar(const Arg *arg) +{ + togglebar(arg); +} + +static void +dotogglefloating(const Arg *arg) +{ + togglefloating(arg); +} + +static void +dotoggletag(const Arg *arg) +{ + toggletag(arg); +} + +static void +dotoggleview(const Arg *arg) +{ + toggleview(arg); +} + +void +doview(const Arg *arg) +{ + view(arg); +} + +void +dozoom(const Arg *arg) +{ + zoom(arg); +} + +void drawbar(Monitor *m) { int x, xx, w; unsigned int i, occ = 0, urg = 0; @@ -768,6 +913,12 @@ enternotify(XEvent *e) { focus(c); } +Bool +evpredicate() +{ + return True; +} + void expose(XEvent *e) { Monitor *m; @@ -1341,11 +1492,30 @@ restack(Monitor *m) { void run(void) { XEvent ev; + fd_set rfds; + int n; + int x11fd, maxfd; /* main event loop */ XSync(dpy, False); - while(running && !XNextEvent(dpy, &ev)) - if(handler[ev.type]) - handler[ev.type](&ev); /* call handler */ + x11fd = ConnectionNumber(dpy); + maxfd = fifofd; + if (x11fd > maxfd) + maxfd = x11fd; + maxfd++; + while (running) { + FD_ZERO(&rfds); + FD_SET(fifofd, &rfds); + FD_SET(x11fd, &rfds); + n = select(maxfd, &rfds, NULL, NULL, NULL); + if (n > 0) { + if (FD_ISSET(fifofd, &rfds)) + dispatchcmd(); + if (FD_ISSET(x11fd, &rfds)) + if (XCheckIfEvent(dpy, &ev, evpredicate, NULL)) + if (handler[ev.type]) + handler[ev.type](&ev); /* call handler */ + } + } } void @@ -1543,6 +1713,9 @@ setup(void) { XSelectInput(dpy, root, wa.event_mask); grabkeys(); focus(NULL); + fifofd = open(dwmfifo, O_RDWR | O_NONBLOCK); + if (fifofd < 0) + die("Failed to open DWM fifo\n"); } void -- 1.7.10.4