#include #include #include #include #include #include #include #define TEXT_METHODS typedef struct { XImage* m_shm_image; XShmSegmentInfo m_shminfo; int m_width, m_height; } XImage_Shm; typedef struct { PyObject_HEAD Display* dpy; int default_scr; Window root, win; int width, height; XVisualInfo visual_info; GC gc, gc_and, gc_or; XImage_Shm planes[1]; Pixmap backpixmap; int shmmode; int selectinput; PyObject* keyevents; PyObject* mouseevents; PyObject* motionevent; } DisplayObject; typedef struct { PyObject_HEAD DisplayObject* dpy; int width, height; Pixmap mask; Pixmap handle; } XPixmapObject; #define DisplayObject_Check(v) ((v)->ob_type == &Display_Type) staticforward PyTypeObject Display_Type; staticforward PyTypeObject XPixmap_Type; static void pixmap_dealloc(XPixmapObject* pm) { if (pm->dpy->dpy) { if (pm->mask != (Pixmap) -1) XFreePixmap(pm->dpy->dpy, pm->mask); XFreePixmap(pm->dpy->dpy, pm->handle); } Py_DECREF(pm->dpy); PyObject_Del(pm); } static XPixmapObject* new_pixmap(DisplayObject* self, int w, int h, int withmask) { XPixmapObject* pm = PyObject_New(XPixmapObject, &XPixmap_Type); if (pm != NULL) { Py_INCREF(self); pm->dpy = self; pm->width = w; pm->height = h; pm->handle = XCreatePixmap(self->dpy, self->win, w, h, self->visual_info.depth); if (withmask) pm->mask = XCreatePixmap(self->dpy, self->win, w, h, self->visual_info.depth); else pm->mask = (Pixmap) -1; } return pm; } static void flush(DisplayObject* self) { Py_BEGIN_ALLOW_THREADS XSync(self->dpy, False); Py_END_ALLOW_THREADS } static int create_shm_image(DisplayObject* self, XImage_Shm* img, int width, int height) { int image_size = 4*width*height; if (XShmQueryExtension(self->dpy) == False) // does we have the extension at all? return 0; img->m_shm_image = XShmCreateImage( self->dpy, self->visual_info.visual, self->visual_info.depth, ZPixmap, NULL, &img->m_shminfo, width, height); if (img->m_shm_image == NULL) return 0; img->m_width = width; img->m_height = height; // Create shared memory segment: img->m_shminfo.shmid = shmget(IPC_PRIVATE, image_size, IPC_CREAT|0777); if (img->m_shminfo.shmid < 0) return 0; // Get memory address to segment: img->m_shminfo.shmaddr = (char *) shmat(img->m_shminfo.shmid, 0, 0); // Tell XServer that it may only read from it and attach to display: img->m_shminfo.readOnly = True; XShmAttach (self->dpy, &img->m_shminfo); // Fill the XImage struct: img->m_shm_image->data = img->m_shminfo.shmaddr; return 1; } static PyObject* new_display(PyObject* dummy, PyObject* args) { DisplayObject* self; XSetWindowAttributes attr; int width, height, use_shm=1; if (!PyArg_ParseTuple(args, "ii|i", &width, &height, &use_shm)) return NULL; self = PyObject_New(DisplayObject, &Display_Type); if (self == NULL) return NULL; self->dpy = XOpenDisplay(NULL); if (self->dpy == NULL) goto err; self->default_scr = DefaultScreen(self->dpy); self->root = RootWindow(self->dpy, self->default_scr); self->width = width; self->height = height; if (!XMatchVisualInfo(self->dpy, self->default_scr, DefaultDepth(self->dpy,self->default_scr), TrueColor, &self->visual_info)) goto err2; self->backpixmap = XCreatePixmap(self->dpy, self->root, width, height, self->visual_info.depth); if (self->backpixmap == (Pixmap) -1) goto err2; /* set window attributes */ memset(&attr, 0, sizeof(attr)); attr.override_redirect = False; attr.background_pixel = BlackPixel(self->dpy, self->default_scr); attr.backing_store = NotUseful; /* Create the window */ self->win = XCreateWindow( self->dpy, self->root, 0, 0, width, height, 0, CopyFromParent, CopyFromParent, self->visual_info.visual, CWOverrideRedirect | CWBackPixel | CWBackingStore, &attr); if (self->win == (Window) -1) goto err2; XMapRaised(self->dpy, self->win); self->shmmode = use_shm && create_shm_image(self, &self->planes[0], width, height); self->gc = XCreateGC(self->dpy, self->win, 0, 0); if (!self->shmmode) { self->gc_and = XCreateGC(self->dpy, self->win, 0, 0); self->gc_or = XCreateGC(self->dpy, self->win, 0, 0); XSetForeground(self->dpy, self->gc, attr.background_pixel); XSetFunction(self->dpy, self->gc_and, GXand); XSetFunction(self->dpy, self->gc_or, GXor); } self->selectinput = 0; self->keyevents = NULL; self->mouseevents = NULL; self->motionevent = NULL; flush(self); return (PyObject*) self; err2: XCloseDisplay(self->dpy); err: Py_DECREF(self); PyErr_SetString(PyExc_IOError, "cannot open X11 display"); return NULL; } static void display_close(DisplayObject* self) { if (self->dpy) { XCloseDisplay(self->dpy); self->dpy = NULL; } } static void display_dealloc(DisplayObject* self) { display_close(self); Py_XDECREF(self->keyevents); Py_XDECREF(self->mouseevents); Py_XDECREF(self->motionevent); PyObject_Del(self); } static PyObject* display_close1(DisplayObject* self, PyObject* args) { display_close(self); Py_INCREF(Py_None); return Py_None; } static int checkopen(DisplayObject* self) { if (self->dpy) return 1; PyErr_SetString(PyExc_IOError, "X11 connexion already closed"); return 0; } static unsigned char* get_dpy_data(DisplayObject* self) { unsigned char* result; if (!checkopen(self)) return NULL; result = (unsigned char*)(self->planes[0].m_shminfo.shmaddr); if (!result) PyErr_SetString(PyExc_IOError, "X11 SHM failed"); return result; } static PyObject* display_clear1(DisplayObject* self, PyObject* args) { if (self->shmmode) { unsigned char* data = get_dpy_data(self); if (data == NULL) return NULL; memset(data, 0, ( self->planes[0].m_shm_image->bits_per_pixel/8 *self->width*self->height ) ); } else { if (!checkopen(self)) return NULL; XFillRectangle(self->dpy, self->backpixmap, self->gc, 0, 0, self->width, self->height); } Py_INCREF(Py_None); return Py_None; } static void pack_pixel(unsigned char *data, int r, int g, int b, int depth, int bytes_per_pixel) { unsigned short pixel = 0; switch( depth ) { /* No True color below 15 bits per pixel */ case 15: pixel = ((r<<7) & 0x7c00) | ((g<<2) & 0x03e0) | ((b>>3) & 0x001f); data[0] = (pixel) & 0xff; data[1] = (pixel>>8) & 0xff; break; case 16: /* assumes 5,6,5 model. */ pixel = ((r<<8) & 0xf800) | ((g<<3) & 0x07e0) | ((b>>3) & 0x001f); data[0] = (pixel) & 0xff; data[1] = (pixel>>8) & 0xff; break; case 24: if( bytes_per_pixel == 3 ) { data[0] = b; data[1] = g; data[2] = r; break; } /* else it's on 32 bits. Drop into depth of 32. */ case 32: *((long *)data) = (r<<16) | (g<<8) | b; break; } } static PyObject* display_pixmap1(DisplayObject* self, PyObject* args) { int w,h; int length; XImage* image; long extent; unsigned char* data = NULL; unsigned char* maskdata = NULL; unsigned char* input = NULL; int scanline, bitmap_pad; XPixmapObject* pm; long keycol = -1; unsigned int bytes_per_pixel = (self->visual_info.depth+7)/8; if (!checkopen(self)) return NULL; if (!PyArg_ParseTuple(args, "ii|s#l", &w, &h, &input, &length, &keycol)) return NULL; if (self->shmmode) { int x, y; unsigned char *dst; int size; long packed_keycol = keycol; PyObject* result; PyObject* str; bytes_per_pixel = self->planes[0].m_shm_image->bits_per_pixel/8; size = bytes_per_pixel*w*h; if (input == NULL ) { Py_INCREF(Py_None); return Py_None; } if( 3*w*h != length ) { PyErr_SetString(PyExc_TypeError, "bad string length"); return NULL; } /* Create a new string and fill it with the correctly packed image */ str = PyString_FromStringAndSize(NULL, size); if (!str) return NULL; if (keycol >= 0) switch( self->visual_info.depth ) { case 15: packed_keycol = (1 << 10) | (1 << 5) | 1; break; case 16: packed_keycol = (1 << 11) | (1 << 5) | 1; break; default: packed_keycol = keycol; break; } result = Py_BuildValue("iiOl", w, h, str, packed_keycol); Py_DECREF(str); /* one ref left in 'result' */ if (!result) return NULL; dst = (unsigned char*) PyString_AS_STRING(str); memset(dst,0,size); for( y=0; yvisual_info.depth, bytes_per_pixel); } return result; } pm = new_pixmap(self, w, h, keycol>=0); if (pm == NULL) return NULL; if (input == NULL) return (PyObject*) pm; /* uninitialized pixmap */ extent = w*h; if (3*extent != length) { PyErr_SetString(PyExc_TypeError, "bad string length"); goto err; } bitmap_pad = self->visual_info.depth >= 24 ? 32 : 16; scanline = ((w+bitmap_pad-1) & ~(bitmap_pad-1)) / 8; /*while (scanline&3) scanline++;*/ data = malloc(self->visual_info.depth*scanline*h); if (data == NULL) { PyErr_NoMemory(); goto err; } memset(data, 0, self->visual_info.depth*scanline*h); maskdata = malloc(self->visual_info.depth*scanline*h); if (maskdata == NULL) { PyErr_NoMemory(); goto err; } memset(maskdata, 0, self->visual_info.depth*scanline*h); { int key_r = keycol>>16; unsigned char key_g = keycol>>8; unsigned char key_b = keycol>>0; unsigned char* target = data; unsigned char* masktarget = maskdata; int plane, color; unsigned int p_size[3]; switch( self->visual_info.depth ) { case 15: p_size[0] = p_size[1] = p_size[2] = 5; break; case 16: p_size[0] = p_size[2] = 5; p_size[1] = 6; break; case 24: case 32: p_size[0] = p_size[1] = p_size[2] = 8; break; } for (color=0; color<3; color++) for (plane=128; plane>=(1<<(8-p_size[color])); plane/=2) { unsigned char* src = input; int x, y; for (y=0; ydpy, self->visual_info.visual, self->visual_info.depth, XYPixmap, 0, maskdata, w, h, bitmap_pad, scanline); if (image == NULL || image == (XImage*) -1) { PyErr_SetString(PyExc_IOError, "XCreateImage failed (2)"); goto err; } image->byte_order = LSBFirst; image->bitmap_bit_order = LSBFirst; maskdata = NULL; XPutImage(self->dpy, pm->mask, self->gc, image, 0, 0, 0, 0, w, h); XDestroyImage(image); } image = XCreateImage(self->dpy, self->visual_info.visual, self->visual_info.depth, XYPixmap, 0, data, w, h, bitmap_pad, scanline); if (image == NULL || image == (XImage*) -1) { PyErr_SetString(PyExc_IOError, "XCreateImage failed"); goto err; } image->byte_order = LSBFirst; image->bitmap_bit_order = LSBFirst; data = NULL; XPutImage(self->dpy, pm->handle, self->gc, image, 0, 0, 0, 0, w, h); XDestroyImage(image); return (PyObject*) pm; err: free(maskdata); free(data); Py_DECREF(pm); return NULL; } static PyObject* display_putppm1(DisplayObject* self, PyObject* args) { if (self->shmmode) { int x,y,w,h,scanline; int bytes_per_line, data_scanline; int clipx=0, clipy=0, clipw=65536, cliph=65536; unsigned char* src; int length; long keycol; unsigned int bytes_per_pixel = self->planes[0].m_shm_image->bits_per_pixel/8; unsigned char* data = get_dpy_data(self); if (!PyArg_ParseTuple(args, "ii(iis#l)|(iiii)", &x, &y, &w, &h, &src, &length, &keycol, &clipx, &clipy, &clipw, &cliph) || !data) return NULL; scanline = bytes_per_pixel*w; if (scanline*h != length) { PyErr_SetString(PyExc_TypeError, "bad string length"); return NULL; } x -= clipx; y -= clipy; clipx += x; clipy += y; clipw += clipx; cliph += clipy; if (clipx<0) clipx=0; if (clipy<0) clipy=0; if (clipw>self->width) clipw=self->width; if (cliph>self->height) cliph=self->height; if (x clipw) w = clipw-x; if (y+h > cliph) h = cliph-y; if (w > 0) { data += bytes_per_pixel*(x+y*self->width); bytes_per_line = w*bytes_per_pixel; data_scanline = bytes_per_pixel*self->width; if (keycol < 0) { while (h>0) { memcpy(data, src, bytes_per_line); src += scanline; data += data_scanline; h--; } } else { int i; unsigned char *keycol_bytes = (unsigned char *)&keycol; switch(bytes_per_pixel) { case 2: while (h>0) { unsigned char* src1 = src; unsigned char* data1 = data; for (i=0; i0) { unsigned char* src1 = src; unsigned char* data1 = data; for (i=0; i0) { unsigned char* src1 = src; unsigned char* data1 = data; for (i=0; iwidth; if (h1 < 0) h1 = pm->height; if (pm->mask == (Pixmap) -1) { XCopyArea(self->dpy, pm->handle, self->backpixmap, self->gc, x1, y1, w1, h1, x, y); } else { XCopyArea(self->dpy, pm->mask, self->backpixmap, self->gc_and, x1, y1, w1, h1, x, y); XCopyArea(self->dpy, pm->handle, self->backpixmap, self->gc_or, x1, y1, w1, h1, x, y); } } Py_INCREF(Py_None); return Py_None; } static PyObject* display_getppm1(DisplayObject* self, PyObject* args) { if (self->shmmode) { int x,y,w,h,scanline; int bytes_per_line, data_scanline; int clipx=0, clipy=0, clipw=self->width, cliph=self->height; unsigned char* dst; int length; PyObject* ignored; PyObject* result; PyObject* str; unsigned int bytes_per_pixel = self->planes[0].m_shm_image->bits_per_pixel/8; unsigned char* data = get_dpy_data(self); if (!PyArg_ParseTuple(args, "(iiii)|O", &x, &y, &w, &h, &ignored) || !data) return NULL; scanline = bytes_per_pixel*w; length = scanline*h; str = PyString_FromStringAndSize(NULL, length); if (!str) return NULL; result = Py_BuildValue("iiOl", w, h, str, -1); Py_DECREF(str); /* one ref left in 'result' */ if (!result) return NULL; dst = (unsigned char*) PyString_AS_STRING(str); if (x clipw) w = clipw-x; if (y+h > cliph) h = cliph-y; if (w > 0) { data += bytes_per_pixel*(x+y*self->width); bytes_per_line = w*bytes_per_pixel; data_scanline = bytes_per_pixel*self->width; while (h>0) { memcpy(dst, data, bytes_per_line); dst += scanline; data += data_scanline; h--; } } return result; } else { int x,y,w,h; XPixmapObject* pm = NULL; if (!checkopen(self)) return NULL; if (!PyArg_ParseTuple(args, "(iiii)|O!", &x, &y, &w, &h, &XPixmap_Type, &pm)) return NULL; if (pm == NULL) { pm = new_pixmap(self, w, h, 0); if (pm == NULL) return NULL; } else Py_INCREF(pm); XCopyArea(self->dpy, self->backpixmap, pm->handle, self->gc, x, y, w, h, 0, 0); return (PyObject*) pm; } } static int readXevents(DisplayObject* self, int blocking) { while (blocking || XEventsQueued(self->dpy, QueuedAfterReading) > 0) { XEvent e; blocking = 0; Py_BEGIN_ALLOW_THREADS XNextEvent(self->dpy, &e); Py_END_ALLOW_THREADS switch (e.type) { case KeyPress: case KeyRelease: { KeySym sym; PyObject* v; int err; if (self->keyevents == NULL) { self->keyevents = PyList_New(0); if (self->keyevents == NULL) return 0; } { char test[80]; int n; n = XLookupString(&e.xkey, test, sizeof(test), &sym, NULL); v = Py_BuildValue("iiN", sym, e.type, PyString_FromStringAndSize(test, n)); } if (v == NULL) return 0; err = PyList_Append(self->keyevents, v); Py_DECREF(v); if (err) return 0; break; } case ButtonPress: { PyObject* v; int err; if (self->mouseevents == NULL) { self->mouseevents = PyList_New(0); if (self->mouseevents == NULL) return 0; } v = Py_BuildValue("ii", e.xbutton.x, e.xbutton.y); if (v == NULL) return 0; err = PyList_Append(self->mouseevents, v); Py_DECREF(v); if (err) return 0; break; } case MotionNotify: { Py_XDECREF(self->motionevent); self->motionevent = Py_BuildValue("ii", e.xmotion.x, e.xmotion.y); if (self->motionevent == NULL) return 0; break; } } } return 1; } static PyObject* display_wait1(DisplayObject* self) { if (!readXevents(self, 1)) return NULL; Py_INCREF(Py_None); return Py_None; } #define ENABLE_EVENTS(mask) do { \ if (!(self->selectinput & (mask))) \ { \ self->selectinput |= (mask); \ XSelectInput(self->dpy, self->win, self->selectinput); \ } \ } while (0) static PyObject* display_keyevents1(DisplayObject* self, PyObject* args) { PyObject* result; ENABLE_EVENTS(KeyPressMask|KeyReleaseMask); if (!readXevents(self, 0)) return NULL; result = self->keyevents; if (result == NULL) result = PyList_New(0); else self->keyevents = NULL; return result; } static PyObject* display_mouseevents1(DisplayObject* self, PyObject* args) { PyObject* result; ENABLE_EVENTS(ButtonPressMask); result = self->mouseevents; if (result == NULL) result = PyList_New(0); else self->mouseevents = NULL; return result; } static PyObject* display_pointermotion1(DisplayObject* self, PyObject* args) { PyObject* result; ENABLE_EVENTS(PointerMotionMask); result = self->motionevent; if (result == NULL) { Py_INCREF(Py_None); result = Py_None; } else self->motionevent = NULL; return result; } static PyObject* display_flip1(DisplayObject* self, PyObject* args) { if (!checkopen(self)) return NULL; if (self->shmmode) { XShmPutImage(self->dpy, self->win, self->gc, self->planes[0].m_shm_image, 0, 0, 0, 0, self->planes[0].m_width, self->planes[0].m_height, False); } else { XCopyArea(self->dpy, self->backpixmap, self->win, self->gc, 0, 0, self->width, self->height, 0, 0); } flush(self); if (!readXevents(self, 0)) return NULL; Py_INCREF(Py_None); return Py_None; } static PyObject* display_fd1(DisplayObject* self, PyObject *args) { return PyInt_FromLong(ConnectionNumber(self->dpy)); } static PyObject* display_shmmode(DisplayObject* self, PyObject *args) { return PyInt_FromLong(self->shmmode); } #ifdef TEXT_METHODS typedef struct { PyObject_HEAD DisplayObject* dpy; XFontStruct* fs; Font fid; int ascent, descent; } XFontObject; staticforward PyTypeObject XFontObject_Type; static void font_dealloc(XFontObject* f) { if (f->dpy->dpy) XFreeFont(f->dpy->dpy, f->fs); Py_DECREF(f->dpy); PyObject_Del(f); } static PyObject* font_size(XFontObject* f, PyObject* args) { char* string; int nchars; int direction, ascent, descent; XCharStruct overall; if (!PyArg_ParseTuple(args, "s#", &string, &nchars)) return NULL; XTextExtents(f->fs, string, nchars, &direction, &ascent, &descent, &overall); return Py_BuildValue("ii", overall.width, f->ascent+f->descent); } static PyObject* font_select(XFontObject* f, PyObject* args) { Display* dpy; GC gc; long fgcolor=-1, bgcolor=-1; if (!PyArg_ParseTuple(args, "|ll", &fgcolor, &bgcolor)) return NULL; dpy = f->dpy->dpy; gc = f->dpy->gc; XSetFont(dpy, gc, f->fid); if (fgcolor != -1) XSetForeground(dpy, gc, fgcolor); if (bgcolor != -1) XSetBackground(dpy, gc, bgcolor); Py_INCREF(Py_None); return Py_None; } static PyObject* display_write(DisplayObject* self, PyObject *args) { char* string; int x, y, nchars; if (!PyArg_ParseTuple(args, "iis#", &x, &y, &string, &nchars)) return NULL; XDrawImageString(self->dpy, self->backpixmap, self->gc, x, y, string, nchars); Py_INCREF(Py_None); return Py_None; } #define OFF(x) offsetof(XFontObject, x) static PyMemberDef font_memberlist[] = { {"display", T_OBJECT, OFF(dpy), RO}, {"ascent", T_INT, OFF(ascent), RO}, {"descent", T_INT, OFF(descent), RO}, {NULL} /* Sentinel */ }; #undef OFF static PyMethodDef font_methodlist[] = { {"size", (PyCFunction)font_size, METH_VARARGS}, {"select", (PyCFunction)font_select, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; statichere PyTypeObject XFontObject_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, "font", sizeof(XFontObject), 0, (destructor)font_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ font_methodlist, /* tp_methods */ font_memberlist, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ }; static PyObject* display_font(DisplayObject* self, PyObject *args) { char* name; XFontStruct* fs; XFontObject* o; if (!PyArg_ParseTuple(args, "s", &name)) return NULL; if (self->shmmode) { PyErr_SetString(PyExc_ValueError, "not for SHM mode"); return NULL; } fs = XLoadQueryFont(self->dpy, name); if (fs == NULL) { PyErr_SetString(PyExc_ValueError, "font not found"); return NULL; } o = PyObject_New(XFontObject, &XFontObject_Type); if (o != NULL) { o->dpy = self; Py_INCREF(self); o->fs = fs; o->fid = fs->fid; o->ascent = fs->ascent; o->descent = fs->descent; } return (PyObject*) o; } #endif static PyMethodDef display_methods[] = { {"close", (PyCFunction)display_close1, METH_VARARGS, NULL}, {"flip", (PyCFunction)display_flip1, METH_VARARGS, NULL}, {"clear", (PyCFunction)display_clear1, METH_VARARGS, NULL}, {"pixmap", (PyCFunction)display_pixmap1, METH_VARARGS, NULL}, {"putppm", (PyCFunction)display_putppm1, METH_VARARGS, NULL}, {"getppm", (PyCFunction)display_getppm1, METH_VARARGS, NULL}, {"keyevents",(PyCFunction)display_keyevents1,METH_VARARGS, NULL}, {"mouseevents",(PyCFunction)display_mouseevents1,METH_VARARGS,NULL}, {"pointermotion",(PyCFunction)display_pointermotion1,METH_VARARGS,NULL}, {"wait", (PyCFunction)display_wait1, METH_NOARGS, NULL}, {"fd", (PyCFunction)display_fd1, METH_VARARGS, NULL}, {"shmmode", (PyCFunction)display_shmmode, METH_VARARGS, NULL}, #ifdef TEXT_METHODS {"font", (PyCFunction)display_font, METH_VARARGS, NULL}, {"write", (PyCFunction)display_write, METH_VARARGS, NULL}, #endif {NULL, NULL} /* sentinel */ }; static PyObject* display_getattr(DisplayObject* self, char* name) { return Py_FindMethod(display_methods, (PyObject*)self, name); } statichere PyTypeObject Display_Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "Display", /*tp_name*/ sizeof(DisplayObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor)display_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ (getattrfunc)display_getattr, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ 0, /*tp_call*/ }; statichere PyTypeObject XPixmap_Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "Pixmap", /*tp_name*/ sizeof(XPixmapObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor)pixmap_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ 0, /*tp_call*/ }; static PyMethodDef ShmMethods[] = { {"Display", new_display, METH_VARARGS}, {NULL, NULL} /* Sentinel */ }; void initxshm(void) { Display_Type.ob_type = &PyType_Type; XPixmap_Type.ob_type = &PyType_Type; Py_InitModule("xshm", ShmMethods); }