################################################ ## pygame-based implementation of xshm ## ################################################ import os, sys import pygame from pygame.locals import * from display.modes import KeyPressed, KeyReleased # print("dpy_pygame", file=sys.stderr ) class Display: musthidemouse = 0 mousevisible = 1 def __init__(self, width, height, title, transparency='yes', fullscreen='no', zoom='100%', smooth='yes', smoothfast='yes'): self.use_transparency = not transparency.startswith('n') self.use_fullscreen = fullscreen.startswith('y') 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.smooth = smooth.startswith('y') self.smoothfast = smoothfast.startswith('y') # Initialize pygame pygame.init() # Set the display mode winstyle = HWSURFACE if self.use_fullscreen: winstyle |= FULLSCREEN bestdepth = pygame.display.mode_ok((int(width * self.scale), int(height * self.scale)), winstyle, 32) self.screen = pygame.display.set_mode((int(width * self.scale), int(height * self.scale)), winstyle, bestdepth) self.offscreen = pygame.Surface((width, height)) #decorate the game window pygame.display.set_caption(title) #pygame.mouse.set_visible(0) self.tbcache = None, None self.events_key = [] self.events_mouse = [] self.prevposition = None EVENT_HANDLERS[KEYDOWN] = self.keydown_handler EVENT_HANDLERS[KEYUP] = self.keyup_handler EVENT_HANDLERS[MOUSEBUTTONDOWN] = self.mousebuttondown_handler def keydown_handler(self, e): if e.key == K_ESCAPE and self.use_fullscreen: raise SystemExit # ESC to exit the game if full-screen self.showmouse(not self.musthidemouse) self.events_key.append((e.key, KeyPressed)) del self.events_key[:-16] def keyup_handler(self, e): self.events_key.append((e.key, KeyReleased)) del self.events_key[:-16] def mousebuttondown_handler(self, e): self.showmouse(1) self.events_mouse.append(self.fixpos(e.pos)) del self.events_mouse[:-8] def pixmap(self, w, h, data, colorkey=-1): print(f"pixmap type(data) = {type(data)}, data={data[:128]}", file=sys.stderr) print(f"pixmap len(data) = {len(data)}, (h, w) = {(h, w)}", file=sys.stderr) img = pygame.image.fromstring(data[:w*h*3], (w, h), "RGB") if colorkey >= 0: r = colorkey & 0xFF g = (colorkey >> 8) & 0xFF b = (colorkey >> 16) & 0xFF img.set_colorkey([r, g, b]) return img # not optimized -- must use getopticon() def getopticon(self, pixmap, rect, alpha=255): if not self.use_transparency: alpha = 255 img = pixmap.subsurface(rect) colorkey = pixmap.get_colorkey() if alpha == 255 and not colorkey: return img.convert(self.offscreen) else: if colorkey: img.set_colorkey(colorkey, RLEACCEL) if alpha < 255: img.set_alpha(alpha, RLEACCEL) img = img.convert_alpha(self.offscreen) img.set_alpha(255, RLEACCEL) return img ## def vflipppm(self, img): ## w, h = img.get_size() ## colorkey = img.get_colorkey() ## data = pygame.image.tostring(img, "RGB", 1) ## flipimg = pygame.image.fromstring(data, (w, h), "RGB") ## flipimg.set_colorkey(colorkey, RLEACCEL) ## return flipimg, h def getppm(self, rect): bkgnd = pygame.Surface(rect[2:]) bkgnd.blit(self.offscreen, (0, 0), rect) return bkgnd def putppm(self, x, y, bitmap, rect=None): if rect: self.offscreen.blit(bitmap, (x, y), rect) else: self.offscreen.blit(bitmap, (x, y)) def flip(self): offscreen = self.offscreen if self.scale != 1: w, h = offscreen.get_size() w = int(w * self.scale) h = int(h * self.scale) if self.scale == 2 and self.smoothfast: offscreen = pygame.transform.scale2x(offscreen) elif self.smooth: offscreen = pygame.transform.smoothscale(offscreen, (w, h)) else: offscreen = pygame.transform.scale(offscreen, (w, h)) self.screen.blit(offscreen, (0, 0)) pygame.display.flip() events_dispatch() def close(self): self.showmouse(1) pygame.display.quit() def clear(self): self.offscreen.fill([0,0,0,]) def fixpos(self, xxx_todo_changeme): (x, y) = xxx_todo_changeme if self.scale != 1: x = int(x / self.scale) y = int(y / self.scale) return (x, y) def events_poll(self): while 1: e = pygame.event.poll() if e.type == NOEVENT: break elif e.type == KEYDOWN: self.events_key.append((e.key, KeyPressed)) del self.events_key[:-16] elif e.type == KEYUP: self.events_key.append((e.key, KeyReleased)) del self.events_key[:-16] elif e.type == MOUSEBUTTONDOWN: self.events_mouse.append(self.fixpos(e.pos)) del self.events_mouse[:-8] elif e.type == ENDMUSICEVENT: self.next_music() elif e.type == QUIT: raise SystemExit def keyevents(self): events_dispatch() events = self.events_key self.events_key = [] return events def pointermotion(self): position = pygame.mouse.get_pos() if position != self.prevposition: self.showmouse(1) self.prevposition = position return self.fixpos(position) else: return None def mouseevents(self): events_dispatch() events = self.events_mouse self.events_mouse = [] return events def selectlist(self): return [] def taskbar(self, xxx_todo_changeme1): (x, y, w, h) = xxx_todo_changeme1 tbs, tbh = self.tbcache if tbh != h: tbs = pygame.Surface((32, h)).convert_alpha(self.offscreen) alpha_f = 256.0 / h for j in range(h): tbs.fill((128, 128, 255, int(j*alpha_f)), (0, j, 32, 1)) self.tbcache = tbs, h for i in range(x, x+w, 32): dw = x+w-i if dw < 32: self.offscreen.blit(tbs, (i, y), (0, 0, dw, h)) else: self.offscreen.blit(tbs, (i, y)) def settaskbar(self, tb_visible): self.showmouse(1) self.musthidemouse = not tb_visible # and self.use_fullscreen def showmouse(self, v): if v != self.mousevisible: self.mousevisible = v pygame.mouse.set_visible(v) def quit_handler(e): raise SystemExit EVENT_HANDLERS = { QUIT: quit_handler, } def events_dispatch(handlers = EVENT_HANDLERS): while 1: e = pygame.event.poll() if e.type == NOEVENT: break elif e.type in handlers: handlers[e.type](e) def htmloptionstext(nameval): return ''' <%s> Full Screen (Esc key to exit)<%s>
<%s> Draw slightly transparent bubbles<%s>
Scale image by <%s size=5>%%
<%s> Smoothed scaled image<%s>
<%s> Semi-smoothed scaled image (for 200%% only)<%s>
''' % (nameval("checkbox", "fullscreen", "yes", default="no"), nameval("hidden", "fullscreen", "no"), nameval("checkbox", "transparency", "yes", default="yes"), nameval("hidden", "transparency", "no"), nameval("text", "zoom", default="100"), nameval("checkbox", "smooth", "yes", default="yes"), nameval("hidden", "smooth", "no"), nameval("checkbox", "smoothfast", "yes", default="no"), nameval("hidden", "smoothfast", "no"))