Fix leak of QWindowsUiaMainProvider instances

Pair up all calls to QWindowsUiaMainProvider::providerForAccessible
with a corresponding QWindowsUiaMainProvider::Release().

This fixes memory leaks when the Narrator application is running
for applications that are recreating UI elements frequently. RAII
ComPtr is not used here because going directly to ComPtr would make
the change harder to review. Switching to ComPtr can be done in a
separate patch.

When the Narrator application is running, we may see that the memory
usage temporarily increases, but it is reclaimed later.

Fixes: QTBUG-126530
Change-Id: I1fd76da5759354633dbf040ba42a007d349264a6
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
(cherry picked from commit 0e65cbc82fbd8585a201c7feb16df410078a8cfb)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Jøger Hansegård 2024-06-24 17:15:23 +02:00 committed by Qt Cherry-pick Bot
parent a92e3cf301
commit c6d6e05aae
7 changed files with 27 additions and 13 deletions

View File

@ -48,6 +48,7 @@ bool QWindowsUiaAccessibility::handleWmGetObject(HWND hwnd, WPARAM wParam, LPARA
if (QAccessibleInterface *accessible = window->accessibleRoot()) {
QWindowsUiaMainProvider *provider = QWindowsUiaMainProvider::providerForAccessible(accessible);
*lResult = UiaReturnRawElementProvider(hwnd, wParam, lParam, provider);
provider->Release();
return true;
}
}

View File

@ -129,7 +129,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_ContainingGrid(IRawEl
return UIA_E_ELEMENTNOTAVAILABLE;
if (QAccessibleInterface *table = tableCellInterface->table()) {
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(table);
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(table); // Detach
}
return S_OK;
}

View File

