diff options
author | Michael Weghorn <m.weghorn@posteo.de> | 2023-07-19 07:52:33 +0200 |
---|---|---|
committer | Michael Weghorn <m.weghorn@posteo.de> | 2023-11-16 14:34:17 +0100 |
commit | 3d58715e6f5b3251c563a9a4e1156517f48a96fe (patch) | |
tree | e32cce9eee6b1b4cf2d5680fd825685287c1ae0c /src/widgets/accessible/complexwidgets.cpp | |
parent | b0bcf475694114bf503167bd11f14647880cd6b6 (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.cpp | 64 |
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) |