wasm: set focus to m_canvas instead of m_window

Setting focus and contentEditable on m_window causes
innerHTML to build up with characters.

This does not happen when using the m_canvas

The downside is that m_canvas is aria-hidden, but this
should, in principle, not be a problem since
m_canvas should not be focused when a11y is in
effect.

Later aria-hidden might be set only if a11y is in
effect.

It turns out this also fixes tabbing between textfields
and buttons bug.

This is a candidate for manual cherry-picking to
6.9 6.9.1

Task-number: QTBUG-136687
Task-number: QTBUG-136562
Change-Id: I08a9db2c39f9b0b0038c75fd06d3504b736ea031
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
Even Oscar Andersen 2025-05-12 11:59:20 +02:00
parent a003aafd86
commit f10a8dbf6c
4 changed files with 15 additions and 26 deletions

View File

@ -86,26 +86,10 @@ void QWasmClipboard::paste(val event)
QWasmIntegration::get()->getWasmClipboard()->sendClipboardData(event);
}
void QWasmClipboard::beforeInput(emscripten::val event)
{
event.call<void>("preventDefault");
event.call<void>("stopPropagation");
}
void QWasmClipboard::input(emscripten::val event)
{
event.call<void>("preventDefault");
event.call<void>("stopPropagation");
event["target"].set("innerHTML", std::string());
event["target"].set("value", std::string());
}
EMSCRIPTEN_BINDINGS(qtClipboardModule) {
function("qtClipboardCutTo", &QWasmClipboard::cut);
function("qtClipboardCopyTo", &QWasmClipboard::copy);
function("qtClipboardPasteTo", &QWasmClipboard::paste);
function("qtClipboardBeforeInput", &QWasmClipboard::beforeInput);
function("qtClipboardInput", &QWasmClipboard::input);
}
QWasmClipboard::QWasmClipboard()

View File

@ -43,8 +43,6 @@ public:
static void cut(emscripten::val event);
static void copy(emscripten::val event);
static void paste(emscripten::val event);
static void beforeInput(emscripten::val event);
static void input(emscripten::val event);
private:
void initClipboardPermissions();

View File

@ -56,7 +56,6 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport,
m_document(dom::document()),
m_decoratedWindow(m_document.call<emscripten::val>("createElement", emscripten::val("div"))),
m_window(m_document.call<emscripten::val>("createElement", emscripten::val("div"))),
m_windowInput(m_document.call<emscripten::val>("createElement", emscripten::val("div"))),
m_a11yContainer(m_document.call<emscripten::val>("createElement", emscripten::val("div"))),
m_canvas(m_document.call<emscripten::val>("createElement", emscripten::val("canvas")))
{
@ -71,17 +70,26 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport,
m_window.set("className", "qt-window");
m_decoratedWindow.call<void>("appendChild", m_window);
m_window.call<void>("appendChild", m_windowInput);
m_canvas["classList"].call<void>("add", emscripten::val("qt-window-canvas"));
// Set contentEditable for two reasons;
// 1) so that the window gets clipboard events,
// 2) For applications who will handle keyboard events, but without having inputMethodAccepted()
//
// Set inputMode to none to avoid keyboard popping up on push buttons
// This is a tradeoff, we are not able to separate between a push button and
// a widget that reads keyboard events.
m_canvas.call<void>("setAttribute", std::string("inputmode"), std::string("none"));
m_canvas.call<void>("setAttribute", std::string("contenteditable"), std::string("true"));
m_canvas["style"].set("outline", std::string("none"));
#if QT_CONFIG(clipboard)
QWasmClipboard::installEventHandlers(m_windowInput);
QWasmClipboard::installEventHandlers(m_canvas);
#endif
// Set inputMode to none to stop the mobile keyboard from opening
// when the user clicks on the window.
m_window.set("inputMode", std::string("none"));
m_windowInput.set("inputMode", std::string("none"));
// Hide the canvas from screen readers.
m_canvas.call<void>("setAttribute", std::string("aria-hidden"), std::string("true"));
@ -119,9 +127,9 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport,
[this](emscripten::val event) { this->handleKeyForInputContextEvent(event); });
}
m_keyDownCallback = std::make_unique<qstdweb::EventCallback>(m_window, "keydown",
m_keyDownCallback = std::make_unique<qstdweb::EventCallback>(m_canvas, "keydown",
[this](emscripten::val event) { this->handleKeyEvent(event); });
m_keyUpCallback =std::make_unique<qstdweb::EventCallback>(m_window, "keyup",
m_keyUpCallback =std::make_unique<qstdweb::EventCallback>(m_canvas, "keyup",
[this](emscripten::val event) { this->handleKeyEvent(event); });
setParent(parent());
@ -718,7 +726,7 @@ void QWasmWindow::requestActivateWindow()
void QWasmWindow::focus()
{
m_windowInput.call<void>("focus");
m_canvas.call<void>("focus");
}
bool QWasmWindow::setMouseGrabEnabled(bool grab)

View File

@ -140,7 +140,6 @@ private:
emscripten::val m_document;
emscripten::val m_decoratedWindow;
emscripten::val m_window;
emscripten::val m_windowInput;
emscripten::val m_a11yContainer;
emscripten::val m_canvas;
emscripten::val m_context2d = emscripten::val::undefined();