From 549fad2daeeccac53b88b4777dcc9effbc2110e5 Mon Sep 17 00:00:00 2001 From: Felix Ernst Date: Mon, 17 Jul 2023 17:13:51 +0300 Subject: Fix accessibility ancestor tree Before this commit, KItemListViewAccessible would always return nullptr as its parent. This meant that accessibility software would have to guess to which window/hierarchy the KItemListView belongs to. Guessing shouldn't be necessary here. This commit makes sure that the KItemListView always returns a sensible parent in the accessible hierarchy. It does so by explicitly setting the accessible parent for every KItemListView after construction in the DolphinView contructor. Since KItemListView now always knows about its accessible parent, the accessibleInterfaceFactory can always ask the KItemListView for that information when constructing the QAccessibleInterfaces. Fixes https://invent.kde.org/system/dolphin/-/issues/47. --- src/tests/kitemlistcontrollerexpandtest.cpp | 3 +++ src/tests/kitemlistcontrollertest.cpp | 3 +++ 2 files changed, 6 insertions(+) (limited to 'src/tests') diff --git a/src/tests/kitemlistcontrollerexpandtest.cpp b/src/tests/kitemlistcontrollerexpandtest.cpp index 368ec67ce..05708f4d2 100644 --- a/src/tests/kitemlistcontrollerexpandtest.cpp +++ b/src/tests/kitemlistcontrollerexpandtest.cpp @@ -48,6 +48,9 @@ void KItemListControllerExpandTest::initTestCase() m_view = new KFileItemListView(); m_controller = new KItemListController(m_model, m_view, this); m_container = new KItemListContainer(m_controller); +#ifndef QT_NO_ACCESSIBILITY + m_view->setAccessibleParentsObject(m_container); +#endif m_controller = m_container->controller(); m_controller->setSelectionBehavior(KItemListController::MultiSelection); m_selectionManager = m_controller->selectionManager(); diff --git a/src/tests/kitemlistcontrollertest.cpp b/src/tests/kitemlistcontrollertest.cpp index d1a9cfc7c..9d345fdd9 100644 --- a/src/tests/kitemlistcontrollertest.cpp +++ b/src/tests/kitemlistcontrollertest.cpp @@ -109,6 +109,9 @@ void KItemListControllerTest::initTestCase() m_view = new KFileItemListView(); m_controller = new KItemListController(m_model, m_view, this); m_container = new KItemListContainer(m_controller); +#ifndef QT_NO_ACCESSIBILITY + m_view->setAccessibleParentsObject(m_container); +#endif m_controller = m_container->controller(); m_controller->setSelectionBehavior(KItemListController::MultiSelection); m_selectionManager = m_controller->selectionManager(); -- cgit v1.3 From b58fead9beaf3165146d3e536b6b14ae1cc9514d Mon Sep 17 00:00:00 2001 From: Felix Ernst Date: Fri, 8 Sep 2023 17:10:29 +0200 Subject: Add test for accessibility ancestor tree This is to make sure that all items that can be tabbed to and their accessible children have the main window somewhere in their ancestry/ancestor tree. --- src/tests/dolphinmainwindowtest.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'src/tests') diff --git a/src/tests/dolphinmainwindowtest.cpp b/src/tests/dolphinmainwindowtest.cpp index 009008002..e6c355a87 100644 --- a/src/tests/dolphinmainwindowtest.cpp +++ b/src/tests/dolphinmainwindowtest.cpp @@ -14,11 +14,14 @@ #include +#include #include #include #include #include +#include + class DolphinMainWindowTest : public QObject { Q_OBJECT @@ -39,6 +42,7 @@ private Q_SLOTS: void testPlacesPanelWidthResistance(); void testGoActions(); void testOpenFiles(); + void testAccessibilityAncestorTree(); void cleanupTestCase(); private: @@ -524,6 +528,39 @@ void DolphinMainWindowTest::testOpenFiles() QTRY_COMPARE(m_mainWindow->m_activeViewContainer->view()->selectedItems().count(), 1); } +void DolphinMainWindowTest::testAccessibilityAncestorTree() +{ + m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false); + m_mainWindow->show(); + QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); + QVERIFY(m_mainWindow->isVisible()); + + std::set testedObjects; // Makes sure we stop testing if we arrive at an item that was already tested. + QAccessibleInterface *accessibleInterfaceOfMainWindow = QAccessible::queryAccessibleInterface(m_mainWindow.get()); + Q_CHECK_PTR(accessibleInterfaceOfMainWindow); + + // We will do accessibility checks for every object that gets focus. Focus will be changed using the Tab key. + while (qApp->focusObject() && !testedObjects.count(qApp->focusObject())) { + const auto currentlyFocusedObject = qApp->focusObject(); + QAccessibleInterface *accessibleInterface = QAccessible::queryAccessibleInterface(currentlyFocusedObject); + + // The accessibleInterfaces of focused objects might themselves have children. + // We go down that hierarchy as far as possible and then test the ancestor tree from there. + while (accessibleInterface->childCount() > 0) { + accessibleInterface = accessibleInterface->child(0); + } + while (accessibleInterface != accessibleInterfaceOfMainWindow) { + QVERIFY2(accessibleInterface, + qPrintable(QString("%1's accessibleInterface or one of its accessible children doesn't have the main window as an ancestor.") + .arg(currentlyFocusedObject->metaObject()->className()))); + accessibleInterface = accessibleInterface->parent(); + } + + testedObjects.insert(currentlyFocusedObject); // Add it to testedObjects so we won't test it again later. + QTest::keyClick(m_mainWindow.get(), Qt::Key::Key_Tab, Qt::ShiftModifier); // ShiftModifier because the Tab cycle is currently broken going forward. + } +} + void DolphinMainWindowTest::cleanupTestCase() { m_mainWindow->showNormal(); -- cgit v1.3