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 <lorn.potter@gmail.com>
This commit is contained in:
Mikolaj Boc 2022-07-29 16:34:29 +02:00
parent 998bd0b528
commit 7485213930
3 changed files with 69 additions and 76 deletions

View File

@ -1131,63 +1131,28 @@ void QWasmCompositor::WindowManipulation::onPointerUp(const PointerEvent& event)
m_screen->canvas().call<void>("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<Qt::KeyboardModifier> modifiers = KeyboardModifier::getForEvent(*keyEvent);
const QFlags<Qt::KeyboardModifier> 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<QWindowSystemInterface::SynchronousDelivery>(
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<QWindowSystemInterface::SynchronousDelivery>(
0, translatedEvent.type, translatedEvent.key, modifiers, translatedEvent.text);
}
bool QWasmCompositor::processWheel(int eventType, const EmscriptenWheelEvent *wheelEvent)

View File

@ -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

View File

@ -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