From d71f9d8c05d70053f2ce46dbb2203309addc0f93 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 19 Jun 2014 18:49:59 +0200 Subject: Accessibility: Top level widgets should only be in the hierarchy once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Linux for example Orca gets confused when showing a dialog that is a child of another widget since it would show up twice in the hierarchy. Task-number: QTBUG-39444 Change-Id: I84773ecc3d6774a652dbeb29ad201779f5b3191c Reviewed-by: Jan Arve Sæther --- src/widgets/accessible/qaccessiblewidget.cpp | 14 ++--- src/widgets/accessible/qaccessiblewidgets.cpp | 12 ++--- src/widgets/accessible/simplewidgets.cpp | 2 +- .../other/qaccessibility/tst_qaccessibility.cpp | 61 ++++++++++++++++++++++ 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/src/widgets/accessible/qaccessiblewidget.cpp b/src/widgets/accessible/qaccessiblewidget.cpp index 73425b9acd..48f99f4d35 100644 --- a/src/widgets/accessible/qaccessiblewidget.cpp +++ b/src/widgets/accessible/qaccessiblewidget.cpp @@ -240,10 +240,10 @@ QWidget *QAccessibleWidget::widget() const */ QObject *QAccessibleWidget::parentObject() const { - QObject *parent = object()->parent(); - if (!parent) - parent = qApp; - return parent; + QWidget *w = widget(); + if (!w || w->isWindow() || !w->parentWidget()) + return qApp; + return w->parent(); } /*! \reimp */ @@ -353,11 +353,7 @@ QAccessibleWidget::relations(QAccessible::Relation match /*= QAccessible::AllRel /*! \reimp */ QAccessibleInterface *QAccessibleWidget::parent() const { - Q_ASSERT(widget()); - QObject *parentWidget= widget()->parentWidget(); - if (!parentWidget) - parentWidget = qApp; - return QAccessible::queryAccessibleInterface(parentWidget); + return QAccessible::queryAccessibleInterface(parentObject()); } /*! \reimp */ diff --git a/src/widgets/accessible/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp index da57d4657d..cc6310d591 100644 --- a/src/widgets/accessible/qaccessiblewidgets.cpp +++ b/src/widgets/accessible/qaccessiblewidgets.cpp @@ -74,7 +74,7 @@ QT_BEGIN_NAMESPACE QString qt_accStripAmp(const QString &text); -QList childWidgets(const QWidget *widget, bool includeTopLevel) +QList childWidgets(const QWidget *widget) { if (widget == 0) return QList(); @@ -85,7 +85,7 @@ QList childWidgets(const QWidget *widget, bool includeTopLevel) if (!w) continue; QString objectName = w->objectName(); - if ((includeTopLevel || !w->isWindow()) + if (!w->isWindow() && !qobject_cast(w) && !qobject_cast(w) && objectName != QLatin1String("qt_rubberband") @@ -970,7 +970,7 @@ QAccessibleMainWindow::QAccessibleMainWindow(QWidget *widget) QAccessibleInterface *QAccessibleMainWindow::child(int index) const { - QList kids = childWidgets(mainWindow(), true); + QList kids = childWidgets(mainWindow()); if (index >= 0 && index < kids.count()) { return QAccessible::queryAccessibleInterface(kids.at(index)); } @@ -979,13 +979,13 @@ QAccessibleInterface *QAccessibleMainWindow::child(int index) const int QAccessibleMainWindow::childCount() const { - QList kids = childWidgets(mainWindow(), true); + QList kids = childWidgets(mainWindow()); return kids.count(); } int QAccessibleMainWindow::indexOfChild(const QAccessibleInterface *iface) const { - QList kids = childWidgets(mainWindow(), true); + QList kids = childWidgets(mainWindow()); return kids.indexOf(static_cast(iface->object())); } @@ -998,7 +998,7 @@ QAccessibleInterface *QAccessibleMainWindow::childAt(int x, int y) const if (!QRect(gp.x(), gp.y(), w->width(), w->height()).contains(x, y)) return 0; - QWidgetList kids = childWidgets(mainWindow(), true); + QWidgetList kids = childWidgets(mainWindow()); QPoint rp = mainWindow()->mapFromGlobal(QPoint(x, y)); for (int i = 0; i < kids.size(); ++i) { QWidget *child = kids.at(i); diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp index 6160b37a0f..88d3981391 100644 --- a/src/widgets/accessible/simplewidgets.cpp +++ b/src/widgets/accessible/simplewidgets.cpp @@ -69,7 +69,7 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_ACCESSIBILITY -extern QList childWidgets(const QWidget *widget, bool includeTopLevel = false); +extern QList childWidgets(const QWidget *widget); QString qt_accStripAmp(const QString &text); QString qt_accHotKey(const QString &text); diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 6068391ce1..c9df497b07 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -251,6 +251,7 @@ private slots: void applicationTest(); void mainWindowTest(); + void subWindowTest(); void buttonTest(); void scrollBarTest(); void tabTest(); @@ -1003,6 +1004,66 @@ void tst_QAccessibility::mainWindowTest() } } +// Dialogs and other sub-windows must appear in the +// accessibility hierarchy exactly once as top level objects +void tst_QAccessibility::subWindowTest() +{ + { + QWidget mainWidget; + mainWidget.setGeometry(100, 100, 100, 100); + mainWidget.show(); + QLabel label(QStringLiteral("Window Contents"), &mainWidget); + mainWidget.setLayout(new QHBoxLayout()); + mainWidget.layout()->addWidget(&label); + + QDialog d(&mainWidget); + d.show(); + + QAccessibleInterface *app = QAccessible::queryAccessibleInterface(qApp); + QVERIFY(app); + QCOMPARE(app->childCount(), 2); + + QAccessibleInterface *windowIface = QAccessible::queryAccessibleInterface(&mainWidget); + QVERIFY(windowIface); + QCOMPARE(windowIface->childCount(), 1); + QCOMPARE(app->child(0), windowIface); + QCOMPARE(windowIface->parent(), app); + + QAccessibleInterface *dialogIface = QAccessible::queryAccessibleInterface(&d); + QVERIFY(dialogIface); + QCOMPARE(app->child(1), dialogIface); + QCOMPARE(dialogIface->parent(), app); + QCOMPARE(dialogIface->parent(), app); + } + + { + QMainWindow mainWindow; + mainWindow.setGeometry(100, 100, 100, 100); + mainWindow.show(); + QLabel label(QStringLiteral("Window Contents"), &mainWindow); + mainWindow.setCentralWidget(&label); + + QDialog d(&mainWindow); + d.show(); + + QAccessibleInterface *app = QAccessible::queryAccessibleInterface(qApp); + QVERIFY(app); + QCOMPARE(app->childCount(), 2); + + QAccessibleInterface *windowIface = QAccessible::queryAccessibleInterface(&mainWindow); + QVERIFY(windowIface); + QCOMPARE(windowIface->childCount(), 1); + QCOMPARE(app->child(0), windowIface); + + QAccessibleInterface *dialogIface = QAccessible::queryAccessibleInterface(&d); + QVERIFY(dialogIface); + QCOMPARE(app->child(1), dialogIface); + QCOMPARE(dialogIface->parent(), app); + QCOMPARE(windowIface->parent(), app); + } + QTestAccessibility::clearEvents(); +} + class CounterButton : public QPushButton { Q_OBJECT public: -- cgit v1.2.3