Windows QPA: Fix QComboBox accessibility with screen readers

Screen readers like NVDA and Narrator were not reading the contents
of a QComboBox when changing its value using the keyboard, without
expanding it, due to missing UI Automation notifications in this case.
This change should also help in other cases where updated string
values were not notified to screen readers.

Fixes: QTBUG-75066
Change-Id: Id7f488380aec5ad27fd11b3cf854d44ab1b28688
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
bb10
Andre de la Rocha 2019-04-09 17:18:49 +02:00
parent 21dcb96ddc
commit ab2c1e20fa
3 changed files with 39 additions and 2 deletions

View File

@ -113,6 +113,9 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
case QAccessible::ValueChanged:
QWindowsUiaMainProvider::notifyValueChange(static_cast<QAccessibleValueChangeEvent *>(event));
break;
case QAccessible::SelectionAdd:
QWindowsUiaMainProvider::notifySelectionChange(event);
break;
case QAccessible::TextAttributeChanged:
case QAccessible::TextColumnChanged:
case QAccessible::TextInserted:

View File

@ -146,9 +146,33 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *event)
{
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
// Notifies changes in values of controls supporting the value interface.
if (accessible->role() == QAccessible::ComboBox && accessible->childCount() > 0) {
QAccessibleInterface *listacc = accessible->child(0);
if (listacc && listacc->role() == QAccessible::List) {
int count = listacc->childCount();
for (int i = 0; i < count; ++i) {
QAccessibleInterface *item = listacc->child(i);
if (item && item->text(QAccessible::Name) == event->value()) {
if (!item->state().selected) {
if (QAccessibleActionInterface *actionInterface = item->actionInterface())
actionInterface->doAction(QAccessibleActionInterface::toggleAction());
}
break;
}
}
}
}
if (event->value().type() == QVariant::String) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
// Notifies changes in string values.
VARIANT oldVal, newVal;
clearVariant(&oldVal);
setVariantString(event->value().toString(), &newVal);
QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
}
} else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
// Notifies changes in values of controls supporting the value interface.
VARIANT oldVal, newVal;
clearVariant(&oldVal);
setVariantDouble(valueInterface->currentValue().toDouble(), &newVal);
@ -158,6 +182,15 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
}
}
void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event)
{
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_SelectionItem_ElementSelectedEventId);
}
}
}
// Notifies changes in text content and selection state of text controls.
void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
{

View File

@ -68,6 +68,7 @@ public:
static void notifyFocusChange(QAccessibleEvent *event);
static void notifyStateChange(QAccessibleStateChangeEvent *event);
static void notifyValueChange(QAccessibleValueChangeEvent *event);
static void notifySelectionChange(QAccessibleEvent *event);
static void notifyTextChange(QAccessibleEvent *event);
// IUnknown