[PATCH] Add XCB backend

Julien Danjou julien at danjou.info
Thu Jan 29 06:37:46 PST 2009


Signed-off-by: Julien Danjou <julien at danjou.info>
---
 AUTHORS              |    3 +-
 ChangeLog            |    4 +
 configure.in         |   18 +++-
 libsn/sn-common.c    |  264 +++++++++++++++++++++++++++++++++++++++++++++-----
 libsn/sn-common.h    |   31 ++++++
 libsn/sn-internals.h |   18 ++++
 libsn/sn-xmessages.c |  244 +++++++++++++++++++++++++++++++++-------------
 libsn/sn-xutils.c    |   53 +++++++++--
 8 files changed, 532 insertions(+), 103 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index 3bc119c..7caa678 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1 +1,2 @@
-Havoc Pennington <hp at redhat.com>
\ No newline at end of file
+Havoc Pennington <hp at redhat.com>
+Julien Danjou    <julien at danjou.info>
diff --git a/ChangeLog b/ChangeLog
index fc906b3..33d9aa5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2009-01-28  Julien Danjou  <julien at danjou.info>
+
+	* add xcb support
+
 2007-03-17  Elijah Newren  <newren gmail com>
 
 	* configure.in: post-release bump to 0.10.
diff --git a/configure.in b/configure.in
index 7ce5ce8..dad1c2f 100644
--- a/configure.in
+++ b/configure.in
@@ -78,8 +78,22 @@ fi
 ## try definining HAVE_BACKTRACE
 AC_CHECK_HEADERS(execinfo.h, [AC_CHECK_FUNCS(backtrace)])
 
-LIBSN_CFLAGS=$X_CFLAGS
-LIBSN_LIBS=" $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
+AC_ARG_WITH([xcb], AS_HELP_STRING([--with-xcb], [build with XCB library]))
+
+if test "x$with_xcb" = "xyes"; then
+    PKG_CHECK_MODULES([xcb], [xcb],,
+        [AC_MSG_ERROR([Cannot find xcb])])
+    PKG_CHECK_MODULES([xcb_aux], [xcb-aux],,
+        [AC_MSG_ERROR([Cannot find xcb-aux])])
+    PKG_CHECK_MODULES([xcb_event], [xcb-event],,
+        [AC_MSG_ERROR([Cannot find xcb-event])])
+    PKG_CHECK_MODULES([xcb_atom], [xcb-atom],,
+        [AC_MSG_ERROR([Cannot find xcb-atom])])
+    AC_DEFINE([HAVE_XCB],1,[Defined to use xcb])
+fi
+
+LIBSN_CFLAGS="$X_CFLAGS $xcb_CFLAGS $xcb_aux_CFLAGS $xcb_event_CFLAGS $xcb_atom_CFLAGS"
+LIBSN_LIBS=" $xcb_LIBS $xcb_aux_LIBS $xcb_event_LIBS $xcb_atom_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
 AC_SUBST(LIBSN_CFLAGS)
 AC_SUBST(LIBSN_LIBS)
 
