ColinPitrat / caprice32

An emulator of the Amstrad CPC 8bit home computer range.
GNU General Public License v2.0
148 stars 32 forks source link

Simplify keyboard support #189

Open ColinPitrat opened 3 years ago

ColinPitrat commented 3 years ago

From https://github.com/ColinPitrat/caprice32/issues/185#issuecomment-808932406

There are things that always bugged me with keyboard handling in caprice32.

map file selection should be automatic

Why should user have to choose "PC keyboard layout"? Plus the offered choices mention operating system.

This feels awkward. Should the end user be exposed to those combinations, when the OS and probably keyboard layout can be probed or at least guessed from hints. Most probably, many users won't bother and just consider the thing broken.

As a convenience, cpc-dev-tool-chain selects it automatically based on probing the operating system keymap, see https://github.com/cpcitor/cpc-dev-tool-chain/blob/master/tool/caprice32/caprice32_local_adjust.sh . This currently covers only part of the use cases but could be a basis for improvement.

map files feel like they replicate known information

IMHO there are basically two ways to handle emulated keyboard. Arnoldemu can do both and calls these:

I have had a look again at the map files. It feels awful that one even have to consider OS difference. Isn't SDL supposed to abstract OS away? Perhaps SDL was fixed in the meantime and some differences between win and linux variants are no longer needed. What happens on Mac?

map files are defined based on SDL_Keycode, so they can only be broken if the file chosen does not match the OS keyboard layout. Had they been defined based on SDL_Scancode they might have been more robust (or not, I'm not naive enough to claim so).

Anyway, since caprice32 chooses the "translated" way, in most keyboard events the needed information to propagate to the CPC is conveyed by the character generated by the key. That character is available in the SDL_TEXTINPUT events, right?

Couldn't keyboard handling be simplified using SDL_TEXTINPUT? All key combinations that generate characters (even complicated like AltGr 0 for the @) would be covered by SDL_TEXTINPUT events immediately. The number of necessary mappings to cover the other cases would be much fewer. Perhaps some of the *map could then be merged because they would no longer be different?

You can answer "no, it's a mess". ;-) I actually had a look at the .map files, and I'd not be surprised.

ColinPitrat commented 3 years ago

Indeed, keyboard handling in caprice32 is a mess.

I agree we shouldn't have two settings (CPC keyboard layout + PC keyboard layout). And I'd love to support both translated & positional modes.

The reason for the win/linux keymaps to exist is that indeed SDL1 was buggy. I suspect the different mappings may not be needed anymore with SDL2, that's one thing I'd like to determine through the testing.

The scancode may be interesting in SDL2. In SDL1, it was documented to be hardware specific and that it shouldn't be used in general (https://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlkeysym.html).

The idea of auto-detecting the right keymap is good. A 2 minutes search allowed me to find this which provides some interesting idea to do it from the code in a platform independent way: https://gist.github.com/g2p/8597984

The SDL_TEXTINPUT is an interesting idea but, as you said, it doesn't cover all keys so it's a bit messy. In SDL1 there was the unicode field which could have been used for keys that had it, but it's not available anymore with SDL2. In SDL2, there's the key name (https://wiki.libsdl.org/SDL_GetKeyName) which could be interesting, but is meant for human consumption so it could be unstable. Probably not a great idea to rely on it.

cpcitor commented 3 years ago

Hey, you found a lot of interesting information, including that (Python-based) gist.

Yes I would stay away from "human-readable name"s which indeed could be unstable... or only cover the plain keypress and not all the combos.

Are you sure that the Unicode field is no longer available in SDL_TEXTINPUT? It looks documented here: https://wiki.libsdl.org/SDL_TextInputEvent . It looks like it can do most of the job.

ColinPitrat commented 3 years ago

In SDL1, you could activate unicode and get a unicode char for each keypress. That's what is not working in SDL2 (because it was not supporting composition).

In SDL2, TEXTINPUT provides a distinct event than KEYUP/KEYDOWN. It has to be activated and handled separately. This is not necessarily an issue, I just have to check what effect it has on other events.

But having slept over it, I think it should work. I could modify mapping to support both keycode, scancode and textinput.