What are all the PC emulators doing "natural keyboard' translation? It definitely isn't VirtualBox or VMware - both of those map keys directly. DOSbox kind of does for DOS itself by virtue of the fact that it's HLE'ing the character input function, but when a program accesses the keyboard directly it reads the keys that are down directly.

It's impossible to hold the same amount of time, because there isn't a 1:1 correspondence between keys and characters. It's also impossible to "translate" modifiers since it's all over the shop with whether something uses a modifier or not. Let's use some real-world examples of why you can't do perfect translation.

Emulated system has a JIS "bitshift" keyboard, host system has a US "typewriter" layout keyboard:
  • User presses Right Shift
  • User presses 2 (on host this types an '@' character)
  • User releases 2
  • User releases RIght Shift

On the emulated system, typing '@' does not involve the shift key at all - it's the key to the right of P unshifted (this key has '[' on the host keyboard). So if you're trying to translate modifiers, what do you do? Press the emulated shift key, then release it for some amount of time before pressing the @ key, then press it again after releasing the emulated @ key?

Same emulated and host configurations:
  • User presses ' (on host this types a "single straight quote")
  • User releases '

The emulated system requires you to type Shift-7 to type a ' character. You're going to need to press the emulated shift key, wait long enough to ensure matrix scanning can detect it, press the emulated 7 key, and then release both keys.

It gets even messier with dead keys. Emulated system had a German DIN keyboard, host has Windows US International layout:
  • User presses Left Shift
  • User presses ' (on host system this initiates a dead key sequence)
  • User releases '
  • User releases Left Shift
  • User presses U (on host system this types ΓΌ because of the current dead key state)
  • User releases U

On the emulated system, this is a single keystroke - the key to the right of P, with no modifiers at all. You can't translate all the keystrokes leading up to the character being typed, because they don't actually produce characters.

What about a failed dead key sequence? Same emulated and host configurations:
  • User presses Left Shift
  • User presses ' (on host system this initiates a dead key sequence)
  • User releases '
  • User releases Left Shift
  • User presses X (on host system this types "x because there's no mapping for X in the current dead key state)
  • User releases X

You can't press the emulated keys for the " (shift-2) when the user starts the dead key sequence, because you can't anticipate the next character they'll type. You need to do the whole sequence when they press X.

You have no way of knowing whether the emulated system is running a game or other program that processes raw keystrokes and works best with everything passed through based on position, or it's running something accepting character input and you should translate characters to keystrokes. And what if it's both? You could be typing into a text editor while some other program is snooping the keyboard directly.

Also, if you want to be able to hold the key for a corresponding amount of time, you need to be doing key translation yourself. You don't get information on when a key is pressed/released from character input events. To be able to pass that through to the emulated system (assuming you had correspondence between keystrokes on both sides to begin with), you'd need to load the host system's keyboard layout, do translation from keystrokes to characters yourself, including dead key mapping, etc. and then pass it through. This would be a big mess of OS-dependent code, and it would have no chance of working at all for languages with IME edit.

If I'm completely missing something that makes this simple, please point it out to me. But I'm really sick of people saying natural keyboard is best and should work properly, when decades of dealing with multiple language support across operating systems tells me it's impossible to do in a satisfactory way, and what we've got now is about the best compromise we're going to get.