Keyboards are awful. VNC makes things worse because it uses X keysyms, which aren't sure whether they're key codes or a character encoding or something betwixt the two somewhere.
The keyboard driver in A/UX can be in several modes, defined in
sys/key.h
:
C:
#define KEY_ASCII 0 /* ascii mode ... with timeouts */
#define KEY_RAW 1 /* raw key codes ... when something changes */
#define KEY_ARAW 2 /* raw key codes ... with KEY_ASCII interface */
#define KEY_MAC 3 /* raw keycodes -> keyTrans -> ascii */
Despite KEY_MAC being a thing, the UI environment actually seems to use KEY_ARAW, where raw ADB physical key codes are passed on. This made my heart sink a little, because it means we somehow need to reverse engineer the physical key code from a keysym.
But what's it passing it on to?
Each kernel subsystem that wants to take control of the keyboard essentially installs a callback function by calling a function called
key_op
. One of the things this function does is to take a new callback and return the old one.
This is the first piece of good news: we can slightly abuse this to get the current callback that's receiving key presses, which gives us a nice place to inject those keypresses.
Because we can't get the callback directly, we have to do a bit of a shuffle. First, we disable interrupts to stop the computer noticing what we're about to do. Then we swap in an invalid callback (which returns the real one). Then we swap the real one back in and re-enable interrupts, but keeping our reference to the callback. We can then call that callback to inject a keypress. We do this dance for every keypress, because the callback may have changed since the last keypress (it depends on what kind of session we're in at the time).
But that still doesn't help much with getting the key codes for keysyms: how are we to know what to put into that callback? At the moment, it's heavily bodged, but I noticed something interesting tonight while reading through the UI keyboard callback: the thing that posts key up and key down events in the mac environment and updates low memory
is in the kernel, not in the Mac System. And the kmap/KCHR that are currently in use—the first to map from physical to virtual keycodes, and the latter to map from virtual keycodes to characters—are both stored in the kernel. With sensible defaults.
I had known that these were there, because I saw them in the kernel export list, and also because they're mentioned in key.h, but I thought these were only used for KEY_MAC mode. But they're not: the UI keyboard callback uses them to generate the character codes to put into the events.
This is extremely handy, because it means that
in theory for non-modifiers we can just come up with a mapping of X keysyms to MacRoman characters, then use the kmap and KCHR from the kernel to construct reverse lookup tables to go from "what character do we want to insert" to "what physical ADB keycodes should we generate".
This is easier said than done, but it's also probably easier than manually trying to curate huge tables of what keys go where. Life is too short for that, and if I'm going to do something time consuming I'd rather it be interesting
.
Any thoughts?