XSendEvent + LD_PRELOAD == win
Posted Sat, 06 Jun 2009
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.