wasm: simplify QWasmWindow constructor

The code implements parts of the event handling as lambdas in
the constructor. This makes it hard to see what the constructor
code itself does.

Instead, move the initial handling of the emscripten::val
event to event handler functions, which then call the existing
process event functions.

Change-Id: I3abc5be47b080c772c699c21f2fe1cc555ff8192
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Piotr Wierciński <piotr.wiercinski@qt.io>
(cherry picked from commit 3117d88cdf2324a7833cdf9ceecc4cba30e1e090)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Morten Sørvig 2024-08-29 15:06:51 +02:00 committed by Qt Cherry-pick Bot
parent e2198f7580
commit 9e7eef5def
2 changed files with 91 additions and 86 deletions

View File

@ -106,99 +106,27 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport,
m_flags = window()->flags();
const auto pointerCallback = std::function([this](emscripten::val event) {
const auto eventTypeString = event["type"].as<std::string>();
// Ideally it should not be happened but
// it takes place sometime with some reason
// without compositionend.
QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
if (wasmInput && !wasmInput->preeditString().isEmpty())
wasmInput->commitPreeditAndClear();
if (processPointer(*PointerEvent::fromWeb(event)))
event.call<void>("preventDefault");
});
m_pointerEnterCallback =
std::make_unique<qstdweb::EventCallback>(m_qtWindow, "pointerenter", pointerCallback);
m_pointerLeaveCallback =
std::make_unique<qstdweb::EventCallback>(m_qtWindow, "pointerleave", pointerCallback);
m_wheelEventCallback = std::make_unique<qstdweb::EventCallback>(
m_qtWindow, "wheel", [this](emscripten::val event) {
if (processWheel(*WheelEvent::fromWeb(event)))
event.call<void>("preventDefault");
});
const auto keyCallbackForInputContext = std::function([this](emscripten::val event) {
QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
if (wasmInput) {
const auto keyString = QString::fromStdString(event["key"].as<std::string>());
qCDebug(qLcQpaWasmInputContext) << "Key callback" << keyString << keyString.size();
if (keyString == "Unidentified") {
// Android makes a bunch of KeyEvents as "Unidentified"
// They will be processed just in InputContext.
return;
} else if (event["ctrlKey"].as<bool>()
|| event["altKey"].as<bool>()
|| event["metaKey"].as<bool>()) {
if (processKeyForInputContext(*KeyEvent::fromWebWithDeadKeyTranslation(event, m_deadKeySupport)))
event.call<void>("preventDefault");
event.call<void>("stopImmediatePropagation");
return;
} else if (keyString.size() != 1) {
if (!wasmInput->preeditString().isEmpty()) {
if (keyString == "Process" || keyString == "Backspace") {
// processed by InputContext
// "Process" should be handled by InputContext but
// QWasmInputContext's function is incomplete now
// so, there will be some exceptions here.
return;
} else if (keyString != "Shift"
&& keyString != "Meta"
&& keyString != "Alt"
&& keyString != "Control"
&& !keyString.startsWith("Arrow")) {
wasmInput->commitPreeditAndClear();
}
}
} else if (wasmInput->inputMethodAccepted()) {
// processed in inputContext with skipping processKey
return;
}
}
qCDebug(qLcQpaWasmInputContext) << "processKey as KeyEvent";
if (processKeyForInputContext(*KeyEvent::fromWebWithDeadKeyTranslation(event, m_deadKeySupport)))
event.call<void>("preventDefault");
event.call<void>("stopImmediatePropagation");
});
const auto keyCallback = std::function([this](emscripten::val event) {
qCDebug(qLcQpaWasmInputContext) << "processKey as KeyEvent";
if (processKey(*KeyEvent::fromWebWithDeadKeyTranslation(event, m_deadKeySupport)))
event.call<void>("preventDefault");
event.call<void>("stopPropagation");
});
m_pointerEnterCallback = std::make_unique<qstdweb::EventCallback>(m_qtWindow, "pointerenter",
[this](emscripten::val event) { this->handlePointerEvent(event); });
m_pointerLeaveCallback = std::make_unique<qstdweb::EventCallback>(m_qtWindow, "pointerleave",
[this](emscripten::val event) { this->handlePointerEvent(event); });
m_wheelEventCallback = std::make_unique<qstdweb::EventCallback>( m_qtWindow, "wheel",
[this](emscripten::val event) { this->handleWheelEvent(event); });
QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
if (wasmInput) {
m_keyDownCallbackForInputContext =
std::make_unique<qstdweb::EventCallback>(wasmInput->m_inputElement,
"keydown",
keyCallbackForInputContext);
std::make_unique<qstdweb::EventCallback>(wasmInput->m_inputElement, "keydown",
[this](emscripten::val event) { this->handleKeyForInputContextEvent(event); });
m_keyUpCallbackForInputContext =
std::make_unique<qstdweb::EventCallback>(wasmInput->m_inputElement,
"keyup",
keyCallbackForInputContext);
std::make_unique<qstdweb::EventCallback>(wasmInput->m_inputElement, "keyup",
[this](emscripten::val event) { this->handleKeyForInputContextEvent(event); });
}
m_keyDownCallback =
std::make_unique<qstdweb::EventCallback>(m_qtWindow, "keydown", keyCallback);
m_keyUpCallback =std::make_unique<qstdweb::EventCallback>(m_qtWindow, "keyup", keyCallback);
m_keyDownCallback = std::make_unique<qstdweb::EventCallback>(m_qtWindow, "keydown",
[this](emscripten::val event) { this->handleKeyEvent(event); });
m_keyUpCallback =std::make_unique<qstdweb::EventCallback>(m_qtWindow, "keyup",
[this](emscripten::val event) { this->handleKeyEvent(event); });
setParent(parent());
}
@ -544,6 +472,14 @@ void QWasmWindow::commitParent(QWasmWindowTreeNode *parent)
m_commitedParent = parent;
}
void QWasmWindow::handleKeyEvent(const emscripten::val &event)
{
qCDebug(qLcQpaWasmInputContext) << "processKey as KeyEvent";
if (processKey(*KeyEvent::fromWebWithDeadKeyTranslation(event, m_deadKeySupport)))
event.call<void>("preventDefault");
event.call<void>("stopPropagation");
}
bool QWasmWindow::processKey(const KeyEvent &event)
{
constexpr bool ProceedToNativeEvent = false;
@ -564,6 +500,52 @@ bool QWasmWindow::processKey(const KeyEvent &event)
: result;
}
void QWasmWindow::handleKeyForInputContextEvent(const emscripten::val &event)
{
QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
if (wasmInput) {
const auto keyString = QString::fromStdString(event["key"].as<std::string>());
qCDebug(qLcQpaWasmInputContext) << "Key callback" << keyString << keyString.size();
if (keyString == "Unidentified") {
// Android makes a bunch of KeyEvents as "Unidentified"
// They will be processed just in InputContext.
return;
} else if (event["ctrlKey"].as<bool>()
|| event["altKey"].as<bool>()
|| event["metaKey"].as<bool>()) {
if (processKeyForInputContext(*KeyEvent::fromWebWithDeadKeyTranslation(event, m_deadKeySupport)))
event.call<void>("preventDefault");
event.call<void>("stopImmediatePropagation");
return;
} else if (keyString.size() != 1) {
if (!wasmInput->preeditString().isEmpty()) {
if (keyString == "Process" || keyString == "Backspace") {
// processed by InputContext
// "Process" should be handled by InputContext but
// QWasmInputContext's function is incomplete now
// so, there will be some exceptions here.
return;
} else if (keyString != "Shift"
&& keyString != "Meta"
&& keyString != "Alt"
&& keyString != "Control"
&& !keyString.startsWith("Arrow")) {
wasmInput->commitPreeditAndClear();
}
}
} else if (wasmInput->inputMethodAccepted()) {
// processed in inputContext with skipping processKey
return;
}
}
qCDebug(qLcQpaWasmInputContext) << "processKey as KeyEvent";
if (processKeyForInputContext(*KeyEvent::fromWebWithDeadKeyTranslation(event, m_deadKeySupport)))
event.call<void>("preventDefault");
event.call<void>("stopImmediatePropagation");
}
bool QWasmWindow::processKeyForInputContext(const KeyEvent &event)
{
qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO;
@ -587,6 +569,19 @@ bool QWasmWindow::processKeyForInputContext(const KeyEvent &event)
return result;
}
void QWasmWindow::handlePointerEvent(const emscripten::val &event)
{
// Ideally it should not be happened but
// it takes place sometime with some reason
// without compositionend.
QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
if (wasmInput && !wasmInput->preeditString().isEmpty())
wasmInput->commitPreeditAndClear();
if (processPointer(*PointerEvent::fromWeb(event)))
event.call<void>("preventDefault");
}
bool QWasmWindow::processPointer(const PointerEvent &event)
{
if (event.pointerType != PointerType::Mouse && event.pointerType != PointerType::Pen)
@ -610,6 +605,12 @@ bool QWasmWindow::processPointer(const PointerEvent &event)
return false;
}
void QWasmWindow::handleWheelEvent(const emscripten::val &event)
{
if (processWheel(*WheelEvent::fromWeb(event)))
event.call<void>("preventDefault");
}
bool QWasmWindow::processWheel(const WheelEvent &event)
{
// Web scroll deltas are inverted from Qt deltas - negate.

View File

@ -123,9 +123,13 @@ private:
void applyWindowState();
void commitParent(QWasmWindowTreeNode *parent);
void handleKeyEvent(const emscripten::val &event);
bool processKey(const KeyEvent &event);
void handleKeyForInputContextEvent(const emscripten::val &event);
bool processKeyForInputContext(const KeyEvent &event);
void handlePointerEvent(const emscripten::val &event);
bool processPointer(const PointerEvent &event);
void handleWheelEvent(const emscripten::val &event);
bool processWheel(const WheelEvent &event);
QWindow *m_window = nullptr;