From fcd3d4fb71c86eb5a97a785b8ebeaf1fe81b65de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 2 Jul 2020 15:23:54 +0200 Subject: [PATCH] macOS: Move key mapping from QtCore to platform plugin There's a bunch of similar and overlapping logic in QCocoaKeyMapper already. Moving it to the same place allows us to easier find ways to reduce the overlap. None of the exported functions were used outside of the plugin. Change-Id: I6953690cdfda5ee8265b33ccbf919184c3a1700f Reviewed-by: Timur Pocheptsov --- src/corelib/kernel/qcore_mac.mm | 142 ------------------ src/corelib/kernel/qcore_mac_p.h | 2 - src/plugins/platforms/cocoa/qcocoakeymapper.h | 2 + .../platforms/cocoa/qcocoakeymapper.mm | 142 ++++++++++++++++++ src/plugins/platforms/cocoa/qcocoamenuitem.mm | 3 +- src/plugins/platforms/cocoa/qcocoansmenu.mm | 2 +- src/plugins/platforms/cocoa/qnsview_keys.mm | 7 +- 7 files changed, 148 insertions(+), 152 deletions(-) diff --git a/src/corelib/kernel/qcore_mac.mm b/src/corelib/kernel/qcore_mac.mm index c1ba9a7b9e2..57d818ffd44 100644 --- a/src/corelib/kernel/qcore_mac.mm +++ b/src/corelib/kernel/qcore_mac.mm @@ -458,148 +458,6 @@ QMacRootLevelAutoReleasePool::~QMacRootLevelAutoReleasePool() // ------------------------------------------------------------------------- -#ifdef Q_OS_MACOS - -// Use this method to keep all the information in the TextSegment. As long as it is ordered -// we are in OK shape, and we can influence that ourselves. -struct KeyPair -{ - QChar cocoaKey; - Qt::Key qtKey; -}; - -bool operator==(const KeyPair &entry, QChar qchar) -{ - return entry.cocoaKey == qchar; -} - -bool operator<(const KeyPair &entry, QChar qchar) -{ - return entry.cocoaKey < qchar; -} - -bool operator<(QChar qchar, const KeyPair &entry) -{ - return qchar < entry.cocoaKey; -} - -bool operator<(const Qt::Key &key, const KeyPair &entry) -{ - return key < entry.qtKey; -} - -bool operator<(const KeyPair &entry, const Qt::Key &key) -{ - return entry.qtKey < key; -} - -struct qtKey2CocoaKeySortLessThan -{ - typedef bool result_type; - Q_DECL_CONSTEXPR result_type operator()(const KeyPair &entry1, const KeyPair &entry2) const noexcept - { - return entry1.qtKey < entry2.qtKey; - } -}; - -static const int NSEscapeCharacter = 27; // not defined by Cocoa headers -static const int NumEntries = 59; -static const KeyPair entries[NumEntries] = { - { NSEnterCharacter, Qt::Key_Enter }, - { NSBackspaceCharacter, Qt::Key_Backspace }, - { NSTabCharacter, Qt::Key_Tab }, - { NSNewlineCharacter, Qt::Key_Return }, - { NSCarriageReturnCharacter, Qt::Key_Return }, - { NSBackTabCharacter, Qt::Key_Backtab }, - { NSEscapeCharacter, Qt::Key_Escape }, - // Cocoa sends us delete when pressing backspace! - // (NB when we reverse this list in qtKey2CocoaKey, there - // will be two indices of Qt::Key_Backspace. But is seems to work - // ok for menu shortcuts (which uses that function): - { NSDeleteCharacter, Qt::Key_Backspace }, - { NSUpArrowFunctionKey, Qt::Key_Up }, - { NSDownArrowFunctionKey, Qt::Key_Down }, - { NSLeftArrowFunctionKey, Qt::Key_Left }, - { NSRightArrowFunctionKey, Qt::Key_Right }, - { NSF1FunctionKey, Qt::Key_F1 }, - { NSF2FunctionKey, Qt::Key_F2 }, - { NSF3FunctionKey, Qt::Key_F3 }, - { NSF4FunctionKey, Qt::Key_F4 }, - { NSF5FunctionKey, Qt::Key_F5 }, - { NSF6FunctionKey, Qt::Key_F6 }, - { NSF7FunctionKey, Qt::Key_F7 }, - { NSF8FunctionKey, Qt::Key_F8 }, - { NSF9FunctionKey, Qt::Key_F9 }, - { NSF10FunctionKey, Qt::Key_F10 }, - { NSF11FunctionKey, Qt::Key_F11 }, - { NSF12FunctionKey, Qt::Key_F12 }, - { NSF13FunctionKey, Qt::Key_F13 }, - { NSF14FunctionKey, Qt::Key_F14 }, - { NSF15FunctionKey, Qt::Key_F15 }, - { NSF16FunctionKey, Qt::Key_F16 }, - { NSF17FunctionKey, Qt::Key_F17 }, - { NSF18FunctionKey, Qt::Key_F18 }, - { NSF19FunctionKey, Qt::Key_F19 }, - { NSF20FunctionKey, Qt::Key_F20 }, - { NSF21FunctionKey, Qt::Key_F21 }, - { NSF22FunctionKey, Qt::Key_F22 }, - { NSF23FunctionKey, Qt::Key_F23 }, - { NSF24FunctionKey, Qt::Key_F24 }, - { NSF25FunctionKey, Qt::Key_F25 }, - { NSF26FunctionKey, Qt::Key_F26 }, - { NSF27FunctionKey, Qt::Key_F27 }, - { NSF28FunctionKey, Qt::Key_F28 }, - { NSF29FunctionKey, Qt::Key_F29 }, - { NSF30FunctionKey, Qt::Key_F30 }, - { NSF31FunctionKey, Qt::Key_F31 }, - { NSF32FunctionKey, Qt::Key_F32 }, - { NSF33FunctionKey, Qt::Key_F33 }, - { NSF34FunctionKey, Qt::Key_F34 }, - { NSF35FunctionKey, Qt::Key_F35 }, - { NSInsertFunctionKey, Qt::Key_Insert }, - { NSDeleteFunctionKey, Qt::Key_Delete }, - { NSHomeFunctionKey, Qt::Key_Home }, - { NSEndFunctionKey, Qt::Key_End }, - { NSPageUpFunctionKey, Qt::Key_PageUp }, - { NSPageDownFunctionKey, Qt::Key_PageDown }, - { NSPrintScreenFunctionKey, Qt::Key_Print }, - { NSScrollLockFunctionKey, Qt::Key_ScrollLock }, - { NSPauseFunctionKey, Qt::Key_Pause }, - { NSSysReqFunctionKey, Qt::Key_SysReq }, - { NSMenuFunctionKey, Qt::Key_Menu }, - { NSHelpFunctionKey, Qt::Key_Help }, -}; -static const KeyPair * const end = entries + NumEntries; - -QChar qt_mac_qtKey2CocoaKey(Qt::Key key) -{ - // The first time this function is called, create a reverse - // lookup table sorted on Qt Key rather than Cocoa key: - static QVector rev_entries(NumEntries); - static bool mustInit = true; - if (mustInit){ - mustInit = false; - for (int i=0; i::iterator i - = std::lower_bound(rev_entries.begin(), rev_entries.end(), key); - if ((i == rev_entries.end()) || (key < *i)) - return QChar(); - return i->cocoaKey; -} - -Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode) -{ - const KeyPair *i = std::lower_bound(entries, end, keyCode); - if ((i == end) || (keyCode < *i)) - return Qt::Key(keyCode.toUpper().unicode()); - return i->qtKey; -} - -#endif // Q_OS_MACOS - void qt_apple_check_os_version() { #if defined(__WATCH_OS_VERSION_MIN_REQUIRED) diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 789476a8840..306d6ac8bb8 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -183,8 +183,6 @@ private: }; #ifdef Q_OS_MACOS -Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key); -Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode); Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode(); #endif diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.h b/src/plugins/platforms/cocoa/qcocoakeymapper.h index f195cda7be1..d93fe16b203 100644 --- a/src/plugins/platforms/cocoa/qcocoakeymapper.h +++ b/src/plugins/platforms/cocoa/qcocoakeymapper.h @@ -83,6 +83,8 @@ public: QList possibleKeys(const QKeyEvent *event) const; static Qt::KeyboardModifiers fromCocoaModifiers(NSEventModifierFlags cocoaModifiers); + static QChar toCocoaKey(Qt::Key key); + static Qt::Key fromCocoaKey(QChar keyCode); private: bool updateKeyboard(); diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.mm b/src/plugins/platforms/cocoa/qcocoakeymapper.mm index 40d13e2d6aa..fdb4fb01e73 100644 --- a/src/plugins/platforms/cocoa/qcocoakeymapper.mm +++ b/src/plugins/platforms/cocoa/qcocoakeymapper.mm @@ -295,6 +295,148 @@ static int toKeyCode(const QChar &key, int virtualKey, int modifiers) return Qt::Key_unknown; } +// --------- Cocoa key mapping moved from Qt Core --------- + +// Use this method to keep all the information in the TextSegment. As long as it is ordered +// we are in OK shape, and we can influence that ourselves. +struct KeyPair +{ + QChar cocoaKey; + Qt::Key qtKey; +}; + +bool operator==(const KeyPair &entry, QChar qchar) +{ + return entry.cocoaKey == qchar; +} + +bool operator<(const KeyPair &entry, QChar qchar) +{ + return entry.cocoaKey < qchar; +} + +bool operator<(QChar qchar, const KeyPair &entry) +{ + return qchar < entry.cocoaKey; +} + +bool operator<(const Qt::Key &key, const KeyPair &entry) +{ + return key < entry.qtKey; +} + +bool operator<(const KeyPair &entry, const Qt::Key &key) +{ + return entry.qtKey < key; +} + +struct qtKey2CocoaKeySortLessThan +{ + typedef bool result_type; + Q_DECL_CONSTEXPR result_type operator()(const KeyPair &entry1, const KeyPair &entry2) const noexcept + { + return entry1.qtKey < entry2.qtKey; + } +}; + +static const int NSEscapeCharacter = 27; // not defined by Cocoa headers +static const int NumEntries = 59; +static const KeyPair entries[NumEntries] = { + { NSEnterCharacter, Qt::Key_Enter }, + { NSBackspaceCharacter, Qt::Key_Backspace }, + { NSTabCharacter, Qt::Key_Tab }, + { NSNewlineCharacter, Qt::Key_Return }, + { NSCarriageReturnCharacter, Qt::Key_Return }, + { NSBackTabCharacter, Qt::Key_Backtab }, + { NSEscapeCharacter, Qt::Key_Escape }, + // Cocoa sends us delete when pressing backspace! + // (NB when we reverse this list in qtKey2CocoaKey, there + // will be two indices of Qt::Key_Backspace. But is seems to work + // ok for menu shortcuts (which uses that function): + { NSDeleteCharacter, Qt::Key_Backspace }, + { NSUpArrowFunctionKey, Qt::Key_Up }, + { NSDownArrowFunctionKey, Qt::Key_Down }, + { NSLeftArrowFunctionKey, Qt::Key_Left }, + { NSRightArrowFunctionKey, Qt::Key_Right }, + { NSF1FunctionKey, Qt::Key_F1 }, + { NSF2FunctionKey, Qt::Key_F2 }, + { NSF3FunctionKey, Qt::Key_F3 }, + { NSF4FunctionKey, Qt::Key_F4 }, + { NSF5FunctionKey, Qt::Key_F5 }, + { NSF6FunctionKey, Qt::Key_F6 }, + { NSF7FunctionKey, Qt::Key_F7 }, + { NSF8FunctionKey, Qt::Key_F8 }, + { NSF9FunctionKey, Qt::Key_F9 }, + { NSF10FunctionKey, Qt::Key_F10 }, + { NSF11FunctionKey, Qt::Key_F11 }, + { NSF12FunctionKey, Qt::Key_F12 }, + { NSF13FunctionKey, Qt::Key_F13 }, + { NSF14FunctionKey, Qt::Key_F14 }, + { NSF15FunctionKey, Qt::Key_F15 }, + { NSF16FunctionKey, Qt::Key_F16 }, + { NSF17FunctionKey, Qt::Key_F17 }, + { NSF18FunctionKey, Qt::Key_F18 }, + { NSF19FunctionKey, Qt::Key_F19 }, + { NSF20FunctionKey, Qt::Key_F20 }, + { NSF21FunctionKey, Qt::Key_F21 }, + { NSF22FunctionKey, Qt::Key_F22 }, + { NSF23FunctionKey, Qt::Key_F23 }, + { NSF24FunctionKey, Qt::Key_F24 }, + { NSF25FunctionKey, Qt::Key_F25 }, + { NSF26FunctionKey, Qt::Key_F26 }, + { NSF27FunctionKey, Qt::Key_F27 }, + { NSF28FunctionKey, Qt::Key_F28 }, + { NSF29FunctionKey, Qt::Key_F29 }, + { NSF30FunctionKey, Qt::Key_F30 }, + { NSF31FunctionKey, Qt::Key_F31 }, + { NSF32FunctionKey, Qt::Key_F32 }, + { NSF33FunctionKey, Qt::Key_F33 }, + { NSF34FunctionKey, Qt::Key_F34 }, + { NSF35FunctionKey, Qt::Key_F35 }, + { NSInsertFunctionKey, Qt::Key_Insert }, + { NSDeleteFunctionKey, Qt::Key_Delete }, + { NSHomeFunctionKey, Qt::Key_Home }, + { NSEndFunctionKey, Qt::Key_End }, + { NSPageUpFunctionKey, Qt::Key_PageUp }, + { NSPageDownFunctionKey, Qt::Key_PageDown }, + { NSPrintScreenFunctionKey, Qt::Key_Print }, + { NSScrollLockFunctionKey, Qt::Key_ScrollLock }, + { NSPauseFunctionKey, Qt::Key_Pause }, + { NSSysReqFunctionKey, Qt::Key_SysReq }, + { NSMenuFunctionKey, Qt::Key_Menu }, + { NSHelpFunctionKey, Qt::Key_Help }, +}; +static const KeyPair * const end = entries + NumEntries; + +QChar QCocoaKeyMapper::toCocoaKey(Qt::Key key) +{ + // The first time this function is called, create a reverse + // lookup table sorted on Qt Key rather than Cocoa key: + static QVector rev_entries(NumEntries); + static bool mustInit = true; + if (mustInit){ + mustInit = false; + for (int i=0; i::iterator i + = std::lower_bound(rev_entries.begin(), rev_entries.end(), key); + if ((i == rev_entries.end()) || (key < *i)) + return QChar(); + return i->cocoaKey; +} + +Qt::Key QCocoaKeyMapper::fromCocoaKey(QChar keyCode) +{ + const KeyPair *i = std::lower_bound(entries, end, keyCode); + if ((i == end) || (keyCode < *i)) + return Qt::Key(keyCode.toUpper().unicode()); + return i->qtKey; +} + +// ------------------------------------------------ + QCocoaKeyMapper::QCocoaKeyMapper() { memset(m_keyLayout, 0, sizeof(m_keyLayout)); diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index c51edb3deca..e5dc1c54e61 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -50,6 +50,7 @@ #include "qcocoahelpers.h" #include "qcocoaapplication.h" // for custom application category #include "qcocoamenuloader.h" +#include "qcocoakeymapper.h" #include #include @@ -99,7 +100,7 @@ static quint32 constructModifierMask(quint32 accel_key) NSString *keySequenceToKeyEqivalent(const QKeySequence &accel) { quint32 accel_key = (accel[0] & ~(Qt::MODIFIER_MASK | Qt::UNICODE_ACCEL)); - QChar cocoa_key = qt_mac_qtKey2CocoaKey(Qt::Key(accel_key)); + QChar cocoa_key = QCocoaKeyMapper::toCocoaKey(Qt::Key(accel_key)); if (cocoa_key.isNull()) cocoa_key = QChar(accel_key).toLower().unicode(); // Similar to qt_mac_removePrivateUnicode change the delete key so the symbol is correctly seen in native menubar diff --git a/src/plugins/platforms/cocoa/qcocoansmenu.mm b/src/plugins/platforms/cocoa/qcocoansmenu.mm index d271a566d93..b94d31251ea 100644 --- a/src/plugins/platforms/cocoa/qcocoansmenu.mm +++ b/src/plugins/platforms/cocoa/qcocoansmenu.mm @@ -264,7 +264,7 @@ static NSString *qt_mac_removePrivateUnicode(NSString *string) } else { ch = QChar([charactersIgnoringModifiers characterAtIndex:0]); } - keyCode = qt_mac_cocoaKey2QtKey(ch); + keyCode = QCocoaKeyMapper::fromCocoaKey(ch); } else { // might be a dead key ch = QChar::ReplacementCharacter; diff --git a/src/plugins/platforms/cocoa/qnsview_keys.mm b/src/plugins/platforms/cocoa/qnsview_keys.mm index 73b2b89176e..0122c01972c 100644 --- a/src/plugins/platforms/cocoa/qnsview_keys.mm +++ b/src/plugins/platforms/cocoa/qnsview_keys.mm @@ -41,11 +41,6 @@ @implementation QNSView (Keys) -- (int)convertKeyCode:(QChar)keyChar -{ - return qt_mac_cocoaKey2QtKey(keyChar); -} - - (bool)handleKeyEvent:(NSEvent *)nsevent eventType:(int)eventType { ulong timestamp = [nsevent timestamp] * 1000; @@ -78,7 +73,7 @@ ch = QChar([charactersIgnoringModifiers characterAtIndex:0]); else if ([characters length] != 0) ch = QChar([characters characterAtIndex:0]); - keyCode = [self convertKeyCode:ch]; + keyCode = QCocoaKeyMapper::fromCocoaKey(ch); } // we will send a key event unless the input method sets m_sendKeyEvent to false