[PATCH] Add support for libxcb

Julien Danjou julien at danjou.info
Wed Jul 28 02:23:34 PDT 2010


Signed-off-by: Julien Danjou <julien at danjou.info>
---
 configure.in            |   33 ++++--
 tools/dbus-launch-x11.c |  252 +++++++++++++++++++++++++++++++++++++++++------
 tools/dbus-launch.c     |    9 ++
 3 files changed, 251 insertions(+), 43 deletions(-)

diff --git a/configure.in b/configure.in
index 648b115..1e448df 100644
--- a/configure.in
+++ b/configure.in
@@ -124,6 +124,8 @@ 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(xcb, AS_HELP_STRING([--enable-xcb],[build with X11 XCB support]),enable_xcb=$enableval,enable_xcb=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 +1015,28 @@ 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
+if test x$enable_x11 = xyes || test x$enable_x11 = xauto ; then
    AC_DEFINE(DBUS_BUILD_X11,1,[Build X11-dependent code])
+   enable_x11=yes
    DBUS_X_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
    DBUS_X_CFLAGS="$X_CFLAGS"
+
+   if test x$enable_xcb != xno; 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 && x$enable_xcb = xyes; then
+         AC_MSG_ERROR([Explicitly requested XCB but libxcb not found])
+      fi
+      if ! $have_xcb_aux && x$enable_xcb = xyes; then
+         AC_MSG_ERROR([Explicitly requested XCB but libxcb-aux not found])
+      fi
+      if $have_xcb && $have_xcb_aux; then
+         enable_xcb=yes
+         AC_DEFINE(HAVE_LIBXCB,1,[Have libxcb])
+         DBUS_X_LIBS="$XCB_LIBS $XCB_AUX_LIBS"
+         DBUS_X_CFLAGS="$XCB_CLFAGS $XCB_AUX_CFLAGS"
+      fi
+   fi
 else
    DBUS_X_LIBS=
    DBUS_X_CFLAGS=
@@ -1630,6 +1640,7 @@ echo "
         Building dnotify support: ${have_dnotify}
         Building kqueue support:  ${have_kqueue}
         Building X11 code:        ${enable_x11}
+        Building X11 XCB code:    ${enable_xcb}
         Building Doxygen docs:    ${enable_doxygen_docs}
         Building XML docs:        ${enable_xml_docs}
         Building cache support:   ${enable_userdb_cache}
diff --git a/tools/dbus-launch-x11.c b/tools/dbus-launch-x11.c
index fe49222..3d4f82c 100644
--- a/tools/dbus-launch-x11.c
+++ b/tools/dbus-launch-x11.c
@@ -34,6 +34,20 @@
 #include <stdio.h>
 #include <string.h>
 #include <pwd.h>
+
+#ifdef HAVE_LIBXCB
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+
+xcb_connection_t *xdisplay = NULL;
+static xcb_atom_t selection_atom;
+static xcb_atom_t address_atom;
+static xcb_atom_t pid_atom;
+typedef xcb_connection_t _dbus_x11_connection_t;
+typedef xcb_atom_t _dbus_x11_atom_t;
+typedef xcb_window_t _dbus_x11_window_t;
+#define _DBUS_NONE XCB_NONE
+#else
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
 
@@ -41,9 +55,14 @@ Display *xdisplay = NULL;
 static Atom selection_atom;
 static Atom address_atom;
 static Atom pid_atom;
+typedef Display _dbus_x11_connection_t;
+typedef Atom _dbus_x11_atom_t;
+typedef Window _dbus_x11_window_t;
+#define _DBUS_NONE None
+#endif
 
 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 +230,34 @@ ensure_session_directory (void)
   free (dir);
 }
 
