[ Home > Softwares > xvkbd > Sending Key Events ]

Sending Key Events

Sending Key Events

To send key events, we can use XSendEvent(), a standard Xlib function, or XTestFakeKeyEvent(), an interface to the XTEST extension.

Sending events with XSendEvent()

To send key events with XSendEvent(), we must set required parameters in a XKeyEvent struct and then invoke XSendEvent().
  XKeyEvent event;

  event.display = display;
  event.window = destination of the event;
  event.root = the root window;
  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.type = KeyPress;  or  event.type = KeyRelease;
  event.keycode = keycode;
  event.state = modifiers;

  XSendEvent(event.display, event.window, TRUE, KeyPressMask, (XEvent *)event);

event.type specifies the type of the event, and we should set KeyPress to simulating key press, and KeyRelease to simulating key release.

event.window (and the second parameter of XSendEvent()) is the window ID of the destination of the event. To send the event to the window which has the input focus at the time, we can use the value obtained via XGetInputFocus(). To send the event to a specific window, we should set the window ID to event.window, and set keyboard focus to the window XSendEvent().

event.keycode is the keycode to be sent, and clients can reproduce the keysym from the keycode and value of the modifiers specified as event.modifiers.

event.state indicates the state of modifiers, and we must set the result of bitwise-or of the values for effective modifiers. Value for modifiers such as Shift or Control are defined as constans (ShiftMask and ControlMask, respectively). If modifiers such as Meta or Mode_switch are required, the value for them can be obtained via XGetModifierMapping().

The dominant problem for use of XSendEvent() is that events send by XSendEvent() (those send_event flag in Event struct were set) may ignored by some clients.

XTEST extension

It may be easier to send key events with XTEST extension, than that of XSendEvent(). In the other hand, it has its own difficulties.

XTestFakeKeyEvent() is the interface to send key events with XTEST extension.

  XTestFakeKeyEvent(display, keycode, True, 0);

The third parameter of XTestFakeKeyEvent() specifies if the key was pressed or released, and KeyPress event will be sent if it was True, and KeyRelease event will be sent if it was False.

It is not possible to specify the destination of the event when using XTestFakeKeyEvent(), the sent events will be delivered through the normal event delivery mechanism in the same way with the events generated with the real keyboard. This will cause difficulties in the situation where the window under the pointer will accept the key events. Generally, we can't assume that the pointer will in the window we want to send the event, so some measure will be required to solve the problem. xvkbd tries to solve the problem by moving the pointer by calling XWarpPointer() before XTestFakeKeyEvent() (and restore the position afterward), but it may not work as desired in some situation.

As in XSendEvent(), character to be sent will be specified with its keycode. But because it is not possible to specify the modifiers directly, and it may be required to set state of the modifiers by sending KeyPress/KeyRelease events for those modifier keys.

Not all X server may support the XTEST extension. We can use XQueryExtension(dpy, "XTEST", ...) to check if the XTEST extension is available.


Keysym and Keycode

Convert Keycode to Keysym

When keys are pressed, X server will send the keycode for the key. The keycode depends to systems, but clients can convert it into portable keysym by functions such as XLookupKeysym(). Each keys usually correspond to multiple keysyms, hence conversion from keycode to keysym usally depends to state of modifiers, too.

Mapping between keycodes and keysyms can be changed by XChangeKeyboardMapping() function or xmodmap command.

Convert Keysym to Keycode

To simulate key events, it will be necessary to convert it into keycode. Keycode correspond to the keysym can be obtained by XKeysymToKeycode(), but we may need to tell the state of the modifiers.

Modifier

Keys can have some meanings depends to state of the other keys (such as Shift, Control, etc.). For example, in normal layout, `a' key will become `A' when Shift was pressed, and become Control-A when Control was pressed. Those keys such as Shift or Control are called modifiers.

Modifiers such as Shift or Mode_switch (AltGr) will have effect to conversion between keycode and keysym. As described in the manual of XChangeKeyboardMapping(), it is possible to assign multiple keysyms for each keycodes.

I couldn't find documentation about this, but it is belieaved that first four keysyms (if any) for each keycodes will correspond to:

  1. None of Shift and Mode_switch are pressed
  2. Shift is pressed
  3. Mode_switch is pressed
  4. Both Shift and Mode_switch are pressed


by T.Sato, 2001-01-08