macOS: Prevent mapping non-keydown events to characters

The [NSEvent charactersByApplyingModifiers:] API only supports key
down events, but we might get into QCocoaKeyMapper::keyMapForKey for
modifier key presses as well (even if QShortcutMap::nextState tries
to filter out modifier keys).

Change-Id: I02f163edac2baa9052f34b4d5d31b6a627d3d85c
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
Tor Arne Vestbø 2020-10-02 19:16:09 +02:00
parent fa8d021fa6
commit 7aac974c78

View File

@ -454,6 +454,14 @@ const QCocoaKeyMapper::KeyMap &QCocoaKeyMapper::keyMapForKey(VirtualKeyCode virt
qCDebug(lcQpaKeyMapper, "Updating key map for virtual key = 0x%02x!", (uint)virtualKey);
// Key mapping via [NSEvent charactersByApplyingModifiers:] only works for key down
// events, but we might (wrongly) get into this code path for other key events such
// as NSEventTypeFlagsChanged.
const bool canMapCocoaEvent = NSApp.currentEvent.type == NSEventTypeKeyDown;
if (!canMapCocoaEvent)
qCWarning(lcQpaKeyMapper) << "Could not map key to character for event" << NSApp.currentEvent;
for (int i = 0; i < kNumModifierCombinations; ++i) {
Q_ASSERT(!i || keyMap[i] == 0);
@ -473,19 +481,19 @@ const QCocoaKeyMapper::KeyMap &QCocoaKeyMapper::keyMapForKey(VirtualKeyCode virt
unicodeKey = QChar(unicodeString[0]);
if (@available(macOS 10.15, *)) {
// Until we've verified that the Cocoa API works as expected
// we first run the event through the Carbon APIs and then
// compare the results to Cocoa.
Q_ASSERT(NSApp.currentEvent);
Q_ASSERT(NSApp.currentEvent.type == NSEventTypeKeyDown);
auto cocoaModifiers = toCocoaModifiers(qtModifiers);
auto *charactersWithModifiers = [NSApp.currentEvent charactersByApplyingModifiers:cocoaModifiers];
Q_ASSERT(charactersWithModifiers && charactersWithModifiers.length > 0);
auto cocoaUnicodeKey = QChar([charactersWithModifiers characterAtIndex:0]);
if (cocoaUnicodeKey != unicodeKey) {
qCWarning(lcQpaKeyMapper) << "Mismatch between Cocoa" << cocoaUnicodeKey
<< "and Carbon" << unicodeKey << "for virtual key" << virtualKey
<< "with" << qtModifiers;
if (canMapCocoaEvent) {
// Until we've verified that the Cocoa API works as expected
// we first run the event through the Carbon APIs and then
// compare the results to Cocoa.
auto cocoaModifiers = toCocoaModifiers(qtModifiers);
auto *charactersWithModifiers = [NSApp.currentEvent charactersByApplyingModifiers:cocoaModifiers];
Q_ASSERT(charactersWithModifiers && charactersWithModifiers.length > 0);
auto cocoaUnicodeKey = QChar([charactersWithModifiers characterAtIndex:0]);
if (cocoaUnicodeKey != unicodeKey) {
qCWarning(lcQpaKeyMapper) << "Mismatch between Cocoa" << cocoaUnicodeKey
<< "and Carbon" << unicodeKey << "for virtual key" << virtualKey
<< "with" << qtModifiers;
}
}
}