SFML community forums

General => General discussions => Topic started by: Laurent on November 25, 2013, 11:06:53 pm

Title: Better keyboard handling
Post by: Laurent on November 25, 2013, 11:06:53 pm
Hi

I'm currently working on improving the keyboard support, and after having a look at how other libraries handle it, I think I have what I need to finally provide good support.

However a few design choices have to be made, so I'd like to collect as many ideas/feedback/use cases as possible to make the right decisions.

There are three problems so far:

1) Many keys have 2 or 3 symbols on them. Which one should be reported when the key is pressed? The obvious answer would be "the main one", i.e. the one that is produced when no modifier key is pressed. However the default symbol for a key may not be the most "standard" one; for example, on my french keyboard, pressing '1' yields a '&', and to get a '1' I have to press shift. SDL has a special handling for these keys, so that the numbers are always reported, even if they are not the default symbol. Same for 'ù' and '%', etc.

2) Should modifier keys (shift, alt, control) be interpreted or not? In other words, does the reported symbol changes when we press a modifier key, or should there be only one symbol reported for each key?

3) Should the scancode be reported too? Reminder: the scancode is a hardware-dependent code that represents the physical location of the key on the keyboard. According to SDL sources, although scancodes are hardware dependent, there seems to be standards. The scancode is typically useful when a program provides the ability to choose key bindings; in this case you don't care which key is pressed, you just want to save its code and be able to test it later. Scancodes are better than key codes here because there is always a unique code for each key (within a keyboard), whereas all key that are not part of the sf::Keyboard::Key enum will all have the same code, sf::Keyboard::Unknown.

What other libraries do:

- SDL is pretty accurate, only 2 or 3 keys are not reported correctly on my keyboard. Modifier keys are not interpreted. It provides scancodes.

- GLFW is bad, on Windows it simply returns what the OS gives, which is wrong for almost every non-trivial key on my keyboard. Modifier keys are not interpreted as far as I remember. It provides scancodes.

- Qt is the best, it always reports the right symbol (even ù, é, ç, £, §, ...), its key codes enum is impressive. Modifier keys are interpreted. It provides both scancodes and the native OS key code.

I haven't tested Allegro, which is usually in my reference libraries too.
Title: Re: Better keyboard handling
Post by: eXpl0it3r on November 25, 2013, 11:50:18 pm
I'm glad you've found the time to look into this! :)

Well I guess my conclusion would be: Use Qt's code as much as possible. ;D

Which translates into:
Title: Re: Better keyboard handling
Post by: Veltas on November 25, 2013, 11:50:58 pm
EDIT 2:
Looking at the current KeyboardEvent, I'd keep that the way it is and then add a new event CharacterInputEvent (or something similarly named) that informs of a new character being inputted.

I say separate event because we think about the keyboard keys pressed and the characters inputted separately, and multiple keys can be combined to form one character, for example.

There are troubles, though. International input is quite complicated and sometimes it's not possible to "just input a character", in far eastern locales for example.

I imagine it's worth aiming for whatever a generic text box would receive, if possible.

If you think Qt's key codes enum is impressive perhaps expand sf::Keyboard::Key?

EDIT3:
What does the TextEvent do? Is that what I'm talking about? If so I'm not sure what I'd change other than expanding sf::Keyboard::Key.

EDIT 4:
Perhaps there should be a way SFML provides to get a string that represents the key as well? This would make it easier to refer to keys with localization. On my keyboard the '6' key is a 6, and ^ when combined with a shift, so should be called "6" by this functionality because as a user I would recognize it as such. This would make it easier to tell the user to press a key, etc.
Title: Re: Better keyboard handling
Post by: zsbzsb on November 25, 2013, 11:55:02 pm
In my humble opinion,

1) Report the interpreted symbol, if no modifier key is pressed then this is "the main one". Or if a modifier key is pressed SFML should report the symbol that the modifier key maps to. On my keyboard pressing Shift+1 should be reported as '!'. As far as I know the physical keys (with different symbols that can be reported depending on the modifier key) vary from keyboard to keyboard. So reporting all possible symbols doesn't seem feasible.

2) As in #1, the symbol according to the modifier key should be returned.

3) Returning scan codes would be useful in certain cases, in the end it probably wouldn't matter in most cases if the scan codes are reported or not. I would say return them just because some people would find them useful and at the most it would add one more member to the key event structure.
Title: Re: Better keyboard handling
Post by: Veltas on November 25, 2013, 11:58:20 pm
3) Returning scan codes would be useful in certain cases, in the end it probably wouldn't matter if the scan codes are reported or not. I would say return them just because some people would find them useful and at the most it would add one more member to the key event structure.

I disagree, it would matter if the scan codes were not reported.

When writing specialised controls you'll want to know which keys on the keyboard are being pressed, not the character inputted.

EDIT: And also you could not return them together, as multiple scan codes will correspond to certain characters (i.e. multiple keys pressed to get one input character).

EDIT2: Looking at the current KeyboardEvent, I'd keep that the way it is and then add a new event CharacterInputEvent (or something similarly named) that informs of a new character being inputted. There are troubles, though. International input is quite complicated and sometimes it's not possible to "just input a character", in far eastern locales for example.


Disregard this, look at my original post.
Title: Re: Better keyboard handling
Post by: wintertime on November 26, 2013, 12:31:42 am
For a realtime game one would typically want to know which key is pressed with a bitfield of modifier keys (or sometimes may want modifier keys reported on their own). If suddenly a weird symbol gets returned when a player uses a modifier key at same time it would only be an annoyance.
Even the numpad keys often are tried to make always work with and without num-lock by testing both the Num key and the other functions, but they are mostly standardised. If one player presses shift+3 and gets § send to the game and another ? thats no fun. Always annoying is if games read the < and > keys in the wrong way (as text events) and then on my keyboard those are at a single key near left shift instead of two keys at 3 and 2 positions left of the right shift and you then need to use shift always. Using the key left of backspace is also pretty annoying when on some keyboards its a dead key with ´ and not + or =.

For a more relaxed game one would be also interested in the keys, but would want to always get a Q, A, Z or Y when the player presses whatever key is labeled like that, for example to mark menu shortcuts. There I think the modifiers would be needed separately in a bitfield, too, as the game could be testing for ctrl+alt+Q or alt-gr+Q and not for @.

For typing text into a edit field or text editor you would still want always the right character, not key, from a separate text input event. It would be annoying to manually put together dead keys like ^ or ´ and a following key, especially because there are so many different layouts.
Title: Re: Better keyboard handling
Post by: Oldie on November 26, 2013, 01:02:16 am
  • Interprete the keys as if one would be writing something in a text editor, it's what people essentially expect (unless every game does it the other way around). Although your number keys thing on the French keyboard seems a bit odd... Could you elaborate a bit more on the issue?
  • Interpret modifier keys.
  • And scan codes seem to be kind of a must, since if everything else breaks at the programmers could at least just do everything with scan codes, rather than having to move on from SFML.