-static Display *
+static _dbus_x11_connection_t *
 open_x11 (void)
 {
+#ifdef HAVE_LIBXCB
+  int screen;
+#endif
+
   if (xdisplay != NULL)
-    return xdisplay;
+    return xdisplay;;
 
-  xdisplay = XOpenDisplay (NULL);
+#ifdef HAVE_LIBXCB
+  xdisplay = xcb_connect (NULL, &screen);
+#else
+  xdisplay = XOpenDisplay(NULL);
+#endif
   if (xdisplay != NULL)
-    {
-      verbose ("Connected to X11 display '%s'\n", DisplayString (xdisplay));
-      XSetIOErrorHandler (x_io_error_handler);
-    }
+      verbose ("Connected to X11 display '%s'\n",
+#ifdef HAVE_LIBXCB
+               getenv("DISPLAY"));
+#else
+               DisplayString (xdisplay));
+#endif
+
   return xdisplay;
 }
 
 static int
-init_x_atoms (Display *display)
+init_x_atoms (_dbus_x11_connection_t *display)
 {
   static const char selection_prefix[] = "_DBUS_SESSION_BUS_SELECTION_";
   static const char address_prefix[] = "_DBUS_SESSION_BUS_ADDRESS";
@@ -237,6 +267,10 @@ init_x_atoms (Display *display)
   const char *machine;
   char *user_name;
   struct passwd *user;
+#ifdef HAVE_LIBXCB
+  xcb_intern_atom_cookie_t selection_atom_c, address_atom_c, pid_atom_c;
+  xcb_intern_atom_reply_t *atom_reply;
+#endif
 
   if (init)
     return TRUE;
@@ -269,15 +303,50 @@ init_x_atoms (Display *display)
   strcat (atom_name, user_name);
   strcat (atom_name, "_");
   strcat (atom_name, machine);
+#ifdef HAVE_LIBXCB
+  selection_atom_c = xcb_intern_atom (display, 0, strlen(atom_name), atom_name);
+#else
   selection_atom = XInternAtom (display, atom_name, FALSE);
+#endif
 
   /* create the address property atom */
   strcpy (atom_name, address_prefix);
+#ifdef HAVE_LIBXCB
+  address_atom_c = xcb_intern_atom (display, 0, strlen(atom_name), atom_name);
+#else
   address_atom = XInternAtom (display, atom_name, FALSE);
+#endif
 
   /* create the PID property atom */
   strcpy (atom_name, pid_prefix);
+#ifdef HAVE_LIBXCB
+  pid_atom_c = xcb_intern_atom (display, 0, strlen(atom_name), atom_name);
+#else
   pid_atom = XInternAtom (display, atom_name, FALSE);
+#endif
+
+#ifdef HAVE_LIBXCB
+  atom_reply = xcb_intern_atom_reply (xdisplay, selection_atom_c, NULL);
+  if (atom_reply)
+    {
+      selection_atom = atom_reply->atom;
+      free (atom_reply);
+    }
+
+  atom_reply = xcb_intern_atom_reply (xdisplay, address_atom_c, NULL);
+  if (atom_reply)
+    {
+      address_atom = atom_reply->atom;
+      free (atom_reply);
+    }
+
+  atom_reply = xcb_intern_atom_reply (xdisplay, pid_atom_c, NULL);
+  if (atom_reply)
+    {
+      pid_atom = atom_reply->atom;
+      free (atom_reply);
+    }
+#endif
 
   free (atom_name);
   free (user_name);
@@ -293,42 +362,108 @@ init_x_atoms (Display *display)
 int
 x11_get_address (char **paddress, pid_t *pid, long *wid)
 {
-  Atom type;
-  Window owner;
+  _dbus_x11_atom_t type;
+  _dbus_x11_window_t owner;
   int format;
   unsigned long items;
   unsigned long after;
   char *data;
-
-  *paddress = NULL;
+#ifdef HAVE_LIBXCB
+  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;
+#endif
 
   /* locate the selection owner */
+#ifdef HAVE_LIBXCB
+  owner_c = xcb_get_selection_owner (xdisplay, selection_atom);
+#else
   owner = XGetSelectionOwner (xdisplay, selection_atom);
-  if (owner == None)
+#endif
+
+  *paddress = NULL;
+
+#ifdef HAVE_LIBXCB
+  owner_r = xcb_get_selection_owner_reply (xdisplay, owner_c, NULL);
+
+  if(owner_r == NULL)
+    return TRUE;
+
+  owner = owner_r->owner;
+  free(owner_r);
+#endif
+
+  if (owner == _DBUS_NONE)
     return TRUE;                /* no owner */
-  if (wid != NULL)
-    *wid = (long) owner;
 
   /* get the bus address */
+#ifdef HAVE_LIBXCB
+  prop_c = xcb_get_property (xdisplay, 0, owner,
+                             address_atom, XCB_ATOM_STRING,
+                             0, 1024);
+#else
   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 */
+#endif
+
+  if (wid != NULL)
+    *wid = (long) owner;
+
+#ifdef HAVE_LIBXCB
+  prop_r = xcb_get_property_reply (xdisplay, prop_c, NULL);
+
+  if (!prop_r)
+    return FALSE;
+
+  data = xcb_get_property_value (prop_r);
+  type = prop_r->type;
+  after = prop_r->bytes_after;
+  format = prop_r->format;
+#endif
+
+  if (type == _DBUS_NONE || after != 0 || data == NULL || format != 8)
+      return FALSE;               /* error */
 
   *paddress = xstrdup (data);
+#ifdef HAVE_LIBXCB
+  free (prop_r);
+#else
   XFree (data);
+#endif
 
   /* get the PID */
   if (pid != NULL)
     {
-      *pid = 0;
+#ifdef HAVE_LIBXCB
+      prop_c = xcb_get_property (xdisplay, 0, owner,
+                                 pid_atom, XCB_ATOM_CARDINAL,
+                                 0, sizeof pid);
+#else
       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)
+#endif
+      *pid = 0;
+#ifdef HAVE_LIBXCB
+      prop_r = xcb_get_property_reply (xdisplay, prop_c, NULL);
+      if (prop_r)
+        {
+          type = prop_r->type;
+          after = prop_r->bytes_after;
+          format = prop_r->format;
+          data = xcb_get_property_value (prop_r);
+        }
+
+#endif
+      if (type != _DBUS_NONE && after == 0 && data != NULL && format == 32)
         *pid = (pid_t) *(long*) data;
+#ifdef HAVE_LIBXCB
+      free (prop_r);
+#else
       XFree (data);
+#endif
     }
 
   return TRUE;                  /* success */
@@ -339,15 +474,24 @@ 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 _dbus_x11_window_t
 set_address_in_x11(char *address, pid_t pid)
 {
   char *current_address;
-  Window wid = None;
+  _dbus_x11_window_t wid = _DBUS_NONE;
+#ifdef HAVE_LIBXCB
+  uint32_t pid32;
+#else
   unsigned long pid32; /* Xlib property functions want _long_ not 32-bit for format "32" */
-  
+#endif
+
   /* lock the X11 display to make sure we're doing this atomically */
+#ifdef HAVE_LIBXCB
+  xcb_screen_t *s;
+  xcb_grab_server (xdisplay);
+#else
   XGrabServer (xdisplay);
+#endif
 
   if (!x11_get_address (&current_address, NULL, NULL))
     {
@@ -363,27 +507,63 @@ set_address_in_x11(char *address, pid_t pid)
     }
 
   /* Create our window */
+#ifdef HAVE_LIBXCB
+  wid = xcb_generate_id (xdisplay);
+
+  s = xcb_aux_get_screen (xdisplay, 0);
+
+  xcb_create_window (xdisplay,
+                     XCB_COPY_FROM_PARENT,
+                     wid,
+                     s->root,
+                     -20, -20, 10, 10,
+                     0, XCB_COPY_FROM_PARENT,
+                     XCB_COPY_FROM_PARENT,
+                     0, NULL);
+#else
   wid = XCreateWindow (xdisplay, RootWindow (xdisplay, 0), -20, -20, 10, 10,
                        0, CopyFromParent, InputOnly, CopyFromParent,
                        0, NULL);
+#endif
+
   verbose ("Created window %d\n", wid);
 
   /* Save the property in the window */
+#ifdef HAVE_LIBXCB
+  xcb_change_property (xdisplay, XCB_PROP_MODE_REPLACE,
+                       wid, address_atom, XCB_ATOM_STRING, 8,
+                       strlen (address), address);
+#else
   XChangeProperty (xdisplay, wid, address_atom, XA_STRING, 8, PropModeReplace,
-                   (unsigned char *)address, strlen (address));
+                   (unsigned char *) address, strlen (address));
+#endif
   pid32 = pid;
-  XChangeProperty (xdisplay, wid, pid_atom, XA_CARDINAL, 32, PropModeReplace,
-                   (unsigned char *)&pid32, 1);
+#ifdef HAVE_LIBXCB
+  xcb_change_property (xdisplay, XCB_PROP_MODE_REPLACE,
+                       wid, pid_atom, XCB_ATOM_CARDINAL, 32,
+                       1, &pid32);
+#else
+  XChangeProperty (xdisplay, wid, pid_atom, XA_STRING, 32, PropModeReplace,
+                   (unsigned char *) &pid32, 1);;
+#endif
 
   /* Now grab the selection */
+#ifdef HAVE_LIBXCB
+  xcb_set_selection_owner (xdisplay, wid, selection_atom, XCB_CURRENT_TIME);
+#else
   XSetSelectionOwner (xdisplay, selection_atom, wid, CurrentTime);
+#endif
 
  out:
   /* Ungrab the server to let other people use it too */
-  XUngrabServer (xdisplay);
-
   /* And make sure that the ungrab gets sent to X11 */
+#ifdef HAVE_LIBXCB
+  xcb_ungrab_server (xdisplay);
+  xcb_flush (xdisplay);
+#else
+  XUngrabServer (xdisplay);
   XFlush (xdisplay);
+#endif
 
   return wid;
 }
