From 0cf6297c15be45d852be98c862bd0211e6de1aa2 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Fri, 8 Sep 2017 18:00:05 +0200 Subject: Add support for Windows UI Automation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the Qt Accessibility Windows back end, formerly based on legacy MSAA, with a new implementation based on UI Automation. Fixes issues with accessibility tools like screen readers and magnifiers, and with the automatic showing and hiding of the virtual keyboard in touchscreen-based Windows computers. [ChangeLog][Windows] The Windows Accessibility back end, formerly based on Microsoft Active Accessibility, was replaced with a new implementation based on Microsoft UI Automation. Task-number: QTPM-487 Task-number: QTBUG-53024 Task-number: QTBUG-43190 Task-number: QTBUG-61926 Task-number: QTBUG-38499 Task-number: QTBUG-38337 Task-number: QTBUG-38501 Task-number: QTBUG-38502 Task-number: QTBUG-38504 Task-number: QTBUG-38505 Task-number: QTBUG-38507 Change-Id: I20b4f8f5e938fef791c6e9c577fcd919140999bd Reviewed-by: Jan Arve Sæther --- .../platforms/windows/accessible/accessible.pri | 19 - .../platforms/windows/accessible/comutils.cpp | 280 ---- .../platforms/windows/accessible/comutils.h | 64 - .../platforms/windows/accessible/iaccessible2.cpp | 1640 -------------------- .../platforms/windows/accessible/iaccessible2.h | 358 ----- .../windows/accessible/qwindowsaccessibility.cpp | 245 --- .../windows/accessible/qwindowsaccessibility.h | 63 - .../windows/accessible/qwindowsmsaaaccessible.cpp | 1223 --------------- .../windows/accessible/qwindowsmsaaaccessible.h | 177 --- 9 files changed, 4069 deletions(-) delete mode 100644 src/plugins/platforms/windows/accessible/accessible.pri delete mode 100644 src/plugins/platforms/windows/accessible/comutils.cpp delete mode 100644 src/plugins/platforms/windows/accessible/comutils.h delete mode 100644 src/plugins/platforms/windows/accessible/iaccessible2.cpp delete mode 100644 src/plugins/platforms/windows/accessible/iaccessible2.h delete mode 100644 src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp delete mode 100644 src/plugins/platforms/windows/accessible/qwindowsaccessibility.h delete mode 100644 src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp delete mode 100644 src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h (limited to 'src/plugins/platforms/windows/accessible') diff --git a/src/plugins/platforms/windows/accessible/accessible.pri b/src/plugins/platforms/windows/accessible/accessible.pri deleted file mode 100644 index 557bdfe307..0000000000 --- a/src/plugins/platforms/windows/accessible/accessible.pri +++ /dev/null @@ -1,19 +0,0 @@ -SOURCES += \ - $$PWD/qwindowsaccessibility.cpp \ - $$PWD/comutils.cpp - -HEADERS += \ - $$PWD/qwindowsaccessibility.h \ - $$PWD/comutils.h - -SOURCES += \ - $$PWD/qwindowsmsaaaccessible.cpp \ - $$PWD/iaccessible2.cpp - -HEADERS += \ - $$PWD/qwindowsmsaaaccessible.h \ - $$PWD/iaccessible2.h - -include(../../../../3rdparty/iaccessible2/iaccessible2.pri) - -mingw: LIBS *= -luuid diff --git a/src/plugins/platforms/windows/accessible/comutils.cpp b/src/plugins/platforms/windows/accessible/comutils.cpp deleted file mode 100644 index 1c072c5e2c..0000000000 --- a/src/plugins/platforms/windows/accessible/comutils.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -#include -#include - -#include "comutils.h" -#include -#include -#include - - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -static DATE QDateTimeToDATE(const QDateTime &dt) -{ - if (!dt.isValid() || dt.isNull()) - return 949998; // Special value for no date (01/01/4501) - - SYSTEMTIME stime; - memset(&stime, 0, sizeof(stime)); - QDate date = dt.date(); - QTime time = dt.time(); - if (date.isValid() && !date.isNull()) { - stime.wDay = WORD(date.day()); - stime.wMonth = WORD(date.month()); - stime.wYear = WORD(date.year()); - } - if (time.isValid() && !time.isNull()) { - stime.wMilliseconds = WORD(time.msec()); - stime.wSecond = WORD(time.second()); - stime.wMinute = WORD(time.minute()); - stime.wHour = WORD(time.hour()); - } - - double vtime; - SystemTimeToVariantTime(&stime, &vtime); - - return vtime; -} - -inline uint QColorToOLEColor(const QColor &col) -{ - return qRgba(col.blue(), col.green(), col.red(), 0x00); -} - -bool QVariant2VARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out) -{ - QVariant qvar = var; - // "type" is the expected type, so coerce if necessary - QVariant::Type proptype = typeName.isEmpty() ? QVariant::Invalid : QVariant::nameToType(typeName); - if (proptype == QVariant::UserType && !typeName.isEmpty()) { - if (typeName == "short" || typeName == "char") - proptype = QVariant::Int; - else if (typeName == "float") - proptype = QVariant::Double; - } - if (proptype != QVariant::Invalid && proptype != QVariant::UserType && proptype != qvar.type()) { - if (qvar.canConvert(int(proptype))) - qvar.convert(int(proptype)); - else - qvar = QVariant(proptype); - } - - if (out && arg.vt == (VT_VARIANT|VT_BYREF) && arg.pvarVal) { - return QVariant2VARIANT(var, *arg.pvarVal, typeName, false); - } - - if (out && proptype == QVariant::UserType && typeName == "QVariant") { - VARIANT *pVariant = new VARIANT; - QVariant2VARIANT(var, *pVariant, QByteArray(), false); - arg.vt = VT_VARIANT|VT_BYREF; - arg.pvarVal = pVariant; - return true; - } - - switch ((int)qvar.type()) { - case QVariant::String: - if (out && arg.vt == (VT_BSTR|VT_BYREF)) { - if (*arg.pbstrVal) - SysFreeString(*arg.pbstrVal); - *arg.pbstrVal = QStringToBSTR(qvar.toString()); - arg.vt = VT_BSTR|VT_BYREF; - } else { - arg.vt = VT_BSTR; - arg.bstrVal = QStringToBSTR(qvar.toString()); - if (out) { - arg.pbstrVal = new BSTR(arg.bstrVal); - arg.vt |= VT_BYREF; - } - } - break; - - case QVariant::Int: - if (out && arg.vt == (VT_I4|VT_BYREF)) { - *arg.plVal = qvar.toInt(); - } else { - arg.vt = VT_I4; - arg.lVal = qvar.toInt(); - if (out) { - if (typeName == "short") { - arg.vt = VT_I2; - arg.piVal = new short(arg.lVal); - } else if (typeName == "char") { - arg.vt = VT_I1; - arg.pcVal= new char(arg.lVal); - } else { - arg.plVal = new long(arg.lVal); - } - arg.vt |= VT_BYREF; - } - } - break; - - case QVariant::UInt: - if (out && (arg.vt == (VT_UINT|VT_BYREF) || arg.vt == (VT_I4|VT_BYREF))) { - *arg.puintVal = qvar.toUInt(); - } else { - arg.vt = VT_UINT; - arg.uintVal = qvar.toUInt(); - if (out) { - arg.puintVal = new uint(arg.uintVal); - arg.vt |= VT_BYREF; - } - } - break; - - case QVariant::LongLong: - if (out && arg.vt == (VT_CY|VT_BYREF)) { - arg.pcyVal->int64 = qvar.toLongLong(); - } else if (out && arg.vt == (VT_I8|VT_BYREF)) { - *arg.pllVal = qvar.toLongLong(); - } else { - arg.vt = VT_I8; - arg.llVal = qvar.toLongLong(); - if (out) { - arg.pllVal = new LONGLONG(arg.llVal); - arg.vt |= VT_BYREF; - } - } - break; - - case QVariant::ULongLong: - if (out && arg.vt == (VT_CY|VT_BYREF)) { - arg.pcyVal->int64 = qvar.toULongLong(); - } else if (out && arg.vt == (VT_UI8|VT_BYREF)) { - *arg.pullVal = qvar.toULongLong(); - } else { - arg.vt = VT_UI8; - arg.ullVal = qvar.toULongLong(); - if (out) { - arg.pullVal = new ULONGLONG(arg.ullVal); - arg.vt |= VT_BYREF; - } - } - break; - - case QVariant::Bool: - if (out && arg.vt == (VT_BOOL|VT_BYREF)) { - *arg.pboolVal = qvar.toBool() ? VARIANT_TRUE : VARIANT_FALSE; - } else { - arg.vt = VT_BOOL; - arg.boolVal = qvar.toBool() ? VARIANT_TRUE : VARIANT_FALSE; - if (out) { - arg.pboolVal = new short(arg.boolVal); - arg.vt |= VT_BYREF; - } - } - break; - case QVariant::Double: - if (out && arg.vt == (VT_R8|VT_BYREF)) { - *arg.pdblVal = qvar.toDouble(); - } else { - arg.vt = VT_R8; - arg.dblVal = qvar.toDouble(); - if (out) { - if (typeName == "float") { - arg.vt = VT_R4; - arg.pfltVal = new float(arg.dblVal); - } else { - arg.pdblVal = new double(arg.dblVal); - } - arg.vt |= VT_BYREF; - } - } - break; - case QVariant::Color: - if (out && arg.vt == (VT_COLOR|VT_BYREF)) { - - *arg.plVal = QColorToOLEColor(qvariant_cast(qvar)); - } else { - arg.vt = VT_COLOR; - arg.lVal = QColorToOLEColor(qvariant_cast(qvar)); - if (out) { - arg.plVal = new long(arg.lVal); - arg.vt |= VT_BYREF; - } - } - break; - - case QVariant::Date: - case QVariant::Time: - case QVariant::DateTime: - if (out && arg.vt == (VT_DATE|VT_BYREF)) { - *arg.pdate = QDateTimeToDATE(qvar.toDateTime()); - } else { - arg.vt = VT_DATE; - arg.date = QDateTimeToDATE(qvar.toDateTime()); - if (out) { - arg.pdate = new DATE(arg.date); - arg.vt |= VT_BYREF; - } - } - break; - - case QVariant::Invalid: // default-parameters not set - if (out && arg.vt == (VT_ERROR|VT_BYREF)) { - *arg.plVal = DISP_E_PARAMNOTFOUND; - } else { - arg.vt = VT_ERROR; - arg.lVal = DISP_E_PARAMNOTFOUND; - if (out) { - arg.plVal = new long(arg.lVal); - arg.vt |= VT_BYREF; - } - } - break; - - default: - return false; - } - - Q_ASSERT(!out || (arg.vt & VT_BYREF)); - return true; -} - -QT_END_NAMESPACE - diff --git a/src/plugins/platforms/windows/accessible/comutils.h b/src/plugins/platforms/windows/accessible/comutils.h deleted file mode 100644 index b1e6183a0f..0000000000 --- a/src/plugins/platforms/windows/accessible/comutils.h +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef COMUTILS_H -#define COMUTILS_H - -#if !defined(_WINDOWS_) && !defined(_WINDOWS_H) && !defined(__WINDOWS__) -#error Must include windows.h first! -#endif - -#include -#include - -QT_BEGIN_NAMESPACE - -class QVariant; - -// Originally QVariantToVARIANT copied from ActiveQt - renamed to avoid conflicts in static builds. -bool QVariant2VARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out); - -inline BSTR QStringToBSTR(const QString &str) -{ - return SysAllocStringLen(reinterpret_cast(str.unicode()), UINT(str.length())); -} - -QT_END_NAMESPACE - -#endif // COMUTILS_H - diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp deleted file mode 100644 index 3e60f45dd7..0000000000 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ /dev/null @@ -1,1640 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include -#ifndef QT_NO_ACCESSIBILITY - -#include "iaccessible2.h" -#include "qwindowsaccessibility.h" -#include -#include -#include -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -template -static inline T *coTaskMemAllocArray(int size) -{ - return static_cast(::CoTaskMemAlloc(sizeof(T) * size_t(size))); -} - -/**************************************************************\ - * AccessibleApplication * - **************************************************************/ - -HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appName(/* [retval][out] */ BSTR *name) -{ - const QString appName = QGuiApplication::applicationName(); - *name = QStringToBSTR(appName); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appVersion(/* [retval][out] */ BSTR *version) -{ - const QString appName = QGuiApplication::applicationVersion(); - *version = QStringToBSTR(appName); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitName(/* [retval][out] */ BSTR *name) -{ - *name = ::SysAllocString(L"Qt"); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitVersion(/* [retval][out] */ BSTR *version) -{ - *version = ::SysAllocString(TEXT(QT_VERSION_STR)); - return S_OK; -} - - -/**************************************************************\ - * AccessibleRelation * - **************************************************************/ -AccessibleRelation::AccessibleRelation(const QList &targets, - QAccessible::Relation relation) - : m_targets(targets), m_relation(relation) -{ - Q_ASSERT(m_targets.count()); -} - -/* IAccessibleRelation */ -HRESULT STDMETHODCALLTYPE AccessibleRelation::get_relationType( - /* [retval][out] */ BSTR *relationType) -{ - *relationType = relationToBSTR(m_relation); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE AccessibleRelation::get_localizedRelationType( - /* [retval][out] */ BSTR *localizedRelationType) -{ - // Who ever needs this??? - *localizedRelationType = relationToBSTR(m_relation); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE AccessibleRelation::get_nTargets( - /* [retval][out] */ long *nTargets) -{ - // ### always one target - *nTargets = m_targets.count(); - return S_OK; -} - -/*! - \internal - Client allocates and deallocates array - (see "Special Consideration when using Arrays", in Accessible2.idl) - */ -HRESULT STDMETHODCALLTYPE AccessibleRelation::get_target( - /* [in] */ long targetIndex, - /* [retval][out] */ IUnknown **target) -{ - if (targetIndex >= 0 && targetIndex < m_targets.count()) { - QAccessibleInterface *iface = m_targets.at(targetIndex); - *target = QWindowsAccessibility::wrap(iface); - if (*target) - return S_OK; - return E_FAIL; - } - return E_INVALIDARG; -} - -/*! - \internal - Client allocates and deallocates \a targets array - (see "Special Consideration when using Arrays", in Accessible2.idl) - */ -HRESULT STDMETHODCALLTYPE AccessibleRelation::get_targets( - /* [in] */ long maxTargets, - /* [length_is][size_is][out] */ IUnknown **targets, - /* [retval][out] */ long *nTargets) -{ - - const int numTargets = qMin(int(maxTargets), m_targets.count()); - for (int i = 0; i < numTargets; ++i) { - QAccessibleInterface *iface = m_targets.at(i); - IAccessible *iacc = QWindowsAccessibility::wrap(iface); - if (!iacc) - return E_FAIL; - *targets = iacc; - ++targets; - } - *nTargets = numTargets; - // \a targets array is allocated by client. - return numTargets > 0 ? S_OK : S_FALSE; -} - - -/**************************************************************\ - * * - * IUnknown * - * * - **************************************************************/ -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOID *iface) -{ - *iface = nullptr; - QAccessibleInterface *accessible = accessibleInterface(); - if (!accessible) - return E_NOINTERFACE; - - if (SUCCEEDED(QWindowsMsaaAccessible::QueryInterface(id, iface)) - || qWindowsComQueryInterface(this, id, iface) - || qWindowsComQueryInterface(this, id, iface) - || qWindowsComQueryInterface(this, id, iface)) { - return S_OK; - } - - if (id == IID_IAccessibleAction) { - if (accessible->actionInterface()) - *iface = static_cast(this); - } else if (id == IID_IAccessibleEditableText) { - if (accessible->editableTextInterface() || - accessible->role() == QAccessible::EditableText) - { - *iface = static_cast(this); - } - } else if (id == IID_IAccessibleHyperlink) { - //*iface = static_cast(this); - } else if (id == IID_IAccessibleHypertext) { - //*iface = static_cast(this); - } else if (id == IID_IAccessibleImage) { - //*iface = static_cast(this); - } else if (id == IID_IAccessibleTable) { - //*iface = static_cast(this); // not supported - } else if (id == IID_IAccessibleTable2) { - if (accessible->tableInterface()) - *iface = static_cast(this); - } else if (id == IID_IAccessibleTableCell) { - if (accessible->tableCellInterface()) - *iface = static_cast(this); - } else if (id == IID_IAccessibleText) { - if (accessible->textInterface()) - *iface = static_cast(this); - } else if (id == IID_IAccessibleValue) { - if (accessible->valueInterface()) - *iface = static_cast(this); - } - if (*iface) { - AddRef(); - return S_OK; - } - return E_NOINTERFACE; -} - - -/* Note that IUnknown is inherited from several interfaces. Therefore we must reimplement all its - functions in the concrete class to avoid ambiguity. -*/ -ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::AddRef() -{ - return QWindowsMsaaAccessible::AddRef(); -} - -ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::Release() -{ - return QWindowsMsaaAccessible::Release(); -} - -/**************************************************************\ - * * - * IAccessible2 * - * * - **************************************************************/ -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRelations(long *nRelations) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!nRelations) - return E_INVALIDARG; - if (!accessible) - return E_FAIL; - - return getRelationsHelper(0, 0, 0, nRelations); -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relation(long relationIndex, IAccessibleRelation **relation) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!relation) - return E_INVALIDARG; - if (!accessible) - return E_FAIL; - - return getRelationsHelper(relation, relationIndex, 1); -} - -/*! - \internal - Client allocates and deallocates array - (see "Special Consideration when using Arrays", in Accessible2.idl) - */ -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relations(long maxRelations, - IAccessibleRelation **relations, - long *nRelations) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - return getRelationsHelper(relations, 0, maxRelations, nRelations); -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::role(long *ia2role) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - long r = accessible->role(); - - switch (r) { - case QAccessible::LayeredPane: r = IA2_ROLE_LAYERED_PANE; break; - case QAccessible::Terminal: r = IA2_ROLE_TERMINAL; break; - case QAccessible::Desktop: r = IA2_ROLE_DESKTOP_PANE; break; - case QAccessible::Paragraph: r = IA2_ROLE_PARAGRAPH; break; - case QAccessible::Section: r = IA2_ROLE_SECTION; break; - default: break; - } - - *ia2role = r; - return S_OK; -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollTo(enum IA2ScrollType /*scrollType*/) -{ - //### Ignore for now - return E_NOTIMPL; -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollToPoint(enum IA2CoordinateType /*coordinateType*/, long /*x*/, long /*y*/) -{ - //### Ignore for now - return E_NOTIMPL; -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_groupPosition(long *groupLevel, - long *similarItemsInGroup, - long *positionInGroup) -{ - // ### Ignore for now. Not sure what this is used for..... - *groupLevel = 0; // Not applicable - *similarItemsInGroup = 0; // Not applicable - *positionInGroup = 0; // Not applicable - return S_FALSE; -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_states(AccessibleStates *states) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - if (!states) - return E_POINTER; - QAccessible::State st = accessible->state(); - AccessibleStates ia2states = 0; - if (st.active) - ia2states |= IA2_STATE_ACTIVE; - if (st.invalid) - ia2states |= IA2_STATE_DEFUNCT; - if (st.editable) - ia2states |= IA2_STATE_EDITABLE; - if (st.multiLine) - ia2states |= IA2_STATE_MULTI_LINE; - if (st.selectableText) - ia2states |= IA2_STATE_SELECTABLE_TEXT; - if (st.supportsAutoCompletion) - ia2states |= IA2_STATE_SUPPORTS_AUTOCOMPLETION; - - *states = ia2states; - return S_OK; -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_extendedRole(BSTR *extendedRole) -{ - //### - *extendedRole = 0; - return E_NOTIMPL; // mozilla does this - //return S_FALSE; -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedExtendedRole(BSTR *localizedExtendedRole) -{ - //### - *localizedExtendedRole = 0; - return E_NOTIMPL; // mozilla does this - //return S_FALSE; -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nExtendedStates(long *nExtendedStates) -{ - // Who will ever intepret these values into something meaningful?? - *nExtendedStates = 0; - return E_NOTIMPL; // mozilla does this - //return S_FALSE; -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_extendedStates(long /*maxExtendedStates*/, - BSTR **extendedStates, - long *nExtendedStates) -{ - *extendedStates = 0; - *nExtendedStates = 0; - return E_NOTIMPL; // mozilla does this - //return S_FALSE; -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedExtendedStates(long /*maxLocalizedExtendedStates*/, - BSTR **localizedExtendedStates, - long *nLocalizedExtendedStates) -{ - *localizedExtendedStates = 0; - *nLocalizedExtendedStates = 0; - return E_NOTIMPL; // mozilla does this - //return S_FALSE; -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_uniqueID(long *outUniqueID) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - qCDebug(lcQpaAccessibility) << "uniqueID: " << showbase << hex << id; - - *outUniqueID = (long)id; - return int(id) < 0 ? S_OK : S_FALSE; -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_windowHandle(HWND *windowHandle) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - return GetWindow(windowHandle); -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_indexInParent(long *indexInParent) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - if (!indexInParent) - return E_INVALIDARG; - QAccessibleInterface *par = accessible->parent(); - *indexInParent = par ? par->indexOfChild(accessible) : -1; - if (*indexInParent < 0) { - qCWarning(lcQpaAccessibility) << "index in parent invalid:" << accessible << "parent:" << par; - return S_FALSE; - } - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locale(IA2Locale *locale) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - IA2Locale res; - QLocale l; - res.country = QStringToBSTR(QLocale::countryToString(l.country())); - res.language = QStringToBSTR(QLocale::languageToString(l.language())); - res.variant = QStringToBSTR(QString()); - *locale = res; - return S_OK; -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(BSTR *attributes) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - *attributes = 0;//QStringToBSTR(QString()); - return S_FALSE; -} - -/**************************************************************\ - * IAccessibleAction * - **************************************************************/ -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::nActions(long *nActions) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - *nActions = QAccessibleBridgeUtils::effectiveActionNames(accessible).count(); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::doAction(long actionIndex) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible); - if (actionIndex < 0 || actionIndex >= actionNames.count()) - return E_INVALIDARG; - const QString actionName = actionNames.at(actionIndex); - return QAccessibleBridgeUtils::performEffectiveAction(accessible, actionName) ? S_OK : S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_description(long actionIndex, BSTR *description) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - *description = 0; - const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible); - if (actionIndex < 0 || actionIndex >= actionNames.count()) - return E_INVALIDARG; - const QString actionName = actionNames.at(actionIndex); - if (QAccessibleActionInterface *actionIface = actionInterface()) - *description = QStringToBSTR(actionIface->localizedActionDescription(actionName)); - else - *description = QStringToBSTR(qAccessibleLocalizedActionDescription(actionName)); - - return *description ? S_OK : S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_keyBinding(long actionIndex, long nMaxBindings, BSTR **keyBindings, long *nBindings) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - Q_UNUSED(nMaxBindings); - BSTR *arrayOfBindingsToReturn = 0; - int numBindings = 0; - if (QAccessibleActionInterface *actionIface = actionInterface()) { - const QStringList actionNames = actionIface->actionNames(); - if (actionIndex < 0 || actionIndex >= actionNames.count()) - return E_INVALIDARG; - const QString actionName = actionNames.at(actionIndex); - const QStringList keyBindings = actionIface->keyBindingsForAction(actionName); - numBindings = keyBindings.count(); - if (numBindings > 0) { - // The IDL documents that the client must free with CoTaskMemFree - arrayOfBindingsToReturn = coTaskMemAllocArray(numBindings); - std::transform(keyBindings.constBegin(), keyBindings.constEnd(), - QT_MAKE_CHECKED_ARRAY_ITERATOR(arrayOfBindingsToReturn, numBindings), - QStringToBSTR); - } - } - *keyBindings = arrayOfBindingsToReturn; - *nBindings = numBindings; - - return numBindings ? S_OK : S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_name(long actionIndex, BSTR *name) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - *name = 0; - const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible); - if (actionIndex < 0 || actionIndex >= actionNames.count()) - return E_INVALIDARG; - const QString actionName = actionNames.at(actionIndex); - *name = QStringToBSTR(actionName); - return *name ? S_OK : S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedName(long actionIndex, BSTR *localizedName) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - *localizedName = 0; - const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible); - if (actionIndex < 0 || actionIndex >= actionNames.count()) - return E_INVALIDARG; - - const QString actionName = actionNames.at(actionIndex); - if (QAccessibleActionInterface *actionIface = actionInterface()) - *localizedName = QStringToBSTR(actionIface->localizedActionName(actionName)); - else - *localizedName = QStringToBSTR(QAccessibleActionInterface::tr(qPrintable(actionName))); - - return *localizedName ? S_OK : S_FALSE; -} - -/**************************************************************\ - * IAccessibleComponent * - **************************************************************/ -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locationInParent(long *x, long *y) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - QPoint topLeft = accessible->rect().topLeft(); - - QAccessibleInterface *parentIface = accessible->parent(); - if (parentIface && parentIface->isValid()) - topLeft -= parentIface->rect().topLeft(); - const QPoint nativeTopLeft = QHighDpi::toNativeLocalPosition(topLeft, accessible->window()); - - - *x = nativeTopLeft.x(); - *y = nativeTopLeft.y(); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_foreground(IA2Color *foreground) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - // IA2Color is a typedef for long - *foreground = static_cast(accessible->foregroundColor().rgb()); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_background(IA2Color *background) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - // IA2Color is a typedef for long - *background = static_cast(accessible->backgroundColor().rgb()); - return S_OK; -} - -/**************************************************************\ - * IAccessibleEditableText * - **************************************************************/ -#if QT_CONFIG(clipboard) -/*! - \internal - - if \a endOffset == -1 it means end of the text -*/ -QString QWindowsIA2Accessible::textForRange(int startOffset, int endOffset) const -{ - QAccessibleInterface *accessible = accessibleInterface(); - - if (QAccessibleTextInterface *textIface = accessible->textInterface()) { - if (endOffset == IA2_TEXT_OFFSET_LENGTH) - endOffset = textIface->characterCount(); - return textIface->text(startOffset, endOffset); - } - QString txt = accessible->text(QAccessible::Value); - if (endOffset == IA2_TEXT_OFFSET_LENGTH) - endOffset = txt.length(); - return txt.mid(startOffset, endOffset - startOffset); -} -#endif - -/*! - \internal -*/ -void QWindowsIA2Accessible::replaceTextFallback(long startOffset, long endOffset, const QString &txt) -{ - QAccessibleInterface *accessible = accessibleInterface(); - QString t = textForRange(0, -1); - if (endOffset == IA2_TEXT_OFFSET_LENGTH) - endOffset = t.length(); - if (endOffset - startOffset == 0) { - t.insert(startOffset, txt); - } else { - t.replace(startOffset, endOffset - startOffset, txt); - } - accessible->setText(QAccessible::Value, t); -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::copyText(long startOffset, long endOffset) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); -#if QT_CONFIG(clipboard) - const QString t = textForRange(startOffset, endOffset); - QGuiApplication::clipboard()->setText(t); - return S_OK; -#else - return E_NOTIMPL; -#endif -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::deleteText(long startOffset, long endOffset) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) - editableTextIface->deleteText(startOffset, endOffset); - else - replaceTextFallback(startOffset, endOffset, QString()); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::insertText(long offset, BSTR *text) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - const QString txt = QString::fromWCharArray(*text); - if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) - editableTextIface->insertText(offset, txt); - else - replaceTextFallback(offset, offset, txt); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::cutText(long startOffset, long endOffset) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); -#if QT_CONFIG(clipboard) - const QString t = textForRange(startOffset, endOffset); - if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) - editableTextIface->deleteText(startOffset, endOffset); - else - replaceTextFallback(startOffset, endOffset, QString()); - QGuiApplication::clipboard()->setText(t); - return S_OK; -#else - return E_NOTIMPL; -#endif -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::pasteText(long offset) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); -#if QT_CONFIG(clipboard) - const QString txt = QGuiApplication::clipboard()->text(); - if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) - editableTextIface->insertText(offset, txt); - else - replaceTextFallback(offset, offset, txt); - return S_OK; -#else - return E_NOTIMPL; -#endif -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::replaceText(long startOffset, long endOffset, BSTR *text) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - const QString txt = QString::fromWCharArray(*text); - if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) - editableTextIface->replaceText(startOffset, endOffset, txt); - else - replaceTextFallback(startOffset, endOffset, txt); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setAttributes(long /*startOffset*/, long /*endOffset*/, BSTR * /*attributes*/) -{ - return E_NOTIMPL; -} - - -/**************************************************************\ - * IAccessibleTable2 * - **************************************************************/ -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_cellAt( long row, long column, IUnknown **cell) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - *cell = 0; - if (QAccessibleTableInterface *tableIface = tableInterface()) { - if (QAccessibleInterface *qtCell = tableIface->cellAt(row, column)) { - *cell = QWindowsAccessibility::wrap(qtCell); - } - } - qCDebug(lcQpaAccessibility) << "found cell? " << *cell; - return *cell ? S_OK : S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caption( IUnknown **captionInterface) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - *captionInterface = 0; - if (QAccessibleTableInterface *tableIface = tableInterface()) { - if (QAccessibleInterface *iface = tableIface->caption()) - *captionInterface = QWindowsAccessibility::wrap(iface); - } - return *captionInterface ? S_OK : S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnDescription( long column, BSTR *description) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - *description = 0; - if (QAccessibleTableInterface *tableIface = tableInterface()) { - const QString qtDesc = tableIface->columnDescription(column); - if (!qtDesc.isEmpty()) - *description = QStringToBSTR(qtDesc); - } - return *description ? S_OK : S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nColumns( long *columnCount) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleTableInterface *tableIface = tableInterface()) { - *columnCount = tableIface->columnCount(); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRows(long *rowCount) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleTableInterface *tableIface = tableInterface()) { - *rowCount = tableIface->rowCount(); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedCells(long *cellCount) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleTableInterface *tableIface = tableInterface()) { - *cellCount = tableIface->selectedCellCount(); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedColumns(long *columnCount) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleTableInterface *tableIface = tableInterface()) { - *columnCount = tableIface->selectedColumnCount(); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedRows(long *rowCount) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleTableInterface *tableIface = tableInterface()) { - *rowCount = tableIface->selectedRowCount(); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowDescription(long row, BSTR *description) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - *description = 0; - if (QAccessibleTableInterface *tableIface = tableInterface()) { - const QString qtDesc = tableIface->rowDescription(row); - if (!qtDesc.isEmpty()) - *description = QStringToBSTR(qtDesc); - } - return *description ? S_OK : S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedCells(IUnknown ***cells, long *nSelectedCells) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - Q_UNUSED(cells); - Q_UNUSED(nSelectedCells); - if (!accessible) - return E_FAIL; - - QList selectedCells = tableInterface()->selectedCells(); - return wrapListOfCells(selectedCells, cells, nSelectedCells); -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedColumns(long **selectedColumns, long *nColumns) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleTableInterface *tableIface = tableInterface()) { - const QList selectedIndices = tableIface->selectedColumns(); - const int count = selectedIndices.count(); - *nColumns = count; - *selectedColumns = nullptr; - if (count) { - *selectedColumns = coTaskMemAllocArray(count); - std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(), - QT_MAKE_CHECKED_ARRAY_ITERATOR(*selectedColumns, count)); - } - return count ? S_OK : S_FALSE; - } - return E_FAIL; - -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedRows(long **selectedRows, long *nRows) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleTableInterface *tableIface = tableInterface()) { - const QList selectedIndices = tableIface->selectedRows(); - const int count = selectedIndices.count(); - *nRows = count; - *selectedRows = nullptr; - if (count) { - *selectedRows = coTaskMemAllocArray(count); - std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(), - QT_MAKE_CHECKED_ARRAY_ITERATOR(*selectedRows, count)); - } - return count ? S_OK : S_FALSE; - } - return E_FAIL; - -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_summary(IUnknown **summaryInterface) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - *summaryInterface = 0; - if (QAccessibleTableInterface *tableIface = tableInterface()) { - if (QAccessibleInterface *iface = tableIface->summary()) - *summaryInterface = QWindowsAccessibility::wrap(iface); - } - return *summaryInterface ? S_OK : S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isColumnSelected(long column, boolean *isSelected) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleTableInterface *tableIface = tableInterface()) { - *isSelected = tableIface->isColumnSelected(column); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isRowSelected(long row, boolean *isSelected) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleTableInterface *tableIface = tableInterface()) { - *isSelected = tableIface->isRowSelected(row); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectRow(long row) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleTableInterface *tableIface = tableInterface()) { - bool ok = tableIface->selectRow(row); - return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails??? - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectColumn(long column) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleTableInterface *tableIface = tableInterface()) { - bool ok = tableIface->selectColumn(column); - return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails??? - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectRow(long row) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleTableInterface *tableIface = tableInterface()) { - bool ok = tableIface->unselectRow(row); - return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails??? - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectColumn(long column) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleTableInterface *tableIface = tableInterface()) { - bool ok = tableIface->unselectColumn(column); - return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails??? - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_modelChange( IA2TableModelChange * /*modelChange*/) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - return E_NOTIMPL; -} - -/**************************************************************\ - * IAccessibleTableCell * -\**************************************************************/ -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnExtent(long *nColumnsSpanned) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - *nColumnsSpanned = tableCellInterface()->columnExtent(); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnHeaderCells(IUnknown ***cellAccessibles, - long *nColumnHeaderCells) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - const QList headerCells = tableCellInterface()->columnHeaderCells(); - return wrapListOfCells(headerCells, cellAccessibles, nColumnHeaderCells); -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnIndex(long *columnIndex) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - *columnIndex = tableCellInterface()->columnIndex(); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowExtent(long *nRowsSpanned) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - *nRowsSpanned = tableCellInterface()->rowExtent(); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowHeaderCells(IUnknown ***cellAccessibles, - long *nRowHeaderCells) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - const QList headerCells = tableCellInterface()->rowHeaderCells(); - return wrapListOfCells(headerCells, cellAccessibles, nRowHeaderCells); -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowIndex(long *rowIndex) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - *rowIndex = tableCellInterface()->rowIndex(); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isSelected( boolean *isSelected) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - *isSelected = tableCellInterface()->isSelected(); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowColumnExtents(long *row, long *column, - long *rowExtents, long *columnExtents, - boolean *isSelected) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible || !tableCellInterface()) - return E_FAIL; - - *row = tableCellInterface()->rowIndex(); - *column = tableCellInterface()->columnIndex(); - *rowExtents = tableCellInterface()->rowExtent(); - *columnExtents = tableCellInterface()->columnExtent(); - *isSelected = tableCellInterface()->isSelected(); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_table(IUnknown **table) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - QAccessibleInterface *tableIface = tableCellInterface()->table(); - - *table = QWindowsAccessibility::wrap(tableIface); - return S_OK; -} - -/**************************************************************\ - * IAccessibleText * -\**************************************************************/ -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::addSelection(long startOffset, - long endOffset) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *text = textInterface()) { - text->addSelection(startOffset, endOffset); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(long offset, - long *startOffset, - long *endOffset, - BSTR *textAttributes) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *text = textInterface()) { - const QString attrs = text->attributes(offset, reinterpret_cast(startOffset), - reinterpret_cast(endOffset)); - *textAttributes = QStringToBSTR(attrs); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caretOffset(long *offset) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *text = textInterface()) { - *offset = text->cursorPosition(); - return S_OK; - } - return E_FAIL; -} - - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_characterExtents(long offset, - enum IA2CoordinateType coordType, - long *x, - long *y, - long *width, - long *height) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *text = textInterface()) { - QRect rect = text->characterRect(offset); - mapFromScreenPos(coordType, rect.topLeft(), x, y); - *width = rect.width(); - *height = rect.height(); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelections(long *nSelections) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *text = textInterface()) { - *nSelections = text->selectionCount(); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_offsetAtPoint(long x, - long y, - enum IA2CoordinateType coordType, - long *offset) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *text = textInterface()) { - QPoint screenPos = mapToScreenPos(coordType, x, y); - *offset = text->offsetAtPoint(screenPos); - return (*offset >=0 ? S_OK : S_FALSE); - } - return E_FAIL; - -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selection(long selectionIndex, - long *startOffset, - long *endOffset) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *text = textInterface()) { - text->selection(selectionIndex, reinterpret_cast(startOffset), - reinterpret_cast(endOffset)); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_text(long startOffset, - long endOffset, - BSTR *text) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *textif = textInterface()) { - const QString t = textif->text(startOffset, endOffset); - if (!t.isEmpty()) { - *text = QStringToBSTR(t); - return S_OK; - } - return E_INVALIDARG; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textBeforeOffset(long offset, - enum IA2TextBoundaryType boundaryType, - long *startOffset, - long *endOffset, - BSTR *text) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *textIface = textInterface()) { - const QString txt = - textIface->textBeforeOffset(offset, static_cast(boundaryType), - reinterpret_cast(startOffset), - reinterpret_cast(endOffset)); - if (!txt.isEmpty()) { - *text = QStringToBSTR(txt); - return S_OK; - } - return S_FALSE; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAfterOffset( - long offset, - enum IA2TextBoundaryType boundaryType, - long *startOffset, - long *endOffset, - BSTR *text) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *textIface = textInterface()) { - const QString txt = - textIface->textAfterOffset(offset, static_cast(boundaryType), - reinterpret_cast(startOffset), - reinterpret_cast(endOffset)); - if (!txt.isEmpty()) { - *text = QStringToBSTR(txt); - return S_OK; - } - return S_FALSE; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAtOffset(long offset, - enum IA2TextBoundaryType boundaryType, - long *startOffset, - long *endOffset, - BSTR *text) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *textIface = textInterface()) { - const QString txt = - textIface->textAtOffset(offset, static_cast(boundaryType), - reinterpret_cast(startOffset), - reinterpret_cast(endOffset)); - if (!txt.isEmpty()) { - *text = QStringToBSTR(txt); - return S_OK; - } - return S_FALSE; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::removeSelection(long selectionIndex) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *textIface = textInterface()) { - textIface->removeSelection(selectionIndex); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCaretOffset(long offset) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *textIface = textInterface()) { - textIface->setCursorPosition(offset); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setSelection(long selectionIndex, - long startOffset, - long endOffset) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *textIface = textInterface()) { - textIface->setSelection(selectionIndex, startOffset, endOffset); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nCharacters(long *nCharacters) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *textIface = textInterface()) { - *nCharacters = textIface->characterCount(); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringTo(long startIndex, - long endIndex, - enum IA2ScrollType scrollType) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (QAccessibleTextInterface *textIface = textInterface()) { - Q_UNUSED(scrollType); //### - textIface->scrollToSubstring(startIndex, endIndex); - return S_OK; - } - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringToPoint(long startIndex, - long endIndex, - enum IA2CoordinateType coordinateType, - long x, - long y) -{ - Q_UNUSED(startIndex); - Q_UNUSED(endIndex); - Q_UNUSED(coordinateType); - Q_UNUSED(x); - Q_UNUSED(y); - - return E_NOTIMPL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_newText(IA2TextSegment *newText) -{ - Q_UNUSED(newText); - return E_NOTIMPL; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_oldText(IA2TextSegment *oldText) -{ - Q_UNUSED(oldText); - return E_NOTIMPL; -} - -/**************************************************************\ - * IAccessibleValue * - **************************************************************/ -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_currentValue(VARIANT *currentValue) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - if (QAccessibleValueInterface *valueIface = valueInterface()) { - const QVariant var = valueIface->currentValue(); - if (QVariant2VARIANT(var, *currentValue, QByteArray(), false)) - return S_OK; - - } - currentValue->vt = VT_EMPTY; - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCurrentValue(VARIANT value) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - HRESULT hr = S_FALSE; - if (QAccessibleValueInterface *valueIface = valueInterface()) { - hr = VariantChangeType(&value, &value, 0, VT_R8); - if (SUCCEEDED(hr)) { - // ### works only for numbers (not date, strings, etc) - valueIface->setCurrentValue(QVariant(value.dblVal)); - } - } - return hr; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_maximumValue(VARIANT *maximumValue) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - if (QAccessibleValueInterface *valueIface = valueInterface()) { - const QVariant var = valueIface->maximumValue(); - if (QVariant2VARIANT(var, *maximumValue, QByteArray(), false)) - return S_OK; - } - maximumValue->vt = VT_EMPTY; - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_minimumValue(VARIANT *minimumValue) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - if (QAccessibleValueInterface *valueIface = valueInterface()) { - const QVariant var = valueIface->minimumValue(); - if (QVariant2VARIANT(var, *minimumValue, QByteArray(), false)) - return S_OK; - } - minimumValue->vt = VT_EMPTY; - return S_FALSE; -} - - -/**************************************************************\ - * IServiceProvider * - **************************************************************/ -/*! - \internal - Reimplemented from IServiceProvider -*/ -HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryService(REFGUID guidService, REFIID riid, void **iface) -{ - if (!iface) - return E_POINTER; - Q_UNUSED(guidService); - *iface = 0; - qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QS(): " << QWindowsAccessibleGuid(riid); - - - if (guidService == IID_IAccessible) { - if (riid == IID_IServiceProvider) { - // do not end up calling QueryInterface for IID_IServiceProvider - *iface = 0; - } else if (riid == IID_IAccessible || riid == IID_IUnknown || riid == IID_IDispatch) { - // The above conditions works with AccProbe and NVDA. - *iface = static_cast(this); - } else { - // According to _dicoveringInterfaces Discovery of Interfaces, we should really only - // enter here if riid == IID_IAccessible2, but some screen readers does not like that, - // and other servers seems to have realized that. (Chrome and Mozilla for instance, - // calls QueryInterface more or less in the same way) - - // For instance, accProbe discovers IID_IAccessibleTable2 by a QueryService only. - return QueryInterface(riid, iface); - } - } - - if (riid == IID_IAccessibleApplication) { - *iface = new AccessibleApplication; - return S_OK; - } - if (*iface) { - AddRef(); - return S_OK; - } - - return E_NOINTERFACE; -} - - -/*! - \internal - private function.. - \a maxRelations max number of relations to return in \a relations - \a relations the array of relations matching - \a startIndex Index to start to return from, - it will return only that specific relation in \a relations - - If \a relations is null, \a startIndex and \a maxRelations are ignored, causing - it to return the number of relations in \a nRelations -*/ -HRESULT QWindowsIA2Accessible::getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations /* = 0*/) -{ - QAccessibleInterface *accessible = accessibleInterface(); - if (nRelations) - *nRelations = 0; - typedef QPair RelationEntry; - QVector rels = accessible->relations(); - QMap relationMap; - for (QVector::const_iterator it = rels.constBegin(); it != rels.constEnd(); ++it) - { - RelationEntry e = *it; - relationMap.insertMulti(e.second, e.first); - } - - QList keys = relationMap.keys(); - const int numRelations = keys.count(); - if (relations) { - for (int i = startIndex; i < qMin(startIndex + int(maxRelations), numRelations); ++i) { - QAccessible::Relation relation = keys.at(i); - QList targets = relationMap.values(relation); - AccessibleRelation *rel = new AccessibleRelation(targets, relation); - *relations = rel; - ++relations; - } - } - if (nRelations) - *nRelations = numRelations; - - return numRelations > 0 ? S_OK : S_FALSE; -} - - - - -/*! - \internal - helper to wrap a QList inside an array of IAccessible* - The IAccessible* array is returned as a IUnknown* -*/ -HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList &inputCells, IUnknown ***outputAccessibles, long *nCellCount) -{ - const int count = inputCells.count(); - // Server allocates array - *nCellCount = count; - *outputAccessibles = nullptr; - if (count) { - *outputAccessibles = coTaskMemAllocArray(count); - std::transform(inputCells.constBegin(), inputCells.constEnd(), - QT_MAKE_CHECKED_ARRAY_ITERATOR(*outputAccessibles, count), - QWindowsAccessibility::wrap); - } - return count > 0 ? S_OK : S_FALSE; -} - -// Q_STATIC_ASSERT(IA2_ROLE_CANVAS == QAccessible::Canvas); // ### Qt 6: make them the same -Q_STATIC_ASSERT(IA2_ROLE_COLOR_CHOOSER == static_cast(QAccessible::ColorChooser)); -Q_STATIC_ASSERT(IA2_ROLE_FOOTER == static_cast(QAccessible::Footer)); -Q_STATIC_ASSERT(IA2_ROLE_FORM == static_cast(QAccessible::Form)); -Q_STATIC_ASSERT(IA2_ROLE_HEADING == static_cast(QAccessible::Heading)); -Q_STATIC_ASSERT(IA2_ROLE_NOTE == static_cast(QAccessible::Note)); -Q_STATIC_ASSERT(IA2_ROLE_COMPLEMENTARY_CONTENT == static_cast(QAccessible::ComplementaryContent)); - -QT_END_NAMESPACE - -#endif //QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h deleted file mode 100644 index e56106f247..0000000000 --- a/src/plugins/platforms/windows/accessible/iaccessible2.h +++ /dev/null @@ -1,358 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef IACCESSIBLE2_H -#define IACCESSIBLE2_H - -#include -#ifndef QT_NO_ACCESSIBILITY - -#include "qwindowscombase.h" -#include "qwindowsmsaaaccessible.h" -#include "comutils.h" - -#include "ia2_api_all.h" - -#include - -QT_BEGIN_NAMESPACE - -#ifdef Q_CC_MINGW -QT_WARNING_DISABLE_GCC("-Wunused-function") // MinGW 7.X claims it is unused -// MinGW's __uuidof operator does not work for the Accessible2 interfaces -template <> -IID qUuidOf() { return IID_IAccessibleComponent; } -#endif // Q_CC_MINGW - -class QWindowsIA2Accessible : public QWindowsMsaaAccessible, - public IAccessibleAction, - public IAccessibleComponent, - public IAccessibleEditableText, - public IAccessibleTable2, - public IAccessibleTableCell, - public IAccessibleText, - public IAccessibleValue, - public IServiceProvider -{ -public: - QWindowsIA2Accessible(QAccessibleInterface *a) : QWindowsMsaaAccessible(a) {} - - /* IUnknown */ - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - - /* IAccessible2 */ - HRESULT STDMETHODCALLTYPE get_nRelations(long *nRelations); - HRESULT STDMETHODCALLTYPE get_relation(long relationIndex, IAccessibleRelation **relation); - HRESULT STDMETHODCALLTYPE get_relations(long maxRelations, IAccessibleRelation **relations, long *nRelations); - HRESULT STDMETHODCALLTYPE role(long *role); - HRESULT STDMETHODCALLTYPE scrollTo(enum IA2ScrollType scrollType); - HRESULT STDMETHODCALLTYPE scrollToPoint(enum IA2CoordinateType coordinateType, long x, long y); - HRESULT STDMETHODCALLTYPE get_groupPosition(long *groupLevel, long *similarItemsInGroup, long *positionInGroup); - HRESULT STDMETHODCALLTYPE get_states(AccessibleStates *states); - HRESULT STDMETHODCALLTYPE get_extendedRole(BSTR *extendedRole); - HRESULT STDMETHODCALLTYPE get_localizedExtendedRole(BSTR *localizedExtendedRole); - HRESULT STDMETHODCALLTYPE get_nExtendedStates(long *nExtendedStates); - HRESULT STDMETHODCALLTYPE get_extendedStates(long maxExtendedStates, BSTR **extendedStates, long *nExtendedStates); - HRESULT STDMETHODCALLTYPE get_localizedExtendedStates(long maxLocalizedExtendedStates, BSTR **localizedExtendedStates, long *nLocalizedExtendedStates); - HRESULT STDMETHODCALLTYPE get_uniqueID(long *uniqueID); - HRESULT STDMETHODCALLTYPE get_windowHandle(HWND *windowHandle); - HRESULT STDMETHODCALLTYPE get_indexInParent(long *indexInParent); - HRESULT STDMETHODCALLTYPE get_locale(IA2Locale *locale); - HRESULT STDMETHODCALLTYPE get_attributes(BSTR *attributes); - - /* IAccessibleAction */ - HRESULT STDMETHODCALLTYPE nActions(long *nActions); - HRESULT STDMETHODCALLTYPE doAction(long actionIndex); - HRESULT STDMETHODCALLTYPE get_description(long actionIndex, BSTR *description); - HRESULT STDMETHODCALLTYPE get_keyBinding(long actionIndex, long nMaxBindings, BSTR **keyBindings, long *nBindings); - HRESULT STDMETHODCALLTYPE get_name(long actionIndex, BSTR *name); - HRESULT STDMETHODCALLTYPE get_localizedName(long actionIndex, BSTR *localizedName); - - /* IAccessibleComponent */ - HRESULT STDMETHODCALLTYPE get_locationInParent(long *x,long *y); - HRESULT STDMETHODCALLTYPE get_foreground(IA2Color *foreground); - HRESULT STDMETHODCALLTYPE get_background(IA2Color *background); - - /* IAccessibleEditableText */ - HRESULT STDMETHODCALLTYPE copyText(long startOffset, long endOffset); - HRESULT STDMETHODCALLTYPE deleteText(long startOffset, long endOffset); - HRESULT STDMETHODCALLTYPE insertText(long offset, BSTR *text); - HRESULT STDMETHODCALLTYPE cutText(long startOffset, long endOffset); - HRESULT STDMETHODCALLTYPE pasteText(long offset); - HRESULT STDMETHODCALLTYPE replaceText(long startOffset, long endOffset, BSTR *text); - HRESULT STDMETHODCALLTYPE setAttributes(long startOffset, long endOffset, BSTR *attributes); - - /* IAccessibleTable2 */ - HRESULT STDMETHODCALLTYPE get_cellAt( long row, long column, IUnknown **cell); - HRESULT STDMETHODCALLTYPE get_caption( IUnknown **accessibleInterface); - HRESULT STDMETHODCALLTYPE get_columnDescription( long column, BSTR *description); - HRESULT STDMETHODCALLTYPE get_nColumns( long *columnCount); - HRESULT STDMETHODCALLTYPE get_nRows( long *rowCount); - HRESULT STDMETHODCALLTYPE get_nSelectedCells( long *cellCount); - HRESULT STDMETHODCALLTYPE get_nSelectedColumns( long *columnCount); - HRESULT STDMETHODCALLTYPE get_nSelectedRows( long *rowCount); - HRESULT STDMETHODCALLTYPE get_rowDescription( long row, BSTR *description); - HRESULT STDMETHODCALLTYPE get_selectedCells( IUnknown ***cells, long *nSelectedCells); - HRESULT STDMETHODCALLTYPE get_selectedColumns( long **selectedColumns, long *nColumns); - HRESULT STDMETHODCALLTYPE get_selectedRows( long **selectedRows, long *nRows); - HRESULT STDMETHODCALLTYPE get_summary( IUnknown **accessibleInterface); - HRESULT STDMETHODCALLTYPE get_isColumnSelected( long column, boolean *isSelected); - HRESULT STDMETHODCALLTYPE get_isRowSelected( long row, boolean *isSelected); - HRESULT STDMETHODCALLTYPE selectRow( long row); - HRESULT STDMETHODCALLTYPE selectColumn( long column); - HRESULT STDMETHODCALLTYPE unselectRow( long row); - HRESULT STDMETHODCALLTYPE unselectColumn( long column); - HRESULT STDMETHODCALLTYPE get_modelChange( IA2TableModelChange *modelChange); - - /* IAccessibleTableCell */ - HRESULT STDMETHODCALLTYPE get_columnExtent(long *nColumnsSpanned); - HRESULT STDMETHODCALLTYPE get_columnHeaderCells(IUnknown ***cellAccessibles, long *nColumnHeaderCells); - HRESULT STDMETHODCALLTYPE get_columnIndex(long *columnIndex); - HRESULT STDMETHODCALLTYPE get_rowExtent(long *nRowsSpanned); - HRESULT STDMETHODCALLTYPE get_rowHeaderCells(IUnknown ***cellAccessibles, long *nRowHeaderCells); - HRESULT STDMETHODCALLTYPE get_rowIndex(long *rowIndex); - HRESULT STDMETHODCALLTYPE get_isSelected( boolean *isSelected); - HRESULT STDMETHODCALLTYPE get_rowColumnExtents(long *row, long *column, - long *rowExtents, long *columnExtents, - boolean *isSelected); - HRESULT STDMETHODCALLTYPE get_table(IUnknown **table); - - - /* IAccessibleText */ - HRESULT STDMETHODCALLTYPE addSelection(long startOffset, long endOffset); - HRESULT STDMETHODCALLTYPE get_attributes(long offset, long *startOffset, - long *endOffset, BSTR *textAttributes); - HRESULT STDMETHODCALLTYPE get_caretOffset(long *offset); - HRESULT STDMETHODCALLTYPE get_characterExtents(long offset, enum IA2CoordinateType coordType, - long *x, long *y, - long *width, long *height); - HRESULT STDMETHODCALLTYPE get_nSelections(long *nSelections); - HRESULT STDMETHODCALLTYPE get_offsetAtPoint(long x, long y, enum IA2CoordinateType coordType, long *offset); - HRESULT STDMETHODCALLTYPE get_selection(long selectionIndex, long *startOffset, long *endOffset); - HRESULT STDMETHODCALLTYPE get_text(long startOffset, long endOffset, BSTR *text); - HRESULT STDMETHODCALLTYPE get_textBeforeOffset(long offset, enum IA2TextBoundaryType boundaryType, - long *startOffset, long *endOffset, BSTR *text); - HRESULT STDMETHODCALLTYPE get_textAfterOffset(long offset, enum IA2TextBoundaryType boundaryType, - long *startOffset, long *endOffset, BSTR *text); - HRESULT STDMETHODCALLTYPE get_textAtOffset(long offset, enum IA2TextBoundaryType boundaryType, - long *startOffset, long *endOffset, BSTR *text); - HRESULT STDMETHODCALLTYPE removeSelection(long selectionIndex); - HRESULT STDMETHODCALLTYPE setCaretOffset(long offset); - HRESULT STDMETHODCALLTYPE setSelection(long selectionIndex, long startOffset, long endOffset); - HRESULT STDMETHODCALLTYPE get_nCharacters(long *nCharacters); - HRESULT STDMETHODCALLTYPE scrollSubstringTo(long startIndex, long endIndex, enum IA2ScrollType scrollType); - HRESULT STDMETHODCALLTYPE scrollSubstringToPoint(long startIndex, long endIndex, - enum IA2CoordinateType coordinateType, long x, long y); - HRESULT STDMETHODCALLTYPE get_newText(IA2TextSegment *newText); - HRESULT STDMETHODCALLTYPE get_oldText(IA2TextSegment *oldText); - - /* IAccessibleValue */ - HRESULT STDMETHODCALLTYPE get_currentValue(VARIANT *currentValue); - HRESULT STDMETHODCALLTYPE setCurrentValue(VARIANT value); - HRESULT STDMETHODCALLTYPE get_maximumValue(VARIANT *maximumValue); - HRESULT STDMETHODCALLTYPE get_minimumValue(VARIANT *minimumValue); - - /* IServiceProvider */ - HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppv); - - /* private helper functions */ -private: - inline QAccessibleTextInterface *textInterface() const { - QAccessibleInterface *accessible = accessibleInterface(); - return accessible ? accessible->textInterface() : static_cast(0); - } - - inline QAccessibleActionInterface *actionInterface() const { - QAccessibleInterface *accessible = accessibleInterface(); - return accessible->actionInterface(); - } - - inline QAccessibleValueInterface *valueInterface() const { - QAccessibleInterface *accessible = accessibleInterface(); - return accessible->valueInterface(); - } - - inline QAccessibleTableInterface *tableInterface() const { - QAccessibleInterface *accessible = accessibleInterface(); - return accessible->tableInterface(); - } - - inline QAccessibleTableCellInterface *tableCellInterface() const { - QAccessibleInterface *accessible = accessibleInterface(); - return accessible->tableCellInterface(); - } - - /*! - \internal - \a screenPos is in screen relative position - \a x and \y (out) is in parent relative position if coordType == IA2_COORDTYPE_PARENT_RELATIVE - */ - void mapFromScreenPos(enum IA2CoordinateType coordType, const QPoint &screenPos, long *x, long *y) const { - QAccessibleInterface *accessible = accessibleInterface(); - if (coordType == IA2_COORDTYPE_PARENT_RELATIVE) { - // caller wants relative to parent - if (QAccessibleInterface *parent = accessible->parent()) { - const QRect parentScreenRect = parent->rect(); - *x = parentScreenRect.x() - screenPos.x(); - *y = parentScreenRect.y() - screenPos.y(); - return; - } - } - *x = screenPos.x(); - *y = screenPos.y(); - } - - /*! - \internal - \a x and \y is in parent relative position if coordType == IA2_COORDTYPE_PARENT_RELATIVE - \return a screen relative position - */ - QPoint mapToScreenPos(enum IA2CoordinateType coordType, long x, long y) const { - QAccessibleInterface *accessible = accessibleInterface(); - if (coordType == IA2_COORDTYPE_PARENT_RELATIVE) { - if (QAccessibleInterface *parent = accessible->parent()) { - const QRect parentScreenRect = parent->rect(); - return QPoint(parentScreenRect.x() + x, parentScreenRect.y() + y); - } - } - return QPoint(x,y); - } - - HRESULT getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations = 0); - HRESULT wrapListOfCells(const QList &inputCells, IUnknown ***outputAccessibles, long *nCellCount); - QString textForRange(int startOffset, int endOffset) const; - void replaceTextFallback(long startOffset, long endOffset, const QString &txt); - -}; - -/**************************************************************\ - * AccessibleApplication * - **************************************************************/ - -#ifdef Q_CC_MINGW -// MinGW's __uuidof operator does not work for the IAccessible2 interfaces -template <> -IID qUuidOf() { return IID_IAccessibleApplication; } - -template <> -IID qUuidOf() { return IID_IAccessible2; } - -template <> -IID qUuidOf() { return IID_IAccessibleRelation; } -#endif // Q_CC_MINGW - -class AccessibleApplication : public QWindowsComBase -{ -public: - AccessibleApplication() {} - - virtual ~AccessibleApplication() {} - - /* IAccessibleApplication */ - HRESULT STDMETHODCALLTYPE get_appName(/* [retval][out] */ BSTR *name); - HRESULT STDMETHODCALLTYPE get_appVersion(/* [retval][out] */ BSTR *version); - HRESULT STDMETHODCALLTYPE get_toolkitName(/* [retval][out] */ BSTR *name); - HRESULT STDMETHODCALLTYPE get_toolkitVersion(/* [retval][out] */ BSTR *version); -}; - - - -/**************************************************************\ - * AccessibleRelation * - **************************************************************/ - - - -class AccessibleRelation : public QWindowsComBase -{ -public: - AccessibleRelation(const QList &targets, - QAccessible::Relation relation); - - virtual ~AccessibleRelation() {} - - /* IAccessibleRelation */ - HRESULT STDMETHODCALLTYPE get_relationType(BSTR *relationType); - HRESULT STDMETHODCALLTYPE get_localizedRelationType(BSTR *localizedRelationType); - HRESULT STDMETHODCALLTYPE get_nTargets(long *nTargets); - HRESULT STDMETHODCALLTYPE get_target(long targetIndex, IUnknown **target); - HRESULT STDMETHODCALLTYPE get_targets(long maxTargets, IUnknown **targets, long *nTargets); - -private: - static BSTR relationToBSTR(QAccessible::Relation relation) - { - const wchar_t *constRelationString = 0; - switch (relation) { - case QAccessible::Label: - constRelationString = IA2_RELATION_LABEL_FOR; - break; - case QAccessible::Labelled: - constRelationString = IA2_RELATION_LABELLED_BY; - break; - case QAccessible::Controller: - constRelationString = IA2_RELATION_CONTROLLER_FOR; - break; - case QAccessible::Controlled: - constRelationString = IA2_RELATION_CONTROLLED_BY; - break; - case QAccessible::AllRelations: - constRelationString = ( L"AllRelations" ); - break; - } - - if (constRelationString) { - BSTR bstrVal; - const UINT wlen = (UINT)wcslen(constRelationString); - bstrVal = ::SysAllocStringLen(constRelationString, wlen); - return bstrVal; - } - return 0; - } - - - QList m_targets; - QAccessible::Relation m_relation; -}; - -QT_END_NAMESPACE - -#endif //QT_NO_ACCESSIBILITY - -#endif // IACCESSIBLE2_H diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp deleted file mode 100644 index e214d47137..0000000000 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#ifndef QT_NO_ACCESSIBILITY - - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // registry helper - -#include "qwindowsaccessibility.h" -#include "iaccessible2.h" -#include "comutils.h" - -#include - -//#include -#ifndef UiaRootObjectId -#define UiaRootObjectId -25 -#endif - -#include -#if !defined(WINABLEAPI) -# include -#endif - -#include -#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU) -#include -#endif - -#include - -QT_BEGIN_NAMESPACE - -/*! - \!internal - \class QWindowsAccessibility - - Implements QPlatformAccessibility - -*/ -QWindowsAccessibility::QWindowsAccessibility() -{ -} - -// Retrieve sound name by checking the icon property of a message box -static inline QString messageBoxAlertSound(const QObject *messageBox) -{ - enum MessageBoxIcon { // Keep in sync with QMessageBox::Icon - Information = 1, - Warning = 2, - Critical = 3 - }; - switch (messageBox->property("icon").toInt()) { - case Information: - return QStringLiteral("SystemAsterisk"); - case Warning: - return QStringLiteral("SystemExclamation"); - case Critical: - return QStringLiteral("SystemHand"); - } - return QString(); -} - -static QString soundFileName(const QString &soundName) -{ - const QString key = QStringLiteral("AppEvents\\Schemes\\Apps\\.Default\\") - + soundName + QStringLiteral("\\.Current"); - return QWindowsFontDatabase::readRegistryString(HKEY_CURRENT_USER, - reinterpret_cast(key.utf16()), L""); -} - -void QWindowsAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event) -{ - QString soundName; - switch (event->type()) { - case QAccessible::PopupMenuStart: - soundName = QLatin1String("MenuPopup"); - break; - - case QAccessible::MenuCommand: - soundName = QLatin1String("MenuCommand"); - break; - - case QAccessible::Alert: - soundName = event->object()->inherits("QMessageBox") ? - messageBoxAlertSound(event->object()) : QStringLiteral("SystemAsterisk"); - break; - default: - break; - } - - if (!soundName.isEmpty() && !soundFileName(soundName).isEmpty()) { - PlaySound(reinterpret_cast(soundName.utf16()), 0, - SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT); - } - - // An event has to be associated with a window, - // so find the first parent that is a widget and that has a WId - QAccessibleInterface *iface = event->accessibleInterface(); - if (!isActive() || !iface || !iface->isValid()) - return; - QWindow *window = QWindowsAccessibility::windowHelper(iface); - - if (!window) { - window = QGuiApplication::focusWindow(); - if (!window) - return; - } - - QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface(); - if (!window->handle()) // Called before show(), no native window yet. - return; - const HWND hWnd = reinterpret_cast(platform->nativeResourceForWindow("handle", window)); - - if (event->type() != QAccessible::MenuCommand && // MenuCommand is faked - event->type() != QAccessible::ObjectDestroyed) { - ::NotifyWinEvent(event->type(), hWnd, OBJID_CLIENT, QAccessible::uniqueId(iface)); - } -} - -QWindow *QWindowsAccessibility::windowHelper(const QAccessibleInterface *iface) -{ - QWindow *window = iface->window(); - if (!window) { - QAccessibleInterface *acc = iface->parent(); - while (acc && acc->isValid() && !window) { - window = acc->window(); - QAccessibleInterface *par = acc->parent(); - acc = par; - } - } - return window; -} - -/*! - \internal - helper to wrap a QAccessibleInterface inside a IAccessible* -*/ -IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) -{ - if (!acc) - return 0; - - // ### FIXME: maybe we should accept double insertions into the cache - if (!QAccessible::uniqueId(acc)) - QAccessible::registerAccessibleInterface(acc); - - QWindowsIA2Accessible *wacc = new QWindowsIA2Accessible(acc); - IAccessible *iacc = 0; - wacc->QueryInterface(IID_IAccessible, reinterpret_cast(&iacc)); - return iacc; -} - -bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult) -{ - if (static_cast(lParam) == static_cast(UiaRootObjectId)) { - /* For UI Automation */ - } else if (DWORD(lParam) == DWORD(OBJID_CLIENT)) { - // Start handling accessibility internally - QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true); - // Ignoring all requests while starting up - // ### Maybe QPA takes care of this??? - if (QCoreApplication::startingUp() || QCoreApplication::closingDown()) - return false; - - typedef LRESULT (WINAPI *PtrLresultFromObject)(REFIID, WPARAM, LPUNKNOWN); - static PtrLresultFromObject ptrLresultFromObject = 0; - static bool oleaccChecked = false; - - if (!oleaccChecked) { - oleaccChecked = true; - ptrLresultFromObject = reinterpret_cast(QSystemLibrary::resolve(QLatin1String("oleacc"), "LresultFromObject")); - } - - if (ptrLresultFromObject) { - QWindow *window = QWindowsContext::instance()->findWindow(hwnd); - if (window) { - QAccessibleInterface *acc = window->accessibleRoot(); - if (acc) { - if (IAccessible *iface = wrap(acc)) { - *lResult = ptrLresultFromObject(IID_IAccessible, wParam, iface); // ref == 2 - if (*lResult) { - iface->Release(); // the client will release the object again, and then it will destroy itself - } - return true; - } - } - } - } - } - return false; -} - -QT_END_NAMESPACE - -#endif //QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h deleted file mode 100644 index 8621e93120..0000000000 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWINDOWSACCESSIBILITY_H -#define QWINDOWSACCESSIBILITY_H - -#include "../qtwindowsglobal.h" -#include "../qwindowscontext.h" -#include - -#include - -QT_BEGIN_NAMESPACE - -class QWindowsAccessibility : public QPlatformAccessibility -{ -public: - QWindowsAccessibility(); - static bool handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult); - void notifyAccessibilityUpdate(QAccessibleEvent *event) override; - static IAccessible *wrap(QAccessibleInterface *acc); - static QWindow *windowHelper(const QAccessibleInterface *iface); -}; - -QT_END_NAMESPACE - -#endif // QWINDOWSACCESSIBILITY_H diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp deleted file mode 100644 index 47b179250a..0000000000 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ /dev/null @@ -1,1223 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#ifndef QT_NO_ACCESSIBILITY - -#include "qwindowsmsaaaccessible.h" -#include "qwindowsaccessibility.h" -#include "qwindowscombase.h" -#include -#include -#include -#include "comutils.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -//#include -#ifndef UiaRootObjectId -#define UiaRootObjectId -25 -#endif - -#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU) -#include -#endif - - -#include - - -QT_BEGIN_NAMESPACE - -class QWindowsEnumerate : public QWindowsComBase -{ -public: - QWindowsEnumerate(const QVector &a) : QWindowsComBase(0), current(0),array(a) {} - virtual ~QWindowsEnumerate() {} - - HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT **ppEnum); - HRESULT STDMETHODCALLTYPE Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched); - HRESULT STDMETHODCALLTYPE Reset(); - HRESULT STDMETHODCALLTYPE Skip(unsigned long celt); - -private: - ULONG current; - QVector array; -}; - -HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Clone(IEnumVARIANT **ppEnum) -{ - QWindowsEnumerate *penum = 0; - *ppEnum = 0; - - penum = new QWindowsEnumerate(array); - if (!penum) - return E_OUTOFMEMORY; - penum->current = current; - penum->array = array; - penum->AddRef(); - *ppEnum = penum; - - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched) -{ - if (pCeltFetched) - *pCeltFetched = 0; - - ULONG l; - for (l = 0; l < celt; l++) { - VariantInit(&rgVar[l]); - if (current + 1 > ULONG(array.size())) { - *pCeltFetched = l; - return S_FALSE; - } - - rgVar[l].vt = VT_I4; - rgVar[l].lVal = array[int(current)]; - ++current; - } - *pCeltFetched = l; - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Reset() -{ - current = 0; - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Skip(unsigned long celt) -{ - current += celt; - if (current > ULONG(array.size())) { - current = ULONG(array.size()); - return S_FALSE; - } - return S_OK; -} - -#if defined(DEBUG_SHOW_ATCLIENT_COMMANDS) -void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleInterface *iface) -{ - qCDebug(lcQpaAccessibility) << iface << funcName; -} -#endif - -/**************************************************************\ - * * - * IUnknown * - * * - **************************************************************/ -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::QueryInterface(REFIID id, LPVOID *iface) -{ - *iface = nullptr; - const bool result = qWindowsComQueryUnknownInterfaceMulti(this, id, iface) - || qWindowsComQueryInterface(this, id, iface) - || qWindowsComQueryInterface(this, id, iface) - || qWindowsComQueryInterface(this, id, iface); - - if (result) { - qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QI() - " - << QWindowsAccessibleGuid(id) << ", iface:" << accessibleInterface(); - } - return result ? S_OK : E_NOINTERFACE; -} - -ULONG STDMETHODCALLTYPE QWindowsMsaaAccessible::AddRef() -{ - return ++ref; -} - -ULONG STDMETHODCALLTYPE QWindowsMsaaAccessible::Release() -{ - if (!--ref) { - delete this; - return 0; - } - return ref; -} - - -/* - IDispatch -*/ - -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetTypeInfoCount(unsigned int * pctinfo) -{ - // We don't use a type library - *pctinfo = 0; - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetTypeInfo(unsigned int, unsigned long, ITypeInfo **pptinfo) -{ - // We don't use a type library - *pptinfo = 0; - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetIDsOfNames(const _GUID &, wchar_t **rgszNames, unsigned int, unsigned long, long *rgdispid) -{ -#if !defined(Q_CC_BOR) && !defined(Q_CC_GNU) - // PROPERTIES: Hierarchical - if (_bstr_t(rgszNames[0]) == _bstr_t(L"accParent")) - rgdispid[0] = DISPID_ACC_PARENT; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accChildCount")) - rgdispid[0] = DISPID_ACC_CHILDCOUNT; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accChild")) - rgdispid[0] = DISPID_ACC_CHILD; - - // PROPERTIES: Descriptional - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accName(")) - rgdispid[0] = DISPID_ACC_NAME; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accValue")) - rgdispid[0] = DISPID_ACC_VALUE; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accDescription")) - rgdispid[0] = DISPID_ACC_DESCRIPTION; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accRole")) - rgdispid[0] = DISPID_ACC_ROLE; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accState")) - rgdispid[0] = DISPID_ACC_STATE; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accHelp")) - rgdispid[0] = DISPID_ACC_HELP; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accHelpTopic")) - rgdispid[0] = DISPID_ACC_HELPTOPIC; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accKeyboardShortcut")) - rgdispid[0] = DISPID_ACC_KEYBOARDSHORTCUT; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accFocus")) - rgdispid[0] = DISPID_ACC_FOCUS; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accSelection")) - rgdispid[0] = DISPID_ACC_SELECTION; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accDefaultAction")) - rgdispid[0] = DISPID_ACC_DEFAULTACTION; - - // METHODS - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accSelect")) - rgdispid[0] = DISPID_ACC_SELECT; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accLocation")) - rgdispid[0] = DISPID_ACC_LOCATION; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accNavigate")) - rgdispid[0] = DISPID_ACC_NAVIGATE; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accHitTest")) - rgdispid[0] = DISPID_ACC_HITTEST; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accDoDefaultAction")) - rgdispid[0] = DISPID_ACC_DODEFAULTACTION; - else - return DISP_E_UNKNOWNINTERFACE; - - return S_OK; -#else - Q_UNUSED(rgszNames); - Q_UNUSED(rgdispid); - - return DISP_E_MEMBERNOTFOUND; -#endif -} - -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::Invoke(long dispIdMember, - const _GUID &, - unsigned long, - unsigned short wFlags, - tagDISPPARAMS *pDispParams, - tagVARIANT *pVarResult, - tagEXCEPINFO *, unsigned int *) -{ - HRESULT hr = DISP_E_MEMBERNOTFOUND; - - switch (dispIdMember) - { - case DISPID_ACC_PARENT: - if (wFlags == DISPATCH_PROPERTYGET) { - if (!pVarResult) - return E_INVALIDARG; - hr = get_accParent(&pVarResult->pdispVal); - } else { - hr = DISP_E_MEMBERNOTFOUND; - } - break; - - case DISPID_ACC_CHILDCOUNT: - if (wFlags == DISPATCH_PROPERTYGET) { - if (!pVarResult) - return E_INVALIDARG; - hr = get_accChildCount(&pVarResult->lVal); - } else { - hr = DISP_E_MEMBERNOTFOUND; - } - break; - - case DISPID_ACC_CHILD: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accChild(pDispParams->rgvarg[0], &pVarResult->pdispVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_NAME: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accName(pDispParams->rgvarg[0], &pVarResult->bstrVal); - else if (wFlags == DISPATCH_PROPERTYPUT) - hr = put_accName(pDispParams->rgvarg[0], pVarResult->bstrVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_VALUE: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accValue(pDispParams->rgvarg[0], &pVarResult->bstrVal); - else if (wFlags == DISPATCH_PROPERTYPUT) - hr = put_accValue(pDispParams->rgvarg[0], pVarResult->bstrVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_DESCRIPTION: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accDescription(pDispParams->rgvarg[0], &pVarResult->bstrVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_ROLE: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accRole(pDispParams->rgvarg[0], pVarResult); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_STATE: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accState(pDispParams->rgvarg[0], pVarResult); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_HELP: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accHelp(pDispParams->rgvarg[0], &pVarResult->bstrVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_HELPTOPIC: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accHelpTopic(&pDispParams->rgvarg[2].bstrVal, pDispParams->rgvarg[1], &pDispParams->rgvarg[0].lVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_KEYBOARDSHORTCUT: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accKeyboardShortcut(pDispParams->rgvarg[0], &pVarResult->bstrVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_FOCUS: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accFocus(pVarResult); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_SELECTION: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accSelection(pVarResult); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_DEFAULTACTION: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accDefaultAction(pDispParams->rgvarg[0], &pVarResult->bstrVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_SELECT: - if (wFlags == DISPATCH_METHOD) - hr = accSelect(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0]); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_LOCATION: - if (wFlags == DISPATCH_METHOD) - hr = accLocation(&pDispParams->rgvarg[4].lVal, &pDispParams->rgvarg[3].lVal, &pDispParams->rgvarg[2].lVal, &pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0]); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_NAVIGATE: - if (wFlags == DISPATCH_METHOD) - hr = accNavigate(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0], pVarResult); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_HITTEST: - if (wFlags == DISPATCH_METHOD) - hr = accHitTest(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0].lVal, pVarResult); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_DODEFAULTACTION: - if (wFlags == DISPATCH_METHOD) - hr = accDoDefaultAction(pDispParams->rgvarg[0]); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - default: - hr = DISP_E_MEMBERNOTFOUND; - break; - } - - if (!SUCCEEDED(hr)) { - return hr; - } - return hr; -} - -/* - IAccessible - -IAccessible::accHitTest documents the value returned in pvarID like this: - -| *Point location* | *vt member* | *Value member* | -+========================================================+=============+=========================+ -| Outside of the object's boundaries, and either inside | VT_EMPTY | None. | -| or outside of the object's bounding rectangle. | | | -+--------------------------------------------------------+-------------+-------------------------+ -| Within the object but not within a child element or a | VT_I4 | lVal is CHILDID_SELF | -| child object. | | | -+--------------------------------------------------------+-------------+-------------------------+ -| Within a child element. | VT_I4 | lVal contains | -| | | the child ID. | -+--------------------------------------------------------+-------------+-------------------------+ -| Within a child object. | VT_DISPATCH | pdispVal is set to the | -| | | child object's IDispatch| -| | | interface pointer | -+--------------------------------------------------------+-------------+-------------------------+ -*/ -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - const QPoint pos = QHighDpi::fromNativeLocalPosition(QPoint(xLeft, yTop), - QWindowsAccessibility::windowHelper(accessible)); - QAccessibleInterface *child = accessible->childAt(pos.x(), pos.y()); - if (child == 0) { - // no child found, return this item if it contains the coordinates - if (accessible->rect().contains(xLeft, yTop)) { - (*pvarID).vt = VT_I4; - (*pvarID).lVal = CHILDID_SELF; - return S_OK; - } - } else { - IAccessible *iface = QWindowsAccessibility::wrap(child); - if (iface) { - (*pvarID).vt = VT_DISPATCH; - (*pvarID).pdispVal = iface; - return S_OK; - } - } - - // Did not find anything - (*pvarID).vt = VT_EMPTY; - return S_FALSE; -} - -/* - It is recommended to read - "Implementing a Microsoft Active Accessibility (MSAA) Server. - Practical Tips for Developers and How Mozilla Does It" - (https://developer.mozilla.org/En/Accessibility/Implementing_an_MSAA_Server) - - to get an overview of what's important to implement and what parts of MSAA - can be ignored. All stuff prefixed with "moz" are information from that page. -*/ -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - QAccessibleInterface *acc = childPointer(accessible, varID); - if (!acc || !acc->isValid()) - return E_FAIL; - const QRect rect = QHighDpi::toNativePixels(acc->rect(), - QWindowsAccessibility::windowHelper(accessible)); - - *pxLeft = rect.x(); - *pyTop = rect.y(); - *pcxWidth = rect.width(); - *pcyHeight = rect.height(); - - return S_OK; -} - -// moz: [important, but no need to implement up/down/left/right] -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - QAccessibleInterface *acc = 0; - switch (navDir) { - case NAVDIR_FIRSTCHILD: - acc = accessible->child(0); - break; - case NAVDIR_LASTCHILD: - acc = accessible->child(accessible->childCount() - 1); - break; - case NAVDIR_NEXT: - case NAVDIR_PREVIOUS: - if (!varStart.lVal){ - QAccessibleInterface *parent = accessible->parent(); - if (parent && parent->isValid()) { - int index = parent->indexOfChild(accessible); - index += (navDir == NAVDIR_NEXT) ? 1 : -1; - if (index >= 0 && index < parent->childCount()) - acc = parent->child(index); - } - } else { - int index = varStart.lVal; - index += (navDir == NAVDIR_NEXT) ? 1 : -1; - if (index > 0 && index <= accessible->childCount()) - acc = accessible->child(index - 1); - } - break; - - // Geometrical - case NAVDIR_UP: - case NAVDIR_DOWN: - case NAVDIR_LEFT: - case NAVDIR_RIGHT: { - QAccessibleInterface *pIface = accessible->parent(); - if (pIface && pIface->isValid()) { - const int indexOfOurself = pIface->indexOfChild(accessible); - QRect startg = accessible->rect(); - QPoint startc = startg.center(); - QAccessibleInterface *candidate = 0; - unsigned mindist = UINT_MAX; // will work on screen sizes at least up to 46340x46340 - const int sibCount = pIface->childCount(); - for (int i = 0; i < sibCount; ++i) { - QAccessibleInterface *sibling = 0; - sibling = pIface->child(i); - Q_ASSERT(sibling); - if (i == indexOfOurself || sibling->state().invisible) { - //ignore ourself and invisible siblings - continue; - } - - QRect sibg = sibling->rect(); - QPoint sibc = sibg.center(); - QPoint sibp; - QPoint startp; - QPoint distp; - switch (navDir) { - case NAVDIR_LEFT: - startp = QPoint(startg.left(), startg.top() + startg.height() / 2); - sibp = QPoint(sibg.right(), sibg.top() + sibg.height() / 2); - if (QPoint(sibc - startc).x() >= 0) { - continue; - } - distp = sibp - startp; - break; - case NAVDIR_RIGHT: - startp = QPoint(startg.right(), startg.top() + startg.height() / 2); - sibp = QPoint(sibg.left(), sibg.top() + sibg.height() / 2); - if (QPoint(sibc - startc).x() <= 0) { - continue; - } - distp = sibp - startp; - break; - case NAVDIR_UP: - startp = QPoint(startg.left() + startg.width() / 2, startg.top()); - sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.bottom()); - if (QPoint(sibc - startc).y() >= 0) { - continue; - } - distp = sibp - startp; - break; - case NAVDIR_DOWN: - startp = QPoint(startg.left() + startg.width() / 2, startg.bottom()); - sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.top()); - if (QPoint(sibc - startc).y() <= 0) { - continue; - } - distp = sibp - startp; - break; - default: - break; - } - - // Since we're *comparing* (and not measuring) distances, we can compare the - // squared distance, (thus, no need to take the sqrt()). - unsigned dist = distp.x() * distp.x() + distp.y() * distp.y(); - if (dist < mindist) { - candidate = sibling; - mindist = dist; - } - } - acc = candidate; - } - } - break; - default: - break; - } - if (!acc) { - (*pvarEnd).vt = VT_EMPTY; - return S_FALSE; - } - - if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) { - (*pvarEnd).vt = VT_DISPATCH; - (*pvarEnd).pdispVal = iface; - return S_OK; - } - - (*pvarEnd).vt = VT_EMPTY; - return S_FALSE; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChild(VARIANT varChildID, IDispatch** ppdispChild) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (varChildID.vt != VT_I4) - return E_INVALIDARG; - - QAccessibleInterface *acc = childPointer(accessible, varChildID); - if (acc && acc->isValid()) { - *ppdispChild = QWindowsAccessibility::wrap(acc); - return S_OK; - } - - return E_FAIL; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChildCount(long* pcountChildren) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - *pcountChildren = accessible->childCount(); - return S_OK; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accParent(IDispatch** ppdispParent) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - QAccessibleInterface *acc = accessible->parent(); - if (acc) { - if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) { - *ppdispParent = iface; - return S_OK; - } - } - - *ppdispParent = 0; - return S_FALSE; -} - -/* - Properties and methods -*/ -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accDoDefaultAction(VARIANT varID) -{ - Q_UNUSED(varID); - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) { - const QString def = actionIface->actionNames().value(0); - if (!def.isEmpty()) { - actionIface->doAction(def); - return S_OK; - } - } - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction) -{ - Q_UNUSED(varID); - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - *pszDefaultAction = 0; - if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) { - const QString def = actionIface->actionNames().value(0); - if (!def.isEmpty()) - *pszDefaultAction = QStringToBSTR(def); - } - return *pszDefaultAction ? S_OK : S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - - QString descr; - if (varID.lVal) { - QAccessibleInterface *child = childPointer(accessible, varID); - if (!child || !child->isValid()) - return E_FAIL; - descr = child->text(QAccessible::Description); - } else { - descr = accessible->text(QAccessible::Description); - } - if (descr.size()) { - *pszDescription = QStringToBSTR(descr); - return S_OK; - } - - *pszDescription = 0; - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accHelp(VARIANT varID, BSTR *pszHelp) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - QString help; - if (varID.lVal) { - QAccessibleInterface *child = childPointer(accessible, varID); - if (!child || !child->isValid()) - return E_FAIL; - help = child->text(QAccessible::Help); - } else { - help = accessible->text(QAccessible::Help); - } - if (help.size()) { - *pszHelp = QStringToBSTR(help); - return S_OK; - } - - *pszHelp = 0; - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accHelpTopic(BSTR *, VARIANT, long *) -{ - return DISP_E_MEMBERNOTFOUND; -} - -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut) -{ - Q_UNUSED(varID); - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - *pszKeyboardShortcut = 0; - if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) { - const QString def = actionIface->actionNames().value(0); - if (!def.isEmpty()) { - const QString keyBoardShortCut = actionIface->keyBindingsForAction(def).value(0); - if (!keyBoardShortCut.isEmpty()) - *pszKeyboardShortcut = QStringToBSTR(keyBoardShortCut); - } - } - return *pszKeyboardShortcut ? S_OK : S_FALSE; -} - -static QAccessibleInterface *relatedInterface(QAccessibleInterface *iface, QAccessible::RelationFlag flag) -{ - typedef QPair RelationPair; - QVector rels = iface->relations(flag); - - return rels.value(0).first; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accName(VARIANT varID, BSTR* pszName) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - QString name; - if (varID.lVal) { - QAccessibleInterface *child = childPointer(accessible, varID); - if (!child || !child->isValid()) - return E_FAIL; - name = child->text(QAccessible::Name); - if (name.isEmpty()) { - if (QAccessibleInterface *labelInterface = relatedInterface(child, QAccessible::Label)) { - name = labelInterface->text(QAccessible::Name); - } - } - } else { - name = accessible->text(QAccessible::Name); - if (name.isEmpty()) { - if (QAccessibleInterface *labelInterface = relatedInterface(accessible, QAccessible::Label)) { - name = labelInterface->text(QAccessible::Name); - } - } - } - - QString shortcut = accessible->text(QAccessible::Accelerator); - if (!shortcut.isEmpty()) - name += QLatin1Char(' ') + shortcut; - - if (name.size()) { - *pszName = QStringToBSTR(name); - return S_OK; - } - - *pszName = 0; - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accName(VARIANT, BSTR) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - return DISP_E_MEMBERNOTFOUND; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - QAccessible::Role role; - if (varID.lVal) { - QAccessibleInterface *child = childPointer(accessible, varID); - if (!child || !child->isValid()) - return E_FAIL; - role = child->role(); - } else { - role = accessible->role(); - } - - if (role != QAccessible::NoRole) { - if (role >= QAccessible::LayeredPane) { - // This block should hopefully only be entered if the AT client - // does not support IAccessible2, since it should prefer IA2::role() then. - if (role == QAccessible::LayeredPane) - role = QAccessible::Pane; - else if (role == QAccessible::WebDocument) - role = QAccessible::Document; - else - role = QAccessible::Client; - } - (*pvarRole).vt = VT_I4; - (*pvarRole).lVal = role; - } else { - (*pvarRole).vt = VT_EMPTY; - } - return S_OK; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accState(VARIANT varID, VARIANT *pvarState) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - QAccessible::State state; - if (varID.lVal) { - QAccessibleInterface *child = childPointer(accessible, varID); - if (!child || !child->isValid()) - return E_FAIL; - state = child->state(); - } else { - state = accessible->state(); - } - - LONG st = 0; - if (state.animated) - st |= STATE_SYSTEM_ANIMATED; - if (state.busy) - st |= STATE_SYSTEM_BUSY; - if (state.checked) - st |= STATE_SYSTEM_CHECKED; - if (state.collapsed) - st |= STATE_SYSTEM_COLLAPSED; - if (state.defaultButton) - st |= STATE_SYSTEM_DEFAULT; - if (state.expanded) - st |= STATE_SYSTEM_EXPANDED; - if (state.extSelectable) - st |= STATE_SYSTEM_EXTSELECTABLE; - if (state.focusable) - st |= STATE_SYSTEM_FOCUSABLE; - if (state.focused) - st |= STATE_SYSTEM_FOCUSED; - if (state.hasPopup) - st |= STATE_SYSTEM_HASPOPUP; - if (state.hotTracked) - st |= STATE_SYSTEM_HOTTRACKED; - if (state.invisible) - st |= STATE_SYSTEM_INVISIBLE; - if (state.linked) - st |= STATE_SYSTEM_LINKED; - if (state.marqueed) - st |= STATE_SYSTEM_MARQUEED; - if (state.checkStateMixed) - st |= STATE_SYSTEM_MIXED; - if (state.movable) - st |= STATE_SYSTEM_MOVEABLE; - if (state.multiSelectable) - st |= STATE_SYSTEM_MULTISELECTABLE; - if (state.offscreen) - st |= STATE_SYSTEM_OFFSCREEN; - if (state.pressed) - st |= STATE_SYSTEM_PRESSED; - if (state.passwordEdit) - st |= STATE_SYSTEM_PROTECTED; - if (state.readOnly) - st |= STATE_SYSTEM_READONLY; - if (state.selectable) - st |= STATE_SYSTEM_SELECTABLE; - if (state.selected) - st |= STATE_SYSTEM_SELECTED; - if (state.selfVoicing) - st |= STATE_SYSTEM_SELFVOICING; - if (state.sizeable) - st |= STATE_SYSTEM_SIZEABLE; - if (state.traversed) - st |= STATE_SYSTEM_TRAVERSED; - if (state.disabled) - st |= STATE_SYSTEM_UNAVAILABLE; - - (*pvarState).vt = VT_I4; - (*pvarState).lVal = st; - return S_OK; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accValue(VARIANT varID, BSTR* pszValue) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (varID.vt != VT_I4) - return E_INVALIDARG; - - if (!accessible || !accessible->isValid() || varID.lVal) { - return E_FAIL; - } - - QString value; - if (accessible->valueInterface()) { - value = accessible->valueInterface()->currentValue().toString(); - } else { - value = accessible->text(QAccessible::Value); - } - if (!value.isNull()) { - *pszValue = QStringToBSTR(value); - return S_OK; - } - - *pszValue = 0; - qCDebug(lcQpaAccessibility) << "return S_FALSE"; - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accValue(VARIANT, BSTR value) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - - if (!accessible || !accessible->isValid()) { - return E_FAIL; - } - - QString qstrValue = QString::fromWCharArray(value); - - if (accessible->valueInterface()) { - accessible->valueInterface()->setCurrentValue(qstrValue); - } else { - accessible->setText(QAccessible::Value, qstrValue); - } - - return S_OK; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accSelect(long flagsSelect, VARIANT varID) -{ - Q_UNUSED(flagsSelect); - Q_UNUSED(varID); - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - bool res = false; - -/* - ### Check for accessibleTableInterface() or accessibleTextInterface() - - ### and if there are no ia2 interfaces we should do nothing?? - if (flagsSelect & SELFLAG_TAKEFOCUS) - res = accessible()->doAction(SetFocus, varID.lVal, QVariantList()); - if (flagsSelect & SELFLAG_TAKESELECTION) { - accessible()->doAction(ClearSelection, 0, QVariantList()); - res = accessible()->doAction(AddToSelection, varID.lVal, QVariantList()); - } - if (flagsSelect & SELFLAG_EXTENDSELECTION) - res = accessible()->doAction(ExtendSelection, varID.lVal, QVariantList()); - if (flagsSelect & SELFLAG_ADDSELECTION) - res = accessible()->doAction(AddToSelection, varID.lVal, QVariantList()); - if (flagsSelect & SELFLAG_REMOVESELECTION) - res = accessible()->doAction(RemoveSelection, varID.lVal, QVariantList()); -*/ - return res ? S_OK : S_FALSE; -} - -/*! - \internal - Can return: - - +-------------+------------------------------------------------------------------------------+ - | VT_EMPTY | None. Neither this object nor any of its children has the keyboard focus. | - +-------------+------------------------------------------------------------------------------+ - | VT_I4 | lVal is CHILDID_SELF. The object itself has the keyboard focus. | - +-------------+------------------------------------------------------------------------------+ - | VT_I4 | lVal contains the child ID of the child element that has the keyboard focus. | - +-------------+------------------------------------------------------------------------------+ - | VT_DISPATCH | pdispVal member is the address of the IDispatch interface for the child | - | | object that has the keyboard focus. | - +-------------+------------------------------------------------------------------------------+ - moz: [important] -*/ -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accFocus(VARIANT *pvarID) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - if (QAccessibleInterface *acc = accessible->focusChild()) { - if (acc == accessible) { - (*pvarID).vt = VT_I4; - (*pvarID).lVal = CHILDID_SELF; - return S_OK; - } else { - if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) { - (*pvarID).vt = VT_DISPATCH; - (*pvarID).pdispVal = iface; - return S_OK; - } - } - } - (*pvarID).vt = VT_EMPTY; - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accSelection(VARIANT *pvarChildren) -{ - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - int cc = accessible->childCount(); - QVector sel(cc); - int selIndex = 0; - for (int i = 0; i < cc; ++i) { - bool isSelected = false; - QAccessibleInterface *child = accessible->child(i); - if (child) { - isSelected = child->state().selected; - } - if (isSelected) - sel[selIndex++] = i+1; - } - sel.resize(selIndex); - if (sel.isEmpty()) { - (*pvarChildren).vt = VT_EMPTY; - return S_FALSE; - } - if (sel.size() == 1) { - (*pvarChildren).vt = VT_I4; - (*pvarChildren).lVal = sel[0]; - return S_OK; - } - IEnumVARIANT *iface = new QWindowsEnumerate(sel); - IUnknown *uiface; - iface->QueryInterface(IID_IUnknown, (void**)&uiface); - (*pvarChildren).vt = VT_UNKNOWN; - (*pvarChildren).punkVal = uiface; - - return S_OK; -} - -/**************************************************************\ - * IOleWindow * - **************************************************************/ -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetWindow(HWND *phwnd) -{ - *phwnd = 0; - QAccessibleInterface *accessible = accessibleInterface(); - accessibleDebugClientCalls(accessible); - if (!accessible) - return E_FAIL; - - QWindow *window = QWindowsAccessibility::windowHelper(accessible); - if (!window) - return E_FAIL; - - QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface(); - Q_ASSERT(platform); - *phwnd = (HWND)platform->nativeResourceForWindow("handle", window); - qCDebug(lcQpaAccessibility) << "QWindowsAccessible::GetWindow(): " << *phwnd; - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::ContextSensitiveHelp(BOOL) -{ - return S_OK; -} - -const char *QWindowsAccessibleGuid::iidToString(const GUID &id) -{ - const char *result = nullptr; - if (id == IID_IUnknown) - result = "IID_IUnknown"; - else if (id == IID_IDispatch) - result = "IID_IDispatch"; - else if (id == IID_IAccessible) - result = "IID_IAccessible"; - else if (id == IID_IOleWindow) - result = "IID_IOleWindow"; - else if (id == IID_IServiceProvider) - result = "IID_IServiceProvider"; - else if (id == IID_IAccessible2) - result = "IID_IAccessible2"; - else if (id == IID_IAccessibleAction) - result = "IID_IAccessibleAction"; - else if (id == IID_IAccessibleApplication) - result = "IID_IAccessibleApplication"; - else if (id == IID_IAccessibleComponent) - result = "IID_IAccessibleComponent"; - else if (id == IID_IAccessibleEditableText) - result = "IID_IAccessibleEditableText"; - else if (id == IID_IAccessibleHyperlink) - result = "IID_IAccessibleHyperlink"; - else if (id == IID_IAccessibleHypertext) - result = "IID_IAccessibleHypertext"; - else if (id == IID_IAccessibleImage) - result = "IID_IAccessibleImage"; - else if (id == IID_IAccessibleRelation) - result = "IID_IAccessibleRelation"; - else if (id == IID_IAccessibleTable) - result = "IID_IAccessibleTable"; - else if (id == IID_IAccessibleTable2) - result = "IID_IAccessibleTable2"; - else if (id == IID_IAccessibleTableCell) - result = "IID_IAccessibleTableCell"; - else if (id == IID_IAccessibleText) - result = "IID_IAccessibleText"; - else if (id == IID_IAccessibleValue) - result = "IID_IAccessibleValue"; - return result; -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug, const GUID &); - -QDebug operator<<(QDebug d, const QWindowsAccessibleGuid &aguid) -{ - QDebugStateSaver saver(d); - d.nospace(); - if (const char *ids = QWindowsAccessibleGuid::iidToString(aguid.guid())) - d << ids; - else - d << aguid.guid(); - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -QT_END_NAMESPACE - -#endif //QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h deleted file mode 100644 index e654f262da..0000000000 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h +++ /dev/null @@ -1,177 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef QWINDOWSMSAAACCESSIBLE_H -#define QWINDOWSMSAAACCESSIBLE_H - -#include -#ifndef QT_NO_ACCESSIBILITY -#include - -#include -#include -#include -#include -#include "ia2_api_all.h" // IAccessible2 inherits from IAccessible - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_DEBUG_OUTPUT -#define DEBUG_SHOW_ATCLIENT_COMMANDS -#endif -#if defined(DEBUG_SHOW_ATCLIENT_COMMANDS) -void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleInterface *iface); -# define accessibleDebugClientCalls(iface) accessibleDebugClientCalls_helper(Q_FUNC_INFO, iface) -#else -# define accessibleDebugClientCalls(iface) -#endif - -QWindow *window_helper(const QAccessibleInterface *iface); - -class QWindowsAccessibleGuid // Helper for QDebug, outputs known ids by name. -{ -public: - explicit QWindowsAccessibleGuid(const GUID &g) : m_guid(g) {} - GUID guid () const { return m_guid; } - static const char *iidToString(const GUID &id); - -private: - GUID m_guid; -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const QWindowsAccessibleGuid &aguid); -#endif - -/**************************************************************\ - * QWindowsAccessible * - **************************************************************/ - -class QWindowsMsaaAccessible : public IAccessible2, public IOleWindow -{ -public: - QWindowsMsaaAccessible(QAccessibleInterface *a) - : ref(0) - { - id = QAccessible::uniqueId(a); - } - - virtual ~QWindowsMsaaAccessible() - { - } - - /* IUnknown */ - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - - /* IDispatch */ - HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int *); - HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int, unsigned long, ITypeInfo **); - HRESULT STDMETHODCALLTYPE GetIDsOfNames(const _GUID &, wchar_t **, unsigned int, unsigned long, long *); - HRESULT STDMETHODCALLTYPE Invoke(long, const _GUID &, unsigned long, unsigned short, tagDISPPARAMS *, tagVARIANT *, tagEXCEPINFO *, unsigned int *); - - /* IAccessible */ - HRESULT STDMETHODCALLTYPE accHitTest(long xLeft, long yTop, VARIANT *pvarID); - HRESULT STDMETHODCALLTYPE accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID); - HRESULT STDMETHODCALLTYPE accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd); - HRESULT STDMETHODCALLTYPE get_accChild(VARIANT varChildID, IDispatch** ppdispChild); - HRESULT STDMETHODCALLTYPE get_accChildCount(long* pcountChildren); - HRESULT STDMETHODCALLTYPE get_accParent(IDispatch** ppdispParent); - - HRESULT STDMETHODCALLTYPE accDoDefaultAction(VARIANT varID); - HRESULT STDMETHODCALLTYPE get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction); - HRESULT STDMETHODCALLTYPE get_accDescription(VARIANT varID, BSTR* pszDescription); - HRESULT STDMETHODCALLTYPE get_accHelp(VARIANT varID, BSTR *pszHelp); - HRESULT STDMETHODCALLTYPE get_accHelpTopic(BSTR *pszHelpFile, VARIANT varChild, long *pidTopic); - HRESULT STDMETHODCALLTYPE get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut); - HRESULT STDMETHODCALLTYPE get_accName(VARIANT varID, BSTR* pszName); - HRESULT STDMETHODCALLTYPE put_accName(VARIANT varChild, BSTR szName); - HRESULT STDMETHODCALLTYPE get_accRole(VARIANT varID, VARIANT *pvarRole); - HRESULT STDMETHODCALLTYPE get_accState(VARIANT varID, VARIANT *pvarState); - HRESULT STDMETHODCALLTYPE get_accValue(VARIANT varID, BSTR* pszValue); - HRESULT STDMETHODCALLTYPE put_accValue(VARIANT varChild, BSTR szValue); - - HRESULT STDMETHODCALLTYPE accSelect(long flagsSelect, VARIANT varID); - HRESULT STDMETHODCALLTYPE get_accFocus(VARIANT *pvarID); - HRESULT STDMETHODCALLTYPE get_accSelection(VARIANT *pvarChildren); - - /* IOleWindow */ - HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd); - HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); - -protected: - QAccessible::Id id; - - QAccessibleInterface *accessibleInterface() const - { - QAccessibleInterface *iface = QAccessible::accessibleInterface(id); - if (iface && iface->isValid()) - return iface; - return 0; - } - - static QAccessibleInterface *childPointer(QAccessibleInterface *parent, VARIANT varID) - { - // -1 since windows API always uses 1 for the first child - Q_ASSERT(parent); - - QAccessibleInterface *acc = 0; - int childIndex = varID.lVal; - if (childIndex == 0) { - // Yes, some AT clients (Active Accessibility Object Inspector) - // actually ask for the same object. As a consequence, we need to clone ourselves: - acc = parent; - } else if (childIndex < 0) { - acc = QAccessible::accessibleInterface((QAccessible::Id)childIndex); - } else { - acc = parent->child(childIndex - 1); - } - return acc; - } - -private: - ULONG ref; - -}; - -QT_END_NAMESPACE - -#endif //QT_NO_ACCESSIBILITY - -#endif // QWINDOWSMSAAACCESSIBLE_H -- cgit v1.2.3