Skip to content

Instantly share code, notes, and snippets.

@olymk2
Last active December 19, 2015 14:22
Show Gist options
  • Select an option

  • Save olymk2/2fca8ec69e25622fd03d to your computer and use it in GitHub Desktop.

Select an option

Save olymk2/2fca8ec69e25622fd03d to your computer and use it in GitHub Desktop.
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