On Mon, Nov 29, 2010 at 2:44 AM, Connor Lane Smith <c...@lubutu.com> wrote:
> Great, it's a lot cleaner this way. One problem with this approach,
> though, is that if data is written to stdin it isn't displayed until
> the next X event. This is likely fine for your use case, and
> dmenu_run, but perhaps not for other cases. To fix that we'd have to
> select between stdin and XConnectionNumber(dc->dpy).

Here is a patch that implements this idea (still available on my
bitbucket repo). It actually makes dmenu pretty slow to read stdin.
comments/fix are welcome.
diff -r a79e4a9cb167 dmenu.c
--- a/dmenu.c	Sat Nov 20 09:25:08 2010 +0000
+++ b/dmenu.c	Mon Nov 29 23:47:52 2010 +0100
@@ -4,6 +4,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/select.h>
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
 #include <X11/Xutil.h>
@@ -34,6 +35,7 @@
 static size_t nextrune(int incr);
 static void paste(void);
 static void readstdin(void);
+static void readXEvent(void);
 static void run(void);
 static void setup(void);
 static void usage(void);
@@ -54,11 +56,13 @@
 static unsigned long normcol[ColLast];
 static unsigned long selcol[ColLast];
 static Atom utf8;
+static Bool eof = False;
 static Bool topbar = True;
 static DC *dc;
 static Item *items = NULL;
 static Item *matches, *sel;
 static Item *prev, *curr, *next;
+static Item **end = &items;
 static Window root, win;
 
 static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
@@ -102,7 +106,6 @@
 
 	dc = initdc();
 	initfont(dc, font);
-	readstdin();
 	setup();
 	run();
 
@@ -433,9 +436,10 @@
 void
 readstdin(void) {
 	char buf[sizeof text], *p;
-	Item *item, **end;
+	Item *item;
 
-	for(end = &items; fgets(buf, sizeof buf, stdin); *end = item, end = &item->next) {
+	eof = eof || !fgets(buf, sizeof buf, stdin);
+	if (!eof) {
 		if((p = strchr(buf, '\n')))
 			*p = '\0';
 		if(!(item = malloc(sizeof *item)))
@@ -444,14 +448,17 @@
 			eprintf("cannot strdup %u bytes\n", strlen(buf)+1);
 		item->next = item->left = item->right = NULL;
 		inputw = MAX(inputw, textw(dc, item->text));
+		*end = item;
+		end = &item->next;
+		match();
 	}
 }
 
 void
-run(void) {
+readXEvent(void) {
 	XEvent ev;
 
-	while(!XNextEvent(dc->dpy, &ev))
+	if(!XNextEvent(dc->dpy, &ev))
 		switch(ev.type) {
 		case Expose:
 			if(ev.xexpose.count == 0)
@@ -472,6 +479,32 @@
 }
 
 void
+run(void) {
+	fd_set fds;
+	int x11_fd, n, nfds;
+	struct timeval tv;
+
+	x11_fd = XConnectionNumber(dc->dpy);
+	nfds = MAX(STDIN_FILENO, x11_fd) + 1;
+	while(1) {
+		tv.tv_sec = 1;
+		tv.tv_usec = 0;
+		FD_ZERO(&fds);
+		FD_SET(STDIN_FILENO, &fds);
+		FD_SET(x11_fd, &fds);
+		n = select(nfds, &fds, NULL, NULL, &tv);
+		if(n < 0)
+			eprintf("cannot select\n");
+		if(n > 0) {
+			if (FD_ISSET(STDIN_FILENO, &fds))
+				readstdin();
+			if (FD_ISSET(x11_fd, &fds))
+				readXEvent();
+		}
+	}
+}
+
+void
 setup(void) {
 	int x, y, screen;
 	XSetWindowAttributes wa;
@@ -531,7 +564,7 @@
 	promptw = prompt ? textw(dc, prompt) : 0;
 	XMapRaised(dc->dpy, win);
 	text[0] = '\0';
-	match();
+	drawmenu();
 }
 
 void

Reply via email to