diff --git a/libsn/sn-common.c b/libsn/sn-common.c
index d5c52c0..66ca2b6 100644
--- a/libsn/sn-common.c
+++ b/libsn/sn-common.c
@@ -1,5 +1,6 @@
 /* 
  * Copyright (C) 2002 Red Hat, Inc.
+ * Copyright (C) 2009 Julien Danjou <julien at danjou.info>
  * 
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -26,14 +27,35 @@
 #include "sn-common.h"
 #include "sn-internals.h"
 
+#ifdef HAVE_XCB
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+#endif
+
 struct SnDisplay
 {
   int refcount;
-  Display *xdisplay;
+  enum SnDisplayType type;
+  union
+  {
+      struct
+      {
+          Display *xdisplay;
+          Screen **screens;
+          SnDisplayErrorTrapPush push_trap_func;
+          SnDisplayErrorTrapPop  pop_trap_func;
+      } xlib;
+#ifdef HAVE_XCB
+      struct
+      {
+          xcb_connection_t *xconnection;
+          xcb_screen_t **screens;
+          SnXcbDisplayErrorTrapPush push_trap_func;
+          SnXcbDisplayErrorTrapPop  pop_trap_func;
+      } xcb;
+#endif
+  } x;
   int n_screens;
-  Screen **screens;
-  SnDisplayErrorTrapPush push_trap_func;
-  SnDisplayErrorTrapPop  pop_trap_func;
   SnList *xmessage_funcs;
   SnList *pending_messages;
 };
@@ -67,19 +89,66 @@ sn_display_new (Display                *xdisplay,
   
   display = sn_new0 (SnDisplay, 1);
 
-  display->xdisplay = xdisplay;
+  display->type = SN_DISPLAY_TYPE_XLIB;
+  display->x.xlib.xdisplay = xdisplay;
   display->n_screens = ScreenCount (xdisplay);
-  display->screens = sn_new (Screen*, display->n_screens);
+  display->x.xlib.screens = sn_new (Screen*, display->n_screens);
+  display->refcount = 1;
+
+  display->x.xlib.push_trap_func = push_trap_func;
+  display->x.xlib.pop_trap_func = pop_trap_func;
+
+  for (i = 0; i < display->n_screens; ++i)
+    display->x.xlib.screens[i] = ScreenOfDisplay (display->x.xlib.xdisplay, i);
+
+  return display;
+}
+
+#ifdef HAVE_XCB
+/**
+ * sn_xcb_display_new:
+ * @xdisplay: an X window system display
+ * @push_trap_func: function to push an X error trap
+ * @pop_trap_func: function to pop an X error trap
+ *
+ * Creates a new #SnDisplay object, containing
+ * data that libsn associates with an X display.
+ *
+ * @push_trap_func should be a function that causes X errors to be
+ * ignored until @pop_trap_func is called as many times as
+ * @push_trap_func has been called. (Nested push/pop pairs must be
+ * supported.) The outermost @pop_trap_func in a set of nested pairs
+ * must call XSync() to ensure that all errors that will occur have in
+ * fact occurred. These functions are used to avoid X errors due to
+ * BadWindow and such.
+ *
+ * Return value: the new #SnDisplay
+ **/
+SnDisplay*
+sn_xcb_display_new (xcb_connection_t          *xconnection,
+                    SnXcbDisplayErrorTrapPush  push_trap_func,
+                    SnXcbDisplayErrorTrapPop   pop_trap_func)
+{
+  SnDisplay *display;
+  int i;
+
+  display = sn_new0 (SnDisplay, 1);
+
+  display->type = SN_DISPLAY_TYPE_XCB;
+  display->x.xcb.xconnection = xconnection;
+  display->n_screens = xcb_setup_roots_length (xcb_get_setup (xconnection));
+  display->x.xcb.screens = sn_new (xcb_screen_t*, display->n_screens);
   display->refcount = 1;
 
-  display->push_trap_func = push_trap_func;
-  display->pop_trap_func = pop_trap_func;
+  display->x.xcb.push_trap_func = push_trap_func;
+  display->x.xcb.pop_trap_func = pop_trap_func;
   
   for (i = 0; i < display->n_screens; ++i)
-    display->screens[i] = ScreenOfDisplay (display->xdisplay, i);
+    display->x.xcb.screens[i] = xcb_aux_get_screen(xconnection, i);
 
   return display;
 }
