raysan5 / raylib

A simple and easy-to-use library to enjoy videogames programming
http://www.raylib.com
zlib License
23.02k stars 2.3k forks source link

On QWERTZ keyboard layouts the Z and Y keys are swapped #2822

Closed DeexCoding closed 1 year ago

DeexCoding commented 1 year ago

Mhm you read the title correctly.

orcmid commented 1 year ago

Isn't this a keyboard mapping handled in the OS?

raysan5 commented 1 year ago

Isn't this a keyboard mapping handled in the OS?

Yes, that's it. Different keyboard layouts should be managed by the user.

DeexCoding commented 1 year ago

Sorry for not responding earlier, but you're wrong. I don't care if it's handled by the os or not, if I call IsKeyDown with KEY_Z that shouldn't return true when the Y key is pressed on my keyboard, not even if it's a different layout if (IsKeyPressed(KEY_Z)) { //On QWERTZ this gets executed when Y is pressed }

orcmid commented 1 year ago

TL;DR: KeyboardKey is defined with the names of the keytops that apply to those codes with the standard US keyboard layout. It is not wrong, just specific. To operate with different keyboards and their keytops (and functions), the application needs to either wire in a different typedef (e.g., QwertzKey, DvorakKey, etc.) and then dynamically adjust based on configuration information, or provide information about what the fixed keyboard assumption is.

DETAILS

In raylib.h the KeyboardKey typedef is tied to the US keyboard layout. (See around line 516 in raylib.h.) That is how the position of a key is understood, no matter what the labels on the keytops are. There is a standard agreement on what the keyboard codes are in the standard layout positions for all conventional keyboards and supported languages.

The problem being encountered here is, "What should keys be called in the software?" The keycode specifies where the key is, but not what the expected internal character encoding should be (which requires knowing what the keytop is and what the keyboard functions are).

For raylib.h an arbitrary choice has been to name the keycodes by the character those keys designate on a US QWERTY keyboard. That masks the level of indirection that actually applies in the accommodation of different layouts, whether based on practice in a language community or a preference among individual users (e.g., Dvorak layout).

Notice that there is a hint of this indirect arrangement (keycodes versus keycode mappings to a keytop character encoding) in the distinction between GetKey and GetCharacter.

How can one navigate this? Well, an application that handles keycodes directly needs to accommodate what the keycode assignment is for a given style of keyboard and language usage. For QWERTZ (and for other cases), the raylib application needs to be able to determine what the user's situation is and switch to a correct correspondence between KEYTOP and KEYCODE. One could build different releases based on keyboard selection, or arrange to handle it dynamically via configuration information (ideally, from the operating system).

There are likely libraries somewhere that accommodate the many variations that arise. There is also probably a way to determine the mapping that the operating system is using for handling of keyboards in utility functions that support keyboard input to applications.

It does no good to want KeyboardKey to be different. Whatever the choice, it will only be correct for a particular keytop layout and incorrect for others.

(PS: One also needs to deal with such situations as Left and Right Shift, Ctrl and Alt keys, the Windows key, shift lock, and things like the NumLock and Function locks, split space bars, the Windows/Mac Key, etc.)

raysan5 commented 1 year ago

@orcmid Thanks for this great and very detailed explanation. raylib is not an engine but a low level library, a standard keyboard layout was chosen for convenience but it's up to the users to create a mapping table for other keyboard layouts if required.

orcmid commented 1 year ago

With respect to how Windows handles this, there is an useful Keyboard Input Overview. It points out the level of indirection between scan codes from keyboards and what is known about the layout/keytops and the Virtual Keys that they are mapped to. This is dynamic and elaborate. The VK_... keys are defined in windows.h which is not terribly helpful. There may be a header that is included by windows.h that might be usable directly. The VK keys are named by the typical labelling of keytops on a US keyboard, which is confounding but difficult to escape. There may be better reference material to help with other layouts.

Keyboard Scan Codes describes the situation as it was in 2009. I suspect there is greater standardization now, at least for PCs conforming to WinTel specifications.

SuperUserNameMan commented 1 year ago

In raylib.h the KeyboardKey typedef is tied to the US keyboard layout.

Hope you don't mind me unearthing this one, but I've just noticed that Emscripten and C don't behave the same way on my Linux.

My keyboard is AZERTY layout.

When i test /core_3d_camera_first_person.c :

Shouldn't all platforms behave the same way regarding keyboard mapping ?

orcmid commented 1 year ago

@SuperUserNameMan

Shouldn't all platforms behave the same way regarding keyboard mapping ?

Are you asking about all platforms or about raylib on any platform? umm, and with the common libraries on which raylib depends.

We're encountering a situation here akin to the one where the display being used has a high dpi value (e.g., 200) and so specifying things in pixels in raylib functions has a poor outcome. I stumbled on this recently, hence Discussion #3342.

To be able to distribute, or even run, the same compiled code on different configurations, even all on the same platform (e.g., any one of Windows, Linux, Mac, iOS, or Android) is creating challenges that did not arise very much in the era of BGI.

It strikes me that there is something akin to the current splitting out of platform-specific function implementations. Except, along with that, there needs to be more run-time configuration adaptability, somehow hidden beneath some portable interfaces.

Keyboard internationalizations and display capabilities are clear cases. File systems are probably another although that seems to be finessed somewhat. Hmm, and also internationalization (i18n, along with all the character sets, fonts, and encodings) and accessibility (a11y) might creep in.

I would hope that raylib itself is somehow neutral and adaptations can be handled by add-ons that implement the same APIs but have platform-specific configuration-dependent functionality depending on the target platform chosen at compile time.

This is a too-long reply. The challenges frighten me and I needed to express that.

SuperUserNameMan commented 1 year ago

Shouldn't all platforms behave the same way regarding keyboard mapping ?

Are you asking about all platforms or about raylib on any platform? umm, and with the common libraries on which raylib depends.

I was asking about raylib on any platform that make use of keyboard indeed (or maybe not indeed since i wasn't clear).

Actually, my real question was : should the difference of behavior between C-raylib and webassembly-raylib be considered as a bug or as a "should be managed by the user" ?

I'm a total noob regarding emscripten, but if it has the ability to return scancodes, maybe the Webassembly version of raylib should use them too ?

What do you think ? Should I open a bug report or not ?

ghost commented 1 year ago

@SuperUserNameMan I could be wrong, but I think what you want could be possible with KeyboardEvent: code property, quoting the Mozilla documentation:

For example, the code returned is "KeyQ" for the Q key on a QWERTY layout keyboard, but the same code value also represents the ' key on Dvorak keyboards and the A key on AZERTY keyboards. That makes it impossible to use the value of code to determine what the name of the key is to users if they're not using an anticipated keyboard layout.

Regarding if that should be the "default", I'm really not sure, would have to test further.

raysan5 commented 1 year ago

@SuperUserNameMan That inconsistency is an issue. Actually raylib, when compiled with emscripten depends on library_glfw.js that should be compatible with GLFW desktop library. If there are inconsistencies, then probably it should be reported to the creators.

SuperUserNameMan commented 1 year ago

@ubkp : Yes, that is what library_glfw.js should use instead of the outdated KeyboardEvent.keyCode.

@raysan5 : And yes, the inconsistency i described comes from library_glfw.js. I'll open an issue on their side.