Reputation: 2602
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:
XDisplayKeycodes
, XGetKeyboardMapping
, XkbGetState
)XkbLockModifiers
)n
unique symbols are encountered, where n
is the number of possible keycodes as returned by XDisplayKeycodes
.n
unique X11 KeySyms via XChangeKeyboardMapping
on the n
available KeyCodesXTestFakeKeyEvent
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.
E.g. 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!
Upvotes: 3
Views: 2197
Reputation: 67
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:
E.g. 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.
Upvotes: 1