Search this site


Metadata

Articles

Projects

Presentations

XSendEvent + LD_PRELOAD == win

As far as feature requests come, for xdotool, one of the more common ones is to have the ability to send key or mouse events to a specific window, not just the active one. XTEST (what xdotool uses for key/mouse currently) doesn't let you specify a window to send events. XSendEvent(3) lets you send hand-crafted events to a specific window, but most applications ignore these sent events.

The XEvent struct has a member 'send_event' which is true if the event came from an XSendEvent call and false otherwise. Programs like firefox and xterm (by default) ignore many events that have 'send_event' set to true.

Enter LD_PRELOAD.

Writing a custom shared library that overrides the default XNextEvent and XPeekEvent functions allows us to force 'send_event' to always be false, so an application with this library loaded will happily handle keyboard/mouse events generated with XSendEvent. I already have a helpful project that lets me write such a shared library: liboverride.

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

void hack_send_event(XEvent *ev) {
  switch (ev->type) {
    case KeyPress: case KeyRelease: case ButtonPress: case ButtonRelease:
      ev->xany.send_event = False;
      break;
  }
}

override(`XNextEvent', `
  {
    real_func(display, event_return);
    hack_send_event(event_return);
    return;
  }
')
This small bit of liboverride code will give me a shared library I can preload with LD_PRELOAD. Doing so will ensure that send_event is false for any key or mouse button events.

Works well. Now that we have a reliable way to allow XSendEvent I think it's worth putting this into xdotool.