summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/wasm/qwasmwindow.cpp
diff options
context:
space:
mode:
authorInho Lee <[email protected]>2023-09-28 13:42:57 +0200
committerInho Lee <[email protected]>2024-07-05 06:54:26 +0200
commitc844a7a5429e74d7cefb9774f288dbaa76fc2bbb (patch)
treebd69ed99324654cd46bec7fe12a471de11f8ba49 /src/plugins/platforms/wasm/qwasmwindow.cpp
parent385c9397712b771e0f2c3f0a6322f0f624f09a8a (diff)
wasm: Revamp QWasmInputContext
1. Use QWasmInputContext by default 2. Use QInputMethodEvent instead of KeyEvent Todo: 1. Platform dependent preedit control especially when cursor moved with preedit. (Tested on Android, Linux, Windows) (Firefox still has a problem but it's not clear why PointerEvent doesn't happen.) 2. Apply existing text to inputMethodQueries. 3. Test on touchscreen devices. 4. Test on IOS devices. 5. When dragging selection, freezing 6. Support context menu Fixes: QTBUG-107139 Fixes: QTBUG-124932 Fixes: QTBUG-117096 Pick-to: 6.7 6.8 Change-Id: Iceb6af3489b3d1195ad58cf8f3deb91275fd1bf4 Reviewed-by: Lorn Potter <[email protected]>
Diffstat (limited to 'src/plugins/platforms/wasm/qwasmwindow.cpp')
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.cpp104
1 files changed, 92 insertions, 12 deletions
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp
index 174fff174e7..eb6b1cd2e3c 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.cpp
+++ b/src/plugins/platforms/wasm/qwasmwindow.cpp
@@ -30,6 +30,7 @@
#include <emscripten/val.h>
#include <QtCore/private/qstdweb_p.h>
+#include <QKeySequence>
QT_BEGIN_NAMESPACE
@@ -106,6 +107,15 @@ 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");
});
@@ -121,25 +131,74 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport,
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");
});
- emscripten::val keyFocusWindow;
- if (QWasmInputContext *wasmContext =
- qobject_cast<QWasmInputContext *>(QWasmIntegration::get()->inputContext())) {
- // if there is an touchscreen input context,
- // use that window for key input
- keyFocusWindow = wasmContext->m_inputElement;
- } else {
- keyFocusWindow = m_qtWindow;
+ QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
+ if (wasmInput) {
+ m_keyDownCallbackForInputContext =
+ std::make_unique<qstdweb::EventCallback>(wasmInput->m_inputElement,
+ "keydown",
+ keyCallbackForInputContext);
+ m_keyUpCallbackForInputContext =
+ std::make_unique<qstdweb::EventCallback>(wasmInput->m_inputElement,
+ "keyup",
+ keyCallbackForInputContext);
}
m_keyDownCallback =
- std::make_unique<qstdweb::EventCallback>(keyFocusWindow, "keydown", keyCallback);
- m_keyUpCallback = std::make_unique<qstdweb::EventCallback>(keyFocusWindow, "keyup", keyCallback);
+ std::make_unique<qstdweb::EventCallback>(m_qtWindow, "keydown", keyCallback);
+ m_keyUpCallback =std::make_unique<qstdweb::EventCallback>(m_qtWindow, "keyup", keyCallback);
+
setParent(parent());
}
@@ -356,8 +415,6 @@ void QWasmWindow::raise()
{
bringToTop();
invalidate();
- if (QWasmIntegration::get()->inputContext())
- m_canvas.call<void>("focus");
}
void QWasmWindow::lower()
@@ -526,6 +583,29 @@ bool QWasmWindow::processKey(const KeyEvent &event)
: result;
}
+bool QWasmWindow::processKeyForInputContext(const KeyEvent &event)
+{
+ qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO;
+ Q_ASSERT(event.type == EventType::KeyDown || event.type == EventType::KeyUp);
+
+ QKeySequence keySeq(event.modifiers | event.key);
+
+ if (keySeq == QKeySequence::Paste) {
+ // Process it in pasteCallback and inputCallback
+ return false;
+ }
+
+ const auto result = QWindowSystemInterface::handleKeyEvent(
+ 0, event.type == EventType::KeyDown ? QEvent::KeyPress : QEvent::KeyRelease, event.key,
+ event.modifiers, event.text);
+
+ // Copy/Cut callback required to copy qtClipboard to system clipboard
+ if (keySeq == QKeySequence::Copy || keySeq == QKeySequence::Cut)
+ return false;
+
+ return result;
+}
+
bool QWasmWindow::processPointer(const PointerEvent &event)
{
if (event.pointerType != PointerType::Mouse && event.pointerType != PointerType::Pen)