[PATCH] Convert xlsatoms to XCB

Peter Harris pharris at opentext.com
Mon Oct 19 15:13:03 PDT 2009


This dramatically improves latency, at the cost of a small amount of
bandwidth.

Signed-off-by: Peter Harris <pharris at opentext.com>
---
 configure.ac |    2 +-
 xlsatoms.c   |  131 ++++++++++++++++++++++++++++++++++++---------------------
 2 files changed, 84 insertions(+), 49 deletions(-)

diff --git a/configure.ac b/configure.ac
index af7e086..34725f1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -39,7 +39,7 @@ AC_PROG_INSTALL
 XORG_DEFAULT_OPTIONS
 
 # Checks for pkg-config packages
-PKG_CHECK_MODULES(XLSATOMS, x11 xmuu)
+PKG_CHECK_MODULES(XLSATOMS, xcb)
 AC_SUBST(XLSATOMS_CFLAGS)
 AC_SUBST(XLSATOMS_LIBS)
 
diff --git a/xlsatoms.c b/xlsatoms.c
index 6e09b21..604a0ca 100644
--- a/xlsatoms.c
+++ b/xlsatoms.c
@@ -29,18 +29,21 @@ in this Software without prior written authorization from The Open Group.
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <X11/Xos.h>
-#include <X11/Xlib.h>
-#include <X11/Xproto.h>
-#include <X11/Xmu/Error.h>
+#include <string.h>
+#include <xcb/xcb.h>
+#include <xcb/xproto.h>
+
+#define ATOMS_PER_BATCH 100 /* This number can be tuned 
+				higher for fewer round-trips
+				lower for less bandwidth wasted */
 
 static char *ProgramName;
+static char *DisplayString;
 
-static void do_name ( Display *dpy, char *format, char *name );
+static void do_name ( xcb_connection_t *c, char *format, char *name );
 static int parse_range ( char *range, long *lowp, long *highp );
-static void do_range ( Display *dpy, char *format, char *range );
-static int catcher ( Display *dpy, XErrorEvent *err );
-static void list_atoms ( Display *dpy, char *format, int mask, 
+static void do_range ( xcb_connection_t *c, char *format, char *range );
+static void list_atoms ( xcb_connection_t *c, char *format, int mask, 
 			 long low, long high );
 
 static void 
@@ -67,7 +70,7 @@ main(int argc, char *argv[])
     char *format = "%lu\t%s";
     int i, doit;
     int didit = 0;
-    Display *dpy = NULL;
+    xcb_connection_t *c = NULL;
 
     ProgramName = argv[0];
 
@@ -88,14 +91,14 @@ main(int argc, char *argv[])
 		  case 'r':			/* -range num-[num] */
 		    if (++i >= argc) usage ();
 		    if (doit) {
-			do_range (dpy, format, argv[i]);
+			do_range (c, format, argv[i]);
 			didit = 1;
 		    }
 		    continue;
 		  case 'n':			/* -name string */
 		    if (++i >= argc) usage ();
 		    if (doit) {
-			do_name (dpy, format, argv[i]);
+			do_name (c, format, argv[i]);
 			didit = 1;
 		    }
 		    continue;
@@ -104,33 +107,42 @@ main(int argc, char *argv[])
 	    usage ();
 	}
 	if (!doit) {
-	    dpy = XOpenDisplay (displayname);
-	    if (!dpy) {
+	    DisplayString = displayname;
+	    if (!DisplayString)
+		DisplayString = getenv("DISPLAY");
+	    if (!DisplayString)
+		DisplayString = "";
+	    c = xcb_connect(displayname, NULL);
+	    if (!c || xcb_connection_has_error(c)) {
 		fprintf (stderr, "%s:  unable to open display \"%s\"\n",
-			 ProgramName, XDisplayName (displayname));
+			 ProgramName, DisplayString);
 		exit (1);
 	    }
 	} else
 	    if (!didit)		/* no options, default is list all */
-		list_atoms(dpy, format, 0, 0, 0);
+		list_atoms(c, format, 0, 0, 0);
     }
 
-    XCloseDisplay (dpy);
+    xcb_disconnect(c);
     exit (0);
 }
 
 static void
