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 --- src/platformsupport/platformsupport.pro | 1 + .../windowsuiautomation/qwindowsuiawrapper.cpp | 117 ++ .../windowsuiautomation/qwindowsuiawrapper_p.h | 100 ++ .../windowsuiautomation/uiaattributeids.h | 88 ++ .../windowsuiautomation/uiaclientinterfaces.h | 255 +++ .../windowsuiautomation/uiacontroltypeids.h | 85 + .../windowsuiautomation/uiaerrorids.h | 51 + .../windowsuiautomation/uiaeventids.h | 79 + .../windowsuiautomation/uiageneralids.h | 46 + .../windowsuiautomation/uiapatternids.h | 78 + .../windowsuiautomation/uiapropertyids.h | 212 +++ .../windowsuiautomation/uiaserverinterfaces.h | 352 +++++ src/platformsupport/windowsuiautomation/uiatypes.h | 145 ++ .../windowsuiautomation/windowsuiautomation.pro | 23 + .../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 --- src/plugins/platforms/windows/qwindowscontext.cpp | 5 +- src/plugins/platforms/windows/qwindowscontext.h | 1 + .../platforms/windows/qwindowsintegration.cpp | 4 +- .../uiautomation/qwindowsuiaaccessibility.cpp | 140 ++ .../uiautomation/qwindowsuiaaccessibility.h | 65 + .../uiautomation/qwindowsuiabaseprovider.cpp | 81 + .../windows/uiautomation/qwindowsuiabaseprovider.h | 78 + .../uiautomation/qwindowsuiagriditemprovider.cpp | 176 +++ .../uiautomation/qwindowsuiagriditemprovider.h | 71 + .../uiautomation/qwindowsuiagridprovider.cpp | 136 ++ .../windows/uiautomation/qwindowsuiagridprovider.h | 69 + .../uiautomation/qwindowsuiainvokeprovider.cpp | 84 + .../uiautomation/qwindowsuiainvokeprovider.h | 67 + .../uiautomation/qwindowsuiamainprovider.cpp | 638 ++++++++ .../windows/uiautomation/qwindowsuiamainprovider.h | 105 ++ .../uiautomation/qwindowsuiaprovidercache.cpp | 106 ++ .../uiautomation/qwindowsuiaprovidercache.h | 77 + .../uiautomation/qwindowsuiarangevalueprovider.cpp | 190 +++ .../uiautomation/qwindowsuiarangevalueprovider.h | 73 + .../qwindowsuiaselectionitemprovider.cpp | 201 +++ .../qwindowsuiaselectionitemprovider.h | 71 + .../uiautomation/qwindowsuiaselectionprovider.cpp | 147 ++ .../uiautomation/qwindowsuiaselectionprovider.h | 69 + .../uiautomation/qwindowsuiatableitemprovider.cpp | 129 ++ .../uiautomation/qwindowsuiatableitemprovider.h | 68 + .../uiautomation/qwindowsuiatableprovider.cpp | 154 ++ .../uiautomation/qwindowsuiatableprovider.h | 69 + .../uiautomation/qwindowsuiatextprovider.cpp | 261 ++++ .../windows/uiautomation/qwindowsuiatextprovider.h | 80 + .../uiautomation/qwindowsuiatextrangeprovider.cpp | 554 +++++++ .../uiautomation/qwindowsuiatextrangeprovider.h | 88 ++ .../uiautomation/qwindowsuiatoggleprovider.cpp | 105 ++ .../uiautomation/qwindowsuiatoggleprovider.h | 68 + .../windows/uiautomation/qwindowsuiautils.cpp | 221 +++ .../windows/uiautomation/qwindowsuiautils.h | 89 ++ .../uiautomation/qwindowsuiavalueprovider.cpp | 132 ++ .../uiautomation/qwindowsuiavalueprovider.h | 70 + .../windows/uiautomation/uiautomation.pri | 43 + src/plugins/platforms/windows/windows.pri | 4 +- sync.profile | 1 + tests/auto/other/qaccessibility/qaccessibility.pro | 5 +- .../other/qaccessibility/tst_qaccessibility.cpp | 281 +--- 65 files changed, 6497 insertions(+), 4280 deletions(-) create mode 100644 src/platformsupport/windowsuiautomation/qwindowsuiawrapper.cpp create mode 100644 src/platformsupport/windowsuiautomation/qwindowsuiawrapper_p.h create mode 100644 src/platformsupport/windowsuiautomation/uiaattributeids.h create mode 100644 src/platformsupport/windowsuiautomation/uiaclientinterfaces.h create mode 100644 src/platformsupport/windowsuiautomation/uiacontroltypeids.h create mode 100644 src/platformsupport/windowsuiautomation/uiaerrorids.h create mode 100644 src/platformsupport/windowsuiautomation/uiaeventids.h create mode 100644 src/platformsupport/windowsuiautomation/uiageneralids.h create mode 100644 src/platformsupport/windowsuiautomation/uiapatternids.h create mode 100644 src/platformsupport/windowsuiautomation/uiapropertyids.h create mode 100644 src/platformsupport/windowsuiautomation/uiaserverinterfaces.h create mode 100644 src/platformsupport/windowsuiautomation/uiatypes.h create mode 100644 src/platformsupport/windowsuiautomation/windowsuiautomation.pro 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 create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h create mode 100644 src/plugins/platforms/windows/uiautomation/uiautomation.pri diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro index 5549984d6a..4f2f56f01f 100644 --- a/src/platformsupport/platformsupport.pro +++ b/src/platformsupport/platformsupport.pro @@ -34,6 +34,7 @@ qtConfig(accessibility) { SUBDIRS += linuxaccessibility linuxaccessibility.depends += accessibility } + win32:!winrt: SUBDIRS += windowsuiautomation } darwin { diff --git a/src/platformsupport/windowsuiautomation/qwindowsuiawrapper.cpp b/src/platformsupport/windowsuiautomation/qwindowsuiawrapper.cpp new file mode 100644 index 0000000000..79541fe636 --- /dev/null +++ b/src/platformsupport/windowsuiautomation/qwindowsuiawrapper.cpp @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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 "qwindowsuiawrapper_p.h" +#include + +QT_BEGIN_NAMESPACE + +// private constructor +QWindowsUiaWrapper::QWindowsUiaWrapper() +{ + QSystemLibrary uiaLib(QStringLiteral("UIAutomationCore")); + if (uiaLib.load()) { + m_pUiaReturnRawElementProvider = reinterpret_cast(uiaLib.resolve("UiaReturnRawElementProvider")); + m_pUiaHostProviderFromHwnd = reinterpret_cast(uiaLib.resolve("UiaHostProviderFromHwnd")); + m_pUiaRaiseAutomationPropertyChangedEvent = reinterpret_cast(uiaLib.resolve("UiaRaiseAutomationPropertyChangedEvent")); + m_pUiaRaiseAutomationEvent = reinterpret_cast(uiaLib.resolve("UiaRaiseAutomationEvent")); + m_pUiaClientsAreListening = reinterpret_cast(uiaLib.resolve("UiaClientsAreListening")); + } +} + +QWindowsUiaWrapper::~QWindowsUiaWrapper() +{ +} + +// shared instance +QWindowsUiaWrapper *QWindowsUiaWrapper::instance() +{ + static QWindowsUiaWrapper wrapper; + return &wrapper; +} + +// True if all symbols resolved. +BOOL QWindowsUiaWrapper::ready() +{ + return m_pUiaReturnRawElementProvider + && m_pUiaHostProviderFromHwnd + && m_pUiaRaiseAutomationPropertyChangedEvent + && m_pUiaRaiseAutomationEvent + && m_pUiaClientsAreListening; +} + +BOOL QWindowsUiaWrapper::clientsAreListening() +{ + if (!m_pUiaClientsAreListening) + return FALSE; + return m_pUiaClientsAreListening(); +} + +LRESULT QWindowsUiaWrapper::returnRawElementProvider(HWND hwnd, WPARAM wParam, LPARAM lParam, IRawElementProviderSimple *el) +{ + if (!m_pUiaReturnRawElementProvider) + return static_cast(NULL); + return m_pUiaReturnRawElementProvider(hwnd, wParam, lParam, el); +} + +HRESULT QWindowsUiaWrapper::hostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **ppProvider) +{ + if (!m_pUiaHostProviderFromHwnd) + return UIA_E_NOTSUPPORTED; + return m_pUiaHostProviderFromHwnd(hwnd, ppProvider); +} + +HRESULT QWindowsUiaWrapper::raiseAutomationPropertyChangedEvent(IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue) +{ + if (!m_pUiaRaiseAutomationPropertyChangedEvent) + return UIA_E_NOTSUPPORTED; + return m_pUiaRaiseAutomationPropertyChangedEvent(pProvider, id, oldValue, newValue); +} + +HRESULT QWindowsUiaWrapper::raiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id) +{ + if (!m_pUiaRaiseAutomationEvent) + return UIA_E_NOTSUPPORTED; + return m_pUiaRaiseAutomationEvent(pProvider, id); +} + +QT_END_NAMESPACE + diff --git a/src/platformsupport/windowsuiautomation/qwindowsuiawrapper_p.h b/src/platformsupport/windowsuiautomation/qwindowsuiawrapper_p.h new file mode 100644 index 0000000000..f89640612e --- /dev/null +++ b/src/platformsupport/windowsuiautomation/qwindowsuiawrapper_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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 QWINDOWSUIAWRAPPER_H +#define QWINDOWSUIAWRAPPER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include "uiatypes.h" +#include "uiaattributeids.h" +#include "uiacontroltypeids.h" +#include "uiaerrorids.h" +#include "uiaeventids.h" +#include "uiageneralids.h" +#include "uiapatternids.h" +#include "uiapropertyids.h" +#include "uiaserverinterfaces.h" +#include "uiaclientinterfaces.h" + +QT_REQUIRE_CONFIG(accessibility); + +QT_BEGIN_NAMESPACE + +class QWindowsUiaWrapper +{ + QWindowsUiaWrapper(); + virtual ~QWindowsUiaWrapper(); +public: + static QWindowsUiaWrapper *instance(); + BOOL ready(); + BOOL clientsAreListening(); + LRESULT returnRawElementProvider(HWND hwnd, WPARAM wParam, LPARAM lParam, IRawElementProviderSimple *el); + HRESULT hostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **ppProvider); + HRESULT raiseAutomationPropertyChangedEvent(IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue); + HRESULT raiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id); + +private: + typedef LRESULT (WINAPI *PtrUiaReturnRawElementProvider)(HWND, WPARAM, LPARAM, IRawElementProviderSimple *); + typedef HRESULT (WINAPI *PtrUiaHostProviderFromHwnd)(HWND, IRawElementProviderSimple **); + typedef HRESULT (WINAPI *PtrUiaRaiseAutomationPropertyChangedEvent)(IRawElementProviderSimple *, PROPERTYID, VARIANT, VARIANT); + typedef HRESULT (WINAPI *PtrUiaRaiseAutomationEvent)(IRawElementProviderSimple *, EVENTID); + typedef BOOL (WINAPI *PtrUiaClientsAreListening)(); + PtrUiaReturnRawElementProvider m_pUiaReturnRawElementProvider = nullptr; + PtrUiaHostProviderFromHwnd m_pUiaHostProviderFromHwnd = nullptr; + PtrUiaRaiseAutomationPropertyChangedEvent m_pUiaRaiseAutomationPropertyChangedEvent = nullptr; + PtrUiaRaiseAutomationEvent m_pUiaRaiseAutomationEvent = nullptr; + PtrUiaClientsAreListening m_pUiaClientsAreListening = nullptr; +}; + +QT_END_NAMESPACE + +#endif //QWINDOWSUIAWRAPPER_H + diff --git a/src/platformsupport/windowsuiautomation/uiaattributeids.h b/src/platformsupport/windowsuiautomation/uiaattributeids.h new file mode 100644 index 0000000000..52e7306a67 --- /dev/null +++ b/src/platformsupport/windowsuiautomation/uiaattributeids.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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 UIAATTRIBUTEIDS_H +#define UIAATTRIBUTEIDS_H + +#define UIA_AnimationStyleAttributeId 40000 +#define UIA_BackgroundColorAttributeId 40001 +#define UIA_BulletStyleAttributeId 40002 +#define UIA_CapStyleAttributeId 40003 +#define UIA_CultureAttributeId 40004 +#define UIA_FontNameAttributeId 40005 +#define UIA_FontSizeAttributeId 40006 +#define UIA_FontWeightAttributeId 40007 +#define UIA_ForegroundColorAttributeId 40008 +#define UIA_HorizontalTextAlignmentAttributeId 40009 +#define UIA_IndentationFirstLineAttributeId 40010 +#define UIA_IndentationLeadingAttributeId 40011 +#define UIA_IndentationTrailingAttributeId 40012 +#define UIA_IsHiddenAttributeId 40013 +#define UIA_IsItalicAttributeId 40014 +#define UIA_IsReadOnlyAttributeId 40015 +#define UIA_IsSubscriptAttributeId 40016 +#define UIA_IsSuperscriptAttributeId 40017 +#define UIA_MarginBottomAttributeId 40018 +#define UIA_MarginLeadingAttributeId 40019 +#define UIA_MarginTopAttributeId 40020 +#define UIA_MarginTrailingAttributeId 40021 +#define UIA_OutlineStylesAttributeId 40022 +#define UIA_OverlineColorAttributeId 40023 +#define UIA_OverlineStyleAttributeId 40024 +#define UIA_StrikethroughColorAttributeId 40025 +#define UIA_StrikethroughStyleAttributeId 40026 +#define UIA_TabsAttributeId 40027 +#define UIA_TextFlowDirectionsAttributeId 40028 +#define UIA_UnderlineColorAttributeId 40029 +#define UIA_UnderlineStyleAttributeId 40030 +#define UIA_AnnotationTypesAttributeId 40031 +#define UIA_AnnotationObjectsAttributeId 40032 +#define UIA_StyleNameAttributeId 40033 +#define UIA_StyleIdAttributeId 40034 +#define UIA_LinkAttributeId 40035 +#define UIA_IsActiveAttributeId 40036 +#define UIA_SelectionActiveEndAttributeId 40037 +#define UIA_CaretPositionAttributeId 40038 +#define UIA_CaretBidiModeAttributeId 40039 +#define UIA_LineSpacingAttributeId 40040 +#define UIA_BeforeParagraphSpacingAttributeId 40041 +#define UIA_AfterParagraphSpacingAttributeId 40042 +#define UIA_SayAsInterpretAsAttributeId 40043 + +#endif diff --git a/src/platformsupport/windowsuiautomation/uiaclientinterfaces.h b/src/platformsupport/windowsuiautomation/uiaclientinterfaces.h new file mode 100644 index 0000000000..b95c05f6a4 --- /dev/null +++ b/src/platformsupport/windowsuiautomation/uiaclientinterfaces.h @@ -0,0 +1,255 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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 UIACLIENTINTERFACES_H +#define UIACLIENTINTERFACES_H + +#include + +#ifndef __IUIAutomationElement_INTERFACE_DEFINED__ + +struct IUIAutomationCondition; +struct IUIAutomationCacheRequest; +struct IUIAutomationElementArray; +struct IUIAutomationTreeWalker; +struct IUIAutomationEventHandler; +struct IUIAutomationPropertyChangedEventHandler; +struct IUIAutomationStructureChangedEventHandler; +struct IUIAutomationFocusChangedEventHandler; +struct IUIAutomationProxyFactory; +struct IUIAutomationProxyFactoryEntry; +struct IUIAutomationProxyFactoryMapping; +#ifndef __IAccessible_FWD_DEFINED__ +#define __IAccessible_FWD_DEFINED__ +struct IAccessible; +#endif /* __IAccessible_FWD_DEFINED__ */ + +#define __IUIAutomationElement_INTERFACE_DEFINED__ +DEFINE_GUID(IID_IUIAutomationElement, 0xd22108aa, 0x8ac5, 0x49a5, 0x83,0x7b, 0x37,0xbb,0xb3,0xd7,0x59,0x1e); +MIDL_INTERFACE("d22108aa-8ac5-49a5-837b-37bbb3d7591e") +IUIAutomationElement : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE SetFocus() = 0; + virtual HRESULT STDMETHODCALLTYPE GetRuntimeId(__RPC__deref_out_opt SAFEARRAY **runtimeId) = 0; + virtual HRESULT STDMETHODCALLTYPE FindFirst(enum TreeScope scope, __RPC__in_opt IUIAutomationCondition *condition, __RPC__deref_out_opt IUIAutomationElement **found) = 0; + virtual HRESULT STDMETHODCALLTYPE FindAll(enum TreeScope scope, __RPC__in_opt IUIAutomationCondition *condition, __RPC__deref_out_opt IUIAutomationElementArray **found) = 0; + virtual HRESULT STDMETHODCALLTYPE FindFirstBuildCache(enum TreeScope scope, __RPC__in_opt IUIAutomationCondition *condition, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **found) = 0; + virtual HRESULT STDMETHODCALLTYPE FindAllBuildCache(enum TreeScope scope, __RPC__in_opt IUIAutomationCondition *condition, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElementArray **found) = 0; + virtual HRESULT STDMETHODCALLTYPE BuildUpdatedCache(__RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **updatedElement) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentPropertyValue(PROPERTYID propertyId, __RPC__out VARIANT *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentPropertyValueEx(PROPERTYID propertyId, BOOL ignoreDefaultValue, __RPC__out VARIANT *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCachedPropertyValue(PROPERTYID propertyId, __RPC__out VARIANT *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCachedPropertyValueEx(PROPERTYID propertyId, BOOL ignoreDefaultValue, __RPC__out VARIANT *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentPatternAs(PATTERNID patternId, __RPC__in REFIID riid, __RPC__deref_out_opt void **patternObject) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCachedPatternAs(PATTERNID patternId, __RPC__in REFIID riid, __RPC__deref_out_opt void **patternObject) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentPattern(PATTERNID patternId, __RPC__deref_out_opt IUnknown **patternObject) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCachedPattern(PATTERNID patternId, __RPC__deref_out_opt IUnknown **patternObject) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCachedParent(__RPC__deref_out_opt IUIAutomationElement **parent) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCachedChildren(__RPC__deref_out_opt IUIAutomationElementArray **children) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentProcessId(__RPC__out int *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentControlType(__RPC__out CONTROLTYPEID *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentLocalizedControlType(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentName(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentAcceleratorKey(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentAccessKey(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentHasKeyboardFocus(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentIsKeyboardFocusable(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentIsEnabled(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentAutomationId(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentClassName(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentHelpText(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentCulture(__RPC__out int *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentIsControlElement(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentIsContentElement(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentIsPassword(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentNativeWindowHandle(__RPC__deref_out_opt UIA_HWND *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentItemType(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentIsOffscreen(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentOrientation(__RPC__out enum OrientationType *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentFrameworkId(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentIsRequiredForForm(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentItemStatus(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentBoundingRectangle(__RPC__out RECT *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentLabeledBy(__RPC__deref_out_opt IUIAutomationElement **retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentAriaRole(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentAriaProperties(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentIsDataValidForForm(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentControllerFor(__RPC__deref_out_opt IUIAutomationElementArray **retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentDescribedBy(__RPC__deref_out_opt IUIAutomationElementArray **retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentFlowsTo(__RPC__deref_out_opt IUIAutomationElementArray **retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CurrentProviderDescription(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedProcessId(__RPC__out int *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedControlType(__RPC__out CONTROLTYPEID *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedLocalizedControlType(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedName(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedAcceleratorKey(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedAccessKey(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedHasKeyboardFocus(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedIsKeyboardFocusable(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedIsEnabled(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedAutomationId(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedClassName(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedHelpText(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedCulture(__RPC__out int *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedIsControlElement(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedIsContentElement(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedIsPassword(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedNativeWindowHandle(__RPC__deref_out_opt UIA_HWND *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedItemType(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedIsOffscreen(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedOrientation(__RPC__out enum OrientationType *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedFrameworkId(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedIsRequiredForForm(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedItemStatus(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedBoundingRectangle(__RPC__out RECT *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedLabeledBy(__RPC__deref_out_opt IUIAutomationElement **retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedAriaRole(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedAriaProperties(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedIsDataValidForForm(__RPC__out BOOL *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedControllerFor(__RPC__deref_out_opt IUIAutomationElementArray **retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedDescribedBy(__RPC__deref_out_opt IUIAutomationElementArray **retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedFlowsTo(__RPC__deref_out_opt IUIAutomationElementArray **retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CachedProviderDescription(__RPC__deref_out_opt BSTR *retVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetClickablePoint(__RPC__out POINT *clickable, __RPC__out BOOL *gotClickable) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IUIAutomationElement, 0xd22108aa, 0x8ac5, 0x49a5, 0x83,0x7b, 0x37,0xbb,0xb3,0xd7,0x59,0x1e) +#endif +#endif + + +#ifndef __IUIAutomation_INTERFACE_DEFINED__ +#define __IUIAutomation_INTERFACE_DEFINED__ +DEFINE_GUID(IID_IUIAutomation, 0x30cbe57d, 0xd9d0, 0x452a, 0xab,0x13, 0x7a,0xc5,0xac,0x48,0x25,0xee); +MIDL_INTERFACE("30cbe57d-d9d0-452a-ab13-7ac5ac4825ee") +IUIAutomation : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE CompareElements(__RPC__in_opt IUIAutomationElement *el1, __RPC__in_opt IUIAutomationElement *el2, __RPC__out BOOL *areSame) = 0; + virtual HRESULT STDMETHODCALLTYPE CompareRuntimeIds(__RPC__in SAFEARRAY * runtimeId1, __RPC__in SAFEARRAY * runtimeId2, __RPC__out BOOL *areSame) = 0; + virtual HRESULT STDMETHODCALLTYPE GetRootElement(__RPC__deref_out_opt IUIAutomationElement **root) = 0; + virtual HRESULT STDMETHODCALLTYPE ElementFromHandle(__RPC__in UIA_HWND hwnd, __RPC__deref_out_opt IUIAutomationElement **element) = 0; + virtual HRESULT STDMETHODCALLTYPE ElementFromPoint(POINT pt, __RPC__deref_out_opt IUIAutomationElement **element) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFocusedElement(__RPC__deref_out_opt IUIAutomationElement **element) = 0; + virtual HRESULT STDMETHODCALLTYPE GetRootElementBuildCache(__RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **root) = 0; + virtual HRESULT STDMETHODCALLTYPE ElementFromHandleBuildCache(__RPC__in UIA_HWND hwnd, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **element) = 0; + virtual HRESULT STDMETHODCALLTYPE ElementFromPointBuildCache(POINT pt, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **element) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFocusedElementBuildCache(__RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **element) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateTreeWalker(__RPC__in_opt IUIAutomationCondition *pCondition, __RPC__deref_out_opt IUIAutomationTreeWalker **walker) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ControlViewWalker(__RPC__deref_out_opt IUIAutomationTreeWalker **walker) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ContentViewWalker(__RPC__deref_out_opt IUIAutomationTreeWalker **walker) = 0; + virtual HRESULT STDMETHODCALLTYPE get_RawViewWalker(__RPC__deref_out_opt IUIAutomationTreeWalker **walker) = 0; + virtual HRESULT STDMETHODCALLTYPE get_RawViewCondition(__RPC__deref_out_opt IUIAutomationCondition **condition) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ControlViewCondition(__RPC__deref_out_opt IUIAutomationCondition **condition) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ContentViewCondition(__RPC__deref_out_opt IUIAutomationCondition **condition) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateCacheRequest(__RPC__deref_out_opt IUIAutomationCacheRequest **cacheRequest) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateTrueCondition(__RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateFalseCondition(__RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0; + virtual HRESULT STDMETHODCALLTYPE CreatePropertyCondition(PROPERTYID propertyId, VARIANT value, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0; + virtual HRESULT STDMETHODCALLTYPE CreatePropertyConditionEx(PROPERTYID propertyId, VARIANT value, enum PropertyConditionFlags flags, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateAndCondition(__RPC__in_opt IUIAutomationCondition *condition1, __RPC__in_opt IUIAutomationCondition *condition2, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateAndConditionFromArray(__RPC__in_opt SAFEARRAY * conditions, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateAndConditionFromNativeArray(__RPC__in_ecount_full(conditionCount) IUIAutomationCondition **conditions, int conditionCount, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateOrCondition(__RPC__in_opt IUIAutomationCondition *condition1, __RPC__in_opt IUIAutomationCondition *condition2, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateOrConditionFromArray(__RPC__in_opt SAFEARRAY * conditions, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateOrConditionFromNativeArray(__RPC__in_ecount_full(conditionCount) IUIAutomationCondition **conditions, int conditionCount, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateNotCondition(__RPC__in_opt IUIAutomationCondition *condition, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0; + virtual HRESULT STDMETHODCALLTYPE AddAutomationEventHandler(EVENTID eventId, __RPC__in_opt IUIAutomationElement *element, enum TreeScope scope, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__in_opt IUIAutomationEventHandler *handler) = 0; + virtual HRESULT STDMETHODCALLTYPE RemoveAutomationEventHandler(EVENTID eventId, __RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationEventHandler *handler) = 0; + virtual HRESULT STDMETHODCALLTYPE AddPropertyChangedEventHandlerNativeArray(__RPC__in_opt IUIAutomationElement *element, enum TreeScope scope, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__in_opt IUIAutomationPropertyChangedEventHandler *handler, __RPC__in_ecount_full(propertyCount) PROPERTYID *propertyArray, int propertyCount) = 0; + virtual HRESULT STDMETHODCALLTYPE AddPropertyChangedEventHandler(__RPC__in_opt IUIAutomationElement *element, enum TreeScope scope, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__in_opt IUIAutomationPropertyChangedEventHandler *handler, __RPC__in SAFEARRAY * propertyArray) = 0; + virtual HRESULT STDMETHODCALLTYPE RemovePropertyChangedEventHandler(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationPropertyChangedEventHandler *handler) = 0; + virtual HRESULT STDMETHODCALLTYPE AddStructureChangedEventHandler(__RPC__in_opt IUIAutomationElement *element, enum TreeScope scope, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__in_opt IUIAutomationStructureChangedEventHandler *handler) = 0; + virtual HRESULT STDMETHODCALLTYPE RemoveStructureChangedEventHandler(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationStructureChangedEventHandler *handler) = 0; + virtual HRESULT STDMETHODCALLTYPE AddFocusChangedEventHandler(__RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__in_opt IUIAutomationFocusChangedEventHandler *handler) = 0; + virtual HRESULT STDMETHODCALLTYPE RemoveFocusChangedEventHandler(__RPC__in_opt IUIAutomationFocusChangedEventHandler *handler) = 0; + virtual HRESULT STDMETHODCALLTYPE RemoveAllEventHandlers() = 0; + virtual HRESULT STDMETHODCALLTYPE IntNativeArrayToSafeArray(__RPC__in_ecount_full(arrayCount) int *array, int arrayCount, __RPC__deref_out_opt SAFEARRAY **safeArray) = 0; + virtual HRESULT STDMETHODCALLTYPE IntSafeArrayToNativeArray(__RPC__in SAFEARRAY * intArray, __RPC__deref_out_ecount_full_opt(*arrayCount) int **array, __RPC__out int *arrayCount) = 0; + virtual HRESULT STDMETHODCALLTYPE RectToVariant(RECT rc, __RPC__out VARIANT *var) = 0; + virtual HRESULT STDMETHODCALLTYPE VariantToRect(VARIANT var, __RPC__out RECT *rc) = 0; + virtual HRESULT STDMETHODCALLTYPE SafeArrayToRectNativeArray(__RPC__in SAFEARRAY * rects, __RPC__deref_out_ecount_full_opt(*rectArrayCount) RECT **rectArray, __RPC__out int *rectArrayCount) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateProxyFactoryEntry(__RPC__in_opt IUIAutomationProxyFactory *factory, __RPC__deref_out_opt IUIAutomationProxyFactoryEntry **factoryEntry) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ProxyFactoryMapping(__RPC__deref_out_opt IUIAutomationProxyFactoryMapping **factoryMapping) = 0; + virtual HRESULT STDMETHODCALLTYPE GetPropertyProgrammaticName(PROPERTYID property, __RPC__deref_out_opt BSTR *name) = 0; + virtual HRESULT STDMETHODCALLTYPE GetPatternProgrammaticName(PATTERNID pattern, __RPC__deref_out_opt BSTR *name) = 0; + virtual HRESULT STDMETHODCALLTYPE PollForPotentialSupportedPatterns(__RPC__in_opt IUIAutomationElement *pElement, __RPC__deref_out_opt SAFEARRAY **patternIds, __RPC__deref_out_opt SAFEARRAY **patternNames) = 0; + virtual HRESULT STDMETHODCALLTYPE PollForPotentialSupportedProperties(__RPC__in_opt IUIAutomationElement *pElement, __RPC__deref_out_opt SAFEARRAY **propertyIds, __RPC__deref_out_opt SAFEARRAY **propertyNames) = 0; + virtual HRESULT STDMETHODCALLTYPE CheckNotSupported(VARIANT value, __RPC__out BOOL *isNotSupported) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ReservedNotSupportedValue(__RPC__deref_out_opt IUnknown **notSupportedValue) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ReservedMixedAttributeValue(__RPC__deref_out_opt IUnknown **mixedAttributeValue) = 0; + virtual HRESULT STDMETHODCALLTYPE ElementFromIAccessible(__RPC__in_opt IAccessible *accessible, int childId, __RPC__deref_out_opt IUIAutomationElement **element) = 0; + virtual HRESULT STDMETHODCALLTYPE ElementFromIAccessibleBuildCache(__RPC__in_opt IAccessible *accessible, int childId, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **element) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IUIAutomation, 0x30cbe57d, 0xd9d0, 0x452a, 0xab,0x13, 0x7a,0xc5,0xac,0x48,0x25,0xee) +#endif +#endif + + +#ifndef __IUIAutomationTreeWalker_INTERFACE_DEFINED__ +#define __IUIAutomationTreeWalker_INTERFACE_DEFINED__ +DEFINE_GUID(IID_IUIAutomationTreeWalker, 0x4042c624, 0x389c, 0x4afc, 0xa6,0x30, 0x9d,0xf8,0x54,0xa5,0x41,0xfc); +MIDL_INTERFACE("4042c624-389c-4afc-a630-9df854a541fc") +IUIAutomationTreeWalker : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE GetParentElement(__RPC__in_opt IUIAutomationElement *element, __RPC__deref_out_opt IUIAutomationElement **parent) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFirstChildElement(__RPC__in_opt IUIAutomationElement *element, __RPC__deref_out_opt IUIAutomationElement **first) = 0; + virtual HRESULT STDMETHODCALLTYPE GetLastChildElement(__RPC__in_opt IUIAutomationElement *element, __RPC__deref_out_opt IUIAutomationElement **last) = 0; + virtual HRESULT STDMETHODCALLTYPE GetNextSiblingElement(__RPC__in_opt IUIAutomationElement *element, __RPC__deref_out_opt IUIAutomationElement **next) = 0; + virtual HRESULT STDMETHODCALLTYPE GetPreviousSiblingElement(__RPC__in_opt IUIAutomationElement *element, __RPC__deref_out_opt IUIAutomationElement **previous) = 0; + virtual HRESULT STDMETHODCALLTYPE NormalizeElement(__RPC__in_opt IUIAutomationElement *element, __RPC__deref_out_opt IUIAutomationElement **normalized) = 0; + virtual HRESULT STDMETHODCALLTYPE GetParentElementBuildCache(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **parent) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFirstChildElementBuildCache(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **first) = 0; + virtual HRESULT STDMETHODCALLTYPE GetLastChildElementBuildCache(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **last) = 0; + virtual HRESULT STDMETHODCALLTYPE GetNextSiblingElementBuildCache(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **next) = 0; + virtual HRESULT STDMETHODCALLTYPE GetPreviousSiblingElementBuildCache(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **previous) = 0; + virtual HRESULT STDMETHODCALLTYPE NormalizeElementBuildCache(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **normalized) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Condition(__RPC__deref_out_opt IUIAutomationCondition **condition) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IUIAutomationTreeWalker, 0x4042c624, 0x389c, 0x4afc, 0xa6,0x30, 0x9d,0xf8,0x54,0xa5,0x41,0xfc) +#endif +#endif + +DEFINE_GUID(CLSID_CUIAutomation, 0xff48dba4, 0x60ef, 0x4201, 0xaa,0x87, 0x54,0x10,0x3e,0xef,0x59,0x4e); + +#endif diff --git a/src/platformsupport/windowsuiautomation/uiacontroltypeids.h b/src/platformsupport/windowsuiautomation/uiacontroltypeids.h new file mode 100644 index 0000000000..d77fc68da9 --- /dev/null +++ b/src/platformsupport/windowsuiautomation/uiacontroltypeids.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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 UIACONTROLTYPEIDS_H +#define UIACONTROLTYPEIDS_H + +#define UIA_ButtonControlTypeId 50000 +#define UIA_CalendarControlTypeId 50001 +#define UIA_CheckBoxControlTypeId 50002 +#define UIA_ComboBoxControlTypeId 50003 +#define UIA_EditControlTypeId 50004 +#define UIA_HyperlinkControlTypeId 50005 +#define UIA_ImageControlTypeId 50006 +#define UIA_ListItemControlTypeId 50007 +#define UIA_ListControlTypeId 50008 +#define UIA_MenuControlTypeId 50009 +#define UIA_MenuBarControlTypeId 50010 +#define UIA_MenuItemControlTypeId 50011 +#define UIA_ProgressBarControlTypeId 50012 +#define UIA_RadioButtonControlTypeId 50013 +#define UIA_ScrollBarControlTypeId 50014 +#define UIA_SliderControlTypeId 50015 +#define UIA_SpinnerControlTypeId 50016 +#define UIA_StatusBarControlTypeId 50017 +#define UIA_TabControlTypeId 50018 +#define UIA_TabItemControlTypeId 50019 +#define UIA_TextControlTypeId 50020 +#define UIA_ToolBarControlTypeId 50021 +#define UIA_ToolTipControlTypeId 50022 +#define UIA_TreeControlTypeId 50023 +#define UIA_TreeItemControlTypeId 50024 +#define UIA_CustomControlTypeId 50025 +#define UIA_GroupControlTypeId 50026 +#define UIA_ThumbControlTypeId 50027 +#define UIA_DataGridControlTypeId 50028 +#define UIA_DataItemControlTypeId 50029 +#define UIA_DocumentControlTypeId 50030 +#define UIA_SplitButtonControlTypeId 50031 +#define UIA_WindowControlTypeId 50032 +#define UIA_PaneControlTypeId 50033 +#define UIA_HeaderControlTypeId 50034 +#define UIA_HeaderItemControlTypeId 50035 +#define UIA_TableControlTypeId 50036 +#define UIA_TitleBarControlTypeId 50037 +#define UIA_SeparatorControlTypeId 50038 +#define UIA_SemanticZoomControlTypeId 50039 +#define UIA_AppBarControlTypeId 50040 + +#endif diff --git a/src/platformsupport/windowsuiautomation/uiaerrorids.h b/src/platformsupport/windowsuiautomation/uiaerrorids.h new file mode 100644 index 0000000000..c25453007d --- /dev/null +++ b/src/platformsupport/windowsuiautomation/uiaerrorids.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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 UIAERRORIDS_H +#define UIAERRORIDS_H + +#define UIA_E_ELEMENTNOTENABLED 0x80040200 +#define UIA_E_ELEMENTNOTAVAILABLE 0x80040201 +#define UIA_E_NOCLICKABLEPOINT 0x80040202 +#define UIA_E_PROXYASSEMBLYNOTLOADED 0x80040203 +#define UIA_E_NOTSUPPORTED 0x80040204 +#define UIA_E_INVALIDOPERATION 0x80131509 +#define UIA_E_TIMEOUT 0x80131505 + +#endif diff --git a/src/platformsupport/windowsuiautomation/uiaeventids.h b/src/platformsupport/windowsuiautomation/uiaeventids.h new file mode 100644 index 0000000000..2b414968ed --- /dev/null +++ b/src/platformsupport/windowsuiautomation/uiaeventids.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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 UIAEVENTIDS_H +#define UIAEVENTIDS_H + +#define UIA_ToolTipOpenedEventId 20000 +#define UIA_ToolTipClosedEventId 20001 +#define UIA_StructureChangedEventId 20002 +#define UIA_MenuOpenedEventId 20003 +#define UIA_AutomationPropertyChangedEventId 20004 +#define UIA_AutomationFocusChangedEventId 20005 +#define UIA_AsyncContentLoadedEventId 20006 +#define UIA_MenuClosedEventId 20007 +#define UIA_LayoutInvalidatedEventId 20008 +#define UIA_Invoke_InvokedEventId 20009 +#define UIA_SelectionItem_ElementAddedToSelectionEventId 20010 +#define UIA_SelectionItem_ElementRemovedFromSelectionEventId 20011 +#define UIA_SelectionItem_ElementSelectedEventId 20012 +#define UIA_Selection_InvalidatedEventId 20013 +#define UIA_Text_TextSelectionChangedEventId 20014 +#define UIA_Text_TextChangedEventId 20015 +#define UIA_Window_WindowOpenedEventId 20016 +#define UIA_Window_WindowClosedEventId 20017 +#define UIA_MenuModeStartEventId 20018 +#define UIA_MenuModeEndEventId 20019 +#define UIA_InputReachedTargetEventId 20020 +#define UIA_InputReachedOtherElementEventId 20021 +#define UIA_InputDiscardedEventId 20022 +#define UIA_SystemAlertEventId 20023 +#define UIA_LiveRegionChangedEventId 20024 +#define UIA_HostedFragmentRootsInvalidatedEventId 20025 +#define UIA_Drag_DragStartEventId 20026 +#define UIA_Drag_DragCancelEventId 20027 +#define UIA_Drag_DragCompleteEventId 20028 +#define UIA_DropTarget_DragEnterEventId 20029 +#define UIA_DropTarget_DragLeaveEventId 20030 +#define UIA_DropTarget_DroppedEventId 20031 +#define UIA_TextEdit_TextChangedEventId 20032 +#define UIA_TextEdit_ConversionTargetChangedEventId 20033 +#define UIA_ChangesEventId 20034 + +#endif diff --git a/src/platformsupport/windowsuiautomation/uiageneralids.h b/src/platformsupport/windowsuiautomation/uiageneralids.h new file mode 100644 index 0000000000..62c795b94a --- /dev/null +++ b/src/platformsupport/windowsuiautomation/uiageneralids.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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 UIAGENERALIDS_H +#define UIAGENERALIDS_H + +#define UiaAppendRuntimeId 3 +#define UiaRootObjectId -25 + +#endif diff --git a/src/platformsupport/windowsuiautomation/uiapatternids.h b/src/platformsupport/windowsuiautomation/uiapatternids.h new file mode 100644 index 0000000000..114aabcaa5 --- /dev/null +++ b/src/platformsupport/windowsuiautomation/uiapatternids.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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 UIAPATTERNIDS_H +#define UIAPATTERNIDS_H + +#define UIA_InvokePatternId 10000 +#define UIA_SelectionPatternId 10001 +#define UIA_ValuePatternId 10002 +#define UIA_RangeValuePatternId 10003 +#define UIA_ScrollPatternId 10004 +#define UIA_ExpandCollapsePatternId 10005 +#define UIA_GridPatternId 10006 +#define UIA_GridItemPatternId 10007 +#define UIA_MultipleViewPatternId 10008 +#define UIA_WindowPatternId 10009 +#define UIA_SelectionItemPatternId 10010 +#define UIA_DockPatternId 10011 +#define UIA_TablePatternId 10012 +#define UIA_TableItemPatternId 10013 +#define UIA_TextPatternId 10014 +#define UIA_TogglePatternId 10015 +#define UIA_TransformPatternId 10016 +#define UIA_ScrollItemPatternId 10017 +#define UIA_LegacyIAccessiblePatternId 10018 +#define UIA_ItemContainerPatternId 10019 +#define UIA_VirtualizedItemPatternId 10020 +#define UIA_SynchronizedInputPatternId 10021 +#define UIA_ObjectModelPatternId 10022 +#define UIA_AnnotationPatternId 10023 +#define UIA_TextPattern2Id 10024 +#define UIA_StylesPatternId 10025 +#define UIA_SpreadsheetPatternId 10026 +#define UIA_SpreadsheetItemPatternId 10027 +#define UIA_TransformPattern2Id 10028 +#define UIA_TextChildPatternId 10029 +#define UIA_DragPatternId 10030 +#define UIA_DropTargetPatternId 10031 +#define UIA_TextEditPatternId 10032 +#define UIA_CustomNavigationPatternId 10033 + +#endif diff --git a/src/platformsupport/windowsuiautomation/uiapropertyids.h b/src/platformsupport/windowsuiautomation/uiapropertyids.h new file mode 100644 index 0000000000..5c35c956f8 --- /dev/null +++ b/src/platformsupport/windowsuiautomation/uiapropertyids.h @@ -0,0 +1,212 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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 UIAPROPERTYIDS_H +#define UIAPROPERTYIDS_H + +#define UIA_RuntimeIdPropertyId 30000 +#define UIA_BoundingRectanglePropertyId 30001 +#define UIA_ProcessIdPropertyId 30002 +#define UIA_ControlTypePropertyId 30003 +#define UIA_LocalizedControlTypePropertyId 30004 +#define UIA_NamePropertyId 30005 +#define UIA_AcceleratorKeyPropertyId 30006 +#define UIA_AccessKeyPropertyId 30007 +#define UIA_HasKeyboardFocusPropertyId 30008 +#define UIA_IsKeyboardFocusablePropertyId 30009 +#define UIA_IsEnabledPropertyId 30010 +#define UIA_AutomationIdPropertyId 30011 +#define UIA_ClassNamePropertyId 30012 +#define UIA_HelpTextPropertyId 30013 +#define UIA_ClickablePointPropertyId 30014 +#define UIA_CulturePropertyId 30015 +#define UIA_IsControlElementPropertyId 30016 +#define UIA_IsContentElementPropertyId 30017 +#define UIA_LabeledByPropertyId 30018 +#define UIA_IsPasswordPropertyId 30019 +#define UIA_NativeWindowHandlePropertyId 30020 +#define UIA_ItemTypePropertyId 30021 +#define UIA_IsOffscreenPropertyId 30022 +#define UIA_OrientationPropertyId 30023 +#define UIA_FrameworkIdPropertyId 30024 +#define UIA_IsRequiredForFormPropertyId 30025 +#define UIA_ItemStatusPropertyId 30026 +#define UIA_IsDockPatternAvailablePropertyId 30027 +#define UIA_IsExpandCollapsePatternAvailablePropertyId 30028 +#define UIA_IsGridItemPatternAvailablePropertyId 30029 +#define UIA_IsGridPatternAvailablePropertyId 30030 +#define UIA_IsInvokePatternAvailablePropertyId 30031 +#define UIA_IsMultipleViewPatternAvailablePropertyId 30032 +#define UIA_IsRangeValuePatternAvailablePropertyId 30033 +#define UIA_IsScrollPatternAvailablePropertyId 30034 +#define UIA_IsScrollItemPatternAvailablePropertyId 30035 +#define UIA_IsSelectionItemPatternAvailablePropertyId 30036 +#define UIA_IsSelectionPatternAvailablePropertyId 30037 +#define UIA_IsTablePatternAvailablePropertyId 30038 +#define UIA_IsTableItemPatternAvailablePropertyId 30039 +#define UIA_IsTextPatternAvailablePropertyId 30040 +#define UIA_IsTogglePatternAvailablePropertyId 30041 +#define UIA_IsTransformPatternAvailablePropertyId 30042 +#define UIA_IsValuePatternAvailablePropertyId 30043 +#define UIA_IsWindowPatternAvailablePropertyId 30044 +#define UIA_ValueValuePropertyId 30045 +#define UIA_ValueIsReadOnlyPropertyId 30046 +#define UIA_RangeValueValuePropertyId 30047 +#define UIA_RangeValueIsReadOnlyPropertyId 30048 +#define UIA_RangeValueMinimumPropertyId 30049 +#define UIA_RangeValueMaximumPropertyId 30050 +#define UIA_RangeValueLargeChangePropertyId 30051 +#define UIA_RangeValueSmallChangePropertyId 30052 +#define UIA_ScrollHorizontalScrollPercentPropertyId 30053 +#define UIA_ScrollHorizontalViewSizePropertyId 30054 +#define UIA_ScrollVerticalScrollPercentPropertyId 30055 +#define UIA_ScrollVerticalViewSizePropertyId 30056 +#define UIA_ScrollHorizontallyScrollablePropertyId 30057 +#define UIA_ScrollVerticallyScrollablePropertyId 30058 +#define UIA_SelectionSelectionPropertyId 30059 +#define UIA_SelectionCanSelectMultiplePropertyId 30060 +#define UIA_SelectionIsSelectionRequiredPropertyId 30061 +#define UIA_GridRowCountPropertyId 30062 +#define UIA_GridColumnCountPropertyId 30063 +#define UIA_GridItemRowPropertyId 30064 +#define UIA_GridItemColumnPropertyId 30065 +#define UIA_GridItemRowSpanPropertyId 30066 +#define UIA_GridItemColumnSpanPropertyId 30067 +#define UIA_GridItemContainingGridPropertyId 30068 +#define UIA_DockDockPositionPropertyId 30069 +#define UIA_ExpandCollapseExpandCollapseStatePropertyId 30070 +#define UIA_MultipleViewCurrentViewPropertyId 30071 +#define UIA_MultipleViewSupportedViewsPropertyId 30072 +#define UIA_WindowCanMaximizePropertyId 30073 +#define UIA_WindowCanMinimizePropertyId 30074 +#define UIA_WindowWindowVisualStatePropertyId 30075 +#define UIA_WindowWindowInteractionStatePropertyId 30076 +#define UIA_WindowIsModalPropertyId 30077 +#define UIA_WindowIsTopmostPropertyId 30078 +#define UIA_SelectionItemIsSelectedPropertyId 30079 +#define UIA_SelectionItemSelectionContainerPropertyId 30080 +#define UIA_TableRowHeadersPropertyId 30081 +#define UIA_TableColumnHeadersPropertyId 30082 +#define UIA_TableRowOrColumnMajorPropertyId 30083 +#define UIA_TableItemRowHeaderItemsPropertyId 30084 +#define UIA_TableItemColumnHeaderItemsPropertyId 30085 +#define UIA_ToggleToggleStatePropertyId 30086 +#define UIA_TransformCanMovePropertyId 30087 +#define UIA_TransformCanResizePropertyId 30088 +#define UIA_TransformCanRotatePropertyId 30089 +#define UIA_IsLegacyIAccessiblePatternAvailablePropertyId 30090 +#define UIA_LegacyIAccessibleChildIdPropertyId 30091 +#define UIA_LegacyIAccessibleNamePropertyId 30092 +#define UIA_LegacyIAccessibleValuePropertyId 30093 +#define UIA_LegacyIAccessibleDescriptionPropertyId 30094 +#define UIA_LegacyIAccessibleRolePropertyId 30095 +#define UIA_LegacyIAccessibleStatePropertyId 30096 +#define UIA_LegacyIAccessibleHelpPropertyId 30097 +#define UIA_LegacyIAccessibleKeyboardShortcutPropertyId 30098 +#define UIA_LegacyIAccessibleSelectionPropertyId 30099 +#define UIA_LegacyIAccessibleDefaultActionPropertyId 30100 +#define UIA_AriaRolePropertyId 30101 +#define UIA_AriaPropertiesPropertyId 30102 +#define UIA_IsDataValidForFormPropertyId 30103 +#define UIA_ControllerForPropertyId 30104 +#define UIA_DescribedByPropertyId 30105 +#define UIA_FlowsToPropertyId 30106 +#define UIA_ProviderDescriptionPropertyId 30107 +#define UIA_IsItemContainerPatternAvailablePropertyId 30108 +#define UIA_IsVirtualizedItemPatternAvailablePropertyId 30109 +#define UIA_IsSynchronizedInputPatternAvailablePropertyId 30110 +#define UIA_OptimizeForVisualContentPropertyId 30111 +#define UIA_IsObjectModelPatternAvailablePropertyId 30112 +#define UIA_AnnotationAnnotationTypeIdPropertyId 30113 +#define UIA_AnnotationAnnotationTypeNamePropertyId 30114 +#define UIA_AnnotationAuthorPropertyId 30115 +#define UIA_AnnotationDateTimePropertyId 30116 +#define UIA_AnnotationTargetPropertyId 30117 +#define UIA_IsAnnotationPatternAvailablePropertyId 30118 +#define UIA_IsTextPattern2AvailablePropertyId 30119 +#define UIA_StylesStyleIdPropertyId 30120 +#define UIA_StylesStyleNamePropertyId 30121 +#define UIA_StylesFillColorPropertyId 30122 +#define UIA_StylesFillPatternStylePropertyId 30123 +#define UIA_StylesShapePropertyId 30124 +#define UIA_StylesFillPatternColorPropertyId 30125 +#define UIA_StylesExtendedPropertiesPropertyId 30126 +#define UIA_IsStylesPatternAvailablePropertyId 30127 +#define UIA_IsSpreadsheetPatternAvailablePropertyId 30128 +#define UIA_SpreadsheetItemFormulaPropertyId 30129 +#define UIA_SpreadsheetItemAnnotationObjectsPropertyId 30130 +#define UIA_SpreadsheetItemAnnotationTypesPropertyId 30131 +#define UIA_IsSpreadsheetItemPatternAvailablePropertyId 30132 +#define UIA_Transform2CanZoomPropertyId 30133 +#define UIA_IsTransformPattern2AvailablePropertyId 30134 +#define UIA_LiveSettingPropertyId 30135 +#define UIA_IsTextChildPatternAvailablePropertyId 30136 +#define UIA_IsDragPatternAvailablePropertyId 30137 +#define UIA_DragIsGrabbedPropertyId 30138 +#define UIA_DragDropEffectPropertyId 30139 +#define UIA_DragDropEffectsPropertyId 30140 +#define UIA_IsDropTargetPatternAvailablePropertyId 30141 +#define UIA_DropTargetDropTargetEffectPropertyId 30142 +#define UIA_DropTargetDropTargetEffectsPropertyId 30143 +#define UIA_DragGrabbedItemsPropertyId 30144 +#define UIA_Transform2ZoomLevelPropertyId 30145 +#define UIA_Transform2ZoomMinimumPropertyId 30146 +#define UIA_Transform2ZoomMaximumPropertyId 30147 +#define UIA_FlowsFromPropertyId 30148 +#define UIA_IsTextEditPatternAvailablePropertyId 30149 +#define UIA_IsPeripheralPropertyId 30150 +#define UIA_IsCustomNavigationPatternAvailablePropertyId 30151 +#define UIA_PositionInSetPropertyId 30152 +#define UIA_SizeOfSetPropertyId 30153 +#define UIA_LevelPropertyId 30154 +#define UIA_AnnotationTypesPropertyId 30155 +#define UIA_AnnotationObjectsPropertyId 30156 +#define UIA_LandmarkTypePropertyId 30157 +#define UIA_LocalizedLandmarkTypePropertyId 30158 +#define UIA_FullDescriptionPropertyId 30159 +#define UIA_FillColorPropertyId 30160 +#define UIA_OutlineColorPropertyId 30161 +#define UIA_FillTypePropertyId 30162 +#define UIA_VisualEffectsPropertyId 30163 +#define UIA_OutlineThicknessPropertyId 30164 +#define UIA_CenterPointPropertyId 30165 +#define UIA_RotationPropertyId 30166 +#define UIA_SizePropertyId 30167 + +#endif diff --git a/src/platformsupport/windowsuiautomation/uiaserverinterfaces.h b/src/platformsupport/windowsuiautomation/uiaserverinterfaces.h new file mode 100644 index 0000000000..caae84755b --- /dev/null +++ b/src/platformsupport/windowsuiautomation/uiaserverinterfaces.h @@ -0,0 +1,352 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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 UIASERVERINTERFACES_H +#define UIASERVERINTERFACES_H + +#include + +#ifndef __IRawElementProviderSimple_INTERFACE_DEFINED__ +#define __IRawElementProviderSimple_INTERFACE_DEFINED__ +DEFINE_GUID(IID_IRawElementProviderSimple, 0xd6dd68d1, 0x86fd, 0x4332, 0x86,0x66, 0x9a,0xbe,0xde,0xa2,0xd2,0x4c); +MIDL_INTERFACE("d6dd68d1-86fd-4332-8666-9abedea2d24c") +IRawElementProviderSimple : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE get_ProviderOptions(__RPC__out enum ProviderOptions *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetPatternProvider(PATTERNID patternId, __RPC__deref_out_opt IUnknown **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetPropertyValue(PROPERTYID propertyId, __RPC__out VARIANT *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_HostRawElementProvider(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IRawElementProviderSimple, 0xd6dd68d1, 0x86fd, 0x4332, 0x86,0x66, 0x9a,0xbe,0xde,0xa2,0xd2,0x4c) +#endif +#endif + + +#ifndef __IRawElementProviderFragmentRoot_FWD_DEFINED__ +#define __IRawElementProviderFragmentRoot_FWD_DEFINED__ +typedef interface IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot; +#endif + + +#ifndef __IRawElementProviderFragment_FWD_DEFINED__ +#define __IRawElementProviderFragment_FWD_DEFINED__ +typedef interface IRawElementProviderFragment IRawElementProviderFragment; +#endif + + +#ifndef __IRawElementProviderFragment_INTERFACE_DEFINED__ +#define __IRawElementProviderFragment_INTERFACE_DEFINED__ +DEFINE_GUID(IID_IRawElementProviderFragment, 0xf7063da8, 0x8359, 0x439c, 0x92,0x97, 0xbb,0xc5,0x29,0x9a,0x7d,0x87); +MIDL_INTERFACE("f7063da8-8359-439c-9297-bbc5299a7d87") +IRawElementProviderFragment : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE Navigate(enum NavigateDirection direction, __RPC__deref_out_opt IRawElementProviderFragment **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetRuntimeId(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_BoundingRectangle(__RPC__out struct UiaRect *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetEmbeddedFragmentRoots(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE SetFocus() = 0; + virtual HRESULT STDMETHODCALLTYPE get_FragmentRoot(__RPC__deref_out_opt IRawElementProviderFragmentRoot **pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IRawElementProviderFragment, 0xf7063da8, 0x8359, 0x439c, 0x92,0x97, 0xbb,0xc5,0x29,0x9a,0x7d,0x87) +#endif +#endif + + +#ifndef __IRawElementProviderFragmentRoot_INTERFACE_DEFINED__ +#define __IRawElementProviderFragmentRoot_INTERFACE_DEFINED__ +DEFINE_GUID(IID_IRawElementProviderFragmentRoot, 0x620ce2a5, 0xab8f, 0x40a9, 0x86,0xcb, 0xde,0x3c,0x75,0x59,0x9b,0x58); +MIDL_INTERFACE("620ce2a5-ab8f-40a9-86cb-de3c75599b58") +IRawElementProviderFragmentRoot : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE ElementProviderFromPoint(double x, double y, __RPC__deref_out_opt IRawElementProviderFragment **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFocus(__RPC__deref_out_opt IRawElementProviderFragment **pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IRawElementProviderFragmentRoot, 0x620ce2a5, 0xab8f, 0x40a9, 0x86,0xcb, 0xde,0x3c,0x75,0x59,0x9b,0x58) +#endif +#endif + + +#ifndef __IValueProvider_INTERFACE_DEFINED__ +#define __IValueProvider_INTERFACE_DEFINED__ +DEFINE_GUID(IID_IValueProvider, 0xc7935180, 0x6fb3, 0x4201, 0xb1,0x74, 0x7d,0xf7,0x3a,0xdb,0xf6,0x4a); +MIDL_INTERFACE("c7935180-6fb3-4201-b174-7df73adbf64a") +IValueProvider : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE SetValue(__RPC__in LPCWSTR val) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Value(__RPC__deref_out_opt BSTR *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_IsReadOnly(__RPC__out BOOL *pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IValueProvider, 0xc7935180, 0x6fb3, 0x4201, 0xb1,0x74, 0x7d,0xf7,0x3a,0xdb,0xf6,0x4a) +#endif +#endif + + +#ifndef __IRangeValueProvider_INTERFACE_DEFINED__ +#define __IRangeValueProvider_INTERFACE_DEFINED__ +DEFINE_GUID(IID_IRangeValueProvider, 0x36dc7aef, 0x33e6, 0x4691, 0xaf,0xe1, 0x2b,0xe7,0x27,0x4b,0x3d,0x33); +MIDL_INTERFACE("36dc7aef-33e6-4691-afe1-2be7274b3d33") +IRangeValueProvider : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE SetValue(double val) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Value(__RPC__out double *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_IsReadOnly(__RPC__out BOOL *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Maximum(__RPC__out double *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Minimum(__RPC__out double *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_LargeChange(__RPC__out double *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_SmallChange(__RPC__out double *pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IRangeValueProvider, 0x36dc7aef, 0x33e6, 0x4691, 0xaf,0xe1, 0x2b,0xe7,0x27,0x4b,0x3d,0x33) +#endif +#endif + + +#ifndef __ITextRangeProvider_INTERFACE_DEFINED__ +#define __ITextRangeProvider_INTERFACE_DEFINED__ +DEFINE_GUID(IID_ITextRangeProvider, 0x5347ad7b, 0xc355, 0x46f8, 0xaf,0xf5, 0x90,0x90,0x33,0x58,0x2f,0x63); +MIDL_INTERFACE("5347ad7b-c355-46f8-aff5-909033582f63") +ITextRangeProvider : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE Clone(__RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE Compare(__RPC__in_opt ITextRangeProvider *range, __RPC__out BOOL *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE CompareEndpoints(enum TextPatternRangeEndpoint endpoint, __RPC__in_opt ITextRangeProvider *targetRange, enum TextPatternRangeEndpoint targetEndpoint, __RPC__out int *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE ExpandToEnclosingUnit(enum TextUnit unit) = 0; + virtual HRESULT STDMETHODCALLTYPE FindAttribute(TEXTATTRIBUTEID attributeId, VARIANT val, BOOL backward, __RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE FindText(__RPC__in BSTR text, BOOL backward, BOOL ignoreCase, __RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetAttributeValue(TEXTATTRIBUTEID attributeId, __RPC__out VARIANT *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetBoundingRectangles(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetEnclosingElement(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetText(int maxLength, __RPC__deref_out_opt BSTR *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE Move(enum TextUnit unit, int count, __RPC__out int *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE MoveEndpointByUnit(enum TextPatternRangeEndpoint endpoint, enum TextUnit unit, int count, __RPC__out int *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE MoveEndpointByRange(enum TextPatternRangeEndpoint endpoint, __RPC__in_opt ITextRangeProvider *targetRange, enum TextPatternRangeEndpoint targetEndpoint) = 0; + virtual HRESULT STDMETHODCALLTYPE Select() = 0; + virtual HRESULT STDMETHODCALLTYPE AddToSelection() = 0; + virtual HRESULT STDMETHODCALLTYPE RemoveFromSelection() = 0; + virtual HRESULT STDMETHODCALLTYPE ScrollIntoView(BOOL alignToTop) = 0; + virtual HRESULT STDMETHODCALLTYPE GetChildren(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ITextRangeProvider, 0x5347ad7b, 0xc355, 0x46f8, 0xaf,0xf5, 0x90,0x90,0x33,0x58,0x2f,0x63) +#endif +#endif + + +#ifndef __ITextProvider_INTERFACE_DEFINED__ +#define __ITextProvider_INTERFACE_DEFINED__ +DEFINE_GUID(IID_ITextProvider, 0x3589c92c, 0x63f3, 0x4367, 0x99,0xbb, 0xad,0xa6,0x53,0xb7,0x7c,0xf2); +MIDL_INTERFACE("3589c92c-63f3-4367-99bb-ada653b77cf2") +ITextProvider : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE GetSelection(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetVisibleRanges(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE RangeFromChild(__RPC__in_opt IRawElementProviderSimple *childElement, __RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE RangeFromPoint(struct UiaPoint point, __RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_DocumentRange(__RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_SupportedTextSelection(__RPC__out enum SupportedTextSelection *pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ITextProvider, 0x3589c92c, 0x63f3, 0x4367, 0x99,0xbb, 0xad,0xa6,0x53,0xb7,0x7c,0xf2) +#endif +#endif + + +#ifndef __ITextProvider2_INTERFACE_DEFINED__ +#define __ITextProvider2_INTERFACE_DEFINED__ +DEFINE_GUID(IID_ITextProvider2, 0x0dc5e6ed, 0x3e16, 0x4bf1, 0x8f,0x9a, 0xa9,0x79,0x87,0x8b,0xc1,0x95); +MIDL_INTERFACE("0dc5e6ed-3e16-4bf1-8f9a-a979878bc195") +ITextProvider2 : public ITextProvider +{ +public: + virtual HRESULT STDMETHODCALLTYPE RangeFromAnnotation(__RPC__in_opt IRawElementProviderSimple *annotationElement, __RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCaretRange(__RPC__out BOOL *isActive, __RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ITextProvider2, 0x0dc5e6ed, 0x3e16, 0x4bf1, 0x8f,0x9a, 0xa9,0x79,0x87,0x8b,0xc1,0x95) +#endif +#endif + + +#ifndef __IToggleProvider_INTERFACE_DEFINED__ +#define __IToggleProvider_INTERFACE_DEFINED__ +DEFINE_GUID(IID_IToggleProvider, 0x56d00bd0, 0xc4f4, 0x433c, 0xa8,0x36, 0x1a,0x52,0xa5,0x7e,0x08,0x92); +MIDL_INTERFACE("56d00bd0-c4f4-433c-a836-1a52a57e0892") +IToggleProvider : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE Toggle() = 0; + virtual HRESULT STDMETHODCALLTYPE get_ToggleState(__RPC__out enum ToggleState *pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IToggleProvider, 0x56d00bd0, 0xc4f4, 0x433c, 0xa8,0x36, 0x1a,0x52,0xa5,0x7e,0x08,0x92) +#endif +#endif + + +#ifndef __IInvokeProvider_INTERFACE_DEFINED__ +#define __IInvokeProvider_INTERFACE_DEFINED__ +DEFINE_GUID(IID_IInvokeProvider, 0x54fcb24b, 0xe18e, 0x47a2, 0xb4,0xd3, 0xec,0xcb,0xe7,0x75,0x99,0xa2); +MIDL_INTERFACE("54fcb24b-e18e-47a2-b4d3-eccbe77599a2") +IInvokeProvider : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE Invoke() = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IInvokeProvider, 0x54fcb24b, 0xe18e, 0x47a2, 0xb4,0xd3, 0xec,0xcb,0xe7,0x75,0x99,0xa2) +#endif +#endif + + +#ifndef __ISelectionProvider_INTERFACE_DEFINED__ +#define __ISelectionProvider_INTERFACE_DEFINED__ +DEFINE_GUID(IID_ISelectionProvider, 0xfb8b03af, 0x3bdf, 0x48d4, 0xbd,0x36, 0x1a,0x65,0x79,0x3b,0xe1,0x68); +MIDL_INTERFACE("fb8b03af-3bdf-48d4-bd36-1a65793be168") +ISelectionProvider : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE GetSelection(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_CanSelectMultiple(__RPC__out BOOL *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_IsSelectionRequired(__RPC__out BOOL *pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ISelectionProvider, 0xfb8b03af, 0x3bdf, 0x48d4, 0xbd,0x36, 0x1a,0x65,0x79,0x3b,0xe1,0x68) +#endif +#endif + + +#ifndef __ISelectionItemProvider_INTERFACE_DEFINED__ +#define __ISelectionItemProvider_INTERFACE_DEFINED__ +DEFINE_GUID(IID_ISelectionItemProvider, 0x2acad808, 0xb2d4, 0x452d, 0xa4,0x07, 0x91,0xff,0x1a,0xd1,0x67,0xb2); +MIDL_INTERFACE("2acad808-b2d4-452d-a407-91ff1ad167b2") +ISelectionItemProvider : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE Select() = 0; + virtual HRESULT STDMETHODCALLTYPE AddToSelection() = 0; + virtual HRESULT STDMETHODCALLTYPE RemoveFromSelection() = 0; + virtual HRESULT STDMETHODCALLTYPE get_IsSelected(__RPC__out BOOL *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_SelectionContainer(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ISelectionItemProvider, 0x2acad808, 0xb2d4, 0x452d, 0xa4,0x07, 0x91,0xff,0x1a,0xd1,0x67,0xb2) +#endif +#endif + + +#ifndef __ITableProvider_INTERFACE_DEFINED__ +#define __ITableProvider_INTERFACE_DEFINED__ +DEFINE_GUID(IID_ITableProvider, 0x9c860395, 0x97b3, 0x490a, 0xb5,0x2a, 0x85,0x8c,0xc2,0x2a,0xf1,0x66); +MIDL_INTERFACE("9c860395-97b3-490a-b52a-858cc22af166") +ITableProvider : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE GetRowHeaders(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetColumnHeaders(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_RowOrColumnMajor(__RPC__out enum RowOrColumnMajor *pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ITableProvider, 0x9c860395, 0x97b3, 0x490a, 0xb5,0x2a, 0x85,0x8c,0xc2,0x2a,0xf1,0x66) +#endif +#endif + + +#ifndef __ITableItemProvider_INTERFACE_DEFINED__ +#define __ITableItemProvider_INTERFACE_DEFINED__ +DEFINE_GUID(IID_ITableItemProvider, 0xb9734fa6, 0x771f, 0x4d78, 0x9c,0x90, 0x25,0x17,0x99,0x93,0x49,0xcd); +MIDL_INTERFACE("b9734fa6-771f-4d78-9c90-2517999349cd") +ITableItemProvider : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE GetRowHeaderItems(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE GetColumnHeaderItems(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ITableItemProvider, 0xb9734fa6, 0x771f, 0x4d78, 0x9c,0x90, 0x25,0x17,0x99,0x93,0x49,0xcd) +#endif +#endif + + +#ifndef __IGridProvider_INTERFACE_DEFINED__ +#define __IGridProvider_INTERFACE_DEFINED__ +DEFINE_GUID(IID_IGridProvider, 0xb17d6187, 0x0907, 0x464b, 0xa1,0x68, 0x0e,0xf1,0x7a,0x15,0x72,0xb1); +MIDL_INTERFACE("b17d6187-0907-464b-a168-0ef17a1572b1") +IGridProvider : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE GetItem(int row, int column, __RPC__deref_out_opt IRawElementProviderSimple **pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_RowCount(__RPC__out int *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ColumnCount(__RPC__out int *pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IGridProvider, 0xb17d6187, 0x0907, 0x464b, 0xa1,0x68, 0x0e,0xf1,0x7a,0x15,0x72,0xb1) +#endif +#endif + + +#ifndef __IGridItemProvider_INTERFACE_DEFINED__ +#define __IGridItemProvider_INTERFACE_DEFINED__ +DEFINE_GUID(IID_IGridItemProvider, 0xd02541f1, 0xfb81, 0x4d64, 0xae,0x32, 0xf5,0x20,0xf8,0xa6,0xdb,0xd1); +MIDL_INTERFACE("d02541f1-fb81-4d64-ae32-f520f8a6dbd1") +IGridItemProvider : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE get_Row(__RPC__out int *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Column(__RPC__out int *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_RowSpan(__RPC__out int *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ColumnSpan(__RPC__out int *pRetVal) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ContainingGrid(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IGridItemProvider, 0xd02541f1, 0xfb81, 0x4d64, 0xae,0x32, 0xf5,0x20,0xf8,0xa6,0xdb,0xd1) +#endif +#endif + +#endif diff --git a/src/platformsupport/windowsuiautomation/uiatypes.h b/src/platformsupport/windowsuiautomation/uiatypes.h new file mode 100644 index 0000000000..25d8b8cb2b --- /dev/null +++ b/src/platformsupport/windowsuiautomation/uiatypes.h @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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 UIATYPES_H +#define UIATYPES_H + +typedef int PROPERTYID; +typedef int PATTERNID; +typedef int EVENTID; +typedef int TEXTATTRIBUTEID; +typedef int CONTROLTYPEID; +typedef int LANDMARKTYPEID; +typedef int METADATAID; + +typedef void *UIA_HWND; + +enum NavigateDirection { + NavigateDirection_Parent = 0, + NavigateDirection_NextSibling = 1, + NavigateDirection_PreviousSibling = 2, + NavigateDirection_FirstChild = 3, + NavigateDirection_LastChild = 4 +}; + +enum ProviderOptions { + ProviderOptions_ClientSideProvider = 0x1, + ProviderOptions_ServerSideProvider = 0x2, + ProviderOptions_NonClientAreaProvider = 0x4, + ProviderOptions_OverrideProvider = 0x8, + ProviderOptions_ProviderOwnsSetFocus = 0x10, + ProviderOptions_UseComThreading = 0x20, + ProviderOptions_RefuseNonClientSupport = 0x40, + ProviderOptions_HasNativeIAccessible = 0x80, + ProviderOptions_UseClientCoordinates = 0x100 +}; + +enum SupportedTextSelection { + SupportedTextSelection_None = 0, + SupportedTextSelection_Single = 1, + SupportedTextSelection_Multiple = 2 +}; + +enum TextUnit { + TextUnit_Character = 0, + TextUnit_Format = 1, + TextUnit_Word = 2, + TextUnit_Line = 3, + TextUnit_Paragraph = 4, + TextUnit_Page = 5, + TextUnit_Document = 6 +}; + +enum TextPatternRangeEndpoint { + TextPatternRangeEndpoint_Start = 0, + TextPatternRangeEndpoint_End = 1 +}; + +enum CaretPosition { + CaretPosition_Unknown = 0, + CaretPosition_EndOfLine = 1, + CaretPosition_BeginningOfLine = 2 +}; + +enum ToggleState { + ToggleState_Off = 0, + ToggleState_On = 1, + ToggleState_Indeterminate = 2 +}; + +enum RowOrColumnMajor { + RowOrColumnMajor_RowMajor = 0, + RowOrColumnMajor_ColumnMajor = 1, + RowOrColumnMajor_Indeterminate = 2 +}; + +enum TreeScope { + TreeScope_None = 0, + TreeScope_Element = 0x1, + TreeScope_Children = 0x2, + TreeScope_Descendants = 0x4, + TreeScope_Parent = 0x8, + TreeScope_Ancestors = 0x10, + TreeScope_Subtree = TreeScope_Element | TreeScope_Children | TreeScope_Descendants +}; + +enum OrientationType { + OrientationType_None = 0, + OrientationType_Horizontal = 1, + OrientationType_Vertical = 2 +}; + +enum PropertyConditionFlags { + PropertyConditionFlags_None = 0, + PropertyConditionFlags_IgnoreCase = 1 +}; + +struct UiaRect { + double left; + double top; + double width; + double height; +}; + +struct UiaPoint { + double x; + double y; +}; + +#endif diff --git a/src/platformsupport/windowsuiautomation/windowsuiautomation.pro b/src/platformsupport/windowsuiautomation/windowsuiautomation.pro new file mode 100644 index 0000000000..28c26477f3 --- /dev/null +++ b/src/platformsupport/windowsuiautomation/windowsuiautomation.pro @@ -0,0 +1,23 @@ +TARGET = QtWindowsUIAutomationSupport +MODULE = windowsuiautomation_support + +QT = core-private gui-private +CONFIG += static internal_module + +HEADERS += \ + qwindowsuiawrapper_p.h \ + uiaattributeids.h \ + uiacontroltypeids.h \ + uiaerrorids.h \ + uiaeventids.h \ + uiageneralids.h \ + uiaserverinterfaces.h \ + uiaclientinterfaces.h \ + uiapatternids.h \ + uiapropertyids.h \ + uiatypes.h + +SOURCES += \ + qwindowsuiawrapper.cpp + +load(qt_module) 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 diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index d07c413100..c146f8ec25 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -53,7 +53,7 @@ #include "qwindowstheme.h" #include #ifndef QT_NO_ACCESSIBILITY -# include "accessible/qwindowsaccessibility.h" +# include "uiautomation/qwindowsuiaaccessibility.h" #endif #if QT_CONFIG(sessionmanager) # include @@ -98,6 +98,7 @@ Q_LOGGING_CATEGORY(lcQpaDialogs, "qt.qpa.dialogs") Q_LOGGING_CATEGORY(lcQpaMenus, "qt.qpa.menus") Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") Q_LOGGING_CATEGORY(lcQpaAccessibility, "qt.qpa.accessibility") +Q_LOGGING_CATEGORY(lcQpaUiAutomation, "qt.qpa.uiautomation") Q_LOGGING_CATEGORY(lcQpaTrayIcon, "qt.qpa.trayicon") int QWindowsContext::verbose = 0; @@ -957,7 +958,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return false; case QtWindows::AccessibleObjectFromWindowRequest: #ifndef QT_NO_ACCESSIBILITY - return QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(hwnd, wParam, lParam, result); + return QWindowsUiaAccessibility::handleWmGetObject(hwnd, wParam, lParam, result); #else return false; #endif diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 45c24bf53b..f2ec307be2 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -66,6 +66,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaDialogs) Q_DECLARE_LOGGING_CATEGORY(lcQpaMenus) Q_DECLARE_LOGGING_CATEGORY(lcQpaTablet) Q_DECLARE_LOGGING_CATEGORY(lcQpaAccessibility) +Q_DECLARE_LOGGING_CATEGORY(lcQpaUiAutomation) Q_DECLARE_LOGGING_CATEGORY(lcQpaTrayIcon) class QWindow; diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index f0be761690..287b65cd5d 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -60,7 +60,7 @@ #include "qwindowsinputcontext.h" #include "qwindowskeymapper.h" #ifndef QT_NO_ACCESSIBILITY -# include "accessible/qwindowsaccessibility.h" +# include "uiautomation/qwindowsuiaaccessibility.h" #endif #include @@ -151,7 +151,7 @@ struct QWindowsIntegrationPrivate #endif // QT_NO_OPENGL QScopedPointer m_inputContext; #ifndef QT_NO_ACCESSIBILITY - QWindowsAccessibility m_accessibility; + QWindowsUiaAccessibility m_accessibility; #endif QWindowsServices m_services; }; diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp new file mode 100644 index 0000000000..907883bf5b --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiaaccessibility.h" +#include "qwindowsuiamainprovider.h" +#include "qwindowsuiautils.h" + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaAccessibility::QWindowsUiaAccessibility() +{ +} + +QWindowsUiaAccessibility::~QWindowsUiaAccessibility() +{ +} + +// Handles UI Automation window messages. +bool QWindowsUiaAccessibility::handleWmGetObject(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult) +{ + if (lParam == LPARAM(UiaRootObjectId)) { + + // Start handling accessibility internally + QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true); + + // Ignoring all requests while starting up / shutting down + if (QCoreApplication::startingUp() || QCoreApplication::closingDown()) + return false; + + if (QWindow *window = QWindowsContext::instance()->findWindow(hwnd)) { + if (QAccessibleInterface *accessible = window->accessibleRoot()) { + QWindowsUiaMainProvider *provider = QWindowsUiaMainProvider::providerForAccessible(accessible); + *lResult = QWindowsUiaWrapper::instance()->returnRawElementProvider(hwnd, wParam, lParam, provider); + return true; + } + } + } + return false; +} + +// Handles accessibility update notifications. +void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event) +{ + if (!event) + return; + + QAccessibleInterface *accessible = event->accessibleInterface(); + if (!isActive() || !accessible || !accessible->isValid()) + return; + + // Ensures QWindowsUiaWrapper is properly initialized. + if (!QWindowsUiaWrapper::instance()->ready()) + return; + + // No need to do anything when nobody is listening. + if (!QWindowsUiaWrapper::instance()->clientsAreListening()) + return; + + switch (event->type()) { + + case QAccessible::Focus: + QWindowsUiaMainProvider::notifyFocusChange(event); + break; + + case QAccessible::StateChanged: + QWindowsUiaMainProvider::notifyStateChange(static_cast(event)); + break; + + case QAccessible::ValueChanged: + QWindowsUiaMainProvider::notifyValueChange(static_cast(event)); + break; + + case QAccessible::TextAttributeChanged: + case QAccessible::TextColumnChanged: + case QAccessible::TextInserted: + case QAccessible::TextRemoved: + case QAccessible::TextUpdated: + case QAccessible::TextSelectionChanged: + case QAccessible::TextCaretMoved: + QWindowsUiaMainProvider::notifyTextChange(event); + break; + + default: + break; + } +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h new file mode 100644 index 0000000000..bbb81d596b --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIAACCESSIBILITY_H +#define QWINDOWSUIAACCESSIBILITY_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowscontext.h" +#include + +QT_BEGIN_NAMESPACE + +// Windows plataform accessibility implemented over UI Automation. +class QWindowsUiaAccessibility : public QPlatformAccessibility +{ +public: + explicit QWindowsUiaAccessibility(); + virtual ~QWindowsUiaAccessibility(); + static bool handleWmGetObject(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult); + void notifyAccessibilityUpdate(QAccessibleEvent *event) override; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIAACCESSIBILITY_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp new file mode 100644 index 0000000000..1e1fc49c0f --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiabaseprovider.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaBaseProvider::QWindowsUiaBaseProvider(QAccessible::Id id) : + m_id(id) +{ +} + +QWindowsUiaBaseProvider::~QWindowsUiaBaseProvider() +{ +} + +QAccessibleInterface *QWindowsUiaBaseProvider::accessibleInterface() const +{ + QAccessibleInterface *accessible = QAccessible::accessibleInterface(m_id); + if (accessible && accessible->isValid()) + return accessible; + return nullptr; +} + +QAccessible::Id QWindowsUiaBaseProvider::id() const +{ + return m_id; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h new file mode 100644 index 0000000000..3ae403e8c5 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIABASEPROVIDER_H +#define QWINDOWSUIABASEPROVIDER_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QAccessibleInterface; +class QDebug; + +// Base class for UI Automation providers. +class QWindowsUiaBaseProvider : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(QWindowsUiaBaseProvider) +public: + explicit QWindowsUiaBaseProvider(QAccessible::Id id); + virtual ~QWindowsUiaBaseProvider(); + + QAccessibleInterface *accessibleInterface() const; + QAccessible::Id id() const; + +private: + QAccessible::Id m_id; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIABASEPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp new file mode 100644 index 0000000000..e0502c00f3 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiagriditemprovider.h" +#include "qwindowsuiamainprovider.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaGridItemProvider::QWindowsUiaGridItemProvider(QAccessible::Id id) : + QWindowsUiaBaseProvider(id) +{ +} + +QWindowsUiaGridItemProvider::~QWindowsUiaGridItemProvider() +{ +} + +// Returns the row index of the item. +HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_Row(int *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = 0; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface(); + if (!tableCellInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + *pRetVal = tableCellInterface->rowIndex(); + return S_OK; +} + +// Returns the column index of the item. +HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_Column(int *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = 0; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface(); + if (!tableCellInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + *pRetVal = tableCellInterface->columnIndex(); + return S_OK; +} + +// Returns the number of rows occupied by the item. +HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_RowSpan(int *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = 0; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface(); + if (!tableCellInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + *pRetVal = tableCellInterface->rowExtent(); + return S_OK; +} + +// Returns the number of columns occupied by the item. +HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_ColumnSpan(int *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = 0; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface(); + if (!tableCellInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + *pRetVal = tableCellInterface->columnExtent(); + return S_OK; +} + +// Returns the provider for the cointaining table/tree. +HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_ContainingGrid(IRawElementProviderSimple **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface(); + if (!tableCellInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + if (QAccessibleInterface *table = tableCellInterface->table()) { + *pRetVal = QWindowsUiaMainProvider::providerForAccessible(table); + } + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h new file mode 100644 index 0000000000..a93b50ef97 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIAGRIDITEMPROVIDER_H +#define QWINDOWSUIAGRIDITEMPROVIDER_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsuiabaseprovider.h" + +QT_BEGIN_NAMESPACE + +// Implements the Grid Item control pattern provider. Used by items within a table/tree. +class QWindowsUiaGridItemProvider : public QWindowsUiaBaseProvider, + public QWindowsComBase +{ + Q_DISABLE_COPY(QWindowsUiaGridItemProvider) +public: + explicit QWindowsUiaGridItemProvider(QAccessible::Id id); + virtual ~QWindowsUiaGridItemProvider(); + + // IGridItemProvider + HRESULT STDMETHODCALLTYPE get_Row(int *pRetVal); + HRESULT STDMETHODCALLTYPE get_Column(int *pRetVal); + HRESULT STDMETHODCALLTYPE get_RowSpan(int *pRetVal); + HRESULT STDMETHODCALLTYPE get_ColumnSpan(int *pRetVal); + HRESULT STDMETHODCALLTYPE get_ContainingGrid(IRawElementProviderSimple **pRetVal); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIAGRIDITEMPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp new file mode 100644 index 0000000000..65c2df703b --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiagridprovider.h" +#include "qwindowsuiamainprovider.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaGridProvider::QWindowsUiaGridProvider(QAccessible::Id id) : + QWindowsUiaBaseProvider(id) +{ +} + +QWindowsUiaGridProvider::~QWindowsUiaGridProvider() +{ +} + +// Returns the provider for an item within a table/tree. +HRESULT STDMETHODCALLTYPE QWindowsUiaGridProvider::GetItem(int row, int column, IRawElementProviderSimple **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTableInterface *tableInterface = accessible->tableInterface(); + if (!tableInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + if ((row >= 0) && (row < tableInterface->rowCount()) && (column >= 0) && (column < tableInterface->columnCount())) { + if (QAccessibleInterface *cell = tableInterface->cellAt(row, column)) { + *pRetVal = QWindowsUiaMainProvider::providerForAccessible(cell); + } + } + return S_OK; +} + +// Returns the number of rows. +HRESULT STDMETHODCALLTYPE QWindowsUiaGridProvider::get_RowCount(int *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = 0; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTableInterface *tableInterface = accessible->tableInterface(); + if (!tableInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + *pRetVal = tableInterface->rowCount(); + return S_OK; +} + +// Returns the number of columns. +HRESULT STDMETHODCALLTYPE QWindowsUiaGridProvider::get_ColumnCount(int *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = 0; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTableInterface *tableInterface = accessible->tableInterface(); + if (!tableInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + *pRetVal = tableInterface->columnCount(); + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h new file mode 100644 index 0000000000..15521f98b3 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIAGRIDPROVIDER_H +#define QWINDOWSUIAGRIDPROVIDER_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsuiabaseprovider.h" + +QT_BEGIN_NAMESPACE + +// Implements the Grid control pattern provider. Used by tables/trees. +class QWindowsUiaGridProvider : public QWindowsUiaBaseProvider, + public QWindowsComBase +{ + Q_DISABLE_COPY(QWindowsUiaGridProvider) +public: + explicit QWindowsUiaGridProvider(QAccessible::Id id); + virtual ~QWindowsUiaGridProvider(); + + // IGridProvider + HRESULT STDMETHODCALLTYPE GetItem(int row, int column, IRawElementProviderSimple **pRetVal); + HRESULT STDMETHODCALLTYPE get_RowCount(int *pRetVal); + HRESULT STDMETHODCALLTYPE get_ColumnCount(int *pRetVal); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIAGRIDPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp new file mode 100644 index 0000000000..2af883c4f6 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiainvokeprovider.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaInvokeProvider::QWindowsUiaInvokeProvider(QAccessible::Id id) : + QWindowsUiaBaseProvider(id) +{ +} + +QWindowsUiaInvokeProvider::~QWindowsUiaInvokeProvider() +{ +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaInvokeProvider::Invoke() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleActionInterface *actionInterface = accessible->actionInterface(); + if (!actionInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + actionInterface->doAction(QAccessibleActionInterface::pressAction()); + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h new file mode 100644 index 0000000000..2b8a646983 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIAINVOKEPROVIDER_H +#define QWINDOWSUIAINVOKEPROVIDER_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsuiabaseprovider.h" + +QT_BEGIN_NAMESPACE + +// Implements the Invoke control pattern provider. +class QWindowsUiaInvokeProvider : public QWindowsUiaBaseProvider, + public QWindowsComBase +{ + Q_DISABLE_COPY(QWindowsUiaInvokeProvider) +public: + explicit QWindowsUiaInvokeProvider(QAccessible::Id id); + virtual ~QWindowsUiaInvokeProvider(); + + // IInvokeProvider + HRESULT STDMETHODCALLTYPE Invoke(); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIAINVOKEPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp new file mode 100644 index 0000000000..46f73f81a0 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -0,0 +1,638 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiamainprovider.h" +#include "qwindowsuiavalueprovider.h" +#include "qwindowsuiarangevalueprovider.h" +#include "qwindowsuiatextprovider.h" +#include "qwindowsuiatoggleprovider.h" +#include "qwindowsuiainvokeprovider.h" +#include "qwindowsuiaselectionprovider.h" +#include "qwindowsuiaselectionitemprovider.h" +#include "qwindowsuiatableprovider.h" +#include "qwindowsuiatableitemprovider.h" +#include "qwindowsuiagridprovider.h" +#include "qwindowsuiagriditemprovider.h" +#include "qwindowscombase.h" +#include "qwindowscontext.h" +#include "qwindowsuiautils.h" +#include "qwindowsuiaprovidercache.h" + +#include +#include +#include +#include + +#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU) +#include +#endif + +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +// Returns a cached instance of the provider for a specific acessible interface. +QWindowsUiaMainProvider *QWindowsUiaMainProvider::providerForAccessible(QAccessibleInterface *accessible) +{ + if (!accessible) + return nullptr; + + QAccessible::Id id = QAccessible::uniqueId(accessible); + QWindowsUiaProviderCache *providerCache = QWindowsUiaProviderCache::instance(); + QWindowsUiaMainProvider *provider = qobject_cast(providerCache->providerForId(id)); + + if (provider) { + provider->AddRef(); + } else { + provider = new QWindowsUiaMainProvider(accessible); + providerCache->insert(id, provider); + } + return provider; +} + +QWindowsUiaMainProvider::QWindowsUiaMainProvider(QAccessibleInterface *a, int initialRefCount) + : QWindowsUiaBaseProvider(QAccessible::uniqueId(a)), + m_ref(initialRefCount) +{ +} + +QWindowsUiaMainProvider::~QWindowsUiaMainProvider() +{ +} + +void QWindowsUiaMainProvider::notifyFocusChange(QAccessibleEvent *event) +{ + if (QAccessibleInterface *accessible = event->accessibleInterface()) { + if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_AutomationFocusChangedEventId); + } + } +} + +void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *event) +{ + if (QAccessibleInterface *accessible = event->accessibleInterface()) { + if (event->changedStates().checked || event->changedStates().checkStateMixed) { + // Notifies states changes in checkboxes. + if (accessible->role() == QAccessible::CheckBox) { + if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + VARIANT oldVal, newVal; + clearVariant(&oldVal); + int toggleState = ToggleState_Off; + if (accessible->state().checked) + toggleState = accessible->state().checkStateMixed ? ToggleState_Indeterminate : ToggleState_On; + setVariantI4(toggleState, &newVal); + QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ToggleToggleStatePropertyId, oldVal, newVal); + } + } + } + if (event->changedStates().active) { + if (accessible->role() == QAccessible::Window) { + // Notifies window opened/closed. + if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + if (accessible->state().active) { + QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Window_WindowOpenedEventId); + } else { + QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Window_WindowClosedEventId); + } + } + } + } + } +} + +void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *event) +{ + if (QAccessibleInterface *accessible = event->accessibleInterface()) { + if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) { + // Notifies changes in values of controls supporting the value interface. + if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + VARIANT oldVal, newVal; + clearVariant(&oldVal); + setVariantDouble(valueInterface->currentValue().toDouble(), &newVal); + QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_RangeValueValuePropertyId, oldVal, newVal); + } + } + } +} + +// Notifies changes in text content and selection state of text controls. +void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event) +{ + if (QAccessibleInterface *accessible = event->accessibleInterface()) { + if (accessible->textInterface()) { + if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + if (event->type() == QAccessible::TextSelectionChanged) { + QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Text_TextSelectionChangedEventId); + } else if (event->type() == QAccessible::TextCaretMoved) { + if (!accessible->state().readOnly) { + QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Text_TextSelectionChangedEventId); + } + } else { + QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Text_TextChangedEventId); + } + } + } + } +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaMainProvider::QueryInterface(REFIID iid, LPVOID *iface) +{ + if (!iface) + return E_INVALIDARG; + *iface = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + + const bool result = qWindowsComQueryUnknownInterfaceMulti(this, iid, iface) + || qWindowsComQueryInterface(this, iid, iface) + || qWindowsComQueryInterface(this, iid, iface) + || (accessible && hwndForAccessible(accessible) && qWindowsComQueryInterface(this, iid, iface)); + return result ? S_OK : E_NOINTERFACE; +} + +ULONG QWindowsUiaMainProvider::AddRef() +{ + return ++m_ref; +} + +ULONG STDMETHODCALLTYPE QWindowsUiaMainProvider::Release() +{ + if (!--m_ref) { + delete this; + return 0; + } + return m_ref; +} + +HRESULT QWindowsUiaMainProvider::get_ProviderOptions(ProviderOptions *pRetVal) +{ + if (!pRetVal) + return E_INVALIDARG; + // We are STA, (OleInitialize()). + *pRetVal = static_cast(ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading); + return S_OK; +} + +// Return providers for specific control patterns +HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknown **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << idPattern; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + switch (idPattern) { + case UIA_TextPatternId: + case UIA_TextPattern2Id: + // All text controls. + if (accessible->textInterface()) { + *pRetVal = new QWindowsUiaTextProvider(id()); + } + break; + case UIA_ValuePatternId: + // All accessible controls return text(QAccessible::Value) (which may be empty). + *pRetVal = new QWindowsUiaValueProvider(id()); + break; + case UIA_RangeValuePatternId: + // Controls providing a numeric value within a range (e.g., sliders, scroll bars, dials). + if (accessible->valueInterface()) { + *pRetVal = new QWindowsUiaRangeValueProvider(id()); + } + break; + case UIA_TogglePatternId: + // Checkbox controls. + if (accessible->role() == QAccessible::CheckBox) { + *pRetVal = new QWindowsUiaToggleProvider(id()); + } + break; + case UIA_SelectionPatternId: + // Lists of items. + if (accessible->role() == QAccessible::List) { + *pRetVal = new QWindowsUiaSelectionProvider(id()); + } + break; + case UIA_SelectionItemPatternId: + // Items within a list and radio buttons. + if ((accessible->role() == QAccessible::RadioButton) + || (accessible->role() == QAccessible::ListItem)) { + *pRetVal = new QWindowsUiaSelectionItemProvider(id()); + } + break; + case UIA_TablePatternId: + // Table/tree. + if (accessible->tableInterface() + && ((accessible->role() == QAccessible::Table) || (accessible->role() == QAccessible::Tree))) { + *pRetVal = new QWindowsUiaTableProvider(id()); + } + break; + case UIA_TableItemPatternId: + // Item within a table/tree. + if (accessible->tableCellInterface() + && ((accessible->role() == QAccessible::Cell) || (accessible->role() == QAccessible::TreeItem))) { + *pRetVal = new QWindowsUiaTableItemProvider(id()); + } + break; + case UIA_GridPatternId: + // Table/tree. + if (accessible->tableInterface() + && ((accessible->role() == QAccessible::Table) || (accessible->role() == QAccessible::Tree))) { + *pRetVal = new QWindowsUiaGridProvider(id()); + } + break; + case UIA_GridItemPatternId: + // Item within a table/tree. + if (accessible->tableCellInterface() + && ((accessible->role() == QAccessible::Cell) || (accessible->role() == QAccessible::TreeItem))) { + *pRetVal = new QWindowsUiaGridItemProvider(id()); + } + break; + case UIA_InvokePatternId: + // Things that have an invokable action (e.g., simple buttons). + if (accessible->actionInterface()) { + *pRetVal = new QWindowsUiaInvokeProvider(id()); + } + break; + default: + break; + } + + return S_OK; +} + +HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << idProp; + + if (!pRetVal) + return E_INVALIDARG; + clearVariant(pRetVal); + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + bool clientTopLevel = (accessible->role() == QAccessible::Client) + && accessible->parent() && (accessible->parent()->role() == QAccessible::Application); + + switch (idProp) { + case UIA_ProcessIdPropertyId: + // PID + setVariantI4(int(GetCurrentProcessId()), pRetVal); + break; + case UIA_AccessKeyPropertyId: + // Accelerator key. + setVariantString(accessible->text(QAccessible::Accelerator), pRetVal); + break; + case UIA_AutomationIdPropertyId: + // Automation ID, which can be used by tools to select a specific control in the UI. + setVariantString(automationIdForAccessible(accessible), pRetVal); + break; + case UIA_ClassNamePropertyId: + // Class name. + if (QObject *o = accessible->object()) { + QString className = QLatin1String(o->metaObject()->className()); + setVariantString(className, pRetVal); + } + break; + case UIA_FrameworkIdPropertyId: + setVariantString(QStringLiteral("Qt"), pRetVal); + break; + case UIA_ControlTypePropertyId: + if (clientTopLevel) { + // Reports a top-level widget as a window, instead of "custom". + setVariantI4(UIA_WindowControlTypeId, pRetVal); + } else { + // Control type converted from role. + setVariantI4(roleToControlTypeId(accessible->role()), pRetVal); + } + break; + case UIA_HelpTextPropertyId: + setVariantString(accessible->text(QAccessible::Help), pRetVal); + break; + case UIA_HasKeyboardFocusPropertyId: + setVariantBool(accessible->state().focused, pRetVal); + break; + case UIA_IsKeyboardFocusablePropertyId: + setVariantBool(accessible->state().focusable, pRetVal); + break; + case UIA_IsOffscreenPropertyId: + setVariantBool(false, pRetVal); + break; + case UIA_IsContentElementPropertyId: + setVariantBool(true, pRetVal); + break; + case UIA_IsControlElementPropertyId: + setVariantBool(true, pRetVal); + break; + case UIA_IsEnabledPropertyId: + setVariantBool(!accessible->state().disabled, pRetVal); + break; + case UIA_IsPasswordPropertyId: + setVariantBool(accessible->role() == QAccessible::EditableText + && accessible->state().passwordEdit, pRetVal); + break; + case UIA_IsPeripheralPropertyId: + // True for peripheral UIs. + if (QWindow *window = windowForAccessible(accessible)) { + const Qt::WindowType wt = window->type(); + setVariantBool(wt == Qt::Popup || wt == Qt::ToolTip || wt == Qt::SplashScreen, pRetVal); + } + break; + case UIA_FullDescriptionPropertyId: + setVariantString(accessible->text(QAccessible::Description), pRetVal); + break; + case UIA_NamePropertyId: { + QString name = accessible->text(QAccessible::Name); + if (name.isEmpty() && clientTopLevel) { + name = QCoreApplication::applicationName(); + } + setVariantString(name, pRetVal); + break; + } + default: + break; + } + return S_OK; +} + +// Generates an ID based on the name of the controls and their parents. +QString QWindowsUiaMainProvider::automationIdForAccessible(const QAccessibleInterface *accessible) +{ + QString result; + if (accessible) { + QObject *obj = accessible->object(); + while (obj) { + QString name = obj->objectName(); + if (name.isEmpty()) + return QString(); + if (!result.isEmpty()) + result.prepend(QLatin1Char('.')); + result.prepend(name); + obj = obj->parent(); + } + } + return result; +} + +HRESULT QWindowsUiaMainProvider::get_HostRawElementProvider(IRawElementProviderSimple **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + // Returns a host provider only for controls associated with a native window handle. Others should return NULL. + if (QAccessibleInterface *accessible = accessibleInterface()) { + if (HWND hwnd = hwndForAccessible(accessible)) { + return QWindowsUiaWrapper::instance()->hostProviderFromHwnd(hwnd, pRetVal); + } + } + return S_OK; +} + +// Navigates within the tree of accessible controls. +HRESULT QWindowsUiaMainProvider::Navigate(NavigateDirection direction, IRawElementProviderFragment **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << direction << " this: " << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleInterface *targetacc = nullptr; + + switch (direction) { + case NavigateDirection_Parent: + targetacc = accessible->parent(); + if (targetacc && (targetacc->role() == QAccessible::Application)) { + targetacc = nullptr; // The app's children are considered top level objects. + } + break; + case NavigateDirection_FirstChild: + targetacc = accessible->child(0); + break; + case NavigateDirection_LastChild: + targetacc = accessible->child(accessible->childCount() - 1); + break; + case NavigateDirection_NextSibling: + case NavigateDirection_PreviousSibling: + if (QAccessibleInterface *parent = accessible->parent()) { + if (parent->isValid()) { + int index = parent->indexOfChild(accessible); + index += (direction == NavigateDirection_NextSibling) ? 1 : -1; + if (index >= 0 && index < parent->childCount()) + targetacc = parent->child(index); + } + } + break; + } + + if (targetacc) + *pRetVal = providerForAccessible(targetacc); + return S_OK; +} + +// Returns a unique id assigned to the UI element, used as key by the UI Automation framework. +HRESULT QWindowsUiaMainProvider::GetRuntimeId(SAFEARRAY **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + // The UiaAppendRuntimeId constant is used to make then ID unique + // among multiple instances running on the system. + int rtId[] = { UiaAppendRuntimeId, int(id()) }; + + if ((*pRetVal = SafeArrayCreateVector(VT_I4, 0, 2))) { + for (LONG i = 0; i < 2; ++i) + SafeArrayPutElement(*pRetVal, &i, &rtId[i]); + } + return S_OK; +} + +// Returns the bounding rectangle for the accessible control. +HRESULT QWindowsUiaMainProvider::get_BoundingRectangle(UiaRect *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QWindow *window = windowForAccessible(accessible); + if (!window) + return UIA_E_ELEMENTNOTAVAILABLE; + + rectToNativeUiaRect(accessible->rect(), window, pRetVal); + return S_OK; +} + +HRESULT QWindowsUiaMainProvider::GetEmbeddedFragmentRoots(SAFEARRAY **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + // No embedded roots. + return S_OK; +} + +// Sets focus to the control. +HRESULT QWindowsUiaMainProvider::SetFocus() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleActionInterface *actionInterface = accessible->actionInterface(); + if (!actionInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + actionInterface->doAction(QAccessibleActionInterface::setFocusAction()); + return S_OK; +} + +HRESULT QWindowsUiaMainProvider::get_FragmentRoot(IRawElementProviderFragmentRoot **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + // Our UI Automation implementation considers the window as the root for + // non-native controls/fragments. + if (QAccessibleInterface *accessible = accessibleInterface()) { + if (QWindow *window = windowForAccessible(accessible)) { + if (QAccessibleInterface *rootacc = window->accessibleRoot()) { + *pRetVal = providerForAccessible(rootacc); + } + } + } + return S_OK; +} + +// Returns a provider for the UI element present at the specified screen coordinates. +HRESULT QWindowsUiaMainProvider::ElementProviderFromPoint(double x, double y, IRawElementProviderFragment **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << x << y; + + if (!pRetVal) { + return E_INVALIDARG; + } + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QWindow *window = windowForAccessible(accessible); + if (!window) + return UIA_E_ELEMENTNOTAVAILABLE; + + // Scales coordinates from High DPI screens. + UiaPoint uiaPoint = {x, y}; + QPoint point; + nativeUiaPointToPoint(uiaPoint, window, &point); + + QAccessibleInterface *targetacc = accessible->childAt(point.x(), point.y()); + + if (targetacc) { + QAccessibleInterface *acc = targetacc; + // Controls can be embedded within grouping elements. By default returns the innermost control. + while (acc) { + targetacc = acc; + // For accessibility tools it may be better to return the text element instead of its subcomponents. + if (targetacc->textInterface()) break; + acc = acc->childAt(point.x(), point.y()); + } + *pRetVal = providerForAccessible(targetacc); + } + return S_OK; +} + +// Returns the fragment with focus. +HRESULT QWindowsUiaMainProvider::GetFocus(IRawElementProviderFragment **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + if (QAccessibleInterface *accessible = accessibleInterface()) { + if (QAccessibleInterface *focusacc = accessible->focusChild()) { + *pRetVal = providerForAccessible(focusacc); + } + } + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h new file mode 100644 index 0000000000..893cbf7f8a --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIAMAINPROVIDER_H +#define QWINDOWSUIAMAINPROVIDER_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsuiabaseprovider.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +// The main UI Automation class. +class QWindowsUiaMainProvider : + public QWindowsUiaBaseProvider, + public IRawElementProviderSimple, + public IRawElementProviderFragment, + public IRawElementProviderFragmentRoot +{ + Q_OBJECT + Q_DISABLE_COPY(QWindowsUiaMainProvider) +public: + static QWindowsUiaMainProvider *providerForAccessible(QAccessibleInterface *accessible); + explicit QWindowsUiaMainProvider(QAccessibleInterface *a, int initialRefCount = 1); + virtual ~QWindowsUiaMainProvider(); + static void notifyFocusChange(QAccessibleEvent *event); + static void notifyStateChange(QAccessibleStateChangeEvent *event); + static void notifyValueChange(QAccessibleValueChangeEvent *event); + static void notifyTextChange(QAccessibleEvent *event); + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IRawElementProviderSimple methods + HRESULT STDMETHODCALLTYPE get_ProviderOptions(ProviderOptions *pRetVal); + HRESULT STDMETHODCALLTYPE GetPatternProvider(PATTERNID idPattern, IUnknown **pRetVal); + HRESULT STDMETHODCALLTYPE GetPropertyValue(PROPERTYID idProp, VARIANT *pRetVal); + HRESULT STDMETHODCALLTYPE get_HostRawElementProvider(IRawElementProviderSimple **pRetVal); + + // IRawElementProviderFragment methods + HRESULT STDMETHODCALLTYPE Navigate(NavigateDirection direction, IRawElementProviderFragment **pRetVal); + HRESULT STDMETHODCALLTYPE GetRuntimeId(SAFEARRAY **pRetVal); + HRESULT STDMETHODCALLTYPE get_BoundingRectangle(UiaRect *pRetVal); + HRESULT STDMETHODCALLTYPE GetEmbeddedFragmentRoots(SAFEARRAY **pRetVal); + HRESULT STDMETHODCALLTYPE SetFocus(); + HRESULT STDMETHODCALLTYPE get_FragmentRoot(IRawElementProviderFragmentRoot **pRetVal); + + // IRawElementProviderFragmentRoot methods + HRESULT STDMETHODCALLTYPE ElementProviderFromPoint(double x, double y, IRawElementProviderFragment **pRetVal); + HRESULT STDMETHODCALLTYPE GetFocus(IRawElementProviderFragment **pRetVal); + +private: + QString automationIdForAccessible(const QAccessibleInterface *accessible); + ULONG m_ref; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIAMAINPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp new file mode 100644 index 0000000000..9f0a1e126f --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiaprovidercache.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +// Private constructor +QWindowsUiaProviderCache::QWindowsUiaProviderCache() +{ +} + +// shared instance +QWindowsUiaProviderCache *QWindowsUiaProviderCache::instance() +{ + static QWindowsUiaProviderCache providerCache; + return &providerCache; +} + +// Returns the provider instance associated with the ID, or nullptr. +QWindowsUiaBaseProvider *QWindowsUiaProviderCache::providerForId(QAccessible::Id id) const +{ + return providerTable.value(id); +} + +// Inserts a provider in the cache and associates it with an accessibility ID. +void QWindowsUiaProviderCache::insert(QAccessible::Id id, QWindowsUiaBaseProvider *provider) +{ + remove(id); + if (provider) { + providerTable[id] = provider; + inverseTable[provider] = id; + // Connects the destroyed signal to our slot, to remove deleted objects from the cache. + QObject::connect(provider, &QObject::destroyed, this, &QWindowsUiaProviderCache::objectDestroyed); + } +} + +// Removes deleted provider objects from the cache. +void QWindowsUiaProviderCache::objectDestroyed(QObject *obj) +{ + // We have to use the inverse table to map the object address back to its ID, + // since at this point (called from QObject destructor), it has already been + // partially destroyed and we cannot treat it as a provider. + auto it = inverseTable.find(obj); + if (it != inverseTable.end()) { + providerTable.remove(*it); + inverseTable.remove(obj); + } +} + +// Removes a provider with a given id from the cache. +void QWindowsUiaProviderCache::remove(QAccessible::Id id) +{ + inverseTable.remove(providerTable.value(id)); + providerTable.remove(id); +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h new file mode 100644 index 0000000000..7ad30ac39c --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIAPROVIDERCACHE_H +#define QWINDOWSUIAPROVIDERCACHE_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsuiabaseprovider.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +// Singleton used to cache provider instances using the accessibility ID as the key. +class QWindowsUiaProviderCache : public QObject +{ + QWindowsUiaProviderCache(); + Q_OBJECT +public: + static QWindowsUiaProviderCache *instance(); + QWindowsUiaBaseProvider *providerForId(QAccessible::Id id) const; + void insert(QAccessible::Id id, QWindowsUiaBaseProvider *provider); + void remove(QAccessible::Id id); + +private Q_SLOTS: + void objectDestroyed(QObject *obj); + +private: + QHash providerTable; + QHash inverseTable; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIAPROVIDERCACHE_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp new file mode 100644 index 0000000000..0cd09c3f0a --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiarangevalueprovider.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaRangeValueProvider::QWindowsUiaRangeValueProvider(QAccessible::Id id) : + QWindowsUiaBaseProvider(id) +{ +} + +QWindowsUiaRangeValueProvider::~QWindowsUiaRangeValueProvider() +{ +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::SetValue(double val) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleValueInterface *valueInterface = accessible->valueInterface(); + if (!valueInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + double minimum = valueInterface->minimumValue().toDouble(); + double maximum = valueInterface->maximumValue().toDouble(); + if ((val < minimum) || (val > maximum)) + return E_INVALIDARG; + + valueInterface->setCurrentValue(QVariant(val)); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::get_Value(double *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleValueInterface *valueInterface = accessible->valueInterface(); + if (!valueInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + QVariant varValue = valueInterface->currentValue(); + *pRetVal = varValue.toDouble(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::get_IsReadOnly(BOOL *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + *pRetVal = accessible->state().readOnly; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::get_Maximum(double *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleValueInterface *valueInterface = accessible->valueInterface(); + if (!valueInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + QVariant varValue = valueInterface->maximumValue(); + *pRetVal = varValue.toDouble(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::get_Minimum(double *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleValueInterface *valueInterface = accessible->valueInterface(); + if (!valueInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + QVariant varValue = valueInterface->minimumValue(); + *pRetVal = varValue.toDouble(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::get_LargeChange(double *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + return get_SmallChange(pRetVal); +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::get_SmallChange(double *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleValueInterface *valueInterface = accessible->valueInterface(); + if (!valueInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + QVariant varValue = valueInterface->minimumStepSize(); + *pRetVal = varValue.toDouble(); + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h new file mode 100644 index 0000000000..f742ef99c2 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIARANGEVALUEPROVIDER_H +#define QWINDOWSUIARANGEVALUEPROVIDER_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsuiabaseprovider.h" + +QT_BEGIN_NAMESPACE + +// Implements the Range Value control pattern provider. +class QWindowsUiaRangeValueProvider : public QWindowsUiaBaseProvider, + public QWindowsComBase +{ + Q_DISABLE_COPY(QWindowsUiaRangeValueProvider) +public: + explicit QWindowsUiaRangeValueProvider(QAccessible::Id id); + virtual ~QWindowsUiaRangeValueProvider(); + + // IRangeValueProvider + HRESULT STDMETHODCALLTYPE SetValue(double val); + HRESULT STDMETHODCALLTYPE get_Value(double *pRetVal); + HRESULT STDMETHODCALLTYPE get_IsReadOnly(BOOL *pRetVal); + HRESULT STDMETHODCALLTYPE get_Maximum(double *pRetVal); + HRESULT STDMETHODCALLTYPE get_Minimum(double *pRetVal); + HRESULT STDMETHODCALLTYPE get_LargeChange(double *pRetVal); + HRESULT STDMETHODCALLTYPE get_SmallChange(double *pRetVal); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIARANGEVALUEPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp new file mode 100644 index 0000000000..45216a6d1c --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiaselectionitemprovider.h" +#include "qwindowsuiamainprovider.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaSelectionItemProvider::QWindowsUiaSelectionItemProvider(QAccessible::Id id) : + QWindowsUiaBaseProvider(id) +{ +} + +QWindowsUiaSelectionItemProvider::~QWindowsUiaSelectionItemProvider() +{ +} + +// Selects the element (deselecting all others). +HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::Select() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleActionInterface *actionInterface = accessible->actionInterface(); + if (!actionInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + if (accessible->role() == QAccessible::RadioButton) { + // For radio buttons we just invoke the selection action; others are automatically deselected. + actionInterface->doAction(QAccessibleActionInterface::pressAction()); + } else { + // Toggle list item if not already selected. It must be done first to support all selection modes. + if (!accessible->state().selected) { + actionInterface->doAction(QAccessibleActionInterface::toggleAction()); + } + // Toggle selected siblings. + if (QAccessibleInterface *parent = accessible->parent()) { + for (int i = 0; i < parent->childCount(); ++i) { + if (QAccessibleInterface *sibling = parent->child(i)) { + if ((sibling != accessible) && (sibling->state().selected)) { + if (QAccessibleActionInterface *siblingAction = sibling->actionInterface()) { + siblingAction->doAction(QAccessibleActionInterface::toggleAction()); + } + } + } + } + } + } + return S_OK; +} + +// Adds the element to the list of selected elements. +HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::AddToSelection() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleActionInterface *actionInterface = accessible->actionInterface(); + if (!actionInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + if (accessible->role() == QAccessible::RadioButton) { + // For radio buttons we invoke the selection action. + actionInterface->doAction(QAccessibleActionInterface::pressAction()); + } else { + // Toggle list item if not already selected. + if (!accessible->state().selected) { + actionInterface->doAction(QAccessibleActionInterface::toggleAction()); + } + } + return S_OK; +} + +// Removes a list item from selection. +HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::RemoveFromSelection() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleActionInterface *actionInterface = accessible->actionInterface(); + if (!actionInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + if (accessible->role() != QAccessible::RadioButton) { + if (accessible->state().selected) { + actionInterface->doAction(QAccessibleActionInterface::toggleAction()); + } + } + + return S_OK; +} + +// Returns true if element is currently selected. +HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_IsSelected(BOOL *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = FALSE; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + if (accessible->role() == QAccessible::RadioButton) + *pRetVal = accessible->state().checked; + else + *pRetVal = accessible->state().selected; + return S_OK; +} + +// Returns the provider for the container element (e.g., the list for the list item). +HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_SelectionContainer(IRawElementProviderSimple **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleActionInterface *actionInterface = accessible->actionInterface(); + if (!actionInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + // Radio buttons do not require a container. + if (accessible->role() == QAccessible::ListItem) { + if (QAccessibleInterface *parent = accessible->parent()) { + if (parent->role() == QAccessible::List) { + *pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent); + } + } + } + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h new file mode 100644 index 0000000000..6a9b5b1e4b --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIASELECTIONITEMPROVIDER_H +#define QWINDOWSUIASELECTIONITEMPROVIDER_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsuiabaseprovider.h" + +QT_BEGIN_NAMESPACE + +// Implements the Selection Item control pattern provider. Used for List items and radio buttons. +class QWindowsUiaSelectionItemProvider : public QWindowsUiaBaseProvider, + public QWindowsComBase +{ + Q_DISABLE_COPY(QWindowsUiaSelectionItemProvider) +public: + explicit QWindowsUiaSelectionItemProvider(QAccessible::Id id); + virtual ~QWindowsUiaSelectionItemProvider(); + + // ISelectionItemProvider + HRESULT STDMETHODCALLTYPE Select(); + HRESULT STDMETHODCALLTYPE AddToSelection(); + HRESULT STDMETHODCALLTYPE RemoveFromSelection(); + HRESULT STDMETHODCALLTYPE get_IsSelected(BOOL *pRetVal); + HRESULT STDMETHODCALLTYPE get_SelectionContainer(IRawElementProviderSimple **pRetVal); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIASELECTIONITEMPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp new file mode 100644 index 0000000000..1c06503bfc --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiaselectionprovider.h" +#include "qwindowsuiamainprovider.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaSelectionProvider::QWindowsUiaSelectionProvider(QAccessible::Id id) : + QWindowsUiaBaseProvider(id) +{ +} + +QWindowsUiaSelectionProvider::~QWindowsUiaSelectionProvider() +{ +} + +// Returns an array of providers with the selected items. +HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::GetSelection(SAFEARRAY **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + // First put selected items in a list, then build a safe array with the right size. + QList selectedList; + for (int i = 0; i < accessible->childCount(); ++i) { + if (QAccessibleInterface *child = accessible->child(i)) { + if (child->state().selected) { + selectedList.append(child); + } + } + } + + if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, selectedList.size()))) { + for (LONG i = 0; i < selectedList.size(); ++i) { + if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(selectedList.at(i))) { + SafeArrayPutElement(*pRetVal, &i, static_cast(childProvider)); + childProvider->Release(); + } + } + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_CanSelectMultiple(BOOL *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = FALSE; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + *pRetVal = accessible->state().multiSelectable; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_IsSelectionRequired(BOOL *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = FALSE; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + // Initially returns false if none are selected. After the first selection, it may be required. + bool anySelected = false; + for (int i = 0; i < accessible->childCount(); ++i) { + if (QAccessibleInterface *child = accessible->child(i)) { + if (child->state().selected) { + anySelected = true; + break; + } + } + } + + *pRetVal = anySelected && !accessible->state().multiSelectable && !accessible->state().extSelectable; + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h new file mode 100644 index 0000000000..5a07a82ac8 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIASELECTIONPROVIDER_H +#define QWINDOWSUIASELECTIONPROVIDER_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsuiabaseprovider.h" + +QT_BEGIN_NAMESPACE + +// Implements the Selection control pattern provider. Used for Lists. +class QWindowsUiaSelectionProvider : public QWindowsUiaBaseProvider, + public QWindowsComBase +{ + Q_DISABLE_COPY(QWindowsUiaSelectionProvider) +public: + explicit QWindowsUiaSelectionProvider(QAccessible::Id id); + virtual ~QWindowsUiaSelectionProvider(); + + // ISelectionProvider + HRESULT STDMETHODCALLTYPE GetSelection(SAFEARRAY **pRetVal); + HRESULT STDMETHODCALLTYPE get_CanSelectMultiple(BOOL *pRetVal); + HRESULT STDMETHODCALLTYPE get_IsSelectionRequired(BOOL *pRetVal); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIASELECTIONPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp new file mode 100644 index 0000000000..3ea29fc86c --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiatableitemprovider.h" +#include "qwindowsuiamainprovider.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaTableItemProvider::QWindowsUiaTableItemProvider(QAccessible::Id id) : + QWindowsUiaBaseProvider(id) +{ +} + +QWindowsUiaTableItemProvider::~QWindowsUiaTableItemProvider() +{ +} + +// Returns the providers for the row headers associated with the item. +HRESULT STDMETHODCALLTYPE QWindowsUiaTableItemProvider::GetRowHeaderItems(SAFEARRAY **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface(); + if (!tableCellInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + QList headers = tableCellInterface->rowHeaderCells(); + + if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) { + for (LONG i = 0; i < headers.size(); ++i) { + if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { + SafeArrayPutElement(*pRetVal, &i, static_cast(headerProvider)); + headerProvider->Release(); + } + } + } + return S_OK; +} + +// Returns the providers for the column headers associated with the item. +HRESULT STDMETHODCALLTYPE QWindowsUiaTableItemProvider::GetColumnHeaderItems(SAFEARRAY **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface(); + if (!tableCellInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + QList headers = tableCellInterface->columnHeaderCells(); + + if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) { + for (LONG i = 0; i < headers.size(); ++i) { + if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { + SafeArrayPutElement(*pRetVal, &i, static_cast(headerProvider)); + headerProvider->Release(); + } + } + } + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h new file mode 100644 index 0000000000..277884c980 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIATABLEITEMPROVIDER_H +#define QWINDOWSUIATABLEITEMPROVIDER_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsuiabaseprovider.h" + +QT_BEGIN_NAMESPACE + +// Implements the Table Item control pattern provider. Used by items within a table/tree. +class QWindowsUiaTableItemProvider : public QWindowsUiaBaseProvider, + public QWindowsComBase +{ + Q_DISABLE_COPY(QWindowsUiaTableItemProvider) +public: + explicit QWindowsUiaTableItemProvider(QAccessible::Id id); + virtual ~QWindowsUiaTableItemProvider(); + + // ITableItemProvider + HRESULT STDMETHODCALLTYPE GetRowHeaderItems(SAFEARRAY **pRetVal); + HRESULT STDMETHODCALLTYPE GetColumnHeaderItems(SAFEARRAY **pRetVal); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIATABLEITEMPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp new file mode 100644 index 0000000000..f79a24536b --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiatableprovider.h" +#include "qwindowsuiamainprovider.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaTableProvider::QWindowsUiaTableProvider(QAccessible::Id id) : + QWindowsUiaBaseProvider(id) +{ +} + +QWindowsUiaTableProvider::~QWindowsUiaTableProvider() +{ +} + +// Gets the providers for all the row headers in the table. +HRESULT STDMETHODCALLTYPE QWindowsUiaTableProvider::GetRowHeaders(SAFEARRAY **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTableInterface *tableInterface = accessible->tableInterface(); + if (!tableInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + QList headers; + + for (int i = 0; i < tableInterface->rowCount(); ++i) { + if (QAccessibleInterface *cell = tableInterface->cellAt(i, 0)) { + if (QAccessibleTableCellInterface *tableCellInterface = cell->tableCellInterface()) { + headers.append(tableCellInterface->rowHeaderCells()); + } + } + } + if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) { + for (LONG i = 0; i < headers.size(); ++i) { + if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { + SafeArrayPutElement(*pRetVal, &i, static_cast(headerProvider)); + headerProvider->Release(); + } + } + } + return S_OK; +} + +// Gets the providers for all the column headers in the table. +HRESULT STDMETHODCALLTYPE QWindowsUiaTableProvider::GetColumnHeaders(SAFEARRAY **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTableInterface *tableInterface = accessible->tableInterface(); + if (!tableInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + QList headers; + + for (int i = 0; i < tableInterface->columnCount(); ++i) { + if (QAccessibleInterface *cell = tableInterface->cellAt(0, i)) { + if (QAccessibleTableCellInterface *tableCellInterface = cell->tableCellInterface()) { + headers.append(tableCellInterface->columnHeaderCells()); + } + } + } + if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) { + for (LONG i = 0; i < headers.size(); ++i) { + if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { + SafeArrayPutElement(*pRetVal, &i, static_cast(headerProvider)); + headerProvider->Release(); + } + } + } + return S_OK; +} + +// Returns the primary direction of traversal for the table. +HRESULT STDMETHODCALLTYPE QWindowsUiaTableProvider::get_RowOrColumnMajor(enum RowOrColumnMajor *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = RowOrColumnMajor_Indeterminate; + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h new file mode 100644 index 0000000000..8cd0acda03 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIATABLEPROVIDER_H +#define QWINDOWSUIATABLEPROVIDER_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsuiabaseprovider.h" + +QT_BEGIN_NAMESPACE + +// Implements the Table control pattern provider. Used by tables/trees. +class QWindowsUiaTableProvider : public QWindowsUiaBaseProvider, + public QWindowsComBase +{ + Q_DISABLE_COPY(QWindowsUiaTableProvider) +public: + explicit QWindowsUiaTableProvider(QAccessible::Id id); + virtual ~QWindowsUiaTableProvider(); + + // ITableProvider + HRESULT STDMETHODCALLTYPE GetRowHeaders(SAFEARRAY **pRetVal); + HRESULT STDMETHODCALLTYPE GetColumnHeaders(SAFEARRAY **pRetVal); + HRESULT STDMETHODCALLTYPE get_RowOrColumnMajor(enum RowOrColumnMajor *pRetVal); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIATABLEPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp new file mode 100644 index 0000000000..e1622933af --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp @@ -0,0 +1,261 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiatextprovider.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaTextProvider::QWindowsUiaTextProvider(QAccessible::Id id) : + QWindowsUiaBaseProvider(id) +{ +} + +QWindowsUiaTextProvider::~QWindowsUiaTextProvider() +{ +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::QueryInterface(REFIID iid, LPVOID *iface) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!iface) + return E_INVALIDARG; + *iface = nullptr; + + const bool result = qWindowsComQueryUnknownInterfaceMulti(this, iid, iface) + || qWindowsComQueryInterface(this, iid, iface) + || qWindowsComQueryInterface(this, iid, iface); + return result ? S_OK : E_NOINTERFACE; +} + +// Returns an array of providers for the selected text ranges. +HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::GetSelection(SAFEARRAY **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTextInterface *textInterface = accessible->textInterface(); + if (!textInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + int selCount = textInterface->selectionCount(); + if (selCount > 0) { + // Build a safe array with the text range providers. + if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, selCount))) { + for (LONG i = 0; i < selCount; ++i) { + int startOffset = 0, endOffset = 0; + textInterface->selection((int)i, &startOffset, &endOffset); + QWindowsUiaTextRangeProvider *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), startOffset, endOffset); + SafeArrayPutElement(*pRetVal, &i, static_cast(textRangeProvider)); + textRangeProvider->Release(); + } + } + } else { + // If there is no selection, we return an array with a single degenerate (empty) text range at the cursor position. + if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 1))) { + LONG i = 0; + int cursorPosition = textInterface->cursorPosition(); + QWindowsUiaTextRangeProvider *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), cursorPosition, cursorPosition); + SafeArrayPutElement(*pRetVal, &i, static_cast(textRangeProvider)); + textRangeProvider->Release(); + } + } + return S_OK; +} + +// Returns an array of providers for the visible text ranges. +HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::GetVisibleRanges(SAFEARRAY **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTextInterface *textInterface = accessible->textInterface(); + if (!textInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + // Considering the entire text as visible. + if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 1))) { + LONG i = 0; + QWindowsUiaTextRangeProvider *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), 0, textInterface->characterCount()); + SafeArrayPutElement(*pRetVal, &i, static_cast(textRangeProvider)); + textRangeProvider->Release(); + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::RangeFromChild(IRawElementProviderSimple * /*childElement*/, + ITextRangeProvider **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + // No children supported. + return S_OK; +} + +// Returns a degenerate text range at the specified point. +HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTextInterface *textInterface = accessible->textInterface(); + if (!textInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + QWindow *window = windowForAccessible(accessible); + if (!window) + return UIA_E_ELEMENTNOTAVAILABLE; + + QPoint pt; + nativeUiaPointToPoint(point, window, &pt); + + int offset = textInterface->offsetAtPoint(pt); + if ((offset >= 0) && (offset < textInterface->characterCount())) { + *pRetVal = new QWindowsUiaTextRangeProvider(id(), offset, offset); + } + return S_OK; +} + +// Returns a text range provider for the entire text. +HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::get_DocumentRange(ITextRangeProvider **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTextInterface *textInterface = accessible->textInterface(); + if (!textInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + *pRetVal = new QWindowsUiaTextRangeProvider(id(), 0, textInterface->characterCount()); + return S_OK; +} + +// Currently supporting single selection. +HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::get_SupportedTextSelection(SupportedTextSelection *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = SupportedTextSelection_Single; + return S_OK; +} + +// Not supporting annotations. +HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::RangeFromAnnotation(IRawElementProviderSimple * /*annotationElement*/, ITextRangeProvider **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::GetCaretRange(BOOL *isActive, ITextRangeProvider **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!isActive || !pRetVal) + return E_INVALIDARG; + *isActive = FALSE; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTextInterface *textInterface = accessible->textInterface(); + if (!textInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + *isActive = accessible->state().focused; + + int cursorPosition = textInterface->cursorPosition(); + *pRetVal = new QWindowsUiaTextRangeProvider(id(), cursorPosition, cursorPosition); + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h new file mode 100644 index 0000000000..a6d10027fa --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIATEXTPROVIDER_H +#define QWINDOWSUIATEXTPROVIDER_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsuiabaseprovider.h" +#include "qwindowsuiatextrangeprovider.h" + +QT_BEGIN_NAMESPACE + +// Implements the Text control pattern provider. Used for text controls. +class QWindowsUiaTextProvider : public QWindowsUiaBaseProvider, + public QWindowsComBase +{ + Q_DISABLE_COPY(QWindowsUiaTextProvider) +public: + explicit QWindowsUiaTextProvider(QAccessible::Id id); + ~QWindowsUiaTextProvider(); + + // IUnknown overrides + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface); + + // ITextProvider + HRESULT STDMETHODCALLTYPE GetSelection(SAFEARRAY **pRetVal); + HRESULT STDMETHODCALLTYPE GetVisibleRanges(SAFEARRAY **pRetVal); + HRESULT STDMETHODCALLTYPE RangeFromChild(IRawElementProviderSimple *childElement, ITextRangeProvider **pRetVal); + HRESULT STDMETHODCALLTYPE RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal); + HRESULT STDMETHODCALLTYPE get_DocumentRange(ITextRangeProvider **pRetVal); + HRESULT STDMETHODCALLTYPE get_SupportedTextSelection(SupportedTextSelection *pRetVal); + + // ITextProvider2 + HRESULT STDMETHODCALLTYPE RangeFromAnnotation(IRawElementProviderSimple *annotationElement, ITextRangeProvider **pRetVal); + HRESULT STDMETHODCALLTYPE GetCaretRange(BOOL *isActive, ITextRangeProvider **pRetVal); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIATEXTPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp new file mode 100644 index 0000000000..dae7cbdd5f --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp @@ -0,0 +1,554 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiatextrangeprovider.h" +#include "qwindowsuiamainprovider.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaTextRangeProvider::QWindowsUiaTextRangeProvider(QAccessible::Id id, int startOffset, int endOffset) : + QWindowsUiaBaseProvider(id), + m_startOffset(startOffset), + m_endOffset(endOffset) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this << startOffset << endOffset; +} + +QWindowsUiaTextRangeProvider::~QWindowsUiaTextRangeProvider() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; +} + +HRESULT QWindowsUiaTextRangeProvider::AddToSelection() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + return Select(); +} + +HRESULT QWindowsUiaTextRangeProvider::Clone(ITextRangeProvider **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + + *pRetVal = new QWindowsUiaTextRangeProvider(id(), m_startOffset, m_endOffset); + return S_OK; +} + +// Two ranges are considered equal if their start/end points are the same. +HRESULT QWindowsUiaTextRangeProvider::Compare(ITextRangeProvider *range, BOOL *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!range || !pRetVal) + return E_INVALIDARG; + + QWindowsUiaTextRangeProvider *targetProvider = static_cast(range); + *pRetVal = ((targetProvider->m_startOffset == m_startOffset) && (targetProvider->m_endOffset == m_endOffset)); + return S_OK; +} + +// Compare different endpoinds between two providers. +HRESULT QWindowsUiaTextRangeProvider::CompareEndpoints(TextPatternRangeEndpoint endpoint, + ITextRangeProvider *targetRange, + TextPatternRangeEndpoint targetEndpoint, + int *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ + << "endpoint=" << endpoint << "targetRange=" << targetRange + << "targetEndpoint=" << targetEndpoint << "this: " << this; + + if (!targetRange || !pRetVal) + return E_INVALIDARG; + + QWindowsUiaTextRangeProvider *targetProvider = static_cast(targetRange); + + int point = (endpoint == TextPatternRangeEndpoint_Start) ? m_startOffset : m_endOffset; + int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ? + targetProvider->m_startOffset : targetProvider->m_endOffset; + *pRetVal = point - targetPoint; + return S_OK; +} + +// Expands/normalizes the range for a given text unit. +HRESULT QWindowsUiaTextRangeProvider::ExpandToEnclosingUnit(TextUnit unit) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "unit=" << unit << "this: " << this; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTextInterface *textInterface = accessible->textInterface(); + if (!textInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + int len = textInterface->characterCount(); + if (len < 1) { + m_startOffset = 0; + m_endOffset = 0; + } else { + if (unit == TextUnit_Character) { + m_startOffset = qBound(0, m_startOffset, len - 1); + m_endOffset = m_startOffset + 1; + } else { + QString text = textInterface->text(0, len); + for (int t = m_startOffset; t >= 0; --t) { + if (!isTextUnitSeparator(unit, text[t]) && ((t == 0) || isTextUnitSeparator(unit, text[t - 1]))) { + m_startOffset = t; + break; + } + } + for (int t = m_startOffset; t < len; ++t) { + if ((t == len - 1) || (isTextUnitSeparator(unit, text[t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit, text[t + 1])))) { + m_endOffset = t + 1; + break; + } + } + } + } + return S_OK; +} + +// Not supported. +HRESULT QWindowsUiaTextRangeProvider::FindAttribute(TEXTATTRIBUTEID /* attributeId */, + VARIANT /* val */, BOOL /* backward */, + ITextRangeProvider **pRetVal) +{ + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + return S_OK; +} + +// Returns the value of a given attribute. +HRESULT STDMETHODCALLTYPE QWindowsUiaTextRangeProvider::GetAttributeValue(TEXTATTRIBUTEID attributeId, + VARIANT *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "attributeId=" << attributeId << "this: " << this; + + if (!pRetVal) + return E_INVALIDARG; + clearVariant(pRetVal); + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTextInterface *textInterface = accessible->textInterface(); + if (!textInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + switch (attributeId) { + case UIA_IsReadOnlyAttributeId: + setVariantBool(accessible->state().readOnly, pRetVal); + break; + case UIA_CaretPositionAttributeId: + if (textInterface->cursorPosition() == 0) + setVariantI4(CaretPosition_BeginningOfLine, pRetVal); + else if (textInterface->cursorPosition() == textInterface->characterCount()) + setVariantI4(CaretPosition_EndOfLine, pRetVal); + else + setVariantI4(CaretPosition_Unknown, pRetVal); + break; + default: + break; + } + return S_OK; +} + +// Returns an array of bounding rectangles for text lines within the range. +HRESULT QWindowsUiaTextRangeProvider::GetBoundingRectangles(SAFEARRAY **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTextInterface *textInterface = accessible->textInterface(); + if (!textInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + QWindow *window = windowForAccessible(accessible); + if (!window) + return UIA_E_ELEMENTNOTAVAILABLE; + + int len = textInterface->characterCount(); + QList rectList; + + if ((m_startOffset >= 0) && (m_endOffset <= len) && (m_startOffset < m_endOffset)) { + int start, end; + textInterface->textAtOffset(m_startOffset, QAccessible::LineBoundary, &start, &end); + while ((start >= 0) && (end >= 0)) { + int startRange = qMax(start, m_startOffset); + int endRange = qMin(end, m_endOffset); + if (startRange < endRange) { + // Calculates a bounding rectangle for the line and adds it to the list. + QRect startRect = textInterface->characterRect(startRange); + QRect endRect = textInterface->characterRect(endRange - 1); + QRect lineRect(qMin(startRect.x(), endRect.x()), + qMin(startRect.y(), endRect.y()), + qMax(startRect.x() + startRect.width(), endRect.x() + endRect.width()) - qMin(startRect.x(), endRect.x()), + qMax(startRect.y() + startRect.height(), endRect.y() + endRect.height()) - qMin(startRect.y(), endRect.y())); + rectList.append(lineRect); + } + if (end >= len) break; + textInterface->textAfterOffset(end + 1, QAccessible::LineBoundary, &start, &end); + } + } + + if ((*pRetVal = SafeArrayCreateVector(VT_R8, 0, 4 * rectList.size()))) { + for (int i = 0; i < rectList.size(); ++i) { + // Scale rect for high DPI screens. + UiaRect uiaRect; + rectToNativeUiaRect(rectList[i], window, &uiaRect); + double coords[4] = { uiaRect.left, uiaRect.top, uiaRect.width, uiaRect.height }; + for (int j = 0; j < 4; ++j) { + LONG idx = 4 * i + j; + SafeArrayPutElement(*pRetVal, &idx, &coords[j]); + } + } + } + return S_OK; +} + +// Returns an array of children elements embedded within the range. +HRESULT QWindowsUiaTextRangeProvider::GetChildren(SAFEARRAY **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + // Not supporting any children. + *pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 0); + return S_OK; +} + +// Returns a provider for the enclosing element (text to which the range belongs). +HRESULT QWindowsUiaTextRangeProvider::GetEnclosingElement(IRawElementProviderSimple **pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + if (!pRetVal) + return E_INVALIDARG; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + *pRetVal = QWindowsUiaMainProvider::providerForAccessible(accessible); + return S_OK; +} + +// Gets the text within the range. +HRESULT QWindowsUiaTextRangeProvider::GetText(int maxLength, BSTR *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << maxLength << "this: " << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTextInterface *textInterface = accessible->textInterface(); + if (!textInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + int len = textInterface->characterCount(); + QString rangeText; + if ((m_startOffset >= 0) && (m_endOffset <= len) && (m_startOffset < m_endOffset)) + rangeText = textInterface->text(m_startOffset, m_endOffset); + + if ((maxLength > -1) && (rangeText.size() > maxLength)) + rangeText.truncate(maxLength); + *pRetVal = bStrFromQString(rangeText); + return S_OK; +} + +// Moves the range a specified number of units (and normalizes it). +HRESULT QWindowsUiaTextRangeProvider::Move(TextUnit unit, int count, int *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "unit=" << unit << "count=" << count << "this: " << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = 0; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTextInterface *textInterface = accessible->textInterface(); + if (!textInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + int len = textInterface->characterCount(); + + if (len < 1) + return S_OK; + + if (unit == TextUnit_Character) { + // Moves the start point, ensuring it lies within the bounds. + int start = qBound(0, m_startOffset + count, len - 1); + // If range was initially empty, leaves it as is; otherwise, normalizes it to one char. + m_endOffset = (m_endOffset > m_startOffset) ? start + 1 : start; + *pRetVal = start - m_startOffset; // Returns the actually moved distance. + m_startOffset = start; + } else { + if (count > 0) { + MoveEndpointByUnit(TextPatternRangeEndpoint_End, unit, count, pRetVal); + MoveEndpointByUnit(TextPatternRangeEndpoint_Start, unit, count, pRetVal); + } else { + MoveEndpointByUnit(TextPatternRangeEndpoint_Start, unit, count, pRetVal); + MoveEndpointByUnit(TextPatternRangeEndpoint_End, unit, count, pRetVal); + } + } + return S_OK; +} + +// Copies the value of an end point from one range to another. +HRESULT QWindowsUiaTextRangeProvider::MoveEndpointByRange(TextPatternRangeEndpoint endpoint, + ITextRangeProvider *targetRange, + TextPatternRangeEndpoint targetEndpoint) +{ + if (!targetRange) + return E_INVALIDARG; + + qCDebug(lcQpaUiAutomation) << __FUNCTION__ + << "endpoint=" << endpoint << "targetRange=" << targetRange << "targetEndpoint=" << targetEndpoint << "this: " << this; + + QWindowsUiaTextRangeProvider *targetProvider = static_cast(targetRange); + + int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ? + targetProvider->m_startOffset : targetProvider->m_endOffset; + + // If the moved endpoint crosses the other endpoint, that one is moved too. + if (endpoint == TextPatternRangeEndpoint_Start) { + m_startOffset = targetPoint; + if (m_endOffset < m_startOffset) + m_endOffset = m_startOffset; + } else { + m_endOffset = targetPoint; + if (m_endOffset < m_startOffset) + m_startOffset = m_endOffset; + } + return S_OK; +} + +// Moves an endpoint an specific number of units. +HRESULT QWindowsUiaTextRangeProvider::MoveEndpointByUnit(TextPatternRangeEndpoint endpoint, + TextUnit unit, int count, + int *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ + << "endpoint=" << endpoint << "unit=" << unit << "count=" << count << "this: " << this; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = 0; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTextInterface *textInterface = accessible->textInterface(); + if (!textInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + int len = textInterface->characterCount(); + + if (len < 1) + return S_OK; + + if (unit == TextUnit_Character) { + if (endpoint == TextPatternRangeEndpoint_Start) { + int boundedValue = qBound(0, m_startOffset + count, len - 1); + *pRetVal = boundedValue - m_startOffset; + m_startOffset = boundedValue; + m_endOffset = qBound(m_startOffset, m_endOffset, len); + } else { + int boundedValue = qBound(0, m_endOffset + count, len); + *pRetVal = boundedValue - m_endOffset; + m_endOffset = boundedValue; + m_startOffset = qBound(0, m_startOffset, m_endOffset); + } + } else { + QString text = textInterface->text(0, len); + int moved = 0; + + if (endpoint == TextPatternRangeEndpoint_Start) { + if (count > 0) { + for (int t = m_startOffset; (t < len - 1) && (moved < count); ++t) { + if (isTextUnitSeparator(unit, text[t]) && !isTextUnitSeparator(unit, text[t + 1])) { + m_startOffset = t + 1; + ++moved; + } + } + m_endOffset = qBound(m_startOffset, m_endOffset, len); + } else { + for (int t = m_startOffset - 1; (t >= 0) && (moved > count); --t) { + if (!isTextUnitSeparator(unit, text[t]) && ((t == 0) || isTextUnitSeparator(unit, text[t - 1]))) { + m_startOffset = t; + --moved; + } + } + } + } else { + if (count > 0) { + for (int t = m_endOffset; (t < len) && (moved < count); ++t) { + if ((t == len - 1) || (isTextUnitSeparator(unit, text[t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit, text[t + 1])))) { + m_endOffset = t + 1; + ++moved; + } + } + } else { + int end = 0; + for (int t = m_endOffset - 2; (t > 0) && (moved > count); --t) { + if (isTextUnitSeparator(unit, text[t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit, text[t + 1]))) { + end = t + 1; + --moved; + } + } + m_endOffset = end; + m_startOffset = qBound(0, m_startOffset, m_endOffset); + } + } + *pRetVal = moved; + } + return S_OK; +} + +HRESULT QWindowsUiaTextRangeProvider::RemoveFromSelection() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + // unselects all + return unselect(); +} + +// Scrolls the range into view. +HRESULT QWindowsUiaTextRangeProvider::ScrollIntoView(BOOL alignToTop) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "alignToTop=" << alignToTop << "this: " << this; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTextInterface *textInterface = accessible->textInterface(); + if (!textInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + textInterface->scrollToSubstring(m_startOffset, m_endOffset); + return S_OK; +} + +// Selects the range. +HRESULT QWindowsUiaTextRangeProvider::Select() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTextInterface *textInterface = accessible->textInterface(); + if (!textInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + // unselects all and adds a new selection + unselect(); + textInterface->addSelection(m_startOffset, m_endOffset); + return S_OK; +} + +// Not supported. +HRESULT QWindowsUiaTextRangeProvider::FindTextW(BSTR /* text */, BOOL /* backward */, + BOOL /* ignoreCase */, + ITextRangeProvider **pRetVal) +{ + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + return S_OK; +} + +// Removes all selected ranges from the text element. +HRESULT QWindowsUiaTextRangeProvider::unselect() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleTextInterface *textInterface = accessible->textInterface(); + if (!textInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + int selCount = textInterface->selectionCount(); + + for (int i = selCount - 1; i >= 0; --i) + textInterface->removeSelection(i); + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h new file mode 100644 index 0000000000..6fe6502c41 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIATEXTRANGEPROVIDER_H +#define QWINDOWSUIATEXTRANGEPROVIDER_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsuiabaseprovider.h" + +QT_BEGIN_NAMESPACE + +// Implements the Text Range control pattern provider. Used for text controls. +class QWindowsUiaTextRangeProvider : public QWindowsUiaBaseProvider, + public QWindowsComBase +{ + Q_DISABLE_COPY(QWindowsUiaTextRangeProvider) +public: + explicit QWindowsUiaTextRangeProvider(QAccessible::Id id, int startOffset, int endOffset); + virtual ~QWindowsUiaTextRangeProvider(); + + HRESULT STDMETHODCALLTYPE AddToSelection(); + HRESULT STDMETHODCALLTYPE Clone(ITextRangeProvider **pRetVal); + HRESULT STDMETHODCALLTYPE Compare(ITextRangeProvider *range, BOOL *pRetVal); + HRESULT STDMETHODCALLTYPE CompareEndpoints(TextPatternRangeEndpoint endpoint, ITextRangeProvider *targetRange, TextPatternRangeEndpoint targetEndpoint, int *pRetVal); + HRESULT STDMETHODCALLTYPE ExpandToEnclosingUnit(TextUnit unit); + HRESULT STDMETHODCALLTYPE FindAttribute(TEXTATTRIBUTEID attributeId, VARIANT val, BOOL backward, ITextRangeProvider **pRetVal); + HRESULT STDMETHODCALLTYPE FindText(BSTR text, BOOL backward, BOOL ignoreCase, ITextRangeProvider **pRetVal); + HRESULT STDMETHODCALLTYPE GetAttributeValue(TEXTATTRIBUTEID attributeId, VARIANT *pRetVal); + HRESULT STDMETHODCALLTYPE GetBoundingRectangles(SAFEARRAY **pRetVal); + HRESULT STDMETHODCALLTYPE GetChildren(SAFEARRAY **pRetVal); + HRESULT STDMETHODCALLTYPE GetEnclosingElement(IRawElementProviderSimple **pRetVal); + HRESULT STDMETHODCALLTYPE GetText(int maxLength, BSTR *pRetVal); + HRESULT STDMETHODCALLTYPE Move(TextUnit unit, int count, int *pRetVal); + HRESULT STDMETHODCALLTYPE MoveEndpointByRange(TextPatternRangeEndpoint endpoint, ITextRangeProvider *targetRange, TextPatternRangeEndpoint targetEndpoint); + HRESULT STDMETHODCALLTYPE MoveEndpointByUnit(TextPatternRangeEndpoint endpoint, TextUnit unit, int count, int *pRetVal); + HRESULT STDMETHODCALLTYPE RemoveFromSelection(); + HRESULT STDMETHODCALLTYPE ScrollIntoView(BOOL alignToTop); + HRESULT STDMETHODCALLTYPE Select(); + +private: + HRESULT unselect(); + int m_startOffset; + int m_endOffset; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIATEXTRANGEPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp new file mode 100644 index 0000000000..01cdfd7e91 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiatoggleprovider.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaToggleProvider::QWindowsUiaToggleProvider(QAccessible::Id id) : + QWindowsUiaBaseProvider(id) +{ +} + +QWindowsUiaToggleProvider::~QWindowsUiaToggleProvider() +{ +} + +// toggles the state by invoking the toggle action +HRESULT STDMETHODCALLTYPE QWindowsUiaToggleProvider::Toggle() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleActionInterface *actionInterface = accessible->actionInterface(); + if (!actionInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + actionInterface->doAction(QAccessibleActionInterface::toggleAction()); + return S_OK; +} + +// Gets the current toggle state. +HRESULT STDMETHODCALLTYPE QWindowsUiaToggleProvider::get_ToggleState(ToggleState *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = ToggleState_Off; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + if (accessible->state().checked) + *pRetVal = accessible->state().checkStateMixed ? ToggleState_Indeterminate : ToggleState_On; + else + *pRetVal = ToggleState_Off; + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h new file mode 100644 index 0000000000..a0df983e40 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIATOGGLEPROVIDER_H +#define QWINDOWSUIATOGGLEPROVIDER_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsuiabaseprovider.h" + +QT_BEGIN_NAMESPACE + +// Implements the Toggle control pattern provider. Used for checkboxes. +class QWindowsUiaToggleProvider : public QWindowsUiaBaseProvider, + public QWindowsComBase +{ + Q_DISABLE_COPY(QWindowsUiaToggleProvider) +public: + explicit QWindowsUiaToggleProvider(QAccessible::Id id); + virtual ~QWindowsUiaToggleProvider(); + + // IToggleProvider + HRESULT STDMETHODCALLTYPE Toggle(); + HRESULT STDMETHODCALLTYPE get_ToggleState(ToggleState *pRetVal); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIATOGGLEPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp new file mode 100644 index 0000000000..89e5075dcb --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiautils.h" +#include "qwindowscontext.h" +#include "qwindowswindow.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QWindowsUiAutomation { + +// Returns the window containing the element (usually the top window), +QWindow *windowForAccessible(const QAccessibleInterface *accessible) +{ + QWindow *window = accessible->window(); + if (!window) { + QAccessibleInterface *acc = accessible->parent(); + while (acc && acc->isValid() && !window) { + window = acc->window(); + QAccessibleInterface *par = acc->parent(); + acc = par; + } + } + return window; +} + +// Returns the native window handle associated with the element, if any. +// Usually it will be NULL, as Qt5 by default uses alien widgets with no native windows. +HWND hwndForAccessible(const QAccessibleInterface *accessible) +{ + if (QWindow *window = accessible->window()) { + if (!accessible->parent() || (accessible->parent()->window() != window)) { + return QWindowsBaseWindow::handleOf(window); + } + } + return NULL; +} + +void clearVariant(VARIANT *variant) +{ + variant->vt = VT_EMPTY; + variant->punkVal = nullptr; +} + +void setVariantI4(int value, VARIANT *variant) +{ + variant->vt = VT_I4; + variant->lVal = value; +} + +void setVariantBool(bool value, VARIANT *variant) +{ + variant->vt = VT_BOOL; + variant->boolVal = value ? -1 : 0; +} + +void setVariantDouble(double value, VARIANT *variant) +{ + variant->vt = VT_R8; + variant->boolVal = value; +} + +BSTR bStrFromQString(const QString &value) +{ + return SysAllocString(reinterpret_cast(value.utf16())); +} + +void setVariantString(const QString &value, VARIANT *variant) +{ + variant->vt = VT_BSTR; + variant->bstrVal = bStrFromQString(value); +} + +// Scales a rect to native coordinates, according to high dpi settings. +void rectToNativeUiaRect(const QRect &rect, const QWindow *w, UiaRect *uiaRect) +{ + if (w && uiaRect) { + const qreal factor = QHighDpiScaling::factor(w); + uiaRect->left = qreal(rect.x()) * factor; + uiaRect->top = qreal(rect.y()) * factor; + uiaRect->width = qreal(rect.width()) * factor; + uiaRect->height = qreal(rect.height()) * factor; + } +} + +// Scales a point from native coordinates, according to high dpi settings. +void nativeUiaPointToPoint(const UiaPoint &uiaPoint, const QWindow *w, QPoint *point) +{ + if (w && point) { + const qreal factor = QHighDpiScaling::factor(w); + point->setX(int(std::lround(uiaPoint.x / factor))); + point->setY(int(std::lround(uiaPoint.y / factor))); + } +} + +// Maps an accessibility role ID to an UI Automation control type ID. +long roleToControlTypeId(QAccessible::Role role) +{ + static const QHash mapping { + {QAccessible::TitleBar, UIA_TitleBarControlTypeId}, + {QAccessible::MenuBar, UIA_MenuBarControlTypeId}, + {QAccessible::ScrollBar, UIA_ScrollBarControlTypeId}, + {QAccessible::Grip, UIA_ThumbControlTypeId}, + {QAccessible::Sound, UIA_CustomControlTypeId}, + {QAccessible::Cursor, UIA_CustomControlTypeId}, + {QAccessible::Caret, UIA_CustomControlTypeId}, + {QAccessible::AlertMessage, UIA_CustomControlTypeId}, + {QAccessible::Window, UIA_WindowControlTypeId}, + {QAccessible::Client, UIA_CustomControlTypeId}, + {QAccessible::PopupMenu, UIA_MenuControlTypeId}, + {QAccessible::MenuItem, UIA_MenuItemControlTypeId}, + {QAccessible::ToolTip, UIA_ToolTipControlTypeId}, + {QAccessible::Application, UIA_CustomControlTypeId}, + {QAccessible::Document, UIA_DocumentControlTypeId}, + {QAccessible::Pane, UIA_PaneControlTypeId}, + {QAccessible::Chart, UIA_CustomControlTypeId}, + {QAccessible::Dialog, UIA_WindowControlTypeId}, + {QAccessible::Border, UIA_CustomControlTypeId}, + {QAccessible::Grouping, UIA_GroupControlTypeId}, + {QAccessible::Separator, UIA_SeparatorControlTypeId}, + {QAccessible::ToolBar, UIA_ToolBarControlTypeId}, + {QAccessible::StatusBar, UIA_StatusBarControlTypeId}, + {QAccessible::Table, UIA_TableControlTypeId}, + {QAccessible::ColumnHeader, UIA_HeaderControlTypeId}, + {QAccessible::RowHeader, UIA_HeaderControlTypeId}, + {QAccessible::Column, UIA_HeaderItemControlTypeId}, + {QAccessible::Row, UIA_HeaderItemControlTypeId}, + {QAccessible::Cell, UIA_DataItemControlTypeId}, + {QAccessible::Link, UIA_HyperlinkControlTypeId}, + {QAccessible::HelpBalloon, UIA_ToolTipControlTypeId}, + {QAccessible::Assistant, UIA_CustomControlTypeId}, + {QAccessible::List, UIA_ListControlTypeId}, + {QAccessible::ListItem, UIA_ListItemControlTypeId}, + {QAccessible::Tree, UIA_TreeControlTypeId}, + {QAccessible::TreeItem, UIA_TreeItemControlTypeId}, + {QAccessible::PageTab, UIA_TabItemControlTypeId}, + {QAccessible::PropertyPage, UIA_CustomControlTypeId}, + {QAccessible::Indicator, UIA_CustomControlTypeId}, + {QAccessible::Graphic, UIA_ImageControlTypeId}, + {QAccessible::StaticText, UIA_EditControlTypeId}, + {QAccessible::EditableText, UIA_EditControlTypeId}, + {QAccessible::Button, UIA_ButtonControlTypeId}, + {QAccessible::CheckBox, UIA_CheckBoxControlTypeId}, + {QAccessible::RadioButton, UIA_RadioButtonControlTypeId}, + {QAccessible::ComboBox, UIA_ComboBoxControlTypeId}, + {QAccessible::ProgressBar, UIA_ProgressBarControlTypeId}, + {QAccessible::Dial, UIA_CustomControlTypeId}, + {QAccessible::HotkeyField, UIA_CustomControlTypeId}, + {QAccessible::Slider, UIA_SliderControlTypeId}, + {QAccessible::SpinBox, UIA_SpinnerControlTypeId}, + {QAccessible::Canvas, UIA_CustomControlTypeId}, + {QAccessible::Animation, UIA_CustomControlTypeId}, + {QAccessible::Equation, UIA_CustomControlTypeId}, + {QAccessible::ButtonDropDown, UIA_ButtonControlTypeId}, + {QAccessible::ButtonMenu, UIA_ButtonControlTypeId}, + {QAccessible::ButtonDropGrid, UIA_ButtonControlTypeId}, + {QAccessible::Whitespace, UIA_CustomControlTypeId}, + {QAccessible::PageTabList, UIA_TabControlTypeId}, + {QAccessible::Clock, UIA_CustomControlTypeId}, + {QAccessible::Splitter, UIA_CustomControlTypeId}, + }; + + return mapping.value(role, UIA_CustomControlTypeId); +} + +// True if a character can be a separator for a text unit. +bool isTextUnitSeparator(TextUnit unit, const QChar &ch) +{ + return (((unit == TextUnit_Word) || (unit == TextUnit_Format)) && ch.isSpace()) + || ((unit == TextUnit_Line) && (ch.toLatin1() == '\n')); +} + +} // namespace QWindowsUiAutomation + + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h new file mode 100644 index 0000000000..15f4d6e8ba --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIAUTILS_H +#define QWINDOWSUIAUTILS_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QWindowsUiAutomation { + +QWindow *windowForAccessible(const QAccessibleInterface *accessible); + +HWND hwndForAccessible(const QAccessibleInterface *accessible); + +void rectToNativeUiaRect(const QRect &rect, const QWindow *w, UiaRect *uiaRect); + +void nativeUiaPointToPoint(const UiaPoint &uiaPoint, const QWindow *w, QPoint *point); + +long roleToControlTypeId(QAccessible::Role role); + +bool isTextUnitSeparator(TextUnit unit, const QChar &ch); + +void clearVariant(VARIANT *variant); + +void setVariantI4(int value, VARIANT *variant); + +void setVariantBool(bool value, VARIANT *variant); + +void setVariantDouble(double value, VARIANT *variant); + +BSTR bStrFromQString(const QString &value); + +void setVariantString(const QString &value, VARIANT *variant); + +} // namespace QWindowsUiAutomation + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIAUTILS_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp new file mode 100644 index 0000000000..ef7d564e22 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwindowsuiavalueprovider.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaValueProvider::QWindowsUiaValueProvider(QAccessible::Id id) : + QWindowsUiaBaseProvider(id) +{ +} + +QWindowsUiaValueProvider::~QWindowsUiaValueProvider() +{ +} + +// Sets the value associated with the control. +HRESULT STDMETHODCALLTYPE QWindowsUiaValueProvider::SetValue(LPCWSTR val) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + // First sets the value as a text. + QString strVal = QString::fromUtf16(reinterpret_cast(val)); + accessible->setText(QAccessible::Value, strVal); + + // Then, if the control supports the value interface (range value) + // and the supplied text can be converted to a number, and that number + // lies within the min/max limits, sets it as the control's current (numeric) value. + if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) { + bool ok = false; + double numval = strVal.toDouble(&ok); + if (ok) { + double minimum = valueInterface->minimumValue().toDouble(); + double maximum = valueInterface->maximumValue().toDouble(); + if ((numval >= minimum) && (numval <= maximum)) { + valueInterface->setCurrentValue(QVariant(numval)); + } + } + } + return S_OK; +} + +// True for read-only controls. +HRESULT STDMETHODCALLTYPE QWindowsUiaValueProvider::get_IsReadOnly(BOOL *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = FALSE; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + *pRetVal = accessible->state().readOnly; + return S_OK; +} + +// Returns the value in text form. +HRESULT STDMETHODCALLTYPE QWindowsUiaValueProvider::get_Value(BSTR *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + *pRetVal = bStrFromQString(accessible->text(QAccessible::Value)); + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h new file mode 100644 index 0000000000..db54fc0a46 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QWINDOWSUIAVALUEPROVIDER_H +#define QWINDOWSUIAVALUEPROVIDER_H + +#include +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsuiabaseprovider.h" + +QT_BEGIN_NAMESPACE + +// Implements the Value control pattern provider. +// Supported for all controls that can return text(QAccessible::Value). +class QWindowsUiaValueProvider : public QWindowsUiaBaseProvider, + public QWindowsComBase +{ + Q_DISABLE_COPY(QWindowsUiaValueProvider) +public: + explicit QWindowsUiaValueProvider(QAccessible::Id id); + virtual ~QWindowsUiaValueProvider(); + + // IValueProvider + HRESULT STDMETHODCALLTYPE SetValue(LPCWSTR val); + HRESULT STDMETHODCALLTYPE get_IsReadOnly(BOOL *pRetVal); + HRESULT STDMETHODCALLTYPE get_Value(BSTR *pRetVal); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY + +#endif // QWINDOWSUIAVALUEPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/uiautomation.pri b/src/plugins/platforms/windows/uiautomation/uiautomation.pri new file mode 100644 index 0000000000..e3071766d9 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/uiautomation.pri @@ -0,0 +1,43 @@ +qtHaveModule(windowsuiautomation_support-private): \ + QT += windowsuiautomation_support-private + +SOURCES += \ + $$PWD/qwindowsuiaaccessibility.cpp \ + $$PWD/qwindowsuiaprovidercache.cpp \ + $$PWD/qwindowsuiamainprovider.cpp \ + $$PWD/qwindowsuiabaseprovider.cpp \ + $$PWD/qwindowsuiavalueprovider.cpp \ + $$PWD/qwindowsuiatextprovider.cpp \ + $$PWD/qwindowsuiatextrangeprovider.cpp \ + $$PWD/qwindowsuiatoggleprovider.cpp \ + $$PWD/qwindowsuiaselectionprovider.cpp \ + $$PWD/qwindowsuiaselectionitemprovider.cpp \ + $$PWD/qwindowsuiainvokeprovider.cpp \ + $$PWD/qwindowsuiarangevalueprovider.cpp \ + $$PWD/qwindowsuiatableprovider.cpp \ + $$PWD/qwindowsuiatableitemprovider.cpp \ + $$PWD/qwindowsuiagridprovider.cpp \ + $$PWD/qwindowsuiagriditemprovider.cpp \ + $$PWD/qwindowsuiautils.cpp + +HEADERS += \ + $$PWD/qwindowsuiaaccessibility.h \ + $$PWD/qwindowsuiaprovidercache.h \ + $$PWD/qwindowsuiamainprovider.h \ + $$PWD/qwindowsuiabaseprovider.h \ + $$PWD/qwindowsuiavalueprovider.h \ + $$PWD/qwindowsuiatextprovider.h \ + $$PWD/qwindowsuiatextrangeprovider.h \ + $$PWD/qwindowsuiatoggleprovider.h \ + $$PWD/qwindowsuiaselectionprovider.h \ + $$PWD/qwindowsuiaselectionitemprovider.h \ + $$PWD/qwindowsuiainvokeprovider.h \ + $$PWD/qwindowsuiarangevalueprovider.h \ + $$PWD/qwindowsuiatableprovider.h \ + $$PWD/qwindowsuiatableitemprovider.h \ + $$PWD/qwindowsuiagridprovider.h \ + $$PWD/qwindowsuiagriditemprovider.h \ + $$PWD/qwindowsuiautils.h + +mingw: LIBS *= -luuid + diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index b7790a66e3..f4c396f7c5 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -53,7 +53,7 @@ HEADERS += \ $$PWD/qwindowsservices.h \ $$PWD/qwindowsnativeinterface.h \ $$PWD/qwindowsopengltester.h \ - $$PWD/qwindowsthreadpoolrunner.h + $$PWD/qwindowsthreadpoolrunner.h \ $$PWD/qwin10helpers.h INCLUDEPATH += $$PWD @@ -109,7 +109,7 @@ qtConfig(imageformat_png):RESOURCES += $$PWD/cursors.qrc RESOURCES += $$PWD/openglblacklists.qrc -qtConfig(accessibility): include($$PWD/accessible/accessible.pri) +qtConfig(accessibility): include($$PWD/uiautomation/uiautomation.pri) qtConfig(combined-angle-lib) { DEFINES *= LIBEGL_NAME=$${LIBQTANGLE_NAME} diff --git a/sync.profile b/sync.profile index a696be5e54..6a50e31102 100644 --- a/sync.profile +++ b/sync.profile @@ -11,6 +11,7 @@ "QtDBus" => "$basedir/src/dbus", "QtConcurrent" => "$basedir/src/concurrent", "QtAccessibilitySupport" => "$basedir/src/platformsupport/accessibility", + "QtWindowsUIAutomationSupport" => "$basedir/src/platformsupport/windowsuiautomation", "QtLinuxAccessibilitySupport" => "$basedir/src/platformsupport/linuxaccessibility", "QtClipboardSupport" => "$basedir/src/platformsupport/clipboard", "QtDeviceDiscoverySupport" => "$basedir/src/platformsupport/devicediscovery", diff --git a/tests/auto/other/qaccessibility/qaccessibility.pro b/tests/auto/other/qaccessibility/qaccessibility.pro index 727d5fe0d7..91e0f7472e 100644 --- a/tests/auto/other/qaccessibility/qaccessibility.pro +++ b/tests/auto/other/qaccessibility/qaccessibility.pro @@ -8,9 +8,8 @@ HEADERS += accessiblewidgets.h unix:!darwin:!haiku:!integity: LIBS += -lm win32 { - !*g++:!winrt { - include(../../../../src/3rdparty/iaccessible2/iaccessible2.pri) - DEFINES += QT_SUPPORTS_IACCESSIBLE2 + !winrt { + QT += windowsuiautomation_support-private } LIBS += -luuid -loleacc -loleaut32 -lole32 } diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index e73af60e74..8d54108737 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -32,12 +32,10 @@ # include #ifndef Q_OS_WINRT # include +# include #endif # include # include -# ifdef QT_SUPPORTS_IACCESSIBLE2 -# include -# endif #endif #include #include @@ -3742,7 +3740,7 @@ void tst_QAccessibility::bridgeTest() // For now this is a simple test to see if the bridge is working at all. // Ideally it should be extended to test all aspects of the bridge. #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) - // First, test MSAA part of bridge + QWidget *window = new QWidget; QVBoxLayout *lay = new QVBoxLayout(window); QPushButton *button = new QPushButton(tr("Push me"), window); @@ -3779,10 +3777,7 @@ void tst_QAccessibility::bridgeTest() window->show(); QVERIFY(QTest::qWaitForWindowExposed(window)); - - /************************************************** - * QPushButton - **************************************************/ + // Validate button position through the accessible interface. QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(button); QPoint buttonPos = button->mapToGlobal(QPoint(0,0)); QRect buttonRect = iface->rect(); @@ -3792,231 +3787,113 @@ void tst_QAccessibility::bridgeTest() POINT pt; pt.x = buttonRect.center().x(); pt.y = buttonRect.center().y(); - IAccessible *iaccButton; - VARIANT varChild; - HRESULT hr = ::AccessibleObjectFromPoint(pt, &iaccButton, &varChild); + // Initialize COM stuff. + HRESULT hr = CoInitialize(nullptr); QVERIFY(SUCCEEDED(hr)); - VARIANT varSELF; - varSELF.vt = VT_I4; - varSELF.lVal = 0; - // **** Test get_accRole **** - VARIANT varRole; - hr = iaccButton->get_accRole(varSELF, &varRole); + // Get UI Automation interface. + IUIAutomation *automation = nullptr; + hr = CoCreateInstance(CLSID_CUIAutomation, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&automation)); QVERIFY(SUCCEEDED(hr)); - QCOMPARE(varRole.vt, (VARTYPE)VT_I4); - QCOMPARE(varRole.lVal, (LONG)ROLE_SYSTEM_PUSHBUTTON); - - // **** Test accLocation **** - long x, y, w, h; - // Do not crash on insane arguments. - varChild.lVal = 999; - hr = iaccButton->accLocation(&x, &y, &w, &h, varChild); - QCOMPARE(SUCCEEDED(hr), false); - - hr = iaccButton->accLocation(&x, &y, &w, &h, varSELF); - QCOMPARE(buttonRect, QRect(x, y, w, h)); - -#ifdef QT_SUPPORTS_IACCESSIBLE2 - // Test IAccessible2 part of bridge - if (IAccessible2 *ia2Button = (IAccessible2*)queryIA2(iaccButton, IID_IAccessible2)) { - // The control supports IAccessible2. - // ia2Button is the reference to the accessible object's IAccessible2 interface. - - /***** Test IAccessibleComponent *****/ - IAccessibleComponent *ia2Component = 0; - hr = ia2Button->QueryInterface(IID_IAccessibleComponent, (void**)&ia2Component); - QVERIFY(SUCCEEDED(hr)); - long x, y; - hr = ia2Component->get_locationInParent(&x, &y); - QVERIFY(SUCCEEDED(hr)); - QCOMPARE(button->pos(), QPoint(x, y)); - ia2Component->Release(); - - /***** Test IAccessibleAction *****/ - IAccessibleAction *ia2Action = 0; - hr = ia2Button->QueryInterface(IID_IAccessibleAction, (void**)&ia2Action); - QVERIFY(SUCCEEDED(hr)); - QVERIFY(ia2Action); - long nActions; - ia2Action->nActions(&nActions); - QVERIFY(nActions >= 1); // "Press" and "SetFocus" - BSTR actionName; - ia2Action->get_name(0, &actionName); - QString name((QChar*)actionName); - ::SysFreeString(actionName); - QCOMPARE(name, QAccessibleActionInterface::pressAction()); - ia2Action->Release(); - - /***** Test IAccessibleRelation *****/ - long nRelations = 0; - hr = ia2Button->get_nRelations(&nRelations); - QVERIFY(SUCCEEDED(hr)); - QCOMPARE(nRelations, (long)1); - - IAccessibleRelation **relations = (IAccessibleRelation **)::CoTaskMemAlloc(sizeof(IAccessibleRelation *) * 4); - hr = ia2Button->get_relations(4, relations, &nRelations); - QVERIFY(SUCCEEDED(hr)); - QCOMPARE(nRelations, (long)1); - - IAccessibleRelation *relation = relations[0]; - BSTR relType; - hr = relation->get_relationType(&relType); - QCOMPARE(QString::fromWCharArray(relType), QLatin1String("labelFor")); - ::SysFreeString(relType); - - long nTargets; - relation->get_nTargets(&nTargets); - QCOMPARE(nTargets, (long)1); - IAccessible *target; // target is the label - hr = relation->get_target(0, (IUnknown**)&target); - QVERIFY(SUCCEEDED(hr)); - - VARIANT varRole; - hr = target->get_accRole(varSELF, &varRole); - QVERIFY(SUCCEEDED(hr)); - Q_ASSERT(varRole.vt == (VARTYPE)VT_I4); - QCOMPARE(varRole.lVal, (LONG)ROLE_SYSTEM_STATICTEXT); + // Get button element from UI Automation using point. + IUIAutomationElement *buttonElement = nullptr; + hr = automation->ElementFromPoint(pt, &buttonElement); + QVERIFY(SUCCEEDED(hr)); - BSTR buttonName; - hr = target->get_accName(varSELF, &buttonName); - QVERIFY(SUCCEEDED(hr)); + // Check that it has a button control type ID. + CONTROLTYPEID controlTypeId; + hr = buttonElement->get_CurrentControlType(&controlTypeId); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(controlTypeId, UIA_ButtonControlTypeId); - QCOMPARE(QString::fromWCharArray(buttonName), QLatin1String("Push my buddy")); - ::SysFreeString(buttonName); - ::CoTaskMemFree(relations); + // Test the bounding rectangle. + RECT rect; + hr = buttonElement->get_CurrentBoundingRectangle(&rect); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(buttonRect, QRect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top)); - // Done testing - ia2Button->Release(); - } -#endif - iaccButton->Release(); + buttonElement->Release(); - /************************************************** - * QWidget - **************************************************/ + // Get native window handle. QWindow *windowHandle = window->windowHandle(); + QVERIFY(windowHandle != 0); QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface(); + QVERIFY(platform != 0); HWND hWnd = (HWND)platform->nativeResourceForWindow("handle", windowHandle); + QVERIFY(hWnd != 0); - IAccessible *iaccWindow; - hr = ::AccessibleObjectFromWindow(hWnd, OBJID_CLIENT, IID_IAccessible, (void**)&iaccWindow); + // Get automation element for the window from handle. + IUIAutomationElement *windowElement = nullptr; + hr = automation->ElementFromHandle(hWnd, &windowElement); QVERIFY(SUCCEEDED(hr)); - hr = iaccWindow->get_accRole(varSELF, &varRole); + QVERIFY(windowElement != 0); + + // Validate that the top-level widget is reported as a window. + hr = windowElement->get_CurrentControlType(&controlTypeId); QVERIFY(SUCCEEDED(hr)); + QCOMPARE(controlTypeId, UIA_WindowControlTypeId); - QCOMPARE(varRole.vt, (VARTYPE)VT_I4); - QCOMPARE(varRole.lVal, (LONG)ROLE_SYSTEM_CLIENT); + // Get a tree walker to walk over elements. + IUIAutomationTreeWalker *controlWalker = nullptr; + IUIAutomationElement *node = nullptr; + QList nodeList; - long nChildren; - hr = iaccWindow->get_accChildCount(&nChildren); + hr = automation->get_ControlViewWalker(&controlWalker); QVERIFY(SUCCEEDED(hr)); - QCOMPARE(nChildren, (long)4); - - /************************************************** - * QTextEdit - **************************************************/ - // Get the second child (the accessible interface for the text edit) - varChild.vt = VT_I4; - varChild.lVal = 2; - QVERIFY(iaccWindow); - IAccessible *iaccTextEdit; - hr = iaccWindow->get_accChild(varChild, (IDispatch**)&iaccTextEdit); - QVERIFY(SUCCEEDED(hr)); - QVERIFY(iaccTextEdit); - hr = iaccTextEdit->get_accRole(varSELF, &varRole); - QVERIFY(SUCCEEDED(hr)); - - QCOMPARE(varRole.vt, (VARTYPE)VT_I4); - QCOMPARE(varRole.lVal, (LONG)ROLE_SYSTEM_TEXT); + QVERIFY(controlWalker != 0); + hr = controlWalker->GetFirstChildElement(windowElement, &node); + QVERIFY(SUCCEEDED(hr)); + QVERIFY(node != 0); + int numElements = 5; // Title bar + 4 widgets -#ifdef QT_SUPPORTS_IACCESSIBLE2 - if (IAccessibleEditableText *ia2TextEdit = (IAccessibleEditableText*)queryIA2(iaccTextEdit, IID_IAccessibleEditableText)) { - ia2TextEdit->copyText(6, 11); - QCOMPARE(QApplication::clipboard()->text(), QLatin1String("world")); - ia2TextEdit->cutText(12, 16); - QCOMPARE(QApplication::clipboard()->text(), QLatin1String("how ")); - ia2TextEdit->Release(); - } - if (IAccessibleText *ia2Text = (IAccessibleText*)queryIA2(iaccTextEdit, IID_IAccessibleText)) { - BSTR txt; - hr = ia2Text->get_text(12, 15, &txt); + while (node) { + nodeList.append(node); + QVERIFY(nodeList.size() <= numElements); + IUIAutomationElement *next = nullptr; + hr = controlWalker->GetNextSiblingElement(node, &next); QVERIFY(SUCCEEDED(hr)); - QCOMPARE(QString((QChar*)txt), QLatin1String("are")); - ia2Text->Release(); + node = next; } -#endif - iaccTextEdit->Release(); + QCOMPARE(nodeList.size(), numElements); + // Title bar + hr = nodeList.at(0)->get_CurrentControlType(&controlTypeId); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(controlTypeId, UIA_TitleBarControlTypeId); - /************************************************** - * QTableWidget - **************************************************/ - { - // Get the second child (the accessible interface for the table widget) - varChild.vt = VT_I4; - varChild.lVal = 3; - QVERIFY(iaccWindow); - IAccessible *iaccTable = 0; - hr = iaccWindow->get_accChild(varChild, (IDispatch**)&iaccTable); - QVERIFY(SUCCEEDED(hr)); - QVERIFY(iaccTable); - hr = iaccTable->get_accRole(varSELF, &varRole); - QVERIFY(SUCCEEDED(hr)); - - QCOMPARE(varRole.vt, (VARTYPE)VT_I4); - QCOMPARE(varRole.lVal, (LONG)ROLE_SYSTEM_TABLE); - + // Button + hr = nodeList.at(1)->get_CurrentControlType(&controlTypeId); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(controlTypeId, UIA_ButtonControlTypeId); -#ifdef QT_SUPPORTS_IACCESSIBLE2 - IAccessibleTable2 *ia2Table = (IAccessibleTable2*)queryIA2(iaccTable, IID_IAccessibleTable2); - QVERIFY(ia2Table); - BSTR bstrDescription; - hr = ia2Table->get_columnDescription(0, &bstrDescription); - QVERIFY(SUCCEEDED(hr)); - QCOMPARE(QString::fromWCharArray(bstrDescription), QLatin1String("h1")); - ::SysFreeString(bstrDescription); + // Edit + hr = nodeList.at(2)->get_CurrentControlType(&controlTypeId); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(controlTypeId, UIA_EditControlTypeId); - hr = ia2Table->get_rowDescription(1, &bstrDescription); - QVERIFY(SUCCEEDED(hr)); - QCOMPARE(QString::fromWCharArray(bstrDescription), QLatin1String("v2")); - ::SysFreeString(bstrDescription); + // Table + hr = nodeList.at(3)->get_CurrentControlType(&controlTypeId); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(controlTypeId, UIA_TableControlTypeId); - IAccessible *accTableCell = 0; - hr = ia2Table->get_cellAt(1, 2, (IUnknown**)&accTableCell); - QVERIFY(SUCCEEDED(hr)); - QVERIFY(accTableCell); - IAccessibleTableCell *ia2TableCell = (IAccessibleTableCell *)queryIA2(accTableCell, IID_IAccessibleTableCell); - QVERIFY(ia2TableCell); - LONG index; - ia2TableCell->get_rowIndex(&index); - QCOMPARE(index, (LONG)1); - ia2TableCell->get_columnIndex(&index); - QCOMPARE(index, (LONG)2); - - IAccessible *iaccTableCell = 0; - hr = ia2TableCell->QueryInterface(IID_IAccessible, (void**)&iaccTableCell); - QVERIFY(SUCCEEDED(hr)); - QVERIFY(iaccTableCell); - BSTR bstrCellName; - hr = iaccTableCell->get_accName(varSELF, &bstrCellName); - QVERIFY(SUCCEEDED(hr)); - QString cellName((QChar*)bstrCellName); - QCOMPARE(cellName, QLatin1String("1.2")); + // Label + hr = nodeList.at(4)->get_CurrentControlType(&controlTypeId); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(controlTypeId, UIA_EditControlTypeId); - accTableCell->Release(); - iaccTableCell->Release(); - ia2TableCell->Release(); - ia2Table->Release(); -#endif - iaccTable->Release(); + for (auto nd : nodeList) { + nd->Release(); } - iaccWindow->Release(); + controlWalker->Release(); + windowElement->Release(); + automation->Release(); + CoUninitialize(); + QTestAccessibility::clearEvents(); #endif } -- cgit v1.2.3