@ -46,7 +46,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaGridProvider::GetItem(int row, int column,
if ((row >= 0) && (row < tableInterface->rowCount()) && (column >= 0) && (column < tableInterface->columnCount())) {
if (QAccessibleInterface *cell = tableInterface->cellAt(row, column)) {
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(cell);
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(cell); // Detach
}
}
return S_OK;

View File

@ -79,8 +79,10 @@ void QWindowsUiaMainProvider::notifyFocusChange(QAccessibleEvent *event)
if (QAccessibleInterface *child = accessible->focusChild())
accessible = child;
}
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible))
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
UiaRaiseAutomationEvent(provider, UIA_AutomationFocusChangedEventId);
provider->Release();
}
}
}
@ -98,6 +100,7 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
toggleState = accessible->state().checkStateMixed ? ToggleState_Indeterminate : ToggleState_On;
setVariantI4(toggleState, &newVal);
UiaRaiseAutomationPropertyChangedEvent(provider, UIA_ToggleToggleStatePropertyId, oldVal, newVal);
provider->Release();
}
}
}
@ -108,12 +111,15 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
if (accessible->state().active) {
UiaRaiseAutomationEvent(provider, UIA_Window_WindowOpenedEventId);
if (QAccessibleInterface *focused = accessible->focusChild()) {
if (QWindowsUiaMainProvider *focusedProvider = providerForAccessible(focused))
if (QWindowsUiaMainProvider *focusedProvider = providerForAccessible(focused)) {
UiaRaiseAutomationEvent(focusedProvider, UIA_AutomationFocusChangedEventId);
focusedProvider->Release();
}
}
} else {
UiaRaiseAutomationEvent(provider, UIA_Window_WindowClosedEventId);
}
provider->Release();
}
}
}
@ -146,6 +152,8 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
clearVariant(&oldVal);
setVariantString(event->value().toString(), &newVal);
UiaRaiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
provider->Release();
HRESULT hr = VariantClear(&newVal); // Free string allocated by setVariantString
Q_ASSERT(hr == S_OK);
Q_UNUSED(hr)
@ -157,6 +165,7 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
clearVariant(&oldVal);
setVariantDouble(valueInterface->currentValue().toDouble(), &newVal);
UiaRaiseAutomationPropertyChangedEvent(provider, UIA_RangeValueValuePropertyId, oldVal, newVal);
provider->Release();
}
}
}
@ -174,6 +183,7 @@ void QWindowsUiaMainProvider::notifyNameChange(QAccessibleEvent *event)
setVariantString(accessible->text(QAccessible::Name), &newVal);
UiaRaiseAutomationPropertyChangedEvent(provider, UIA_NamePropertyId, oldVal, newVal);
::SysFreeString(newVal.bstrVal);
provider->Release();
}
}
}
@ -184,6 +194,7 @@ void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event)
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
UiaRaiseAutomationEvent(provider, UIA_SelectionItem_ElementSelectedEventId);
provider->Release();
}
}
}
@ -203,6 +214,7 @@ void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
} else {
UiaRaiseAutomationEvent(provider, UIA_Text_TextChangedEventId);
}
provider->Release();
}
}
}
@ -222,6 +234,7 @@ void QWindowsUiaMainProvider::raiseNotification(QAccessibleAnnouncementEvent *ev
::SysFreeString(message);
::SysFreeString(activityId);
provider->Release();
}
}
}
@ -697,7 +710,7 @@ HRESULT QWindowsUiaMainProvider::Navigate(NavigateDirection direction, IRawEleme
}
if (targetacc)
*pRetVal = providerForAccessible(targetacc);
*pRetVal = providerForAccessible(targetacc); // Detach
return S_OK;
}
@ -786,7 +799,7 @@ HRESULT QWindowsUiaMainProvider::get_FragmentRoot(IRawElementProviderFragmentRoo
if (QAccessibleInterface *accessible = accessibleInterface()) {
if (QWindow *window = windowForAccessible(accessible)) {
if (QAccessibleInterface *rootacc = window->accessibleRoot()) {
*pRetVal = providerForAccessible(rootacc);
*pRetVal = providerForAccessible(rootacc); // Detach
}
}
}
@ -827,7 +840,7 @@ HRESULT QWindowsUiaMainProvider::ElementProviderFromPoint(double x, double y, IR
if (targetacc->textInterface()) break;
acc = acc->childAt(point.x(), point.y());
}
*pRetVal = providerForAccessible(targetacc);
*pRetVal = providerForAccessible(targetacc); // Detach
}
return S_OK;
}
@ -843,7 +856,7 @@ HRESULT QWindowsUiaMainProvider::GetFocus(IRawElementProviderFragment **pRetVal)
if (QAccessibleInterface *accessible = accessibleInterface()) {
if (QAccessibleInterface *focusacc = accessible->focusChild()) {
*pRetVal = providerForAccessible(focusacc);
*pRetVal = providerForAccessible(focusacc); // Detach
}
}
return S_OK;

View File

@ -178,7 +178,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_SelectionContain
QAccessibleInterface *parent = accessible->parent();
if (parent && parent->selectionInterface()) {
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent);
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent); // Detach
return S_OK;
}
@ -190,7 +190,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_SelectionContain
if (parent) {
if ((accessible->role() == QAccessible::ListItem && parent->role() == QAccessible::List)
|| (accessible->role() == QAccessible::PageTab && parent->role() == QAccessible::PageTabList)) {
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent);
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent); // Detach
}
}
return S_OK;

View File

@ -163,7 +163,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_FirstSelectedItem(__
if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(firstSelectedChild))
{
*pRetVal = static_cast<IRawElementProviderSimple *>(childProvider);
*pRetVal = static_cast<IRawElementProviderSimple *>(childProvider); // Detach
return S_OK;
}
@ -208,7 +208,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_LastSelectedItem(__R
if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(lastSelectedChild))
{
*pRetVal = static_cast<IRawElementProviderSimple *>(childProvider);
*pRetVal = static_cast<IRawElementProviderSimple *>(childProvider); // Detach
return S_OK;
}

View File

@ -265,7 +265,7 @@ HRESULT QWindowsUiaTextRangeProvider::GetEnclosingElement(IRawElementProviderSim
if (!accessible)
return UIA_E_ELEMENTNOTAVAILABLE;
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(accessible);
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(accessible); // Detach
return S_OK;
}