Keyboard shortcuts problem

(I noticed this problem when using Projucer, but I guess it affects all programs created with JUCE)

When typing, for example, in Hebrew, the key which would be "V" in English produces the letter "ה".

In most OS X apps, Cmd+V still works for paste in this mode, because the shortcut is a key-binding rather than a letter-binding, and it is still the same key..

In Projucer, Cmd+V only works as paste when typing in English and the letter for the key is still "v".

So do you mean that in hebrew mode it's adding a shift modifier and producing cmd+shift+V ?

Nope. In Hebrew mode I the exact same keys for Cmd+V as I would do in English mode or any other mode - the two keys which have "Cmd" and "V" printed on them. Even though the key "V" would not produce the letter "V" in Hebrew mode, it is still the same key for the purpose of keyboard shortcuts (this is how it is on OS X. In windows it is normally a "letter shortcut" too iirc).

Yeah, I understand that, but what I meant was: when the key event arrives, has the keyboard driver/OS added a shift (or other) modifier key? If not then there's no reason why it wouldn't recognise it.

I don't know the details of how the OS sends the key events. I suppose it probably sends key events and char events separately and maybe JUCE handler the char events rather than key events? Just guessing - haven't looked deeply to this one, just reporting the symptom..

Hi there,

A few thoughts on this. First of all, you say "the cmd+v shortcut is a key-binding rather than a letter-binding". That can't be true: For example I can switch to Dvorak, which is an alternative English layout where 'c' and 'v' are assigned to other physical keys. And then of course I'd expect cmd+v to work with that new 'v' key and not the old one (which types 'k' on Dvorak layout). And that's exactly what happens in OSX.

Anyway, I can reproduce your problem with hebrew and I can confirm that other OSX apps get this right, but JUCE apps don't. And here is the reason for it: juce_TextEditorKeyMapper.h:96

if (key == KeyPress ('v', ModifierKeys::commandModifier, 0)
      || key == KeyPress (KeyPress::insertKey, ModifierKeys::shiftModifier, 0))
    return target.pasteFromClipboard();

So yes, it does look for the character 'v' and not any physical key (the insertKey is something else).

But then how would I even fix this? It would need to be smart enough to know when to look for the key (e.g. in Hebrew, Russian, Arabic...) and when to look for the character instead (e.g. in Dvorak, Colemak...).

This becomes even more complicated if you consider other key commands like, for example, cmd+z for "undo". On a German keyboard, 'y' and 'z' are swapped. So again you would not look at the physical key but at the character (whereas you would still have to look at the physical key if you're on Hebrew). Likewise, 'q' is on another physical key on the French keyboard layout (cmd+q for "quit") etc etc. All those commands would instantly break if I change the code to look for the key instead of the character.

This seems very complicated to get right and doesn't sound like something we could easily do in JUCE (consider effort vs. benefit). The current behaviour seems a lesser evil to me than going down that path (i.e. it currently works correctly with all keyboard layouts that use latin characters). Unless maybe there is an API somewhere that already solves all those problems and that we could use instead?

OK, after a bit more thinking here is a possible solution, although I am not yet 100% sure this could work:

First check whether the key is an ASCII character. If yes, apply the usual commands like cmd+c, cmd+v etc. based on that character (good for all the latin-based key layouts). If it is not an ASCII character (as is the case for scripts like Hebrew, Arabic, Russian, etc.) then instead use the physical key to determine the command to trigger.

The question now is how to get the physical key. I haven't found a way yet to do this in JUCE.

As an example, another UI library that I’m familiar with, GLFW, has separate key input and text input events.

So that in your key input callback you can do key == GLFW_KEY_V && mods == GLFW_MOD_SUPER && action == GLFW_PRESS to handle cmd+v regardless of the input language.


Note that also in Cocoa, the keyEvent should have a keyCode which should identify the key regardless of the input language.

1 Like

It’s great to have an example, but as timur mentioned, most programs will not disregard the input language when detecting shortcuts. So the logic probably relies on checking if the letter is part of ASCII.