Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDL3 key questions #10139

Closed
slouken opened this issue Jun 29, 2024 · 10 comments · Fixed by #10156
Closed

SDL3 key questions #10139

slouken opened this issue Jun 29, 2024 · 10 comments · Fixed by #10156
Milestone

Comments

@slouken
Copy link
Collaborator

slouken commented Jun 29, 2024

Q1: Should event keycodes be modified keys or unmodified keys by default?

Q2: Should key names be the label printed on the key as in SDL2, or be the value of keycode? e.g. should SDLK_a and SDLK_A have the same name? Should SDL_SCANCODE_1 be '1' or '&' on the French keyboard? What should the name of SDLK_AMPERSAND be on the French keyboard?

Q3: Should we have separate SDL keycodes for numpad keys based on numlock state? As prior art, Windows has entirely different VK codes for those keys depending on whether numlock is on, and X11 has separate KP_Left and KP_4 keysyms.

Related issues:
#3559
#10150

@slouken slouken added this to the 3.0 ABI milestone Jun 29, 2024
@slouken
Copy link
Collaborator Author

slouken commented Jun 29, 2024

@libsdl-org/a-team, sanity check?

@slouken slouken changed the title SDL numpad keycodes SDL3 key questions Jun 30, 2024
@slouken
Copy link
Collaborator Author

slouken commented Jun 30, 2024

Q1: Should event keycodes be modified keys or unmodified keys by default?

Prior art:

  • Windows uses the same virtual keycode for the 'A' key regardless of shift state
  • X11 uses the keysym 'a' for unmodified A, and 'A' for A when shift is held down or capslock is on
  • Web events contain 'a' for unmodified A and 'A' for when shift is held down or capslock is on, you can view this yourself at https://w3c.github.io/uievents/tools/key-event-viewer.html.

Pros for unmodified keys:

  • Compatibility with SDL2 applications
  • Game actions can easily be mapped to keycodes ignoring modifier state

Cons for unmodified keys:

  • You won't get key events for keys that aren't in the keymap, or for platforms that don't have a keymap, e.g. web, on-screen keyboard, etc.

Pros for modified keys:

  • Game actions can be easily be mapped to keycodes where modifier state is important
  • You will get key events for any key that's typed, and the events will come naturally from the web platform and mobile devices

Thoughts:

  • It's important for cross-platform consistency that web and desktop platforms behave the same way.
  • Games which bind keys non-positionally often have enough actions that they use control and shift as additional modifiers and many of them bind 'p' as distinct from 'P' and distinct from Ctrl-P. It's confusing that you'd have to handle Ctrl+'p' as distinct from Ctrl+'P'.
  • On a US keyboard, you might easily have distinct actions bound to '.' and '>', even though they're the same base key. They would be represented in the UI as '.' and '>', not '.' and Shift+'.', and the same is true for 'p' and 'P' if they're bound to different actions. This is especially true as '>' is a separate key on many international keyboards, and you could keep the same key bindings in that case.
  • If you have 'r' mapped to the reload action, you might want 'r' to reload regardless of whether shift or capslock is held down. In that case it's easy to add 'R' also mapped to the reload action.

It seems like for key bindings, you're either binding positionally, in which case you'd be looking at scancodes and not keycodes, or you'd want to show the final character code that is used for the binding regardless of the key sequence that got you there. For example, you could map an action to '>' and it would either be Shift+'.' on a US layout, or the '>' key on an international keyboard. An even better example is mapping an action to 'ù', which is a key on a French keyboard, but would have to be entered via ALT+0249 on a US keyboard, and would never show up as a distinct key event.

Anecdotally, web events give you the key 'ъ' with the code BracketRight, when you press that key with the Russian keyboard layout.

@slouken
Copy link
Collaborator Author

slouken commented Jun 30, 2024

Q1: Should event keycodes be modified keys or unmodified keys by default?

An alternative might be to leave keycode as it was in SDL2, and add charcode to the events, which behaves like the SDL1 unicode field, and contains the keycode including modifiers.

One downside to this would be that application developers would be confused as to which they should be using, especially since charcode wouldn't be directly equivalent to text input (e.g. Alt+0249 = 'ù') even though it would look like it in many cases. Another downside is that now sometimes applications would be looking at charcode for some key events and keycode for others, e.g. arrow keys, etc., reinforcing the idea of using charcode for text input even more.

I'm thinking the additional confusion isn't worth it here, and we should just decide what keycode means and allow applications to switch that meaning or use SDL_GetKeyFromScancode() depending on their needs.

