Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

a method to know current keyboard layout #5503

Closed
SuperUserNameMan opened this issue Jun 30, 2016 · 26 comments
Closed

a method to know current keyboard layout #5503

SuperUserNameMan opened this issue Jun 30, 2016 · 26 comments

Comments

@SuperUserNameMan
Copy link
Contributor

SuperUserNameMan commented Jun 30, 2016

Operating system or device - Godot version:
official 2.0.3stable

Issue description (what happened, and what was expected):

I would like to know what is the current keyboard layout (AZERTY, QWERTY, QWERTZ, DWOWAKR, etc) so the game automatically setup keyboard mapping without asking the player for interactions or configurations.

Current workarounds

A workaround is to "guess" according to what returns OS.get_locale(), but is not safe.

An other workaround when it is about mapping "WASD", is to use "ESDF" instead, but it might not be 100% universal, and might disturb some hardcore-gamers.

An other workaround for "WASD" that make AZERTY ("ZQSD") and QWERTx ("WASD") and QZERTY ("ZASD") all work out of the box, is to map [WZ] [AQ] [S] [D].

PS : and if you also want to support DVORAK (",AOE") keyboard out of the box, you'll have to map [WZ,] [AQ] [SO] [DE].
edit : there are several variant of DVORAK : dvorak for left hand, for right hand and "normal" dvorak, each layout is different.

Steps to reproduce:

Link to minimal example project (optional but very welcome):

@SuperUserNameMan
Copy link
Contributor Author

SuperUserNameMan commented Jul 1, 2016

Okay,

So I've started studying this idea, trying to implement OS_Window::get_latin_keyboard_variant() which is already implemented for OSX.

Win32 API does not provide straight forward method to differentiate kb layouts based on AZERTY, QWERTY, QZERTY etc.

So far, i've done some experiments using GetKeyboardLayout() and GetKeyboardLayoutName() (which returns a string containing an hex number instead of a human readable string).

These functions will return a different "Language identifier" for each country and languages.

This "language identifier" does not give any obvious information about AZERTY, QWERTY etc.

If we really want this feature, and if we want to make it the most reliable possible, I think it would be required to list all "language identifiers" that are not QWERTY (since QWERTY would be default) and to store these lists into some static arrays that the OS_Window::get_latin_keyboard_variant() will have to scan.

Like i said upper, and if i understood correctly, this function is already available for OSX.
On all other platforms, OS::get_latin_keyboard_variant() returns QWERTY by default.
On mobile platform, it does not really matter (except maybe for android devices accepting hardware kb ?).
On Linux, I have no idea how to implement it neither if it is possible.

What do you suggest ?

@SuperUserNameMan
Copy link
Contributor Author

Some more reading about an overcomplicated workaround :
http://archives.miloush.net/michkap/archive/2004/12/05/275231.html

And the legend of an undocumented GetLayoutDescription() function hidden in a comment :
http://archives.miloush.net/michkap/archive/2008/09/29/8968315.html

HRESULT GetLayoutDescription (LPWSTR szId, LPCWSTR pszName, LPUINT uBufLength, DWORD dwFlags) that returns a human-readable IME description (like "English(US) - Dvorak"). Combining both together, it's easy to get a list of all active IMEs installed.

@SuperUserNameMan
Copy link
Contributor Author

SuperUserNameMan commented Jul 2, 2016

I've wrote some python tool scripts to collect keyboard layouts names into a CSV.

"layout names" are hexadecimal string like returned by the win32 GetKeyboardLayourName().
The human readable name is "layout text" that are available into the windows registry.
There is also a layout ID (the third column into the CSV) that is also available into the windows registry, but i don't know if it is usefull data.

The script and the csv are available here :
https://github.com/SuperUserNameMan/os_windows_get_latin_keyboard_variant

What is required now, is to test all layout to identify which ones are based on AZERTY, QWERTZ, QZERTY, DVORAK etc. (we can ignore QWERTY keyboards as it would be default)

If someone here wants to participate and has a google account, here is a shared google sheet :

You can test several keywords layouts using the [Windows] + [Space] keys and add as much layouts as you want using the little keyboard layout icon into the task bar.

@reduz
Copy link
Member

reduz commented Jul 2, 2016

Godot already detects this and remaps the keys accordingly

On Sat, Jul 2, 2016 at 9:26 AM, SuperUserNameMan notifications@github.com
wrote:

I've wrote some python tool scripts to collect keyboard layouts names into
a CSV.