+#endif
 
 /**
  * sn_display_ref:
@@ -110,7 +179,19 @@ sn_display_unref (SnDisplay *display)
         sn_list_free (display->xmessage_funcs);
       if (display->pending_messages)
         sn_list_free (display->pending_messages);
-      sn_free (display->screens);
+#ifdef HAVE_XCB
+      switch (display->type)
+      {
+       case SN_DISPLAY_TYPE_XCB:
+        sn_free (display->x.xcb.screens);
+        break;
+       case SN_DISPLAY_TYPE_XLIB:
+#endif
+        sn_free (display->x.xlib.screens);
+#ifdef HAVE_XCB
+        break;
+      }
+#endif
       sn_free (display);
     }
 }
@@ -126,9 +207,28 @@ sn_display_unref (SnDisplay *display)
 Display*
 sn_display_get_x_display (SnDisplay *display)
 {
+  if(display->type == SN_DISPLAY_TYPE_XLIB)
+      return display->x.xlib.xdisplay;
+  return NULL;
+}
 
-  return display->xdisplay;
+#ifdef HAVE_XCB
+/**
+ * sn_display_get_x_connection:
+ * @display: an #SnDisplay
+ *
+ *
+ *
+ * Return value: X connection for this #SnDisplay
+ **/
+xcb_connection_t*
+sn_display_get_x_connection(SnDisplay *display)
+{
+  if(display->type == SN_DISPLAY_TYPE_XCB)
+      return display->x.xcb.xconnection;
+  return NULL;
 }
