Best way to handle different keyboard layouts?

DSP, Plug-in and Host development discussion.
RELATED
PRODUCTS
Kraku
KVRian
Topic Starter
1491 posts since 13 Oct, 2003 from Oulu, Finland

Post Thu Jun 30, 2022 12:02 am

I want to handle different keyboard layouts (QWERTY/QWERTZ/AZERTY) so that a key at the same place in different keyboards do the exact same thing (for PC and Mac). Like in trackers how they handle music note playing from computers keyboard. For example Renoise seems to handle this automatically. How did they achieve this in practise?

What's the best way to achieve this? I'm using JUCE for development.

Also I'm looking for people who'd like to run a quick test application on their PC, which outputs key codes and character codes from their keyboard layout, so I can see what their keyboards are actually outputting in practise. I'm looking for people with QWERTY (standard and Scandic), QWERTZ and AZERTY keyboards. If you feel. you can spare about one minute of time to run the application and send me the results, I'd much appreciate it.

User avatar
polac
KVRist
157 posts since 8 Mar, 2003 from Cologne

Post Thu Jun 30, 2022 1:14 am

In windows you can do this via scancode:

case WM_KEYUP:
case WM_KEYDOWN:
{
int nVirtKey = (int) wParam;
int scanCode = (lParam>>16)&0xff;

User avatar
mystran
KVRAF
7163 posts since 12 Feb, 2006 from Helsinki, Finland

Post Thu Jun 30, 2022 1:49 am

Kraku wrote: Thu Jun 30, 2022 12:02 am I want to handle different keyboard layouts (QWERTY/QWERTZ/AZERTY) so that a key at the same place in different keyboards do the exact same thing (for PC and Mac). Like in trackers how they handle music note playing from computers keyboard. For example Renoise seems to handle this automatically. How did they achieve this in practise?
Operating systems will generally give you "raw" keycodes for the physical keys as part of the keydown/keyup events. On Windows that's the VK_ stuff in wParam of WM_KEYDOWN/_KEYUP and on macOS it's the [event keyCode] delivered to keyDown: and keyUp: methods. The actual codes are OS specific so you'll basically need a table lookup to make it platform independent, but that's it.

The actual translation from physical keys to whatever the layout says is actually done by the application. On Windows if the messageloop calls TranslateMessage that'll synthesize WM_CHAR/WM_UNICHAR. In Cocoa NSView has interpretKeyEvents: that'll translate and call insertText: for you. In both cases you can also translate yourself if you feel like it.
What's the best way to achieve this? I'm using JUCE for development.
Unfortunately looking at modules/juce_gui_basics/native/juce_win32_Windowing.cpp it looks like JUCE appears to be doing the wrong(*) thing and translates (MapVirtualKey) the keydown/keyup messages, so I think you'd basically have to modify the keyboard handling in JUCE's native wrappers or translate backwards (which is potentially lossy).

(*) At least "wrong" for our purposes.
Also I'm looking for people who'd like to run a quick test application on their PC, which outputs key codes and character codes from their keyboard layout, so I can see what their keyboards are actually outputting in practise. I'm looking for people with QWERTY (standard and Scandic), QWERTZ and AZERTY keyboards. If you feel. you can spare about one minute of time to run the application and send me the results, I'd much appreciate it.
Why not just install a selection of layouts on your development system?
Preferred pronouns would be "it/it" because according to this country, I'm a piece of human trash.

Kraku
KVRian
Topic Starter
1491 posts since 13 Oct, 2003 from Oulu, Finland

Post Fri Jul 01, 2022 1:24 am

mystran wrote: Thu Jun 30, 2022 1:49 am
What's the best way to achieve this? I'm using JUCE for development.
Unfortunately looking at modules/juce_gui_basics/native/juce_win32_Windowing.cpp it looks like JUCE appears to be doing the wrong(*) thing and translates (MapVirtualKey) the keydown/keyup messages, so I think you'd basically have to modify the keyboard handling in JUCE's native wrappers or translate backwards (which is potentially lossy).

(*) At least "wrong" for our purposes.
Thanks, very informative!

I'll see if I can figure out an easy way to expand JUCE to handle what I want it to do.

mystran wrote: Thu Jun 30, 2022 1:49 am
Also I'm looking for people who'd like to run a quick test application on their PC, which outputs key codes and character codes from their keyboard layout, so I can see what their keyboards are actually outputting in practise. I'm looking for people with QWERTY (standard and Scandic), QWERTZ and AZERTY keyboards. If you feel. you can spare about one minute of time to run the application and send me the results, I'd much appreciate it.
Why not just install a selection of layouts on your development system?
I'm already doing that, but since I'm not very familiar with how operating systems and keyboard hardware handle the key codes, I wanted to test what's really coming out of the keyboard.

How does the keyboard hardware / OS handle such situations, where there are extra keys on some key rows? For example in Finnish keyboard there is a key for "<>" characters right after the left Shift key. On some keyboard layouts that key is missing. Does that key appear with the same key code on all keyboards that have a key at that location? What about the key right next to it, if/if not that extra key is present on the given keyboard?

User avatar
mystran
KVRAF
7163 posts since 12 Feb, 2006 from Helsinki, Finland

Post Fri Jul 01, 2022 1:41 am

Kraku wrote: Fri Jul 01, 2022 1:24 am How does the keyboard hardware / OS handle such situations, where there are extra keys on some key rows? For example in Finnish keyboard there is a key for "<>" characters right after the left Shift key. On some keyboard layouts that key is missing. Does that key appear with the same key code on all keyboards that have a key at that location? What about the key right next to it, if/if not that extra key is present on the given keyboard?
For the most part all the keys that are common between keyboards have the same codes everywhere and those keys only present on certain keyboards have their own codes that are just missing from keyboards where those keys are not present.

That particular key is what SDL for example calls NONUSBACKSLASH (the name is because it's backslash key on UK layout) and there's some oddities with that particular key, like on macOS it's keycodes are swapped with GRAVE (§ on finnish layout) if the keyboard is in ISO mode.. and I can't remember if there was some weirdness on Windows too, but like physically when the key is present it's always the same "nonusbackslash" key.

ps. For emphasis, the actual US backslash key is missing from basically all european keyboards, but from the point of view of hardware keycodes it's a different key, so it's fine to assume that any given "scancode" is found in certain place on the keyboard as long as it's one of the standard hardware layouts.
Preferred pronouns would be "it/it" because according to this country, I'm a piece of human trash.

Kraku
KVRian
Topic Starter
1491 posts since 13 Oct, 2003 from Oulu, Finland

Post Fri Jul 01, 2022 2:40 am

mystran wrote: Fri Jul 01, 2022 1:41 am ps. For emphasis, the actual US backslash key is missing from basically all european keyboards, but from the point of view of hardware keycodes it's a different key, so it's fine to assume that any given "scancode" is found in certain place on the keyboard as long as it's one of the standard hardware layouts.
Makes sense.

I think I'll see if JUCE lets me hack some simple callback function into its code which gets called with he hardware keycode every time key goes down/up.

Kraku
KVRian
Topic Starter
1491 posts since 13 Oct, 2003 from Oulu, Finland

Post Fri Jul 01, 2022 3:14 am

Hmm, my initial test don't seem to agree with what has been said on this thread so far:

I tried hacking my own test into Mac side of JUCE, into:

bool handleKeyEvent (NSEvent* ev, bool isKeyDown)
which can be found in juce_mac_NSViewComponentPeer.mm

I copy/pasted the following lines from JUCE to see what the NSEvent says the keycode is:

String unmodified = nsStringToJuce ([ev charactersIgnoringModifiers]);
auto keyCode = (int) unmodified[0];

I get different key code when I switch between QWERY and AZERTY keyboard layouts. I tried pressing Q key with both layouts. Then Z key. Both times the input keycode was different between the layouts.
Last edited by Kraku on Fri Jul 01, 2022 3:40 am, edited 1 time in total.

User avatar
mystran
KVRAF
7163 posts since 12 Feb, 2006 from Helsinki, Finland

Post Fri Jul 01, 2022 3:31 am

Kraku wrote: Fri Jul 01, 2022 3:14 am I copy/pasted the following lines from JUCE to see what the NSEvent says the keycode is:
String unmodified = nsStringToJuce ([ev charactersIgnoringModifiers]);
auto keyCode = (int) unmodified[0];
You want [ev keyCode] rather than [ev charactersIgnoringModifiers] because "keyCode" is the physical key and "charactersIgnoringModifiers" is the letter printed on the keycap (assuming the layout is set to match, obviously). These are fundamentally two different things.
Preferred pronouns would be "it/it" because according to this country, I'm a piece of human trash.

Kraku
KVRian
Topic Starter
1491 posts since 13 Oct, 2003 from Oulu, Finland

Post Fri Jul 01, 2022 3:45 am

mystran wrote: Fri Jul 01, 2022 3:31 am You want [ev keyCode] rather than [ev charactersIgnoringModifiers] because "keyCode" is the physical key and "charactersIgnoringModifiers" is the letter printed on the keycap (assuming the layout is set to match, obviously). These are fundamentally two different things.
Aha! Indeed it works with that modification. Thank you! :)

I'll check the windows side next.

Return to “DSP and Plug-in Development”