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

1

6

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

Frasco answered 14/4, 2015 at 22:8 Comment(0)
Y
5

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.

Yachtsman answered 16/5, 2015 at 22:6 Comment(1)
this sadly does not seem to work for me... ctypes seem to be finding the library in the right path, but something is failing silently unfortunatelyLeoni

© 2022 - 2024 — McMap. All rights reserved.