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:
parent
998bd0b528
commit
7485213930
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user