Sending fake keypress events to an X11 window

This C++ example code will send a cursor-down event to the currently focussed window. It can easily be modified to send other key events. It would be a good starting point to write a virtual keyboard or remote control application.

// Send a fake keystroke event to an X window.
// by Adam Pierce - http://www.doctort.org/adam/
// This is public domain software. It is free to use by anyone for any purpose.

#include <X11/Xlib.h>
#include <X11/keysym.h>

// The key code to be sent.
// A full list of available codes can be found in /usr/include/X11/keysymdef.h
#define KEYCODE XK_Down

// Function to create a keyboard event
XKeyEvent createKeyEvent(Display *display, Window &win,
                           Window &winRoot, bool press,
                           int keycode, int modifiers)
{
   XKeyEvent event;

   event.display     = display;
   event.window      = win;
   event.root        = winRoot;
   event.subwindow   = None;
   event.time        = CurrentTime;
   event.x           = 1;
   event.y           = 1;
   event.x_root      = 1;
   event.y_root      = 1;
   event.same_screen = True;
   event.keycode     = XKeysymToKeycode(display, keycode);
   event.state       = modifiers;

   if(press)
      event.type = KeyPress;
   else
      event.type = KeyRelease;

   return event;
}

main()
{
// Obtain the X11 display.
   Display *display = XOpenDisplay(0);
   if(display == NULL)
      return -1;

// Get the root window for the current display.
   Window winRoot = XDefaultRootWindow(display);

// Find the window which has the current keyboard focus.
   Window winFocus;
   int    revert;
   XGetInputFocus(display, &winFocus, &revert);

// Send a fake key press event to the window.
   XKeyEvent event = createKeyEvent(display, winFocus, winRoot, true, KEYCODE, 0);
   XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);

// Send a fake key release event to the window.
   event = createKeyEvent(display, winFocus, winRoot, false, KEYCODE, 0);
   XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);

// Done.
   XCloseDisplay(display);
   return 0;
}

To compile it, you need to type this:

g++ -o XFakeKey XFakeKey.cpp -L/usr/X11R6/lib -lX11

