Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Better keyboard handling  (Read 68138 times)

0 Members and 3 Guests are viewing this topic.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: Better keyboard handling
« Reply #45 on: November 29, 2013, 05:17:42 pm »
From my perspective we need/want:
  • A way to identify any key press.
  • A way to map most of those key presses in an programmer friendly way.
  • A way to retrieve characters for the given key combination.

I can see the following solutions:
  • Directly provide scan codes - we don't have to care what they actually represent, as long as we have scan codes we can map them "somehow".
  • An enum representing the "default" keys.
  • TextEntered should be enough here.

With that said, the current issue we're mostly have been discussing is around number two.

When programming for keyboards the thing you really want to do is use scan codes for everything, you essentially don't want to write if key = "Z" then, because as soon as you switch your QWERTY with a QWERTZ keyboard the whole mapping is gone.
You also don't want to use key press events for checking text input, because a "key" in the key press event should represent a single key and not any kind of character - it's just the key with the scan code X.

A solution I could see is, using a fixed layout (e.g. US) for the scan code to "key names" conversion. So whenever you'd reference to the key "1" you'd mean "the key that is labeled 1 on an US keyboard layout" or if you use "Z" then you'd mean "the key that is labeled Z on an US keyboard layout". This can lead to a lot of confusion, but at least people wouldn't be forced to use the non-expressive scan codes.

But since we'd be sometimes interested in knowing "what key did the user press on his keyboard layout?", we need a way to label keys. Tank suggested a map with language specifier, while this might work, it most likely gets pretty ugly over time and the more layouts you got, the more code duplication you'd be making. Instead I'd suggest SFML to retrieve the current layout and translate the scan code to the current layout, without the programmer ever having to care about what layout the user has.

In short we need:
  • Scan Codes
  • Unique names for scan codes
  • Scan-codes to current-layout converter
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Re: Better keyboard handling
« Reply #46 on: November 29, 2013, 05:26:07 pm »
The example I gave was only related to providing hard-coded defaults in a game. Your "US layout is default" idea that makes it able to at least map anything in code is actually what I wanted to express with this:

sf::Keyboard::toScanCode( sf::Keyboard::Q )

