[PATCH] Replace libx11 by libxcb

Julien Danjou julien at danjou.info
Tue Jul 27 10:57:18 PDT 2010


Signed-off-by: Julien Danjou <julien at danjou.info>
---
 configure.in            |   30 ++++----
 tools/dbus-launch-x11.c |  200 +++++++++++++++++++++++++++++++---------------
 tools/dbus-launch.c     |   12 ++--
 3 files changed, 157 insertions(+), 85 deletions(-)

diff --git a/configure.in b/configure.in
index 648b115..adaa1d4 100644
--- a/configure.in
+++ b/configure.in
@@ -124,6 +124,7 @@ AC_ARG_ENABLE(libaudit,AS_HELP_STRING([--enable-libaudit],[build audit daemon su
 AC_ARG_ENABLE(dnotify, AS_HELP_STRING([--enable-dnotify],[build with dnotify support (linux only)]),enable_dnotify=$enableval,enable_dnotify=auto)
 AC_ARG_ENABLE(inotify, AS_HELP_STRING([--enable-inotify],[build with inotify support (linux only)]),enable_inotify=$enableval,enable_inotify=auto)
 AC_ARG_ENABLE(kqueue, AS_HELP_STRING([--enable-kqueue],[build with kqueue support]),enable_kqueue=$enableval,enable_kqueue=auto)
+AC_ARG_ENABLE(x11, AS_HELP_STRING([--enable-x11],[build with X11 support]),enable_x11=$enableval,enable_x11=auto)
 AC_ARG_ENABLE(console-owner-file, AS_HELP_STRING([--enable-console-owner-file],[enable console owner file]),enable_console_owner_file=$enableval,enable_console_owner_file=auto)
 AC_ARG_ENABLE(userdb-cache, AS_HELP_STRING([--enable-userdb-cache],[build with userdb-cache support]),enable_userdb_cache=$enableval,enable_userdb_cache=yes)
 
@@ -1013,20 +1014,21 @@ if test x$dbus_win = xyes ; then
 else
 AC_PATH_XTRA
 
-## for now enable_x11 just tracks have_x11,
-## there's no --enable-x11
-if test x$no_x = xyes ; then
-   have_x11=no
-   enable_x11=no
-else
-   have_x11=yes
-   enable_x11=yes
-fi
-
-if test x$enable_x11 = xyes ; then
-   AC_DEFINE(DBUS_BUILD_X11,1,[Build X11-dependent code])
-   DBUS_X_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
-   DBUS_X_CFLAGS="$X_CFLAGS"
+if test x$enable_x11 = xyes || test x$enable_x11 = xauto ; then
+   PKG_CHECK_MODULES(XCB, xcb >= 1.6, have_xcb=true, have_xcb=false)
+   PKG_CHECK_MODULES(XCB_AUX, xcb-aux >= 0.3.6, have_xcb_aux=true, have_xcb_aux=false)
+   if ! $have_xcb && test x$enable_x11 = xyes; then
+      AC_MSG_ERROR([Explicitly requested X11 but libxcb not found])
+   fi
+   if ! $have_xcb_aux && test x$enable_x11 = xyes; then
+      AC_MSG_ERROR([Explicitly requested X11 but libxcb-aux not found])
+   fi
+   if $have_xcb && $have_xcb_aux; then
+      enable_x11=yes
+      AC_DEFINE(DBUS_BUILD_X11,1,[Build X11-dependent code])
+      DBUS_X_LIBS="$XCB_LIBS $XCB_AUX_LIBS"
+      DBUS_X_CFLAGS="$XCB_CLFAGS $XCB_AUX_CFLAGS"
+   fi
 else
    DBUS_X_LIBS=
    DBUS_X_CFLAGS=
diff --git a/tools/dbus-launch-x11.c b/tools/dbus-launch-x11.c
index fe49222..c2f9d19 100644
--- a/tools/dbus-launch-x11.c
+++ b/tools/dbus-launch-x11.c
@@ -34,16 +34,16 @@
 #include <stdio.h>
 #include <string.h>
 #include <pwd.h>
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
 
-Display *xdisplay = NULL;
-static Atom selection_atom;
-static Atom address_atom;
-static Atom pid_atom;
+xcb_connection_t *xconnection = NULL;
+static xcb_atom_t selection_atom;
+static xcb_atom_t address_atom;
+static xcb_atom_t pid_atom;
 
 static int
-x_io_error_handler (Display *xdisplay)
+x_io_error_handler (void)
 {
   verbose ("X IO error\n");
   kill_bus_and_exit (0);
@@ -211,23 +211,23 @@ ensure_session_directory (void)
   free (dir);
 }
 
-static Display *
+static xcb_connection_t *
 open_x11 (void)
 {
-  if (xdisplay != NULL)
-    return xdisplay;
+  int screen;
 
-  xdisplay = XOpenDisplay (NULL);
-  if (xdisplay != NULL)
-    {
-      verbose ("Connected to X11 display '%s'\n", DisplayString (xdisplay));
-      XSetIOErrorHandler (x_io_error_handler);
-    }
-  return xdisplay;
+  if (xconnection != NULL)
+    return xconnection;
+
+  xconnection = xcb_connect (NULL, &screen);
+  if (xconnection != NULL)
+      verbose ("Connected to X11 display '%s'\n", getenv("DISPLAY"));
+
+  return xconnection;
 }
 
 static int
-init_x_atoms (Display *display)
+init_x_atoms (xcb_connection_t *conn)
 {
   static const char selection_prefix[] = "_DBUS_SESSION_BUS_SELECTION_";
   static const char address_prefix[] = "_DBUS_SESSION_BUS_ADDRESS";
@@ -237,6 +237,8 @@ init_x_atoms (Display *display)
   const char *machine;
   char *user_name;
   struct passwd *user;
+  xcb_intern_atom_cookie_t selection_atom_c, address_atom_c, pid_atom_c;
+  xcb_intern_atom_reply_t *atom_reply;
 
   if (init)
     return TRUE;
@@ -269,15 +271,36 @@ init_x_atoms (Display *display)
   strcat (atom_name, user_name);
   strcat (atom_name, "_");
   strcat (atom_name, machine);
-  selection_atom = XInternAtom (display, atom_name, FALSE);
+  selection_atom_c = xcb_intern_atom(conn, 0, strlen(atom_name), atom_name);
 
   /* create the address property atom */
   strcpy (atom_name, address_prefix);
-  address_atom = XInternAtom (display, atom_name, FALSE);
+  address_atom_c = xcb_intern_atom(conn, 0, strlen(atom_name), atom_name);
 
   /* create the PID property atom */
   strcpy (atom_name, pid_prefix);
-  pid_atom = XInternAtom (display, atom_name, FALSE);
+  pid_atom_c = xcb_intern_atom(conn, 0, strlen(atom_name), atom_name);
+
+  atom_reply = xcb_intern_atom_reply (conn, selection_atom_c, NULL);
+  if (atom_reply)
+    {
+      selection_atom = atom_reply->atom;
+      free (atom_reply);
+    }
+
+  atom_reply = xcb_intern_atom_reply (conn, address_atom_c, NULL);
+  if (atom_reply)
+    {
+      address_atom = atom_reply->atom;
+      free (atom_reply);
+    }
+
+  atom_reply = xcb_intern_atom_reply (conn, pid_atom_c, NULL);
+  if (atom_reply)
+    {
+      pid_atom = atom_reply->atom;
+      free (atom_reply);
+    }
 
   free (atom_name);
   free (user_name);
@@ -293,42 +316,77 @@ init_x_atoms (Display *display)
 int
 x11_get_address (char **paddress, pid_t *pid, long *wid)
 {
-  Atom type;
-  Window owner;
+  xcb_atom_t type;
+  xcb_window_t owner;
   int format;
   unsigned long items;
   unsigned long after;
   char *data;
+  xcb_get_selection_owner_cookie_t owner_c;
+  xcb_get_selection_owner_reply_t *owner_r;
+  xcb_get_property_cookie_t prop_c;
+  xcb_get_property_reply_t *prop_r;
+
+  /* locate the selection owner */
+  owner_c = xcb_get_selection_owner (xconnection, selection_atom);
 
   *paddress = NULL;
 
-  /* locate the selection owner */
-  owner = XGetSelectionOwner (xdisplay, selection_atom);
-  if (owner == None)
+  owner_r = xcb_get_selection_owner_reply (xconnection, owner_c, NULL);
+
+  if(owner_r == NULL)
+    return TRUE;
+
+  owner = owner_r->owner;
+  free(owner_r);
+
+  if (owner == XCB_NONE)
     return TRUE;                /* no owner */
+
+  /* get the bus address */
+  prop_c = xcb_get_property (xconnection, 0, owner,
+                             address_atom, XCB_ATOM_STRING,
+                             0, 1024);
+
   if (wid != NULL)
     *wid = (long) owner;
 
-  /* get the bus address */
-  XGetWindowProperty (xdisplay, owner, address_atom, 0, 1024, False,
-                      XA_STRING, &type, &format, &items, &after,
-                      (unsigned char **) &data);
-  if (type == None || after != 0 || data == NULL || format != 8)
-    return FALSE;               /* error */
+  prop_r = xcb_get_property_reply (xconnection, prop_c, NULL);
+
+  if (!prop_r)
+    return FALSE;
+
+  data = xcb_get_property_value (prop_r);
+
+  if (prop_r->type == XCB_NONE
+      || prop_r->bytes_after != 0
+      ||  data == NULL || prop_r->format != 8)
+    {
+      free (prop_r);
+      return FALSE;               /* error */
+    }
 
   *paddress = xstrdup (data);
-  XFree (data);
+  free (prop_r);
 
   /* get the PID */
   if (pid != NULL)
     {
+      prop_c = xcb_get_property (xconnection, 0, owner,
+                                 pid_atom, XCB_ATOM_CARDINAL,
+                                 0, sizeof pid);
       *pid = 0;
-      XGetWindowProperty (xdisplay, owner, pid_atom, 0, sizeof pid, False,
-                          XA_CARDINAL, &type, &format, &items, &after,
-                          (unsigned char **) &data);
-      if (type != None && after == 0 && data != NULL && format == 32)
-        *pid = (pid_t) *(long*) data;
-      XFree (data);
+      prop_r = xcb_get_property_reply (xconnection, prop_c, NULL);
+      if (prop_r)
+        {
+          data = xcb_get_property_value (prop_r);
+          if (prop_r->type != XCB_NONE
+              && prop_r->bytes_after == 0
+              && data != NULL
+              && prop_r->format == 32)
+            *pid = (pid_t) *(long*) data;
+          free (prop_r);
+        }
     }
 
   return TRUE;                  /* success */
@@ -339,15 +397,16 @@ x11_get_address (char **paddress, pid_t *pid, long *wid)
  * If an error occurs, returns -1. If the selection already exists,
  * returns 1. (i.e. another daemon is already running)
  */
-static Window
+static xcb_window_t
 set_address_in_x11(char *address, pid_t pid)
 {
   char *current_address;
-  Window wid = None;
-  unsigned long pid32; /* Xlib property functions want _long_ not 32-bit for format "32" */
-  
+  xcb_window_t wid = XCB_NONE;
+  uint32_t pid32;
+  xcb_screen_t *s;
+
   /* lock the X11 display to make sure we're doing this atomically */
-  XGrabServer (xdisplay);
+  xcb_grab_server (xconnection);
 
   if (!x11_get_address (&current_address, NULL, NULL))
     {
@@ -363,27 +422,38 @@ set_address_in_x11(char *address, pid_t pid)
     }
 
   /* Create our window */
-  wid = XCreateWindow (xdisplay, RootWindow (xdisplay, 0), -20, -20, 10, 10,
-                       0, CopyFromParent, InputOnly, CopyFromParent,
-                       0, NULL);
+  wid = xcb_generate_id (xconnection);
+  s = xcb_aux_get_screen (xconnection, 0);
+
+  xcb_create_window (xconnection,
+                     XCB_COPY_FROM_PARENT,
+                     wid,
+                     s->root,
+                     -20, -20, 10, 10,
+                     0, XCB_COPY_FROM_PARENT,
+                     XCB_COPY_FROM_PARENT,
+                     0, NULL);
+
   verbose ("Created window %d\n", wid);
 
   /* Save the property in the window */
-  XChangeProperty (xdisplay, wid, address_atom, XA_STRING, 8, PropModeReplace,
-                   (unsigned char *)address, strlen (address));
+  xcb_change_property (xconnection, XCB_PROP_MODE_REPLACE,
+                       wid, address_atom, XCB_ATOM_STRING, 8,
+                       strlen (address), address);
   pid32 = pid;
-  XChangeProperty (xdisplay, wid, pid_atom, XA_CARDINAL, 32, PropModeReplace,
-                   (unsigned char *)&pid32, 1);
+  xcb_change_property (xconnection, XCB_PROP_MODE_REPLACE,
+                       wid, pid_atom, XCB_ATOM_CARDINAL, 32,
+                       1, &pid32);
 
   /* Now grab the selection */
-  XSetSelectionOwner (xdisplay, selection_atom, wid, CurrentTime);
+  xcb_set_selection_owner (xconnection, wid, selection_atom, XCB_CURRENT_TIME);
 
  out:
   /* Ungrab the server to let other people use it too */
-  XUngrabServer (xdisplay);
+  xcb_ungrab_server (xconnection);
 
   /* And make sure that the ungrab gets sent to X11 */
-  XFlush (xdisplay);
+  xcb_flush (xconnection);
 
   return wid;
 }
@@ -393,7 +463,7 @@ set_address_in_x11(char *address, pid_t pid)
  * success, FALSE if an error occurs.
  */
 static int
-set_address_in_file (char *address, pid_t pid, Window wid)
+set_address_in_file (char *address, pid_t pid, xcb_window_t wid)
 {
   char *session_file;
   FILE *f;
@@ -428,8 +498,8 @@ set_address_in_file (char *address, pid_t pid, Window wid)
 int
 x11_save_address (char *address, pid_t pid, long *wid)
 {
-  Window id = set_address_in_x11 (address, pid);
-  if (id != None)
+  xcb_window_t id = set_address_in_x11 (address, pid);
+  if (id != XCB_NONE)
     {
       if (!set_address_in_file (address, pid, id))
         return FALSE;
@@ -444,19 +514,19 @@ x11_save_address (char *address, pid_t pid, long *wid)
 int
 x11_init (void)
 {
-  return open_x11 () != NULL && init_x_atoms (xdisplay);
+  return open_x11 () != NULL && init_x_atoms (xconnection);
 }
 
 void
 x11_handle_event (void)
 {
-  if (xdisplay != NULL)
-    {      
-      while (XPending (xdisplay))
-        {
-          XEvent ignored;
-          XNextEvent (xdisplay, &ignored);
-        }
+  if (xconnection != NULL)
+    {
+      xcb_generic_event_t *ignored;
+      while ((ignored = xcb_poll_for_event (xconnection)))
+        free (ignored);
+      if (xcb_connection_has_error (xconnection))
+        x_io_error_handler();
     }
 }  
 
diff --git a/tools/dbus-launch.c b/tools/dbus-launch.c
index ec4c9a5..f6760c6 100644
--- a/tools/dbus-launch.c
+++ b/tools/dbus-launch.c
@@ -39,8 +39,8 @@
 #include <time.h>
 
 #ifdef DBUS_BUILD_X11
-#include <X11/Xlib.h>
-extern Display *xdisplay;
+#include <xcb/xcb.h>
+extern xcb_connection_t *xconnection;
 #endif
 
 static char* machine_uuid = NULL;
@@ -436,9 +436,9 @@ kill_bus_when_session_ends (void)
   
 #ifdef DBUS_BUILD_X11
   x11_init();
-  if (xdisplay != NULL)
+  if (xconnection != NULL)
     {
-      x_fd = ConnectionNumber (xdisplay);
+      x_fd = xcb_get_file_descriptor (xconnection);
     }
   else
     x_fd = -1;
@@ -981,7 +981,7 @@ main (int argc, char **argv)
       char write_address_fd_as_string[MAX_FD_LEN];
 
 #ifdef DBUS_BUILD_X11
-      xdisplay = NULL;
+      xconnection = NULL;
 #endif
 
       if (close_stderr)
@@ -1171,7 +1171,7 @@ main (int argc, char **argv)
       close (bus_pid_to_launcher_pipe[READ_END]);
 
 #ifdef DBUS_BUILD_X11
-      if (xdisplay != NULL)
+      if (xconnection != NULL)
         {
           verbose("Saving x11 address\n");
           ret2 = x11_save_address (bus_address, bus_pid, &wid);
-- 
1.7.1



More information about the dbus mailing list