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()