From 784555cc2fa9d1625a4cac458c15d28cf0c1f4d7 Mon Sep 17 00:00:00 2001 From: Mikolaj Boc Date: Fri, 29 Jul 2022 08:57:16 +0200 Subject: Refactor QWasmEventTranslator for added readability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change listing: - change names of abbreviated structures/variables (e.g. KeyTbl -> WebToQtKeyCodeMappings) - add constants for commonly used magic strings ("Dead", StringTerminator) - use common idioms for common tasks (find_if, std::optional) - use binary search as facilitated by the sorted array instead of a full search - this optimizes the code at no cost - remove dead code (double translateEmscriptKey in QWasmEventTranslator::getKey, remove sticky dead key support as it was write-only, remove the dead setIsMac and g_usePlatformMacSpecifics, remove the dead getWindowAt). - cull the public interface on QWasmEventTranslator as some functions are only used internally (translateEmscriptKey) - simplify / shorten functions by short-circuiting - modernize definitions (= default) - auto-format the changes using clang-format The file is now much easier to read and understand. Change-Id: I5ea2bdafd9b9abc009feeb5516ddd87fb0ca212e Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/wasm/qwasmcompositor.cpp | 1 - .../platforms/wasm/qwasmeventtranslator.cpp | 197 +++++++++------------ src/plugins/platforms/wasm/qwasmeventtranslator.h | 12 -- 3 files changed, 83 insertions(+), 127 deletions(-) diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index f7545b855c..5547fac2ad 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -1145,7 +1145,6 @@ bool QWasmCompositor::processKeyboard(int eventType, const EmscriptenKeyboardEve break; case EMSCRIPTEN_EVENT_KEYUP: // up keyType = QEvent::KeyRelease; - m_eventTranslator->setStickyDeadKey(keyEvent); break; default: break; diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp index d99d9f7d9a..fdf3eede03 100644 --- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp +++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp @@ -28,41 +28,47 @@ QT_BEGIN_NAMESPACE using namespace emscripten; -typedef struct emkb2qt { +namespace { +constexpr std::string_view WebDeadKeyValue = "Dead"; + +struct Emkb2QtData +{ + static constexpr char StringTerminator = '\0'; + const char *em; unsigned int qt; - constexpr bool operator <=(const emkb2qt &that) const noexcept + constexpr bool operator<=(const Emkb2QtData &that) const noexcept { return !(strcmp(that) > 0); } - bool operator <(const emkb2qt &that) const noexcept + bool operator<(const Emkb2QtData &that) const noexcept { return ::strcmp(em, that.em) < 0; } + + constexpr bool operator==(const Emkb2QtData &that) const noexcept { return strcmp(that) == 0; } + + constexpr int strcmp(const Emkb2QtData &that, const int i = 0) const { - return ::strcmp(em, that.em) < 0; + return em[i] == StringTerminator && that.em[i] == StringTerminator ? 0 + : em[i] == StringTerminator ? -1 + : that.em[i] == StringTerminator ? 1 + : em[i] < that.em[i] ? -1 + : em[i] > that.em[i] ? 1 + : strcmp(that, i + 1); } - constexpr int strcmp(const emkb2qt &that, const int i = 0) const - { - return em[i] == 0 && that.em[i] == 0 ? 0 - : em[i] == 0 ? -1 - : that.em[i] == 0 ? 1 - : em[i] < that.em[i] ? -1 - : em[i] > that.em[i] ? 1 - : strcmp(that, i + 1); - } -} emkb2qt_t; +}; template struct Emkb2Qt { static constexpr const char storage[sizeof ... (EmChar) + 1] = {EmChar..., '\0'}; - using Type = emkb2qt_t; + using Type = Emkb2QtData; static constexpr Type data() noexcept { return Type{storage, Qt}; } }; template constexpr char Emkb2Qt::storage[]; -static constexpr const auto KeyTbl = qMakeArray( +static constexpr const auto WebToQtKeyCodeMappings = qMakeArray( QSortedData< Emkb2Qt< Qt::Key_Escape, 'E','s','c','a','p','e' >, Emkb2Qt< Qt::Key_Tab, 'T','a','b' >, @@ -120,7 +126,7 @@ static constexpr const auto KeyTbl = qMakeArray( >::Data{} ); -static constexpr const auto DeadKeyShiftTbl = qMakeArray( +static constexpr const auto WebToQtKeyCodeMappingsWithShift = qMakeArray( QSortedData< // shifted Emkb2Qt< Qt::Key_Agrave, '\xc3','\x80' >, @@ -155,42 +161,33 @@ static constexpr const auto DeadKeyShiftTbl = qMakeArray( >::Data{} ); -QWasmEventTranslator::QWasmEventTranslator() : QObject() +std::optional findMappingByBisection(const char *toFind) { + const Emkb2QtData searchKey{ toFind, 0 }; + const auto it = std::lower_bound(WebToQtKeyCodeMappings.cbegin(), WebToQtKeyCodeMappings.cend(), + searchKey); + return it != WebToQtKeyCodeMappings.cend() && searchKey == *it ? static_cast(it->qt) + : std::optional(); } -QWasmEventTranslator::~QWasmEventTranslator() +bool isDeadKeyEvent(const EmscriptenKeyboardEvent *emKeyEvent) { + return qstrncmp(emKeyEvent->key, WebDeadKeyValue.data(), WebDeadKeyValue.size()) == 0; } -Qt::Key QWasmEventTranslator::translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey) +Qt::Key translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey) { - Qt::Key qtKey = Qt::Key_unknown; - - if (qstrncmp(emscriptKey->key, "Dead", 4) == 0 ) { - emkb2qt_t searchKey1{emscriptKey->code, 0}; - for (auto it1 = KeyTbl.cbegin(); it1 != KeyTbl.end(); ++it1) - if (it1 != KeyTbl.end() && (qstrcmp(searchKey1.em, it1->em) == 0)) { - qtKey = static_cast(it1->qt); - } - } - if (qtKey == Qt::Key_unknown) { - emkb2qt_t searchKey{emscriptKey->key, 0}; - // search key - auto it1 = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey); - if (it1 != KeyTbl.end() && !(searchKey < *it1)) { - qtKey = static_cast(it1->qt); - } + if (isDeadKeyEvent(emscriptKey)) { + if (auto mapping = findMappingByBisection(emscriptKey->code)) + return *mapping; } + if (auto mapping = findMappingByBisection(emscriptKey->key)) + return *mapping; - if (qtKey == Qt::Key_unknown) { - // cast to unicode key - QString str = QString::fromUtf8(emscriptKey->key).toUpper(); - QStringIterator i(str); - qtKey = static_cast(i.next(0)); - } - - return qtKey; + // cast to unicode key + QString str = QString::fromUtf8(emscriptKey->key).toUpper(); + QStringIterator i(str); + return static_cast(i.next(0)); } struct KeyMapping { Qt::Key from, to; }; @@ -247,46 +244,45 @@ static Qt::Key find(const KeyMapping (&map)[N], Qt::Key key) noexcept return find_impl(map, map + N, key); } -Qt::Key QWasmEventTranslator::translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey) +Qt::Key translateBaseKeyUsingDeadKey(Qt::Key accentBaseKey, Qt::Key deadKey) { - Qt::Key wasmKey = Qt::Key_unknown; - - if (deadKey == Qt::Key_QuoteLeft ) { - if (platform() == Platform::MacOS) { // ` macOS: Key_Dead_Grave - wasmKey = find(graveKeyTable, accentBaseKey); - } else { - wasmKey = find(diaeresisKeyTable, accentBaseKey); - } - return wasmKey; - } - switch (deadKey) { - // case Qt::Key_QuoteLeft: + case Qt::Key_QuoteLeft: { + // ` macOS: Key_Dead_Grave + return platform() == Platform::MacOS ? find(graveKeyTable, accentBaseKey) + : find(diaeresisKeyTable, accentBaseKey); + } case Qt::Key_O: // ´ Key_Dead_Grave - wasmKey = find(graveKeyTable, accentBaseKey); - break; + return find(graveKeyTable, accentBaseKey); case Qt::Key_E: // ´ Key_Dead_Acute - wasmKey = find(acuteKeyTable, accentBaseKey); - break; + return find(acuteKeyTable, accentBaseKey); case Qt::Key_AsciiTilde: - case Qt::Key_N:// Key_Dead_Tilde - wasmKey = find(tildeKeyTable, accentBaseKey); - break; - case Qt::Key_U:// ¨ Key_Dead_Diaeresis - wasmKey = find(diaeresisKeyTable, accentBaseKey); - break; - case Qt::Key_I:// macOS Key_Dead_Circumflex - case Qt::Key_6:// linux - case Qt::Key_Apostrophe:// linux - wasmKey = find(circumflexKeyTable, accentBaseKey); - break; + case Qt::Key_N: // Key_Dead_Tilde + return find(tildeKeyTable, accentBaseKey); + case Qt::Key_U: // ¨ Key_Dead_Diaeresis + return find(diaeresisKeyTable, accentBaseKey); + case Qt::Key_I: // macOS Key_Dead_Circumflex + case Qt::Key_6: // linux + case Qt::Key_Apostrophe: // linux + return find(circumflexKeyTable, accentBaseKey); default: - break; - + return Qt::Key_unknown; }; - return wasmKey; } +template +std::optional findKeyTextByKeyId(const T &mappingArray, Qt::Key qtKey) +{ + const auto it = std::find_if(mappingArray.cbegin(), mappingArray.cend(), + [qtKey](const Emkb2QtData &data) { return data.qt == qtKey; }); + return it != mappingArray.cend() ? it->em : std::optional(); +} +} // namespace + +QWasmEventTranslator::QWasmEventTranslator() = default; + +QWasmEventTranslator::~QWasmEventTranslator() = default; + QCursor QWasmEventTranslator::cursorForMode(QWasmCompositor::ResizeMode m) { switch (m) { @@ -310,45 +306,27 @@ QCursor QWasmEventTranslator::cursorForMode(QWasmCompositor::ResizeMode m) QString QWasmEventTranslator::getKeyText(const EmscriptenKeyboardEvent *keyEvent, Qt::Key qtKey) { - QString keyText; - if (m_emDeadKey != Qt::Key_unknown) { - Qt::Key transformedKey = translateDeadKey(m_emDeadKey, qtKey); - - if (transformedKey != Qt::Key_unknown) - qtKey = transformedKey; - - if (keyEvent->shiftKey == 0) { - for (auto it = KeyTbl.cbegin(); it != KeyTbl.end(); ++it) { - if (it != KeyTbl.end() && (qtKey == static_cast(it->qt))) { - keyText = it->em; - m_emDeadKey = Qt::Key_unknown; - break; - } - } - } else { - for (auto it = DeadKeyShiftTbl.cbegin(); it != DeadKeyShiftTbl.end(); ++it) { - if (it != DeadKeyShiftTbl.end() && (qtKey == static_cast(it->qt))) { - keyText = it->em; - m_emDeadKey = Qt::Key_unknown; - break; - } - } + const Qt::Key translatedKey = translateBaseKeyUsingDeadKey(qtKey, m_emDeadKey); + if (translatedKey != Qt::Key_unknown) + qtKey = translatedKey; + + if (auto text = keyEvent->shiftKey + ? findKeyTextByKeyId(WebToQtKeyCodeMappingsWithShift, qtKey) + : findKeyTextByKeyId(WebToQtKeyCodeMappings, qtKey)) { + m_emDeadKey = Qt::Key_unknown; + return *text; } } - if (keyText.isEmpty()) - keyText = QString::fromUtf8(keyEvent->key); - return keyText; + return QString::fromUtf8(keyEvent->key); } Qt::Key QWasmEventTranslator::getKey(const EmscriptenKeyboardEvent *keyEvent) { Qt::Key qtKey = translateEmscriptKey(keyEvent); - if (qstrncmp(keyEvent->key, "Dead", 4) == 0 || qtKey == Qt::Key_AltGr) { - qtKey = translateEmscriptKey(keyEvent); - m_emStickyDeadKey = true; - if (keyEvent->shiftKey == 1 && qtKey == Qt::Key_QuoteLeft) + if (isDeadKeyEvent(keyEvent) || qtKey == Qt::Key_AltGr) { + if (keyEvent->shiftKey && qtKey == Qt::Key_QuoteLeft) qtKey = Qt::Key_AsciiTilde; m_emDeadKey = qtKey; } @@ -356,13 +334,4 @@ Qt::Key QWasmEventTranslator::getKey(const EmscriptenKeyboardEvent *keyEvent) return qtKey; } -void QWasmEventTranslator::setStickyDeadKey(const EmscriptenKeyboardEvent *keyEvent) -{ - Qt::Key qtKey = translateEmscriptKey(keyEvent); - - if (m_emStickyDeadKey && qtKey != Qt::Key_Alt) { - m_emStickyDeadKey = false; - } -} - QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.h b/src/plugins/platforms/wasm/qwasmeventtranslator.h index c076ba38bc..5bde30ab91 100644 --- a/src/plugins/platforms/wasm/qwasmeventtranslator.h +++ b/src/plugins/platforms/wasm/qwasmeventtranslator.h @@ -24,30 +24,18 @@ class QWasmEventTranslator : public QObject Q_OBJECT public: - explicit QWasmEventTranslator(); ~QWasmEventTranslator(); - static Qt::Key translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey); static QCursor cursorForMode(QWasmCompositor::ResizeMode mode); QString getKeyText(const EmscriptenKeyboardEvent *keyEvent, Qt::Key key); Qt::Key getKey(const EmscriptenKeyboardEvent *keyEvent); - void setStickyDeadKey(const EmscriptenKeyboardEvent *keyEvent); - - void setIsMac(bool is_mac) {g_usePlatformMacSpecifics = is_mac;}; - bool g_usePlatformMacSpecifics = false; - -Q_SIGNALS: - void getWindowAt(const QPoint &point, QWindow **window); -private: - static Qt::Key translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey); private: static quint64 getTimestamp(); Qt::Key m_emDeadKey = Qt::Key_unknown; - bool m_emStickyDeadKey = false; }; -- cgit v1.2.3