@slouken
Copy link
Collaborator Author

slouken commented Jun 30, 2024

After discussion with @icculus, we agreed the right thing is to remove the keycode entirely from the keyboard event. That will make it so most programs that just want to use the keyboard as a 101 key gamepad will do the right thing, and programs that want keycodes will have precise control over exactly how they want them.

For desktop platforms we'll have the keymap available, and for web platforms we'll dynamically build the keymap as keyboard events come in.

@slouken
Copy link
Collaborator Author

slouken commented Jun 30, 2024

With this change, the answers to the original questions are easy:

Q1: Should event keycodes be modified keys or unmodified keys by default?

The application can look up keycodes using modifiers or not, as they wish.

Q2: Should key names be the label printed on the key as in SDL2, or be the value of keycode? e.g. should SDLK_a and SDLK_A have the same name? Should SDL_SCANCODE_1 be '1' or '&' on the French keyboard? What should the name of SDLK_AMPERSAND be on the French keyboard?

The names of the keycodes are the printable character for printable keycodes, or the name of the associated scancode for unprintable keycodes.

Q3: Should we have separate SDL keycodes for numpad keys based on numlock state? As prior art, Windows has entirely different VK codes for those keys depending on whether numlock is on, and X11 has separate KP_Left and KP_4 keysyms.

The scancode will remain SDL_SCANCODE_KP_4, for example, but the keycode will be SDLK_LEFT or SDLK_4, depending on numlock state.

@slouken
Copy link
Collaborator Author

slouken commented Jul 1, 2024

So this ends up not working well because we want scancodes to represent the physical key locations, but people may have remapped keys so semantically they've swapped modifier keys or moved escape closer to the center of the keyboard. The right thing for applications is to look at the keycode as the semantic meaning of the key, as they have been doing all along.

I think that leaves us with making the keycode the base key as it is in SDL2, giving us the following answers:

Q1: Should event keycodes be modified keys or unmodified keys by default?

Events will have unmodified keys. Also the hint will allow using French number keycodes and forcing English keycodes for non-latin keyboards as user options, but we'll remove the option for modified keys, because that's something applications would have to code for to handle correctly.

We'll still have a function to take a scancode and modifier and return the actual key in the keymap regardless of the keycode in the event, so SDL_GetKeyFromScancode(SDL_SCANCODE_1, SDL_KMOD_NONE) will return SDLK_AMPERSAND for the French keyboard layout even if the keycode in the event is SDLK_1.

Q2: Should key names be the label printed on the key as in SDL2, or be the value of keycode? e.g. should SDLK_a and SDLK_A have the same name? Should SDL_SCANCODE_1 be '1' or '&' on the French keyboard? What should the name of SDLK_AMPERSAND be on the French keyboard?

Key names are not related to key layout, and the name for both 'a' and 'A' keycodes is "A". We'll document this.

Separately we'll rename SDLK_[a-z] to SDLK_[A-Z], but leave the values lower case.

Q3: Should we have separate SDL keycodes for numpad keys based on numlock state? As prior art, Windows has entirely different VK codes for those keys depending on whether numlock is on, and X11 has separate KP_Left and KP_4 keysyms.

The keycode in the event and the layout will be SDLK_LEFT or SDLK_4 when the scancode is SDL_SCANCODE_KP_4, depending on the numlock modifier state.

@icculus
Copy link
Collaborator

icculus commented Jul 1, 2024

I've started writing up a "best practices" wiki page for this, with the final details and code examples to be filled in when code changes are pushed for this issue. I've barely proofread this, so feel free to make edits directly if you like:

https://wiki.libsdl.org/SDL3/BestKeyboardPractices

@Lzard
Copy link
Contributor

Lzard commented Jul 1, 2024

Mirroring the joystick and gamepad APIs, would it make sense to generate separate keyboard events, so users can simply consider the ones they care about and maybe disable the others?

@slouken
Copy link
Collaborator Author

slouken commented Jul 1, 2024

I've started writing up a "best practices" wiki page for this, with the final details and code examples to be filled in when code changes are pushed for this issue. I've barely proofread this, so feel free to make edits directly if you like:

https://wiki.libsdl.org/SDL3/BestKeyboardPractices

I added some code for the chat box and text editor use cases.

@icculus
Copy link
Collaborator

icculus commented Jul 1, 2024

I added some code for the chat box and text editor use cases.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants