summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Danjou <julien@danjou.info>2010-01-14 11:48:05 +0100
committerSteve Chaplin <stevech1097@yahoo.com.au>2010-02-06 13:03:06 +0800
commitd98974c0a3de11fde1e5cdfd6dd469624c6c17d6 (patch)
tree38e331379357bd452ef7eb838f7d1c943b3da688
parent9b1c3a86f13d86dbd3f26c4d527f64309f64389a (diff)
downloadpy2cairo-d98974c0a3de11fde1e5cdfd6dd469624c6c17d6.tar.gz
Add XCB support using xpyb
Signed-off-by: Julien Danjou <julien@danjou.info>
-rw-r--r--configure.ac6
-rw-r--r--doc/reference/surfaces.rst23
-rw-r--r--src/cairomodule.c5
-rw-r--r--src/private.h5
-rw-r--r--src/surface.c93
5 files changed, 127 insertions, 5 deletions
diff --git a/configure.ac b/configure.ac
index f305587..550ae3e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,6 +9,7 @@ m4_define(pycairo_version, pycairo_version_major.pycairo_version_minor.pycairo_v
# versions of packages we require
m4_define(cairo_required_version, 1.8.8)
+m4_define(xpyb_required_version, 1.3)
AC_INIT([pycairo],
[pycairo_version],
@@ -45,6 +46,11 @@ if test -n "$export_dynamic"; then
CAIRO_LIBS=`echo $CAIRO_LIBS | sed -e "s/$export_dynamic//"`
fi
+# xpyb
+PKG_CHECK_MODULES(XPYB, xpyb >= xpyb_required_version,[have_xpyb=yes],[have_xpyb=no])
+AS_IF([test "x$have_xpyb" = "xyes"],
+ [AC_DEFINE([HAVE_XPYB], [1], [Define to 1 if xpyb is available])])
+
# Checks for header files ---
AM_CHECK_PYTHON_HEADERS(,[AC_MSG_ERROR(could not find Python headers)])
diff --git a/doc/reference/surfaces.rst b/doc/reference/surfaces.rst
index 0957649..fbec39e 100644
--- a/doc/reference/surfaces.rst
+++ b/doc/reference/surfaces.rst
@@ -637,10 +637,27 @@ Note that the XCB surface automatically takes advantage of X render extension
if it is available.
.. class:: XCBSurface
+ :param connection: an XCB connection
+ :param drawable: a X drawable
+ :param visualtype: a X visualtype
+ :param width: The surface width
+ :param height: The surface height
- .. note:: *XCBSurface* cannot be instantiated directly because Python
- interaction with XCB would require open source Python bindings to Xlib
- which provided a C API.
+ Creates a cairo surface that targets the given drawable (pixmap or window).
+
+ .. note:: This methods works using xpyb.
+
+ .. method:: set_size(width, height)
+ :param width: The width of the surface
+ :param height: The height of the surface
+
+ Informs cairo of the new size of the X Drawable underlying the surface. For a surface created
+ for a Window (rather than a Pixmap), this function must be called each time the size of the
+ window changes. (For a subwindow, you are normally resizing the window yourself, but for a
+ toplevel window, it is necessary to listen for ConfigureNotify events.)
+
+ A Pixmap can never change size, so it is never necessary to call this function on a surface
+ created for a Pixmap.
class XlibSurface(:class:`Surface`)
diff --git a/src/cairomodule.c b/src/cairomodule.c
index a83ba49..21b7b20 100644
--- a/src/cairomodule.c
+++ b/src/cairomodule.c
@@ -39,6 +39,11 @@
# include <cairo-ps.h>
#endif
+/* for XCB api */
+#if defined(CAIRO_HAS_XCB_SURFACE) && defined(HAVE_XPYB)
+xpyb_CAPI_t *xpyb_CAPI;
+PyObject *xpybVISUALTYPE_type;
+#endif
/* A module specific exception */
PyObject *CairoError = NULL;
diff --git a/src/private.h b/src/private.h
index 4bbf4fd..708f04c 100644
--- a/src/private.h
+++ b/src/private.h
@@ -96,6 +96,11 @@ extern PyTypeObject PycairoWin32Surface_Type;
#if CAIRO_HAS_XCB_SURFACE
extern PyTypeObject PycairoXCBSurface_Type;
+#ifdef HAVE_XPYB
+# include <xpyb.h>
+extern xpyb_CAPI_t *xpyb_CAPI;
+extern PyObject *xpybVISUALTYPE_type;
+#endif
#endif
#if CAIRO_HAS_XLIB_SURFACE
diff --git a/src/surface.c b/src/surface.c
index 7a6fd2e..568aad7 100644
--- a/src/surface.c
+++ b/src/surface.c
@@ -1144,13 +1144,102 @@ PyTypeObject PycairoWin32Surface_Type = {
#ifdef CAIRO_HAS_XCB_SURFACE
#include <cairo-xcb.h>
+#ifdef HAVE_XPYB
+/** Convert a Python object from xpyb to a C struct matching libxcb type.
+ * The object must be referenced if you want to keep returned data away from
+ * garbage collection.
+ * @param obj The object to convert.
+ * @param len The size of the object read by Python.
+ * @return A pointer to that data.
+ */
+const void *
+xpyb2struct(PyObject *obj, Py_ssize_t *len)
+{
+ const void *data;
+
+ if (PyObject_AsReadBuffer(obj, &data, len) < 0)
+ return NULL;
+
+ return data;
+}
+
+static int
+have_xpyb(void)
+{
+ static int have_xpyb = -1;
+ if(have_xpyb == -1) {
+ /* Get type from xpyb */
+ xpyb_IMPORT;
+ /* Some types are not defined in the CAPI */
+ PyObject *xpyb_module = PyImport_ImportModule("xcb.xproto");
+ if (xpyb_module) {
+ PyObject *dict = PyModule_GetDict(xpyb_module);
+ xpybVISUALTYPE_type = PyDict_GetItemString(dict, "VISUALTYPE");
+ Py_DECREF(xpyb_module);
+ have_xpyb = 1;
+ }
+ else
+ have_xpyb = 0;
+ }
+ return have_xpyb;
+}
+
+#endif
+
static PyObject *
xcb_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
+#ifdef HAVE_XPYB
+ int width, height;
+ xcb_drawable_t drawable;
+ PyObject *visual;
+ xpybConn *conn;
+
+ if(!have_xpyb())
+ return NULL;
+
+ if (!PyArg_ParseTuple(args, "O!IO!ii:XCBSurface.__new__",
+ xpyb_CAPI->xpybConn_type, &conn,
+ &drawable,
+ xpybVISUALTYPE_type, &visual,
+ &width, &height))
+ return NULL;
+
+ /* Convert Python object VISUALTYPE to a xcb_visualtype_t */
+ Py_ssize_t length;
+ xcb_visualtype_t *visualtype = (xcb_visualtype_t *) xpyb2struct(visual, &length);
+
+ if (length < sizeof(xcb_visualtype_t))
+ return NULL;
+
+ return PycairoSurface_FromSurface (
+ cairo_xcb_surface_create (conn->conn, drawable, visualtype,
+ width, height), NULL);
+#else
PyErr_SetString(PyExc_TypeError,
- "The XCBSurface type cannot be directly instantiated");
+ "pycairo was not compiled with xpyb support");
return NULL;
+#endif
}
+#ifdef HAVE_XPYB
+static PyObject *
+xcb_surface_set_size (PycairoXCBSurface *o, PyObject *args) {
+ int width, height;
+
+ if (!PyArg_ParseTuple(args, "ii:XCBSurface.set_size", &width, &height))
+ return NULL;
+ cairo_xcb_surface_set_size (o->surface, width, height);
+ Py_RETURN_NONE;
+}
+#endif
+
+static PyMethodDef xcb_surface_methods[] = {
+#ifdef HAVE_XPYB
+ {"set_size", (PyCFunction)xcb_surface_set_size, METH_VARARGS },
+#endif
+ {NULL, NULL, 0, NULL},
+};
+
PyTypeObject PycairoXCBSurface_Type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
@@ -1180,7 +1269,7 @@ PyTypeObject PycairoXCBSurface_Type = {
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
- 0, /* tp_methods */
+ xcb_surface_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&PycairoSurface_Type, /* tp_base */