@@ -393,7 +573,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, _dbus_x11_window_t wid)
 {
   char *session_file;
   FILE *f;
@@ -428,8 +608,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)
+  _dbus_x11_window_t id = set_address_in_x11 (address, pid);
+  if (id != _DBUS_NONE)
     {
       if (!set_address_in_file (address, pid, id))
         return FALSE;
@@ -451,12 +631,20 @@ void
 x11_handle_event (void)
 {
   if (xdisplay != NULL)
-    {      
+    {
+#ifdef HAVE_LIBXCB
+      xcb_generic_event_t *ignored;
+      while ((ignored = xcb_poll_for_event (xdisplay)))
+        free (ignored);
+      if (xcb_connection_has_error (xdisplay))
+        x_io_error_handler();
+#else
       while (XPending (xdisplay))
         {
           XEvent ignored;
           XNextEvent (xdisplay, &ignored);
         }
+#endif
     }
 }  
 
diff --git a/tools/dbus-launch.c b/tools/dbus-launch.c
index ec4c9a5..72e17ea 100644
--- a/tools/dbus-launch.c
+++ b/tools/dbus-launch.c
@@ -39,9 +39,14 @@
 #include <time.h>
 
 #ifdef DBUS_BUILD_X11
+#ifdef HAVE_LIBXCB
+#include <xcb/xcb.h>
+extern xcb_connection_t *xdisplay;
+#else
 #include <X11/Xlib.h>
 extern Display *xdisplay;
 #endif
+#endif
 
 static char* machine_uuid = NULL;
 
@@ -438,7 +443,11 @@ kill_bus_when_session_ends (void)
   x11_init();
   if (xdisplay != NULL)
     {
+#ifdef HAVE_LIBXCB
+      x_fd = xcb_get_file_descriptor (xdisplay);
+#else
       x_fd = ConnectionNumber (xdisplay);
+#endif
     }
   else
     x_fd = -1;
-- 
1.7.1



More information about the dbus mailing list