Use Microsoft::WRL::ComPtr to manage lifetime of QWindowsUiaMainProvider
Using smart pointers for managing COM object lifetimes reduces risk of introducing reference counting regressions. Task-number: QTBUG-126530 Change-Id: If487b78eae6403c762205ecc042e8872e3a6b940 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io> (cherry picked from commit f51896b74e57459748313af750c013353d013821) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
29c32e7cdc
commit
89ba182737
@ -561,6 +561,7 @@ qt_internal_extend_target(Core CONDITION WIN32
|
|||||||
plugin/qsystemlibrary.cpp plugin/qsystemlibrary_p.h
|
plugin/qsystemlibrary.cpp plugin/qsystemlibrary_p.h
|
||||||
thread/qthread_win.cpp
|
thread/qthread_win.cpp
|
||||||
platform/windows/qcomobject_p.h
|
platform/windows/qcomobject_p.h
|
||||||
|
platform/windows/qcomptr_p.h
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
advapi32
|
advapi32
|
||||||
authz
|
authz
|
||||||
|
43
src/corelib/platform/windows/qcomptr_p.h
Normal file
43
src/corelib/platform/windows/qcomptr_p.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
#ifndef QCOMPTR_P_H
|
||||||
|
#define QCOMPTR_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <QtCore/private/qglobal_p.h>
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN) || defined(Q_QDOC)
|
||||||
|
|
||||||
|
#include <QtCore/qt_windows.h>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
using Microsoft::WRL::ComPtr;
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
ComPtr<T> makeComObject(Args &&...args)
|
||||||
|
{
|
||||||
|
ComPtr<T> p;
|
||||||
|
// Don't use Attach because of MINGW64 bug
|
||||||
|
// #892 Microsoft::WRL::ComPtr::Attach leaks references
|
||||||
|
*p.GetAddressOf() = new T(std::forward<Args>(args)...);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // Q_OS_WIN
|
||||||
|
|
||||||
|
#endif // QCOMPTR_P_H
|
@ -46,9 +46,8 @@ bool QWindowsUiaAccessibility::handleWmGetObject(HWND hwnd, WPARAM wParam, LPARA
|
|||||||
|
|
||||||
if (QWindow *window = QWindowsContext::instance()->findWindow(hwnd)) {
|
if (QWindow *window = QWindowsContext::instance()->findWindow(hwnd)) {
|
||||||
if (QAccessibleInterface *accessible = window->accessibleRoot()) {
|
if (QAccessibleInterface *accessible = window->accessibleRoot()) {
|
||||||
QWindowsUiaMainProvider *provider = QWindowsUiaMainProvider::providerForAccessible(accessible);
|
auto provider = QWindowsUiaMainProvider::providerForAccessible(accessible);
|
||||||
*lResult = UiaReturnRawElementProvider(hwnd, wParam, lParam, provider);
|
*lResult = UiaReturnRawElementProvider(hwnd, wParam, lParam, provider.Get());
|
||||||
provider->Release();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_ContainingGrid(IRawEl
|
|||||||
return UIA_E_ELEMENTNOTAVAILABLE;
|
return UIA_E_ELEMENTNOTAVAILABLE;
|
||||||
|
|
||||||
if (QAccessibleInterface *table = tableCellInterface->table()) {
|
if (QAccessibleInterface *table = tableCellInterface->table()) {
|
||||||
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(table); // Detach
|
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(table).Detach();
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -45,9 +45,8 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaGridProvider::GetItem(int row, int column,
|
|||||||
return UIA_E_ELEMENTNOTAVAILABLE;
|
return UIA_E_ELEMENTNOTAVAILABLE;
|
||||||
|
|
||||||
if ((row >= 0) && (row < tableInterface->rowCount()) && (column >= 0) && (column < tableInterface->columnCount())) {
|
if ((row >= 0) && (row < tableInterface->rowCount()) && (column >= 0) && (column < tableInterface->columnCount())) {
|
||||||
if (QAccessibleInterface *cell = tableInterface->cellAt(row, column)) {
|
if (QAccessibleInterface *cell = tableInterface->cellAt(row, column))
|
||||||
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(cell); // Detach
|
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(cell).Detach();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -40,18 +40,18 @@ QT_BEGIN_NAMESPACE
|
|||||||
using namespace QWindowsUiAutomation;
|
using namespace QWindowsUiAutomation;
|
||||||
|
|
||||||
// Returns a cached instance of the provider for a specific accessible interface.
|
// Returns a cached instance of the provider for a specific accessible interface.
|
||||||
QWindowsUiaMainProvider *QWindowsUiaMainProvider::providerForAccessible(QAccessibleInterface *accessible)
|
ComPtr<QWindowsUiaMainProvider> QWindowsUiaMainProvider::providerForAccessible(QAccessibleInterface *accessible)
|
||||||
{
|
{
|
||||||
if (!accessible)
|
if (!accessible)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
QAccessible::Id id = QAccessible::uniqueId(accessible);
|
QAccessible::Id id = QAccessible::uniqueId(accessible);
|
||||||
QWindowsUiaProviderCache *providerCache = QWindowsUiaProviderCache::instance();
|
QWindowsUiaProviderCache *providerCache = QWindowsUiaProviderCache::instance();
|
||||||
QWindowsUiaMainProvider *provider = providerCache->providerForId(id);
|
ComPtr<QWindowsUiaMainProvider> provider = providerCache->providerForId(id);
|
||||||
|
|
||||||
if (!provider) {
|
if (!provider) {
|
||||||
provider = new QWindowsUiaMainProvider(accessible);
|
provider = makeComObject<QWindowsUiaMainProvider>(accessible);
|
||||||
providerCache->insert(id, provider);
|
providerCache->insert(id, provider.Get()); // Cache holds weak references
|
||||||
}
|
}
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
@ -73,10 +73,8 @@ void QWindowsUiaMainProvider::notifyFocusChange(QAccessibleEvent *event)
|
|||||||
if (QAccessibleInterface *child = accessible->focusChild())
|
if (QAccessibleInterface *child = accessible->focusChild())
|
||||||
accessible = child;
|
accessible = child;
|
||||||
}
|
}
|
||||||
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
|
if (auto provider = providerForAccessible(accessible))
|
||||||
UiaRaiseAutomationEvent(provider, UIA_AutomationFocusChangedEventId);
|
UiaRaiseAutomationEvent(provider.Get(), UIA_AutomationFocusChangedEventId);
|
||||||
provider->Release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,34 +84,33 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
|
|||||||
if (event->changedStates().checked || event->changedStates().checkStateMixed) {
|
if (event->changedStates().checked || event->changedStates().checkStateMixed) {
|
||||||
// Notifies states changes in checkboxes.
|
// Notifies states changes in checkboxes.
|
||||||
if (accessible->role() == QAccessible::CheckBox) {
|
if (accessible->role() == QAccessible::CheckBox) {
|
||||||
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
|
if (auto provider = providerForAccessible(accessible)) {
|
||||||
VARIANT oldVal, newVal;
|
VARIANT oldVal, newVal;
|
||||||
clearVariant(&oldVal);
|
clearVariant(&oldVal);
|
||||||
int toggleState = ToggleState_Off;
|
int toggleState = ToggleState_Off;
|
||||||
if (accessible->state().checked)
|
if (accessible->state().checked)
|
||||||
toggleState = accessible->state().checkStateMixed ? ToggleState_Indeterminate : ToggleState_On;
|
toggleState = accessible->state().checkStateMixed ? ToggleState_Indeterminate : ToggleState_On;
|
||||||
setVariantI4(toggleState, &newVal);
|
setVariantI4(toggleState, &newVal);
|
||||||
UiaRaiseAutomationPropertyChangedEvent(provider, UIA_ToggleToggleStatePropertyId, oldVal, newVal);
|
UiaRaiseAutomationPropertyChangedEvent(
|
||||||
provider->Release();
|
provider.Get(), UIA_ToggleToggleStatePropertyId, oldVal, newVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (event->changedStates().active) {
|
if (event->changedStates().active) {
|
||||||
if (accessible->role() == QAccessible::Window) {
|
if (accessible->role() == QAccessible::Window) {
|
||||||
// Notifies window opened/closed.
|
// Notifies window opened/closed.
|
||||||
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
|
if (auto provider = providerForAccessible(accessible)) {
|
||||||
if (accessible->state().active) {
|
if (accessible->state().active) {
|
||||||
UiaRaiseAutomationEvent(provider, UIA_Window_WindowOpenedEventId);
|
UiaRaiseAutomationEvent(provider.Get(), UIA_Window_WindowOpenedEventId);
|
||||||
if (QAccessibleInterface *focused = accessible->focusChild()) {
|
if (QAccessibleInterface *focused = accessible->focusChild()) {
|
||||||
if (QWindowsUiaMainProvider *focusedProvider = providerForAccessible(focused)) {
|
if (auto focusedProvider = providerForAccessible(focused)) {
|
||||||
UiaRaiseAutomationEvent(focusedProvider, UIA_AutomationFocusChangedEventId);
|
UiaRaiseAutomationEvent(focusedProvider.Get(),
|
||||||
focusedProvider->Release();
|
UIA_AutomationFocusChangedEventId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UiaRaiseAutomationEvent(provider, UIA_Window_WindowClosedEventId);
|
UiaRaiseAutomationEvent(provider.Get(), UIA_Window_WindowClosedEventId);
|
||||||
}
|
}
|
||||||
provider->Release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,26 +137,26 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (event->value().typeId() == QMetaType::QString) {
|
if (event->value().typeId() == QMetaType::QString) {
|
||||||
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
|
if (auto provider = providerForAccessible(accessible)) {
|
||||||
// Notifies changes in string values.
|
// Notifies changes in string values.
|
||||||
VARIANT oldVal, newVal;
|
VARIANT oldVal, newVal;
|
||||||
clearVariant(&oldVal);
|
clearVariant(&oldVal);
|
||||||
setVariantString(event->value().toString(), &newVal);
|
setVariantString(event->value().toString(), &newVal);
|
||||||
UiaRaiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
|
UiaRaiseAutomationPropertyChangedEvent(provider.Get(), UIA_ValueValuePropertyId,
|
||||||
provider->Release();
|
oldVal, newVal);
|
||||||
|
|
||||||
HRESULT hr = VariantClear(&newVal); // Free string allocated by setVariantString
|
HRESULT hr = VariantClear(&newVal); // Free string allocated by setVariantString
|
||||||
Q_ASSERT(hr == S_OK);
|
Q_ASSERT(hr == S_OK);
|
||||||
Q_UNUSED(hr)
|
Q_UNUSED(hr)
|
||||||
}
|
}
|
||||||
} else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
|
} else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
|
||||||
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
|
if (auto provider = providerForAccessible(accessible)) {
|
||||||
// Notifies changes in values of controls supporting the value interface.
|
// Notifies changes in values of controls supporting the value interface.
|
||||||
VARIANT oldVal, newVal;
|
VARIANT oldVal, newVal;
|
||||||
clearVariant(&oldVal);
|
clearVariant(&oldVal);
|
||||||
setVariantDouble(valueInterface->currentValue().toDouble(), &newVal);
|
setVariantDouble(valueInterface->currentValue().toDouble(), &newVal);
|
||||||
UiaRaiseAutomationPropertyChangedEvent(provider, UIA_RangeValueValuePropertyId, oldVal, newVal);
|
UiaRaiseAutomationPropertyChangedEvent(
|
||||||
provider->Release();
|
provider.Get(), UIA_RangeValueValuePropertyId, oldVal, newVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,13 +168,13 @@ void QWindowsUiaMainProvider::notifyNameChange(QAccessibleEvent *event)
|
|||||||
// Restrict notification to combo boxes, which need it for accessibility,
|
// Restrict notification to combo boxes, which need it for accessibility,
|
||||||
// in order to avoid slowdowns with unnecessary notifications.
|
// in order to avoid slowdowns with unnecessary notifications.
|
||||||
if (accessible->role() == QAccessible::ComboBox) {
|
if (accessible->role() == QAccessible::ComboBox) {
|
||||||
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
|
if (auto provider = providerForAccessible(accessible)) {
|
||||||
VARIANT oldVal, newVal;
|
VARIANT oldVal, newVal;
|
||||||
clearVariant(&oldVal);
|
clearVariant(&oldVal);
|
||||||
setVariantString(accessible->text(QAccessible::Name), &newVal);
|
setVariantString(accessible->text(QAccessible::Name), &newVal);
|
||||||
UiaRaiseAutomationPropertyChangedEvent(provider, UIA_NamePropertyId, oldVal, newVal);
|
UiaRaiseAutomationPropertyChangedEvent(provider.Get(), UIA_NamePropertyId, oldVal,
|
||||||
|
newVal);
|
||||||
::SysFreeString(newVal.bstrVal);
|
::SysFreeString(newVal.bstrVal);
|
||||||
provider->Release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,10 +183,8 @@ void QWindowsUiaMainProvider::notifyNameChange(QAccessibleEvent *event)
|
|||||||
void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event)
|
void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event)
|
||||||
{
|
{
|
||||||
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
|
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
|
||||||
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
|
if (auto provider = providerForAccessible(accessible))
|
||||||
UiaRaiseAutomationEvent(provider, UIA_SelectionItem_ElementSelectedEventId);
|
UiaRaiseAutomationEvent(provider.Get(), UIA_SelectionItem_ElementSelectedEventId);
|
||||||
provider->Release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,17 +193,17 @@ void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
|
|||||||
{
|
{
|
||||||
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
|
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
|
||||||
if (accessible->textInterface()) {
|
if (accessible->textInterface()) {
|
||||||
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
|
if (auto provider = providerForAccessible(accessible)) {
|
||||||
if (event->type() == QAccessible::TextSelectionChanged) {
|
if (event->type() == QAccessible::TextSelectionChanged) {
|
||||||
UiaRaiseAutomationEvent(provider, UIA_Text_TextSelectionChangedEventId);
|
UiaRaiseAutomationEvent(provider.Get(), UIA_Text_TextSelectionChangedEventId);
|
||||||
} else if (event->type() == QAccessible::TextCaretMoved) {
|
} else if (event->type() == QAccessible::TextCaretMoved) {
|
||||||
if (!accessible->state().readOnly) {
|
if (!accessible->state().readOnly) {
|
||||||
UiaRaiseAutomationEvent(provider, UIA_Text_TextSelectionChangedEventId);
|
UiaRaiseAutomationEvent(provider.Get(),
|
||||||
|
UIA_Text_TextSelectionChangedEventId);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UiaRaiseAutomationEvent(provider, UIA_Text_TextChangedEventId);
|
UiaRaiseAutomationEvent(provider.Get(), UIA_Text_TextChangedEventId);
|
||||||
}
|
}
|
||||||
provider->Release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,18 +212,18 @@ void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
|
|||||||
void QWindowsUiaMainProvider::raiseNotification(QAccessibleAnnouncementEvent *event)
|
void QWindowsUiaMainProvider::raiseNotification(QAccessibleAnnouncementEvent *event)
|
||||||
{
|
{
|
||||||
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
|
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
|
||||||
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
|
if (auto provider = providerForAccessible(accessible)) {
|
||||||
BSTR message = bStrFromQString(event->message());
|
BSTR message = bStrFromQString(event->message());
|
||||||
QAccessible::AnnouncementPoliteness prio = event->politeness();
|
QAccessible::AnnouncementPoliteness prio = event->politeness();
|
||||||
NotificationProcessing processing = (prio == QAccessible::AnnouncementPoliteness::Assertive)
|
NotificationProcessing processing = (prio == QAccessible::AnnouncementPoliteness::Assertive)
|
||||||
? NotificationProcessing_ImportantAll
|
? NotificationProcessing_ImportantAll
|
||||||
: NotificationProcessing_All;
|
: NotificationProcessing_All;
|
||||||
BSTR activityId = bStrFromQString(QString::fromLatin1(""));
|
BSTR activityId = bStrFromQString(QString::fromLatin1(""));
|
||||||
UiaRaiseNotificationEvent(provider, NotificationKind_Other, processing, message, activityId);
|
UiaRaiseNotificationEvent(provider.Get(), NotificationKind_Other, processing, message,
|
||||||
|
activityId);
|
||||||
|
|
||||||
::SysFreeString(message);
|
::SysFreeString(message);
|
||||||
::SysFreeString(activityId);
|
::SysFreeString(activityId);
|
||||||
provider->Release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -383,9 +378,9 @@ void QWindowsUiaMainProvider::fillVariantArrayForRelation(QAccessibleInterface*
|
|||||||
|
|
||||||
SAFEARRAY *elements = SafeArrayCreateVector(VT_UNKNOWN, 0, relationInterfaces.size());
|
SAFEARRAY *elements = SafeArrayCreateVector(VT_UNKNOWN, 0, relationInterfaces.size());
|
||||||
for (LONG i = 0; i < relationInterfaces.size(); ++i) {
|
for (LONG i = 0; i < relationInterfaces.size(); ++i) {
|
||||||
if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(relationInterfaces.at(i).first)) {
|
if (ComPtr<IRawElementProviderSimple> provider =
|
||||||
SafeArrayPutElement(elements, &i, static_cast<IRawElementProviderSimple*>(childProvider));
|
providerForAccessible(relationInterfaces.at(i).first)) {
|
||||||
childProvider->Release();
|
SafeArrayPutElement(elements, &i, provider.Get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -697,7 +692,7 @@ HRESULT QWindowsUiaMainProvider::Navigate(NavigateDirection direction, IRawEleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (targetacc)
|
if (targetacc)
|
||||||
*pRetVal = providerForAccessible(targetacc); // Detach
|
*pRetVal = providerForAccessible(targetacc).Detach();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,9 +780,8 @@ HRESULT QWindowsUiaMainProvider::get_FragmentRoot(IRawElementProviderFragmentRoo
|
|||||||
// non-native controls/fragments.
|
// non-native controls/fragments.
|
||||||
if (QAccessibleInterface *accessible = accessibleInterface()) {
|
if (QAccessibleInterface *accessible = accessibleInterface()) {
|
||||||
if (QWindow *window = windowForAccessible(accessible)) {
|
if (QWindow *window = windowForAccessible(accessible)) {
|
||||||
if (QAccessibleInterface *rootacc = window->accessibleRoot()) {
|
if (QAccessibleInterface *rootacc = window->accessibleRoot())
|
||||||
*pRetVal = providerForAccessible(rootacc); // Detach
|
*pRetVal = providerForAccessible(rootacc).Detach();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@ -827,7 +821,7 @@ HRESULT QWindowsUiaMainProvider::ElementProviderFromPoint(double x, double y, IR
|
|||||||
if (targetacc->textInterface()) break;
|
if (targetacc->textInterface()) break;
|
||||||
acc = acc->childAt(point.x(), point.y());
|
acc = acc->childAt(point.x(), point.y());
|
||||||
}
|
}
|
||||||
*pRetVal = providerForAccessible(targetacc); // Detach
|
*pRetVal = providerForAccessible(targetacc).Detach();
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@ -843,7 +837,7 @@ HRESULT QWindowsUiaMainProvider::GetFocus(IRawElementProviderFragment **pRetVal)
|
|||||||
|
|
||||||
if (QAccessibleInterface *accessible = accessibleInterface()) {
|
if (QAccessibleInterface *accessible = accessibleInterface()) {
|
||||||
if (QAccessibleInterface *focusacc = accessible->focusChild()) {
|
if (QAccessibleInterface *focusacc = accessible->focusChild()) {
|
||||||
*pRetVal = providerForAccessible(focusacc); // Detach
|
*pRetVal = providerForAccessible(focusacc).Detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <QtCore/qmutex.h>
|
#include <QtCore/qmutex.h>
|
||||||
#include <QtCore/qt_windows.h>
|
#include <QtCore/qt_windows.h>
|
||||||
#include <QtGui/qaccessible.h>
|
#include <QtGui/qaccessible.h>
|
||||||
|
#include <QtCore/private/qcomptr_p.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ class QWindowsUiaMainProvider :
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY_MOVE(QWindowsUiaMainProvider)
|
Q_DISABLE_COPY_MOVE(QWindowsUiaMainProvider)
|
||||||
public:
|
public:
|
||||||
static QWindowsUiaMainProvider *providerForAccessible(QAccessibleInterface *accessible);
|
static ComPtr<QWindowsUiaMainProvider> providerForAccessible(QAccessibleInterface *accessible);
|
||||||
explicit QWindowsUiaMainProvider(QAccessibleInterface *a);
|
explicit QWindowsUiaMainProvider(QAccessibleInterface *a);
|
||||||
virtual ~QWindowsUiaMainProvider();
|
virtual ~QWindowsUiaMainProvider();
|
||||||
static void notifyFocusChange(QAccessibleEvent *event);
|
static void notifyFocusChange(QAccessibleEvent *event);
|
||||||
|
@ -26,12 +26,13 @@ QWindowsUiaProviderCache *QWindowsUiaProviderCache::instance()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns the provider instance associated with the ID, or nullptr.
|
// Returns the provider instance associated with the ID, or nullptr.
|
||||||
QWindowsUiaMainProvider *QWindowsUiaProviderCache::providerForId(QAccessible::Id id) const
|
ComPtr<QWindowsUiaMainProvider> QWindowsUiaProviderCache::providerForId(QAccessible::Id id) const
|
||||||
{
|
{
|
||||||
QMutexLocker guard{ &m_tableMutex };
|
QMutexLocker guard{ &m_tableMutex };
|
||||||
QWindowsUiaMainProvider *provider = m_providerTable.value(id);
|
|
||||||
if (provider)
|
// Make sure lifetime is extended while holding the mutex
|
||||||
provider->AddRef(); // Make sure lifetime is extended while holding the mutex
|
ComPtr<QWindowsUiaMainProvider> provider = m_providerTable.value(id);
|
||||||
|
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <QtCore/qhash.h>
|
#include <QtCore/qhash.h>
|
||||||
#include <QtCore/qmutex.h>
|
#include <QtCore/qmutex.h>
|
||||||
#include <QtGui/qaccessible.h>
|
#include <QtGui/qaccessible.h>
|
||||||
|
#include <QtCore/private/qcomptr_p.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ class QWindowsUiaProviderCache : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
static QWindowsUiaProviderCache *instance();
|
static QWindowsUiaProviderCache *instance();
|
||||||
QWindowsUiaMainProvider *providerForId(QAccessible::Id id) const;
|
ComPtr<QWindowsUiaMainProvider> providerForId(QAccessible::Id id) const;
|
||||||
void insert(QAccessible::Id id, QWindowsUiaMainProvider *provider);
|
void insert(QAccessible::Id id, QWindowsUiaMainProvider *provider);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
|
@ -178,7 +178,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_SelectionContain
|
|||||||
|
|
||||||
QAccessibleInterface *parent = accessible->parent();
|
QAccessibleInterface *parent = accessible->parent();
|
||||||
if (parent && parent->selectionInterface()) {
|
if (parent && parent->selectionInterface()) {
|
||||||
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent); // Detach
|
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent).Detach();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +190,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_SelectionContain
|
|||||||
if (parent) {
|
if (parent) {
|
||||||
if ((accessible->role() == QAccessible::ListItem && parent->role() == QAccessible::List)
|
if ((accessible->role() == QAccessible::ListItem && parent->role() == QAccessible::List)
|
||||||
|| (accessible->role() == QAccessible::PageTab && parent->role() == QAccessible::PageTabList)) {
|
|| (accessible->role() == QAccessible::PageTab && parent->role() == QAccessible::PageTabList)) {
|
||||||
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent); // Detach
|
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent).Detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -65,9 +65,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::GetSelection(SAFEARRAY *
|
|||||||
|
|
||||||
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, selectedList.size()))) {
|
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, selectedList.size()))) {
|
||||||
for (LONG i = 0; i < selectedList.size(); ++i) {
|
for (LONG i = 0; i < selectedList.size(); ++i) {
|
||||||
if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(selectedList.at(i))) {
|
if (ComPtr<IRawElementProviderSimple> provider =
|
||||||
SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(childProvider));
|
QWindowsUiaMainProvider::providerForAccessible(selectedList.at(i))) {
|
||||||
childProvider->Release();
|
SafeArrayPutElement(*pRetVal, &i, provider.Get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,9 +161,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_FirstSelectedItem(__
|
|||||||
if (!firstSelectedChild)
|
if (!firstSelectedChild)
|
||||||
return UIA_E_ELEMENTNOTAVAILABLE;
|
return UIA_E_ELEMENTNOTAVAILABLE;
|
||||||
|
|
||||||
if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(firstSelectedChild))
|
if (ComPtr<IRawElementProviderSimple> childProvider =
|
||||||
{
|
QWindowsUiaMainProvider::providerForAccessible(firstSelectedChild)) {
|
||||||
*pRetVal = static_cast<IRawElementProviderSimple *>(childProvider); // Detach
|
*pRetVal = childProvider.Detach();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,9 +206,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_LastSelectedItem(__R
|
|||||||
if (!lastSelectedChild)
|
if (!lastSelectedChild)
|
||||||
return UIA_E_ELEMENTNOTAVAILABLE;
|
return UIA_E_ELEMENTNOTAVAILABLE;
|
||||||
|
|
||||||
if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(lastSelectedChild))
|
if (ComPtr<IRawElementProviderSimple> childProvider =
|
||||||
{
|
QWindowsUiaMainProvider::providerForAccessible(lastSelectedChild)) {
|
||||||
*pRetVal = static_cast<IRawElementProviderSimple *>(childProvider); // Detach
|
*pRetVal = childProvider.Detach();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,9 +48,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableItemProvider::GetRowHeaderItems(SAFEAR
|
|||||||
|
|
||||||
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
|
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
|
||||||
for (LONG i = 0; i < headers.size(); ++i) {
|
for (LONG i = 0; i < headers.size(); ++i) {
|
||||||
if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
|
if (ComPtr<IRawElementProviderSimple> provider =
|
||||||
SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(headerProvider));
|
QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
|
||||||
headerProvider->Release();
|
SafeArrayPutElement(*pRetVal, &i, provider.Get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,9 +78,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableItemProvider::GetColumnHeaderItems(SAF
|
|||||||
|
|
||||||
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
|
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
|
||||||
for (LONG i = 0; i < headers.size(); ++i) {
|
for (LONG i = 0; i < headers.size(); ++i) {
|
||||||
if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
|
if (ComPtr<IRawElementProviderSimple> provider =
|
||||||
SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(headerProvider));
|
QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
|
||||||
headerProvider->Release();
|
SafeArrayPutElement(*pRetVal, &i, provider.Get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,9 +55,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableProvider::GetRowHeaders(SAFEARRAY **pR
|
|||||||
}
|
}
|
||||||
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
|
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
|
||||||
for (LONG i = 0; i < headers.size(); ++i) {
|
for (LONG i = 0; i < headers.size(); ++i) {
|
||||||
if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
|
if (ComPtr<IRawElementProviderSimple> provider =
|
||||||
SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(headerProvider));
|
QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
|
||||||
headerProvider->Release();
|
SafeArrayPutElement(*pRetVal, &i, provider.Get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,9 +92,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableProvider::GetColumnHeaders(SAFEARRAY *
|
|||||||
}
|
}
|
||||||
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
|
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
|
||||||
for (LONG i = 0; i < headers.size(); ++i) {
|
for (LONG i = 0; i < headers.size(); ++i) {
|
||||||
if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
|
if (ComPtr<IRawElementProviderSimple> provider =
|
||||||
SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(headerProvider));
|
QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
|
||||||
headerProvider->Release();
|
SafeArrayPutElement(*pRetVal, &i, provider.Get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,7 +265,7 @@ HRESULT QWindowsUiaTextRangeProvider::GetEnclosingElement(IRawElementProviderSim
|
|||||||
if (!accessible)
|
if (!accessible)
|
||||||
return UIA_E_ELEMENTNOTAVAILABLE;
|
return UIA_E_ELEMENTNOTAVAILABLE;
|
||||||
|
|
||||||
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(accessible); // Detach
|
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(accessible).Detach();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,23 +6,10 @@
|
|||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
|
||||||
#include <private/qcomobject_p.h>
|
#include <private/qcomobject_p.h>
|
||||||
|
#include <QtCore/private/qcomptr_p.h>
|
||||||
# include <wrl/client.h>
|
|
||||||
|
|
||||||
using Microsoft::WRL::ComPtr;
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
|
||||||
ComPtr<T> makeComObject(Args &&...args)
|
|
||||||
{
|
|
||||||
ComPtr<T> p;
|
|
||||||
// Don't use Attach because of MINGW64 bug
|
|
||||||
// #892 Microsoft::WRL::ComPtr::Attach leaks references
|
|
||||||
*p.GetAddressOf() = new T(std::forward<Args>(args)...);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
MIDL_INTERFACE("878fab04-7da0-41ea-9c49-058c7fa0d80a")
|
MIDL_INTERFACE("878fab04-7da0-41ea-9c49-058c7fa0d80a")
|
||||||
IIntermediate : public IUnknown{};
|
IIntermediate : public IUnknown{};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user