Last active
December 19, 2015 14:22
-
-
Save olymk2/2fca8ec69e25622fd03d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import sys | |
| import xcb | |
| from xcb.xproto import * | |
| import xcb.xproto as xproto | |
| import xcb.render | |
| import xcb.composite | |
| from PIL import Image | |
| from lxml import etree | |
| from StringIO import StringIO | |
| import struct | |
| # helper to load a png | |
| class image_resource: | |
| """ Useful code for handling png to pixmap conversion""" | |
| filename = '' | |
| width = 0 | |
| height = 0 | |
| data = '' | |
| xformat = 2 # XYBitmap = 0, XYPixmap = 1, ZPixmap = 2 | |
| def __init__(self, filename, new_width=None, new_height=None, colour=None): | |
| """ load image and convert to RGBA then convert to a string if there is a colour | |
| create an image with a solid background and paste the loaded image on top to fix transparency. | |
| we could adjust this to paste the image on to an existing window border image at some point | |
| convert the string characters to there integer counter parts ready for the xserver to use""" | |
| self.filename = filename | |
| with open(filename, 'rb') as fp: | |
| img = Image.open(fp) | |
| # convert for use with xcb | |
| self.width, self.height = img.size | |
| self.data = [ord(s) for s in img.convert('RGBA').tostring('raw', 'BGRA')] | |
| del(img) | |
| #https://magcius.github.io/xplain/article/composite.html | |
| #https://www.talisman.org/~erlkonig/misc/x11-composite-tutorial/ | |
| #~ http://stackoverflow.com/questions/16146377/xrender-display-pictures-from-disk-application-generated-images | |
| #~ * create pixmap | |
| #~ * transfer image data to server using XPutImage | |
| #~ * create Picture object associated with your pixmap | |
| #~ * create Picture object associated with your window | |
| #~ * compose them using XRenderComposite | |
| def sdir(dictionary, search='', args=False): | |
| import inspect | |
| for item, item2 in [(item.lower(), item) for item in dir(dictionary)]: | |
| if search in item: | |
| if args: | |
| print item2 | |
| if not item2.startswith('__'): | |
| print(inspect.getargspec(getattr(dictionary, item2))) | |
| print getattr(dictionary, item2).func_defaults | |
| print '%s - %s' % (item2, getattr(dictionary, item2).func_code.co_varnames) | |
| else: | |
| print item2 | |
| def find_format(screen): | |
| for d in screen.depths: | |
| if d.depth == depth: | |
| print d.depth | |
| for v in d.visuals: | |
| if v.visual == visual: | |
| return v.format | |
| raise Exception("Failed to find an appropriate Render pictformat!") | |
| def startup(): | |
| canvas = setup.roots[0] | |
| white = setup.roots[0].white_pixel | |
| blue = conn.core.AllocColor(canvas.default_colormap, 0x0000, 0x0000, 0xFFFF).reply().pixel | |
| cookie = conn.render.QueryPictFormats() | |
| reply = cookie.reply() | |
| visual_format = find_format(reply.screens[0]) | |
| conn.core.CreateColormapChecked(xproto.ColormapAlloc._None, colourmap, window, visual_format) | |
| # setup a new window | |
| conn.core.CreateWindow( | |
| depth=depth, wid=window, parent=root, | |
| x=0, y=0, width=640, height=480, border_width=0, | |
| _class=WindowClass.InputOutput, | |
| visual=visual, | |
| value_mask=CW.BackPixel | CW.EventMask, | |
| value_list = [ blue, EventMask.ButtonPress | EventMask.EnterWindow | EventMask.LeaveWindow | EventMask.Exposure ]) | |
| conn.composite.RedirectWindow(window=window, update=xcb.composite.Redirect.Automatic) | |
| #~ conn.composite.RedirectSubwindows(window=window, update=xcb.composite.Redirect.Automatic) | |
| # dont think this should be needed | |
| _NET_WM_WINDOW_OPACITY = 528 | |
| buf = struct.pack('I', _NET_WM_WINDOW_OPACITY) | |
| _NET_WM_WINDOW_OPACITY = conn.core.InternAtom(True, len('_NET_WM_WINDOW_OPACITY'), '_NET_WM_WINDOW_OPACITY').reply() | |
| conn.core.ChangeProperty(xproto.PropMode.Replace, window, _NET_WM_WINDOW_OPACITY.atom, xproto.Atom.STRING, 0.5, 1, buf) | |
| #~ conn.core.ChangeProperty(PropMode.Replace, window, xcb.XA_WM_NAME, xcb.XA_STRING, 8, len('transparent example'), 'transparent example') | |
| # | |
| transparent_image = image_resource('transparency.png') | |
| # create a new pixmap and graphics context to copy the image data into | |
| pixmap = conn.generate_id() | |
| conn.core.CreatePixmap(24, pixmap, window, transparent_image.width, transparent_image.height) | |
| gc = conn.generate_id() | |
| conn.core.CreateGC( | |
| gc, pixmap, xproto.GC.Background | xproto.GC.Foreground, | |
| [blue, blue]) | |
| result = conn.core.PutImageChecked( | |
| format=transparent_image.xformat, | |
| drawable=pixmap, | |
| gc=gc, | |
| width=transparent_image.width, height=transparent_image.height, | |
| dst_x=0, dst_y=0, | |
| left_pad=0, depth=24, | |
| data_len=len(transparent_image.data), data=transparent_image.data) | |
| print visual_format | |
| # Now create a picture of that pixmap. | |
| #~ root_buffer_picture = conn.generate_id() | |
| #~ test_picture = root_buffer_picture | |
| conn.render.CreatePicture( | |
| pid=root_buffer_picture, | |
| drawable=pixmap, | |
| format=visual_format, | |
| value_mask=0, | |
| value_list=[] | |
| ) | |
| conn.render.CreatePicture( | |
| pid=window_picture, | |
| drawable=window, | |
| format=visual_format, | |
| value_mask=0, | |
| value_list=[] | |
| ) | |
| conn.core.FreePixmap(pixmap) | |
| conn.render.CreatePicture(pid, window, visual_format, 0, []) | |
| conn.core.MapWindow(window) | |
| conn.flush() | |
| def paint(): | |
| conn.core.ClearArea(False, window, 0, 0, 0, 0) | |
| for x in xrange(0, 7): | |
| for y in xrange(0, 5): | |
| rectangle = ((x + 1) * 24 + x * 64, (y + 1) * 24 + y * 64, 64, 64) | |
| color = (x * 65535 / 7, y * 65535 / 5, (x * y) * 65535 / 35, 65535) | |
| conn.render.FillRectangles(xcb.render.PictOp.Src, pid, color, 1, rectangle) | |
| conn.render.Composite(op=3, src=root_buffer_picture, mask=0, dst=window_picture, src_x=0, src_y=0, mask_x=0, mask_y=0, dst_x=0, dst_y=0, width=200, height=200); | |
| conn.flush() | |
| def run(): | |
| startup() | |
| print 'Click in window to exit.' | |
| while True: | |
| try: | |
| event = conn.wait_for_event() | |
| except xcb.ProtocolException, error: | |
| print "Protocol error %s received!" % error.__class__.__name__ | |
| break | |
| except: | |
| print "Unexpected error received: %s" % error.message | |
| break | |
| if isinstance(event, ExposeEvent): | |
| paint() | |
| elif isinstance(event, EnterNotifyEvent): | |
| print 'Enter (%d, %d)' % (event.event_x, event.event_y) | |
| elif isinstance(event, LeaveNotifyEvent): | |
| print 'Leave (%d, %d)' % (event.event_x, event.event_y) | |
| elif isinstance(event, ButtonPressEvent): | |
| print 'Button %d down' % event.detail | |
| break | |
| conn.disconnect() | |
| if __name__ == '__main__': | |
| conn = xcb.connect() | |
| conn.render = conn(xcb.render.key) | |
| conn.composite = conn(xcb.composite.key) | |
| setup = conn.get_setup() | |
| root = setup.roots[0].root | |
| depth = setup.roots[0].root_depth | |
| visual = setup.roots[0].root_visual | |
| colourmap = conn.generate_id() | |
| window = conn.generate_id() | |
| window_picture = conn.generate_id() | |
| pid = conn.generate_id() | |
| root_buffer_picture = conn.generate_id() | |
| png_picture = conn.generate_id() | |
| run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment

