diff options
Diffstat (limited to 'src/surface.c')
-rw-r--r-- | src/surface.c | 93 |
1 files changed, 91 insertions, 2 deletions
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 */ |