Essentially agree with that.
In my current work in progress, players can enter custom player names. So far I have been able to type in special characters, using modifier keys or not, like: &, #, ü, € or ç. So the first two points are needed.
Scan codes sound like an interesting add, which could enable programmers to bind to any type of keyboard if they wished. This sounds like the Linux kernel providing numerous drivers for graphics cards.

If everything mentioned was to be implemented, would this mean that key events be bound to scan codes and not to sf::Keyboard::Key anymore? Or to both, like in Qt?

Also, exploiter, are you just asking how digits are displayed on a French keyboard? Well, instead of being the main characters on the 10-key top row, they are the Shift characters at the same places. So, you have to press Shift + & to get 1, Shift + é to get 2, etc. The joy of Azerty keyboards! ;D
Title: AW: Re: Better keyboard handling
Post by: eXpl0it3r on November 26, 2013, 01:39:41 am
Also, exploiter, are you just asking how digits are displayed on a French keyboard? Well, instead of being the main characters on the 10-key top row, they are the Shift characters at the same places. So, you have to press Shift + & to get 1, Shift + é to get 2, etc. The joy of Azerty keyboards! ;D
That sounds horrible! :o

Thinking about it and discussing it on IRC, I wonder whether it would be enough to provide:

That way one has the full abstraction of the keyboard (scan codes) and their localized  input, while being able to find what other keys are pressed.
Title: Re: Better keyboard handling
Post by: Laurent on November 26, 2013, 09:10:56 am
Important
We don't care at all about text input here. It's the job of the TextEntered event, which already works perfectly. So let's not talk about text boxes or whatever, providing the typed character is not the goal of this modification. We are only talking about finding the most useful way to identify keys for key events.

Modifier keys are already provided separately in key events, so there's no need to discuss them. What must be decided is whether the returned key code is the default one, or the combined one. And I repeat that we don't care about text input ;)

I think we all agree about the usefulness of scancodes.

About providing interpreted keys or "standard" ones, it's complicated. What if someone maps actions or inventory or weapon selection to number keys? On a french keyboard, these keys would be unreachable if we just report the default symbols.

Quote
Fully interpreted keys, similar to what the Text Event does.
Why should we provide something similar to the TextEntered event?
Title: Re: Better keyboard handling
Post by: Nexus on November 26, 2013, 09:37:01 am
Maybe we should not only look how other libraries, but also how games handle keys. If common libraries provide a certain way, but games work around it for the sake of usability, then we can directly look at the latter.

A good example is squad/group assignment in strategy games. Usually, the keys 0-9 are used to refer to a squad, and Ctrl+0-9 to assign it. How does this work on French keyboards, do you have to additionally press Shift?

Laurent also mentioned inventory or weapons, can we gather some ways how games handle them on different keyboards?
Title: Re: Better keyboard handling
Post by: wintertime on November 26, 2013, 10:46:30 am
The strategy game example shows you really want to know the non-modified key(+modifiers the game can interpret itself). The label the localized key would correspond to with current modiers is useless in that case.
Especially when you consider shift+number is often also mapped in strategy games to "add this group to current selection" which could collide with "select only this group".
Some even map alt+number, shift+alt+number, ctrl+alt+number and/or shift+ctrl+alt+number.

Do there exist even more contrived mappings where the numbers are mapped to some completely other keys? Then some games would want those, but others would want the row where they are commonly found.
Title: Re: Better keyboard handling
Post by: Laurent on November 26, 2013, 10:48:00 am
Quote
The strategy game example shows you really want to know the non-modified key
So how do you handle french keyboards, where the non-modified key is not the number?
Title: Re: Better keyboard handling
Post by: wintertime on November 26, 2013, 10:53:28 am
I think if a strategy game maps unmodified key to a hotkey it always wants the same id the number key on non-french keyboards would give. Then you could still use that hotkey only and the game switches to only select the group and if you press shift it would add to selection. That avoids having the mappings collide.
Title: Re: Better keyboard handling
Post by: eXpl0it3r on November 26, 2013, 11:28:32 am
Why should we provide something similar to the TextEntered event?
My point kind of was, that it's more or less useless/"ignorant" to actually define keys like we do now. Why do we assume that there exists a key called "A" or "Z" or ...? How do you define the key A on the following layout?