30 thoughts on “Sending fake keypress events to an X11 window

  1. YES!!!

    Finally I found what I looked for (I almost 7 hours searching the web for this little example!).

    Adam Pierce – you are my hero!!!

    Thanks Thanks Thanks

    :) ;)

  2. Thank you all for the positive comments. I also spent hours trying to find something like this and ended up having to write it myself.

  3. Brilliant, I have thought for ages that there must be a way to do this programmatically but had real trouble finding it actually written out somewhere online.

    Thanks a lot.

  4. Excellent example. However, one thing should be noted:
    I found out you have to request the focus window for every new key event you send

    getfocus(), keypress(), keyrelease() will not work
    while
    getfocus(), keypress(), getfocus(), keyrelease() works perfectly.

  5. Try setting the “modifiers” parameter of the createKeyEvent function with values like XK_Shift_L or XK_Meta_L. See /usr/include/X11/keysymdef.h for a list of possible values.

  6. FYI for those who don’t know, you can run ‘xev’ in a terminal to get keycodes – it opens a small window while it runs, then information on all keypresses are output to the terminal. For example: I typed “hi”

    KeyPress event, serial 23, synthetic NO, window 0x4c00001,
    root 0×59, subw 0×0, time 153093161, (423,461), root:(424,491),
    state 0×10, keycode 43 (keysym 0×68, h), same_screen YES,
    XLookupString gives 1 bytes: (68) “h”
    XmbLookupString gives 1 bytes: (68) “h”
    XFilterEvent returns: False

    KeyRelease event, serial 26, synthetic NO, window 0x4c00001,
    root 0×59, subw 0×0, time 153093232, (423,461), root:(424,491),
    state 0×10, keycode 43 (keysym 0×68, h), same_screen YES,
    XLookupString gives 1 bytes: (68) “h”
    XFilterEvent returns: False

    KeyPress event, serial 26, synthetic NO, window 0x4c00001,
    root 0×59, subw 0×0, time 153093374, (423,461), root:(424,491),
    state 0×10, keycode 31 (keysym 0×69, i), same_screen YES,
    XLookupString gives 1 bytes: (69) “i”
    XmbLookupString gives 1 bytes: (69) “i”
    XFilterEvent returns: False

    KeyRelease event, serial 26, synthetic NO, window 0x4c00001,
    root 0×59, subw 0×0, time 153093434, (423,461), root:(424,491),
    state 0×10, keycode 31 (keysym 0×69, i), same_screen YES,
    XLookupString gives 1 bytes: (69) “i”
    XFilterEvent returns: False

    So, keycode 43 is ‘h’ and 31 is ‘i’ – *on my keyboard*. It may or may not be different for you.. I’m not really sure.

    In any case, this should help a lot. I’ve been having troubles with Super and CTRL getting stuck on this new laptop somehow, so maybe I can use this to force a key-release…

  7. Wow! Thanks Adam! This is invaluable. I just used XFakeKey to talk to my “headless firefox” inside of xvfb. The down clicks are working, the screenshots are changing!! Very exciting.

  8. This has got me one step closer. But what I need is to be able to do is set keyboard focus on an already open window (in this case firefox), and then hit a key. how do you change window focus? I’ve Googled and not found a simple way yet. Oh and I’m trying to do it in Ruby but if you point me to a lib or just a C example I’ll probly find a method to bind to it.
    Thanks and fine work Adam

  9. Thanks Adam!

    > But what I need is to be able to do is set keyboard focus
    Feel free to correct me, what I’m using now is:

    /*
    * Window_With_Name: routine to locate a window with a given name on a display.
    * If no window with the given name is found, 0 is returned.
    * If more than one window has the given name, the first
    * one found will be returned. Only top and its subwindows
    * are looked at. Normally, top should be the RootWindow.
    */
    Window
    Window_With_Name(Display *display, Window top, const char *name)
    {
    Window *children, dummy;
    unsigned int nchildren;
    unsigned int i;
    Window w=0;
    char *window_name;

    if (XFetchName(display, top, &window_name) && !strcmp(window_name, name))
    return(top);

    if (!XQueryTree(display, top, &dummy, &dummy, &children, &nchildren))
    return(0);

    for (i=0; i<nchildren; i++) {
    w = Window_With_Name(display, children[i], name);
    if (w)
    break;
    }
    if (children) XFree ((char *)children);
    return(w);
    }

    int
    main(int argc, char *argv[])
    {
    display = XOpenDisplay(0);
    if (!display)
    exit(EXIT_FAILURE);

    Window window_root = DefaultRootWindow(display);
    if (!window_root)
    exit(EXIT_FAILURE);

    Window window_found = Window_With_Name(display, window_root, “put here the name of the window”);

    if (window_found)
    {
    XSetInputFocus(display, window_found, RevertToNone, CurrentTime);

    // Send keys to window_found

  10. With the method of the last comment you can automate any application (sending “keypresses” to its window).

    This method needs that the window is not minimized, maybe some hacker can find a method that is valid even if the window is minimized.

  11. I’ve been searching for several hours trying to find something like this, thank you very much.

    For some reason this doesn’t seem to send the key event to the focused window (a urxvt terminal in my case), but I read at this website (http://www.handhelds.org/moin/moin.cgi/GeneratingSyntheticX11Events) that a key event generated in this way is tagged as fake and many programs ignore events with that tag. However, as the site suggests, the thing to do is use the XTest function instead. So, I made this small change:

    XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);
    was changed to
    XTestFakeKeyEvent(event.display, event.keycode, True, CurrentTime);

    To complie this I had to do g++ -o XFakeKey XFakeKey.cpp -L/usr/X11R6/lib -lX11 -lXtst

    Now it works perfectly.

    Again, thank you.

  12. Please , can you show me where can i document myself about X11 .
    I need documentation to develop a keylogger . THANKS

  13. Very helpful, thank you.

    A word of warning to those who try to modify it: multiple calls to XOpenDisplay() with the same parameter return different handles; sending the press event with one handle and the release event with another will not work.

  14. Nice code thanks at all
    it does not work for me @Antonio

    I can get the window handler if i set the focus i become a Parameter error

    X Error of failed request: BadMatch (invalid parameter attributes)
    Major opcode of failed request: 42 (X_SetInputFocus)
    Serial number of failed request: 156
    Current serial number in output stream: 157

    My Problem is after a localhost Webserver Update i will send a ctrl+f5 to firefox for reload it not works for me
    dbus and firefox as option the same

  15. Thanks Adam! Brilliant. I needed* to send an F5 to Empathy to make it show all chat windows after starting. This worked perfectly first time.

    * For some definition of “needed”.

  16. Howdy!

    This is an old post, but you may be interested in xdotool (and libxdo). It’s an open source tool that helps you automate a bunch of the madness that is dealing with X11. It’ll help you simulate key and mouse events in addition to doing window operations (resize, move, close, unmap/map), and some window manager actions (move windows to another desktop, etc), and searching for windows by property and title.

  17. It actually doesnt work for me. I have debian lenny with gnome, i compiled example, but each function other than XOpenDisplay returns 1 (bad request code). Stuck with it.. :(

  18. #include

    main()
    {
    Display *display = XOpenDisplay(“:0.0″);
    XTestFakeKeyEvent (display, 40, 1, 0);
    XTestFakeKeyEvent (display, 40, 0, 0);
    XCloseDisplay(display);
    return 0;
    }

  19. include meant to be “X11/extensions/XTest.h”, it mangled my post because of angle brackets

  20. I am looking for sample code which will receive events and print. In the above example you are sending KEYCODE correct, but here I need to capture the KEYCODE events that are sent to X.

    Anybody please throw some pointers how to implement.

    Thanks,
    Raja

  21. Hi, Sorry about my english, I am brasilian, I do a program very similar to yours, it works but i open a Keditor to test and the char like F dont happens only f when I press F, an other thing is that I try to do something like alt+f to open file but it didnt work, what I need to do? I send alt-press, f-press f-release, alt-release

    plz help me, send me an email if you konw something thebest_br@hotmail.com

Comments are closed.