+#endif
 
 /**
  * sn_internal_display_get_id:
@@ -141,27 +241,38 @@ sn_display_get_x_display (SnDisplay *display)
 void *
 sn_internal_display_get_id (SnDisplay *display)
 {
-    return display->xdisplay;
+#ifdef HAVE_XCB
+  switch (display->type)
+  {
+   case SN_DISPLAY_TYPE_XLIB:
+#endif
+    return display->x.xlib.xdisplay;
+#ifdef HAVE_XCB
+   case SN_DISPLAY_TYPE_XCB:
+    return display->x.xcb.xconnection;
+  }
+  return NULL;
+#endif
 }
 
 /**
  * sn_internal_display_get_x_screen:
  * @display: an #SnDisplay
  * @number: screen number to get
- * 
+ *
  * Gets a screen by number; if the screen number
  * does not exist, returns %NULL.
- * 
+ *
  * Return value: X screen or %NULL
  **/
 Screen*
 sn_internal_display_get_x_screen (SnDisplay *display,
                                   int        number)
 {
-  if (number < 0 || number >= display->n_screens)
+  if (display->type != SN_DISPLAY_TYPE_XLIB || number < 0 || number >= display->n_screens)
     return NULL;
   else
-    return display->screens[number];
+    return display->x.xlib.screens[number];
 }
 
 /**
@@ -178,12 +289,58 @@ Window
 sn_internal_display_get_root_window (SnDisplay *display,
                                      int       number)
 {
-    if (number < 0 || number >= display->n_screens)
-        return None;
-    return RootWindow (display->xdisplay, number);
+    if (number >= 0 && number < display->n_screens)
+#ifdef HAVE_XCB
+      switch (display->type)
+      {
+       case SN_DISPLAY_TYPE_XLIB:
+#endif
+        return RootWindow (display->x.xlib.xdisplay, number);
+#ifdef HAVE_XCB
+       case SN_DISPLAY_TYPE_XCB:
+        return display->x.xcb.screens[number]->root;
+      }
+#endif
+    return None;
 }
 
 /**
+ * sn_internal_display_get_type
+ * @display: an #SnDisplay
+ *
+ *
+ *
+ * Return value: X connection type
+ */
+enum SnDisplayType
+sn_internal_display_get_type (SnDisplay *display)
+{
+    return display->type;
+}
+
+#ifdef HAVE_XCB
+/**
+ * sn_internal_display_get_x_screen:
+ * @display: an #SnDisplay
+ * @number: screen number to get
+ * 
+ * Gets a screen by number; if the screen number
+ * does not exist, returns %NULL.
+ * 
+ * Return value: X screen or %NULL
+ **/
+xcb_screen_t*
+sn_internal_display_get_xcb_screen (SnDisplay *display,
+                                    int        number)
+{
+  if (display->type != SN_DISPLAY_TYPE_XCB || number < 0 || number >= display->n_screens)
+    return NULL;
+  else
+    return display->x.xcb.screens[number];
+}
+#endif
+
+/**
  * sn_internal_display_get_screen_number:
  * @display an #SnDisplay
  *
@@ -230,6 +387,41 @@ sn_display_process_event (SnDisplay *display,
   return retval;
 }
 
+#ifdef HAVE_XCB
+/**
+ * sn_xcb_display_process_event:
+ * @display: a display
+ * @xevent: X event
+ *
+ * libsn should be given a chance to see all X events by passing them
+ * to this function. If the event was a property notify or client
+ * message related to the launch feedback protocol, the
+ * sn_display_process_event() returns true. Calling
+ * sn_display_process_event() is not currently required for launchees,
+ * only launchers and launch feedback displayers. The function returns
+ * false for mapping, unmapping, window destruction, and selection
+ * events even if they were involved in launch feedback.
+ *
+ * Return value: true if the event was a property notify or client message involved in launch feedback
+ **/
+sn_bool_t
+sn_xcb_display_process_event (SnDisplay           *display,
+                              xcb_generic_event_t *xevent)
+{
+  sn_bool_t retval;
+
+  retval = FALSE;
+
+  if (sn_internal_monitor_process_event (display))
+    retval = TRUE;
+
+  if (sn_xcb_internal_xmessage_process_event (display, xevent))
+    retval = TRUE;
+
+  return retval;
+}
+#endif
+
 /**
  * sn_display_error_trap_push:
  * @display: a display
@@ -239,8 +431,21 @@ sn_display_process_event (SnDisplay *display,
 void
 sn_display_error_trap_push (SnDisplay *display)
 {
-  if (display->push_trap_func)
-    (* display->push_trap_func) (display, display->xdisplay);
+#ifdef HAVE_XCB
+  switch (display->type)
+  {
+   case SN_DISPLAY_TYPE_XCB:
+    if (display->x.xcb.push_trap_func)
+      (* display->x.xcb.push_trap_func) (display, display->x.xcb.xconnection);
+    break;
+   case SN_DISPLAY_TYPE_XLIB:
+#endif
+    if (display->x.xlib.push_trap_func)
+      (* display->x.xlib.push_trap_func) (display, display->x.xlib.xdisplay);
+#ifdef HAVE_XCB
+    break;
+  }
+#endif
 }
 
 /**
@@ -252,8 +457,21 @@ sn_display_error_trap_push (SnDisplay *display)
 void
 sn_display_error_trap_pop  (SnDisplay *display)
 {
-  if (display->pop_trap_func)
-    (* display->pop_trap_func) (display, display->xdisplay);
+#ifdef HAVE_XCB
+  switch (display->type)
+  {
+   case SN_DISPLAY_TYPE_XCB:
+    if (display->x.xcb.pop_trap_func)
+      (* display->x.xcb.pop_trap_func) (display, display->x.xcb.xconnection);
+    break;
+   case SN_DISPLAY_TYPE_XLIB:
+#endif
+    if (display->x.xlib.pop_trap_func)
+      (* display->x.xlib.pop_trap_func) (display, display->x.xlib.xdisplay);
+#ifdef HAVE_XCB
+    break;
+  }
+#endif
 }
 
 void
diff --git a/libsn/sn-common.h b/libsn/sn-common.h
index 79366ca..8fa34e8 100644
--- a/libsn/sn-common.h
+++ b/libsn/sn-common.h
@@ -29,6 +29,14 @@
 #include <libsn/sn-util.h>
 #include <X11/Xlib.h>
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_XCB
+#include <xcb/xcb.h>
+#endif
+
 SN_BEGIN_DECLS
 
 #ifndef SN_API_NOT_YET_FROZEN
@@ -42,14 +50,37 @@ typedef void (* SnDisplayErrorTrapPush) (SnDisplay *display,
 typedef void (* SnDisplayErrorTrapPop)  (SnDisplay *display,
                                          Display   *xdisplay);
 
+#ifdef HAVE_XCB
+typedef void (* SnXcbDisplayErrorTrapPush) (SnDisplay        *display,
+                                            xcb_connection_t *xconnection);
+typedef void (* SnXcbDisplayErrorTrapPop)  (SnDisplay        *display,
+                                            xcb_connection_t *xconnection);
+#endif
+
 SnDisplay* sn_display_new             (Display                *xdisplay,
                                        SnDisplayErrorTrapPush  push_trap_func,
                                        SnDisplayErrorTrapPop   pop_trap_func);
+
+#ifdef HAVE_XCB
+SnDisplay* sn_xcb_display_new         (xcb_connection_t          *xconnection,
+                                       SnXcbDisplayErrorTrapPush  push_trap_func,
+                                       SnXcbDisplayErrorTrapPop   pop_trap_func);
+#endif
+
 void       sn_display_ref             (SnDisplay              *display);
 void       sn_display_unref           (SnDisplay              *display);
 Display*   sn_display_get_x_display   (SnDisplay              *display);
+#ifdef HAVE_XCB
+xcb_connection_t* sn_display_get_x_connection (SnDisplay       *display);
+#endif
+
 sn_bool_t  sn_display_process_event   (SnDisplay              *display,
                                        XEvent                 *xevent);
+#ifdef HAVE_XCB
+sn_bool_t  sn_xcb_display_process_event (SnDisplay              *display,
+                                         xcb_generic_event_t    *xevent);
+#endif
+
 void       sn_display_error_trap_push (SnDisplay              *display);
 void       sn_display_error_trap_pop  (SnDisplay              *display);
 
diff --git a/libsn/sn-internals.h b/libsn/sn-internals.h
index 43ea186..1024d0b 100644
--- a/libsn/sn-internals.h
+++ b/libsn/sn-internals.h
@@ -49,6 +49,12 @@ SN_BEGIN_DECLS
 #define NULL ((void*) 0)
 #endif
 
+enum SnDisplayType
+{
+    SN_DISPLAY_TYPE_XLIB,
+    SN_DISPLAY_TYPE_XCB
+};
+
 /* --- From sn-common.c --- */
 Screen*    sn_internal_display_get_x_screen    (SnDisplay              *display,
                                                 int                     number);