"layout names" are hexadecimal string like returned by the win32
GetKeyboardLayourName().
The human readable name is "layout text" that are available into the
windows registry.
There is also a layout ID (the third column into the CSV) that is also
available into the windows registry, but i don't know if it is usefull data.

The script and the csv are available here :
https://github.com/SuperUserNameMan/os_windows_get_latin_keyboard_variant

What is required now, is to test all layout to identify which ones are
based on AZERTY, QWERTZ, QZERTY, DVORAK etc. (we can ignore QWERTY
keyboards as it would be default)

If someone here wants to participate and has a google account, here is a
shared google sheet :

https://docs.google.com/spreadsheets/d/1aKasLNLaXtWuPFENOP72f_WaWC2SreXvLhsWmb9OuJM/edit?usp=sharing

You can test several keywords layouts using the [Windows] + [Space] keys
and add as much layouts as you want using the little keyboard layout icon
into the task bar.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#5503 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AF-Z29u2xsJjL8kojfeFHhb4qwfbo79Aks5qRljogaJpZM4JCQD5
.

@SuperUserNameMan
Copy link
Contributor Author

SuperUserNameMan commented Jul 2, 2016

@reduz : Unless I missed something into the Godot API, i'm not sure we are talking about the same thing.

For instance, if I map "WASD" keys to actions into Poject settings Input Map, this mapping will be correct only for QWERTY keyboards.
On my AZERTY keyboard, the W key is next to the X key, and the A key is at the place of the Q key.
My players would have to setup the keyboard mapping manually to ZQSD or to press the [Window] + [Space] combination to ask windows to activate English kayboard layout.
I think it is TOO complicated for some casual gamers.

So the solution i'm proposing is to add a get_latin_keyboard_variant() that would return "AZERTY" or "QWERTZ" or "QWERTY" etc, allowing the game to remap keyboard to actions appropriatly.

I've found no way to do that in Godot.

@reduz
Copy link
Member

reduz commented Jul 2, 2016

there already is a function named exactly OS.get_latin_keyboard_variant()
:P it's just not exposed to script, I'll expose it

On Sat, Jul 2, 2016 at 9:46 AM, SuperUserNameMan notifications@github.com
wrote:

@reduz https://github.com/reduz : Unless I missed something into the
Godot API, i'm not sure we are talking about the same thing.

For instance, if I setup bind "WASD" keys to action into Poject settings
Input Map, this mapping will be correct only for QWERTY keyboards.
On my AZERTY keyboards, the W key is next to the X key, and the A key is
at the place of the W key.
My players would have to setup the keyboard mapping manually to ZQSD or to
press the [Window] + [Space] combination to ask windows to activate English
kayboard layout.
I think it is TOO complicated for some casual gamers.

So the solution i'm proposing is to add a get_latin_keyboard_variant()
that would return "AZERTY" or "QWERTZ" or "QWERTY" etc, allowing to game to
change the remap the keyboard mapping to actions appropriatly.

I've found no way to do that in Godot.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#5503 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AF-Z25uS3RpWkLFYhM9oLzJs1aOos65Nks5qRl23gaJpZM4JCQD5
.

@SuperUserNameMan
Copy link
Contributor Author

@reduz : yes but it returns QWERTY by default, because it is not implemented for Windows.
I tried it already.

@SuperUserNameMan
Copy link
Contributor Author

(only OSX version seems to be implemented)

@SuperUserNameMan
Copy link
Contributor Author

SuperUserNameMan commented Jul 2, 2016

Okay,; for those still interested, i've managed to inventory as much latin keyboard layout variant as possible into this CSV. (note : this is for windows implementation only)

Actually, among the latin kb variants, there are more than just AZERTY, QWERTY, QWERTZ, QZERTY, DVORAK and NEO that were already listed in godot/core/os/os.h

For instance :

  • the turkmen keyboard layout is ÄWERTY (with a strange accent over the A),
  • the Turkish F keyboard is bizarre layout
  • the Finland/Norway keyboard is some sort of "àS`ERT£" with Q and W accessed through Alt-Gr ...
  • the Azeri latin kb is : "QÜERTY"
    etc

Also, there are several variants of DVORAK : LEFT HAND, RIGHT HAND and "normal" which each have a special layouts.

Even if it is possible to implement this feature for Windows, I still don't know if it is possible for other platforms, and if the current OSX implementation is reliable.

I don't know about the 3 persons who have reacted with a thumb-up to this thread ( @bojidar-bg , @timoschwarzer, @Zylann ), but personally i've stopped thinking this feature is really needed.

So, if no one complain, i vote for closing this feature request.

@Zylann
Copy link
Contributor

Zylann commented Jul 2, 2016

