summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Danjou <julien@danjou.info>2009-01-28 16:13:42 +0100
committerJulien Danjou <julien@danjou.info>2009-04-03 12:58:59 +0200
commit15c0bae76e0bcd5d2839a791cf51c8b22e615fe2 (patch)
tree1d0d8843cc2c5501d7804fe9f9ada53ecf455c79
parent3dfbceccffe5c7d44f4acc9cde4ed4e8e2e2ce36 (diff)
downloadstartup-notification-15c0bae76e0bcd5d2839a791cf51c8b22e615fe2.tar.gz
Add XCB backend
Signed-off-by: Julien Danjou <julien@danjou.info>
-rw-r--r--AUTHORS3
-rw-r--r--ChangeLog4
-rw-r--r--configure.in18
-rw-r--r--libsn/sn-common.c264
-rw-r--r--libsn/sn-common.h31
-rw-r--r--libsn/sn-internals.h18
-rw-r--r--libsn/sn-xmessages.c244
-rw-r--r--libsn/sn-xutils.c53
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@redhat.com> \ No newline at end of file
+Havoc Pennington <hp@redhat.com>
+Julien Danjou <julien@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@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@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@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);
}