summaryrefslogtreecommitdiff
path: root/display/pythonxlibintf.py
diff options
context:
space:
mode:
Diffstat (limited to 'display/pythonxlibintf.py')
-rw-r--r--display/pythonxlibintf.py202
1 files changed, 202 insertions, 0 deletions
diff --git a/display/pythonxlibintf.py b/display/pythonxlibintf.py
new file mode 100644
index 0000000..5e32715
--- /dev/null
+++ b/display/pythonxlibintf.py
@@ -0,0 +1,202 @@
+
+ ################################################
+## pygame-based implementation of xshm ##
+################################################
+
+import os, sys
+from Xlib import X, display
+
+
+# -*-*- SLOOWWW -*-*-
+import psyco; psyco.full()
+
+
+class Display:
+
+ def __init__(self, width, height, title):
+ self.dpy = display.Display()
+ self.default_scr = self.dpy.screen()
+ self.root = self.default_scr.root
+ self.width = width
+ self.height = height
+ self.depth = self.default_scr.root_depth
+
+ self.backpixmap = self.root.create_pixmap(width, height, self.depth)
+ self.win = self.root.create_window(
+ 0, 0, width, height, 0, self.depth,
+ override_redirec = 0,
+ background_pixel = self.default_scr.black_pixel,
+ backing_store = X.NotUseful,
+ )
+ self.win.map()
+
+ self.gc = self.win.create_gc()
+ self.gc_and = self.win.create_gc()
+ self.gc_or = self.win.create_gc()
+
+ self.gc.change(foreground = self.default_scr.black_pixel)
+ self.gc_and.change(function = X.GXand)
+ self.gc_or .change(function = X.GXor)
+
+ self.selectinput = 0
+ self.keyev = []
+ self.mouseev = []
+ self.motionev = None
+ self.dpy.flush()
+
+ pixel = "\x00\x00\x80"
+ hole = "\x01\x01\x01"
+ self.taskbkgnd = self.pixmap(32, 32,
+ ((pixel+hole)*16 + (hole+pixel)*16) * 16,
+ 0x010101)
+
+ def pixmap(self, w, h, data, colorkey=-1):
+ print >> sys.stderr, '.',
+ extent = w*h
+ depth = self.depth
+ if depth >= 24:
+ bitmap_pad = 32
+ else:
+ bitmap_pad = 16
+ scanline = ((w+bitmap_pad-1) & ~(bitmap_pad-1)) / 8;
+ if colorkey >= 0:
+ key = (chr(colorkey >> 16) +
+ chr((colorkey>>8) & 0xFF) +
+ chr(colorkey & 0xFF))
+ else:
+ key = None
+ if depth == 15:
+ p_size = 5, 5, 5
+ elif depth == 16:
+ p_size = 5, 6, 5
+ elif depth == 24 or depth == 32:
+ p_size = 8, 8, 8
+ else:
+ raise ValueError, 'unsupported screen depth %d' % depth
+
+ imgdata = []
+ maskdata = []
+
+ for color in range(3):
+ plane = 128
+ while plane >= (1<<(8-p_size[color])):
+ src = 0
+ for y in range(h):
+ imgline = 0L
+ maskline = 0L
+ shifter = 1L
+ for x in range(w):
+ if data[src:src+3] == key:
+ # transparent
+ maskline |= shifter
+ elif ord(data[src+color]) & plane:
+ imgline |= shifter
+ shifter <<= 1
+ src += 3
+ imgdata.append(long2string(imgline, scanline))
+ maskdata.append(long2string(maskline, scanline))
+ plane /= 2
+
+ imgdata = ''.join(imgdata)
+ if colorkey >= 0:
+ maskdata = ''.join(maskdata)
+ mask = self.win.create_pixmap(w, h, depth)
+ mask.put_image(self.gc, 0, 0, w, h, X.XYPixmap, depth, 0, maskdata)
+ else:
+ mask = None
+ imgdata = ''.join(imgdata)
+ image = self.win.create_pixmap(w, h, depth)
+ image.put_image(self.gc, 0, 0, w, h, X.XYPixmap, depth, 0, imgdata)
+ image.mask = mask
+ image.size = w, h
+ return image
+
+ def getppm(self, (x, y, w, h), bkgnd=None):
+ if bkgnd is None:
+ bkgnd = self.win.create_pixmap(w, h, self.depth)
+ bkgnd.mask = None
+ bkgnd.size = w, h
+ bkgnd.copy_area(self.gc, self.backpixmap, x, y, w, h, 0, 0)
+ return bkgnd
+
+ def putppm(self, x, y, image, rect=None):
+ if rect:
+ x1, y1, w1, h1 = rect
+ else:
+ x1 = y1 = 0
+ w1, h1 = image.size
+ if image.mask is None:
+ self.backpixmap.copy_area(self.gc, image, x1, y1, w1, h1, x, y)
+ else:
+ self.backpixmap.copy_area(self.gc_and, image.mask,
+ x1, y1, w1, h1, x, y)
+ self.backpixmap.copy_area(self.gc_or, image,
+ x1, y1, w1, h1, x, y)
+
+ def flip(self):
+ self.win.copy_area(self.gc, self.backpixmap,
+ 0, 0, self.width, self.height, 0, 0)
+ self.dpy.flush()
+ self.readXevents()
+
+ def close(self):
+ self.dpy.close()
+
+ def clear(self):
+ self.backpixmap.fill_rectangle(self.gc, 0, 0, self.width, self.height)
+
+ def readXevents(self):
+ n = self.dpy.pending_events()
+ if n:
+ for i in range(n):
+ event = self.dpy.next_event()
+ if event.type == X.KeyPress or event.type == X.KeyRelease:
+ self.keyev.append((event.detail, event.type))
+ elif event.type == X.ButtonPress:
+ self.mouseev.append((event.event_x, event.event_y))
+ elif event.type == X.MotionNotify:
+ self.motionev = event.event_x, event.event_y
+ elif event.type == X.DestroyNotify:
+ raise SystemExit
+ self.readXevents()
+
+ def enable_event(self, mask):
+ self.selectinput |= mask
+ self.win.change_attributes(event_mask=self.selectinput)
+
+ def keyevents(self):
+ if not (self.selectinput & X.KeyReleaseMask):
+ self.enable_event(X.KeyPressMask | X.KeyReleaseMask)
+ self.readXevents()
+ result = self.keyev
+ self.keyev = []
+ return result
+
+ def mouseevents(self):
+ if not (self.selectinput & X.ButtonPressMask):
+ self.enable_event(X.ButtonPressMask)
+ result = self.mouseev
+ self.mouseev = []
+ return result
+
+ def pointermotion(self):
+ result = self.motionev
+ self.motionev = None
+ return result
+
+ def has_sound(self):
+ return 0
+
+ def selectlist(self):
+ from socket import fromfd, AF_INET, SOCK_STREAM
+ return [fromfd(self.dpy.fileno(), AF_INET, SOCK_STREAM)]
+
+ def taskbar(self, (x, y, w, h)):
+ for j in range(y, y+h, 32):
+ for i in range(x, x+w, 32):
+ self.putppm(i, j, self.taskbkgnd,
+ (0, 0, x+w-i, y+h-j))
+
+
+def long2string(bits, strlen):
+ return ''.join([chr((bits>>n)&0xFF) for n in range(0, 8*strlen, 8)])