From 87061fb751879ffb9cd4919a10ee604217cdb23e Mon Sep 17 00:00:00 2001 From: attila Date: Sun, 12 Dec 2021 19:05:50 +0100 Subject: [PATCH] MacOS: Change keyCode calculation to fix shortcuts with non-Latin languages --- .../native/juce_mac_NSViewComponentPeer.mm | 117 ++++++++++++++---- 1 file changed, 95 insertions(+), 22 deletions(-) diff --git a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm index d351642fda..edff4142f6 100644 --- a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm +++ b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm @@ -40,6 +40,66 @@ namespace juce namespace juce { +//============================================================================== +static constexpr int translateVirtualToAsciiKeyCode (int keyCode) noexcept +{ + switch (keyCode) + { + // The virtual keycodes are from HIToolbox/Events.h + case 0x00: return 'A'; + case 0x01: return 'S'; + case 0x02: return 'D'; + case 0x03: return 'F'; + case 0x04: return 'H'; + case 0x05: return 'G'; + case 0x06: return 'Z'; + case 0x07: return 'X'; + case 0x08: return 'C'; + case 0x09: return 'V'; + case 0x0B: return 'B'; + case 0x0C: return 'Q'; + case 0x0D: return 'W'; + case 0x0E: return 'E'; + case 0x0F: return 'R'; + case 0x10: return 'Y'; + case 0x11: return 'T'; + case 0x12: return '1'; + case 0x13: return '2'; + case 0x14: return '3'; + case 0x15: return '4'; + case 0x16: return '6'; + case 0x17: return '5'; + case 0x18: return '='; // kVK_ANSI_Equal + case 0x19: return '9'; + case 0x1A: return '7'; + case 0x1B: return '-'; // kVK_ANSI_Minus + case 0x1C: return '8'; + case 0x1D: return '0'; + case 0x1E: return ']'; // kVK_ANSI_RightBracket + case 0x1F: return 'O'; + case 0x20: return 'U'; + case 0x21: return '['; // kVK_ANSI_LeftBracket + case 0x22: return 'I'; + case 0x23: return 'P'; + case 0x25: return 'L'; + case 0x26: return 'J'; + case 0x27: return '"'; // kVK_ANSI_Quote + case 0x28: return 'K'; + case 0x29: return ';'; // kVK_ANSI_Semicolon + case 0x2A: return '\\'; // kVK_ANSI_Backslash + case 0x2B: return ','; // kVK_ANSI_Comma + case 0x2C: return '/'; // kVK_ANSI_Slash + case 0x2D: return 'N'; + case 0x2E: return 'M'; + case 0x2F: return '.'; // kVK_ANSI_Period + case 0x32: return '`'; // kVK_ANSI_Grave + + default: return keyCode; + } +} + +constexpr int extendedKeyModifier = 0x30000; + //============================================================================== class NSViewComponentPeer : public ComponentPeer, private Timer @@ -1259,6 +1319,19 @@ public: else keyCode = (int) CharacterFunctions::toUpperCase ((juce_wchar) keyCode); + // The purpose of the keyCode is to provide information about non-printing characters to facilitate + // keyboard control over the application. + // + // So when keyCode is decoded as a printing character outside the ASCII range we need to replace it. + // This holds when the keyCode is larger than 0xff and not part one of the two MacOS specific + // non-printing ranges. + if (keyCode > 0xff + && ! (keyCode >= NSUpArrowFunctionKey && keyCode <= NSModeSwitchFunctionKey) + && ! (keyCode >= extendedKeyModifier)) + { + keyCode = translateVirtualToAsciiKeyCode ([ev keyCode]); + } + if (([ev modifierFlags] & NSEventModifierFlagNumericPad) != 0) { const int numPadConversions[] = { '0', KeyPress::numberPad0, '1', KeyPress::numberPad1, @@ -2542,27 +2615,27 @@ const int KeyPress::F33Key = NSF33FunctionKey; const int KeyPress::F34Key = NSF34FunctionKey; const int KeyPress::F35Key = NSF35FunctionKey; -const int KeyPress::numberPad0 = 0x30020; -const int KeyPress::numberPad1 = 0x30021; -const int KeyPress::numberPad2 = 0x30022; -const int KeyPress::numberPad3 = 0x30023; -const int KeyPress::numberPad4 = 0x30024; -const int KeyPress::numberPad5 = 0x30025; -const int KeyPress::numberPad6 = 0x30026; -const int KeyPress::numberPad7 = 0x30027; -const int KeyPress::numberPad8 = 0x30028; -const int KeyPress::numberPad9 = 0x30029; -const int KeyPress::numberPadAdd = 0x3002a; -const int KeyPress::numberPadSubtract = 0x3002b; -const int KeyPress::numberPadMultiply = 0x3002c; -const int KeyPress::numberPadDivide = 0x3002d; -const int KeyPress::numberPadSeparator = 0x3002e; -const int KeyPress::numberPadDecimalPoint = 0x3002f; -const int KeyPress::numberPadEquals = 0x30030; -const int KeyPress::numberPadDelete = 0x30031; -const int KeyPress::playKey = 0x30000; -const int KeyPress::stopKey = 0x30001; -const int KeyPress::fastForwardKey = 0x30002; -const int KeyPress::rewindKey = 0x30003; +const int KeyPress::numberPad0 = extendedKeyModifier + 0x20; +const int KeyPress::numberPad1 = extendedKeyModifier + 0x21; +const int KeyPress::numberPad2 = extendedKeyModifier + 0x22; +const int KeyPress::numberPad3 = extendedKeyModifier + 0x23; +const int KeyPress::numberPad4 = extendedKeyModifier + 0x24; +const int KeyPress::numberPad5 = extendedKeyModifier + 0x25; +const int KeyPress::numberPad6 = extendedKeyModifier + 0x26; +const int KeyPress::numberPad7 = extendedKeyModifier + 0x27; +const int KeyPress::numberPad8 = extendedKeyModifier + 0x28; +const int KeyPress::numberPad9 = extendedKeyModifier + 0x29; +const int KeyPress::numberPadAdd = extendedKeyModifier + 0x2a; +const int KeyPress::numberPadSubtract = extendedKeyModifier + 0x2b; +const int KeyPress::numberPadMultiply = extendedKeyModifier + 0x2c; +const int KeyPress::numberPadDivide = extendedKeyModifier + 0x2d; +const int KeyPress::numberPadSeparator = extendedKeyModifier + 0x2e; +const int KeyPress::numberPadDecimalPoint = extendedKeyModifier + 0x2f; +const int KeyPress::numberPadEquals = extendedKeyModifier + 0x30; +const int KeyPress::numberPadDelete = extendedKeyModifier + 0x31; +const int KeyPress::playKey = extendedKeyModifier + 0x00; +const int KeyPress::stopKey = extendedKeyModifier + 0x01; +const int KeyPress::fastForwardKey = extendedKeyModifier + 0x02; +const int KeyPress::rewindKey = extendedKeyModifier + 0x03; } // namespace juce