scancode vs keycode

Hi there,

This is sort of a newbie question here, though I have searched the forum and only found pretty old messages related to the subject.

I understand the keydown event returns 2 different approaches to detecting the key that was pressed, keycode and scancode. Reading the manuals online, I understand that the idea is that scancode returns some physical code for the key pressed, while keycode tries to provide a code that represents a symbol that is mapped to the key pressed based on current keyboard layout in use.

Which is great.

Furthermore, we have the modifier field which lets us identify if a modifier was simultaneously pressed, like shift, control, alt, etc.

However, and here is my question:

I understand that scancode will provide a single code per key, and modifiers let´s us check that user is trying to get alternater results from the key (shift for uppercase, etc). So, this is great if my application needs to take care of the keyboard mappings by itself, and the code must be ready to process different mappings for different keyboard layouts.

I am failing to graps however the benefit of keycode use. It correctly returns the mapped symbol code only for the non.modified symbols. So, if I press “a” in my keyboard, I get a code for “a”. But if I press SHIFT-A, I still get a code for “a” and am supposed to check the modifier to understand an uppercase symbol is required. Meaning we don´t get the benefit of resolving the symbol using system mappings and now need to think/configure in our application how does modifiers work on different layouts.

Most keyboard have very different symbol mappings for the number-shift combinations, some use alt-gr as well, and not being able to use a pre-defined “key to symbol mapping” seems a great shortcoming.

Is this really how this works or am I missing something ? Is there a way for SDL to resolve the keyboard symbol mapping without needing to rely on manual configuration on the programming side when using keycode or other functions?

Normally, you should be getting the symbol (“a” or “A”) from the SDL_TEXTINPUT event, not from the SDL_KEYDOWN event. SDL_TEXTINPUT takes account of the keyboard layout, modifier keys etc. and does all the work for you. In my app, I only use SDL_KEYDOWN for ‘non-printing’ keys (cursor keys, function keys and so on).

Contrary to what the documentation implies, you do not need to call SDL_StartTextInput() in order to receive SDL_TEXTINPUT events, so long as you are not interested in compositing.

Thanks for the tip. My initial research seems to indicate that SDL_TEXTINPUT is geared towards string input processing, while I am looking for character input processing. Let me check if I can somehow emulate character processing with SDL_TEXTINPUT and revert back.

SDL_TEXTINPUT is the correct event to use for “character input” processing. It can certainly sometimes return a multi-byte string, not least because SDL2 uses UTF-8 encoding so even a single keypress may result in such a string (for example the £ key on this keyboard does).

Text input is hard. AFAIK in SDL we only have SDL_TEXTINPUT events on keypress that have input char (may consist of several Unicode codepoints).

And there is no crossplatform way in SDL how to manually convert keycode\scancode to char (multiple unicode chars).

For Windows you can use ToUnicodeEx() API to convert scancode + vkcode + keyboard state (array of pressed keys + modifiers) to character in HKL layout. This function is used inside Windows to convert WM_KEYDOWN messages to WM_CHAR inside TranslateMessage() call (there are additional stuff like ALT+KEY codes processing on this way). WM_CHAR in result get converted to SDL_TEXTINPUT by SDL code.

1 Like

SDL is trying to support essentially 3 different types of keyboard input:

  1. SDL scancodes are used for games that require position independent key input, e.g. an FPS that uses WASD for movement should use scancodes because the position is important (i.e. the key position shouldn’t change on a French AZERTY keyboard, etc.)
  2. SDL keycodes are used for games that use symbolic key input, e.g. ‘I’ for inventory, ‘B’ for bag, etc. This is useful for MMOs and other games where the label on the key is important for understanding what the action is. Typically shift or control modifiers on those keys do something related to the original function and aren’t related to another letter that might be mapped there (e.g. Shift-B closes all bags, etc.)
  3. SDL text input is used for games that have a text field for chat, or character names, etc.

Games don’t always follow these usage patterns, but this is the way it was originally designed.

1 Like

Yes, this makes sense. I am writing an emulator, so my use case is that I need to detect the symbol corresponding to the key pressed + modifiers and emulate a keypress for the corresponding symbol on the emulated machine. I have solved my issue by mapping my keyboard layout to the scancodes returned (interestingly I found what seems to be a bug on the keycode attributes, as I have 2 different symbols with the same code on my keyboard). But I am using a Spanish (Spain) keyboard, and therefore, will need to work on different mappings to make sure it works on other layouts. Which is why I will try to do some tests with the text input to see if I can avoid the keyboard mapping issue.

Just an update that SDL_TEXTINPUT works almost perfectly for me. However, it still doesn’t handle (or maybe I don’t know how to handle) CTRL key combinations and special keys like BS, ESC, ARROWS, TAB. Which forced me to revert to keydown events for these. It is less of an issue, but I still need to manually map some keys that rely on non-standard key combinations.

In my app I do exactly the same: I receive ‘printing’ characters from SDL_TEXTINPUT and control characters, special keys etc. from SDL_KEYDOWN. It works well for me.