@@ -59,6 +65,13 @@ int        sn_internal_display_get_screen_number (SnDisplay *display);
 
 void*      sn_internal_display_get_id (SnDisplay *display);
 
+#ifdef HAVE_XCB
+xcb_screen_t* sn_internal_display_get_xcb_screen (SnDisplay              *display,
+                                                  int                     number);
+#endif
+
+enum SnDisplayType sn_internal_display_get_type (SnDisplay *display);
+
 void       sn_internal_display_get_xmessage_data (SnDisplay              *display,
                                                   SnList                **funcs,
                                                   SnList                **pending);
@@ -87,6 +100,11 @@ void sn_internal_append_to_string (char      **append_to,
 sn_bool_t sn_internal_xmessage_process_event (SnDisplay *display,
                                               XEvent    *xevent);
 
+#ifdef HAVE_XCB
+sn_bool_t sn_xcb_internal_xmessage_process_event (SnDisplay          *display,
+                                                  xcb_generic_event_t *xevent);
+#endif
+
 SN_END_DECLS
 
 #endif /* __SN_INTERNALS_H__ */
diff --git a/libsn/sn-xmessages.c b/libsn/sn-xmessages.c
index ed1df71..1e1653b 100644
--- a/libsn/sn-xmessages.c
+++ b/libsn/sn-xmessages.c
@@ -1,5 +1,6 @@
 /* 
  * Copyright (C) 2002 Red Hat, Inc.
+ * Copyright (C) 2009 Julien Danjou <julien at danjou.info>
  * 
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -22,6 +23,12 @@
  * SOFTWARE.
  */
 
+#include <config.h>
+
+#ifdef HAVE_XCB
+#include <xcb/xcb_event.h>
+#endif
+
 #include "sn-xmessages.h"
 #include "sn-list.h"
 #include "sn-internals.h"
@@ -145,11 +152,6 @@ sn_internal_broadcast_xmessage   (SnDisplay      *display,
                                   const char     *message_type_begin,
                                   const char     *message)
 {
-  Atom type_atom;
-  Atom type_atom_begin;
-  Window xwindow;
-  Display *xdisplay;
-
   if (!sn_internal_utf8_validate (message, -1))
     {
       fprintf (stderr,
@@ -158,70 +160,137 @@ sn_internal_broadcast_xmessage   (SnDisplay      *display,
       return;
     }
 
-  xdisplay = sn_display_get_x_display (display);
-
+#ifdef HAVE_XCB
+  switch (sn_internal_display_get_type (display))
   {
-    XSetWindowAttributes attrs;
-
-    attrs.override_redirect = True;
-    attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
-
-    xwindow =
-      XCreateWindow (xdisplay,
-                     RootWindow (xdisplay, 0),
-                     -100, -100, 1, 1,
-                     0,
-                     CopyFromParent,
-                     CopyFromParent,
-                     CopyFromParent,
-                     CWOverrideRedirect | CWEventMask,
-                     &attrs);
-  }
-
-  type_atom = sn_internal_atom_get (display, message_type);
-  type_atom_begin = sn_internal_atom_get (display, message_type_begin);
+   case SN_DISPLAY_TYPE_XLIB:
+#endif
+    {
+      Atom type_atom;
+      Atom type_atom_begin;
+      Window xwindow;
+      XSetWindowAttributes attrs;
+      Display *xdisplay = sn_display_get_x_display (display);
   
-  {
-    XEvent xevent;
-    const char *src;
-    const char *src_end;
-    char *dest;
-    char *dest_end;
-    
-    xevent.xclient.type = ClientMessage;
-    xevent.xclient.message_type = type_atom_begin;
-    xevent.xclient.display = xdisplay;
-    xevent.xclient.window = xwindow;
-    xevent.xclient.format = 8;
-
-    src = message;
-    src_end = message + strlen (message) + 1; /* +1 to include nul byte */
+      attrs.override_redirect = True;
+      attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
+
+      xwindow =
+        XCreateWindow (xdisplay,
+                       RootWindow (xdisplay, 0),
+                       -100, -100, 1, 1,
+                       0,
+                       CopyFromParent,
+                       CopyFromParent,
+                       CopyFromParent,
+                       CWOverrideRedirect | CWEventMask,
+                       &attrs);
+      type_atom = sn_internal_atom_get (display, message_type);
+      type_atom_begin = sn_internal_atom_get (display, message_type_begin);
     
-    while (src != src_end)
       {
-        dest = &xevent.xclient.data.b[0];
-        dest_end = dest + 20;        
+        XEvent xevent;
+        const char *src;
+        const char *src_end;
+        char *dest;
+        char *dest_end;
+
+        xevent.xclient.type = ClientMessage;
+        xevent.xclient.message_type = type_atom_begin;
+        xevent.xclient.display = xdisplay;
+        xevent.xclient.window = xwindow;
+        xevent.xclient.format = 8;
+
+        src = message;
+        src_end = message + strlen (message) + 1; /* +1 to include nul byte */
         
-        while (dest != dest_end &&
-               src != src_end)
+        while (src != src_end)
           {
-            *dest = *src;
-            ++dest;
-            ++src;
+            dest = &xevent.xclient.data.b[0];
+            dest_end = dest + 20;
+
+            while (dest != dest_end &&
+                   src != src_end)
+              {
+                *dest = *src;
+                ++dest;
+                ++src;
+              }
+
+            XSendEvent (xdisplay,
+                        RootWindow (xdisplay, screen),
+                        False,
+                        PropertyChangeMask,
+                        &xevent);
+
+            xevent.xclient.message_type = type_atom;
           }
-        
-        XSendEvent (xdisplay,
-                    RootWindow (xdisplay, screen),
-                    False,
-                    PropertyChangeMask,
-                    &xevent);
+      }
+
+      XDestroyWindow (xdisplay, xwindow);
+      XFlush (xdisplay);
+    }
+#ifdef HAVE_XCB
+    break;
+   case SN_DISPLAY_TYPE_XCB:
+    {
+      xcb_atom_t type_atom;
+      xcb_atom_t type_atom_begin;
+      xcb_window_t xwindow;
+      uint32_t attrs[] = { 1, XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY };
+      xcb_connection_t *xconnection = sn_display_get_x_connection (display);
+      xcb_screen_t *s = sn_internal_display_get_xcb_screen (display, screen);
+
+      xwindow = xcb_generate_id(xconnection);
+      xcb_create_window(xconnection, s->root_depth, xwindow, s->root,
+                        -100, -100, 1, 1, 0, XCB_COPY_FROM_PARENT, s->root_visual,
+                        XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
+                        attrs);
+
+      type_atom = sn_internal_atom_get (display, message_type);
+      type_atom_begin = sn_internal_atom_get (display, message_type_begin);
+
+      {
+        xcb_client_message_event_t xevent;
+        const char *src;
+        const char *src_end;
+        unsigned char *dest;
+        unsigned char *dest_end;
+
+        xevent.response_type = XCB_CLIENT_MESSAGE;
+        xevent.type = type_atom_begin;
+        xevent.window = xwindow;
+        xevent.format = 8;
+
+        src = message;
+        src_end = message + strlen (message) + 1; /* +1 to include nul byte */
+
+        while (src != src_end)
+          {
+            dest = &xevent.data.data8[0];
+            dest_end = dest + 20;
+
+            while (dest != dest_end &&
+                   src != src_end)
+              {
+                *dest = *src;
+                ++dest;
+                ++src;
+              }
 
-        xevent.xclient.message_type = type_atom;
+            xcb_send_event (xconnection, 0, s->root, XCB_EVENT_MASK_PROPERTY_CHANGE,
+                            (char *) &xevent);
+
+            xevent.type = type_atom;
+          }
       }
-  }
 
-  XDestroyWindow (xdisplay, xwindow);
-  XFlush (xdisplay);
+      xcb_destroy_window (xconnection, xwindow);
+      xcb_flush(xconnection);
+    }
+    break;
+  }
+#endif
 }
 
 typedef struct
@@ -252,7 +321,8 @@ handler_for_atom_foreach (void *value,
 
 static sn_bool_t
 some_handler_handles_event (SnDisplay *display,
-                            XEvent    *xevent)
+                            Atom atom,
+                            Window win)
 {
   HandlerForAtomData hfad;
   SnList *xmessage_funcs;
@@ -260,9 +330,9 @@ some_handler_handles_event (SnDisplay *display,
   sn_internal_display_get_xmessage_data (display, &xmessage_funcs,
                                          NULL);
   
-  hfad.atom = xevent->xclient.message_type;
+  hfad.atom = atom;
   hfad.xid = sn_internal_display_get_id (display);
-  hfad.xwindow = xevent->xclient.window;
+  hfad.xwindow = win;
   hfad.found_handler = FALSE;
 
   if (xmessage_funcs)
@@ -367,7 +437,9 @@ get_or_add_message(SnList *pending_messages,
 
 static SnXmessage*
 add_event_to_messages (SnDisplay *display,
-                       XEvent    *xevent)
+                       Window win,
+                       Atom message_type,
+                       const char *data)
 {
   SnXmessage *message;
   SnList *pending_messages;
@@ -376,8 +448,7 @@ add_event_to_messages (SnDisplay *display,
                                          &pending_messages);
 
   message = get_or_add_message(pending_messages,
-                               xevent->xclient.window,
-                               xevent->xclient.message_type);
+                               win, message_type);
 
   /* We don't want screwy situations to end up causing us to allocate
    * infinite memory. Cap the length of a message.
@@ -393,7 +464,7 @@ add_event_to_messages (SnDisplay *display,
       return NULL;
     }
   
-  if (message_set_message (message, &xevent->xclient.data.b[0]))
+  if (message_set_message (message, data))
     {
       /* Pull message out of the pending queue and return it */
       sn_list_remove (pending_messages, message);
@@ -476,11 +547,47 @@ sn_internal_xmessage_process_event (SnDisplay *display,
   switch (xevent->xany.type)
     {
     case ClientMessage:
-      if (some_handler_handles_event (display, xevent))
+      if (some_handler_handles_event (display,
+                                      xevent->xclient.message_type,
+                                      xevent->xclient.window))
+        {
+          retval = TRUE;
+
+          message = add_event_to_messages (display,
+                                           xevent->xclient.window,
+                                           xevent->xclient.message_type,
+                                           xevent->xclient.data.b);
+        }
+      break;
+    }
+
+  xmessage_process_message (display, message);
+
+  return retval;
+}
+
+#ifdef HAVE_XCB
+sn_bool_t
+sn_xcb_internal_xmessage_process_event (SnDisplay           *display,
+                                        xcb_generic_event_t *xevent)
+{
+  sn_bool_t retval = FALSE;
+  SnXmessage *message = NULL;
+  xcb_client_message_event_t *ev = (xcb_client_message_event_t *) xevent;
+
+  switch (XCB_EVENT_RESPONSE_TYPE(xevent))
+    {
+    case XCB_CLIENT_MESSAGE:
+      if (some_handler_handles_event (display,
+                                      ev->type,
+                                      ev->window))
         {
           retval = TRUE;
 
-          message = add_event_to_messages (display, xevent);
+          message = add_event_to_messages (display,
+                                           ev->window,
+                                           ev->type,
+                                           (const char *) ev->data.data8);
         }
       break;
     }
@@ -489,6 +596,7 @@ sn_internal_xmessage_process_event (SnDisplay *display,
 
   return retval;
 }
+#endif
 
 static void
 sn_internal_append_to_string_escaped (char      **append_to,
diff --git a/libsn/sn-xutils.c b/libsn/sn-xutils.c
index b40b305..1fece87 100644
--- a/libsn/sn-xutils.c
+++ b/libsn/sn-xutils.c
@@ -22,17 +22,35 @@
  * SOFTWARE.
  */
 
+#include <config.h>
 #include "sn-internals.h"
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
 
+#ifdef HAVE_XCB
+#include <xcb/xcb.h>
+#include <xcb/xcb_atom.h>
+#endif
+
 Atom
 sn_internal_atom_get (SnDisplay  *display,
                       const char *atom_name)
 {
-  return XInternAtom (sn_display_get_x_display (display),
-                      atom_name,
-                      False);
+#ifdef HAVE_XCB
+    switch (sn_internal_display_get_type (display))
+    {
+     case SN_DISPLAY_TYPE_XLIB:
+#endif
+      return XInternAtom (sn_display_get_x_display (display),
+                          atom_name,
+                          False);
+#ifdef HAVE_XCB
+     case SN_DISPLAY_TYPE_XCB:
+      return xcb_atom_get (sn_display_get_x_connection (display),
+                           atom_name);
+    }
+    return None;
+#endif
 }
 
 void
@@ -43,12 +61,29 @@ sn_internal_set_utf8_string (SnDisplay  *display,
 {
   sn_display_error_trap_push (display);
 
-  XChangeProperty (sn_display_get_x_display (display),
-                   xwindow,
-                   sn_internal_atom_get (display, property),
-                   sn_internal_atom_get (display, "UTF8_STRING"),
-                   8, PropModeReplace, (unsigned char*) str,
-                   strlen (str));
+#ifdef HAVE_XCB
+  switch (sn_internal_display_get_type (display))
+  {
+    case SN_DISPLAY_TYPE_XLIB:
+#endif
+      XChangeProperty (sn_display_get_x_display (display),
+                       xwindow,
+                       sn_internal_atom_get (display, property),
+                       sn_internal_atom_get (display, "UTF8_STRING"),
+                       8, PropModeReplace, (unsigned char*) str,
+                       strlen (str));
+#ifdef HAVE_XCB
+      break;
+     case SN_DISPLAY_TYPE_XCB:
+      xcb_change_property (sn_display_get_x_connection (display),
+                           XCB_PROP_MODE_REPLACE,
+                           xwindow,
+                           sn_internal_atom_get (display, property),
+                           sn_internal_atom_get (display, "UTF8_STRING"),
+                           8, strlen (str), str);
+      break;
+  }
+#endif
 
   sn_display_error_trap_pop (display);
 }
-- 
1.5.6.5



More information about the xdg mailing list