This patch includes a small correction I forgot to put in the previous
patch. There is no need to specify a timeval to wait for (select
should block until some data arrives either on stdin or on the x11
file descriptor, as recommended by the select() man page).
diff -r 2b9683c50723 dmenu.c
--- a/dmenu.c	Wed Dec 01 20:25:10 2010 +0000
+++ b/dmenu.c	Tue Dec 07 17:32:54 2010 +0100
@@ -4,6 +4,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <fcntl.h>
+#include <sys/select.h>
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
 #include <X11/Xutil.h>
@@ -34,6 +36,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);
@@ -59,6 +62,7 @@
 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,9 @@
 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) {
+	while (fgets(buf, sizeof buf, stdin)) {
 		if((p = strchr(buf, '\n')))
 			*p = '\0';
 		if(!(item = malloc(sizeof *item)))
@@ -444,14 +447,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))
+	while(XPending(dc->dpy) && !XNextEvent(dc->dpy, &ev))
 		switch(ev.type) {
 		case Expose:
 			if(ev.xexpose.count == 0)
@@ -472,6 +478,32 @@
 }
 
 void
+run(void) {
+	fd_set fds;
+	int x11_fd, n, nfds, flags;
+
+	flags = fcntl(STDIN_FILENO, F_GETFL);
+	flags |= O_NONBLOCK;
+	fcntl(STDIN_FILENO, F_SETFL, flags);
+
+	x11_fd = XConnectionNumber(dc->dpy);
+	nfds = MAX(STDIN_FILENO, x11_fd) + 1;
+	while(1) {
+		FD_ZERO(&fds);
+		if (!feof(stdin))
+			FD_SET(STDIN_FILENO, &fds);
+		FD_SET(x11_fd, &fds);
+		n = select(nfds, &fds, NULL, NULL, NULL);
+		if(n < 0)
+			eprintf("cannot select\n");
+		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 +563,7 @@
 	promptw = prompt ? textw(dc, prompt) : 0;
 	XMapRaised(dc->dpy, win);
 	text[0] = '\0';
-	match();
+	drawmenu();
 }
 
 void

Reply via email to