schellingb / ZillaLib

Sleek multiplatform C++ 2D and 3D game creation!
https://zillalib.github.io/
zlib License
110 stars 8 forks source link

SDL2 keycode vs. scancode #20

Open tobybear opened 1 month ago

tobybear commented 1 month ago

One of the issues I keep bumping into with ZillaLib: The platforms that use the SDL2 backend return the keys pressed (on the SDL_KEYDOWN and SDL_KEYUP events) with their scancode, not their keycode. This means for non US keyboard layouts, the keys get reported incorrectly. For example on German keyboards, pressing the 'Y' key will return as ZLK_Z being pressed instead of ZLK_Y. This is especially annoying for text input or shortcut handling. Possible solutions might for example be to make the SDL_GetKeyFromScancode() functionality available from within ZillaLib, or to (optionally) return in.key.keysym.sym instead of in.key.keysym.scancode in line 481 of ZL_PlatformSDL. Any thoughts on this?

tobybear commented 1 month ago

Hmm, giving it further thoughts, I am not sure what would be the best approach. From a developer's point if view, I can see both keycode and scancode as valid requirements: sometimes you might want to have the position of keys, e.g. for Z and X as adjacent action buttons to work even when Y and X are next to each other on many keyboards instead. (This is how it is currently with ZillaLib: pressing Y yields Z on many layouts). And sometimes you have text input fields or keyboards shortcuts where you want to know the key being pressed, no matter where on the keyboard it is. So the Y key would always return Y.

For my purposes, I extended the ZillaLib key struct to include both keycode and scancode from SDL (with same value on other platforms) and depending on my application needs I use one or the other (or both).

schellingb commented 1 month ago

Yes, the idea is to use the ZLK_ scancodes are meant to represent physical keys because for games WASD input should be the four directional letter keys which might be ZQSD on a French AZERTY keyboard, or as you've said YX as action keys would be ZX on a german QWERTZ keyboard.

Then for any kind of text input there is ZL_Display::sigTextInput which gives you a pressed characters as a UTF8 sequence. This often is just one character represented by a one byte long string, but pressing ä on a German keyboard should give you a byte sequence of 0xC3 0xA4 which is Unicode ä encoded in UTF-8. Also inputting any upper case letters or modifiers like SHIFT+Numbers will pass what matches the currently active keyboard layout.

Fun thing I just noticed though... The web export seems to not follow that. Not sure if JavaScript APIs or browsers have changed since but as of now that seems incorrect :-( See https://zillalib.github.io/samples/?06

tobybear commented 1 month ago

I understand the main focus on game input controls where scancode definitely make more sense. I am occasionally using ZillaLib to prototype applications and there I encounter the keycode/scancode issue from time to time. In any case, it is not much of an issue any more to me, as I adapted my own (already modified) ZillaLib branch to make both scancode and keycode available.

Funny thing you bring up the web input sample, as some years ago when I experimentally replaced the Zillalib SDL2 backend with a custom GLFW backend, I could not get the keycode reporting to work. Back then I compared the output from the web sample with my GLFW code and stumbled upon this Y vs. Z issue. Had I known that the web code is buggy and my GLFW code with the scancodes was already alright to begin with, that would have saved me hours of searching and probably also prevented me from abandoning that GLFW port. LOL :)