简体   繁体   中英

X11/Xlib: virtual keyboard input and keyboard mapping synchronization issue

For an automated test application I have to simulate large amount of unicode keyboard input into an old X11 application (of which I don't have any source access). My program takes the input from an UCS-2 LE encoded input stream via stdin and the basic operation is as follows:

  1. Save current keyboard layout and lock modifiers ( XDisplayKeycodes , XGetKeyboardMapping , XkbGetState )
  2. Unlock active modifiers ( XkbLockModifiers )
  3. Disable all X11 slave keyboard devices via Xinput2 extension
  4. Read input into a key press queue until n unique symbols are encountered, where n is the number of possible keycodes as returned by XDisplayKeycodes .
  5. Map these n unique X11 KeySyms via XChangeKeyboardMapping on the n available KeyCodes
  6. Type the correct KeyCodes for all enqueued KeySyms via XTestFakeKeyEvent
  7. Clear the queue and continue at 4.) until no input is available
  8. Reactivate keyboards and restore initial modifiers and mappings

Basically this system works better and much more performant than any virtual X11 key input tool I've seen so far.

However, there is an issue I can currently only fix using ugly delays:

As any other X11 application, the target application receives a MappingNotify (request==Keyboard) event from the X server after my application succeeded in changing the keyboard mapping table. The usual response of a X11 client is to call XRefreshKeyboardMapping to update Xlib's knowledge of the new keyboard layout.

Now if the the client has some lag processing its X11 event queue, the XRefreshKeyboardMapping call might return a too recent mapping that is already some generations too far in the future. Eg my input generator has already done the fourth XChangeKeyboardMapping when the target application just arrived at handling the second MappingNotify event in its XEvent queue handler. Actually it should get the second generation of the map, which isn't available at the X server anymore at that time.

Unfortunately there is no map id or version of any kind in the keyboard MappingNotify event so that XRefreshKeyboardMapping could refer to a specific map ... and the X server does not seem to keep a history either.

The result is that the X11 application's KeyCode to KeySym conversion operates with an invalid layout and generates wrong KeySyms.

So basically I have to wait until all clients (or at least the one with the input focus) have requested and received my last XChangeKeyboardMapping map before I am allowed to do the next XChangeKeyboardMapping .

I can fix 99.9% of the errors using a delay before XChangeKeyboardMapping and that delay is calculated by some ugly witchcraft (amount of key strokes etc.) and is way to high if 100% accuracy has to be achieved.

So my question is if there is any way to programmatically be notified or to check if a X11 client has completed XRefreshKeyboardMapping or if its map is in sync with the server map?

If not, is there a way to get another X11 client's current mapping via xlib (to check if the map is current)?

Thanks for any hints!

I've done something similar on Windows in the past. I had the luxury of being able to use the SendInput function which accepts a KEYBDINPUT structure with KEYEVENTF_UNICODE flag. Unfortunately X11 does not support direct keystroke synthesizing of Unicode characters.

Since I cannot comment yet I'm forced to give a suggestion as answer:

Have you considered using the clipboard instead in order to transfer your " unicode input " into this X11 application's input field ?

You also might consider using direct Unicode input if that application uses a toolkit that supports this:

Eg programs based on GTK+ (that includes all GNOME applications) support Unicode input.
Hold Ctrl + Shift and type u followed by the Unicode hex digits and release Ctrl and Shift again.

I guess it should be easy to synthesize these sequences using the Xtest extension.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM