sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

dwm-dwmfifo-20230713-e81f17d.diff (8240B)


      1 From a37879a10bbca1591a2677ddecd641a4bcb8ffbd 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..202ed6a 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_RDONLY | 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