diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index 93b9d705c0..6ee4c9082a 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -305,15 +305,17 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow break; case UIA_SelectionPatternId: case UIA_SelectionPattern2Id: - // Lists of items. - if (accessible->role() == QAccessible::List + // Selections via QAccessibleSelectionInterface or lists of items. + if (accessible->selectionInterface() + || accessible->role() == QAccessible::List || accessible->role() == QAccessible::PageTabList) { *pRetVal = new QWindowsUiaSelectionProvider(id()); } break; case UIA_SelectionItemPatternId: - // Items within a list and radio buttons. - if ((accessible->role() == QAccessible::RadioButton) + // Parent supports selection interface or items within a list and radio buttons. + if ((accessible->parent() && accessible->parent()->selectionInterface()) + || (accessible->role() == QAccessible::RadioButton) || (accessible->role() == QAccessible::ListItem) || (accessible->role() == QAccessible::PageTab)) { *pRetVal = new QWindowsUiaSelectionItemProvider(id()); diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp index 7e829b24a7..95bc2f7570 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp @@ -36,6 +36,14 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::Select() if (!accessible) return UIA_E_ELEMENTNOTAVAILABLE; + if (QAccessibleInterface *parent = accessible->parent()) { + if (QAccessibleSelectionInterface *selectionInterface = parent->selectionInterface()) { + selectionInterface->clear(); + bool ok = selectionInterface->select(accessible); + return ok ? S_OK : S_FALSE; + } + } + QAccessibleActionInterface *actionInterface = accessible->actionInterface(); if (!actionInterface) return UIA_E_ELEMENTNOTAVAILABLE; @@ -73,6 +81,13 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::AddToSelection() if (!accessible) return UIA_E_ELEMENTNOTAVAILABLE; + if (QAccessibleInterface *parent = accessible->parent()) { + if (QAccessibleSelectionInterface *selectionInterface = parent->selectionInterface()) { + bool ok = selectionInterface->select(accessible); + return ok ? S_OK : S_FALSE; + } + } + QAccessibleActionInterface *actionInterface = accessible->actionInterface(); if (!actionInterface) return UIA_E_ELEMENTNOTAVAILABLE; @@ -98,6 +113,13 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::RemoveFromSelection( if (!accessible) return UIA_E_ELEMENTNOTAVAILABLE; + if (QAccessibleInterface *parent = accessible->parent()) { + if (QAccessibleSelectionInterface *selectionInterface = parent->selectionInterface()) { + bool ok = selectionInterface->unselect(accessible); + return ok ? S_OK : S_FALSE; + } + } + QAccessibleActionInterface *actionInterface = accessible->actionInterface(); if (!actionInterface) return UIA_E_ELEMENTNOTAVAILABLE; @@ -124,6 +146,14 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_IsSelected(BOOL if (!accessible) return UIA_E_ELEMENTNOTAVAILABLE; + if (QAccessibleInterface *parent = accessible->parent()) { + if (QAccessibleSelectionInterface *selectionInterface = parent->selectionInterface()) { + bool selected = selectionInterface->isSelected(accessible); + *pRetVal = selected ? TRUE : FALSE; + return S_OK; + } + } + if (accessible->role() == QAccessible::RadioButton) *pRetVal = accessible->state().checked; else if (accessible->role() == QAccessible::PageTab) @@ -146,12 +176,18 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_SelectionContain if (!accessible) return UIA_E_ELEMENTNOTAVAILABLE; + QAccessibleInterface *parent = accessible->parent(); + if (parent && parent->selectionInterface()) { + *pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent); + return S_OK; + } + QAccessibleActionInterface *actionInterface = accessible->actionInterface(); if (!actionInterface) return UIA_E_ELEMENTNOTAVAILABLE; // Radio buttons do not require a container. - if (QAccessibleInterface *parent = accessible->parent()) { + if (parent) { if ((accessible->role() == QAccessible::ListItem && parent->role() == QAccessible::List) || (accessible->role() == QAccessible::PageTab && parent->role() == QAccessible::PageTabList)) { *pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent); diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp index b5bf6c12e8..37148c655a 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp @@ -41,19 +41,23 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::GetSelection(SAFEARRAY * if (!accessible) return UIA_E_ELEMENTNOTAVAILABLE; - // First put selected items in a list, then build a safe array with the right size. + // First get/create list of selected items, then build a safe array with the right size. QList selectedList; - const int childCount = accessible->childCount(); - selectedList.reserve(childCount); - for (int i = 0; i < childCount; ++i) { - if (QAccessibleInterface *child = accessible->child(i)) { - if (accessible->role() == QAccessible::PageTabList) { - if (child->role() == QAccessible::PageTab && child->state().focused) { - selectedList.append(child); - } - } else { - if (child->state().selected) { - selectedList.append(child); + if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface()) { + selectedList = selectionInterface->selectedItems(); + } else { + const int childCount = accessible->childCount(); + selectedList.reserve(childCount); + for (int i = 0; i < childCount; ++i) { + if (QAccessibleInterface *child = accessible->child(i)) { + if (accessible->role() == QAccessible::PageTabList) { + if (child->role() == QAccessible::PageTab && child->state().focused) { + selectedList.append(child); + } + } else { + if (child->state().selected) { + selectedList.append(child); + } } } } @@ -104,11 +108,15 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_IsSelectionRequired( // Initially returns false if none are selected. After the first selection, it may be required. bool anySelected = false; - for (int i = 0; i < accessible->childCount(); ++i) { - if (QAccessibleInterface *child = accessible->child(i)) { - if (child->state().selected) { - anySelected = true; - break; + if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface()) { + anySelected = selectionInterface->selectedItem(0) != nullptr; + } else { + for (int i = 0; i < accessible->childCount(); ++i) { + if (QAccessibleInterface *child = accessible->child(i)) { + if (child->state().selected) { + anySelected = true; + break; + } } } } @@ -131,17 +139,23 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_FirstSelectedItem(__ return UIA_E_ELEMENTNOTAVAILABLE; QAccessibleInterface *firstSelectedChild = nullptr; - int i = 0; - while (!firstSelectedChild && i < accessible->childCount()) { - if (QAccessibleInterface *child = accessible->child(i)) { - if (accessible->role() == QAccessible::PageTabList) { - if (child->role() == QAccessible::PageTab && child->state().focused) + if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface()) { + firstSelectedChild = selectionInterface->selectedItem(0); + if (!firstSelectedChild) + return UIA_E_ELEMENTNOTAVAILABLE; + } else { + int i = 0; + while (!firstSelectedChild && i < accessible->childCount()) { + if (QAccessibleInterface *child = accessible->child(i)) { + if (accessible->role() == QAccessible::PageTabList) { + if (child->role() == QAccessible::PageTab && child->state().focused) + firstSelectedChild = child; + } else if (child->state().selected) { firstSelectedChild = child; - } else if (child->state().selected) { - firstSelectedChild = child; + } } + i++; } - i++; } if (!firstSelectedChild) @@ -169,17 +183,24 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_LastSelectedItem(__R return UIA_E_ELEMENTNOTAVAILABLE; QAccessibleInterface *lastSelectedChild = nullptr; - int i = accessible->childCount() - 1; - while (!lastSelectedChild && i >= 0) { - if (QAccessibleInterface *child = accessible->child(i)) { - if (accessible->role() == QAccessible::PageTabList) { - if (child->role() == QAccessible::PageTab && child->state().focused) + if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface()) { + const int selectedItemCount = selectionInterface->selectedItemCount(); + if (selectedItemCount <= 0) + return UIA_E_ELEMENTNOTAVAILABLE; + lastSelectedChild = selectionInterface->selectedItem(selectedItemCount - 1); + } else { + int i = accessible->childCount() - 1; + while (!lastSelectedChild && i >= 0) { + if (QAccessibleInterface *child = accessible->child(i)) { + if (accessible->role() == QAccessible::PageTabList) { + if (child->role() == QAccessible::PageTab && child->state().focused) + lastSelectedChild = child; + } else if (child->state().selected) { lastSelectedChild = child; - } else if (child->state().selected) { - lastSelectedChild = child; + } } + i--; } - i--; } if (!lastSelectedChild) @@ -212,19 +233,24 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_ItemCount(__RPC__out if (!accessible) return UIA_E_ELEMENTNOTAVAILABLE; - int selectedCount = 0; - for (int i = 0; i < accessible->childCount(); i++) { - if (QAccessibleInterface *child = accessible->child(i)) { - if (accessible->role() == QAccessible::PageTabList) { - if (child->role() == QAccessible::PageTab && child->state().focused) + + if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface()) + *pRetVal = selectionInterface->selectedItemCount(); + else { + int selectedCount = 0; + for (int i = 0; i < accessible->childCount(); i++) { + if (QAccessibleInterface *child = accessible->child(i)) { + if (accessible->role() == QAccessible::PageTabList) { + if (child->role() == QAccessible::PageTab && child->state().focused) + selectedCount++; + } else if (child->state().selected) { selectedCount++; - } else if (child->state().selected) { - selectedCount++; + } } } + *pRetVal = selectedCount; } - *pRetVal = selectedCount; return S_OK; }