I was trying to wrap my head around the code of how mame does its UI Paste function (and also the lua does its emu.keypost()) because the text pasting in the apple2e driver seems to scramble the input.

Grep is pretty useful to scan the whole source tree because I couldn't figure out where things are:

Natural keyboard mode will never work particularly well, since it's a pretty much impossible set of requirements. It's supposed to translate host character input to emulated keystrokes. Not all keystrokes produce characters, some characters require multiple keystrokes to produce, and IME edit opens another whole can of worms. It kinda works for simple cases, but it's always going to be something that's nice if it works at best.

Sounds like something that should be implemented or enabled on a per-driver basis, then. Otherwise it seems like exactly the sort of half-baked, user-hostile, anti-feature that MAME is infamous for. It violates the hell out of the rule of least surprise.

Natural keyboard mode isn't enabled by default, you have to use -natural on command line or go into the menu and switch it on. It works a lot better than it used to provided the PORT_CHAR declarations for the driver are done properly. It also performs a bit better in 0.190 than it did before, as I eliminated an O(n) lookup, but the speed at which it generates keystrokes is still pretty conservative, as it has to work with some slow systems.

I had a quick look at the apple2e driver and it seems to have the wrong PORT_CHAR for a few keys, as though it was quickly copy/pasted from the Apple II+ and not fully updated (Apple II+ uses a "bitshift" style layout, while Apple IIe uses a "typewriter shift" style layout). I'm not going to mess with trying to make control keys work in natural mode, as that's problematic, but I've tried to at least fix the shifted digits and arrow keys in natural keyboard mode with 64ac8e4. I've only tried fixing the US Apple IIe and variants, not the UK, French and Spanish versions.

Note that the Apple II drivers are set up to translate uppercase letters to unshifted letter keys for natural keyboard/UI paste/keypost. If you type/paste/post lowercase letters, it will press the emulated shift key when typing each one.

I really wanted to have a proper "delay after a CR" during a paste so that after a CR, you'd have a delay while the computer would process the line of input.

If you have a key pressed too long on the Apple2e, it starts to auto repeat. So you want your delay AFTER the CR has been pressed and released.

Calling m_timer->adjust(choose_delay(m_buffer[m_bufbegin])); doesn't really give you a proper delay amount, especially since this function gets executed at least twice for each keypress/release.

I wrestled mightily with the function natural_keyboard::timer to get a delay that was "long" without triggering the autorepeat.

This function actually first "presses" all of the fields for a given keycode, then it releases them one by one each time it gets called after that. It seems really counter-intuitive. One of the things that really threw me for a loop is that it does things "reversed" like field->set_value(!m_status_keydown). m_status_keydown comes in as false, it sets all the fields, then it flips the m_status_keydown.

I haven't tested this very much, but it seems to work for the couple of pastes I've thrown at it.

Sounds like something that should be implemented or enabled on a per-driver basis, then. Otherwise it seems like exactly the sort of half-baked, user-hostile, anti-feature that MAME is infamous for. It violates the hell out of the rule of least surprise.

On the contrary, it's exactly the sort of user-friendliness you advocate: it changes the keyboard emulation from matching the layout of the original at the expense of what's actually marked on your PC keyboard to (attempting to) make it so e.g. shift-2 on a US keyboard is always @, even on machines where shift-2 is " or a UK pound sign or whatever. I would argue that having keys on your PC keyboard *not* generate the same thing on the emulated system is actually the major violation of least-surprise here. In particular, pretty much all other computer emulators *only* have an equivalent of natural keyboard mode.

it's user unfriendly when it doesn't work for games etc. because it never really seems to register keys as held down, only 'pressed once' especially if they're shifted keys or whatever else..

while the idea is good in concept, the implementation of it is definitely horrible and acts in completely unexpected ways and how you toggle it on / off at runtime doesn't seem to be common knowledge either.

Yes, we all agree the implementation sucks; it should hold down the keys on the emulated keyboard for the same amount of time that the user holds down the original key(s) etc. But the concept is pretty much industry-standard.

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.