#include #include #include #include #include #include #include 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 plane; 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) { XSync(self->dpy, False); } 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); /* Mark the segment as destroyable (it will be destroyed when this process terminates) */ shmctl(img->m_shminfo.shmid, IPC_RMID, NULL); /* 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; /* 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->plane, width, height); self->gc = XCreateGC(self->dpy, self->win, 0, 0); if (!self->shmmode) { self->backpixmap = XCreatePixmap(self->dpy, self->root, width, height, self->visual_info.depth); if (self->backpixmap == (Pixmap) -1) goto err2; 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->plane.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->plane.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; } inline 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; unsigned char* input = NULL; int length; long keycol = -1; 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; int bytes_per_pixel = self->plane.m_shm_image->bits_per_pixel/8; int countblocks, countpixels; PyObject* result; PyObject* strblocks; PyObject* strpixels; unsigned int* pblocks; unsigned char* ppixels; unsigned char* input1; if (input == NULL) { Py_INCREF(Py_None); return Py_None; } if (3*w*h != length) { PyErr_SetString(PyExc_ValueError, "bad string length"); return NULL; } /* Convert the image to our internal format. See display_putppm1() for a description of the format. */ countblocks = 0; countpixels = 0; input1 = input; for (y=0; yvisual_info.depth, bytes_per_pixel); ppixels += bytes_per_pixel; } } *pblocks++ = 0; /* end-of-line marker block */ } result = Py_BuildValue("iiOO", w, h, strblocks, strpixels); Py_DECREF(strblocks); Py_DECREF(strpixels); return result; } else { XImage* image; long extent; unsigned char* data = NULL; unsigned char* maskdata = NULL; int scanline, bitmap_pad; XPixmapObject* pm; 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_ValueError, "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_get(DisplayObject* self, int x, int y, int w, int h) { if (self->shmmode) { int clipx=0, clipy=0, clipw=self->width, cliph=self->height; int original_w, original_h; int firstline=0, firstcol=0; unsigned int bytes_per_pixel = self->plane.m_shm_image->bits_per_pixel/8; unsigned char* data = get_dpy_data(self); if (!data) return NULL; original_w = w; original_h = h; if (x clipw) w = clipw-x; if (y+h > cliph) h = cliph-y; { int countblocks = original_h + ((w>0 && h>0) ? h : 0); /* end blocks + real blocks */ int countpixels = (w>0 && h>0) ? w * h : 0; PyObject* result; PyObject* strblocks; PyObject* strpixels; unsigned int* pblocks; unsigned char* ppixels; int wbytes = w * bytes_per_pixel; int block = (firstcol * bytes_per_pixel) | (wbytes << 16); int data_scanline = bytes_per_pixel*self->width; /* allocate memory */ strblocks = PyString_FromStringAndSize(NULL, countblocks*sizeof(int)); if (strblocks == NULL) return NULL; strpixels = PyString_FromStringAndSize(NULL, countpixels*bytes_per_pixel); if (strpixels == NULL) { Py_DECREF(strblocks); return NULL; } /* write data */ pblocks = (unsigned int*) PyString_AS_STRING(strblocks); ppixels = (unsigned char*) PyString_AS_STRING(strpixels); data += bytes_per_pixel*(x+y*self->width); for (y=0; y= firstline && y < firstline+h && w > 0) { *pblocks++ = block; memcpy(ppixels, data, wbytes); ppixels += wbytes; data += data_scanline; } *pblocks++ = 0; } result = Py_BuildValue("iiOO", original_w, original_h, strblocks, strpixels); Py_DECREF(strblocks); Py_DECREF(strpixels); return result; } } else { XPixmapObject* pm = new_pixmap(self, w, h, 0); if (pm != NULL) XCopyArea(self->dpy, self->backpixmap, pm->handle, self->gc, x, y, w, h, 0, 0); return (PyObject*) pm; } } static PyObject* save_background(DisplayObject* self, int x, int y, int w, int h, int save_bkgnd) { if (save_bkgnd) { PyObject* pm = display_get(self, x, y, w, h); PyObject* result; if (pm == NULL) return NULL; result = Py_BuildValue("iiO", x, y, pm); Py_DECREF(pm); return result; } else { Py_INCREF(Py_None); return Py_None; } } #define ALPHAFACTOR 2 #define ALPHABLEND(maximum, x, y) ((maximum-y)*x/(maximum*ALPHAFACTOR) + y) static void memcpy_alpha_32(unsigned int* dst, unsigned int* src, int count) { int i; for (i=0; i> 16; int xg = x & 0xff00; int xb = x & 0xff; int yr = y >> 16; int yg = y & 0xff00; int yb = y & 0xff; int zr = ALPHABLEND(0xff, xr, yr); int zg = ALPHABLEND(0xff00, xg, yg); int zb = ALPHABLEND(0xff, xb, yb); dst[i] = (zr << 16) | (zg & 0xff00) | zb; } } static void memcpy_alpha_24(unsigned char* dst, unsigned char* src, int count) { int i; for (i=0; i> 10; int xg = x & 0x03e0; int xb = x & 0x001f; int yr = y >> 10; int yg = y & 0x03e0; int yb = y & 0x001f; int zr = ALPHABLEND(31, xr, yr); int zg = ALPHABLEND(0x3e0, xg, yg); int zb = ALPHABLEND(31, xb, yb); dst[i] = (zr << 10) | (zg & 0x03e0) | zb; } } static void memcpy_alpha_16(unsigned short* dst, unsigned short* src, int count) { int i; for (i=0; i> 11; int xg = x & 0x07e0; int xb = x & 0x001f; int yr = y >> 11; int yg = y & 0x07e0; int yb = y & 0x001f; int zr = ALPHABLEND(31, xr, yr); int zg = ALPHABLEND(0x7e0, xg, yg); int zb = ALPHABLEND(31, xb, yb); dst[i] = (zr << 11) | (zg & 0x07e0) | zb; } } typedef void (*memcpy_alpha_fn) (unsigned char*, unsigned char*, int); static PyObject* display_overlay(DisplayObject* self, PyObject* args, int save_bkgnd) { PyObject* result; if (self->shmmode) { int x,y,w,h, original_x, original_y, original_w, original_h; int data_scanline; int clipx=0, clipy=0, clipw=65536, cliph=65536, alpha=255; unsigned int* src; unsigned char* srcdata; unsigned char* original_srcdata; int length1, length2, firstline=0, firstcol=0; unsigned int bytes_per_pixel = self->plane.m_shm_image->bits_per_pixel/8; memcpy_alpha_fn memcpy_alpha; unsigned char* data = get_dpy_data(self); if (!PyArg_ParseTuple(args, "ii(iis#s#)|(iiii)i", &x, &y, &w, &h, &src, &length1, &srcdata, &length2, &clipx, &clipy, &clipw, &cliph, &alpha) || !data) return NULL; original_x = x; original_y = y; original_w = w; original_h = h; original_srcdata = srcdata; 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 && h > 0) { int dstoffset, blocksize; unsigned int block; data += bytes_per_pixel*(x+y*self->width); data_scanline = bytes_per_pixel*self->width; memcpy_alpha = (memcpy_alpha_fn) memcpy; if (alpha < 255) switch (self->visual_info.depth) { case 15: memcpy_alpha = (memcpy_alpha_fn) memcpy_alpha_15; break; case 16: memcpy_alpha = (memcpy_alpha_fn) memcpy_alpha_16; break; case 24: memcpy_alpha = (memcpy_alpha_fn) memcpy_alpha_24; break; case 32: memcpy_alpha = (memcpy_alpha_fn) memcpy_alpha_32; break; } /* 'structure' points to a sequence of int-sized blocks with the following meaning: n & 0xFFFF -- byte offset within the line n >> 16 -- number of opaque bytes to copy there n == 0 means end of line. */ /* read and ignore 'firstline' complete lines */ while (firstline--) { while ((block = *src++) != 0) { blocksize = block >> 16; srcdata += blocksize; } } if (w == original_w) { if (!save_bkgnd) { /* common fast case: copy the whole width of the image */ do { while ((block = *src++) != 0) { dstoffset = block & 0xFFFF; blocksize = block >> 16; memcpy(data + dstoffset, srcdata, blocksize); srcdata += blocksize; } data += data_scanline; } while (--h); result = Py_None; Py_INCREF(result); } else { /* copy and save the background */ PyObject* cliprect; PyObject* strblocks; PyObject* strpixels; unsigned char* ppixels; strpixels = PyString_FromStringAndSize(NULL, length2); if (strpixels == NULL) return NULL; ppixels = (unsigned char*) PyString_AS_STRING(strpixels); ppixels += srcdata - original_srcdata; do { while ((block = *src++) != 0) { dstoffset = block & 0xFFFF; blocksize = block >> 16; memcpy(ppixels, data + dstoffset, blocksize); ppixels += blocksize; memcpy_alpha(data + dstoffset, srcdata, blocksize); srcdata += blocksize; } data += data_scanline; } while (--h); strblocks = PyTuple_GET_ITEM(PyTuple_GET_ITEM(args, 2), 2); if (PyTuple_GET_SIZE(args) > 3) { cliprect = PyTuple_GET_ITEM(args, 3); result = Py_BuildValue("ii(iiOO)O", original_x, original_y, original_w, original_h, strblocks, strpixels, cliprect); } else { result = Py_BuildValue("ii(iiOO)", original_x, original_y, original_w, original_h, strblocks, strpixels); } Py_DECREF(strpixels); } } else { /* byte offsets within a line */ unsigned char* blocksrc; int skip, lastcol; result = save_background(self, x, y, w, h, save_bkgnd); lastcol = (firstcol + w) * bytes_per_pixel; firstcol *= bytes_per_pixel; /* slow case: only copy a portion of the width of the image */ data -= firstcol; do { while ((block = *src++) != 0) { dstoffset = block & 0xFFFF; blocksize = block >> 16; blocksrc = srcdata; srcdata += blocksize; skip = firstcol - dstoffset; if (skip < 0) skip = 0; if (blocksize > lastcol - dstoffset) blocksize = lastcol - dstoffset; if (blocksize > skip) memcpy_alpha(data + dstoffset + skip, blocksrc + skip, blocksize - skip); } data += data_scanline; } while (--h); } } else { result = args; Py_INCREF(result); } } else { int x,y, x1=0,y1=0,w1=-1,h1=-1,alpha; XPixmapObject* pm; if (!checkopen(self)) return NULL; if (!PyArg_ParseTuple(args, "iiO!|(iiii)i", &x, &y, &XPixmap_Type, &pm, &x1, &y1, &w1, &h1, &alpha)) return NULL; if (w1 < 0) w1 = pm->width; if (h1 < 0) h1 = pm->height; result = save_background(self, x, y, w1, h1, save_bkgnd); 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); } } return result; } static PyObject* display_putppm1(DisplayObject* self, PyObject* args) { return display_overlay(self, args, 0); } static PyObject* display_overlayppm1(DisplayObject* self, PyObject* args) { return display_overlay(self, args, 1); } static PyObject* display_getppm1(DisplayObject* self, PyObject* args) { int x, y, w, h; if (!checkopen(self)) return NULL; if (!PyArg_ParseTuple(args, "(iiii)", &x, &y, &w, &h)) return NULL; return display_get(self, x, y, w, h); } static int readXevents(DisplayObject* self) { while (XEventsQueued(self->dpy, QueuedAfterReading) > 0) { XEvent e; XNextEvent(self->dpy, &e); 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; } sym = XLookupKeysym(&e.xkey,0); v = Py_BuildValue("ii", sym, e.type); 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; } #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)) 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->plane.m_shm_image, 0, 0, 0, 0, self->plane.m_width, self->plane.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)) 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); } 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}, {"overlayppm",(PyCFunction)display_overlayppm1, METH_VARARGS, NULL}, {"keyevents",(PyCFunction)display_keyevents1,METH_VARARGS, NULL}, {"mouseevents",(PyCFunction)display_mouseevents1,METH_VARARGS,NULL}, {"pointermotion",(PyCFunction)display_pointermotion1,METH_VARARGS,NULL}, {"fd", (PyCFunction)display_fd1, METH_VARARGS, NULL}, {"shmmode", (PyCFunction)display_shmmode, METH_VARARGS, NULL}, {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); }