summaryrefslogtreecommitdiffstats
path: root/src/widgets/accessible/complexwidgets.cpp
diff options
context:
space:
mode:
authorMichael Weghorn <m.weghorn@posteo.de>2023-07-19 07:52:33 +0200
committerMichael Weghorn <m.weghorn@posteo.de>2023-11-16 14:34:17 +0100
commit3d58715e6f5b3251c563a9a4e1156517f48a96fe (patch)
treee32cce9eee6b1b4cf2d5680fd825685287c1ae0c /src/widgets/accessible/complexwidgets.cpp
parentb0bcf475694114bf503167bd11f14647880cd6b6 (diff)
a11y: Implement QAccessibleSelectionInterface for QAccessibleTabBar
So far, there was custom handling for exposing the selection of tab bars on Windows via UIA, s. QWindowsUiaSelectionProvider. Implement QAccessibleSelectionInterface for QAccessibleTabBar, so selection is exposed via the platform a11y bridge on all platforms. (This makes the custom handling for tab bars in QWindowsUiaSelectionProvider obsolete for qtbase's own classes, but there are 4 more uses of the QAccessible::PageTabList role in qtdeclarative that might need a closer look before dropping the custom handling from QWindowsUiaSelectionProvider.) For consistency, also set the selectable/selected state for the tab buttons (that are the selectable children of the tab bar). Sample use via AT-SPI on Linux using Accerciser to interact on the a11y level (check the current selection, then select the second tab): 1) run the qtabbar example (tests/manual/qtabbar) 2) start Accerciser 3) select the tab bar in Accerciser's tree view of the a11y hierarchy 4) query for currently selected item, switch selection from "Tab 0" to "Tab 1" by using the following commands in Accerciser's IPython console: In [10]: sel = acc.querySelection() In [11]: sel.nSelectedChildren Out[11]: 1 In [12]: sel.getSelectedChild(0) Out[12]: <Atspi.Accessible object at 0x7fe01ce8a240 (AtspiAccessible at 0x43928c0)> In [13]: sel.getSelectedChild(0).name Out[13]: 'Tab 0' In [14]: sel.selectChild(1) Out[14]: True In [15]: sel.getSelectedChild(0).name Out[15]: 'Tab 1' Equivalent on Windows using NVDA's Python console: 1) start NVDA 2) run the qtabbar example (tests/manual/qtabbar) 3) click on the first tab ("Tab 0") in the tab bar 4) press Numpad_insert+control+z to start the NVDA Python console and capture snapshot variables 5) query and use the interfaces using NVDA's Python console: >>> import UIAHandler >>> tabbar = focus.parent >>> selectionpattern2 = tabbar.UIAElement.GetCurrentPattern(10034).QueryInterface(UIAHandler.IUIAutomationSelectionPattern2) >>> selectionpattern2.CurrentFirstSelectedItem.CurrentName 'Tab 0' >>> selectionpattern2.CurrentLastSelectedItem.CurrentName 'Tab 0' >>> selectionpattern2.CurrentItemCount 1 >>> selectionitempattern = tabbar.children[1].UIAElement.GetCurrentPattern(10010).QueryInterface(UIAHandler.IUIAutomationSelectionItemPattern) >>> selectionitempattern.Select() 0 >>> selectionpattern2.CurrentFirstSelectedItem.CurrentName 'Tab 1' Fixes: QTBUG-104602 Change-Id: I49b05bb84852c86a2b8669d7843fe173caf28e18 Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Diffstat (limited to 'src/widgets/accessible/complexwidgets.cpp')
-rw-r--r--src/widgets/accessible/complexwidgets.cpp64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/widgets/accessible/complexwidgets.cpp b/src/widgets/accessible/complexwidgets.cpp
index d9f5a5ae81..77bf8504fa 100644
--- a/src/widgets/accessible/complexwidgets.cpp
+++ b/src/widgets/accessible/complexwidgets.cpp
@@ -78,7 +78,9 @@ public:
}
QAccessible::State s = parent()->state();
+ s.selectable = true;
s.focused = (m_index == m_parent->currentIndex());
+ s.selected = s.focused;
return s;
}
QRect rect() const override {
@@ -181,6 +183,14 @@ QAccessibleTabBar::~QAccessibleTabBar()
QAccessible::deleteAccessibleInterface(id);
}
+void *QAccessibleTabBar::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::SelectionInterface) {
+ return static_cast<QAccessibleSelectionInterface*>(this);
+ }
+ return QAccessibleWidget::interface_cast(t);
+}
+
/*! Returns the QTabBar. */
QTabBar *QAccessibleTabBar::tabBar() const
{
@@ -258,6 +268,60 @@ QString QAccessibleTabBar::text(QAccessible::Text t) const
return QString();
}
+int QAccessibleTabBar::selectedItemCount() const
+{
+ if (tabBar()->currentIndex() >= 0)
+ return 1;
+ return 0;
+}
+
+QList<QAccessibleInterface*> QAccessibleTabBar::selectedItems() const
+{
+ QList<QAccessibleInterface*> items;
+ QAccessibleInterface *selected = selectedItem(0);
+ if (selected)
+ items.push_back(selected);
+ return items;
+}
+
+QAccessibleInterface* QAccessibleTabBar::selectedItem(int selectionIndex) const
+{
+ const int currentIndex = tabBar()->currentIndex();
+ if (selectionIndex != 0 || currentIndex < 0)
+ return nullptr;
+ return child(currentIndex);
+}
+
+bool QAccessibleTabBar::isSelected(QAccessibleInterface *childItem) const
+{
+ return childItem && selectedItem(0) == childItem;
+}
+
+bool QAccessibleTabBar::select(QAccessibleInterface *childItem)
+{
+ const int childIndex = indexOfChild(childItem);
+ if (childIndex >= 0) {
+ tabBar()->setCurrentIndex(childIndex);
+ return true;
+ }
+ return false;
+}
+
+bool QAccessibleTabBar::unselect(QAccessibleInterface *)
+{
+ return false;
+}
+
+bool QAccessibleTabBar::selectAll()
+{
+ return false;
+}
+
+bool QAccessibleTabBar::clear()
+{
+ return false;
+}
+
#endif // QT_CONFIG(tabbar)
#if QT_CONFIG(combobox)