diff options
Diffstat (limited to 'src/plugins/platforms/wasm/qwasmaccessibility.cpp')
-rw-r--r-- | src/plugins/platforms/wasm/qwasmaccessibility.cpp | 109 |
1 files changed, 81 insertions, 28 deletions
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.cpp b/src/plugins/platforms/wasm/qwasmaccessibility.cpp index 523f94578b..2e430176be 100644 --- a/src/plugins/platforms/wasm/qwasmaccessibility.cpp +++ b/src/plugins/platforms/wasm/qwasmaccessibility.cpp @@ -5,10 +5,12 @@ #include "qwasmscreen.h" #include "qwasmwindow.h" #include "qwasmintegration.h" -#include <QtGui/private/qaccessiblebridgeutils_p.h> - #include <QtGui/qwindow.h> +#if QT_CONFIG(accessibility) + +#include <QtGui/private/qaccessiblebridgeutils_p.h> + Q_LOGGING_CATEGORY(lcQpaAccessibility, "qt.qpa.accessibility") // Qt WebAssembly a11y backend @@ -21,13 +23,6 @@ Q_LOGGING_CATEGORY(lcQpaAccessibility, "qt.qpa.accessibility") // events. In addition or alternatively, we could also walk the accessibility tree // from setRootObject(). -namespace { -QWasmWindow *asWasmWindow(QWindow *window) -{ - return static_cast<QWasmWindow*>(window->handle()); -} -} // namespace - QWasmAccessibility::QWasmAccessibility() { @@ -65,12 +60,9 @@ void QWasmAccessibility::addAccessibilityEnableButtonImpl(QWindow *window) emscripten::val document = getDocument(container); emscripten::val button = document.call<emscripten::val>("createElement", std::string("button")); button.set("innerText", std::string("Enable Screen Reader")); + button["classList"].call<void>("add", emscripten::val("hidden-visually-read-by-screen-reader")); container.call<void>("appendChild", button); - emscripten::val style = button["style"]; - style.set("width", "100%"); - style.set("height", "100%"); - auto enableContext = std::make_tuple(button, std::make_unique<qstdweb::EventCallback> (button, std::string("click"), [this](emscripten::val) { enableAccessibility(); })); m_enableButtons.insert(std::make_pair(window, std::move(enableContext))); @@ -108,7 +100,8 @@ void QWasmAccessibility::enableAccessibility() emscripten::val QWasmAccessibility::getContainer(QWindow *window) { - return window ? asWasmWindow(window)->a11yContainer() : emscripten::val::undefined(); + return window ? static_cast<QWasmWindow *>(window->handle())->a11yContainer() + : emscripten::val::undefined(); } emscripten::val QWasmAccessibility::getContainer(QAccessibleInterface *iface) @@ -247,12 +240,21 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac case QAccessible::Dialog: { element = document.call<emscripten::val>("createElement", std::string("dialog")); }break; - case QAccessible::ToolBar: - case QAccessible::ButtonMenu: { + case QAccessible::ToolBar:{ element = document.call<emscripten::val>("createElement", std::string("div")); QString text = iface->text(QAccessible::Name); - element.call<void>("setAttribute", std::string("role"), std::string("widget")); + element.call<void>("setAttribute", std::string("role"), std::string("toolbar")); + element.call<void>("setAttribute", std::string("title"), text.toStdString()); + element.call<void>("addEventListener", emscripten::val("click"), + emscripten::val::module_property("qtEventReceived"), true); + }break; + case QAccessible::MenuItem: + case QAccessible::ButtonMenu: { + element = document.call<emscripten::val>("createElement", std::string("button")); + QString text = iface->text(QAccessible::Name); + + element.call<void>("setAttribute", std::string("role"), std::string("menuitem")); element.call<void>("setAttribute", std::string("title"), text.toStdString()); element.call<void>("addEventListener", emscripten::val("click"), emscripten::val::module_property("qtEventReceived"), true); @@ -261,12 +263,14 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac case QAccessible::PopupMenu: { element = document.call<emscripten::val>("createElement",std::string("div")); QString text = iface->text(QAccessible::Name); - element.call<void>("setAttribute", std::string("role"), std::string("widget")); + element.call<void>("setAttribute", std::string("role"), std::string("menubar")); element.call<void>("setAttribute", std::string("title"), text.toStdString()); for (int i = 0; i < iface->childCount(); ++i) { - ensureHtmlElement(iface->child(i)); - setHtmlElementTextName(iface->child(i)); - setHtmlElementGeometry(iface->child(i)); + emscripten::val childElement = emscripten::val::undefined(); + childElement= ensureHtmlElement(iface->child(i)); + childElement.call<void>("setAttribute", std::string("aria-owns"), text.toStdString()); + setHtmlElementTextName(iface->child(i)); + setHtmlElementGeometry(iface->child(i)); } }break; case QAccessible::EditableText: { @@ -280,6 +284,10 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac element = document.call<emscripten::val>("createElement", std::string("div")); } + QString id = QAccessibleBridgeUtils::accessibleId(iface); + if (iface->role() != QAccessible::PageTabList) + element.call<void>("setAttribute", std::string("id"), id.toStdString()); + return element; }(); @@ -370,12 +378,21 @@ void QWasmAccessibility::setHtmlElementTextNameLE(QAccessibleInterface *iface) { element.set("innerHTML", value.toStdString()); } +void QWasmAccessibility::setHtmlElementDescription(QAccessibleInterface *iface) { + emscripten::val element = ensureHtmlElement(iface); + QString desc = iface->text(QAccessible::Description); + element.call<void>("setAttribute", std::string("aria-description"), desc.toStdString()); +} + void QWasmAccessibility::handleStaticTextUpdate(QAccessibleEvent *event) { switch (event->type()) { case QAccessible::NameChanged: { setHtmlElementTextName(event->accessibleInterface()); } break; + case QAccessible::DescriptionChanged: { + setHtmlElementDescription(event->accessibleInterface()); + } break; default: qCDebug(lcQpaAccessibility) << "TODO: implement handleStaticTextUpdate for event" << event->type(); break; @@ -394,7 +411,9 @@ void QWasmAccessibility::handleLineEditUpdate(QAccessibleEvent *event) { case QAccessible::TextCaretMoved: { setHtmlElementTextNameLE(event->accessibleInterface()); } break; - + case QAccessible::DescriptionChanged: { + setHtmlElementDescription(event->accessibleInterface()); + } break; default: qCDebug(lcQpaAccessibility) << "TODO: implement handleLineEditUpdate for event" << event->type(); break; @@ -405,13 +424,11 @@ void QWasmAccessibility::handleEventFromHtmlElement(const emscripten::val event) { QAccessibleInterface *iface = m_elements.key(event["target"]); - if (iface == nullptr) { return; } else { QString eventType = QString::fromStdString(event["type"].as<std::string>()); const auto& actionNames = QAccessibleBridgeUtils::effectiveActionNames(iface); - if (actionNames.contains(QAccessibleActionInterface::pressAction())) { iface->actionInterface()->doAction(QAccessibleActionInterface::pressAction()); @@ -429,8 +446,11 @@ void QWasmAccessibility::handleEventFromHtmlElement(const emscripten::val event) } else if (eventType == "input") { - if (iface->editableTextInterface()) { - std::string insertText = event["target"]["value"].as<std::string>(); + // as EditableTextInterface is not implemented in qml accessibility + // so we need to check the role for text to update in the textbox during accessibility + + if (iface->editableTextInterface() || iface->role() == QAccessible::EditableText) { + std::string insertText = event["target"]["value"].as<std::string>(); iface->setText(QAccessible::Value, QString::fromStdString(insertText)); } } @@ -455,6 +475,9 @@ void QWasmAccessibility::handleCheckBoxUpdate(QAccessibleEvent *event) bool checkedString = accessible->state().checked ? true : false; element.call<void>("setAttribute", std::string("checked"), checkedString); } break; + case QAccessible::DescriptionChanged: { + setHtmlElementDescription(event->accessibleInterface()); + } break; default: qCDebug(lcQpaAccessibility) << "TODO: implement handleCheckBoxUpdate for event" << event->type(); break; @@ -471,6 +494,9 @@ void QWasmAccessibility::handleToolUpdate(QAccessibleEvent *event) emscripten::val element = ensureHtmlElement(iface); element.call<void>("setAttribute", std::string("title"), text.toStdString()); } break; + case QAccessible::DescriptionChanged: { + setHtmlElementDescription(event->accessibleInterface()); + } break; default: qCDebug(lcQpaAccessibility) << "TODO: implement handleToolUpdate for event" << event->type(); break; @@ -482,6 +508,7 @@ void QWasmAccessibility::handleMenuUpdate(QAccessibleEvent *event) QString text = iface->text(QAccessible::Name); QString desc = iface->text(QAccessible::Description); switch (event->type()) { + case QAccessible::Focus: case QAccessible::NameChanged: case QAccessible::MenuStart ://"TODO: To implement later case QAccessible::PopupMenuStart://"TODO: To implement later @@ -489,6 +516,9 @@ void QWasmAccessibility::handleMenuUpdate(QAccessibleEvent *event) emscripten::val element = ensureHtmlElement(iface); element.call<void>("setAttribute", std::string("title"), text.toStdString()); } break; + case QAccessible::DescriptionChanged: { + setHtmlElementDescription(event->accessibleInterface()); + } break; default: qCDebug(lcQpaAccessibility) << "TODO: implement handleMenuUpdate for event" << event->type(); break; @@ -503,7 +533,9 @@ void QWasmAccessibility::handleDialogUpdate(QAccessibleEvent *event) { case QAccessible::StateChanged: { setHtmlElementTextName(event->accessibleInterface()); } break; - + case QAccessible::DescriptionChanged: { + setHtmlElementDescription(event->accessibleInterface()); + } break; default: qCDebug(lcQpaAccessibility) << "TODO: implement handleLineEditUpdate for event" << event->type(); break; @@ -521,6 +553,7 @@ void QWasmAccessibility::populateAccessibilityTree(QAccessibleInterface *iface) setHtmlElementVisibility(iface, visible); setHtmlElementGeometry(iface); setHtmlElementTextName(iface); + setHtmlElementDescription(iface); for (int i = 0; i < iface->childCount(); ++i) populateAccessibilityTree(iface->child(i)); @@ -539,6 +572,9 @@ void QWasmAccessibility::handleRadioButtonUpdate(QAccessibleEvent *event) std::string checkedString = accessible->state().checked ? "true" : "false"; element.call<void>("setAttribute", std::string("checked"), checkedString); } break; + case QAccessible::DescriptionChanged: { + setHtmlElementDescription(event->accessibleInterface()); + } break; default: qDebug() << "TODO: implement handleRadioButtonUpdate for event" << event->type(); break; @@ -558,6 +594,9 @@ void QWasmAccessibility::handleSpinBoxUpdate(QAccessibleEvent *event) std::string valueString = accessible->valueInterface()->currentValue().toString().toStdString(); element.call<void>("setAttribute", std::string("value"), valueString); } break; + case QAccessible::DescriptionChanged: { + setHtmlElementDescription(event->accessibleInterface()); + } break; default: qDebug() << "TODO: implement handleSpinBoxUpdate for event" << event->type(); break; @@ -577,6 +616,9 @@ void QWasmAccessibility::handleSliderUpdate(QAccessibleEvent *event) std::string valueString = accessible->valueInterface()->currentValue().toString().toStdString(); element.call<void>("setAttribute", std::string("value"), valueString); } break; + case QAccessible::DescriptionChanged: { + setHtmlElementDescription(event->accessibleInterface()); + } break; default: qDebug() << "TODO: implement handleSliderUpdate for event" << event->type(); break; @@ -596,6 +638,9 @@ void QWasmAccessibility::handleScrollBarUpdate(QAccessibleEvent *event) std::string valueString = accessible->valueInterface()->currentValue().toString().toStdString(); element.call<void>("setAttribute", std::string("aria-valuenow"), valueString); } break; + case QAccessible::DescriptionChanged: { + setHtmlElementDescription(event->accessibleInterface()); + } break; default: qDebug() << "TODO: implement handleSliderUpdate for event" << event->type(); break; @@ -612,6 +657,9 @@ void QWasmAccessibility::handlePageTabUpdate(QAccessibleEvent *event) case QAccessible::Focus: { setHtmlElementTextName(event->accessibleInterface()); } break; + case QAccessible::DescriptionChanged: { + setHtmlElementDescription(event->accessibleInterface()); + } break; default: qDebug() << "TODO: implement handlePageTabUpdate for event" << event->type(); break; @@ -627,6 +675,9 @@ void QWasmAccessibility::handlePageTabListUpdate(QAccessibleEvent *event) case QAccessible::Focus: { setHtmlElementTextName(event->accessibleInterface()); } break; + case QAccessible::DescriptionChanged: { + setHtmlElementDescription(event->accessibleInterface()); + } break; default: qDebug() << "TODO: implement handlePageTabUpdate for event" << event->type(); break; @@ -648,12 +699,12 @@ void QWasmAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event) // https://doc.qt.io/qt-5/qaccessible.html#Event-enum switch (event->type()) { case QAccessible::ObjectShow: - setHtmlElementVisibility(iface, true); // Sync up properties on show; setHtmlElementGeometry(iface); setHtmlElementTextName(iface); + setHtmlElementDescription(iface); return; break; @@ -738,3 +789,5 @@ void QWasmAccessibility::onHtmlEventReceived(emscripten::val event) EMSCRIPTEN_BINDINGS(qtButtonEvent) { function("qtEventReceived", &QWasmAccessibility::onHtmlEventReceived); } + +#endif // QT_CONFIG(accessibility) |