(https://upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Keyboard_Layout_Armenian.png/420px-Keyboard_Layout_Armenian.png)


So since it's kind of useless trying to define keys after a certain or a few certain layouts, my idea of using scan codes to define the key, returning the actual "character" that gets generated when pressing the key and defining codes for special keys (break, scroll lock, etc), could work with any keyboard layout.
Than again as you said, scancodes are not very consistent either...

It's just an idea and I might be over looking the most obvious fact why one does not do it that way, but it just seems odd to me to define keys based on the latin letters only. Sure I guess the most common layouts are some variants of the American layout, but should one just ignore all the other layouts? ;)
Title: Re: Better keyboard handling
Post by: Laurent on November 26, 2013, 11:41:53 am
Quote
I think if a strategy game maps unmodified key to a hotkey it always wants the same id the number key on non-french keyboards would give. Then you could still use that hotkey only and the game switches to only select the group and if you press shift it would add to selection.
I'm reading this again and again, but, although it looks ok, I fail to understand it ;D
Title: Re: Better keyboard handling
Post by: Veltas on November 26, 2013, 01:07:11 pm
I think he's saying "the number keys on a French keyboard should be interpreted like the numbers on normal keyboards, despite them not actually typing numbers when you hit them without modifiers".
Title: Re: Better keyboard handling
Post by: Lo-X on November 26, 2013, 01:10:52 pm
Quote
I think if a strategy game maps unmodified key to a hotkey it always wants the same id the number key on non-french keyboards would give. Then you could still use that hotkey only and the game switches to only select the group and if you press shift it would add to selection.
I'm reading this again and again, but, although it looks ok, I fail to understand it ;D

In a game like Warcraft 3, where '1', '2' '3', ... are mapped to unit control, french keyboard works well (I mean, no need for shift).

From a game developper point of view, we shouldn't return the modified key but the standard key and check if the modifier is pressed. Yes it's a check we have to do but it also allow more flexible things (I think).

Plus, if I understand it well, if we return interpreted keys, there will be a difference between 'a' and 'A' (upper/lower case). In a game, I want my 'a' or capslock+'a' key to do the same, but 'Shift'+'A' to be mapped to any other action I want to.
Title: Re: Better keyboard handling
Post by: Laurent on November 26, 2013, 01:27:47 pm
Quote
In a game like Warcraft 3, where '1', '2' '3', ... are mapped to unit control, french keyboard works well (I mean, no need for shift).

From a game developper point of view, we shouldn't return the modified key but the standard key and check if the modifier is pressed
But how do you know that '1' is pressed on a french keyboard if SFML returns the unmodified key ('&') ? Even if you know that the 'shift' key is pressed, but that won't give you the corresponding modified key ('1').

If we only return the unmodified key, there's no way to know that '1' is pressed on a french keyboard. So we must either change the "default" symbol for some keys (like SDL does), or return all the possible symbols of the pressed key.

Quote
Plus, if I understand it well, if we return interpreted keys, there will be a difference between 'a' and 'A' (upper/lower case).
APIs that return interpreted keys usually don't differenciate between upper case and lower case letters. There's only one Key::A constant.
Title: Re: Better keyboard handling
Post by: Lo-X on November 26, 2013, 02:03:04 pm
But how do you know that '1' is pressed on a french keyboard if SFML returns the unmodified key ('&') ? Even if you know that the 'shift' key is pressed, but that won't give you the corresponding modified key ('1').

If we only return the unmodified key, there's no way to know that '1' is pressed on a french keyboard. So we must either change the "default" symbol for some keys (like SDL does), or return all the possible symbols of the pressed key.

That's what I wanted to say : we should return '1' instead of '&' on french keyboard (or any other keyboard in that case). What I meant in "standard" was "the same for anyone whenever possible".
I don't know how it's coded in any library, so I don't know if it's hard to do.
I just think, what about special keys (symbols, etc..) ? Is there a way to standardise them ? The more I think about it, the more it becomes tricky.

I agree with Nexus to looking at this from a game point of view. Also I know this is not a video game lib. Plus, it's true that hotkeys kinda solve the problem, but it's not always implemented. [I'm going nut here :p ] If I had to chose one of the three models you gave in the first post, I would chose the SDL one.

APIs that return interpreted keys usually don't differenciate between upper case and lower case letters. There's only one Key::A constant.

So that's perfect :)
Title: Re: Better keyboard handling
Post by: eXpl0it3r on November 26, 2013, 02:33:21 pm
It seems like I know nothing about foreign keyboards (see here (http://superuser.com/questions/193931/how-do-people-type-different-languages-into-computer)), so I guess one can work on top of a few different layouts.
Title: Re: Better keyboard handling
Post by: Tank on November 26, 2013, 03:05:16 pm
Let's see what we mostly need in games:
Point 1 is to support any type of keyboard and key. It doesn't matter which key it is. Because point 1 does not give any information about the key itself, there needs to be a descriptive name, or in case of a printable character the character itself. Point 3 gives information about key presses of a pre-defined subset of generally available keys (unprintable keys mostly), so that key combinations can be implemented (Ctrl+A etc.). It could be an enum containing these values for example: PrintableKey, Control, Shift, Tab, ...

Such an event structure allows me to use any key I want, get a name for it for using it visually and interpret keys that are available across all keyboards, e.g. for key combinations.
Title: Re: Better keyboard handling
Post by: Laurent on November 26, 2013, 03:18:59 pm
Quote
Such an event structure allows me to use any key I want, get a name for it for using it visually and interpret keys that are available across all keyboards, e.g. for key combinations.
It still doesn't solve the number keys issue, does it?
Title: Re: Better keyboard handling
Post by: Tank on November 26, 2013, 03:22:48 pm
I think it does. On your keyboard, the key's name would be "&", on my keyboard it'd be "1". The scan code is completely irrelevant. The key mapping as well, because it's a printable character/no special key.
Title: Re: Better keyboard handling
Post by: Laurent on November 26, 2013, 03:35:10 pm
So what do you write in your code to refer to that key, so that it works with any layout?
Title: Re: Better keyboard handling
Post by: Tank on November 26, 2013, 03:56:30 pm
There's no general solution, because it depends on the layout (just like languages/localization).

What you can do however is providing good defaults, either depending on the target system including language (a French installation will probably use a AZERTY-compatible keyboard) and keyboard type (to be honest I don't know if there's a good way of detecting the active keyboard layout on all systems SFML supports).

So in the end it'll be something like this:
keys["de"][Action::JUMP] = "1";
keys["fr"][Action::JUMP] = "&";
Title: Re: Better keyboard handling
Post by: wintertime on November 26, 2013, 04:08:09 pm
One more try. :P
The point is to separate your thinking of the different involved things:
1. key on the keyboard (example is key second row at 4th column)
2. the labels on it (american (3, #, nothing) or german (3, §, ³) or french (", 3, #))
3. the character it would produce in combination with formerly pressed dead keys and currently pressed modifier keys (if no modifier is pressed its in many layouts '3' and on some '"')

1. Would be prefered for many games so they dont need to do some guesswork on backwards-translate what the library forward-translated, because they would test a constant of KEY_ROW2_COLUMN4 or KEY_COLUMN4_ROW2 (or for "convenience" a library may call it KEY_3 if its believed by its creator it would apply to the majority of layouts even though it may mean something else on some layouts). The constants may have much in common with the scan code, but there are quirks.
2. It may in some ways be wanted by a game to know what label to print on screen when the key gets pressed, but it gets ambiguous with the many layouts, though it may be convenient in some situations to get KEY_LABELED_3 event always when any key is pressed that includes that label if its primary, secondary or third class. For example a game shows a list labeled 1 to 10 and wants to know when some key with such a label gets pressed (but for that the text-event may be reused instead as an inferior alternative). I'm not sure but this may be got from the VK_ constants in Windows or other things on other OS.
3. Would be the domain of the character text input event, not the key event. And here you would like to get UTF-32 codes.
Title: Re: Better keyboard handling
Post by: Laurent on November 26, 2013, 04:21:00 pm
Scancodes are great when key bindings are configured by the user itself. But if you want to provide a fixed binding programmatically (sf::Key::Num1 => "select first weapon"), this is still not possible with what you said. Even text events wouldn't help, since they would produce '&' on french keyboards. The only solution to this problem is to somehow provide all the symbols of the key, or force '1' to be the default even if it would normally require a modifier in order to be outputed.
Title: Re: Better keyboard handling
Post by: Tank on November 26, 2013, 04:45:02 pm
Laurent:
If you replied to my post, then no, the only solution is to provide a set of default values for each layout.
Title: Re: Better keyboard handling
Post by: Laurent on November 26, 2013, 04:52:07 pm
I was replying to wintertime (sorry it was not clear). Your previous post was explicit enough about the lack of simple solution to this problem :P
Title: Re: Better keyboard handling
Post by: zsbzsb on November 26, 2013, 05:04:19 pm
The only solution to this problem is to somehow provide all the symbols of the key

I don't see how that is possible considering the symbols on the physical keys changes depending on the keyboard. For example you have a '&' and a '1' on your first number key, yet on my US layout I have '1' and '!' together on my first key.
Title: Re: Better keyboard handling
Post by: Nexus on November 26, 2013, 05:47:29 pm
However the default symbol for a key may not be the most "standard" one; for example, on my french keyboard, pressing '1' yields a '&', and to get a '1' I have to press shift. SDL has a special handling for these keys, so that the numbers are always reported, even if they are not the default symbol. Same for 'ù' and '%', etc.
Since SDL as well as games seem to interpret the number keys always as numbers, why don't we do it, too?

Should modifier keys (shift, alt, control) be interpreted or not? In other words, does the reported symbol changes when we press a modifier key, or should there be only one symbol reported for each key?
I find it most intuitive if every key enumerator corresponds to one physical key (and if the keyboard has too few keys, some enumerators are unused), and thus, modifiers are not taken into account. In most games, modifiers are used explicitly; the worst I could imagine is a reverse-mapping on developer side to make different keyboards behave similarly.

The question is then, how do we name the special keys (comma, dash, ...). I would suggest to use the American layout as reference. Figuring out which key corresponds on a different key layout looks acceptable to me...

About scancodes, how did you imagine to provide them API-wise? Also as part of the sf::Event object created by the KeyPressed event?
Title: Re: Better keyboard handling
Post by: Laurent on November 26, 2013, 07:54:05 pm
Quote
I don't see how that is possible considering the symbols on the physical keys changes depending on the keyboard. For example you have a '&' and a '1' on your first number key, yet on my US layout I have '1' and '!' together on my first key.
So SFML would report '&' and '1' on a french keyboard, and '1' and '!' on a US keyboard. Since both contain '1', your weapon selection code can work in both cases.
But it's just an idea. It doesn't seem to be a standard way of doing it.

Quote
Since SDL as well as games seem to interpret the number keys always as numbers, why don't we do it, too?
I would prefer finding a general rule, but if it's the best solution I'll do it. Then we should also think about all the other keys, it's not just about numbers.

Quote
The question is then, how do we name the special keys (comma, dash, ...). I would suggest to use the American layout as reference. Figuring out which key corresponds on a different key layout looks acceptable to me...
Something like this?

if (event.type == sf::Event::KeyPressed)
{
    if (layout == "us" && event.key.code == sf::Keyboard::Num1
     || layout == "fr" && event.key.code == sf::Keyboard::Ampersand
     || layout == ".." && event.key.code == ..
     || ...)
    {
        // '1' was pressed :)
    }
???

Quote
About scancodes, how did you imagine to provide them API-wise? Also as part of the sf::Event object created by the KeyPressed event?
Yes, and the corresponding functions in sf::Keyboard.
Title: Re: Better keyboard handling
Post by: Laurent on November 26, 2013, 07:56:48 pm
Just a new idea: maybe a reverse lookup function would do the job

if (event.key.scancode == sf::Keyboard::scancode(sf::Keyboard::Num1)) // if same physical key as '1', whatever its default symbol is
{
    // '1' is pressed
}
Title: Re: Better keyboard handling
Post by: wintertime on November 26, 2013, 08:20:19 pm
There seem to be 3 sets of scancodes, but most keyboards would use same set.
According to http://retired.beyondlogic.org/keyboard/keybrd.htm you could mostly just do:
if(event.key.scancode == 0x16)
{
    event.key.code = sf::Keyboard::Num1;
}
 
Title: Re: Better keyboard handling
Post by: Laurent on November 26, 2013, 08:55:18 pm
According to SDL source code, yes, there are standards for scancodes. They refer to the USB standard, but I haven't had a look at it. However the SDL sources have different lookup tables for each OS. Maybe that's something worth investigating.

But how would it help? Obviously you would have to name scancodes (sf::Scancode::Num1 instead of 0x16), like SDL does, but you just move the problem from key codes to scancodes, i.e. which scancode is returned when you press '1' on a french keyboard: Scancode::Num1 or Scancode::Ampersand?
Title: Re: Better keyboard handling
Post by: Tank on November 26, 2013, 09:10:02 pm
I still can't see how providing constants for dynamic things shall work at all.. If Scancode::Num1 can be different across platforms/keyboard, then I think the design is flawed.
Title: Re: Better keyboard handling
Post by: wintertime on November 26, 2013, 10:11:29 pm
Keyboards are so quirky you always have to remap some codes. But from what I read at http://www.scs.stanford.edu/10wi-cs140/pintos/specs/kbd/scancodes-9.html#ss9.5 (there are many more pages dedicated to scan codes including pictures with national mappings) they are much more standardized than national layouts.
Set 1 and 3 seem to be out of fashion for a long time (whos gonna run a XT with an 8088 cpu and set 1?), set 2 is used mostly and also USB-legacy support produces set 2 only. Though some linuxes may try to run with set 3 (I hope there is some setting available to read from OS to tell this situation).
It obviously is a difficult thing and needs much testing, but I would think most keys would produce same scan code on same physical key position on different layouts. And it feels better than back-translating 100 localized layouts.

Edit: Its even more complicated, windows may map the perfectly good set 2 scan codes to set 1 scan code. http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc
Title: Re: Better keyboard handling
Post by: Josh_M on November 26, 2013, 11:08:07 pm
As someone completely uneducated on the topic, what is wrong with using the USB codes on that list from wintertime? I assume it's because some embedded/propriety formats (ie: laptops) or PS/2 connections have different input.
Title: Re: Better keyboard handling
Post by: Mario on November 27, 2013, 02:07:44 am
The most common input handling should always work with scancodes IMO. I simply hate having games with odd controls just because someone based it on the QWERTY layout (e.g. having to use X and Z, while Z and Y are swapped on German layouts compared to English ones).

Events like "Text entered" could report the resulting key.

Also to note: At least SDL 1.2 was inconsistent with keys as well, not sure how/if that's changes since then though.

Scancode/key conversion: Never do it manually! This should be done on operating system level.

Also there should be some easy accessible way to convert a scancode to a readable "label" for that specific key. This one would have to be based on the current keyboard layout.
Title: Re: Better keyboard handling
Post by: Tank on November 27, 2013, 08:05:51 am
I agree to Mario. From what I understood it's exactly what I proposed as well. :)
Title: Re: Better keyboard handling
Post by: Laurent on November 27, 2013, 08:26:11 am
Answering "we must use scancodes" is not enough. How do you identify them in the API (a number or a named constant)? How would they be used (how do you implement consistent WSAD movement in your game)? How do they solve the various problems that were mentioned in this thread?

I really think we need some details now ;)
Title: Re: Better keyboard handling
Post by: Tank on November 27, 2013, 08:37:49 am
What if SFML allows to identify the keyboard model and provides enums for the most common used standardized scan codes? This allows to hardcode key mappings in source code, depending on the active layout of the user.

So, when a key event in SFML is triggered, it carries the scan code + a readable label (character itself or name of special key). The developer can then go and compare it with the active model's scan mode mapping table, like this:

if( event.type == sf::Event::KeyPressed ) {
  if( event.key.scanCode == sf::Keyboard::toScanCode( sf::Keyboard::Q ) ) {
    std::cout << "Key " << event.key.label << " was pressed." << std::endl;
    // ...
  }
}

getScanCode translates into a scan code that's valid for the active keyboard layout. Maybe there could even be a sf::KeyboardLayout that holds the key code<->scan code mappings shown above.

sf::Keyboard::Q is still a key code, a way to specify the location of the key I want to listen for. This just has to be defined in SFML and can't be implemented to work localized for everybody (i.e. when I, as a German, give sf::Keyboard::Z, then the QWERTY Z key will be targeted, not the QWERTZ Z key).
Title: Re: Better keyboard handling
Post by: Laurent on November 29, 2013, 04:21:13 pm
No more idea / comment / whatever?
Title: Re: Better keyboard handling
Post by: Nexus on November 29, 2013, 04:37:06 pm
What were the main problems with the current system, apart from missing keys? If that's clear for everyone, it might be easier to focus on a corresponding solution...
Title: Re: Better keyboard handling
Post by: Laurent on November 29, 2013, 04:46:15 pm
Quote
What were the main problems with the current system, apart from missing keys?
Everything that is explained in the first post ;)
Title: Re: Better keyboard handling
Post by: eXpl0it3r on November 29, 2013, 05:17:42 pm
From my perspective we need/want:

I can see the following solutions:

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:
Title: Re: Better keyboard handling
Post by: Tank 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.
Title: AW: Better keyboard handling
Post by: eXpl0it3r 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.
Title: Re: Better keyboard handling
Post by: Nexus 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).
Title: Re: AW: Better keyboard handling
Post by: Tank 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.
Title: Re: AW: Better keyboard handling
Post by: Nexus 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?
Title: AW: Re: AW: Better keyboard handling
Post by: eXpl0it3r 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. ;)
Title: Re: Better keyboard handling
Post by: Nexus 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 :)
Title: Re: Better keyboard handling
Post by: Laurent 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?
Title: Re: Better keyboard handling
Post by: wintertime 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.)
Title: Re: Better keyboard handling
Post by: Laurent 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?
Title: Re: Better keyboard handling
Post by: Oldie 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:

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?
Title: Re: Better keyboard handling
Post by: Flash 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:


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

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:
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.
Title: Re: Better keyboard handling
Post by: Laurent 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').
Title: Re: Better keyboard handling
Post by: Flash 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-".
Title: Re: Better keyboard handling
Post by: Laurent on November 30, 2013, 08:49:39 pm
Quote
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 what should I do for keys with punctuation marks, or other symbols? Choose the most "standard" symbol, or define no key code for them?
Title: Re: Better keyboard handling
Post by: Flash on November 30, 2013, 10:11:29 pm
Quote
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 what should I do for keys with punctuation marks, or other symbols? Choose the most "standard" symbol, or define no key code for them?
As I said, IMO there should be no named key definitions for those keys. There should however be location definitions for them (example with semicolon key).
The reason for the need of named keys is so that keys can be bound according to a named patter (e.g. 't' for target, 'm' for missile, etc.). This reason does not exist for symbolic keys. They are chosen because of their location. If you allowed programmers to do named keybindings on symbolic keys, we would end up with games that have nonsensical key assignments on foreign keyboards. Furthermore, the second problem I mentioned would get much bigger, because there would be even more possible overlap between named and location keybindings.
Title: Re: Better keyboard handling
Post by: Ixrec on April 06, 2014, 09:01:16 pm
Since I can't find any recent discussions on this with the forum search...

I don't think "named identifiers" can be part of a true solution to international keyboard handling, because any alphanumeric key we're familiar with may not exist on other keyboards, as shown back on page 1 by exploter's Armenian keyboard example:
(https://upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Keyboard_Layout_Armenian.png/420px-Keyboard_Layout_Armenian.png)
So even if we wanted to let the programmer bind "missile" to the "m" key or "group 7" to the "7" key, we can't even guarantee there is an m key or a 7 key at all, much less agonize over how to locate it.

To use Flash's terminology: "named keybinding" is simply not possible in general (not even for number keys!), so you need to use "location keybinding" and "named display" for everything.

The only good use for key names is to give developers an easy way of specifying key locations.  In fact, sf::Keyboard already seems to be representing key locations (eg, it has 'A' but no 'a', 'Num1' but no '!').

So in my admittedly uneducated opinion, the best solution is to do the following:
1) add scancodes (which is already happening in 2.2, yay!)
2) add some means of getting a human-readable description of a scancode, ie "named display", since every game with a tutorial or a key bindings menu will need this (and I'm sure you could make something far better than what I've hacked together for my program).  Perhaps a Keyboard::getDescription() method taking a sf::Keyevent or scancode and returning a string.
3) ideally, rename the "code" member of sf::KeyEvent to "location", because that's what it currently is (or at least what it should be going forward); obviously this would have to wait until SFML 3

