From 74852139308b3798ffefbf94c62a056bdb1898c4 Mon Sep 17 00:00:00 2001 From: Mikolaj Boc Date: Fri, 29 Jul 2022 16:34:29 +0200 Subject: [PATCH] Deliver correct key code on key release on WASM Changed the behavior in which key events are delivered to targets. Before the change, in case of a EMSCRIPTEN_EVENT_KEYUP event, the key code and text were not filled in correctly as they should. This resulted in wrong behavior when event targets expected these codes being available. Fixes: QTBUG-105213 Change-Id: Ie66b5d6d395d08af655fcb00f1f616ad43d6bea4 Reviewed-by: Lorn Potter --- .../platforms/wasm/qwasmcompositor.cpp | 67 +++++-------------- .../platforms/wasm/qwasmeventtranslator.cpp | 67 +++++++++++++------ .../platforms/wasm/qwasmeventtranslator.h | 11 ++- 3 files changed, 69 insertions(+), 76 deletions(-) diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index 5547fac2ad0..e93098cf79d 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -1131,63 +1131,28 @@ void QWasmCompositor::WindowManipulation::onPointerUp(const PointerEvent& event) m_screen->canvas().call("releasePointerCapture", event.pointerId); } -bool QWasmCompositor::processKeyboard(int eventType, const EmscriptenKeyboardEvent *keyEvent) +bool QWasmCompositor::processKeyboard(int eventType, const EmscriptenKeyboardEvent *emKeyEvent) { - Qt::Key qtKey; - QString keyText; - QEvent::Type keyType = QEvent::None; - switch (eventType) { - case EMSCRIPTEN_EVENT_KEYPRESS: - case EMSCRIPTEN_EVENT_KEYDOWN: // down - keyType = QEvent::KeyPress; - qtKey = m_eventTranslator->getKey(keyEvent); - keyText = m_eventTranslator->getKeyText(keyEvent, qtKey); - break; - case EMSCRIPTEN_EVENT_KEYUP: // up - keyType = QEvent::KeyRelease; - break; - default: - break; - }; + Q_ASSERT(eventType == EMSCRIPTEN_EVENT_KEYDOWN || eventType == EMSCRIPTEN_EVENT_KEYUP); - if (keyType == QEvent::None) - return 0; + auto translatedEvent = m_eventTranslator->translateKeyEvent(eventType, emKeyEvent); - QFlags modifiers = KeyboardModifier::getForEvent(*keyEvent); + const QFlags modifiers = KeyboardModifier::getForEvent(*emKeyEvent); - // Clipboard fallback path: cut/copy/paste are handled by clipboard event - // handlers if direct clipboard access is not available. - if (!QWasmIntegration::get()->getWasmClipboard()->hasClipboardApi && modifiers & Qt::ControlModifier && - (qtKey == Qt::Key_X || qtKey == Qt::Key_C || qtKey == Qt::Key_V)) { - if (qtKey == Qt::Key_V) { - QWasmIntegration::get()->getWasmClipboard()->isPaste = true; - } - return false; + // Clipboard path: cut/copy/paste are handled by clipboard event or direct clipboard access. + if (translatedEvent.type == QEvent::KeyPress && modifiers.testFlag(Qt::ControlModifier) + && (translatedEvent.key == Qt::Key_X || translatedEvent.key == Qt::Key_V + || translatedEvent.key == Qt::Key_C)) { + QWasmIntegration::get()->getWasmClipboard()->isPaste = translatedEvent.key == Qt::Key_V; + return false; // continue on to event } - bool accepted = false; - - if (keyType == QEvent::KeyPress && - modifiers.testFlag(Qt::ControlModifier) - && qtKey == Qt::Key_V) { - QWasmIntegration::get()->getWasmClipboard()->isPaste = true; - accepted = false; // continue on to event - } else { - if (keyText.isEmpty()) - keyText = QString(keyEvent->key); - if (keyText.size() > 1) - keyText.clear(); - accepted = QWindowSystemInterface::handleKeyEvent( - 0, keyType, qtKey, modifiers, keyText); - } - if (keyType == QEvent::KeyPress && - modifiers.testFlag(Qt::ControlModifier) - && qtKey == Qt::Key_C) { - QWasmIntegration::get()->getWasmClipboard()->isPaste = false; - accepted = false; // continue on to event - } - - return accepted; + if (translatedEvent.text.isEmpty()) + translatedEvent.text = QString(emKeyEvent->key); + if (translatedEvent.text.size() > 1) + translatedEvent.text.clear(); + return QWindowSystemInterface::handleKeyEvent( + 0, translatedEvent.type, translatedEvent.key, modifiers, translatedEvent.text); } bool QWasmCompositor::processWheel(int eventType, const EmscriptenWheelEvent *wheelEvent) diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp index fdf3eede031..01f15e7dffe 100644 --- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp +++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp @@ -304,34 +304,57 @@ QCursor QWasmEventTranslator::cursorForMode(QWasmCompositor::ResizeMode m) return Qt::ArrowCursor; } -QString QWasmEventTranslator::getKeyText(const EmscriptenKeyboardEvent *keyEvent, Qt::Key qtKey) +QWasmEventTranslator::TranslatedEvent +QWasmEventTranslator::translateKeyEvent(int emEventType, const EmscriptenKeyboardEvent *keyEvent) { - if (m_emDeadKey != Qt::Key_unknown) { - const Qt::Key translatedKey = translateBaseKeyUsingDeadKey(qtKey, m_emDeadKey); + TranslatedEvent ret; + switch (emEventType) { + case EMSCRIPTEN_EVENT_KEYDOWN: + ret.type = QEvent::KeyPress; + break; + case EMSCRIPTEN_EVENT_KEYUP: + ret.type = QEvent::KeyRelease; + break; + default: + // Should not be reached - do not call with this event type. + Q_ASSERT(false); + break; + }; + + ret.key = translateEmscriptKey(keyEvent); + + if (isDeadKeyEvent(keyEvent) || ret.key == Qt::Key_AltGr) { + if (keyEvent->shiftKey && ret.key == Qt::Key_QuoteLeft) + ret.key = Qt::Key_AsciiTilde; + m_emDeadKey = ret.key; + } + + if (m_emDeadKey != Qt::Key_unknown + && (m_keyModifiedByDeadKeyOnPress == Qt::Key_unknown + || ret.key == m_keyModifiedByDeadKeyOnPress)) { + const Qt::Key baseKey = ret.key; + const Qt::Key translatedKey = translateBaseKeyUsingDeadKey(baseKey, m_emDeadKey); if (translatedKey != Qt::Key_unknown) - qtKey = translatedKey; + ret.key = translatedKey; if (auto text = keyEvent->shiftKey - ? findKeyTextByKeyId(WebToQtKeyCodeMappingsWithShift, qtKey) - : findKeyTextByKeyId(WebToQtKeyCodeMappings, qtKey)) { - m_emDeadKey = Qt::Key_unknown; - return *text; + ? findKeyTextByKeyId(WebToQtKeyCodeMappingsWithShift, ret.key) + : findKeyTextByKeyId(WebToQtKeyCodeMappings, ret.key)) { + if (ret.type == QEvent::KeyPress) { + Q_ASSERT(m_keyModifiedByDeadKeyOnPress == Qt::Key_unknown); + m_keyModifiedByDeadKeyOnPress = baseKey; + } else { + Q_ASSERT(ret.type == QEvent::KeyRelease); + Q_ASSERT(m_keyModifiedByDeadKeyOnPress == baseKey); + m_keyModifiedByDeadKeyOnPress = Qt::Key_unknown; + m_emDeadKey = Qt::Key_unknown; + } + ret.text = *text; + return ret; } } - return QString::fromUtf8(keyEvent->key); -} - -Qt::Key QWasmEventTranslator::getKey(const EmscriptenKeyboardEvent *keyEvent) -{ - Qt::Key qtKey = translateEmscriptKey(keyEvent); - - if (isDeadKeyEvent(keyEvent) || qtKey == Qt::Key_AltGr) { - if (keyEvent->shiftKey && qtKey == Qt::Key_QuoteLeft) - qtKey = Qt::Key_AsciiTilde; - m_emDeadKey = qtKey; - } - - return qtKey; + ret.text = QString::fromUtf8(keyEvent->key); + return ret; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.h b/src/plugins/platforms/wasm/qwasmeventtranslator.h index 5bde30ab91a..8f4e9f6d05f 100644 --- a/src/plugins/platforms/wasm/qwasmeventtranslator.h +++ b/src/plugins/platforms/wasm/qwasmeventtranslator.h @@ -24,19 +24,24 @@ class QWasmEventTranslator : public QObject Q_OBJECT public: + struct TranslatedEvent + { + QEvent::Type type; + Qt::Key key; + QString text; + }; explicit QWasmEventTranslator(); ~QWasmEventTranslator(); static QCursor cursorForMode(QWasmCompositor::ResizeMode mode); - QString getKeyText(const EmscriptenKeyboardEvent *keyEvent, Qt::Key key); - Qt::Key getKey(const EmscriptenKeyboardEvent *keyEvent); + TranslatedEvent translateKeyEvent(int emEventType, const EmscriptenKeyboardEvent *keyEvent); private: static quint64 getTimestamp(); Qt::Key m_emDeadKey = Qt::Key_unknown; - + Qt::Key m_keyModifiedByDeadKeyOnPress = Qt::Key_unknown; }; QT_END_NAMESPACE