Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use python xlib to generate a single keypress?

Tags:

python

xlib

I want to make a very simple python 3 script that will generate a single keypress (F15). I don't want to use a bunch of libraries to do this as I only need one key to be pressed and don't need support for the whole keyboard. I know I need to use KeyPress and KeyRelease in order to generate a keyboard event. I'm just not sure where exactly to start and the documentation is a little confusing.

http://tronche.com/gui/x/xlib/events/keyboard-pointer/keyboard-pointer.html http://python-xlib.sourceforge.net/?page=documentation

like image 981
Dolores Avatar asked Apr 14 '15 22:04

Dolores


1 Answers

I'll use ctypes to show you how it could work, but porting it to python-xlib should be straightforward. So lets start with loading the library:

import ctypes
X11 = ctypes.CDLL("libX11.so")

and defining the structures needed:

class Display(ctypes.Structure):
    """ opaque struct """

class XKeyEvent(ctypes.Structure):
    _fields_ = [
            ('type', ctypes.c_int),
            ('serial', ctypes.c_ulong),
            ('send_event', ctypes.c_int),
            ('display', ctypes.POINTER(Display)),
            ('window', ctypes.c_ulong),
            ('root', ctypes.c_ulong),
            ('subwindow', ctypes.c_ulong),
            ('time', ctypes.c_ulong),
            ('x', ctypes.c_int),
            ('y', ctypes.c_int),
            ('x_root', ctypes.c_int),
            ('y_root', ctypes.c_int),
            ('state', ctypes.c_uint),
            ('keycode', ctypes.c_uint),
            ('same_screen', ctypes.c_int),
        ]

class XEvent(ctypes.Union):
    _fields_ = [
            ('type', ctypes.c_int),
            ('xkey', XKeyEvent),
            ('pad', ctypes.c_long*24),
        ]

X11.XOpenDisplay.restype = ctypes.POINTER(Display)

Now we just need to send the event to the root window:

display = X11.XOpenDisplay(None)
key = XEvent(type=2).xkey #KeyPress
key.keycode = X11.XKeysymToKeycode(display, 0xffcc) #F15
key.window = key.root = X11.XDefaultRootWindow(display)
X11.XSendEvent(display, key.window, True, 1, ctypes.byref(key))
X11.XCloseDisplay(display)

This minimal example worked well for me (just using F2 instead). The same can be done to send a KeyRelease event. If a special window is to be targeted, key.window should be set appropriately.

I'm not sure, if it's necessary to use the XEvent union, since it'd worked with the XKeyEvent all alone for me, but it's better to be safe.

like image 56
tynn Avatar answered Oct 01 '22 17:10

tynn