A lot of the games I play assume I have a QWERTY keyboard and it's very annoying, especially when the keys are hardcoded or if the game has no remapping feature. if it's not possible to have a perfect solution, a tradeoff would be better than nothing.

@SuperUserNameMan
Copy link
Contributor Author

SuperUserNameMan commented Jul 2, 2016

@Zylann :

Maybe we could write a tiny tutorial or a note to add to the godot documentation to try to make other game-developers slightly more aware that there is something else than QWERTY, and that hard-coding key mapping is evil ?

As for us who are already aware of that and who would like to automate the key mapping according to the player kb layout, we could use some simple workarounds like this one :

  • we could present the player a simple interface asking him to click on a button among "AZERTY", "QWERTY", "QWERTZ" etc and "OTHER". Each button would set a different preset, and clicking "OTHER" would ask the player to press a key for "up", an other for "down", etc.

That would be as much complicated than picking a flag to select a language.
And also, it would be reliable on all platforms.

What do you think ?

@SuperUserNameMan
Copy link
Contributor Author

SuperUserNameMan commented Jul 2, 2016

Well, i tried to git push my branch to github but something went wrong and git commands are all chinese to me.

So here is my Windows implementation of :

OS::LatinKeyboardVariant OS_Windows::get_latin_keyboard_variant() const {

    unsigned long azerty[] = { 
        0x00020401, // Arabic (102) AZERTY
        0x0001080c, // Belgian (Comma)
        0x0000080c, // Belgian French
        0x0000040c, // French
        0 // <--- STOP MARK
    };
    unsigned long qwertz[] = {
        0x0000041a, // Croation
        0x00000405, // Czech
        0x00000407, // German
        0x00010407, // German (IBM)
        0x0000040e, // Hungarian
        0x0000046e, // Luxembourgish
        0x00010415, // Polish (214)
        0x00000418, // Romanian (Legacy)
        0x0000081a, // Serbian (Latin)
        0x0000041b, // Slovak
        0x00000424, // Slovenian
        0x0001042e, // Sorbian Extended
        0x0002042e, // Sorbian Standard
        0x0000042e, // Sorbian Standard (Legacy)
        0x0000100c, // Swiss French
        0x00000807, // Swiss German
        0 // <--- STOP MARK
    };
    unsigned long dvorak[] = {
        0x00010409, // US-Dvorak
        0x00030409, // US-Dvorak for left hand
        0x00040409, // US-Dvorak for right hand
        0 // <--- STOP MARK
    };

    char name[ KL_NAMELENGTH + 1 ]; name[0] = 0;
    GetKeyboardLayoutNameA( name );

    //print_line( name );

    unsigned long hex = strtoul(name, NULL, 16);

    int i=0;
    while( azerty[i] != 0 ) {
        if (azerty[i] == hex) return LATIN_KEYBOARD_AZERTY;
        i++;
    }

    i = 0;
    while( qwertz[i] != 0 ) {
        if (qwertz[i] == hex) return LATIN_KEYBOARD_QWERTZ;
        i++;
    }

    i = 0;
    while( dvorak[i] != 0 ) {
        if (dvorak[i] == hex) return LATIN_KEYBOARD_DVORAK;
        i++; 
    }

    return LATIN_KEYBOARD_QWERTY;
}

reduz added a commit that referenced this issue Jul 10, 2016
…riant

windows get_latin_keyboard_variant() implementation and gdscript binding, #5503
@SuperUserNameMan
Copy link
Contributor Author

SuperUserNameMan commented Sep 2, 2016

I'm just bumping this one to remind other contributors that Linux / BSD / Amiga / whatever others platform with keyboard input other than Windows platforms still lack an implementation of this function, and that the MacOS implementation needs testing.

@SuperUserNameMan
Copy link
Contributor Author

apparently, you have implemented it for Linux #12480 #12517.
if no other platform needs an implementation, you could close this issue.

@SuperUserNameMan
Copy link
Contributor Author

@icnikerazah : i don't think your issue is related to the get_latin_keyboard_variant() method which only tries to tell wether the keyboard is QWERTY, AZERTY or WEIRDY.

@rosshadden
Copy link
Contributor

I came here wondering if such an automatic mapping was possible, though I figured it's not. I'm glad I found this issue, but it does sound like something that is probably best in dev-land to implement in-game mappings, and possibly pre-defined layouts. I just looked for an existing solution because I realized every time I make a game I always develop it with dvorak mappings, and switch them later, haha.

@KoBeWi
Copy link
Member

KoBeWi commented Jun 11, 2019

if no other platform needs an implementation, you could close this issue.

