Here a some precisions about my code:

1) It is currently in a working state. it may need some polishing work, but the major part of the work is already done.
2) I am using the XKB *database* and nothing of the XKB *API*
3) Once the keycode->virtual key code map is loaded, I use keycodes at run time and map them to virtual key codes, then to scan codes. ANY X program receives the keycodes. Look in xwin.c. keycodes alone are unreliable as they are hardware dependent, but that was the whole point of using the XKB *database* to map them a consistent naming system (XKB key names / virtual key codes). My perl script exports part of the XKB database to keycodes -> virtual key codes, but reading keycodes -> XKB keynames maps and then mapping XKB keynames to virtual key codes and writing that into a new file.

I still disagree that we should add XKB as a dependency. Ilya, how would you get around the fact that XKB keynames are not exactly "ready" to be used? How would you map them to scan codes? Mapping them their corresponding virtual key code works perfectly, but I don't think it is a good idea to do that at run time, there are tons of XKB keynames. You can take a look at the perl script, the mapping from XKB keynames to virtual key code is done there.

About your goal #1 and #2:

Goal #1: Send precise AT scancodes, no matter what. (As much as possible, keep it language-agnostic, keep local language-specific keyboard mappings out of the way.)
Goal #2: Give the remote server a good hint about the local keyboard preferences.

My code mainly solves #1 with the usage of virtual key codes (language and keyboard agnostic codes), but I have also worked a lot on #2. look like locales.h for #2. xkbkeymap.c contains a function that finds the locale and gets its corresponding locale ID, and then uses it to find a default keyboard layout ID that would normally correspond to someone using that locale. The hard coded maps between locale ID and keyboard layout ID are made from documentation from Microsoft. I left the corresponding URLs in comments.