diff options
Diffstat (limited to 'display/dpy_gtk.py')
-rw-r--r-- | display/dpy_gtk.py | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/display/dpy_gtk.py b/display/dpy_gtk.py new file mode 100644 index 0000000..7b73516 --- /dev/null +++ b/display/dpy_gtk.py @@ -0,0 +1,204 @@ + + ################################################ +## GTK-based implementation of xshm ## +################################################ + +import os, sys, math +from modes import KeyPressed, KeyReleased +import caching + +def import_trickery(): + global gtk, gdk + argv = sys.argv[:] + del sys.argv[1:] + import gtk + from gtk import gdk + sys.argv[:] = argv +import_trickery() + + +class Display: + + def __init__(self, width, height, title, zoom="100"): + if zoom.endswith('%'): + zoom = zoom[:-1] + scale = float(zoom) / 100.0 + iscale = int(scale+0.001) + if abs(scale - iscale) < 0.002: + scale = iscale + self.scale = scale + + self.width = int(width * scale) + self.height = int(height * scale) + self.tempppmfile = caching.mktemp('.ppm') + + # create a top level window + w = self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) + w.connect("destroy", lambda w: sys.exit()) + w.connect("key-press-event", self.key_press_event) + w.connect("key-release-event", self.key_release_event) + w.connect("motion-notify-event", self.motion_notify_event) + w.connect("button-press-event", self.button_press_event) + w.add_events(gdk.KEY_PRESS_MASK | + gdk.POINTER_MOTION_MASK | + gdk.BUTTON_PRESS_MASK) + w.resize(self.width, self.height) + w.set_title(title) + w.show() + + self.offscreen = gtk.create_pixmap(w.window, self.width, self.height) + self.gc = gdk.gc_new(w.window) + self.gc.set_rgb_fg_color(gdk.color_parse('#000000')) + + self.events_key = [] + self.events_mouse = [] + self.event_motion = None + + pixel = "\x00\x00\x80" + hole = "\x01\x01\x01" + pb = self.pixmap(32, 32, ((pixel+hole)*16 + (hole+pixel)*16) * 16, 0x010101) + self.taskbkgnd = self.renderpixbuf(pb) + + def taskbar(self, (x, y, w, h)): + scale = self.scale + x2 = x+w + y2 = y+h + x, y, x2, y2 = int(x*scale), int(y*scale), int(x2*scale), int(y2*scale) + pixmap, gc, ignored = self.taskbkgnd + for j in range(y, y2, 32): + for i in range(x, x2, 32): + gc.set_clip_origin(i, j) + self.offscreen.draw_drawable(gc, pixmap, 0, 0, + i, j, x2-i, y2-j) + + def pixmap(self, w, h, data, colorkey=-1): + filename = self.tempppmfile + f = open(filename, 'wb') + print >> f, 'P6' + print >> f, w, h + print >> f, 255 + f.write(data) + f.close() + pb = gdk.pixbuf_new_from_file(filename) + if colorkey >= 0: + pb = pb.add_alpha(1, chr(colorkey >> 16), + chr((colorkey >> 8) & 0xFF), + chr(colorkey & 0xFF)) + if self.scale == 1: + return self.renderpixbuf((pb,)) + else: + return (pb,) + + def renderpixbuf(self, input): + if len(input) == 3: + return input + pb, = input + pixmap, mask = pb.render_pixmap_and_mask() + if mask is not None: + gc = gdk.gc_new(self.window.window) + gc.set_clip_mask(mask) + return (pixmap, gc, mask) + else: + return (pixmap, self.gc, None) + + def getopticon(self, input, (x, y, w, h), ignored_alpha=255): + if len(input) == 3: + return None + pb, = input + scale = self.scale + newpb = gdk.Pixbuf("rgb", 1, 8, w, h) + newpb.fill(0) + pb.copy_area(x, y, w, h, newpb, 0, 0) + newpb = newpb.scale_simple(int(w*scale), int(h*scale), + gdk.INTERP_HYPER) + if newpb is None: + return None, None, None + else: + return self.renderpixbuf((newpb,)) + + def getppm(self, (x, y, w, h), int=int, ceil=math.ceil): + scale = self.scale + if isinstance(scale, int): + x *= scale + y *= scale + w *= scale + h *= scale + else: + w = int(ceil((x+w)*scale)) + h = int(ceil((y+h)*scale)) + x = int(x*scale) + y = int(y*scale) + w -= x + h -= y + bkgnd = gtk.create_pixmap(self.window.window, w, h) + bkgnd.draw_drawable(self.gc, self.offscreen, x, y, 0, 0, w, h) + return bkgnd, self.gc, None + + def putppm(self, x, y, (pixmap, gc, ignored), rect=None, int=int): + if pixmap is None: + return + scale = self.scale + if rect is None: + srcx = srcy = 0 + w = h = 4095 + else: + srcx, srcy, w, h = rect + x = int(x*scale) + y = int(y*scale) + if gc is not self.gc: + gc.set_clip_origin(x-srcx, y-srcy) + self.offscreen.draw_drawable(gc, pixmap, srcx, srcy, x, y, w, h) + + def flip(self): + self.window.window.draw_drawable(self.gc, self.offscreen, + 0, 0, 0, 0, self.width, self.height) + gdk.flush() + self.events_poll() + + def close(self): + self.window.destroy() + + def clear(self): + self.offscreen.draw_rectangle(self.gc, 1, + 0, 0, self.width, self.height) + + def events_poll(self): + while gtk.events_pending(): + gtk.main_iteration() + + def key_press_event(self, window, event): + self.events_key.append((event.keyval, KeyPressed)) + + def key_release_event(self, window, event): + self.events_key.append((event.keyval, KeyReleased)) + + def motion_notify_event(self, window, event): + self.event_motion = (int(event.x/self.scale), int(event.y/self.scale)) + + def button_press_event(self, window, event): + self.events_mouse.append((int(event.x/self.scale), int(event.y/self.scale))) + + def keyevents(self): + self.events_poll() + result = self.events_key + self.events_key = [] + return result + + def pointermotion(self): + result = self.event_motion + self.event_motion = None + return result + + def mouseevents(self): + self.events_poll() + result = self.events_mouse + self.events_mouse = [] + return result + + def selectlist(self): + return [] + + +def htmloptionstext(nameval): + return 'Scale image by <%s size=5>%%' % ( + nameval('text', 'zoom', default='100')) |