The remaining platforms are Android, iOS, UWP and HTML5 (probably). Do we need this method for these platforms?

@Calinou
Copy link
Member

Calinou commented Mar 4, 2020

Now that #18020 is merged, this method is much less useful. Should we still keep this issue open or consider desktop-only support to be good enough for this method?

One use case I see for this method is showing a keyboard image with example shortcuts, with the keyboard image matching the user's keyboard layout. Other than that, I can't see any other use cases for it.

@SuperUserNameMan
Copy link
Contributor Author

One use case I see for this method is showing a keyboard image with example shortcuts, with the keyboard image matching the user's keyboard layout. Other than that, I can't see any other use cases for it.

in-game tutorial/help/hints : "When an enemy throw a grenade to you, press Q to catch it." (on azerty, this would be "A").

@WilliamTambellini
Copy link

Just a warning that
OS.get_latin_keyboard_variant()
does nt seem to work correctly on Linux with godot 3.2.1 :
on my french azerty keyboard, it returns: "QWERTY"
The OS (CentOS7) is correctly aware of the fr keyboard:
$ localectl
System Locale: LANG=en_US.UTF-8
VC Keymap: fr
X11 Layout: fr

@Calinou
Copy link
Member

Calinou commented May 30, 2020

@WilliamTambellini The method implementation is here:

3.2

https://github.com/godotengine/godot/blob/640a8a6a1bf6e3bef8cc1d863c8a806cf0a9a789/platform/x11/os_x11.cpp#L3423-L3453

master

DisplayServerX11::LatinKeyboardVariant DisplayServerX11::get_latin_keyboard_variant() const {
_THREAD_SAFE_METHOD_
XkbDescRec *xkbdesc = XkbAllocKeyboard();
ERR_FAIL_COND_V(!xkbdesc, LATIN_KEYBOARD_QWERTY);
XkbGetNames(x11_display, XkbSymbolsNameMask, xkbdesc);
ERR_FAIL_COND_V(!xkbdesc->names, LATIN_KEYBOARD_QWERTY);
ERR_FAIL_COND_V(!xkbdesc->names->symbols, LATIN_KEYBOARD_QWERTY);
char *layout = XGetAtomName(x11_display, xkbdesc->names->symbols);
ERR_FAIL_COND_V(!layout, LATIN_KEYBOARD_QWERTY);
Vector<String> info = String(layout).split("+");
ERR_FAIL_INDEX_V(1, info.size(), LATIN_KEYBOARD_QWERTY);
if (info[1].find("colemak") != -1) {
return LATIN_KEYBOARD_COLEMAK;
} else if (info[1].find("qwertz") != -1) {
return LATIN_KEYBOARD_QWERTZ;
} else if (info[1].find("azerty") != -1) {
return LATIN_KEYBOARD_AZERTY;
} else if (info[1].find("qzerty") != -1) {
return LATIN_KEYBOARD_QZERTY;
} else if (info[1].find("dvorak") != -1) {
return LATIN_KEYBOARD_DVORAK;
} else if (info[1].find("neo") != -1) {
return LATIN_KEYBOARD_NEO;
}
return LATIN_KEYBOARD_QWERTY;
}

I'm not sure exactly why it's not working.

@WilliamTambellini
Copy link

Tks @Calinou
Looks like DisplayServerX11::get_latin_keyboard_variant is just not aware of the 'fr' layout:
$ setxkbmap -print | grep xkb_symbols
xkb_symbols { include "pc+fr+us:2+inet(evdev)" };

Preparing a PR.

@Calinou
Copy link
Member

Calinou commented Jun 5, 2020

@WilliamTambellini OK 🙂 Make sure to open the pull request against the master branch first. We can backport it to the 3.2 branch afterwards.

@WilliamTambellini
Copy link

WilliamTambellini commented Jun 5, 2020

sure @Calinou : done:
#39330

@SuperUserNameMan
Copy link
Contributor Author

I've received a Google notification of someone trying to access this doc :
https://docs.google.com/spreadsheets/d/1aKasLNLaXtWuPFENOP72f_WaWC2SreXvLhsWmb9OuJM/edit?usp=sharing

I don't think it is useful information anymore, but just in case, i have salvaged it from the recycle bin and restored the share.

Maybe someone more involved should make a copy just in case I clean up my drive again.

@Calinou
Copy link
Member

Calinou commented Oct 1, 2020

This was implemented by #39457 (and made less relevant by #18020), closing.

@Calinou Calinou closed this as completed Oct 1, 2020
@Calinou Calinou added this to the 4.0 milestone Oct 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants