summaryrefslogtreecommitdiff
path: root/display/dpy_gtk.py
diff options
context:
space:
mode:
Diffstat (limited to 'display/dpy_gtk.py')
-rw-r--r--display/dpy_gtk.py204
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'))