-do_name(Display *dpy, char *format, char *name)
+do_name(xcb_connection_t *c, char *format, char *name)
 {
-    Atom a = XInternAtom (dpy, name, True);
+    xcb_intern_atom_reply_t *a = xcb_intern_atom_reply(c, 
+	xcb_intern_atom_unchecked(c, 1, strlen(name), name), NULL);
 
-    if (a != None) {
-	printf (format, (unsigned long) a, name);
+    if (a && a->atom != XCB_NONE) {
+	printf (format, (unsigned long) a->atom, name);
 	putchar ('\n');
     } else {
 	fprintf (stderr, "%s:  no atom named \"%s\" on server \"%s\"\n",
-		 ProgramName, name, DisplayString(dpy));
+		 ProgramName, name, DisplayString);
     }
+
+    if (a)
+	free(a);
 }
 
 
@@ -173,62 +185,85 @@ parse_range(char *range, long *lowp, long *highp)
 }
 
 static void
-do_range(Display *dpy, char *format, char *range)
+do_range(xcb_connection_t *c, char *format, char *range)
 {
     int mask;
     long low, high;
 
     mask = parse_range (range, &low, &high);
-    list_atoms (dpy, format, mask, low, high);
+    list_atoms (c, format, mask, low, high);
 }
 
-
-static int 
-catcher(Display *dpy, XErrorEvent *err)
+static int
+say_batch(xcb_connection_t *c, char *format, xcb_get_atom_name_cookie_t *cookie, long low, long count)
 {
-    if (err->request_code != X_GetAtomName) {
-	XmuPrintDefaultErrorMessage (dpy, err, stderr);
+    xcb_generic_error_t *e;
+    char atom_name[1024];
+    long i;
+    int done = 0;
+
+    for (i = 0; i < count; i++)
+	cookie[i] = xcb_get_atom_name(c, i + low);
+
+    for (i = 0; i < count; i++) {
+	xcb_get_atom_name_reply_t *r;
+	r = xcb_get_atom_name_reply(c, cookie[i], &e);
+	if (r) {
+	    /* We could just use %*.s in 'format', but we want to be compatible
+	       with legacy command line usage */
+	    snprintf(atom_name, sizeof(atom_name), "%.*s",
+		r->name_len, xcb_get_atom_name_name(r));
+
+	    printf (format, i + low, atom_name);
+	    putchar ('\n');
+	    free(r);
+	}
+	if (e) {
+	    done = 1;
+	    free(e);
+	}
     }
-    return 0;
+
+    return done;
 }
 
 static void
-list_atoms(Display *dpy, char *format, int mask, long low, long high)
+list_atoms(xcb_connection_t *c, char *format, int mask, long low, long high)
 {
-    XErrorHandler oldhandler = XSetErrorHandler (catcher);
+    xcb_get_atom_name_cookie_t *cookie_jar;
+    int done = 0;
 
     switch (mask) {
       case RangeHigh:
 	low = 1;
 	/* fall through */
       case (RangeLow | RangeHigh):
-	for (; low <= high; low++) {
-	    char *s = XGetAtomName (dpy, (Atom)low);
-	    if (s) {
-		printf (format, low, s);
-		putchar ('\n');
-		XFree (s);
-	    }
+	cookie_jar = malloc((high - low + 1) * sizeof(xcb_get_atom_name_cookie_t));
+        if (!cookie_jar) {
+	    fprintf(stderr, "Out of memory allocating space for %ld atom requests\n", high - low);
+	    return;
 	}
+
+	say_batch(c, format, cookie_jar, low, high - low + 1);
+	free(cookie_jar);
 	break;
 
       default:
 	low = 1;
 	/* fall through */
       case RangeLow:
-	for (; ; low++) {
-	    char *s = XGetAtomName (dpy, (Atom)low);
-	    if (s) {
-		printf (format, low, s);
-		putchar ('\n');
-		XFree (s);
-	    } else {
-		break;
-	    }
+	cookie_jar = malloc(ATOMS_PER_BATCH * sizeof(xcb_get_atom_name_cookie_t));
+        if (!cookie_jar) {
+	    fprintf(stderr, "Out of memory allocating space for %ld atom requests\n", (long) ATOMS_PER_BATCH);
+	    return;
+	}
+	while (!done) {
+	    done = say_batch(c, format, cookie_jar, low, ATOMS_PER_BATCH);
+	    low += ATOMS_PER_BATCH;
 	}
+	free(cookie_jar);
 	break;
     }
 
-    XSetErrorHandler (oldhandler);
     return;
 }
-- 
1.6.5.1.1367.gcd48


--------------060702030302000000010809--


More information about the Xcb mailing list