[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 (¤t_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