wasm: set contenteditable on canvas

We don't want to make the top-level screen contenteditable,
since that interferes with accessibility. Instead, make
the canvas contenteditable and install clipboard event
handlers there.

Also move follow-up settings which counters some of the
effects contenteditable (outline: none and inputmode: none),
and move aria-hidden.

Change-Id: Ibe73d8d097acd948ba8920c781a2003db0a14f3d
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
(cherry picked from commit 2443f2be07607e44ec483278873702eb0f57ab26)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Morten Sørvig 2023-02-03 12:59:42 +01:00 committed by Qt Cherry-pick Bot
parent 192291bb08
commit 79ffb2eb33
6 changed files with 21 additions and 19 deletions

View File

@ -240,15 +240,15 @@ void QWasmClipboard::initClipboardPermissions()
})()); })());
} }
void QWasmClipboard::installEventHandlers(const emscripten::val &screenElement) void QWasmClipboard::installEventHandlers(const emscripten::val &target)
{ {
emscripten::val cContext = val::undefined(); emscripten::val cContext = val::undefined();
emscripten::val isChromium = val::global("window")["chrome"]; emscripten::val isChromium = val::global("window")["chrome"];
if (!isChromium.isUndefined()) { if (!isChromium.isUndefined()) {
cContext = val::global("document"); cContext = val::global("document");
} else { } else {
cContext = screenElement; cContext = target;
} }
// Fallback path for browsers which do not support direct clipboard access // Fallback path for browsers which do not support direct clipboard access
cContext.call<void>("addEventListener", val("cut"), cContext.call<void>("addEventListener", val("cut"),
val::module_property("qtClipboardCutTo"), true); val::module_property("qtClipboardCutTo"), true);

View File

@ -36,7 +36,7 @@ public:
ProcessKeyboardResult processKeyboard(const QWasmEventTranslator::TranslatedEvent &event, ProcessKeyboardResult processKeyboard(const QWasmEventTranslator::TranslatedEvent &event,
const QFlags<Qt::KeyboardModifier> &modifiers); const QFlags<Qt::KeyboardModifier> &modifiers);
void installEventHandlers(const emscripten::val &canvas); static void installEventHandlers(const emscripten::val &target);
bool hasClipboardApi(); bool hasClipboardApi();
private: private:

View File

@ -24,7 +24,6 @@ const char *Style = R"css(
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
outline: none;
} }
.qt-window { .qt-window {

View File

@ -278,7 +278,6 @@ void QWasmIntegration::addScreen(const emscripten::val &element)
{ {
QWasmScreen *screen = new QWasmScreen(element); QWasmScreen *screen = new QWasmScreen(element);
m_screens.append(qMakePair(element, screen)); m_screens.append(qMakePair(element, screen));
m_clipboard->installEventHandlers(element);
QWindowSystemInterface::handleScreenAdded(screen); QWindowSystemInterface::handleScreenAdded(screen);
} }

View File

@ -57,22 +57,11 @@ QWasmScreen::QWasmScreen(const emscripten::val &containerOrCanvas)
m_shadowContainer["classList"].call<void>("add", std::string("qt-screen")); m_shadowContainer["classList"].call<void>("add", std::string("qt-screen"));
// Set contenteditable so that the canvas gets clipboard events,
// then hide the resulting focus frame, and reset the cursor.
m_shadowContainer.set("contentEditable", std::string("true"));
// set inputmode to none to stop mobile keyboard opening
// when user clicks anywhere on the canvas.
m_shadowContainer.set("inputmode", std::string("none"));
// Hide the canvas from screen readers.
m_shadowContainer.call<void>("setAttribute", std::string("aria-hidden"), std::string("true"));
// Disable the default context menu; Qt applications typically // Disable the default context menu; Qt applications typically
// provide custom right-click behavior. // provide custom right-click behavior.
m_onContextMenu = std::make_unique<qstdweb::EventCallback>( m_onContextMenu = std::make_unique<qstdweb::EventCallback>(
m_shadowContainer, "contextmenu", m_shadowContainer, "contextmenu",
[](emscripten::val event) { event.call<void>("preventDefault"); }); [](emscripten::val event) { event.call<void>("preventDefault"); });
// Create "specialHTMLTargets" mapping for the canvas - the element might be unreachable based // Create "specialHTMLTargets" mapping for the canvas - the element might be unreachable based
// on its id only under some conditions, like the target being embedded in a shadow DOM or a // on its id only under some conditions, like the target being embedded in a shadow DOM or a
// subframe. // subframe.

View File

@ -20,6 +20,7 @@
#include "qwasmeventdispatcher.h" #include "qwasmeventdispatcher.h"
#include "qwasmstring.h" #include "qwasmstring.h"
#include "qwasmaccessibility.h" #include "qwasmaccessibility.h"
#include "qwasmclipboard.h"
#include <iostream> #include <iostream>
#include <emscripten/val.h> #include <emscripten/val.h>
@ -56,6 +57,20 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingSt
m_canvas["classList"].call<void>("add", emscripten::val("qt-window-content")); m_canvas["classList"].call<void>("add", emscripten::val("qt-window-content"));
// Set contenteditable so that the canvas gets clipboard events,
// then hide the resulting focus frame.
m_canvas.set("contentEditable", std::string("true"));
m_canvas["style"].set("outline", std::string("none"));
QWasmClipboard::installEventHandlers(m_canvas);
// set inputmode to none to stop mobile keyboard opening
// when user clicks anywhere on the canvas.
m_canvas.set("inputmode", std::string("none"));
// Hide the canvas from screen readers.
m_canvas.call<void>("setAttribute", std::string("aria-hidden"), std::string("true"));
m_windowContents.call<void>("appendChild", m_canvasContainer); m_windowContents.call<void>("appendChild", m_canvasContainer);
m_canvasContainer["classList"].call<void>("add", emscripten::val("qt-window-canvas-container")); m_canvasContainer["classList"].call<void>("add", emscripten::val("qt-window-canvas-container"));