Regarding the French keyboard number row issue: The value sf::Keyboard::Num1 should represent the physical location that the 1 key is at on a QWERTY keyboard, not the "1" character that may or may not be its default binding on some other keyboard, in which case simply doing if(e.location == sf::Keyboard::Num1) would work just fine.  No extra hassle for the users, and no changes to the public API except renaming that one member someday.


P.S. I'd also like an sf::Joystick::getDescription() someday (the best I can give the user right now is "positive movement along axis 2") though I have no idea how feasible that might be.
Title: Re: Better keyboard handling
Post by: Laurent on April 06, 2014, 09:16:19 pm
Thanks for your feedback, it is very important with SFML 2.2 approaching (even if it won't include the final solution) :)

Quote
I'd also like an sf::Joystick::getDescription() someday (the best I can give the user right now is "positive movement along axis 2")
A description for what? Axes? They are already clearly identified (X, Y, POV, etc.).
Title: Re: Better keyboard handling
Post by: Ixrec on April 06, 2014, 09:52:12 pm
I mean strings like "left trigger pressed" or "right analog stick up" for an Xbox controller, etc.  Analogous to how Keyboard::getDescription(sf::Keyboard::Num1) might return "1" for my keyboard and "&" for yours.  But that's another subject, a much lower priority, and (I assume) a much harder feature to implement.
Title: Re: Better keyboard handling
Post by: Laurent on April 06, 2014, 11:03:43 pm
Indeed, I don't even think it is possible to implement.

Let's go back to the original topic ;)
Title: Re: Better keyboard handling
Post by: Senzaki on April 14, 2014, 10:28:11 am
Well, if someone needs scancodes before SFML 2.2 comes out, I implemented their support because I needed them in my project. See this pull request (https://github.com/SFML/SFML/pull/568) for more details. The way scancodes are translated to "SFML scancodes" is exactly the same as in SDL. (Note : I don't expect it to be directly integrated in SFML, but at least it could give ideas for a better implementation.)
Title: Re: Better keyboard handling
Post by: Flash on April 18, 2014, 08:03:06 pm
Since I can't find any recent discussions on this with the forum search...

I don't think "named identifiers" can be part of a true solution to international keyboard handling, because any alphanumeric key we're familiar with may not exist on other keyboards, as shown back on page 1 by exploter's Armenian keyboard example:
(https://upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Keyboard_Layout_Armenian.png/420px-Keyboard_Layout_Armenian.png)
So even if we wanted to let the programmer bind "missile" to the "m" key or "group 7" to the "7" key, we can't even guarantee there is an m key or a 7 key at all, much less agonize over how to locate it.

To use Flash's terminology: "named keybinding" is simply not possible in general (not even for number keys!), so you need to use "location keybinding" and "named display" for everything.

That is correct, and I have to admit that was a stupid oversight on my part.
However, I already stated that it should be made absolutely clear that if the developer uses named keybindings, he should also offer the possibility to customize keys. So people with a non-latin keyboard would have to customize keys.
Therefore, I still think named keybindings make sense. If you don't allow named keybindings, you only increase the number of people who have to customize.
With named keybindings => everybody without a latin keyboard needs to reassign keys.
Without named keybindgs => everybody without a qwerty keyboard needs to reassign keys.
Title: Re: Better keyboard handling
Post by: Ixrec on April 18, 2014, 08:57:02 pm
I agree in the sense that I think key locations should be referred to by their QWERTY names (is there any other sensible way to do it?), which implies we'd get named binding support "for free" on QWERTY keyboards.  I see no reason to restrict this implicit support, though it'd be nice if the property was eventually renamed "location" as I suggested so that developers are more likely to realize that any named bindings they use won't work on other keyboards.

I'm a little more skeptical on the idea of supporting named keybinding across all latin keyboards, because this would probably force SFML to answer tricky questions like "is A equal to a?" and "is á equal to a?", or require the programmer to provide equivalence classes for each character.  Not to mention there's always the possibility the a/á/whatever key conflicts with a location binding (I think you said earlier that this is negligible, but it's still nonzero).  And there's even weirder cases: if I ask for the "i" key on a Turkish keyboard (http://www.elgin.free-online.co.uk/turkish_de.gif), which one do I get?  Dotted i or dotless i?  (you may say obviously the dotted one, but what if I asked for the "I" key instead? should I then get the dotless i key?).  And that's just the complications I can think of off the top of my head.

To sum up: I think named bindings for all latin keyboards would be nice, but I'm not sure it's possible without embedding a lot of extremely arbitrary and fragile rules into SFML.  Putting those rules into an extension might be a good idea though (maybe some extra methods in thor::ActionMap?).

EDIT: It's possible Windows virtual key codes already attempt to do this, so maybe SFML is already inheriting from Windows' built-in arbitrary rules.  No idea about Mac and Linux.  If all three do have something similar, I would be in favor of exposing it in SFML (in addition to scan codes and locations).


P.S. I'm not sure about the claim that necessarily more people "need" to rebind all their keys if developers don't do named keybinding, but that probably depends heavily on the genre.  For the stuff I play (platformers, puzzle games, action games) I find the locations of the keys is infinitely more important than the letters that happen to be on them (eg, WASD have nothing to do with up/left/down/right, and no one minds).  I assume in strategy or simulation games where you have far more keys, there's more benefit to named binding.  Are those the use cases you're thinking of?
Title: Re: Better keyboard handling
Post by: Flash on April 19, 2014, 10:49:50 am
To sum up: I think named bindings for all latin keyboards would be nice, but I'm not sure it's possible without embedding a lot of extremely arbitrary and fragile rules into SFML.  Putting those rules into an extension might be a good idea though (maybe some extra methods in thor::ActionMap?).

EDIT: It's possible Windows virtual key codes already attempt to do this, so maybe SFML is already inheriting from Windows' built-in arbitrary rules.  No idea about Mac and Linux.  If all three do have something similar, I would be in favor of exposing it in SFML (in addition to scan codes and locations).
I agree. I wrote about named identifiers:
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).
So just to clarify: If it is not possible to do it via the operating system, I wouldn't propose to implement it in SFML. That would indeed induce a lot of headache.

P.S. I'm not sure about the claim that necessarily more people "need" to rebind all their keys if developers don't do named keybinding, but that probably depends heavily on the genre.  For the stuff I play (platformers, puzzle games, action games) I find the locations of the keys is infinitely more important than the letters that happen to be on them (eg, WASD have nothing to do with up/left/down/right, and no one minds).  I assume in strategy or simulation games where you have far more keys, there's more benefit to named binding.  Are those the use cases you're thinking of?
Yes, it is heavily depending on the genre. For a platformer the location is indeed the most important aspect.
Flight & Space sims are the most notorious ones in the other direction. There are games that have two or three function on every key (in combination with CTRL and ALT), and those are usually selected according to their name in order to ease memorization. Here's the example of X-Wing Alliance (http://www.allgame.com/game.php?id=17144&tab=controls), which is an arbitrary mix of named and location binding.
Title: Re: Better keyboard handling
Post by: Ixrec on April 19, 2014, 11:50:39 am
Flight & Space sims are the most notorious ones in the other direction. There are games that have two or three function on every key (in combination with CTRL and ALT), and those are usually selected according to their name in order to ease memorization. Here's the example of X-Wing Alliance (http://www.allgame.com/game.php?id=17144&tab=controls), which is an arbitrary mix of named and location binding.

Thanks for the link.

After looking up tons of keyboard layouts I've come to the conclusion that named bindings for just the letters A-Z are completely safe across all keyboards, assuming the only other bindings used are QWERTY-location bindings for numbers, puncutation and control keys (ie no non-English letters), and assuming those named A-Z bindings fall back to location bindings on systems where the keys do not exist (which SO told me Windows does).

So, since you said that game uses a mix of named and location, do you happen to know if all of its number/punctuation mark bindings are location-based?  And what most other games like this do?

Here's some of the conflicts I found that might occur if someone used named binding for punctuation and/or numbers:
Title: Re: Better keyboard handling
Post by: Flash on April 19, 2014, 03:43:52 pm
Thanks for the link.

After looking up tons of keyboard layouts I've come to the conclusion that named bindings for just the letters A-Z are completely safe across all keyboards, assuming the only other bindings used are QWERTY-location bindings for numbers, puncutation and control keys (ie no non-English letters), and assuming those named A-Z bindings fall back to location bindings on systems where the keys do not exist (which SO told me Windows does).
I don't think this is correct. As I wrote in my first post in this topic, French AZERTY keyboard have the letter M in the position of the semicolon on a QWERTY keyboard.

Quote
So, since you said that game uses a mix of named and location, do you happen to know if all of its number/punctuation mark bindings are location-based?  And what most other games like this do?
I did not express myself very well here. What I meant is that it is clear by the design of the shortcuts to be a mix of name and location. As I said, I don't know any game that actually implements this correctly. All the games I know implement either location keybinding, which makes shortcuts hard to memorize or named keybinding, which is even worse, and forces you to press key combinations for what was intended to be a simple keystroke on some keyboards. I don't know by heart what XWA does, but it does allow re-assignment, so it could be dealt with.

Quote
Here's some of the conflicts I found that might occur if someone used named binding for punctuation and/or numbers:
  • On the "KazWin" keyboard, . and , are the same key
  • On the Serbian keyboard, ; and , are the same key
  • On Russian keyboards, 4 and ; are the same key
  • On Russian (Typewriter) keyboards, 6 and , are the same key
  • On most Central/South American keyboards, Q and @ are the same key
  • I'm fairly sure I saw a keyboard whose number row had 1,2,3,4,6, but none of 5,7,8,9,0.  I can't remember which one this was now.
I also said that for this reason I would not suggest including named keybindings for anything beyond alphabet and numbers. There is no reason for their existence (you cannot easily memorize the keystroke, because a punctuation mark is not the beginning of a word), and it only leads to conflicts.
So apart from the last one (which seems really strange to me), those shouldn't be a problem. The only conflict I see thus far is the M / ; conflict, if M is bound by name and ; by location.
Title: Re: Better keyboard handling
Post by: Ixrec on April 19, 2014, 06:45:16 pm
I don't think this is correct. As I wrote in my first post in this topic, French AZERTY keyboard have the letter M in the position of the semicolon on a QWERTY keyboard.

Damn, missed that one.


Well it seems like we agree on everything that matters anyway.  Maybe future tutorials on keyboard handling should have a big warning about not using named bindings unless you also provide rebinding.

Should we try to make some concrete proposals for how SFML should implement/expose this stuff?  My first thought is simply giving the key event "scancode", "location" and "vkey" properties.
Title: Re: Better keyboard handling
Post by: Flash on April 20, 2014, 07:39:24 pm
Should we try to make some concrete proposals for how SFML should implement/expose this stuff?  My first thought is simply giving the key event "scancode", "location" and "vkey" properties.
I don't know, I had the impression that Laurent likes to think about those things by himself.
If he wants us to, we can try to make some proposals.
Title: Re: Better keyboard handling
Post by: Nexus on April 20, 2014, 07:47:22 pm
We always appreciate ideas, that's why Laurent opened this thread :)

However I don't know how much of the functionality you're currently discussing will make it into SFML 2.2 -- the plan is to release it rather soon, and to add basic scancode support. In a first version, this might entail only unnamed integers that can be used for comparison (key rebinding). This way, we have enough time to discuss all the advantages and drawbacks of different naming possibilites, experiment with them and test them thoroughly, and we don't have to implement a last-minute solution that will soon prove as not ideal.
Title: Re: Better keyboard handling
Post by: Jabberwocky on July 06, 2014, 10:09:31 pm
I thought I'd add my experiences using OIS (http://sourceforge.net/projects/wgois/) (object oriented input system) in a video game.  I think it mostly confirms what has already been decided.

OIS reports an OIS::KeyEvent when keyboard keys are pressed.

Code: [Select]
   class _OISExport KeyEvent : public EventArg
   {
   public:
      KeyEvent(Object* obj, KeyCode kc, unsigned int txt) : EventArg(obj), key(kc), text(txt) {}
      virtual ~KeyEvent() {}

      //! KeyCode of event
      const KeyCode key;
      //! Text character, depends on current TextTranslationMode
      unsigned int text;
   };

KeyCode is a scan code.  For game controls, you always key map using these KeyCodes (scan codes).
KeyCode is just a handy enum which enumerates the scan codes, presumably according to an American keyboard.

Code: [Select]
//! Keyboard scan codes
enum KeyCode
{
KC_UNASSIGNED  = 0x00,
KC_ESCAPE      = 0x01,
KC_1           = 0x02,
KC_2           = 0x03,
KC_3           = 0x04,
KC_4           = 0x05,
KC_5           = 0x06,
KC_6           = 0x07,
KC_7           = 0x08,
KC_8           = 0x09,
KC_9           = 0x0A,
KC_0           = 0x0B,
KC_MINUS       = 0x0C,    // - on main keyboard
KC_EQUALS      = 0x0D,
KC_BACK        = 0x0E,    // backspace
KC_TAB         = 0x0F,
KC_Q           = 0x10,
KC_W           = 0x11,
KC_E           = 0x12,
KC_R           = 0x13,
KC_T           = 0x14,
KC_Y           = 0x15,
KC_U           = 0x16,
KC_I           = 0x17,
KC_O           = 0x18,
KC_P           = 0x19,
KC_LBRACKET    = 0x1A,
KC_RBRACKET    = 0x1B,
KC_RETURN      = 0x1C,    // Enter on main keyboard
KC_LCONTROL    = 0x1D,
KC_A           = 0x1E,
KC_S           = 0x1F,
KC_D           = 0x20,
KC_F           = 0x21,
KC_G           = 0x22,
KC_H           = 0x23,
KC_J           = 0x24,
KC_K           = 0x25,
KC_L           = 0x26,
KC_SEMICOLON   = 0x27,
KC_APOSTROPHE  = 0x28,
KC_GRAVE       = 0x29,    // accent
KC_LSHIFT      = 0x2A,
KC_BACKSLASH   = 0x2B,
KC_Z           = 0x2C,
KC_X           = 0x2D,
KC_C           = 0x2E,
KC_V           = 0x2F,
KC_B           = 0x30,
KC_N           = 0x31,
KC_M           = 0x32,
KC_COMMA       = 0x33,
KC_PERIOD      = 0x34,    // . on main keyboard
KC_SLASH       = 0x35,    // / on main keyboard
KC_RSHIFT      = 0x36,
KC_MULTIPLY    = 0x37,    // * on numeric keypad
KC_LMENU       = 0x38,    // left Alt
KC_SPACE       = 0x39,
KC_CAPITAL     = 0x3A,
KC_F1          = 0x3B,
KC_F2          = 0x3C,
KC_F3          = 0x3D,
KC_F4          = 0x3E,
KC_F5          = 0x3F,
KC_F6          = 0x40,
KC_F7          = 0x41,
KC_F8          = 0x42,
KC_F9          = 0x43,
KC_F10         = 0x44,
KC_NUMLOCK     = 0x45,
KC_SCROLL      = 0x46,    // Scroll Lock
KC_NUMPAD7     = 0x47,
KC_NUMPAD8     = 0x48,
KC_NUMPAD9     = 0x49,
KC_SUBTRACT    = 0x4A,    // - on numeric keypad
KC_NUMPAD4     = 0x4B,
KC_NUMPAD5     = 0x4C,
KC_NUMPAD6     = 0x4D,
KC_ADD         = 0x4E,    // + on numeric keypad
KC_NUMPAD1     = 0x4F,
KC_NUMPAD2     = 0x50,
KC_NUMPAD3     = 0x51,
KC_NUMPAD0     = 0x52,
KC_DECIMAL     = 0x53,    // . on numeric keypad
KC_OEM_102     = 0x56,    // < > | on UK/Germany keyboards
KC_F11         = 0x57,
KC_F12         = 0x58,
KC_F13         = 0x64,    //                     (NEC PC98)
KC_F14         = 0x65,    //                     (NEC PC98)
KC_F15         = 0x66,    //                     (NEC PC98)
KC_KANA        = 0x70,    // (Japanese keyboard)
KC_ABNT_C1     = 0x73,    // / ? on Portugese (Brazilian) keyboards
KC_CONVERT     = 0x79,    // (Japanese keyboard)
KC_NOCONVERT   = 0x7B,    // (Japanese keyboard)
KC_YEN         = 0x7D,    // (Japanese keyboard)
KC_ABNT_C2     = 0x7E,    // Numpad . on Portugese (Brazilian) keyboards
KC_NUMPADEQUALS= 0x8D,    // = on numeric keypad (NEC PC98)
KC_PREVTRACK   = 0x90,    // Previous Track (KC_CIRCUMFLEX on Japanese keyboard)
KC_AT          = 0x91,    //                     (NEC PC98)
KC_COLON       = 0x92,    //                     (NEC PC98)
KC_UNDERLINE   = 0x93,    //                     (NEC PC98)
KC_KANJI       = 0x94,    // (Japanese keyboard)
KC_STOP        = 0x95,    //                     (NEC PC98)
KC_AX          = 0x96,    //                     (Japan AX)
KC_UNLABELED   = 0x97,    //                        (J3100)
KC_NEXTTRACK   = 0x99,    // Next Track
KC_NUMPADENTER = 0x9C,    // Enter on numeric keypad
KC_RCONTROL    = 0x9D,
KC_MUTE        = 0xA0,    // Mute
KC_CALCULATOR  = 0xA1,    // Calculator
KC_PLAYPAUSE   = 0xA2,    // Play / Pause
KC_MEDIASTOP   = 0xA4,    // Media Stop
KC_VOLUMEDOWN  = 0xAE,    // Volume -
KC_VOLUMEUP    = 0xB0,    // Volume +
KC_WEBHOME     = 0xB2,    // Web home
KC_NUMPADCOMMA = 0xB3,    // , on numeric keypad (NEC PC98)
KC_DIVIDE      = 0xB5,    // / on numeric keypad
KC_SYSRQ       = 0xB7,
KC_RMENU       = 0xB8,    // right Alt
KC_PAUSE       = 0xC5,    // Pause
KC_HOME        = 0xC7,    // Home on arrow keypad
KC_UP          = 0xC8,    // UpArrow on arrow keypad
KC_PGUP        = 0xC9,    // PgUp on arrow keypad
KC_LEFT        = 0xCB,    // LeftArrow on arrow keypad
KC_RIGHT       = 0xCD,    // RightArrow on arrow keypad
KC_END         = 0xCF,    // End on arrow keypad
KC_DOWN        = 0xD0,    // DownArrow on arrow keypad
KC_PGDOWN      = 0xD1,    // PgDn on arrow keypad
KC_INSERT      = 0xD2,    // Insert on arrow keypad
KC_DELETE      = 0xD3,    // Delete on arrow keypad
KC_LWIN        = 0xDB,    // Left Windows key
KC_RWIN        = 0xDC,    // Right Windows key
KC_APPS        = 0xDD,    // AppMenu key
KC_POWER       = 0xDE,    // System Power
KC_SLEEP       = 0xDF,    // System Sleep
KC_WAKE        = 0xE3,    // System Wake
KC_WEBSEARCH   = 0xE5,    // Web Search
KC_WEBFAVORITES= 0xE6,    // Web Favorites
KC_WEBREFRESH  = 0xE7,    // Web Refresh
KC_WEBSTOP     = 0xE8,    // Web Stop
KC_WEBFORWARD  = 0xE9,    // Web Forward
KC_WEBBACK     = 0xEA,    // Web Back
KC_MYCOMPUTER  = 0xEB,    // My Computer
KC_MAIL        = 0xEC,    // Mail
KC_MEDIASELECT = 0xED     // Media Select
};

Even though the KeyCode enum is non-localized, it makes no difference as it is only ever seen by the programmer.  Inside the keymap file, you associate controls with the numeric scancode, so this works regardless of language.

The only remaining problem is how you display these KeyCodes/scan codes in the key mapping user interface.

e.g. English:
Fire:   space
Reload:  left shift

vs. French:
Tirer:  maj gauche
Recharger:  espace


If SFML offered some kind of funtion like: 
Code: [Select]
  (w)char GetLocalizedKeyChar(unsigned int scanCode);or
Code: [Select]
  std::(w)string GetLocalizedKeyName(unsigned int scanCode);
Which translated a scan code to whatever primary character is on that key, that'd be awesome.  I don't know if this is possible.  Otherwise, it's just up to the game developer to pay a translator to do this for each language the game supports, and SFML can ignore this responsibility.
Title: Re: Better keyboard handling
Post by: ChronicRat on October 29, 2014, 07:17:17 pm
Any news for subj?
Title: Re: Better keyboard handling
Post by: binbinhfr on April 22, 2020, 10:23:03 am
any news on this ?
I still don't figure out how to implement a keyboard customisation in my game... (allowing AZERTY / QWERTY users to remap keys).
Title: Re: Better keyboard handling
Post by: eXpl0it3r on April 22, 2020, 02:07:48 pm
Custom keyboard bindings are already possible now, you have to make the key detection code variable or use something like Thor's Action (https://bromeon.ch/libraries/thor/tutorials/v2.0/actions.html).
Please open a separate topic if you want to discuss your specific situation.

Regarding the scancode situation, I've been very slowly working on getting the scancode implementation consolidated. I'll be doing some additional analyzes to see what is still needed.
You can follow the open PR here: https://github.com/SFML/SFML/pull/1235
Title: Re: Better keyboard handling
Post by: eXpl0it3r on June 12, 2020, 12:27:59 am
I have added some questions regarding scancode key names to the PR.
Please have a look and provide feedback :)

https://github.com/SFML/SFML/pull/1235#issuecomment-642956688