sf::Keyboard::Q would be the location of the Q key on a chosen layout (QWERTY or another popular one), and toScanCode() translates that into the appropriate scan code of the current active layout/keyboard.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
AW: Better keyboard handling
« Reply #47 on: November 29, 2013, 06:06:54 pm »
I see...
An option would be to let the programmer choose a layout while a default is pre-set, thus non-QWERTY keyboard owners wouldn't have to constantly look up the layout.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Better keyboard handling
« Reply #48 on: November 29, 2013, 06:10:25 pm »
Everything that is explained in the first post ;)
I asked because somebody might already have tried to support a variety of keyboards using SFML, and could have come up with concrete problems (most people in this thread seem to work with one layout). As far as I interpret the answers, different names for a key (1 or &, { or [, etc) and the issues related to them seem to be most important.

A solution I could see is, using a fixed layout (e.g. US) for the scan code to "key names" conversion. So whenever you'd reference to the key "1" you'd mean "the key that is labeled 1 on an US keyboard layout" or if you use "Z" then you'd mean "the key that is labeled Z on an US keyboard layout". This can lead to a lot of confusion, but at least people wouldn't be forced to use the non-expressive scan codes.
That looks like a good solution, but it should 1. be clear from the API that the "Z" doesn't necessarily match the letter on the key, and 2. it should not be too cumbersome to use (such as a manual mapping of magic numbers).

It would also be nice if one could infer the US-layout key enumerator from a scan code, for things such as a customized key-binding UI. But it seems like with sf::Keyboard::scancode(), this would be possible (iterate through all keys, store the corresponding scan codes, and then reverse the mapping).
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Re: AW: Better keyboard handling
« Reply #49 on: November 29, 2013, 06:13:06 pm »
I see...
An option would be to let the programmer choose a layout while a default is pre-set, thus non-QWERTY keyboard owners wouldn't have to constantly look up the layout.
Sounds like a good alternative to me. So instead of sf::Keyboard::Q, one would do sf::Keyboard::Qwertz::Q etc.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: AW: Better keyboard handling
« Reply #50 on: November 29, 2013, 06:15:12 pm »
Sounds like a good alternative to me. So instead of sf::Keyboard::Q, one would do sf::Keyboard::Qwertz::Q etc.
This will be a huge effort to implement, and very hard to test without dozens of different keyboards. Shouldn't such a feature rather be an addition to SFML, which is brought together by different community members?
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
AW: Re: AW: Better keyboard handling
« Reply #51 on: November 29, 2013, 06:53:38 pm »
This will be a huge effort to implement, and very hard to test without dozens of different keyboards. Shouldn't such a feature rather be an addition to SFML, which is brought together by different community members?
Would it? One most likely just needs to find a good source as reference and testing could then be done by the communtiy.

As we all know native is always better. I'm sure if Thor was part of SFML it would get constantly used, but instead people either don't know it or don't want to build yet another library.
And I really don't want SFML being split into "mandatory" community modules, like with SDL. Besides, fixes can always be applied when needed. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Better keyboard handling
« Reply #52 on: November 29, 2013, 08:34:49 pm »
As we all know native is always better.
Not necessarily. Take Boost as an example: A lot of functionality was included in TR1, and eventually in the C++11 standard. Many errors and design issues could be fixed like this. Once the keyboard mappings are mature enough, SFML could still adopt them. Of course, the comparison is not 100% adequate, because things in the standard library are written in stone for decades, but I think for SFML it's not bad if it has a stable API either ;)

The other advantage of an external project is that it will probably be maintained more actively and a lot of people could have write access, while Laurent could focus his spare time on other important issues. For this specific functionality, you could have a simple header with the mappings for different keyboard layouts in terms of inline functions.

But anyway, it's Laurent's turn to decide on this. I would find it already cool if SFML provided the possibility to even build something like that :)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Better keyboard handling
« Reply #53 on: November 29, 2013, 09:16:19 pm »
I did more tests with SDL, especially scancodes. SDL_Scancode names are those of the standard US keyboard, and SDL_Keycode names are those that match the user's layout (most "standard" symbol of the key, not always the primary one; and modifiers ignored).

So when I press 'A' on my french keyboard, I get a SDL_SCANCODE_Q and SDL_KEYCODE_A. When I press '&', I get SDL_SCANCODE_1 and SDL_KEYCODE_1. There's no inverse lookup function, and no keyboard identification function either.

Does it match what you guys are suggesting?
Laurent Gomila - SFML developer

wintertime

  • Sr. Member
  • ****
  • Posts: 255
    • View Profile
Re: Better keyboard handling
« Reply #54 on: November 29, 2013, 09:37:14 pm »
Yes, I did not look at SDL, but its way of doing seems good to me. Just add those enums, tell in the docs one is for key position, one for keycode/localized label.
(And its already in the docs people should use text event for text input, so the third case is covered, too.)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Better keyboard handling
« Reply #55 on: November 29, 2013, 09:43:59 pm »
I don't like blindly copying SDL :P

What about their keycodes? They chose to return the most "common" symbol of the key, which is a very personal choice. Should I do exactly the same too?
Laurent Gomila - SFML developer

Oldie

  • Newbie
  • *
  • Posts: 34
    • View Profile
Re: Better keyboard handling
« Reply #56 on: November 29, 2013, 09:59:53 pm »
To take two examples, the Qwerty layout and the Azerty layout do not share an identical, physical key distribution:

As you can see, Azerty has:
  • an additional key with "<" and ">" on the bottom-left corner (where Qwerty has a large Shift key),
  • an additional key with "*" and "µ" on the right (where Qwerty has a large Enter key).

And Qwerty has an additional key with "\" and "|" on the top-right corner (where Azerty has a large Backspace key).

Wouldn't these differences, amongst others with other layouts, make things difficult?
Working on a Tic-tac-toe game

Flash

  • Newbie
  • *
  • Posts: 22
    • View Profile
Re: Better keyboard handling
« Reply #57 on: November 30, 2013, 04:16:58 pm »
Hi guys,

I registered for this topic, because it is IMO very important, and almost all games do it wrong. Right now, I'm using only the Audio module of SFML (hope that will change, though). Therefore, I don't know how keyboard handling works currently. I hope I can contribute nevertheless, as I have thought much about this topic. In my opinion we should first try to find out how it should be done, before we determine if it is possible to do it like that. Therefore I want to begin with the gamer's perspective.

The Gamer's Perspective

From a gamer's perspective, keys should sometimes be mapped according to their physical location (e.g. wasd) let's call this "location keybinding", and sometimes according to what is printed on the key (e.g. e for eject, t for target), let's call this "named keybinding". Almost no game has ever done this right, and this was especially problematic during DOS times with nonmappable keybindings. In many cases, the game used a combination of both for determining the layout of the keys. E.g. many flight simulators and space sims use the letter keys for named keybindings and the area around the enter keys for location keybindings. But all of those games use either only scancodes (thus mixing up the named keybindings on non-english keyboards, e.g. Auto-tracking becomes Ctrl-Q on an Azerty keyboard instead of Ctrl-A in Wing Commander 3), or only the characters that the keyboard produces, forcing Alt Gr-( and Alt GR-) on an Azerty keyboard to decrease/increase throttle, instead of the two keys next to Enter in some games.

If a game offers freely chosable keybindings, as soon as the user selects a key it should (obviously) reflect the location of this key (location keybinding). However, it would still be good if an appropriate default keybindings works equally well on all keyboards. Additionally, in the keybindings menu, it should be shown what is actually on the keyboard of the user (named display).

To sum up:
  • A) Some keybindings should be done according to their physical location (location keybinding)
  • B) Some keybindings should be done according to what is printed on the key (named keybinding
  • C) The programmer should think about why he chooses that key and select the appropriate method
  • D) If the keys are shown anywhere in the game, they should always display what the user sees on his keyboard (named display)
  • E) If keys can be redistributed by the user, they should always reflect their physical location (location keybinding)


