summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa/qcocoakeymapper.mm
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2020-06-28 13:03:11 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2020-06-30 10:11:23 +0200
commitd962de314b0e78250952b5ea493bbe47f4f3e4c8 (patch)
tree2dab4acda605836d38dce773a6fe9a6191dc7792 /src/plugins/platforms/cocoa/qcocoakeymapper.mm
parentd0ccacaf28a4819dfb8e9b074ec2522cbe77d80f (diff)
macOS: Modernize QCocoaKeyMapper
Paying off technical debt from Qt 4 times, and preparation for removing Carbon dependency. - Proper variable names (m_ prefix, titleCase, fullyWrittenOut) - Modern data structures for lookups - Removal of dead code/variables - Categorized logging - Built in constants instead of magic numbers - Typed variables instead of naked integers Change-Id: Ie14621e0da8ed61e2185fa05373047204dc4ea62 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoakeymapper.mm')
-rw-r--r--src/plugins/platforms/cocoa/qcocoakeymapper.mm584
1 files changed, 276 insertions, 308 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.mm b/src/plugins/platforms/cocoa/qcocoakeymapper.mm
index 8d923bb9ec..a0004f6f8f 100644
--- a/src/plugins/platforms/cocoa/qcocoakeymapper.mm
+++ b/src/plugins/platforms/cocoa/qcocoakeymapper.mm
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -41,308 +41,246 @@
#include "qcocoakeymapper.h"
-#include <QtCore/QDebug>
+#include <QtCore/qloggingcategory.h>
#include <QtGui/QGuiApplication>
QT_BEGIN_NAMESPACE
-// QCocoaKeyMapper debug facilities
-//#define DEBUG_KEY_BINDINGS
-//#define DEBUG_KEY_BINDINGS_MODIFIERS
-//#define DEBUG_KEY_MAPS
-
-// Possible modifier states.
-// NOTE: The order of these states match the order in updatePossibleKeyCodes()!
-static const Qt::KeyboardModifiers ModsTbl[] = {
- Qt::NoModifier, // 0
- Qt::ShiftModifier, // 1
- Qt::ControlModifier, // 2
- Qt::ControlModifier | Qt::ShiftModifier, // 3
- Qt::AltModifier, // 4
- Qt::AltModifier | Qt::ShiftModifier, // 5
- Qt::AltModifier | Qt::ControlModifier, // 6
- Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7
- Qt::MetaModifier, // 8
- Qt::MetaModifier | Qt::ShiftModifier, // 9
- Qt::MetaModifier | Qt::ControlModifier, // 10
- Qt::MetaModifier | Qt::ControlModifier | Qt::ShiftModifier,// 11
- Qt::MetaModifier | Qt::AltModifier, // 12
- Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier, // 13
- Qt::MetaModifier | Qt::AltModifier | Qt::ControlModifier, // 14
- Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 15
+Q_LOGGING_CATEGORY(lcQpaKeyMapper, "qt.qpa.keymapper");
+Q_LOGGING_CATEGORY(lcQpaKeyMapperKeys, "qt.qpa.keymapper.keys");
+Q_LOGGING_CATEGORY(lcQpaKeyMapperModifiers, "qt.qpa.keymapper.modifiers");
+
+static constexpr std::tuple<int, Qt::KeyboardModifier> carbonModifierMap[] = {
+ { shiftKey, Qt::ShiftModifier },
+ { rightShiftKey, Qt::ShiftModifier },
+ { controlKey, Qt::MetaModifier },
+ { rightControlKey, Qt::MetaModifier },
+ { cmdKey, Qt::ControlModifier },
+ { optionKey, Qt::AltModifier },
+ { rightOptionKey, Qt::AltModifier },
+ { kEventKeyModifierNumLockMask, Qt::KeypadModifier }
};
-bool qt_mac_eat_unicode_key = false;
-
-
-/* key maps */
-struct qt_mac_enum_mapper
-{
- int mac_code;
- int qt_code;
-#if defined(DEBUG_KEY_BINDINGS)
-# define QT_MAC_MAP_ENUM(x) x, #x
- const char *desc;
-#else
-# define QT_MAC_MAP_ENUM(x) x
-#endif
-};
+using CarbonModifiers = UInt32; // As opposed to EventModifiers which is UInt16
-//modifiers
-static qt_mac_enum_mapper qt_mac_modifier_symbols[] = {
- { shiftKey, QT_MAC_MAP_ENUM(Qt::ShiftModifier) },
- { rightShiftKey, QT_MAC_MAP_ENUM(Qt::ShiftModifier) },
- { controlKey, QT_MAC_MAP_ENUM(Qt::MetaModifier) },
- { rightControlKey, QT_MAC_MAP_ENUM(Qt::MetaModifier) },
- { cmdKey, QT_MAC_MAP_ENUM(Qt::ControlModifier) },
- { optionKey, QT_MAC_MAP_ENUM(Qt::AltModifier) },
- { rightOptionKey, QT_MAC_MAP_ENUM(Qt::AltModifier) },
- { kEventKeyModifierNumLockMask, QT_MAC_MAP_ENUM(Qt::KeypadModifier) },
- { 0, QT_MAC_MAP_ENUM(0) }
-};
-Qt::KeyboardModifiers qt_mac_get_modifiers(int keys)
+Qt::KeyboardModifiers fromCarbonModifiers(CarbonModifiers carbonModifiers)
{
-#ifdef DEBUG_KEY_BINDINGS_MODIFIERS
- qDebug("Qt: internal: **Mapping modifiers: %d (0x%04x)", keys, keys);
-#endif
- Qt::KeyboardModifiers ret = Qt::NoModifier;
- for (int i = 0; qt_mac_modifier_symbols[i].qt_code; i++) {
- if (keys & qt_mac_modifier_symbols[i].mac_code) {
-#ifdef DEBUG_KEY_BINDINGS_MODIFIERS
- qDebug("Qt: internal: got modifier: %s", qt_mac_modifier_symbols[i].desc);
-#endif
- ret |= Qt::KeyboardModifier(qt_mac_modifier_symbols[i].qt_code);
+ qCDebug(lcQpaKeyMapperModifiers, "Mapping carbon modifiers: %d (0x%04x)",
+ carbonModifiers, carbonModifiers);
+
+ Qt::KeyboardModifiers qtModifiers = Qt::NoModifier;
+ for (const auto &[carbonModifier, qtModifier] : carbonModifierMap) {
+ if (carbonModifiers & carbonModifier) {
+ qCDebug(lcQpaKeyMapperModifiers) << "Got modifier" << qtModifier;
+ qtModifiers |= qtModifier;
}
}
+
if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
- Qt::KeyboardModifiers oldModifiers = ret;
- ret &= ~(Qt::MetaModifier | Qt::ControlModifier);
+ Qt::KeyboardModifiers oldModifiers = qtModifiers;
+ qtModifiers &= ~(Qt::MetaModifier | Qt::ControlModifier);
if (oldModifiers & Qt::ControlModifier)
- ret |= Qt::MetaModifier;
+ qtModifiers |= Qt::MetaModifier;
if (oldModifiers & Qt::MetaModifier)
- ret |= Qt::ControlModifier;
+ qtModifiers |= Qt::ControlModifier;
}
- return ret;
+
+ return qtModifiers;
}
-static int qt_mac_get_mac_modifiers(Qt::KeyboardModifiers keys)
+
+static CarbonModifiers toCarbonModifiers(Qt::KeyboardModifiers qtModifiers)
{
-#ifdef DEBUG_KEY_BINDINGS_MODIFIERS
- qDebug("Qt: internal: **Mapping modifiers: %d (0x%04x)", (int)keys, (int)keys);
-#endif
- int ret = 0;
- for (int i = 0; qt_mac_modifier_symbols[i].qt_code; i++) {
- if (keys & qt_mac_modifier_symbols[i].qt_code) {
-#ifdef DEBUG_KEY_BINDINGS_MODIFIERS
- qDebug("Qt: internal: got modifier: %s", qt_mac_modifier_symbols[i].desc);
-#endif
- ret |= qt_mac_modifier_symbols[i].mac_code;
+ qCDebug(lcQpaKeyMapperModifiers).verbosity(1) << "Mapping" << qtModifiers;
+
+ CarbonModifiers carbonModifiers = 0;
+ for (const auto &[carbonModifier, qtModifier] : carbonModifierMap) {
+ if (qtModifiers & qtModifier) {
+ qCDebug(lcQpaKeyMapperModifiers) << "Got carbon modifier" << carbonModifier;
+ carbonModifiers |= carbonModifier;
}
}
if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
- int oldModifiers = ret;
- ret &= ~(controlKeyBit | cmdKeyBit);
+ int oldModifiers = carbonModifiers;
+ carbonModifiers &= ~(controlKeyBit | cmdKeyBit);
if (oldModifiers & controlKeyBit)
- ret |= cmdKeyBit;
+ carbonModifiers |= cmdKeyBit;
if (oldModifiers & cmdKeyBit)
- ret |= controlKeyBit;
+ carbonModifiers |= controlKeyBit;
}
- return ret;
+ return carbonModifiers;
}
-//keyboard keys (non-modifiers)
-static qt_mac_enum_mapper qt_mac_keyboard_symbols[] = {
- { kHomeCharCode, QT_MAC_MAP_ENUM(Qt::Key_Home) },
- { kEnterCharCode, QT_MAC_MAP_ENUM(Qt::Key_Enter) },
- { kEndCharCode, QT_MAC_MAP_ENUM(Qt::Key_End) },
- { kBackspaceCharCode, QT_MAC_MAP_ENUM(Qt::Key_Backspace) },
- { kTabCharCode, QT_MAC_MAP_ENUM(Qt::Key_Tab) },
- { kPageUpCharCode, QT_MAC_MAP_ENUM(Qt::Key_PageUp) },
- { kPageDownCharCode, QT_MAC_MAP_ENUM(Qt::Key_PageDown) },
- { kReturnCharCode, QT_MAC_MAP_ENUM(Qt::Key_Return) },
- { kEscapeCharCode, QT_MAC_MAP_ENUM(Qt::Key_Escape) },
- { kLeftArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Left) },
- { kRightArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Right) },
- { kUpArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Up) },
- { kDownArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Down) },
- { kHelpCharCode, QT_MAC_MAP_ENUM(Qt::Key_Help) },
- { kDeleteCharCode, QT_MAC_MAP_ENUM(Qt::Key_Delete) },
-//ascii maps, for debug
- { ':', QT_MAC_MAP_ENUM(Qt::Key_Colon) },
- { ';', QT_MAC_MAP_ENUM(Qt::Key_Semicolon) },
- { '<', QT_MAC_MAP_ENUM(Qt::Key_Less) },
- { '=', QT_MAC_MAP_ENUM(Qt::Key_Equal) },
- { '>', QT_MAC_MAP_ENUM(Qt::Key_Greater) },
- { '?', QT_MAC_MAP_ENUM(Qt::Key_Question) },
- { '@', QT_MAC_MAP_ENUM(Qt::Key_At) },
- { ' ', QT_MAC_MAP_ENUM(Qt::Key_Space) },
- { '!', QT_MAC_MAP_ENUM(Qt::Key_Exclam) },
- { '"', QT_MAC_MAP_ENUM(Qt::Key_QuoteDbl) },
- { '#', QT_MAC_MAP_ENUM(Qt::Key_NumberSign) },
- { '$', QT_MAC_MAP_ENUM(Qt::Key_Dollar) },
- { '%', QT_MAC_MAP_ENUM(Qt::Key_Percent) },
- { '&', QT_MAC_MAP_ENUM(Qt::Key_Ampersand) },
- { '\'', QT_MAC_MAP_ENUM(Qt::Key_Apostrophe) },
- { '(', QT_MAC_MAP_ENUM(Qt::Key_ParenLeft) },
- { ')', QT_MAC_MAP_ENUM(Qt::Key_ParenRight) },
- { '*', QT_MAC_MAP_ENUM(Qt::Key_Asterisk) },
- { '+', QT_MAC_MAP_ENUM(Qt::Key_Plus) },
- { ',', QT_MAC_MAP_ENUM(Qt::Key_Comma) },
- { '-', QT_MAC_MAP_ENUM(Qt::Key_Minus) },
- { '.', QT_MAC_MAP_ENUM(Qt::Key_Period) },
- { '/', QT_MAC_MAP_ENUM(Qt::Key_Slash) },
- { '[', QT_MAC_MAP_ENUM(Qt::Key_BracketLeft) },
- { ']', QT_MAC_MAP_ENUM(Qt::Key_BracketRight) },
- { '\\', QT_MAC_MAP_ENUM(Qt::Key_Backslash) },
- { '_', QT_MAC_MAP_ENUM(Qt::Key_Underscore) },
- { '`', QT_MAC_MAP_ENUM(Qt::Key_QuoteLeft) },
- { '{', QT_MAC_MAP_ENUM(Qt::Key_BraceLeft) },
- { '}', QT_MAC_MAP_ENUM(Qt::Key_BraceRight) },
- { '|', QT_MAC_MAP_ENUM(Qt::Key_Bar) },
- { '~', QT_MAC_MAP_ENUM(Qt::Key_AsciiTilde) },
- { '^', QT_MAC_MAP_ENUM(Qt::Key_AsciiCircum) },
- { 0, QT_MAC_MAP_ENUM(0) }
+// Keyboard keys (non-modifiers)
+static QHash<QChar, Qt::Key> standardKeys = {
+ { kHomeCharCode, Qt::Key_Home },
+ { kEnterCharCode, Qt::Key_Enter },
+ { kEndCharCode, Qt::Key_End },
+ { kBackspaceCharCode, Qt::Key_Backspace },
+ { kTabCharCode, Qt::Key_Tab },
+ { kPageUpCharCode, Qt::Key_PageUp },
+ { kPageDownCharCode, Qt::Key_PageDown },
+ { kReturnCharCode, Qt::Key_Return },
+ { kEscapeCharCode, Qt::Key_Escape },
+ { kLeftArrowCharCode, Qt::Key_Left },
+ { kRightArrowCharCode, Qt::Key_Right },
+ { kUpArrowCharCode, Qt::Key_Up },
+ { kDownArrowCharCode, Qt::Key_Down },
+ { kHelpCharCode, Qt::Key_Help },
+ { kDeleteCharCode, Qt::Key_Delete },
+ // ASCII maps, for debugging
+ { ':', Qt::Key_Colon },
+ { ';', Qt::Key_Semicolon },
+ { '<', Qt::Key_Less },
+ { '=', Qt::Key_Equal },
+ { '>', Qt::Key_Greater },
+ { '?', Qt::Key_Question },
+ { '@', Qt::Key_At },
+ { ' ', Qt::Key_Space },
+ { '!', Qt::Key_Exclam },
+ { '"', Qt::Key_QuoteDbl },
+ { '#', Qt::Key_NumberSign },
+ { '$', Qt::Key_Dollar },
+ { '%', Qt::Key_Percent },
+ { '&', Qt::Key_Ampersand },
+ { '\'', Qt::Key_Apostrophe },
+ { '(', Qt::Key_ParenLeft },
+ { ')', Qt::Key_ParenRight },
+ { '*', Qt::Key_Asterisk },
+ { '+', Qt::Key_Plus },
+ { ',', Qt::Key_Comma },
+ { '-', Qt::Key_Minus },
+ { '.', Qt::Key_Period },
+ { '/', Qt::Key_Slash },
+ { '[', Qt::Key_BracketLeft },
+ { ']', Qt::Key_BracketRight },
+ { '\\', Qt::Key_Backslash },
+ { '_', Qt::Key_Underscore },
+ { '`', Qt::Key_QuoteLeft },
+ { '{', Qt::Key_BraceLeft },
+ { '}', Qt::Key_BraceRight },
+ { '|', Qt::Key_Bar },
+ { '~', Qt::Key_AsciiTilde },
+ { '^', Qt::Key_AsciiCircum }
};
-static qt_mac_enum_mapper qt_mac_keyvkey_symbols[] = { //real scan codes
- { kVK_F1, QT_MAC_MAP_ENUM(Qt::Key_F1) },
- { kVK_F2, QT_MAC_MAP_ENUM(Qt::Key_F2) },
- { kVK_F3, QT_MAC_MAP_ENUM(Qt::Key_F3) },
- { kVK_F4, QT_MAC_MAP_ENUM(Qt::Key_F4) },
- { kVK_F5, QT_MAC_MAP_ENUM(Qt::Key_F5) },
- { kVK_F6, QT_MAC_MAP_ENUM(Qt::Key_F6) },
- { kVK_F7, QT_MAC_MAP_ENUM(Qt::Key_F7) },
- { kVK_F8, QT_MAC_MAP_ENUM(Qt::Key_F8) },
- { kVK_F9, QT_MAC_MAP_ENUM(Qt::Key_F9) },
- { kVK_F10, QT_MAC_MAP_ENUM(Qt::Key_F10) },
- { kVK_F11, QT_MAC_MAP_ENUM(Qt::Key_F11) },
- { kVK_F12, QT_MAC_MAP_ENUM(Qt::Key_F12) },
- { kVK_F13, QT_MAC_MAP_ENUM(Qt::Key_F13) },
- { kVK_F14, QT_MAC_MAP_ENUM(Qt::Key_F14) },
- { kVK_F15, QT_MAC_MAP_ENUM(Qt::Key_F15) },
- { kVK_F16, QT_MAC_MAP_ENUM(Qt::Key_F16) },
- { kVK_Return, QT_MAC_MAP_ENUM(Qt::Key_Return) },
- { kVK_Tab, QT_MAC_MAP_ENUM(Qt::Key_Tab) },
- { kVK_Escape, QT_MAC_MAP_ENUM(Qt::Key_Escape) },
- { kVK_Help, QT_MAC_MAP_ENUM(Qt::Key_Help) },
- { kVK_UpArrow, QT_MAC_MAP_ENUM(Qt::Key_Up) },
- { kVK_DownArrow, QT_MAC_MAP_ENUM(Qt::Key_Down) },
- { kVK_LeftArrow, QT_MAC_MAP_ENUM(Qt::Key_Left) },
- { kVK_RightArrow, QT_MAC_MAP_ENUM(Qt::Key_Right) },
- { kVK_PageUp, QT_MAC_MAP_ENUM(Qt::Key_PageUp) },
- { kVK_PageDown, QT_MAC_MAP_ENUM(Qt::Key_PageDown) },
- { 0, QT_MAC_MAP_ENUM(0) }
+static QHash<QChar, Qt::Key> virtualKeys = {
+ { kVK_F1, Qt::Key_F1 },
+ { kVK_F2, Qt::Key_F2 },
+ { kVK_F3, Qt::Key_F3 },
+ { kVK_F4, Qt::Key_F4 },
+ { kVK_F5, Qt::Key_F5 },
+ { kVK_F6, Qt::Key_F6 },
+ { kVK_F7, Qt::Key_F7 },
+ { kVK_F8, Qt::Key_F8 },
+ { kVK_F9, Qt::Key_F9 },
+ { kVK_F10, Qt::Key_F10 },
+ { kVK_F11, Qt::Key_F11 },
+ { kVK_F12, Qt::Key_F12 },
+ { kVK_F13, Qt::Key_F13 },
+ { kVK_F14, Qt::Key_F14 },
+ { kVK_F15, Qt::Key_F15 },
+ { kVK_F16, Qt::Key_F16 },
+ { kVK_Return, Qt::Key_Return },
+ { kVK_Tab, Qt::Key_Tab },
+ { kVK_Escape, Qt::Key_Escape },
+ { kVK_Help, Qt::Key_Help },
+ { kVK_UpArrow, Qt::Key_Up },
+ { kVK_DownArrow, Qt::Key_Down },
+ { kVK_LeftArrow, Qt::Key_Left },
+ { kVK_RightArrow, Qt::Key_Right },
+ { kVK_PageUp, Qt::Key_PageUp },
+ { kVK_PageDown, Qt::Key_PageDown }
};
-static qt_mac_enum_mapper qt_mac_private_unicode[] = {
- { 0xF700, QT_MAC_MAP_ENUM(Qt::Key_Up) }, //NSUpArrowFunctionKey
- { 0xF701, QT_MAC_MAP_ENUM(Qt::Key_Down) }, //NSDownArrowFunctionKey
- { 0xF702, QT_MAC_MAP_ENUM(Qt::Key_Left) }, //NSLeftArrowFunctionKey
- { 0xF703, QT_MAC_MAP_ENUM(Qt::Key_Right) }, //NSRightArrowFunctionKey
- { 0xF727, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertFunctionKey
- { 0xF728, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteFunctionKey
- { 0xF729, QT_MAC_MAP_ENUM(Qt::Key_Home) }, //NSHomeFunctionKey
- { 0xF72B, QT_MAC_MAP_ENUM(Qt::Key_End) }, //NSEndFunctionKey
- { 0xF72C, QT_MAC_MAP_ENUM(Qt::Key_PageUp) }, //NSPageUpFunctionKey
- { 0xF72D, QT_MAC_MAP_ENUM(Qt::Key_PageDown) }, //NSPageDownFunctionKey
- { 0xF72E, QT_MAC_MAP_ENUM(Qt::Key_Print) }, //NSPrintScreenFunctionKey
- { 0xF72F, QT_MAC_MAP_ENUM(Qt::Key_ScrollLock) }, //NSScrollLockFunctionKey
- { 0xF730, QT_MAC_MAP_ENUM(Qt::Key_Pause) }, //NSPauseFunctionKey
- { 0xF731, QT_MAC_MAP_ENUM(Qt::Key_SysReq) }, //NSSysReqFunctionKey
- { 0xF735, QT_MAC_MAP_ENUM(Qt::Key_Menu) }, //NSMenuFunctionKey
- { 0xF738, QT_MAC_MAP_ENUM(Qt::Key_Printer) }, //NSPrintFunctionKey
- { 0xF73A, QT_MAC_MAP_ENUM(Qt::Key_Clear) }, //NSClearDisplayFunctionKey
- { 0xF73D, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertCharFunctionKey
- { 0xF73E, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteCharFunctionKey
- { 0xF741, QT_MAC_MAP_ENUM(Qt::Key_Select) }, //NSSelectFunctionKey
- { 0xF742, QT_MAC_MAP_ENUM(Qt::Key_Execute) }, //NSExecuteFunctionKey
- { 0xF743, QT_MAC_MAP_ENUM(Qt::Key_Undo) }, //NSUndoFunctionKey
- { 0xF744, QT_MAC_MAP_ENUM(Qt::Key_Redo) }, //NSRedoFunctionKey
- { 0xF745, QT_MAC_MAP_ENUM(Qt::Key_Find) }, //NSFindFunctionKey
- { 0xF746, QT_MAC_MAP_ENUM(Qt::Key_Help) }, //NSHelpFunctionKey
- { 0xF747, QT_MAC_MAP_ENUM(Qt::Key_Mode_switch) }, //NSModeSwitchFunctionKey
- { 0, QT_MAC_MAP_ENUM(0) }
+static QHash<QChar, Qt::Key> functionKeys = {
+ { NSUpArrowFunctionKey, Qt::Key_Up },
+ { NSDownArrowFunctionKey, Qt::Key_Down },
+ { NSLeftArrowFunctionKey, Qt::Key_Left },
+ { NSRightArrowFunctionKey, Qt::Key_Right },
+ // F1-35 function keys handled manually below
+ { 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 },
+ { NSPrintFunctionKey, Qt::Key_Printer },
+ { NSClearDisplayFunctionKey, Qt::Key_Clear },
+ { NSInsertCharFunctionKey, Qt::Key_Insert },
+ { NSDeleteCharFunctionKey, Qt::Key_Delete },
+ { NSSelectFunctionKey, Qt::Key_Select },
+ { NSExecuteFunctionKey, Qt::Key_Execute },
+ { NSUndoFunctionKey, Qt::Key_Undo },
+ { NSRedoFunctionKey, Qt::Key_Redo },
+ { NSFindFunctionKey, Qt::Key_Find },
+ { NSHelpFunctionKey, Qt::Key_Help },
+ { NSModeSwitchFunctionKey, Qt::Key_Mode_switch }
};
-static int qt_mac_get_key(int modif, const QChar &key, int virtualKey)
+static int toKeyCode(const QChar &key, int virtualKey, int modifiers)
{
-#ifdef DEBUG_KEY_BINDINGS
- qDebug("**Mapping key: %d (0x%04x) - %d (0x%04x)", key.unicode(), key.unicode(), virtualKey, virtualKey);
-#endif
+ qCDebug(lcQpaKeyMapperKeys, "Mapping key: %d (0x%04x) / vk %d (0x%04x)",
+ key.unicode(), key.unicode(), virtualKey, virtualKey);
if (key == kClearCharCode && virtualKey == 0x47)
return Qt::Key_Clear;
if (key.isDigit()) {
-#ifdef DEBUG_KEY_BINDINGS
- qDebug("%d: got key: %d", __LINE__, key.digitValue());
-#endif
+ qCDebug(lcQpaKeyMapperKeys, "Got digit key: %d", key.digitValue());
return key.digitValue() + Qt::Key_0;
}
if (key.isLetter()) {
-#ifdef DEBUG_KEY_BINDINGS
- qDebug("%d: got key: %d", __LINE__, (key.toUpper().unicode() - 'A'));
-#endif
+ qCDebug(lcQpaKeyMapperKeys, "Got letter key: %d", (key.toUpper().unicode() - 'A'));
return (key.toUpper().unicode() - 'A') + Qt::Key_A;
}
if (key.isSymbol()) {
-#ifdef DEBUG_KEY_BINDINGS
- qDebug("%d: got key: %d", __LINE__, (key.unicode()));
-#endif
+ qCDebug(lcQpaKeyMapperKeys, "Got symbol key: %d", (key.unicode()));
return key.unicode();
}
- for (int i = 0; qt_mac_keyboard_symbols[i].qt_code; i++) {
- if (qt_mac_keyboard_symbols[i].mac_code == key) {
- /* To work like Qt for X11 we issue Backtab when Shift + Tab are pressed */
- if (qt_mac_keyboard_symbols[i].qt_code == Qt::Key_Tab && (modif & Qt::ShiftModifier)) {
-#ifdef DEBUG_KEY_BINDINGS
- qDebug("%d: got key: Qt::Key_Backtab", __LINE__);
-#endif
- return Qt::Key_Backtab;
- }
-
-#ifdef DEBUG_KEY_BINDINGS
- qDebug("%d: got key: %s", __LINE__, qt_mac_keyboard_symbols[i].desc);
-#endif
- return qt_mac_keyboard_symbols[i].qt_code;
+ if (auto qtKey = standardKeys.value(key)) {
+ // To work like Qt for X11 we issue Backtab when Shift + Tab are pressed
+ if (qtKey == Qt::Key_Tab && (modifiers & Qt::ShiftModifier)) {
+ qCDebug(lcQpaKeyMapperKeys, "Got key: Qt::Key_Backtab");
+ return Qt::Key_Backtab;
}
+
+ qCDebug(lcQpaKeyMapperKeys) << "Got" << qtKey;
+ return qtKey;
}
- //last ditch try to match the scan code
- for (int i = 0; qt_mac_keyvkey_symbols[i].qt_code; i++) {
- if (qt_mac_keyvkey_symbols[i].mac_code == virtualKey) {
-#ifdef DEBUG_KEY_BINDINGS
- qDebug("%d: got key: %s", __LINE__, qt_mac_keyvkey_symbols[i].desc);
-#endif
- return qt_mac_keyvkey_symbols[i].qt_code;
- }
+ // Last ditch try to match the scan code
+ if (auto qtKey = virtualKeys.value(virtualKey)) {
+ qCDebug(lcQpaKeyMapperKeys) << "Got scancode" << qtKey;
+ return qtKey;
}
- // check if they belong to key codes in private unicode range
- if (key >= 0xf700 && key <= 0xf747) {
- if (key >= 0xf704 && key <= 0xf726) {
- return Qt::Key_F1 + (key.unicode() - 0xf704) ;
+ // Check if they belong to key codes in private unicode range
+ if (key >= NSUpArrowFunctionKey && key <= NSModeSwitchFunctionKey) {
+ if (auto qtKey = functionKeys.value(key)) {
+ qCDebug(lcQpaKeyMapperKeys) << "Got" << qtKey;
+ return qtKey;
+ } else if (key >= NSF1FunctionKey && key <= NSF35FunctionKey) {
+ auto functionKey = Qt::Key_F1 + (key.unicode() - NSF1FunctionKey) ;
+ qCDebug(lcQpaKeyMapperKeys) << "Got" << functionKey;
+ return functionKey;
}
- for (int i = 0; qt_mac_private_unicode[i].qt_code; i++) {
- if (qt_mac_private_unicode[i].mac_code == key) {
- return qt_mac_private_unicode[i].qt_code;
- }
- }
-
}
- //oh well
-#ifdef DEBUG_KEY_BINDINGS
- qDebug("Unknown case.. %s:%d %d[%d] %d", __FILE__, __LINE__, key.unicode(), key.toLatin1(), virtualKey);
-#endif
+ qCDebug(lcQpaKeyMapperKeys, "Unknown case.. %d[%d] %d", key.unicode(), key.toLatin1(), virtualKey);
return Qt::Key_unknown;
}
QCocoaKeyMapper::QCocoaKeyMapper()
{
- memset(keyLayout, 0, sizeof(keyLayout));
+ memset(m_keyLayout, 0, sizeof(m_keyLayout));
}
QCocoaKeyMapper::~QCocoaKeyMapper()
@@ -352,48 +290,49 @@ QCocoaKeyMapper::~QCocoaKeyMapper()
Qt::KeyboardModifiers QCocoaKeyMapper::queryKeyboardModifiers()
{
- return qt_mac_get_modifiers(GetCurrentKeyModifiers());
+ return fromCarbonModifiers(GetCurrentKeyModifiers());
}
bool QCocoaKeyMapper::updateKeyboard()
{
- const UCKeyboardLayout *uchrData = nullptr;
QCFType<TISInputSourceRef> source = TISCopyInputMethodKeyboardLayoutOverride();
if (!source)
source = TISCopyCurrentKeyboardInputSource();
- if (keyboard_mode != NullMode && source == currentInputSource) {
+
+ if (m_keyboardMode != NullMode && source == m_currentInputSource)
return false;
- }
+
Q_ASSERT(source);
- CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(source,
- kTISPropertyUnicodeKeyLayoutData));
- uchrData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : nullptr;
-
- keyboard_kind = LMGetKbdType();
- if (uchrData) {
- keyboard_layout_format = uchrData;
- keyboard_mode = UnicodeMode;
+ m_currentInputSource = source;
+ m_keyboardKind = LMGetKbdType();
+ m_deadKeyState = 0;
+
+ deleteLayouts();
+
+ if (auto data = CFDataRef(TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData))) {
+ const UCKeyboardLayout *uchrData = reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data));
+ Q_ASSERT(uchrData);
+ m_keyboardLayoutFormat = uchrData;
+ m_keyboardMode = UnicodeMode;
} else {
- keyboard_layout_format = nullptr;
- keyboard_mode = NullMode;
+ m_keyboardLayoutFormat = nullptr;
+ m_keyboardMode = NullMode;
}
- currentInputSource = source;
- keyboard_dead = 0;
- const auto newMode = keyboard_mode;
- deleteLayouts();
- keyboard_mode = newMode;
+ qCDebug(lcQpaKeyMapper) << "Updated keyboard to"
+ << QString::fromCFString(CFStringRef(TISGetInputSourceProperty(
+ m_currentInputSource, kTISPropertyLocalizedName)));
return true;
}
void QCocoaKeyMapper::deleteLayouts()
{
- keyboard_mode = NullMode;
+ m_keyboardMode = NullMode;
for (int i = 0; i < 255; ++i) {
- if (keyLayout[i]) {
- delete keyLayout[i];
- keyLayout[i] = nullptr;
+ if (m_keyLayout[i]) {
+ delete m_keyLayout[i];
+ m_keyLayout[i] = nullptr;
}
}
}
@@ -404,69 +343,98 @@ void QCocoaKeyMapper::clearMappings()
updateKeyboard();
}
+static constexpr Qt::KeyboardModifiers modifierCombinations[] = {
+ Qt::NoModifier, // 0
+ Qt::ShiftModifier, // 1
+ Qt::ControlModifier, // 2
+ Qt::ControlModifier | Qt::ShiftModifier, // 3
+ Qt::AltModifier, // 4
+ Qt::AltModifier | Qt::ShiftModifier, // 5
+ Qt::AltModifier | Qt::ControlModifier, // 6
+ Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7
+ Qt::MetaModifier, // 8
+ Qt::MetaModifier | Qt::ShiftModifier, // 9
+ Qt::MetaModifier | Qt::ControlModifier, // 10
+ Qt::MetaModifier | Qt::ControlModifier | Qt::ShiftModifier, // 11
+ Qt::MetaModifier | Qt::AltModifier, // 12
+ Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier, // 13
+ Qt::MetaModifier | Qt::AltModifier | Qt::ControlModifier, // 14
+ Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 15
+};
+
+/*
+ Updates the key map for the given \macVirtualKey by applying
+ all possible modifier combinations.
+*/
void QCocoaKeyMapper::updateKeyMap(unsigned short macVirtualKey, QChar unicodeKey)
{
updateKeyboard();
- if (keyLayout[macVirtualKey])
+ if (m_keyLayout[macVirtualKey])
return;
- UniCharCount buffer_size = 10;
- UniChar buffer[buffer_size];
- keyLayout[macVirtualKey] = new KeyboardLayoutItem;
- for (int i = 0; i < 16; ++i) {
- UniCharCount out_buffer_size = 0;
- keyLayout[macVirtualKey]->qtKey[i] = 0;
-
- const UInt32 keyModifier = ((qt_mac_get_mac_modifiers(ModsTbl[i]) >> 8) & 0xFF);
- OSStatus err = UCKeyTranslate(keyboard_layout_format, macVirtualKey, kUCKeyActionDown, keyModifier,
- keyboard_kind, 0, &keyboard_dead, buffer_size, &out_buffer_size, buffer);
- if (err == noErr && out_buffer_size) {
- const QChar unicode(buffer[0]);
- int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey);
- if (qtkey == Qt::Key_unknown)
- qtkey = unicode.unicode();
- keyLayout[macVirtualKey]->qtKey[i] = qtkey;
- } else {
- int qtkey = qt_mac_get_key(keyModifier, unicodeKey, macVirtualKey);
- if (qtkey == Qt::Key_unknown)
- qtkey = unicodeKey.unicode();
- keyLayout[macVirtualKey]->qtKey[i] = qtkey;
- }
- }
-#ifdef DEBUG_KEY_MAPS
- qDebug("updateKeyMap for virtual key = 0x%02x!", (uint)macVirtualKey);
+ qCDebug(lcQpaKeyMapper, "Updating key map for virtual key = 0x%02x!", (uint)macVirtualKey);
+
+ UniCharCount maxStringLength = 10;
+ UniChar unicodeString[maxStringLength];
+ m_keyLayout[macVirtualKey] = new KeyboardLayoutItem;
+
for (int i = 0; i < 16; ++i) {
- qDebug(" [%d] (%d,0x%02x,'%c')", i,
- keyLayout[macVirtualKey]->qtKey[i],
- keyLayout[macVirtualKey]->qtKey[i],
- keyLayout[macVirtualKey]->qtKey[i]);
+ UniCharCount actualStringLength = 0;
+ m_keyLayout[macVirtualKey]->qtKey[i] = 0;
+
+ auto qtModifiers = modifierCombinations[i];
+ auto carbonModifiers = toCarbonModifiers(qtModifiers);
+ const UInt32 modifierKeyState = (carbonModifiers >> 8) & 0xFF;
+ OSStatus err = UCKeyTranslate(m_keyboardLayoutFormat, macVirtualKey,
+ kUCKeyActionDown, modifierKeyState, m_keyboardKind, OptionBits(0),
+ &m_deadKeyState, maxStringLength, &actualStringLength, unicodeString);
+
+ // Use translated unicode key if valid
+ if (err == noErr && actualStringLength)
+ unicodeKey = QChar(unicodeString[0]);
+
+ int qtkey = toKeyCode(unicodeKey, macVirtualKey, modifierKeyState);
+ if (qtkey == Qt::Key_unknown)
+ qtkey = unicodeKey.unicode();
+
+ m_keyLayout[macVirtualKey]->qtKey[i] = qtkey;
+
+ qCDebug(lcQpaKeyMapper, " [%d] (%d,0x%02x,'%c')", i, qtkey, qtkey, qtkey);
}
-#endif
}
QList<int> QCocoaKeyMapper::possibleKeys(const QKeyEvent *event) const
{
QList<int> ret;
- const_cast<QCocoaKeyMapper *>(this)->updateKeyMap(event->nativeVirtualKey(), QChar(event->key()));
- KeyboardLayoutItem *kbItem = keyLayout[event->nativeVirtualKey()];
+ auto virtualKey = event->nativeVirtualKey();
+ const_cast<QCocoaKeyMapper *>(this)->updateKeyMap(virtualKey, QChar(event->key()));
+ KeyboardLayoutItem *keyLayout = m_keyLayout[virtualKey];
- if (!kbItem) // Key is not in any keyboard layout (e.g. eisu-key on Japanese keyboard)
+ if (!keyLayout) // Key is not in any keyboard layout (e.g. eisu-key on Japanese keyboard)
return ret;
- int baseKey = kbItem->qtKey[0];
- Qt::KeyboardModifiers keyMods = event->modifiers();
+ int baseKey = keyLayout->qtKey[Qt::NoModifier];
+ auto eventModifiers = event->modifiers();
- ret << int(baseKey + keyMods); // The base key is _always_ valid, of course
+ // The base key is always valid
+ ret << int(baseKey + eventModifiers);
for (int i = 1; i < 8; ++i) {
- Qt::KeyboardModifiers neededMods = ModsTbl[i];
- int key = kbItem->qtKey[i];
- if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) {
- ret << int(key + (keyMods & ~neededMods));
- }
+ int keyAfterApplyingModifiers = keyLayout->qtKey[i];
+ if (!keyAfterApplyingModifiers)
+ continue;
+ if (keyAfterApplyingModifiers == baseKey)
+ continue;
+
+ // Include key if event modifiers includes, or matches
+ // perfectly, the current candidate modifiers.
+ auto candidateModifiers = modifierCombinations[i];
+ if ((eventModifiers & candidateModifiers) == candidateModifiers)
+ ret << int(keyAfterApplyingModifiers + (eventModifiers & ~candidateModifiers));
}
+
return ret;
}