from ctypes import *
import ctypes.util
import sys, weakref
libX11_name = ctypes.util.find_library("X11")
if not libX11_name:
raise Exception("libX11 not found")
X11 = ctypes.CDLL(libX11_name)
Xwrap = ctypes.CDLL('./libXwrap.so')
XID = c_ulong
P_XDisplay = c_void_p
XGC = c_void_p
XWindow = XID
XTime = c_ulong
Bool = c_int
XDrawable = XID
XAtom = XID
XColormap = XID
XStatus = c_int
class XKeyEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
('root', XWindow),
('subwindow', XWindow),
('time', XTime),
('x', c_int),
('y', c_int),
('x_root', c_int),
('y_root', c_int),
('state', c_uint),
('keycode', c_uint),
('same_screen', Bool),
]
class XButtonEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
('root', XWindow),
('subwindow', XWindow),
('time', XTime),
('x', c_int),
('y', c_int),
('x_root', c_int),
('y_root', c_int),
('state', c_uint),
('button', c_uint),
('same_screen', Bool),
]
class XMotionEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
('root', XWindow),
('subwindow', XWindow),
('time', XTime),
('x', c_int),
('y', c_int),
('x_root', c_int),
('y_root', c_int),
('state', c_uint),
('is_hint', c_byte),
('same_screen', Bool),
]
class XCrossingEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
('root', XWindow),
('subwindow', XWindow),
('time', XTime),
('x', c_int),
('y', c_int),
('x_root', c_int),
('y_root', c_int),
('mode', c_int),
('detail', c_int),
('same_screen', Bool),
('focus', Bool),
('state', c_uint),
]
class XFocusChangeEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
('mode', c_int),
('detail', c_int),
]
class XKeymapEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
('key_vector', c_byte * 32),
]
class XExposeEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
('x', c_int),
('y', c_int),
('width', c_int),
('height', c_int),
('count', c_int),
]
class XGraphicsExposeEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('drawable', XDrawable),
('x', c_int),
('y', c_int),
('width', c_int),
('height', c_int),
('count', c_int),
('major_code', c_int),
('minor_code', c_int),
]
class XNoExposeEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('drawable', XDrawable),
('major_code', c_int),
('minor_code', c_int),
]
class XVisibilityEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
('state', c_int),
]
class XCreateWindowEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('parent', XWindow),
('window', XWindow),
('x', c_int),
('y', c_int),
('width', c_int),
('height', c_int),
('border_width', c_int),
('override_redirect', Bool),
]
class XDestroyWindowEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('event', XWindow),
('window', XWindow),
]
class XUnmapEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('event', XWindow),
('window', XWindow),
('from_configure', Bool),
]
class XMapEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('event', XWindow),
('window', XWindow),
('override_redirect', Bool),
]
class XMapRequestEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('parent', XWindow),
('window', XWindow),
]
class XReparentEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('event', XWindow),
('window', XWindow),
('parent', XWindow),
('x', c_int),
('y', c_int),
('override_redirect', Bool),
]
class XConfigureEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('event', XWindow),
('window', XWindow),
('x', c_int),
('y', c_int),
('width', c_int),
('height', c_int),
('border_width', c_int),
('above', XWindow),
('override_redirect', Bool),
]
class XGravityEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('event', XWindow),
('window', XWindow),
('x', c_int),
('y', c_int),
]
class XResizeRequestEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
('width', c_int),
('height', c_int),
]
class XConfigureRequestEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('parent', XWindow),
('window', XWindow),
('x', c_int),
('y', c_int),
('width', c_int),
('height', c_int),
('border_width', c_int),
('above', XWindow),
('detail', c_int),
('value_mask', c_ulong),
]
class XCirculateEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('event', XWindow),
('window', XWindow),
('place', c_int),
]
class XCirculateRequestEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('parent', XWindow),
('window', XWindow),
('place', c_int),
]
class XPropertyEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
('atom', XAtom),
('time', XTime),
('state', c_int),
]
class XSelectionClearEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
('selection', XAtom),
('time', XTime),
]
class XSelectionRequestEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('owner', XWindow),
('requestor', XWindow),
('selection', XAtom),
('target', XAtom),
('property', XAtom),
('time', XTime),
]
class XSelectionEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('requestor', XWindow),
('selection', XAtom),
('target', XAtom),
('property', XAtom),
('time', XTime),
]
class XColormapEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
('colormap', XColormap),
('new', Bool),
('state', c_int),
]
class XClientMessageEvent_data(Union):
_fields_ = [
('b', c_byte * 20),
('s', c_short * 10),
('l', c_long * 5),
]
class XClientMessageEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
('message_type', XAtom),
('format', c_int),
('data', XClientMessageEvent_data),
]
class XMappingEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
('request', c_int),
('first_keycode', c_int),
('count', c_int),
]
class XErrorEvent(Structure):
_fields_ = [
('type', c_int),
('display', P_XDisplay),
('resourceid', XID),
('serial', c_ulong),
('error_code', c_ubyte),
('request_code', c_ubyte),
('minor_code', c_ubyte),
]
class XAnyEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('window', XWindow),
]
class XGenericEvent(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('extension', c_int),
('evtype', c_int),
]
class XGenericEventCookie(Structure):
_fields_ = [
('type', c_int),
('serial', c_ulong),
('send_event', Bool),
('display', P_XDisplay),
('extension', c_int),
('evtype', c_int),
('cookie', c_uint),
('data', c_void_p),
]
class XEvent(Union):
_fields_ = [
('type', c_int),
('xany', XAnyEvent),
('xkey', XKeyEvent),
('xbutton', XButtonEvent),
('xmotion', XMotionEvent),
('xcrossing', XCrossingEvent),
('xfocus', XFocusChangeEvent),
('xexpose', XExposeEvent),
('xgraphicsexpose', XGraphicsExposeEvent),
('xnoexpose', XNoExposeEvent),
('xvisibility', XVisibilityEvent),
('xcreatewindow', XCreateWindowEvent),
('xdestroywindow', XDestroyWindowEvent),
('xunmap', XUnmapEvent),
('xmap', XMapEvent),
('xmaprequest', XMapRequestEvent),
('xreparent', XReparentEvent),
('xconfigure', XConfigureEvent),
('xgravity', XGravityEvent),
('xresizerequest', XResizeRequestEvent),
('xconfigurerequest', XConfigureRequestEvent),
('xcirculate', XCirculateEvent),
('xcirculaterequest', XCirculateRequestEvent),
('xproperty', XPropertyEvent),
('xselectionclear', XSelectionClearEvent),
('xselectionrequest', XSelectionRequestEvent),
('xselection', XSelectionEvent),
('xcolormap', XColormapEvent),
('xclient', XClientMessageEvent),
('xmapping', XMappingEvent),
('xerror', XErrorEvent),
('xkeymap', XKeymapEvent),
('xgeneric', XGenericEvent),
('xcookie', XGenericEventCookie),
('pad', c_long * 24),
]
# Event numbers
KeyPress = 2
KeyRelease = 3
ButtonPress = 4
ButtonRelease = 5
MotionNotify = 6
EnterNotify = 7
LeaveNotify = 8
FocusIn = 9
FocusOut = 10
KeymapNotify = 11
Expose = 12
GraphicsExpose = 13
NoExpose = 14
VisibilityNotify = 15
CreateNotify = 16
DestroyNotify = 17
UnmapNotify = 18
MapNotify = 19
MapRequest = 20
ReparentNotify = 21
ConfigureNotify = 22
ConfigureRequest = 23
GravityNotify = 24
ResizeRequest = 25
CirculateNotify = 26
CirculateRequest = 27
PropertyNotify = 28
SelectionClear = 29
SelectionRequest = 30
SelectionNotify = 31
ColormapNotify = 32
ClientMessage = 33
MappingNotify = 34
GenericEvent = 35
# Event masks
NoEventMask = 0
KeyPressMask = 1 << 0
KeyReleaseMask = 1 << 1
ButtonPressMask = 1 << 2
ButtonReleaseMask = 1 << 3
EnterWindowMask = 1 << 4
LeaveWindowMask = 1 << 5
PointerMotionMask = 1 << 6
PointerMotionHintMask = 1 << 7
Button1MotionMask = 1 << 8
Button2MotionMask = 1 << 9
Button3MotionMask = 1 << 10
Button4MotionMask = 1 << 11
Button5MotionMask = 1 << 12
ButtonMotionMask = 1 << 13
KeymapStateMask = 1 << 14
ExposureMask = 1 << 15
VisibilityChangeMask = 1 << 16
StructureNotifyMask = 1 << 17
ResizeRedirectMask = 1 << 18
SubstructureNotifyMask = 1 << 19
SubstructureRedirectMask = 1 << 20
FocusChangeMask = 1 << 21
PropertyChangeMask = 1 << 22
ColormapChangeMask = 1 << 23
OwnerGrabButtonMask = 1 << 24
def declare(lib, ret, name, *args):
f = getattr(lib, name)
f.argtypes = args
f.restype = ret
declare(X11, P_XDisplay, 'XOpenDisplay', c_char_p)
declare(X11, c_int, 'XCloseDisplay', P_XDisplay)
declare(X11, XWindow, 'XCreateSimpleWindow', P_XDisplay, XWindow,
c_int, c_int, c_uint, c_uint,
c_uint, c_ulong, c_ulong)
declare(X11, c_int, 'XDestroyWindow', P_XDisplay, XWindow)
declare(X11, c_int, 'XMapWindow', P_XDisplay, XWindow)
declare(X11, c_int, 'XUnmapWindow', P_XDisplay, XWindow)
declare(X11, c_int, 'XNextEvent', P_XDisplay, POINTER(XEvent))
declare(X11, XAtom, 'XInternAtom', P_XDisplay, c_char_p, Bool)
declare(X11, XStatus, 'XSetWMProtocols', P_XDisplay, XWindow, POINTER(XAtom), c_int)
declare(X11, c_int, 'XSelectInput', P_XDisplay, XWindow, c_long)
declare(Xwrap, c_int, 'Xw_DefaultScreen', P_XDisplay)
declare(Xwrap, XGC, 'Xw_DefaultGC', P_XDisplay, c_int)
declare(Xwrap, XWindow, 'Xw_RootWindow', P_XDisplay, c_int)
declare(Xwrap, c_ulong, 'Xw_BlackPixel', P_XDisplay, c_int)
declare(Xwrap, c_ulong, 'Xw_WhitePixel', P_XDisplay, c_int)
class Display(object):
def __init__(self, name=None):
self.open = False
self._d = X11.XOpenDisplay(None)
if not self._d:
raise Exception("Cannot open display: %s" % name)
self.wm_delete_window = X11.XInternAtom(
self._d,
"WM_DELETE_WINDOW",
False)
self.open = True
def close(self):
if self.open:
X11.XCloseDisplay(self._d)
self.open = False
def __del__(self):
if self.open:
sys.stderr.write("WARNING: Display wasn't closed")
self.close()
def run(self):
"""Run event loop"""
e = XEvent()
while True:
X11.XNextEvent(self._d, pointer(e))
print "Event type %d" % e.type
if e.type == ClientMessage:
if e.xclient.data.l[0] == self.wm_delete_window:
# Close window
return
class Window(object):
def __init__(self, display, x=10, y=10, width=300, height=300):
self.open = False
self.x = x
self.y = y
self.width = width
self.height = height
self.display = weakref.ref(display)
self._s = Xwrap.Xw_DefaultScreen(display._d)
self._gc = Xwrap.Xw_DefaultGC(display._d, self._s)
self._w = X11.XCreateSimpleWindow(
display._d,
Xwrap.Xw_RootWindow(display._d, self._s),
x, y, width, height, 1,
Xwrap.Xw_BlackPixel(display._d, self._s), # border
Xwrap.Xw_WhitePixel(display._d, self._s), # background
)
atom = XAtom(display.wm_delete_window)
if not X11.XSetWMProtocols(
display._d,
self._w,
pointer(atom),
1
):
raise Exception("XSetWMProtocols failed")
X11.XSelectInput(display._d, self._w,
ExposureMask | KeyPressMask | StructureNotifyMask
| PointerMotionMask | ButtonPressMask | ButtonReleaseMask)
self.open = True
def show(self):
X11.XMapWindow(self.display()._d, self._w)
def hide(self):
X11.XUnmapWindow(self.display()._d, self._w)
def close(self):
if self.open:
X11.XDestroyWindow(self.display()._d, self._w)
self.open = False
def __del__(self):
if self.open:
sys.stderr.write("WARNING: Window wasn't closed")
self.close()
d = Display()
w = Window(d)
w.show()
d.run()
w.close()
d.close()