The Programmers Perspective

The programmer should always put the user first. Therefore, everything that is written above, remains. However, we now have an additional problem: The programmer himself might have a strange keyboard. Thus
  • If he wants to do a location keybinding, how is he supposed to know what the location code for a specific location is?
  • If he does a named keybinding, he could bind on a symbol that is hidden or does not exist on the user's keyboard

Proposal

A possible solution would be to offer to sets of identifiers, location and named identifiers.

A) Location identifiers need to be provided for every key. They could by default be named according to the Qwerty layout. (In all likelihood they would be constants evaluating to the scancode).

(Regarding 1.:) As a convenience for the programmers, alternative names for the most used keyboards could be used. Thus sf::Keyboard::location::semicolon would be equivalent to sf::Keyboard::location::colon, sf::Keyboard::location::Azerty::M and sf::Keyboard::location::Qwertz::OE. A programmer with an even more exotic keyboard would either have to google a picture of a Qwerty keyboard or write a little program that outputs the location identifier for a pressed key. This program could also be provided.

B) Named identifiers do not need to be provided for every key. They should only be provided for the letters and numerics, possibly some additional keys, like Esc or the F-Keys. The reason for the need for named identifiers does not apply to the symbol keys, and the programmer is discouraged from using a symbol as a named identifier that does not exist on a user's keyboard (regarding 2.).
The operating systems keyboard event should provide those. If they need to be converted to location identifiers (most likely for asynchronous key handling), this should also be done by the operating system (but I don't know if it's possible).

C) Additionally, there should be a function like toDescription(...) that takes both location and named identifiers and returns a descriptive text, that should reflect what the user can see on his keyboard. It should be trivial for named identifiers. For location identifiers, this can only be done by the operating system. It should theoretically be possible (the OS takes a scancode and gives a char), but I don't know if this functionality (simulate a keyboard event in order to receive the correct character according to the user's locale) is available on all operating systems

Problems:

This proposal has two problems:
  • There is a minor problem because physical key locations differ as well - E.g the key left of backspace in Qwerty is located in the third row left of return in Azwerty and Qwertz. However, I think we can ignore this. There is no software solution to this problem.
  • There is a major problem because of the overlapping of named and location identifiers. Say I write a game that uses sf::Keyboard::location::semicolon for "adjust throttle to enemy" and the named keybinding 'm' for "missile". Then a French user (hi Laurent) has a problem, because they evaluate to the same key on Azerty.
The only solution to the second problem that I can think of is that it needs to be emphasized in the documentation that if one uses both named and location identifiers in the same game, then the keys must be reassignable. However, an overlap will occur only in very few cases, and it is IMO still a preferrable alternative to the either - or approach taken by most games, where a reassignment (or the ability to memorize nonsensical key combinations) is needed on almost all foreign keyboards.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Better keyboard handling
« Reply #58 on: November 30, 2013, 06:59:49 pm »
Thanks for your detailed feedback. It confirms that we need to do it the SDL way.

One issue that is not addressed in your post though, is what symbol the named keybinding should provide: the default one or the most useful one? On my french keyboard, for example, numbers are not the main symbol of number keys. If I press the '1' key I'll get a '&' (I must press shift to get '1').
« Last Edit: November 30, 2013, 08:46:34 pm by Laurent »
Laurent Gomila - SFML developer

Flash

  • Newbie
  • *
  • Posts: 22
    • View Profile
Re: Better keyboard handling
« Reply #59 on: November 30, 2013, 07:47:59 pm »
Well, I addressed it indirectly, when I said:
They should only be provided for the letters and numerics, possibly some additional keys, like Esc or the F-Keys. The reason for the need for named identifiers does not apply to the symbol keys, and the programmer is discouraged from using a symbol as a named identifier

So if a programmer, who has no idea of a French keyboard, uses a numeric named identifier, because '3' is the key for "triple awesome", it should work on a French keyboard as well. I understand that this is problematic to implement, because without this, one could simply use the character the operation system returns for that key, but that would be " on an Azerty keyboard. The only solution I see (that doesn't involve a hardcoded key schema for every available keyboard) is to ask the OS for both key and shift+key and compare with both (internally), and hope there is no strange keyboard out there that puts numeric keys on other modifiers.

Regarding the key description text, I would just use whatever the operation system provides. If a user does the keybinding himself, he can live with the description " or Shift-".