summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSharad Sahu <sharad.sahu@crossware.io>2022-06-08 17:20:41 +0530
committerMorten Johan Sørvig <morten.sorvig@qt.io>2022-12-27 14:30:25 +0000
commit13c3fd959ed400396ee770d3e300778cf20a50a9 (patch)
treecccd065f103214450015a97148125b9801c3176d
parent42d4619967688e4f313f5508de7594f0c0c976ff (diff)
wasm: Work on wasm accessibility elements and events
Implement a11y support by adding html elements (Toolbar, Menu, DialogBox) and events of the appropriate type and/or with the appropriate ARIA attribute behind the canvas. Pick-to: 6.5 Change-Id: If9c9fbff9a451b44e57de5d8834f4a78f33f41bc Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.cpp128
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.h8
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt4
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/basica11ywidget.cpp114
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/basica11ywidget.h41
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/main.cpp24
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/tabswidget.cpp63
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/tabswidget.h34
8 files changed, 392 insertions, 24 deletions
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.cpp b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
index cb1e3f135c..552f7846ea 100644
--- a/src/plugins/platforms/wasm/qwasmaccessibility.cpp
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
@@ -140,7 +140,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
// Translate the Qt a11y elemen role into html element type + ARIA role.
// Here we can either create <div> elements with a spesific ARIA role,
// or create e.g. <button> elements which should have built-in accessibility.
- emscripten::val element = [iface, document] {
+ emscripten::val element = [this, iface, document] {
emscripten::val element = emscripten::val::undefined();
@@ -149,16 +149,44 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
case QAccessible::Button: {
element = document.call<emscripten::val>("createElement", std::string("button"));
} break;
-
case QAccessible::CheckBox: {
element = document.call<emscripten::val>("createElement", std::string("input"));
element.call<void>("setAttribute", std::string("type"), std::string("checkbox"));
} break;
-
+ case QAccessible::Dialog: {
+ element = document.call<emscripten::val>("createElement", std::string("dialog"));
+ }break;
+ case QAccessible::ToolBar:
+ case QAccessible::ButtonMenu: {
+ 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("title"), text.toStdString());
+ element.call<void>("addEventListener", emscripten::val("click"),
+ emscripten::val::module_property("qtEventReceived"), true);
+ }break;
+ case QAccessible::MenuBar:
+ 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("title"), text.toStdString());
+ for (int i = 0; i < iface->childCount(); ++i) {
+ ensureHtmlElement(iface->child(i));
+ setHtmlElementTextName(iface->child(i));
+ setHtmlElementGeometry(iface->child(i));
+ }
+ }break;
+ case QAccessible::EditableText: {
+ element = document.call<emscripten::val>("createElement", std::string("input"));
+ element.call<void>("setAttribute", std::string("type"),std::string("text"));
+ element.call<void>("addEventListener", emscripten::val("input"),
+ emscripten::val::module_property("qtEventReceived"), true);
+ } break;
default:
qCDebug(lcQpaAccessibility) << "TODO: createHtmlElement() handle" << iface->role();
element = document.call<emscripten::val>("createElement", std::string("div"));
- //element.set("AriaRole", "foo");
}
return element;
@@ -245,6 +273,34 @@ void QWasmAccessibility::handleStaticTextUpdate(QAccessibleEvent *event)
}
}
+void QWasmAccessibility::setHtmlElementTextNameLE(QAccessibleInterface *iface) {
+ emscripten::val element = ensureHtmlElement(iface);
+ QString text = iface->text(QAccessible::Name);
+ element.call<void>("setAttribute", std::string("name"), text.toStdString());
+ QString value = iface->text(QAccessible::Value);
+ element.set("innerHTML", value.toStdString());
+}
+
+void QWasmAccessibility::handleLineEditUpdate(QAccessibleEvent *event) {
+
+ switch (event->type()) {
+ case QAccessible::NameChanged: {
+ setHtmlElementTextName(event->accessibleInterface());
+ } break;
+ case QAccessible::Focus:
+ case QAccessible::TextRemoved:
+ case QAccessible::TextInserted:
+ case QAccessible::TextCaretMoved: {
+ setHtmlElementTextNameLE(event->accessibleInterface());
+ } break;
+
+ default:
+ qCDebug(lcQpaAccessibility) << "TODO: implement handleLineEditUpdate for event" << event->type();
+ break;
+ }
+}
+
+
void QWasmAccessibility::handleButtonUpdate(QAccessibleEvent *event)
{
qCDebug(lcQpaAccessibility) << "TODO: implement handleButtonUpdate for event" << event->type();
@@ -261,6 +317,55 @@ void QWasmAccessibility::handleCheckBoxUpdate(QAccessibleEvent *event)
break;
}
}
+void QWasmAccessibility::handleToolUpdate(QAccessibleEvent *event)
+{
+ QAccessibleInterface *iface = event->accessibleInterface();
+ QString text = iface->text(QAccessible::Name);
+ QString desc = iface->text(QAccessible::Description);
+ switch (event->type()) {
+ case QAccessible::NameChanged:
+ case QAccessible::StateChanged:{
+ emscripten::val element = ensureHtmlElement(iface);
+ element.call<void>("setAttribute", std::string("title"), text.toStdString());
+ } break;
+ default:
+ qCDebug(lcQpaAccessibility) << "TODO: implement handleToolUpdate for event" << event->type();
+ break;
+ }
+}
+void QWasmAccessibility::handleMenuUpdate(QAccessibleEvent *event)
+{
+ QAccessibleInterface *iface = event->accessibleInterface();
+ QString text = iface->text(QAccessible::Name);
+ QString desc = iface->text(QAccessible::Description);
+ switch (event->type()) {
+ case QAccessible::NameChanged:
+ case QAccessible::MenuStart ://"TODO: To implement later
+ case QAccessible::PopupMenuStart://"TODO: To implement later
+ case QAccessible::StateChanged:{
+ emscripten::val element = ensureHtmlElement(iface);
+ element.call<void>("setAttribute", std::string("title"), text.toStdString());
+ } break;
+ default:
+ qCDebug(lcQpaAccessibility) << "TODO: implement handleMenuUpdate for event" << event->type();
+ break;
+ }
+}
+void QWasmAccessibility::handleDialogUpdate(QAccessibleEvent *event) {
+
+ switch (event->type()) {
+ case QAccessible::NameChanged:
+ case QAccessible::Focus:
+ case QAccessible::DialogStart:
+ case QAccessible::StateChanged: {
+ setHtmlElementTextName(event->accessibleInterface());
+ } break;
+
+ default:
+ qCDebug(lcQpaAccessibility) << "TODO: implement handleLineEditUpdate for event" << event->type();
+ break;
+ }
+}
void QWasmAccessibility::populateAccessibilityTree(QAccessibleInterface *iface)
{
@@ -323,6 +428,21 @@ void QWasmAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
case QAccessible::CheckBox:
handleCheckBoxUpdate(event);
break;
+ case QAccessible::EditableText:
+ handleLineEditUpdate(event);
+ break;
+ case QAccessible::Dialog:
+ handleDialogUpdate(event);
+ break;
+ case QAccessible::MenuItem:
+ case QAccessible::MenuBar:
+ case QAccessible::PopupMenu:
+ handleMenuUpdate(event);
+ break;
+ case QAccessible::ToolBar:
+ case QAccessible::ButtonMenu:
+ handleToolUpdate(event);
+ break;
default:
qCDebug(lcQpaAccessibility) << "TODO: implement notifyAccessibilityUpdate for role" << iface->role();
};
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.h b/src/plugins/platforms/wasm/qwasmaccessibility.h
index 2c76f41c00..35f97259e8 100644
--- a/src/plugins/platforms/wasm/qwasmaccessibility.h
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.h
@@ -12,6 +12,7 @@
#include <QLoggingCategory>
#include <map>
+#include <emscripten/bind.h>
Q_DECLARE_LOGGING_CATEGORY(lcQpaAccessibility)
@@ -47,6 +48,12 @@ private:
void handleStaticTextUpdate(QAccessibleEvent *event);
void handleButtonUpdate(QAccessibleEvent *event);
void handleCheckBoxUpdate(QAccessibleEvent *event);
+ void handleDialogUpdate(QAccessibleEvent *event);
+ void handleMenuUpdate(QAccessibleEvent *event);
+ void handleToolUpdate(QAccessibleEvent *event);
+ void handleLineEditUpdate(QAccessibleEvent *event);
+ void setHtmlElementTextNameLE(QAccessibleInterface *iface);
+
void populateAccessibilityTree(QAccessibleInterface *iface);
void notifyAccessibilityUpdate(QAccessibleEvent *event) override;
@@ -54,6 +61,7 @@ private:
void initialize() override;
void cleanup() override;
+
private:
static QWasmAccessibility *s_instance;
QObject *m_rootObject = nullptr;
diff --git a/tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt b/tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt
index 2aafd831ac..11534bdf68 100644
--- a/tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt
+++ b/tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt
@@ -1,6 +1,10 @@
qt_internal_add_manual_test(a11y_basic_widgets
GUI
SOURCES
+ tabswidget.cpp
+ tabswidget.h
+ basica11ywidget.h
+ basica11ywidget.cpp
main.cpp
LIBRARIES
Qt::Core
diff --git a/tests/manual/wasm/a11y/basic_widgets/basica11ywidget.cpp b/tests/manual/wasm/a11y/basic_widgets/basica11ywidget.cpp
new file mode 100644
index 0000000000..eaf736160a
--- /dev/null
+++ b/tests/manual/wasm/a11y/basic_widgets/basica11ywidget.cpp
@@ -0,0 +1,114 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "basica11ywidget.h"
+
+BasicA11yWidget::BasicA11yWidget() :
+ m_toolBar (new QToolBar()),
+ m_layout(new QVBoxLayout),
+ m_tabWidget(new QTabWidget)
+{
+ createActions();
+ createMenus();
+ createToolBar();
+ m_lblDateTime =new QLabel("Select Chrono Menu for todays date and time.");
+ m_layout->addWidget(m_lblDateTime);
+ m_tabWidget->addTab(new GeneralTab(), ("General Widget"));
+ m_editView =new EditViewTab();
+ m_tabWidget->addTab(m_editView, ("Edit Widget"));
+ m_layout->addWidget(m_tabWidget);
+
+ m_layout->addStretch();
+
+ connect(m_editView, &EditViewTab::connectToToolBar, this,&BasicA11yWidget::connectToolBar);
+ setLayout(m_layout);
+
+}
+void BasicA11yWidget::handleButton() {
+
+ QDialog *asmSmplDlg = new QDialog(this);
+ QVBoxLayout *vlayout = new QVBoxLayout(asmSmplDlg);
+ asmSmplDlg->setWindowTitle("WebAssembly Dialog box ");
+ QLabel *label = new QLabel("Accessibility Demo sample application developed in Qt.");
+ QAbstractButton *bExit = new QPushButton("Exit");
+ vlayout->addWidget(label);
+ vlayout->addWidget(bExit);
+ asmSmplDlg->setLayout(vlayout);
+ auto p = asmSmplDlg->palette();
+ p.setColor( asmSmplDlg->backgroundRole(), Qt::gray);
+ asmSmplDlg->setPalette(p);
+ asmSmplDlg->show();
+ asmSmplDlg->connect(bExit, SIGNAL(clicked()), asmSmplDlg, SLOT(close()));
+}
+
+void BasicA11yWidget::createToolBar()
+{
+ m_copyAct = new QAction(tr("&Copy"), this);
+ m_copyAct->setShortcuts(QKeySequence::Copy);
+
+ m_pasteAct = new QAction(tr("&Paste"), this);
+ m_pasteAct->setStatusTip(tr("To paste selected text"));
+ m_pasteAct->setShortcuts(QKeySequence::Paste);
+
+ m_cutAct = new QAction(tr("C&ut"), this);
+ m_cutAct->setShortcuts(QKeySequence::Cut);
+
+ m_toolBar->addAction(m_copyAct);
+ m_toolBar->addAction(m_cutAct);
+ m_toolBar->addAction(m_pasteAct);
+ m_layout->addWidget(m_toolBar);
+
+}
+void BasicA11yWidget::connectToolBar()
+{
+ connect(m_copyAct, &QAction::triggered, m_editView->getTextEdit(), &QPlainTextEdit::copy);
+ connect(m_pasteAct, &QAction::triggered, m_editView->getTextEdit(), &QPlainTextEdit::paste);
+ connect(m_cutAct, &QAction::triggered, m_editView->getTextEdit(), &QPlainTextEdit::cut);
+}
+void BasicA11yWidget::createActions()
+{
+ m_DateAct = new QAction( tr("&Date"), this);
+ m_DateAct->setStatusTip(tr("To tell you todays date."));
+ connect(m_DateAct, &QAction::triggered, this, &BasicA11yWidget::todaysDate);
+
+ m_TimeAct = new QAction(tr("&Time"), this);
+ m_TimeAct->setStatusTip(tr("To tell you current time."));
+ connect(m_TimeAct, &QAction::triggered, this, &BasicA11yWidget::currentTime);
+
+}
+void BasicA11yWidget::createMenus()
+{
+ m_menuBar = new QMenuBar();
+
+ m_TodayMenu = m_menuBar->addMenu(tr("&Chrono"));
+ m_TodayMenu->addAction(m_DateAct);
+ m_TodayMenu->addAction(m_TimeAct);
+
+ m_aboutAct = new QAction(tr("&About"), this);
+ m_aboutAct->setStatusTip(tr("Show the application's About box"));
+ connect(m_aboutAct, &QAction::triggered, this, &BasicA11yWidget::about);
+
+ m_helpMenu = m_menuBar->addMenu(tr("&Help"));
+ m_helpMenu->addAction(m_aboutAct);
+
+ m_layout->setMenuBar(m_menuBar);
+}
+
+void BasicA11yWidget::todaysDate()
+{
+ QDateTime dt=QDateTime::currentDateTime();
+ QString str = "Today's Date:"+ dt.date().toString();
+ m_lblDateTime->setText(str);
+}
+
+void BasicA11yWidget::currentTime()
+{
+ QDateTime dt=QDateTime::currentDateTime();
+ QString str = "Current Time:"+ dt.time().toString();
+ m_lblDateTime->setText(str);
+}
+
+void BasicA11yWidget::about()
+{
+ handleButton();
+}
diff --git a/tests/manual/wasm/a11y/basic_widgets/basica11ywidget.h b/tests/manual/wasm/a11y/basic_widgets/basica11ywidget.h
new file mode 100644
index 0000000000..c8d9a4157b
--- /dev/null
+++ b/tests/manual/wasm/a11y/basic_widgets/basica11ywidget.h
@@ -0,0 +1,41 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include <QtWidgets>
+#include "tabswidget.h"
+
+class BasicA11yWidget: public QWidget
+{
+ Q_OBJECT
+private:
+ QMenu* m_helpMenu = nullptr;
+ QMenu* m_TodayMenu = nullptr;
+ QMenuBar* m_menuBar = nullptr;
+ QToolBar* m_toolBar = nullptr;
+ QLabel* m_lblDateTime = nullptr;
+ QVBoxLayout* m_layout = nullptr ;
+ QTabWidget* m_tabWidget = nullptr;
+ EditViewTab *m_editView = nullptr;
+
+ QAction* m_DateAct = nullptr;
+ QAction* m_TimeAct = nullptr;
+ QAction* m_aboutAct = nullptr;
+ QAction* m_copyAct = nullptr;
+ QAction* m_pasteAct = nullptr;
+ QAction* m_cutAct = nullptr;
+
+public slots:
+ void connectToolBar();
+public:
+ BasicA11yWidget() ;
+ void createActions();
+ void createMenus();
+ void createToolBar();
+
+ void todaysDate();
+ void currentTime();
+ void about();
+ QToolBar* getToolbar(){return m_toolBar;}
+ void handleButton();
+
+};
diff --git a/tests/manual/wasm/a11y/basic_widgets/main.cpp b/tests/manual/wasm/a11y/basic_widgets/main.cpp
index 78f142bc1e..5417195ecf 100644
--- a/tests/manual/wasm/a11y/basic_widgets/main.cpp
+++ b/tests/manual/wasm/a11y/basic_widgets/main.cpp
@@ -1,26 +1,9 @@
-// Copyright (C) 2019 The Qt Company Ltd.
+// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QApplication>
#include <QtWidgets>
-
-class BasicA11yWidget: public QWidget
-{
-public:
- BasicA11yWidget() {
-
- QVBoxLayout *layout = new QVBoxLayout();
-
- layout->addWidget(new QLabel("This is a text label"));
- layout->addWidget(new QPushButton("This is a push button"));
- layout->addWidget(new QCheckBox("This is a check box"));
-
- // TODO: Add more widgets
-
- layout->addStretch();
-
- setLayout(layout);
- }
-};
+#include "basica11ywidget.h"
int main(int argc, char **argv)
{
@@ -31,3 +14,4 @@ int main(int argc, char **argv)
return app.exec();
}
+
diff --git a/tests/manual/wasm/a11y/basic_widgets/tabswidget.cpp b/tests/manual/wasm/a11y/basic_widgets/tabswidget.cpp
new file mode 100644
index 0000000000..19bd0cf71b
--- /dev/null
+++ b/tests/manual/wasm/a11y/basic_widgets/tabswidget.cpp
@@ -0,0 +1,63 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "tabswidget.h"
+
+GeneralTab::GeneralTab(QWidget *parent)
+ : QWidget(parent)
+{
+ QVBoxLayout *layout = new QVBoxLayout();
+ layout->setSizeConstraint(QLayout::SetMaximumSize);
+
+ layout->addWidget(new QLabel("This is a text label"));
+
+ QPushButton *btn = new QPushButton("This is a push button");
+ layout->addWidget(btn);
+ connect(btn, &QPushButton::released, this, [=] () {
+ btn->setText("You clicked me");
+ });
+
+ layout->addWidget(new QCheckBox("This is a check box"));
+
+ layout->addWidget(new QRadioButton("Radio 1"));
+ layout->addWidget(new QRadioButton("Radio 2"));
+
+ QSlider *slider = new QSlider(Qt::Horizontal);
+ slider->setTickInterval(10);
+ slider->setTickPosition(QSlider::TicksAbove);
+ layout->addWidget(slider);
+
+ QSpinBox *spin = new QSpinBox();
+ spin->setValue(10);
+ spin->setSingleStep(1);
+ layout->addWidget(spin);
+ layout->addStretch();
+
+ QScrollBar *scrollBar = new QScrollBar(Qt::Horizontal);
+ scrollBar->setFocusPolicy(Qt::StrongFocus);
+ layout->addWidget(scrollBar);
+
+ setLayout(layout);
+}
+
+
+EditViewTab::EditViewTab(QWidget *parent) :
+ QWidget(parent)
+{
+ QVBoxLayout *layout = new QVBoxLayout();
+ layout->setSizeConstraint(QLayout::SetMaximumSize);
+ textEdit = new QPlainTextEdit();
+ textEdit->setPlaceholderText("Enter Text here");
+ layout->addWidget(textEdit);
+ setLayout(layout);
+
+}
+
+void EditViewTab::showEvent( QShowEvent* event ) {
+ if (!b_connected)
+ {
+ emit connectToToolBar();
+ b_connected=true;
+ }
+ QWidget::showEvent( event );
+}
diff --git a/tests/manual/wasm/a11y/basic_widgets/tabswidget.h b/tests/manual/wasm/a11y/basic_widgets/tabswidget.h
new file mode 100644
index 0000000000..0d7983cb42
--- /dev/null
+++ b/tests/manual/wasm/a11y/basic_widgets/tabswidget.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef TABDIALOG_H
+#define TABDIALOG_H
+#include <QTabWidget>
+#include <QtWidgets>
+
+class GeneralTab : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ explicit GeneralTab(QWidget *parent = nullptr);
+};
+
+class EditViewTab : public QWidget
+{
+
+ Q_OBJECT
+private:
+ bool b_connected = false;
+ QPlainTextEdit* textEdit =nullptr;
+ QToolBar* m_toolbar= nullptr;
+public:
+ void showEvent( QShowEvent* event ) ;
+ QPlainTextEdit* getTextEdit(){return textEdit;}
+ explicit EditViewTab( QWidget *parent = nullptr);
+signals:
+ void connectToToolBar();
+};
+
+#endif