From 436faee8b3704f9aae5620bc69f14c3461fc208c Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Tue, 27 Feb 2018 19:59:54 +0100 Subject: WinRT: Add Windows UI Automation support Adds support to accessibility tools and programmatic UI control to the WinRT platform through Windows UI Automation, using the AutomationPeer API. [ChangeLog][winrt][feature] Added support to Windows UI Automation to the WinRT QPA, allowing Qt-based UWP applications to operate with accessibility and programmatic UI control tools. Change-Id: If0a8edbebc7c16c4896d749f2d7e11809b4b37b3 Reviewed-by: Oliver Wolff Reviewed-by: Maurice Kalinowski --- src/plugins/platforms/winrt/qwinrtcanvas.cpp | 146 ++++ src/plugins/platforms/winrt/qwinrtcanvas.h | 75 ++ src/plugins/platforms/winrt/qwinrtintegration.cpp | 17 + src/plugins/platforms/winrt/qwinrtintegration.h | 3 + src/plugins/platforms/winrt/qwinrtscreen.cpp | 22 +- .../winrt/uiautomation/qwinrtuiaaccessibility.cpp | 106 +++ .../winrt/uiautomation/qwinrtuiaaccessibility.h | 64 ++ .../winrt/uiautomation/qwinrtuiabaseprovider.cpp | 76 ++ .../winrt/uiautomation/qwinrtuiabaseprovider.h | 72 ++ .../uiautomation/qwinrtuiacontrolmetadata.cpp | 182 +++++ .../winrt/uiautomation/qwinrtuiacontrolmetadata.h | 117 ++++ .../uiautomation/qwinrtuiaemptypropertyvalue.h | 108 +++ .../uiautomation/qwinrtuiagriditemprovider.cpp | 160 +++++ .../winrt/uiautomation/qwinrtuiagriditemprovider.h | 78 +++ .../winrt/uiautomation/qwinrtuiagridprovider.cpp | 135 ++++ .../winrt/uiautomation/qwinrtuiagridprovider.h | 76 ++ .../winrt/uiautomation/qwinrtuiainvokeprovider.cpp | 88 +++ .../winrt/uiautomation/qwinrtuiainvokeprovider.h | 74 ++ .../winrt/uiautomation/qwinrtuiamainprovider.cpp | 779 +++++++++++++++++++++ .../winrt/uiautomation/qwinrtuiamainprovider.h | 124 ++++ .../winrt/uiautomation/qwinrtuiametadatacache.cpp | 112 +++ .../winrt/uiautomation/qwinrtuiametadatacache.h | 76 ++ .../winrt/uiautomation/qwinrtuiapeervector.cpp | 149 ++++ .../winrt/uiautomation/qwinrtuiapeervector.h | 80 +++ .../winrt/uiautomation/qwinrtuiaprovidercache.cpp | 99 +++ .../winrt/uiautomation/qwinrtuiaprovidercache.h | 77 ++ .../uiautomation/qwinrtuiarangevalueprovider.cpp | 167 +++++ .../uiautomation/qwinrtuiarangevalueprovider.h | 80 +++ .../qwinrtuiaselectionitemprovider.cpp | 214 ++++++ .../uiautomation/qwinrtuiaselectionitemprovider.h | 78 +++ .../uiautomation/qwinrtuiaselectionprovider.cpp | 158 +++++ .../uiautomation/qwinrtuiaselectionprovider.h | 76 ++ .../uiautomation/qwinrtuiatableitemprovider.cpp | 141 ++++ .../uiautomation/qwinrtuiatableitemprovider.h | 75 ++ .../winrt/uiautomation/qwinrtuiatableprovider.cpp | 167 +++++ .../winrt/uiautomation/qwinrtuiatableprovider.h | 76 ++ .../winrt/uiautomation/qwinrtuiatextprovider.cpp | 232 ++++++ .../winrt/uiautomation/qwinrtuiatextprovider.h | 83 +++ .../uiautomation/qwinrtuiatextrangeprovider.cpp | 497 +++++++++++++ .../uiautomation/qwinrtuiatextrangeprovider.h | 95 +++ .../winrt/uiautomation/qwinrtuiatoggleprovider.cpp | 104 +++ .../winrt/uiautomation/qwinrtuiatoggleprovider.h | 75 ++ .../winrt/uiautomation/qwinrtuiautils.cpp | 182 +++++ .../platforms/winrt/uiautomation/qwinrtuiautils.h | 83 +++ .../winrt/uiautomation/qwinrtuiavalueprovider.cpp | 136 ++++ .../winrt/uiautomation/qwinrtuiavalueprovider.h | 77 ++ .../platforms/winrt/uiautomation/uiautomation.pri | 45 ++ src/plugins/platforms/winrt/winrt.pro | 4 + 48 files changed, 5930 insertions(+), 10 deletions(-) create mode 100644 src/plugins/platforms/winrt/qwinrtcanvas.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtcanvas.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiaemptypropertyvalue.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.h create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.cpp create mode 100644 src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.h create mode 100644 src/plugins/platforms/winrt/uiautomation/uiautomation.pri (limited to 'src/plugins/platforms/winrt') diff --git a/src/plugins/platforms/winrt/qwinrtcanvas.cpp b/src/plugins/platforms/winrt/qwinrtcanvas.cpp new file mode 100644 index 0000000000..ad77d811e6 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtcanvas.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 "qwinrtcanvas.h" +#include "uiautomation/qwinrtuiaaccessibility.h" +#include "uiautomation/qwinrtuiamainprovider.h" +#include "uiautomation/qwinrtuiametadatacache.h" +#include "uiautomation/qwinrtuiautils.h" + +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::System; +using namespace ABI::Windows::UI; +using namespace ABI::Windows::UI::Core; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; + +QT_BEGIN_NAMESPACE + +QWinRTCanvas::QWinRTCanvas(const std::function &delegateWindow) +{ + ComPtr factory; + HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(), IID_PPV_ARGS(&factory)); + Q_ASSERT_SUCCEEDED(hr); + + hr = factory->CreateInstance(this, &m_base, &m_core); + Q_ASSERT_SUCCEEDED(hr); + + delegate = delegateWindow; +} + +QWinRTCanvas::~QWinRTCanvas() +{ +} + +HRESULT STDMETHODCALLTYPE QWinRTCanvas::QueryInterface(REFIID iid, LPVOID *iface) +{ + if (!iface) + return E_POINTER; + *iface = nullptr; + + if (iid == IID_IUnknown) { + *iface = static_cast(this); + AddRef(); + return S_OK; + } else if (iid == Xaml::IID_IUIElementOverrides) { + *iface = static_cast(this); + AddRef(); + return S_OK; + } else { + return m_base.CopyTo(iid, iface); + } +} + +HRESULT STDMETHODCALLTYPE QWinRTCanvas::GetIids(ULONG *iidCount, IID **iids) +{ + *iidCount = 0; + *iids = nullptr; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTCanvas::GetRuntimeClassName(HSTRING *className) +{ + const wchar_t *name = L"QWinRTCanvas"; + return ::WindowsCreateString(name, static_cast(::wcslen(name)), className); +} + +HRESULT STDMETHODCALLTYPE QWinRTCanvas::GetTrustLevel(TrustLevel *trustLevel) +{ + *trustLevel = TrustLevel::BaseTrust; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTCanvas::OnCreateAutomationPeer(Xaml::Automation::Peers::IAutomationPeer **returnValue) +{ + if (!returnValue) + return E_INVALIDARG; + *returnValue = nullptr; + + if (delegate) { + if (QWindow *window = delegate()) { + QWinRTUiaAccessibility::activate(); + if (QAccessibleInterface *accessible = window->accessibleRoot()) { + QAccessible::Id accid = QWinRTUiAutomation::idForAccessible(accessible); + QWinRTUiaMetadataCache::instance()->load(accid); + if (ComPtr provider = QWinRTUiaMainProvider::providerForAccessibleId(accid)) + return provider.CopyTo(returnValue); + } + } + } + return m_base->OnCreateAutomationPeer(returnValue); +} + +HRESULT STDMETHODCALLTYPE QWinRTCanvas::OnDisconnectVisualChildren() +{ + return m_base->OnDisconnectVisualChildren(); +} + +HRESULT STDMETHODCALLTYPE QWinRTCanvas::FindSubElementsForTouchTargeting(Point point, Rect boundingRect, IIterable*> **returnValue) +{ + return m_base->FindSubElementsForTouchTargeting(point, boundingRect, returnValue); +} + +QT_END_NAMESPACE + diff --git a/src/plugins/platforms/winrt/qwinrtcanvas.h b/src/plugins/platforms/winrt/qwinrtcanvas.h new file mode 100644 index 0000000000..68c15c7602 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtcanvas.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTCANVAS_H +#define QWINRTCANVAS_H + +#include +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QWinRTCanvas: + public Microsoft::WRL::RuntimeClass +{ +public: + QWinRTCanvas(const std::function &delegateWindow); + virtual ~QWinRTCanvas(); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *iface) override; + HRESULT STDMETHODCALLTYPE GetIids(ULONG *iidCount, IID **iids) override; + HRESULT STDMETHODCALLTYPE GetRuntimeClassName(HSTRING *className) override; + HRESULT STDMETHODCALLTYPE GetTrustLevel(TrustLevel *trustLevel) override; + HRESULT STDMETHODCALLTYPE OnCreateAutomationPeer(ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer **returnValue) override; + HRESULT STDMETHODCALLTYPE OnDisconnectVisualChildren() override; + HRESULT STDMETHODCALLTYPE FindSubElementsForTouchTargeting(ABI::Windows::Foundation::Point point, ABI::Windows::Foundation::Rect boundingRect, ABI::Windows::Foundation::Collections::IIterable*> **returnValue) override; + +private: + Microsoft::WRL::ComPtr m_base; + Microsoft::WRL::ComPtr m_core; + std::function delegate; +}; + +QT_END_NAMESPACE + +#endif // QWINRTCANVAS_H diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 7a30c8d98b..eae043f3a7 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -50,6 +50,9 @@ #ifndef QT_NO_DRAGANDDROP #include "qwinrtdrag.h" #endif +#if QT_CONFIG(accessibility) +# include "uiautomation/qwinrtuiaaccessibility.h" +#endif #include #include @@ -119,6 +122,9 @@ public: QPlatformClipboard *clipboard; QWinRTScreen *mainScreen; QScopedPointer inputContext; +#if QT_CONFIG(accessibility) + QWinRTUiaAccessibility *accessibility; +#endif ComPtr application; QHash applicationTokens; @@ -198,6 +204,9 @@ QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate) screenAdded(d->mainScreen); d->platformServices = new QWinRTServices; d->clipboard = new QWinRTClipboard; +#if QT_CONFIG(accessibility) + d->accessibility = new QWinRTUiaAccessibility; +#endif } QWinRTIntegration::~QWinRTIntegration() @@ -315,6 +324,14 @@ QPlatformDrag *QWinRTIntegration::drag() const } #endif // QT_NO_DRAGANDDROP +#if QT_CONFIG(accessibility) +QPlatformAccessibility *QWinRTIntegration::accessibility() const +{ + Q_D(const QWinRTIntegration); + return d->accessibility; +} +#endif // QT_CONFIG(accessibility) + Qt::KeyboardModifiers QWinRTIntegration::queryKeyboardModifiers() const { Q_D(const QWinRTIntegration); diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h index e22532a266..adc7620727 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.h +++ b/src/plugins/platforms/winrt/qwinrtintegration.h @@ -100,6 +100,9 @@ public: #ifndef QT_NO_DRAGANDDROP QPlatformDrag *drag() const override; #endif +#if QT_CONFIG(accessibility) + QPlatformAccessibility *accessibility() const override; +#endif Qt::KeyboardModifiers queryKeyboardModifiers() const override; diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index e37aeb0bc5..a325d6f817 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -46,6 +46,7 @@ #include "qwinrtdrag.h" #endif #include "qwinrtwindow.h" +#include "qwinrtcanvas.h" #include #include @@ -463,7 +464,7 @@ public: QTouchDevice *touchDevice; ComPtr coreWindow; ComPtr redirect; - ComPtr canvas; + ComPtr canvas; ComPtr view; ComPtr displayInformation; @@ -553,27 +554,25 @@ QWinRTScreen::QWinRTScreen() hr = applicationViewStatics->GetForCurrentView(&d->view); RETURN_VOID_IF_FAILED("Could not access currentView"); - // Create a canvas and set it as the window content. Eventually, this should have its own method so multiple "screens" can be added - ComPtr canvas; - hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(), &canvas); - Q_ASSERT_SUCCEEDED(hr); + d->canvas = Make([this]() { return topWindow(); }); + ComPtr frameworkElement; - hr = canvas.As(&frameworkElement); + hr = d->canvas.As(&frameworkElement); Q_ASSERT_SUCCEEDED(hr); hr = frameworkElement->put_Width(d->logicalRect.width()); Q_ASSERT_SUCCEEDED(hr); hr = frameworkElement->put_Height(d->logicalRect.height()); Q_ASSERT_SUCCEEDED(hr); + ComPtr uiElement; - hr = canvas.As(&uiElement); + hr = d->canvas.As(&uiElement); Q_ASSERT_SUCCEEDED(hr); + #ifndef QT_NO_DRAGANDDROP QWinRTDrag::instance()->setUiElement(uiElement); #endif hr = window->put_Content(uiElement.Get()); Q_ASSERT_SUCCEEDED(hr); - hr = canvas.As(&d->canvas); - Q_ASSERT_SUCCEEDED(hr); d->cursor.reset(new QWinRTCursor); @@ -723,7 +722,10 @@ ICoreWindow *QWinRTScreen::coreWindow() const Xaml::IDependencyObject *QWinRTScreen::canvas() const { Q_D(const QWinRTScreen); - return d->canvas.Get(); + Xaml::IDependencyObject *depCanvas; + if (SUCCEEDED(d->canvas.CopyTo(&depCanvas))) + return depCanvas; + return nullptr; } void QWinRTScreen::initialize() diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.cpp new file mode 100644 index 0000000000..878fcd0f96 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiaaccessibility.h" +#include "qwinrtuiamainprovider.h" + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QWinRTUiaAccessibility::QWinRTUiaAccessibility() +{ +} + +QWinRTUiaAccessibility::~QWinRTUiaAccessibility() +{ +} + +// Handles UI Automation window messages. +void QWinRTUiaAccessibility::activate() +{ + // Start handling accessibility internally + QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true); +} + +// Handles accessibility update notifications. +void QWinRTUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event) +{ + if (!event) + return; + + QAccessibleInterface *accessible = event->accessibleInterface(); + if (!isActive() || !accessible || !accessible->isValid()) + return; + + switch (event->type()) { + case QAccessible::Focus: + QWinRTUiaMainProvider::notifyFocusChange(event); + break; + case QAccessible::StateChanged: + QWinRTUiaMainProvider::notifyStateChange(static_cast(event)); + break; + case QAccessible::ValueChanged: + QWinRTUiaMainProvider::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: + QWinRTUiaMainProvider::notifyTextChange(event); + break; + default: + break; + } +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.h new file mode 100644 index 0000000000..b966271e21 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIAACCESSIBILITY_H +#define QWINRTUIAACCESSIBILITY_H + +#include +#if QT_CONFIG(accessibility) + +#include + +QT_BEGIN_NAMESPACE + +// WinRT platform accessibility implemented over UI Automation. +class QWinRTUiaAccessibility : public QPlatformAccessibility +{ +public: + explicit QWinRTUiaAccessibility(); + virtual ~QWinRTUiaAccessibility(); + static void activate(); + void notifyAccessibilityUpdate(QAccessibleEvent *event) override; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIAACCESSIBILITY_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.cpp new file mode 100644 index 0000000000..ee53714caa --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QWinRTUiaBaseProvider::QWinRTUiaBaseProvider(QAccessible::Id id) : + m_id(id) +{ +} + +QWinRTUiaBaseProvider::~QWinRTUiaBaseProvider() +{ +} + +QAccessibleInterface *QWinRTUiaBaseProvider::accessibleInterface() const +{ + QAccessibleInterface *accessible = QAccessible::accessibleInterface(m_id); + if (accessible && accessible->isValid()) + return accessible; + return nullptr; +} + +QAccessible::Id QWinRTUiaBaseProvider::id() const +{ + return m_id; +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.h new file mode 100644 index 0000000000..d8837354dc --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIABASEPROVIDER_H +#define QWINRTUIABASEPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +// Base class for UI Automation providers. +class QWinRTUiaBaseProvider : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(QWinRTUiaBaseProvider) +public: + explicit QWinRTUiaBaseProvider(QAccessible::Id id); + virtual ~QWinRTUiaBaseProvider(); + + QAccessibleInterface *accessibleInterface() const; + QAccessible::Id id() const; + +private: + QAccessible::Id m_id; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIABASEPROVIDER_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.cpp new file mode 100644 index 0000000000..4e406a3545 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiacontrolmetadata.h" +#include "qwinrtuiautils.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWinRTUiAutomation; + +QWinRTUiaControlMetadata::QWinRTUiaControlMetadata() +{ +} + +QWinRTUiaControlMetadata::QWinRTUiaControlMetadata(QAccessible::Id id) +{ + update(id); +} + +void QWinRTUiaControlMetadata::update(QAccessible::Id id) +{ + if (QAccessibleInterface *accessible = accessibleForId(id)) { + m_automationId = generateAutomationId(accessible); + m_className = generateClassName(accessible); + m_controlName = generateControlName(accessible); + m_role = generateRole(accessible); + m_state = accessible->state(); + m_accelerator = accessible->text(QAccessible::Accelerator); + m_access = accessible->text(QAccessible::Accelerator); + m_help = accessible->text(QAccessible::Help); + m_description = accessible->text(QAccessible::Description); + m_value = accessible->text(QAccessible::Value); + m_boundingRect = accessible->rect(); + updateValueData(accessible); + updateTableData(accessible); + updateTextData(accessible); + } +} + +QString QWinRTUiaControlMetadata::generateControlName(QAccessibleInterface *accessible) +{ + const bool clientTopLevel = (accessible->role() == QAccessible::Client) + && accessible->parent() && (accessible->parent()->role() == QAccessible::Application); + + QString name = accessible->text(QAccessible::Name); + if (name.isEmpty() && clientTopLevel) + name = QCoreApplication::applicationName(); + return name; +} + +QString QWinRTUiaControlMetadata::generateClassName(QAccessibleInterface *accessible) +{ + QString name; + + if (QObject *obj = accessible->object()) + name = QLatin1String(obj->metaObject()->className()); + return name; +} + +// Generates an ID based on the name of the controls and their parents. +QString QWinRTUiaControlMetadata::generateAutomationId(QAccessibleInterface *accessible) +{ + QString autid; + QObject *obj = accessible->object(); + while (obj) { + QString name = obj->objectName(); + if (name.isEmpty()) { + autid = QStringLiteral(""); + break; + } + if (!autid.isEmpty()) + autid.prepend(QLatin1Char('.')); + autid.prepend(name); + obj = obj->parent(); + } + return autid; +} + +QAccessible::Role QWinRTUiaControlMetadata::generateRole(QAccessibleInterface *accessible) +{ + const bool clientTopLevel = (accessible->role() == QAccessible::Client) + && accessible->parent() && (accessible->parent()->role() == QAccessible::Application); + + if (clientTopLevel) { + // Reports a top-level widget as a window. + return QAccessible::Window; + } else { + return accessible->role(); + } +} + +void QWinRTUiaControlMetadata::updateValueData(QAccessibleInterface *accessible) +{ + if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) { + m_minimumValue = valueInterface->minimumValue().toDouble(); + m_maximumValue = valueInterface->maximumValue().toDouble(); + m_currentValue = valueInterface->currentValue().toDouble(); + m_minimumStepSize = valueInterface->minimumStepSize().toDouble(); + } else { + m_minimumValue = 0.0; + m_maximumValue = 0.0; + m_currentValue = 0.0; + m_minimumStepSize = 0.0; + } +} + +void QWinRTUiaControlMetadata::updateTableData(QAccessibleInterface *accessible) +{ + if (QAccessibleTableInterface *tableInterface = accessible->tableInterface()) { + m_rowIndex = 0; + m_columnIndex = 0; + m_rowCount = tableInterface->rowCount(); + m_columnCount = tableInterface->columnCount(); + } else if (QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface()) { + m_rowIndex = tableCellInterface->rowIndex(); + m_columnIndex = tableCellInterface->columnIndex(); + m_rowCount = tableCellInterface->rowExtent(); + m_columnCount = tableCellInterface->columnExtent(); + } else { + m_rowIndex = 0; + m_columnIndex = 0; + m_rowCount = 0; + m_columnCount = 0; + } +} + +void QWinRTUiaControlMetadata::updateTextData(QAccessibleInterface *accessible) +{ + if (QAccessibleTextInterface *textInterface = accessible->textInterface()) { + m_cursorPosition = textInterface->cursorPosition(); + m_text = textInterface->text(0, textInterface->characterCount()); + } else { + m_cursorPosition = 0; + m_text = QStringLiteral(""); + } +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.h new file mode 100644 index 0000000000..769f073a1b --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIACONTROLMETADATA_H +#define QWINRTUIACONTROLMETADATA_H + +#include +#if QT_CONFIG(accessibility) + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +// Cacheable control metadata +class QWinRTUiaControlMetadata +{ +public: + QWinRTUiaControlMetadata(); + QWinRTUiaControlMetadata(QAccessible::Id id); + void update(QAccessible::Id id); + QString automationId() const { return m_automationId; } + QString className() const { return m_className; } + QString controlName() const { return m_controlName; } + QString accelerator() const { return m_accelerator; } + QString access() const { return m_access; } + QString help() const { return m_help; } + QString description() const { return m_description; } + QString value() const { return m_value; } + QString text() const { return m_text; } + QAccessible::Role role() const { return m_role; } + QAccessible::State state() const { return m_state; } + QRect boundingRect() const { return m_boundingRect; } + double minimumValue() const { return m_minimumValue; } + double maximumValue() const { return m_maximumValue; } + double currentValue() const { return m_currentValue; } + double minimumStepSize() const { return m_minimumStepSize; } + int rowIndex() const { return m_rowIndex; } + int columnIndex() const { return m_columnIndex; } + int rowCount() const { return m_rowCount; } + int columnCount() const { return m_columnCount; } + int characterCount() const { return m_text.length(); } + int cursorPosition() const { return m_cursorPosition; } + +private: + QString generateControlName(QAccessibleInterface *accessible); + QString generateClassName(QAccessibleInterface *accessible); + QString generateAutomationId(QAccessibleInterface *accessible); + QAccessible::Role generateRole(QAccessibleInterface *accessible); + void updateValueData(QAccessibleInterface *accessible); + void updateTableData(QAccessibleInterface *accessible); + void updateTextData(QAccessibleInterface *accessible); + QString m_automationId; + QString m_className; + QString m_controlName; + QString m_accelerator; + QString m_access; + QString m_help; + QString m_description; + QString m_value; + QString m_text; + QAccessible::Role m_role = QAccessible::NoRole; + QAccessible::State m_state; + QRect m_boundingRect; + double m_minimumValue = 0.0; + double m_maximumValue = 0.0; + double m_currentValue = 0.0; + double m_minimumStepSize = 0.0; + int m_rowIndex = 0; + int m_columnIndex = 0; + int m_rowCount = 0; + int m_columnCount = 0; + int m_cursorPosition = 0; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIACONTROLMETADATA_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaemptypropertyvalue.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaemptypropertyvalue.h new file mode 100644 index 0000000000..35e4df75fc --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaemptypropertyvalue.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIAEMPTYPROPERTYVALUE_H +#define QWINRTUIAEMPTYPROPERTYVALUE_H + +#include +#if QT_CONFIG(accessibility) + +#include +#include + +QT_BEGIN_NAMESPACE + +// Implements an empty property value. +class QWinRTUiaEmptyPropertyValue : + public Microsoft::WRL::RuntimeClass +{ + InspectableClass(L"QWinRTUiaEmptyPropertyValue", BaseTrust); +public: + + HRESULT STDMETHODCALLTYPE get_Type(ABI::Windows::Foundation::PropertyType *value) + { + *value = ABI::Windows::Foundation::PropertyType_Empty; + return S_OK; + } + + HRESULT STDMETHODCALLTYPE get_IsNumericScalar(boolean*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetUInt8(BYTE*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetInt16(INT16*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetUInt16(UINT16*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetInt32(INT32*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetUInt32(UINT32*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetInt64(INT64*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetUInt64(UINT64*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetSingle(FLOAT*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetDouble(DOUBLE*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetChar16(WCHAR*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetBoolean(boolean*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetString(HSTRING*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetGuid(GUID*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetDateTime(ABI::Windows::Foundation::DateTime*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetTimeSpan(ABI::Windows::Foundation::TimeSpan*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetPoint(ABI::Windows::Foundation::Point*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetSize(ABI::Windows::Foundation::Size*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetRect(ABI::Windows::Foundation::Rect*) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetUInt8Array(UINT32*, BYTE**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetInt16Array(UINT32*, INT16**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetUInt16Array(UINT32*, UINT16**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetInt32Array(UINT32*, INT32**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetUInt32Array(UINT32*, UINT32**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetInt64Array(UINT32*, INT64**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetUInt64Array(UINT32*, UINT64**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetSingleArray(UINT32*, FLOAT**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetDoubleArray(UINT32*, DOUBLE**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetChar16Array(UINT32*, WCHAR**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetBooleanArray(UINT32*, boolean**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetStringArray(UINT32*, HSTRING**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetInspectableArray(UINT32*, IInspectable***) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetGuidArray(UINT32*, GUID**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetDateTimeArray(UINT32*, ABI::Windows::Foundation::DateTime**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetTimeSpanArray(UINT32*, ABI::Windows::Foundation::TimeSpan**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetPointArray(UINT32*, ABI::Windows::Foundation::Point**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetSizeArray(UINT32*, ABI::Windows::Foundation::Size**) { return E_FAIL; } + HRESULT STDMETHODCALLTYPE GetRectArray(UINT32*, ABI::Windows::Foundation::Rect**) { return E_FAIL; } +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIAEMPTYPROPERTYVALUE_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.cpp new file mode 100644 index 0000000000..524000b618 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiagriditemprovider.h" +#include "qwinrtuiamainprovider.h" +#include "qwinrtuiametadatacache.h" +#include "qwinrtuiautils.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWinRTUiAutomation; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::UI::Xaml::Automation::Provider; +using namespace ABI::Windows::UI::Xaml::Automation::Peers; + +QWinRTUiaGridItemProvider::QWinRTUiaGridItemProvider(QAccessible::Id id) : + QWinRTUiaBaseProvider(id) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +QWinRTUiaGridItemProvider::~QWinRTUiaGridItemProvider() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +// Returns the column index of the item. +HRESULT STDMETHODCALLTYPE QWinRTUiaGridItemProvider::get_Column(INT32 *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *value = metadata->columnIndex(); + return S_OK; +} + +// Returns the number of columns occupied by the item. +HRESULT STDMETHODCALLTYPE QWinRTUiaGridItemProvider::get_ColumnSpan(INT32 *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *value = metadata->columnCount(); + return S_OK; +} + +// Returns the provider for the containing table/tree. +HRESULT STDMETHODCALLTYPE QWinRTUiaGridItemProvider::get_ContainingGrid(IIRawElementProviderSimple **value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + *value = nullptr; + + auto accid = id(); + auto elementId = QSharedPointer(new QAccessible::Id(0)); + auto ptrElementId = new QSharedPointer(elementId); + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementId]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + if (QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface()) { + if (QAccessibleInterface *table = tableCellInterface->table()) { + **ptrElementId = idForAccessible(table); + QWinRTUiaMetadataCache::instance()->load(**ptrElementId); + } + } + } + delete ptrElementId; + return S_OK; + }))) { + return E_FAIL; + } + + if (!*elementId) + return S_OK; + + return QWinRTUiaMainProvider::rawProviderForAccessibleId(*elementId, value); +} + +// Returns the row index of the item. +HRESULT STDMETHODCALLTYPE QWinRTUiaGridItemProvider::get_Row(INT32 *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *value = metadata->rowIndex(); + return S_OK; +} + +// Returns the number of rows occupied by the item. +HRESULT STDMETHODCALLTYPE QWinRTUiaGridItemProvider::get_RowSpan(INT32 *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *value = metadata->rowCount(); + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.h new file mode 100644 index 0000000000..70504fc555 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIAGRIDITEMPROVIDER_H +#define QWINRTUIAGRIDITEMPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +// Implements the Grid Item control pattern provider. Used by items within a table/tree. +class QWinRTUiaGridItemProvider : + public QWinRTUiaBaseProvider, + public Microsoft::WRL::RuntimeClass +{ + Q_OBJECT + Q_DISABLE_COPY(QWinRTUiaGridItemProvider) + InspectableClass(L"QWinRTUiaGridItemProvider", BaseTrust); + +public: + explicit QWinRTUiaGridItemProvider(QAccessible::Id id); + virtual ~QWinRTUiaGridItemProvider(); + + // IGridItemProvider + HRESULT STDMETHODCALLTYPE get_Column(INT32 *value) override; + HRESULT STDMETHODCALLTYPE get_ColumnSpan(INT32 *value) override; + HRESULT STDMETHODCALLTYPE get_ContainingGrid(ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple **value) override; + HRESULT STDMETHODCALLTYPE get_Row(INT32 *value) override; + HRESULT STDMETHODCALLTYPE get_RowSpan(INT32 *value) override; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIAGRIDITEMPROVIDER_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.cpp new file mode 100644 index 0000000000..e469991de2 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiagridprovider.h" +#include "qwinrtuiamainprovider.h" +#include "qwinrtuiametadatacache.h" +#include "qwinrtuiautils.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWinRTUiAutomation; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::UI::Xaml::Automation::Provider; +using namespace ABI::Windows::UI::Xaml::Automation::Peers; + +QWinRTUiaGridProvider::QWinRTUiaGridProvider(QAccessible::Id id) : + QWinRTUiaBaseProvider(id) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +QWinRTUiaGridProvider::~QWinRTUiaGridProvider() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +// Returns the number of columns. +HRESULT STDMETHODCALLTYPE QWinRTUiaGridProvider::get_ColumnCount(INT32 *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *value = metadata->columnCount(); + return S_OK; +} + +// Returns the number of rows. +HRESULT STDMETHODCALLTYPE QWinRTUiaGridProvider::get_RowCount(INT32 *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *value = metadata->rowCount(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaGridProvider::GetItem(INT32 row, INT32 column, IIRawElementProviderSimple **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + *returnValue = nullptr; + + auto accid = id(); + auto elementId = QSharedPointer(new QAccessible::Id(0)); + auto ptrElementId = new QSharedPointer(elementId); + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, row, column, ptrElementId]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + if (QAccessibleTableInterface *tableInterface = accessible->tableInterface()) { + if ((row >= 0) && (row < tableInterface->rowCount()) && (column >= 0) && (column < tableInterface->columnCount())) { + if (QAccessibleInterface *cell = tableInterface->cellAt(row, column)) { + **ptrElementId = idForAccessible(cell); + QWinRTUiaMetadataCache::instance()->load(**ptrElementId); + } + } + } + } + delete ptrElementId; + return S_OK; + }))) { + return E_FAIL; + } + + if (!*elementId) + return E_FAIL; + + return QWinRTUiaMainProvider::rawProviderForAccessibleId(*elementId, returnValue); +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.h new file mode 100644 index 0000000000..d6dfaed315 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIAGRIDPROVIDER_H +#define QWINRTUIAGRIDPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +// Implements the Grid control pattern provider. Used by tables/trees. +class QWinRTUiaGridProvider : + public QWinRTUiaBaseProvider, + public Microsoft::WRL::RuntimeClass +{ + Q_OBJECT + Q_DISABLE_COPY(QWinRTUiaGridProvider) + InspectableClass(L"QWinRTUiaGridProvider", BaseTrust); + +public: + explicit QWinRTUiaGridProvider(QAccessible::Id id); + virtual ~QWinRTUiaGridProvider(); + + // IGridProvider + HRESULT STDMETHODCALLTYPE get_ColumnCount(INT32 *value) override; + HRESULT STDMETHODCALLTYPE get_RowCount(INT32 *value) override; + HRESULT STDMETHODCALLTYPE GetItem(INT32 row, INT32 column, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple **returnValue) override; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIAGRIDPROVIDER_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.cpp new file mode 100644 index 0000000000..e2cf7bc107 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiainvokeprovider.h" +#include "qwinrtuiametadatacache.h" +#include "qwinrtuiautils.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWinRTUiAutomation; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::UI::Xaml::Automation::Provider; + +QWinRTUiaInvokeProvider::QWinRTUiaInvokeProvider(QAccessible::Id id) : + QWinRTUiaBaseProvider(id) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +QWinRTUiaInvokeProvider::~QWinRTUiaInvokeProvider() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaInvokeProvider::Invoke() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + auto accid = id(); + + QEventDispatcherWinRT::runOnMainThread([accid]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) + if (QAccessibleActionInterface *actionInterface = accessible->actionInterface()) + actionInterface->doAction(QAccessibleActionInterface::pressAction()); + QWinRTUiaMetadataCache::instance()->load(accid); + return S_OK; + }, 0); + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.h new file mode 100644 index 0000000000..dfe7917a16 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIAINVOKEPROVIDER_H +#define QWINRTUIAINVOKEPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +// Implements the Invoke control pattern provider. +class QWinRTUiaInvokeProvider : + public QWinRTUiaBaseProvider, + public Microsoft::WRL::RuntimeClass +{ + Q_OBJECT + Q_DISABLE_COPY(QWinRTUiaInvokeProvider) + InspectableClass(L"QWinRTUiaInvokeProvider", BaseTrust); + +public: + explicit QWinRTUiaInvokeProvider(QAccessible::Id id); + virtual ~QWinRTUiaInvokeProvider(); + + // IInvokeProvider + HRESULT STDMETHODCALLTYPE Invoke() override; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIAINVOKEPROVIDER_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.cpp new file mode 100644 index 0000000000..99efe27c34 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.cpp @@ -0,0 +1,779 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiamainprovider.h" +#include "qwinrtuiaprovidercache.h" +#include "qwinrtuiavalueprovider.h" +#include "qwinrtuiarangevalueprovider.h" +#include "qwinrtuiatextprovider.h" +#include "qwinrtuiatoggleprovider.h" +#include "qwinrtuiainvokeprovider.h" +#include "qwinrtuiaselectionprovider.h" +#include "qwinrtuiaselectionitemprovider.h" +#include "qwinrtuiatableprovider.h" +#include "qwinrtuiatableitemprovider.h" +#include "qwinrtuiagridprovider.h" +#include "qwinrtuiagriditemprovider.h" +#include "qwinrtuiapeervector.h" +#include "qwinrtuiametadatacache.h" +#include "qwinrtuiaemptypropertyvalue.h" +#include "qwinrtuiautils.h" + +#include +#include +#include +#include +#include + +using namespace QWinRTUiAutomation; +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::System; +using namespace ABI::Windows::UI; +using namespace ABI::Windows::UI::Core; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::UI::Xaml::Automation::Provider; +using namespace ABI::Windows::UI::Xaml::Automation::Peers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; + +QT_BEGIN_NAMESPACE + +QWinRTUiaMainProvider::QWinRTUiaMainProvider(QAccessible::Id id) + : QWinRTUiaBaseProvider(id) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + ComPtr factory; + HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Automation_Peers_AutomationPeer).Get(), IID_PPV_ARGS(&factory)); + Q_ASSERT_SUCCEEDED(hr); + + hr = factory->CreateInstance(this, &m_base, &m_core); + Q_ASSERT_SUCCEEDED(hr); +} + +QWinRTUiaMainProvider::~QWinRTUiaMainProvider() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::QueryInterface(REFIID iid, LPVOID *iface) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!iface) + return E_POINTER; + *iface = nullptr; + + if (iid == IID_IUnknown) { + *iface = static_cast(this); + AddRef(); + return S_OK; + } else if (iid == IID_IAutomationPeerOverrides) { + *iface = static_cast(this); + AddRef(); + return S_OK; + } else { + return m_base.CopyTo(iid, iface); + } +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetIids(ULONG *iidCount, IID **iids) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + *iidCount = 0; + *iids = nullptr; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetRuntimeClassName(HSTRING *className) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + return qHString(QStringLiteral("QWinRTUiaMainProvider"), className); +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetTrustLevel(TrustLevel *trustLevel) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + *trustLevel = TrustLevel::BaseTrust; + return S_OK; +} + +// Returns a cached instance of the provider for a specific accessible interface. +QWinRTUiaMainProvider *QWinRTUiaMainProvider::providerForAccessibleId(QAccessible::Id id) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + QWinRTUiaProviderCache *providerCache = QWinRTUiaProviderCache::instance(); + QWinRTUiaMainProvider *provider = qobject_cast(providerCache->providerForId(id)); + + if (provider) { + provider->AddRef(); + } else { + ComPtr p = Make(id); + provider = p.Get(); + provider->AddRef(); + providerCache->insert(id, provider); + } + return provider; +} + +// Returns an IIRawElementProviderSimple for a specific accessible interface. +HRESULT QWinRTUiaMainProvider::rawProviderForAccessibleId(QAccessible::Id elementId, + IIRawElementProviderSimple **returnValue) +{ + if (!returnValue) + return E_INVALIDARG; + *returnValue = nullptr; + + if (ComPtr provider = providerForAccessibleId(elementId)) { + ComPtr automationPeer; + if (SUCCEEDED(provider.As(&automationPeer))) { + ComPtr automationPeerProtected; + if (SUCCEEDED(provider.As(&automationPeerProtected))) { + return automationPeerProtected->ProviderFromPeer(automationPeer.Get(), returnValue); + } + } + } + return E_FAIL; +} + +// Returns an array of IIRawElementProviderSimple instances for a list of accessible interface ids. +HRESULT QWinRTUiaMainProvider::rawProviderArrayForAccessibleIdList(const QList &elementIds, + UINT32 *returnValueSize, + IIRawElementProviderSimple ***returnValue) +{ + if (!returnValueSize || !returnValue) + return E_INVALIDARG; + *returnValueSize = 0; + *returnValue = nullptr; + + QList rawProviderList; + + for (auto elementId : qAsConst(elementIds)) { + IIRawElementProviderSimple *rawProvider; + if (SUCCEEDED(rawProviderForAccessibleId(elementId, &rawProvider))) + rawProviderList.append(rawProvider); + } + + if (rawProviderList.size() == 0) + return S_OK; + + *returnValue = static_cast(CoTaskMemAlloc(rawProviderList.size() * sizeof(IIRawElementProviderSimple *))); + if (!*returnValue) { + for (auto rawProvider : qAsConst(rawProviderList)) + rawProvider->Release(); + return E_OUTOFMEMORY; + } + + int index = 0; + for (auto rawProvider : qAsConst(rawProviderList)) + (*returnValue)[index++] = rawProvider; + *returnValueSize = rawProviderList.size(); + return S_OK; +} + +void QWinRTUiaMainProvider::notifyFocusChange(QAccessibleEvent *event) +{ + if (QAccessibleInterface *accessible = event->accessibleInterface()) { + QAccessible::Id accid = idForAccessible(accessible); + QWinRTUiaMetadataCache::instance()->load(accid); + QEventDispatcherWinRT::runOnXamlThread([accid]() { + if (ComPtr provider = providerForAccessibleId(accid)) { + ComPtr automationPeer; + if (SUCCEEDED(provider->QueryInterface(IID_PPV_ARGS(&automationPeer)))) { + automationPeer->RaiseAutomationEvent(AutomationEvents_AutomationFocusChanged); + } + } + return S_OK; + }, false); + } +} + +void QWinRTUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *event) +{ + if (QAccessibleInterface *accessible = event->accessibleInterface()) { + QAccessible::Id accid = idForAccessible(accessible); + QWinRTUiaMetadataCache::instance()->load(accid); + + if (event->changedStates().checked || event->changedStates().checkStateMixed) { + // Notifies states changes in checkboxes. + if (accessible->role() == QAccessible::CheckBox) { + QEventDispatcherWinRT::runOnXamlThread([accid]() { + if (ComPtr provider = providerForAccessibleId(accid)) { + ComPtr automationPeer; + if (SUCCEEDED(provider->QueryInterface(IID_PPV_ARGS(&automationPeer)))) { + ComPtr toggleStatics; + if (SUCCEEDED(RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Automation_TogglePatternIdentifiers).Get(), IID_PPV_ARGS(&toggleStatics)))) { + ComPtr toggleStateProperty; + if (SUCCEEDED(toggleStatics->get_ToggleStateProperty(&toggleStateProperty))) { + ComPtr emptyValue = Make(); + // by sending an event with an empty value we force ui automation to refresh its state + automationPeer->RaisePropertyChangedEvent(toggleStateProperty.Get(), emptyValue.Get(), emptyValue.Get()); + } + } + } + } + return S_OK; + }, false); + } + } + if (event->changedStates().active) { + if (accessible->role() == QAccessible::Window) { + // Notifies window opened/closed. + bool active = accessible->state().active; + QEventDispatcherWinRT::runOnXamlThread([accid, active]() { + if (ComPtr provider = providerForAccessibleId(accid)) { + ComPtr automationPeer; + if (SUCCEEDED(provider->QueryInterface(IID_PPV_ARGS(&automationPeer)))) { + if (active) { + automationPeer->RaiseAutomationEvent(AutomationEvents_WindowOpened); + } else { + automationPeer->RaiseAutomationEvent(AutomationEvents_WindowClosed); + } + } + } + return S_OK; + }, false); + } + } + } +} + +void QWinRTUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *event) +{ + if (QAccessibleInterface *accessible = event->accessibleInterface()) { + QAccessible::Id accid = idForAccessible(accessible); + QWinRTUiaMetadataCache::instance()->load(accid); + if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) { + // Notifies changes in values of controls supporting the value interface. + double value = valueInterface->currentValue().toDouble(); + QEventDispatcherWinRT::runOnXamlThread([accid, value]() { + // For some reason RaisePropertyChangedEvent() does not seem to be + // forwarding notifications for any property types except empty, + // which would do nothing here. ToDo: find a workaround. + return S_OK; + }, false); + } + } +} + +// Notifies changes in text content and selection state of text controls. +void QWinRTUiaMainProvider::notifyTextChange(QAccessibleEvent *event) +{ + if (QAccessibleInterface *accessible = event->accessibleInterface()) { + QAccessible::Id accid = idForAccessible(accessible); + QWinRTUiaMetadataCache::instance()->load(accid); + bool readOnly = accessible->state().readOnly; + QAccessible::Event eventType = event->type(); + if (accessible->textInterface()) { + QEventDispatcherWinRT::runOnXamlThread([accid, eventType, readOnly]() { + if (ComPtr provider = providerForAccessibleId(accid)) { + ComPtr automationPeer; + if (SUCCEEDED(provider->QueryInterface(IID_PPV_ARGS(&automationPeer)))) { + if (eventType == QAccessible::TextSelectionChanged) { + automationPeer->RaiseAutomationEvent(AutomationEvents_TextPatternOnTextSelectionChanged); + } else if (eventType == QAccessible::TextCaretMoved) { + if (!readOnly) { + automationPeer->RaiseAutomationEvent(AutomationEvents_TextPatternOnTextSelectionChanged); + } + } else { + automationPeer->RaiseAutomationEvent(AutomationEvents_TextPatternOnTextChanged); + } + } + } + return S_OK; + }, false); + } + } +} + +// Return providers for specific control patterns +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetPatternCore(PatternInterface patternInterface, IInspectable **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << patternInterface; + + if (!returnValue) + return E_INVALIDARG; + *returnValue = nullptr; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return E_FAIL; + + switch (patternInterface) { + case PatternInterface_Text: + case PatternInterface_Text2: { + // All text controls. + if (accessible->textInterface()) { + ComPtr provider = Make(id()); + return provider.CopyTo(returnValue); + } + break; + } + case PatternInterface_Value: { + // All accessible controls return text(QAccessible::Value) (which may be empty). + ComPtr provider = Make(id()); + return provider.CopyTo(returnValue); + } + case PatternInterface_RangeValue: { + // Controls providing a numeric value within a range (e.g., sliders, scroll bars, dials). + if (accessible->valueInterface()) { + ComPtr provider = Make(id()); + return provider.CopyTo(returnValue); + } + break; + } + case PatternInterface_Toggle: { + // Checkbox controls. + if (accessible->role() == QAccessible::CheckBox) { + ComPtr provider = Make(id()); + return provider.CopyTo(returnValue); + } + break; + } + case PatternInterface_Selection: { + // Lists of items. + if (accessible->role() == QAccessible::List) { + ComPtr provider = Make(id()); + return provider.CopyTo(returnValue); + } + break; + } + case PatternInterface_SelectionItem: { + // Items within a list and radio buttons. + if ((accessible->role() == QAccessible::RadioButton) + || (accessible->role() == QAccessible::ListItem)) { + ComPtr provider = Make(id()); + return provider.CopyTo(returnValue); + } + break; + } + case PatternInterface_Table: { + // Table/tree. + if (accessible->tableInterface() + && ((accessible->role() == QAccessible::Table) || (accessible->role() == QAccessible::Tree))) { + ComPtr provider = Make(id()); + return provider.CopyTo(returnValue); + } + break; + } + case PatternInterface_TableItem: { + // Item within a table/tree. + if (accessible->tableCellInterface() + && ((accessible->role() == QAccessible::Cell) || (accessible->role() == QAccessible::TreeItem))) { + ComPtr provider = Make(id()); + return provider.CopyTo(returnValue); + } + break; + } + case PatternInterface_Grid: { + // Table/tree. + if (accessible->tableInterface() + && ((accessible->role() == QAccessible::Table) || (accessible->role() == QAccessible::Tree))) { + ComPtr provider = Make(id()); + return provider.CopyTo(returnValue); + } + break; + } + case PatternInterface_GridItem: { + // Item within a table/tree. + if (accessible->tableCellInterface() + && ((accessible->role() == QAccessible::Cell) || (accessible->role() == QAccessible::TreeItem))) { + ComPtr provider = Make(id()); + return provider.CopyTo(returnValue); + } + break; + } + case PatternInterface_Invoke: { + // Things that have an invokable action (e.g., simple buttons). + if (accessible->actionInterface()) { + ComPtr provider = Make(id()); + return provider.CopyTo(returnValue); + } + break; + } + default: + break; + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetAcceleratorKeyCore(HSTRING *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + return qHString(metadata->accelerator(), returnValue); +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetAccessKeyCore(HSTRING *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + return qHString(metadata->access(), returnValue); +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetAutomationControlTypeCore(AutomationControlType *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *returnValue = roleToControlType(metadata->role()); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetAutomationIdCore(HSTRING *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + return qHString(metadata->automationId(), returnValue); +} + +// Returns the bounding rectangle for the accessible control. +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetBoundingRectangleCore(ABI::Windows::Foundation::Rect *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + + QRect rect = metadata->boundingRect(); + returnValue->X = rect.x(); + returnValue->Y = rect.y(); + returnValue->Width = rect.width(); + returnValue->Height = rect.height(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetChildrenCore(IVector **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + *returnValue = nullptr; + + auto accid = id(); + auto children = QSharedPointer>(new QList); + auto ptrChildren = new QSharedPointer>(children); + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrChildren]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + int childCount = accessible->childCount(); + for (int i = 0; i < childCount; ++i) { + if (QAccessibleInterface *childAcc = accessible->child(i)) { + QAccessible::Id childId = idForAccessible(childAcc); + QWinRTUiaMetadataCache::instance()->load(childId); + (*ptrChildren)->append(childId); + } + } + } + delete ptrChildren; + return S_OK; + }))) { + return E_FAIL; + } + + ComPtr> peerVector = Make(); + + for (auto childId : qAsConst(*children)) { + if (ComPtr provider = providerForAccessibleId(childId)) { + IAutomationPeer *peer; + if (SUCCEEDED(provider.CopyTo(&peer))) + peerVector->Append(peer); + } + } + return peerVector.CopyTo(returnValue); +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetClassNameCore(HSTRING *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + return qHString(metadata->className(), returnValue); +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetClickablePointCore(ABI::Windows::Foundation::Point *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetHelpTextCore(HSTRING *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + return qHString(metadata->help(), returnValue); +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetItemStatusCore(HSTRING *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetItemTypeCore(HSTRING *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetLabeledByCore(IAutomationPeer **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetLocalizedControlTypeCore(HSTRING *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetNameCore(HSTRING *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + return qHString(metadata->controlName(), returnValue); +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetOrientationCore(AutomationOrientation *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + *returnValue = AutomationOrientation_None; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::HasKeyboardFocusCore(boolean *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *returnValue = (metadata->state().focused != 0); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::IsContentElementCore(boolean *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + *returnValue = true; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::IsControlElementCore(boolean *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + *returnValue = true; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::IsEnabledCore(boolean *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *returnValue = (metadata->state().disabled == 0); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::IsKeyboardFocusableCore(boolean *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *returnValue = (metadata->state().focusable != 0); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::IsOffscreenCore(boolean *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + *returnValue = false; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::IsPasswordCore(boolean *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *returnValue = (metadata->role() == QAccessible::EditableText) && (metadata->state().passwordEdit != 0); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::IsRequiredForFormCore(boolean *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + *returnValue = false; + return S_OK; +} + +// Sets focus to the control. +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::SetFocusCore() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return E_FAIL; + + QAccessibleActionInterface *actionInterface = accessible->actionInterface(); + if (!actionInterface) + return E_FAIL; + + QEventDispatcherWinRT::runOnMainThread([actionInterface]() { + actionInterface->doAction(QAccessibleActionInterface::setFocusAction()); + return S_OK; + }); + return S_OK; +} + +// Returns a provider for the UI element present at the specified screen coordinates. +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetPeerFromPointCore(ABI::Windows::Foundation::Point point, IAutomationPeer **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + *returnValue = nullptr; + + // Scale coordinates from High DPI screens? + + auto accid = id(); + auto elementId = QSharedPointer(new QAccessible::Id(0)); + auto ptrElementId = new QSharedPointer(elementId); + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementId, point]() { + // Controls can be embedded within grouping elements. By default returns the innermost control. + QAccessibleInterface *target = accessibleForId(accid); + while (QAccessibleInterface *tmpacc = target->childAt(point.X, point.Y)) { + target = tmpacc; + // For accessibility tools it may be better to return the text element instead of its subcomponents. + if (target->textInterface()) break; + } + **ptrElementId = idForAccessible(target); + QWinRTUiaMetadataCache::instance()->load(**ptrElementId); + delete ptrElementId; + return S_OK; + }))) { + return E_FAIL; + } + + if (ComPtr provider = providerForAccessibleId(*elementId)) + return provider.CopyTo(returnValue); + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetLiveSettingCore(AutomationLiveSetting *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + return E_NOTIMPL; +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.h new file mode 100644 index 0000000000..3ae9d2759e --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIAMAINPROVIDER_H +#define QWINRTUIAMAINPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +// The main WinRT UI Automation class. +class QWinRTUiaMainProvider: + public QWinRTUiaBaseProvider, + public Microsoft::WRL::RuntimeClass +{ + Q_OBJECT + Q_DISABLE_COPY(QWinRTUiaMainProvider) + +public: + explicit QWinRTUiaMainProvider(QAccessible::Id id); + virtual ~QWinRTUiaMainProvider(); + static QWinRTUiaMainProvider *providerForAccessibleId(QAccessible::Id id); + static HRESULT rawProviderForAccessibleId(QAccessible::Id elementId, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple **returnValue); + static HRESULT rawProviderArrayForAccessibleIdList(const QList &elementIds, UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple ***returnValue); + 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) override; + + // IInspectable + HRESULT STDMETHODCALLTYPE GetIids(ULONG *iidCount, IID **iids) override; + HRESULT STDMETHODCALLTYPE GetRuntimeClassName(HSTRING *className) override; + HRESULT STDMETHODCALLTYPE GetTrustLevel(TrustLevel *trustLevel) override; + + // IAutomationPeerOverrides + HRESULT STDMETHODCALLTYPE GetPatternCore(ABI::Windows::UI::Xaml::Automation::Peers::PatternInterface patternInterface, IInspectable **returnValue) override; + HRESULT STDMETHODCALLTYPE GetAcceleratorKeyCore(HSTRING *returnValue) override; + HRESULT STDMETHODCALLTYPE GetAccessKeyCore(HSTRING *returnValue) override; + HRESULT STDMETHODCALLTYPE GetAutomationControlTypeCore(ABI::Windows::UI::Xaml::Automation::Peers::AutomationControlType *returnValue) override; + HRESULT STDMETHODCALLTYPE GetAutomationIdCore(HSTRING *returnValue) override; + HRESULT STDMETHODCALLTYPE GetBoundingRectangleCore(ABI::Windows::Foundation::Rect *returnValue) override; + HRESULT STDMETHODCALLTYPE GetChildrenCore(ABI::Windows::Foundation::Collections::IVector **returnValue) override; + HRESULT STDMETHODCALLTYPE GetClassNameCore(HSTRING *returnValue) override; + HRESULT STDMETHODCALLTYPE GetClickablePointCore(ABI::Windows::Foundation::Point *returnValue) override; + HRESULT STDMETHODCALLTYPE GetHelpTextCore(HSTRING *returnValue) override; + HRESULT STDMETHODCALLTYPE GetItemStatusCore(HSTRING *returnValue) override; + HRESULT STDMETHODCALLTYPE GetItemTypeCore(HSTRING *returnValue) override; + HRESULT STDMETHODCALLTYPE GetLabeledByCore(ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer **returnValue) override; + HRESULT STDMETHODCALLTYPE GetLocalizedControlTypeCore(HSTRING *returnValue) override; + HRESULT STDMETHODCALLTYPE GetNameCore(HSTRING *returnValue) override; + HRESULT STDMETHODCALLTYPE GetOrientationCore(ABI::Windows::UI::Xaml::Automation::Peers::AutomationOrientation *returnValue) override; + HRESULT STDMETHODCALLTYPE HasKeyboardFocusCore(boolean *returnValue) override; + HRESULT STDMETHODCALLTYPE IsContentElementCore(boolean *returnValue) override; + HRESULT STDMETHODCALLTYPE IsControlElementCore(boolean *returnValue) override; + HRESULT STDMETHODCALLTYPE IsEnabledCore(boolean *returnValue) override; + HRESULT STDMETHODCALLTYPE IsKeyboardFocusableCore(boolean *returnValue) override; + HRESULT STDMETHODCALLTYPE IsOffscreenCore(boolean *returnValue) override; + HRESULT STDMETHODCALLTYPE IsPasswordCore(boolean *returnValue) override; + HRESULT STDMETHODCALLTYPE IsRequiredForFormCore(boolean *returnValue) override; + HRESULT STDMETHODCALLTYPE SetFocusCore() override; + HRESULT STDMETHODCALLTYPE GetPeerFromPointCore(ABI::Windows::Foundation::Point point, ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer **returnValue) override; + HRESULT STDMETHODCALLTYPE GetLiveSettingCore(ABI::Windows::UI::Xaml::Automation::Peers::AutomationLiveSetting *returnValue) override; + +private: + Microsoft::WRL::ComPtr m_base; + Microsoft::WRL::ComPtr m_core; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIAMAINPROVIDER_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.cpp new file mode 100644 index 0000000000..442ff184a8 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiametadatacache.h" +#include "qwinrtuiautils.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWinRTUiAutomation; + +// Private constructor +QWinRTUiaMetadataCache::QWinRTUiaMetadataCache() +{ +} + +// shared instance +QWinRTUiaMetadataCache *QWinRTUiaMetadataCache::instance() +{ + static QWinRTUiaMetadataCache metadataCache; + return &metadataCache; +} + +// Returns the cached metadata associated with the ID, or an instance with default values. +QSharedPointer QWinRTUiaMetadataCache::metadataForId(QAccessible::Id id) +{ + QSharedPointer metadata; + + m_mutex.lock(); + if (m_metadataTable.contains(id)) + metadata = m_metadataTable[id]; + else + metadata = QSharedPointer(new QWinRTUiaControlMetadata); + m_mutex.unlock(); + return metadata; +} + +// Caches metadata from the accessibility framework within the main thread. +bool QWinRTUiaMetadataCache::load(QAccessible::Id id) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([id]() { + QWinRTUiaMetadataCache::instance()->insert(id, QSharedPointer(new QWinRTUiaControlMetadata(id))); + return S_OK; + }))) { + return false; + } + return true; +} + +// Inserts metadata in the cache and associates it with an accessibility ID. +void QWinRTUiaMetadataCache::insert(QAccessible::Id id, const QSharedPointer &metadata) +{ + m_mutex.lock(); + m_metadataTable[id] = metadata; + m_mutex.unlock(); +} + +// Removes metadata with a given id from the cache. +void QWinRTUiaMetadataCache::remove(QAccessible::Id id) +{ + m_mutex.lock(); + m_metadataTable.remove(id); + m_mutex.unlock(); +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.h new file mode 100644 index 0000000000..2d68d1b654 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIAMETADATACACHE_H +#define QWINRTUIAMETADATACACHE_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiacontrolmetadata.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +// Singleton used to cache metadata using the accessibility ID as the key. +class QWinRTUiaMetadataCache : public QObject +{ + QWinRTUiaMetadataCache(); + Q_OBJECT +public: + static QWinRTUiaMetadataCache *instance(); + QSharedPointer metadataForId(QAccessible::Id id); + void insert(QAccessible::Id id, const QSharedPointer &metadata); + void remove(QAccessible::Id id); + bool load(QAccessible::Id id); + +private: + QHash> m_metadataTable; + QMutex m_mutex; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIAMETADATACACHE_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.cpp new file mode 100644 index 0000000000..e3d6bcae4b --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.cpp @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiapeervector.h" +#include "qwinrtuiautils.h" + +using namespace ABI::Windows::UI::Xaml::Automation::Peers; +using namespace ABI::Windows::Foundation::Collections; + +QT_BEGIN_NAMESPACE + +HRESULT QWinRTUiaPeerVector::GetAt(quint32 index, IAutomationPeer **item) +{ + if (index >= quint32(m_impl.size())) + return E_FAIL; + if ((*item = m_impl.at(index))) + (*item)->AddRef(); + return S_OK; +} + +HRESULT QWinRTUiaPeerVector::get_Size(quint32 *size) +{ + *size = m_impl.size(); + return S_OK; +} + +HRESULT QWinRTUiaPeerVector::GetView(IVectorView **view) +{ + *view = nullptr; + return E_NOTIMPL; +} + +HRESULT QWinRTUiaPeerVector::IndexOf(IAutomationPeer *value, quint32 *index, boolean *found) +{ + int idx = m_impl.indexOf(value); + if (idx > -1) { + *index = quint32(idx); + *found = true; + } else { + *found = false; + } + return S_OK; +} + +HRESULT QWinRTUiaPeerVector::SetAt(quint32 index, IAutomationPeer *item) +{ + if (index >= quint32(m_impl.size())) + return E_FAIL; + if (IAutomationPeer *elem = m_impl.at(index)) { + if (elem == item) + return S_OK; + else + elem->Release(); + } + if (item) + item->AddRef(); + m_impl[index] = item; + return S_OK; +} + +HRESULT QWinRTUiaPeerVector::InsertAt(quint32 index, IAutomationPeer *item) +{ + if (index >= quint32(m_impl.size())) + return E_FAIL; + if (item) + item->AddRef(); + m_impl.insert(index, item); + return S_OK; +} + +HRESULT QWinRTUiaPeerVector::RemoveAt(quint32 index) +{ + if (index >= quint32(m_impl.size())) + return E_FAIL; + if (IAutomationPeer *elem = m_impl.at(index)) + elem->Release(); + m_impl.remove(index); + return S_OK; +} + +HRESULT QWinRTUiaPeerVector::Append(IAutomationPeer *item) +{ + if (item) + item->AddRef(); + m_impl.append(item); + return S_OK; +} + +HRESULT QWinRTUiaPeerVector::RemoveAtEnd() +{ + if (m_impl.size() == 0) + return E_FAIL; + if (IAutomationPeer *elem = m_impl.last()) + elem->Release(); + m_impl.removeLast(); + return S_OK; +} + +HRESULT QWinRTUiaPeerVector::Clear() +{ + for (auto elem : qAsConst(m_impl)) + if (elem) + elem->Release(); + m_impl.clear(); + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.h new file mode 100644 index 0000000000..265526de09 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIAPEERVECTOR_H +#define QWINRTUIAPEERVECTOR_H + +#include +#if QT_CONFIG(accessibility) + +#include +#include +#include +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +// Implements IVector +class QWinRTUiaPeerVector : public Microsoft::WRL::RuntimeClass> +{ +public: + HRESULT STDMETHODCALLTYPE GetAt(quint32 index, ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer **item) override; + HRESULT STDMETHODCALLTYPE get_Size(quint32 *size) override; + HRESULT STDMETHODCALLTYPE GetView(ABI::Windows::Foundation::Collections::IVectorView **view) override; + HRESULT STDMETHODCALLTYPE IndexOf(ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer *value, quint32 *index, boolean *found) override; + HRESULT STDMETHODCALLTYPE SetAt(quint32 index, ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer *item) override; + HRESULT STDMETHODCALLTYPE InsertAt(quint32 index, ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer *item) override; + HRESULT STDMETHODCALLTYPE RemoveAt(quint32 index) override; + HRESULT STDMETHODCALLTYPE Append(ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer *item) override; + HRESULT STDMETHODCALLTYPE RemoveAtEnd() override; + HRESULT STDMETHODCALLTYPE Clear() override; +private: + QVector m_impl; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIAPEERVECTOR_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.cpp new file mode 100644 index 0000000000..06ff094c45 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiaprovidercache.h" + +QT_BEGIN_NAMESPACE + +// Private constructor +QWinRTUiaProviderCache::QWinRTUiaProviderCache() +{ +} + +// shared instance +QWinRTUiaProviderCache *QWinRTUiaProviderCache::instance() +{ + static QWinRTUiaProviderCache providerCache; + return &providerCache; +} + +// Returns the provider instance associated with the ID, or nullptr. +QWinRTUiaBaseProvider *QWinRTUiaProviderCache::providerForId(QAccessible::Id id) const +{ + return m_providerTable.value(id); +} + +// Inserts a provider in the cache and associates it with an accessibility ID. +void QWinRTUiaProviderCache::insert(QAccessible::Id id, QWinRTUiaBaseProvider *provider) +{ + remove(id); + if (provider) { + m_providerTable[id] = provider; + m_inverseTable[provider] = id; + // Connects the destroyed signal to our slot, to remove deleted objects from the cache. + QObject::connect(provider, &QObject::destroyed, this, &QWinRTUiaProviderCache::objectDestroyed); + } +} + +// Removes deleted provider objects from the cache. +void QWinRTUiaProviderCache::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 = m_inverseTable.find(obj); + if (it != m_inverseTable.end()) { + m_providerTable.remove(*it); + m_inverseTable.remove(obj); + } +} + +// Removes a provider with a given id from the cache. +void QWinRTUiaProviderCache::remove(QAccessible::Id id) +{ + m_inverseTable.remove(m_providerTable.value(id)); + m_providerTable.remove(id); +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.h new file mode 100644 index 0000000000..393ef7d562 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIAPROVIDERCACHE_H +#define QWINRTUIAPROVIDERCACHE_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +// Singleton used to cache provider instances using the accessibility ID as the key. +class QWinRTUiaProviderCache : public QObject +{ + QWinRTUiaProviderCache(); + Q_OBJECT +public: + static QWinRTUiaProviderCache *instance(); + QWinRTUiaBaseProvider *providerForId(QAccessible::Id id) const; + void insert(QAccessible::Id id, QWinRTUiaBaseProvider *provider); + void remove(QAccessible::Id id); + +private Q_SLOTS: + void objectDestroyed(QObject *obj); + +private: + QHash m_providerTable; + QHash m_inverseTable; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIAPROVIDERCACHE_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.cpp new file mode 100644 index 0000000000..4ac59c890a --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.cpp @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiarangevalueprovider.h" +#include "qwinrtuiametadatacache.h" +#include "qwinrtuiautils.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWinRTUiAutomation; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::UI::Xaml::Automation::Provider; + +QWinRTUiaRangeValueProvider::QWinRTUiaRangeValueProvider(QAccessible::Id id) : + QWinRTUiaBaseProvider(id) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +QWinRTUiaRangeValueProvider::~QWinRTUiaRangeValueProvider() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaRangeValueProvider::get_IsReadOnly(boolean *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *value = (metadata->state().readOnly != 0); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaRangeValueProvider::get_LargeChange(DOUBLE *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *value = metadata->minimumStepSize(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaRangeValueProvider::get_Maximum(DOUBLE *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *value = metadata->maximumValue(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaRangeValueProvider::get_Minimum(DOUBLE *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *value = metadata->minimumValue(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaRangeValueProvider::get_SmallChange(DOUBLE *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *value = metadata->minimumStepSize(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaRangeValueProvider::get_Value(DOUBLE *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *value = metadata->currentValue(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaRangeValueProvider::SetValue(DOUBLE value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + auto accid = id(); + + QEventDispatcherWinRT::runOnMainThread([accid, value]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) { + double minimum = valueInterface->minimumValue().toDouble(); + double maximum = valueInterface->maximumValue().toDouble(); + if ((value >= minimum) && (value <= maximum)) { + valueInterface->setCurrentValue(QVariant(value)); + } + } + } + QWinRTUiaMetadataCache::instance()->load(accid); + return S_OK; + }, 0); + + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.h new file mode 100644 index 0000000000..4e98959526 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIARANGEVALUEPROVIDER_H +#define QWINRTUIARANGEVALUEPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +// Implements the Range Value control pattern provider. +class QWinRTUiaRangeValueProvider : + public QWinRTUiaBaseProvider, + public Microsoft::WRL::RuntimeClass +{ + Q_OBJECT + Q_DISABLE_COPY(QWinRTUiaRangeValueProvider) + InspectableClass(L"QWinRTUiaRangeValueProvider", BaseTrust); + +public: + explicit QWinRTUiaRangeValueProvider(QAccessible::Id id); + virtual ~QWinRTUiaRangeValueProvider(); + + // IRangeValueProvider + HRESULT STDMETHODCALLTYPE get_IsReadOnly(boolean *value) override; + HRESULT STDMETHODCALLTYPE get_LargeChange(DOUBLE *value) override; + HRESULT STDMETHODCALLTYPE get_Maximum(DOUBLE *value) override; + HRESULT STDMETHODCALLTYPE get_Minimum(DOUBLE *value) override; + HRESULT STDMETHODCALLTYPE get_SmallChange(DOUBLE *value) override; + HRESULT STDMETHODCALLTYPE get_Value(DOUBLE *value) override; + HRESULT STDMETHODCALLTYPE SetValue(DOUBLE value) override; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIARANGEVALUEPROVIDER_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.cpp new file mode 100644 index 0000000000..9bc88272ba --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiaselectionitemprovider.h" +#include "qwinrtuiamainprovider.h" +#include "qwinrtuiametadatacache.h" +#include "qwinrtuiautils.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWinRTUiAutomation; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::UI::Xaml::Automation::Provider; +using namespace ABI::Windows::UI::Xaml::Automation::Peers; + +QWinRTUiaSelectionItemProvider::QWinRTUiaSelectionItemProvider(QAccessible::Id id) : + QWinRTUiaBaseProvider(id) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +QWinRTUiaSelectionItemProvider::~QWinRTUiaSelectionItemProvider() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +// Returns true if element is currently selected. +HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionItemProvider::get_IsSelected(boolean *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + if (metadata->role() == QAccessible::RadioButton) + *value = metadata->state().checked; + else + *value = metadata->state().selected; + return S_OK; +} + +// Returns the provider for the container element (e.g., the list for the list item). +HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionItemProvider::get_SelectionContainer(IIRawElementProviderSimple **value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + *value = nullptr; + + auto accid = id(); + auto elementId = QSharedPointer(new QAccessible::Id(0)); + auto ptrElementId = new QSharedPointer(elementId); + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementId]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + // Radio buttons do not require a container. + if (accessible->role() == QAccessible::ListItem) { + if (QAccessibleInterface *parent = accessible->parent()) { + if (parent->role() == QAccessible::List) { + **ptrElementId = idForAccessible(parent); + } + } + } + } + delete ptrElementId; + return S_OK; + }))) { + return E_FAIL; + } + + if (!*elementId) + return S_OK; + + return QWinRTUiaMainProvider::rawProviderForAccessibleId(*elementId, value); +} + +// Adds the element to the list of selected elements. +HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionItemProvider::AddToSelection() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + auto accid = id(); + + QEventDispatcherWinRT::runOnMainThread([accid]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + if (QAccessibleActionInterface *actionInterface = accessible->actionInterface()) { + 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()); + } + } + } + } + QWinRTUiaMetadataCache::instance()->load(accid); + return S_OK; + }, 0); + return S_OK; +} + +// Removes a list item from selection. +HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionItemProvider::RemoveFromSelection() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + auto accid = id(); + + QEventDispatcherWinRT::runOnMainThread([accid]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + if (QAccessibleActionInterface *actionInterface = accessible->actionInterface()) { + if (accessible->role() != QAccessible::RadioButton) { + if (accessible->state().selected) { + actionInterface->doAction(QAccessibleActionInterface::toggleAction()); + } + } + } + } + QWinRTUiaMetadataCache::instance()->load(accid); + return S_OK; + }, 0); + return S_OK; +} + +// Selects the element (deselecting all others). +HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionItemProvider::Select() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + auto accid = id(); + + QEventDispatcherWinRT::runOnMainThread([accid]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + if (QAccessibleActionInterface *actionInterface = accessible->actionInterface()) { + 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()); + } + } + } + } + } + } + } + } + QWinRTUiaMetadataCache::instance()->load(accid); + return S_OK; + }, 0); + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.h new file mode 100644 index 0000000000..1b3cce7495 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIASELECTIONITEMPROVIDER_H +#define QWINRTUIASELECTIONITEMPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +// Implements the Selection Item control pattern provider. Used for List items and radio buttons. +class QWinRTUiaSelectionItemProvider : + public QWinRTUiaBaseProvider, + public Microsoft::WRL::RuntimeClass +{ + Q_OBJECT + Q_DISABLE_COPY(QWinRTUiaSelectionItemProvider) + InspectableClass(L"QWinRTUiaSelectionItemProvider", BaseTrust); + +public: + explicit QWinRTUiaSelectionItemProvider(QAccessible::Id id); + virtual ~QWinRTUiaSelectionItemProvider(); + + // ISelectionItemProvider + HRESULT STDMETHODCALLTYPE get_IsSelected(boolean *value) override; + HRESULT STDMETHODCALLTYPE get_SelectionContainer(ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple **value) override; + HRESULT STDMETHODCALLTYPE AddToSelection() override; + HRESULT STDMETHODCALLTYPE RemoveFromSelection() override; + HRESULT STDMETHODCALLTYPE Select() override; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIASELECTIONITEMPROVIDER_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.cpp new file mode 100644 index 0000000000..9e61a8df61 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiaselectionprovider.h" +#include "qwinrtuiametadatacache.h" +#include "qwinrtuiamainprovider.h" +#include "qwinrtuiautils.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWinRTUiAutomation; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::UI::Xaml::Automation::Provider; +using namespace ABI::Windows::UI::Xaml::Automation::Peers; + +QWinRTUiaSelectionProvider::QWinRTUiaSelectionProvider(QAccessible::Id id) : + QWinRTUiaBaseProvider(id) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +QWinRTUiaSelectionProvider::~QWinRTUiaSelectionProvider() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionProvider::get_CanSelectMultiple(boolean *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *value = (metadata->state().multiSelectable != 0); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionProvider::get_IsSelectionRequired(boolean *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + *value = false; + + auto accid = id(); + auto selectionRequired = QSharedPointer(new bool(false)); + auto ptrSelectionRequired = new QSharedPointer(selectionRequired); + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrSelectionRequired]() { + // Initially returns false if none are selected. After the first selection, it may be required. + bool anySelected = false; + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + int childCount = accessible->childCount(); + for (int i = 0; i < childCount; ++i) { + if (QAccessibleInterface *childAcc = accessible->child(i)) { + if (childAcc->state().selected) { + anySelected = true; + break; + } + } + } + **ptrSelectionRequired = anySelected && !accessible->state().multiSelectable && !accessible->state().extSelectable; + } + delete ptrSelectionRequired; + return S_OK; + }))) { + return E_FAIL; + } + + *value = *selectionRequired; + return S_OK; +} + +// Returns an array of providers with the selected items. +HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionProvider::GetSelection(UINT32 *returnValueSize, IIRawElementProviderSimple ***returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValueSize || !returnValue) + return E_INVALIDARG; + *returnValueSize = 0; + *returnValue = nullptr; + + auto accid = id(); + auto elementIds = QSharedPointer>(new QList); + auto ptrElementIds = new QSharedPointer>(elementIds); + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementIds]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + int childCount = accessible->childCount(); + for (int i = 0; i < childCount; ++i) { + if (QAccessibleInterface *childAcc = accessible->child(i)) { + if (childAcc->state().selected) { + QAccessible::Id childId = idForAccessible(childAcc); + QWinRTUiaMetadataCache::instance()->load(childId); + (*ptrElementIds)->append(childId); + } + } + } + } + delete ptrElementIds; + return S_OK; + }))) { + return E_FAIL; + } + + return QWinRTUiaMainProvider::rawProviderArrayForAccessibleIdList(*elementIds, returnValueSize, returnValue); +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.h new file mode 100644 index 0000000000..dcd286800f --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIASELECTIONPROVIDER_H +#define QWINRTUIASELECTIONPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +// Implements the Selection control pattern provider. Used for Lists. +class QWinRTUiaSelectionProvider : + public QWinRTUiaBaseProvider, + public Microsoft::WRL::RuntimeClass +{ + Q_OBJECT + Q_DISABLE_COPY(QWinRTUiaSelectionProvider) + InspectableClass(L"QWinRTUiaSelectionProvider", BaseTrust); + +public: + explicit QWinRTUiaSelectionProvider(QAccessible::Id id); + virtual ~QWinRTUiaSelectionProvider(); + + // ISelectionProvider + HRESULT STDMETHODCALLTYPE get_CanSelectMultiple(boolean *value) override; + HRESULT STDMETHODCALLTYPE get_IsSelectionRequired(boolean *value) override; + HRESULT STDMETHODCALLTYPE GetSelection(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple ***returnValue) override; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIASELECTIONPROVIDER_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.cpp new file mode 100644 index 0000000000..1af74a8b72 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiatableitemprovider.h" +#include "qwinrtuiamainprovider.h" +#include "qwinrtuiametadatacache.h" +#include "qwinrtuiautils.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWinRTUiAutomation; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::UI::Xaml::Automation::Provider; + +QWinRTUiaTableItemProvider::QWinRTUiaTableItemProvider(QAccessible::Id id) : + QWinRTUiaBaseProvider(id) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +QWinRTUiaTableItemProvider::~QWinRTUiaTableItemProvider() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +// Returns the providers for the column headers associated with the item. +HRESULT STDMETHODCALLTYPE QWinRTUiaTableItemProvider::GetColumnHeaderItems(UINT32 *returnValueSize, IIRawElementProviderSimple ***returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValueSize || !returnValue) + return E_INVALIDARG; + *returnValueSize = 0; + *returnValue = nullptr; + + auto accid = id(); + auto elementIds = QSharedPointer>(new QList); + auto ptrElementIds = new QSharedPointer>(elementIds); + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementIds]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + if (QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface()) { + QList headers = tableCellInterface->columnHeaderCells(); + for (auto header : qAsConst(headers)) { + QAccessible::Id headerId = idForAccessible(header); + QWinRTUiaMetadataCache::instance()->load(headerId); + (*ptrElementIds)->append(headerId); + } + } + } + delete ptrElementIds; + return S_OK; + }))) { + return E_FAIL; + } + + return QWinRTUiaMainProvider::rawProviderArrayForAccessibleIdList(*elementIds, returnValueSize, returnValue); +} + +// Returns the providers for the row headers associated with the item. +HRESULT STDMETHODCALLTYPE QWinRTUiaTableItemProvider::GetRowHeaderItems(UINT32 *returnValueSize, IIRawElementProviderSimple ***returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValueSize || !returnValue) + return E_INVALIDARG; + *returnValueSize = 0; + *returnValue = nullptr; + + auto accid = id(); + auto elementIds = QSharedPointer>(new QList); + auto ptrElementIds = new QSharedPointer>(elementIds); + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementIds]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + if (QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface()) { + QList headers = tableCellInterface->rowHeaderCells(); + for (auto header : qAsConst(headers)) { + QAccessible::Id headerId = idForAccessible(header); + QWinRTUiaMetadataCache::instance()->load(headerId); + (*ptrElementIds)->append(headerId); + } + } + } + delete ptrElementIds; + return S_OK; + }))) { + return E_FAIL; + } + + return QWinRTUiaMainProvider::rawProviderArrayForAccessibleIdList(*elementIds, returnValueSize, returnValue); +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.h new file mode 100644 index 0000000000..cb759864ae --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIATABLEITEMPROVIDER_H +#define QWINRTUIATABLEITEMPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +// Implements the Table Item control pattern provider. Used by items within a table/tree. +class QWinRTUiaTableItemProvider : + public QWinRTUiaBaseProvider, + public Microsoft::WRL::RuntimeClass +{ + Q_OBJECT + Q_DISABLE_COPY(QWinRTUiaTableItemProvider) + InspectableClass(L"QWinRTUiaTableItemProvider", BaseTrust); + +public: + explicit QWinRTUiaTableItemProvider(QAccessible::Id id); + virtual ~QWinRTUiaTableItemProvider(); + + // ITableItemProvider + HRESULT STDMETHODCALLTYPE GetColumnHeaderItems(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple ***returnValue) override; + HRESULT STDMETHODCALLTYPE GetRowHeaderItems(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple ***returnValue) override; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIATABLEITEMPROVIDER_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.cpp new file mode 100644 index 0000000000..e71ade3c1f --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.cpp @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiatableprovider.h" +#include "qwinrtuiamainprovider.h" +#include "qwinrtuiametadatacache.h" +#include "qwinrtuiautils.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWinRTUiAutomation; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::UI::Xaml::Automation::Provider; +using namespace ABI::Windows::UI::Xaml::Automation::Peers; + +QWinRTUiaTableProvider::QWinRTUiaTableProvider(QAccessible::Id id) : + QWinRTUiaBaseProvider(id) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +QWinRTUiaTableProvider::~QWinRTUiaTableProvider() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +// Returns the primary direction of traversal for the table. +HRESULT STDMETHODCALLTYPE QWinRTUiaTableProvider::get_RowOrColumnMajor(RowOrColumnMajor *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + *value = RowOrColumnMajor_Indeterminate; + return S_OK; +} + +// Gets the providers for all the column headers in the table. +HRESULT STDMETHODCALLTYPE QWinRTUiaTableProvider::GetColumnHeaders(UINT32 *returnValueSize, IIRawElementProviderSimple ***returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValueSize || !returnValue) + return E_INVALIDARG; + *returnValueSize = 0; + *returnValue = nullptr; + + auto accid = id(); + auto elementIds = QSharedPointer>(new QList); + auto ptrElementIds = new QSharedPointer>(elementIds); + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementIds]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + if (QAccessibleTableInterface *tableInterface = accessible->tableInterface()) { + for (int i = 0; i < tableInterface->columnCount(); ++i) { + if (QAccessibleInterface *cell = tableInterface->cellAt(0, i)) { + QWinRTUiaMetadataCache::instance()->load(idForAccessible(cell)); + if (QAccessibleTableCellInterface *tableCellInterface = cell->tableCellInterface()) { + QList headers = tableCellInterface->columnHeaderCells(); + for (auto header : qAsConst(headers)) { + QAccessible::Id headerId = idForAccessible(header); + QWinRTUiaMetadataCache::instance()->load(headerId); + (*ptrElementIds)->append(headerId); + } + } + } + } + } + } + delete ptrElementIds; + return S_OK; + }))) { + return E_FAIL; + } + + return QWinRTUiaMainProvider::rawProviderArrayForAccessibleIdList(*elementIds, returnValueSize, returnValue); +} + +// Gets the providers for all the row headers in the table. +HRESULT STDMETHODCALLTYPE QWinRTUiaTableProvider::GetRowHeaders(UINT32 *returnValueSize, IIRawElementProviderSimple ***returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValueSize || !returnValue) + return E_INVALIDARG; + *returnValueSize = 0; + *returnValue = nullptr; + + auto accid = id(); + auto elementIds = QSharedPointer>(new QList); + auto ptrElementIds = new QSharedPointer>(elementIds); + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementIds]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + if (QAccessibleTableInterface *tableInterface = accessible->tableInterface()) { + for (int i = 0; i < tableInterface->rowCount(); ++i) { + if (QAccessibleInterface *cell = tableInterface->cellAt(i, 0)) { + QWinRTUiaMetadataCache::instance()->load(idForAccessible(cell)); + if (QAccessibleTableCellInterface *tableCellInterface = cell->tableCellInterface()) { + QList headers = tableCellInterface->rowHeaderCells(); + for (auto header : qAsConst(headers)) { + QAccessible::Id headerId = idForAccessible(header); + QWinRTUiaMetadataCache::instance()->load(headerId); + (*ptrElementIds)->append(headerId); + } + } + } + } + } + } + delete ptrElementIds; + return S_OK; + }))) { + return E_FAIL; + } + + return QWinRTUiaMainProvider::rawProviderArrayForAccessibleIdList(*elementIds, returnValueSize, returnValue); +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.h new file mode 100644 index 0000000000..0cd174e401 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIATABLEPROVIDER_H +#define QWINRTUIATABLEPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +// Implements the Table control pattern provider. Used by tables/trees. +class QWinRTUiaTableProvider : + public QWinRTUiaBaseProvider, + public Microsoft::WRL::RuntimeClass +{ + Q_OBJECT + Q_DISABLE_COPY(QWinRTUiaTableProvider) + InspectableClass(L"QWinRTUiaTableProvider", BaseTrust); + +public: + explicit QWinRTUiaTableProvider(QAccessible::Id id); + virtual ~QWinRTUiaTableProvider(); + + // ITableProvider + HRESULT STDMETHODCALLTYPE get_RowOrColumnMajor(ABI::Windows::UI::Xaml::Automation::RowOrColumnMajor *value) override; + HRESULT STDMETHODCALLTYPE GetColumnHeaders(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple ***returnValue) override; + HRESULT STDMETHODCALLTYPE GetRowHeaders(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple ***returnValue) override; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIATABLEPROVIDER_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.cpp new file mode 100644 index 0000000000..aa120377df --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.cpp @@ -0,0 +1,232 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiatextprovider.h" +#include "qwinrtuiametadatacache.h" +#include "qwinrtuiatextrangeprovider.h" +#include "qwinrtuiautils.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWinRTUiAutomation; +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::UI::Xaml::Automation::Provider; + +QWinRTUiaTextProvider::QWinRTUiaTextProvider(QAccessible::Id id) : + QWinRTUiaBaseProvider(id) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +QWinRTUiaTextProvider::~QWinRTUiaTextProvider() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +// Returns a text range provider for the entire text. +HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::get_DocumentRange(ITextRangeProvider **value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + ComPtr textRangeProvider = Make(id(), 0, metadata->characterCount()); + return textRangeProvider.CopyTo(value); +} + +// Currently supporting single selection. +HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::get_SupportedTextSelection(SupportedTextSelection *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + if (!value) + return E_INVALIDARG; + *value = SupportedTextSelection_Single; + return S_OK; + +} + +// Returns an array of providers for the selected text ranges. +HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::GetSelection(UINT32 *returnValueSize, ITextRangeProvider ***returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValueSize || !returnValue) + return E_INVALIDARG; + *returnValueSize = 0; + *returnValue = nullptr; + + auto accid = id(); + auto selections = QSharedPointer>>(new QList>); + auto ptrSelections = new QSharedPointer>>(selections); + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrSelections]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + if (QAccessibleTextInterface *textInterface = accessible->textInterface()) { + for (int i = 0; i < textInterface->selectionCount(); ++i) { + QPair sel; + textInterface->selection(i, &sel.first, &sel.second); + (*ptrSelections)->append(sel); + } + if ((*ptrSelections)->size() == 0) { + // If there is no selection, we return an array with a single degenerate (empty) text range at the cursor position. + QPair sel(textInterface->cursorPosition(), textInterface->cursorPosition()); + (*ptrSelections)->append(sel); + } + } + } + delete ptrSelections; + return S_OK; + }))) { + return E_FAIL; + } + + int selCount = selections->size(); + if (selCount < 1) + return E_FAIL; + + ITextRangeProvider **providerArray = static_cast(CoTaskMemAlloc(selCount * sizeof(ITextRangeProvider *))); + if (!providerArray) + return E_OUTOFMEMORY; + + for (int i = 0; i < selCount; ++i) { + ComPtr textRangeProvider = Make(id(), (*selections)[i].first, (*selections)[i].second); + textRangeProvider.CopyTo(&providerArray[i]); + } + *returnValueSize = selCount; + *returnValue = providerArray; + return S_OK; +} + +// Returns an array of providers for the visible text ranges. +HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::GetVisibleRanges(UINT32 *returnValueSize, ITextRangeProvider ***returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValueSize || !returnValue) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + + // Considering the entire text as visible. + ComPtr textRangeProvider = Make(id(), 0, metadata->characterCount()); + textRangeProvider.CopyTo(*returnValue); + *returnValueSize = 1; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::RangeFromChild(IIRawElementProviderSimple *childElement, ITextRangeProvider **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + if (!childElement || !returnValue) + return E_INVALIDARG; + *returnValue = nullptr; + // No children supported. + return S_OK; +} + +// Returns a degenerate text range at the specified point. +HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::RangeFromPoint(ABI::Windows::Foundation::Point screenLocation, ITextRangeProvider **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + *returnValue = nullptr; + + const QPoint pt(screenLocation.X, screenLocation.Y); + auto accid = id(); + auto offset = QSharedPointer(new int); + auto ptrOffset = new QSharedPointer(offset); + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, pt, ptrOffset]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) + if (QAccessibleTextInterface *textInterface = accessible->textInterface()) + **ptrOffset = qBound(0, textInterface->offsetAtPoint(pt), textInterface->characterCount() - 1); + delete ptrOffset; + return S_OK; + }))) { + return E_FAIL; + } + + ComPtr textRangeProvider = Make(id(), *offset, *offset); + textRangeProvider.CopyTo(returnValue); + return S_OK; +} + +// Not supporting annotations. +HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::RangeFromAnnotation(IIRawElementProviderSimple *annotationElement, ITextRangeProvider **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + if (!annotationElement || !returnValue) + return E_INVALIDARG; + *returnValue = nullptr; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::GetCaretRange(boolean *isActive, ITextRangeProvider **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!isActive || !returnValue) + return E_INVALIDARG; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *isActive = metadata->state().focused; + + ComPtr textRangeProvider = Make(id(), metadata->cursorPosition(), metadata->cursorPosition()); + return textRangeProvider.CopyTo(returnValue); +} + + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.h new file mode 100644 index 0000000000..80d88e4115 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIATEXTPROVIDER_H +#define QWINRTUIATEXTPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +// Implements the Text control pattern provider. Used for text controls. +class QWinRTUiaTextProvider : + public QWinRTUiaBaseProvider, + public Microsoft::WRL::RuntimeClass +{ + Q_OBJECT + Q_DISABLE_COPY(QWinRTUiaTextProvider) + InspectableClass(L"QWinRTUiaTextProvider", BaseTrust); + +public: + explicit QWinRTUiaTextProvider(QAccessible::Id id); + virtual ~QWinRTUiaTextProvider(); + + // ITextProvider + HRESULT STDMETHODCALLTYPE get_DocumentRange(ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **value) override; + HRESULT STDMETHODCALLTYPE get_SupportedTextSelection(ABI::Windows::UI::Xaml::Automation::SupportedTextSelection *value) override; + HRESULT STDMETHODCALLTYPE GetSelection(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider ***returnValue) override; + HRESULT STDMETHODCALLTYPE GetVisibleRanges(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider ***returnValue) override; + HRESULT STDMETHODCALLTYPE RangeFromChild(ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple *childElement, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **returnValue) override; + HRESULT STDMETHODCALLTYPE RangeFromPoint(ABI::Windows::Foundation::Point screenLocation, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **returnValue) override; + + // ITextProvider2 + HRESULT STDMETHODCALLTYPE RangeFromAnnotation(ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple *annotationElement, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **returnValue) override; + HRESULT STDMETHODCALLTYPE GetCaretRange(boolean *isActive, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **returnValue) override; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIATEXTPROVIDER_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.cpp new file mode 100644 index 0000000000..fc3778d652 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.cpp @@ -0,0 +1,497 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiatextrangeprovider.h" +#include "qwinrtuiametadatacache.h" +#include "qwinrtuiamainprovider.h" +#include "qwinrtuiautils.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWinRTUiAutomation; +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::UI::Xaml::Automation::Provider; +using namespace ABI::Windows::UI::Xaml::Automation::Text; + +QWinRTUiaTextRangeProvider::QWinRTUiaTextRangeProvider(QAccessible::Id id, int startOffset, int endOffset) : + QWinRTUiaBaseProvider(id), + m_startOffset(startOffset), + m_endOffset(endOffset) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << startOffset << endOffset; +} + +QWinRTUiaTextRangeProvider::~QWinRTUiaTextRangeProvider() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::Clone(ITextRangeProvider **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + if (!returnValue) + return E_INVALIDARG; + + ComPtr textRangeProvider = Make(id(), m_startOffset, m_endOffset); + textRangeProvider.CopyTo(returnValue); + return S_OK; +} + +// Two ranges are considered equal if their start/end points are the same. +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::Compare(ITextRangeProvider *textRangeProvider, boolean *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + if (!textRangeProvider || !returnValue) + return E_INVALIDARG; + + QWinRTUiaTextRangeProvider *targetProvider = static_cast(textRangeProvider); + *returnValue = ((targetProvider->m_startOffset == m_startOffset) && (targetProvider->m_endOffset == m_endOffset)); + return S_OK; +} + +// Compare different endpoinds between two providers. +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::CompareEndpoints(TextPatternRangeEndpoint endpoint, ITextRangeProvider *textRangeProvider, TextPatternRangeEndpoint targetEndpoint, INT32 *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!textRangeProvider || !returnValue) + return E_INVALIDARG; + + QWinRTUiaTextRangeProvider *targetProvider = static_cast(textRangeProvider); + + int point = (endpoint == TextPatternRangeEndpoint_Start) ? m_startOffset : m_endOffset; + int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ? + targetProvider->m_startOffset : targetProvider->m_endOffset; + *returnValue = point - targetPoint; + return S_OK; +} + +// Expands/normalizes the range for a given text unit. +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::ExpandToEnclosingUnit(TextUnit unit) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "unit=" << unit << "this: " << this; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + + int len = metadata->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 = metadata->text(); + 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 STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::FindAttribute(INT32 /*attributeId*/, IInspectable * /*value*/, boolean /*backward*/, ITextRangeProvider **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + if (!returnValue) + return E_INVALIDARG; + *returnValue = nullptr; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::FindText(HSTRING /*text*/, boolean /*backward*/, boolean /*ignoreCase*/, ITextRangeProvider **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + if (!returnValue) + return E_INVALIDARG; + *returnValue = nullptr; + return S_OK; +} + +// Returns the value of a given attribute. +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::GetAttributeValue(INT32 attributeId, IInspectable **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "attributeId=" << attributeId; + + if (!returnValue) + return E_INVALIDARG; + *returnValue = nullptr; + + ComPtr propertyValueStatics; + if (FAILED(RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), IID_PPV_ARGS(&propertyValueStatics)))) + return E_FAIL; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + + switch (attributeId) { + case AutomationTextAttributesEnum_IsReadOnlyAttribute: + return propertyValueStatics->CreateBoolean(metadata->state().readOnly, returnValue); + case AutomationTextAttributesEnum_CaretPositionAttribute: + if (metadata->cursorPosition() == 0) + return propertyValueStatics->CreateInt32(AutomationCaretPosition_BeginningOfLine, returnValue); + else if (metadata->cursorPosition() == metadata->characterCount()) + return propertyValueStatics->CreateInt32(AutomationCaretPosition_EndOfLine, returnValue); + else + return propertyValueStatics->CreateInt32(AutomationCaretPosition_Unknown, returnValue); + default: + break; + } + return E_FAIL; +} + +// Returns an array of bounding rectangles for text lines within the range. +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::GetBoundingRectangles(UINT32 *returnValueSize, DOUBLE **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValueSize || !returnValue) + return E_INVALIDARG; + *returnValueSize = 0; + *returnValue = nullptr; + + auto accid = id(); + auto startOffset = m_startOffset; + auto endOffset = m_endOffset; + auto rects = QSharedPointer>(new QList); + auto ptrRects = new QSharedPointer>(rects); + + if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, startOffset, endOffset, ptrRects]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + if (QAccessibleTextInterface *textInterface = accessible->textInterface()) { + int len = textInterface->characterCount(); + if ((startOffset >= 0) && (endOffset <= len) && (startOffset < endOffset)) { + int start, end; + textInterface->textAtOffset(startOffset, QAccessible::LineBoundary, &start, &end); + while ((start >= 0) && (end >= 0)) { + int startRange = qMax(start, startOffset); + int endRange = qMin(end, endOffset); + if (startRange < endRange) { + // Calculates a bounding rectangle for the line and adds it to the list. + const QRect startRect = textInterface->characterRect(startRange); + const QRect endRect = textInterface->characterRect(endRange - 1); + const 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())); + (*ptrRects)->append(lineRect); + } + if (end >= len) break; + textInterface->textAfterOffset(end + 1, QAccessible::LineBoundary, &start, &end); + } + } + } + } + delete ptrRects; + return S_OK; + }))) { + return E_FAIL; + } + + DOUBLE *doubleArray = static_cast(CoTaskMemAlloc(4 * rects->size() * sizeof(DOUBLE))); + if (!doubleArray) + return E_OUTOFMEMORY; + + for (int i = 0; i < rects->size(); ++i) { + doubleArray[i*4] = (*rects)[i].left(); + doubleArray[i*4+1] = (*rects)[i].top(); + doubleArray[i*4+2] = (*rects)[i].width(); + doubleArray[i*4+3] = (*rects)[i].height(); + } + *returnValue = doubleArray; + *returnValueSize = 4 * rects->size(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::GetEnclosingElement(IIRawElementProviderSimple **returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + if (!returnValue) + return E_INVALIDARG; + return QWinRTUiaMainProvider::rawProviderForAccessibleId(id(), returnValue); +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::GetText(INT32 maxLength, HSTRING *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + if (!returnValue) + return E_INVALIDARG; + *returnValue = nullptr; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + + QString rangeText = metadata->text().mid(m_startOffset, m_endOffset - m_startOffset); + + if ((maxLength > -1) && (rangeText.size() > maxLength)) + rangeText.truncate(maxLength); + return qHString(rangeText, returnValue); +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::Move(TextUnit unit, INT32 count, INT32 *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + if (!returnValue) + return E_INVALIDARG; + *returnValue = 0; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + + int len = metadata->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; + *returnValue = start - m_startOffset; // Returns the actually moved distance. + m_startOffset = start; + } else { + if (count > 0) { + MoveEndpointByUnit(TextPatternRangeEndpoint_End, unit, count, returnValue); + MoveEndpointByUnit(TextPatternRangeEndpoint_Start, unit, count, returnValue); + } else { + MoveEndpointByUnit(TextPatternRangeEndpoint_Start, unit, count, returnValue); + MoveEndpointByUnit(TextPatternRangeEndpoint_End, unit, count, returnValue); + } + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::MoveEndpointByUnit(TextPatternRangeEndpoint endpoint, TextUnit unit, INT32 count, INT32 *returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + if (!returnValue) + return E_INVALIDARG; + *returnValue = 0; + + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + + int len = metadata->characterCount(); + if (len < 1) + return S_OK; + + if (unit == TextUnit_Character) { + if (endpoint == TextPatternRangeEndpoint_Start) { + int boundedValue = qBound(0, m_startOffset + count, len - 1); + *returnValue = boundedValue - m_startOffset; + m_startOffset = boundedValue; + m_endOffset = qBound(m_startOffset, m_endOffset, len); + } else { + int boundedValue = qBound(0, m_endOffset + count, len); + *returnValue = boundedValue - m_endOffset; + m_endOffset = boundedValue; + m_startOffset = qBound(0, m_startOffset, m_endOffset); + } + } else { + QString text = metadata->text(); + 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); + } + } + *returnValue = moved; + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::MoveEndpointByRange(TextPatternRangeEndpoint endpoint, ITextRangeProvider *textRangeProvider, TextPatternRangeEndpoint targetEndpoint) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + if (!textRangeProvider) + return E_INVALIDARG; + + QWinRTUiaTextRangeProvider *targetProvider = static_cast(textRangeProvider); + + 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; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::Select() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + auto accid = id(); + auto startOffset = m_startOffset; + auto endOffset = m_endOffset; + + QEventDispatcherWinRT::runOnMainThread([accid, startOffset, endOffset]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) + if (QAccessibleTextInterface *textInterface = accessible->textInterface()) { + // unselects all and adds a new selection + for (int i = textInterface->selectionCount() - 1; i >= 0; --i) + textInterface->removeSelection(i); + textInterface->addSelection(startOffset, endOffset); + } + QWinRTUiaMetadataCache::instance()->load(accid); + return S_OK; + }, 0); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::AddToSelection() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + return Select(); +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::RemoveFromSelection() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + auto accid = id(); + + QEventDispatcherWinRT::runOnMainThread([accid]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) + if (QAccessibleTextInterface *textInterface = accessible->textInterface()) { + // unselects all + for (int i = textInterface->selectionCount() - 1; i >= 0; --i) + textInterface->removeSelection(i); + } + QWinRTUiaMetadataCache::instance()->load(accid); + return S_OK; + }, 0); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::ScrollIntoView(boolean /*alignToTop*/) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + auto accid = id(); + auto startOffset = m_startOffset; + auto endOffset = m_endOffset; + + QEventDispatcherWinRT::runOnMainThread([accid, startOffset, endOffset]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) + if (QAccessibleTextInterface *textInterface = accessible->textInterface()) { + textInterface->scrollToSubstring(startOffset, endOffset); + } + QWinRTUiaMetadataCache::instance()->load(accid); + return S_OK; + }, 0); + return S_OK; +} + +// Returns an array of children elements embedded within the range. +HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::GetChildren(UINT32 *returnValueSize, IIRawElementProviderSimple ***returnValue) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!returnValue) + return E_INVALIDARG; + // Not supporting any children. + returnValueSize = 0; + *returnValue = nullptr; + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.h new file mode 100644 index 0000000000..81b5f0d400 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIATEXTRANGEPROVIDER_H +#define QWINRTUIATEXTRANGEPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +// Implements the Text Range control pattern provider. Used for text controls. +class QWinRTUiaTextRangeProvider : + public QWinRTUiaBaseProvider, + public Microsoft::WRL::RuntimeClass +{ + Q_OBJECT + Q_DISABLE_COPY(QWinRTUiaTextRangeProvider) + InspectableClass(L"QWinRTUiaTextRangeProvider", BaseTrust); + +public: + explicit QWinRTUiaTextRangeProvider(QAccessible::Id id, int startOffset, int endOffset); + virtual ~QWinRTUiaTextRangeProvider(); + + // ITextRangeProvider + HRESULT STDMETHODCALLTYPE Clone(ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **returnValue) override; + HRESULT STDMETHODCALLTYPE Compare(ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider *textRangeProvider, boolean *returnValue) override; + HRESULT STDMETHODCALLTYPE CompareEndpoints(ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider *textRangeProvider, ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint targetEndpoint, INT32 *returnValue) override; + HRESULT STDMETHODCALLTYPE ExpandToEnclosingUnit(ABI::Windows::UI::Xaml::Automation::Text::TextUnit unit) override; + HRESULT STDMETHODCALLTYPE FindAttribute(INT32 attributeId, IInspectable *value, boolean backward, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **returnValue) override; + HRESULT STDMETHODCALLTYPE FindText(HSTRING text, boolean backward, boolean ignoreCase, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **returnValue) override; + HRESULT STDMETHODCALLTYPE GetAttributeValue(INT32 attributeId, IInspectable **returnValue) override; + HRESULT STDMETHODCALLTYPE GetBoundingRectangles(UINT32 *returnValueSize, DOUBLE **returnValue) override; + HRESULT STDMETHODCALLTYPE GetEnclosingElement(ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple **returnValue) override; + HRESULT STDMETHODCALLTYPE GetText(INT32 maxLength, HSTRING *returnValue) override; + HRESULT STDMETHODCALLTYPE Move(ABI::Windows::UI::Xaml::Automation::Text::TextUnit unit, INT32 count, INT32 *returnValue) override; + HRESULT STDMETHODCALLTYPE MoveEndpointByUnit(ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint, ABI::Windows::UI::Xaml::Automation::Text::TextUnit unit, INT32 count, INT32 *returnValue) override; + HRESULT STDMETHODCALLTYPE MoveEndpointByRange(ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider *textRangeProvider, ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint targetEndpoint) override; + HRESULT STDMETHODCALLTYPE Select() override; + HRESULT STDMETHODCALLTYPE AddToSelection() override; + HRESULT STDMETHODCALLTYPE RemoveFromSelection() override; + HRESULT STDMETHODCALLTYPE ScrollIntoView(boolean alignToTop) override; + HRESULT STDMETHODCALLTYPE GetChildren(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple ***returnValue) override; + +private: + int m_startOffset; + int m_endOffset; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIATEXTRANGEPROVIDER_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.cpp new file mode 100644 index 0000000000..59f55eb422 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiatoggleprovider.h" +#include "qwinrtuiametadatacache.h" +#include "qwinrtuiautils.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWinRTUiAutomation; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::UI::Xaml::Automation::Provider; + +QWinRTUiaToggleProvider::QWinRTUiaToggleProvider(QAccessible::Id id) : + QWinRTUiaBaseProvider(id) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +QWinRTUiaToggleProvider::~QWinRTUiaToggleProvider() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +// Gets the current toggle state. +HRESULT STDMETHODCALLTYPE QWinRTUiaToggleProvider::get_ToggleState(ToggleState *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + if (metadata->state().checked) + *value = metadata->state().checkStateMixed ? ToggleState_Indeterminate : ToggleState_On; + else + *value = ToggleState_Off; + return S_OK; +} + +// Toggles the state by invoking the toggle action. +HRESULT STDMETHODCALLTYPE QWinRTUiaToggleProvider::Toggle() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + auto accid = id(); + + QEventDispatcherWinRT::runOnMainThread([accid]() { + if (QAccessibleInterface *accessible = accessibleForId(accid)) + if (QAccessibleActionInterface *actionInterface = accessible->actionInterface()) + actionInterface->doAction(QAccessibleActionInterface::toggleAction()); + QWinRTUiaMetadataCache::instance()->load(accid); + return S_OK; + }, 0); + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.h new file mode 100644 index 0000000000..3d1740c0a1 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIATOGGLEPROVIDER_H +#define QWINRTUIATOGGLEPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +// Implements the Toggle control pattern provider. Used for checkboxes. +class QWinRTUiaToggleProvider : + public QWinRTUiaBaseProvider, + public Microsoft::WRL::RuntimeClass +{ + Q_OBJECT + Q_DISABLE_COPY(QWinRTUiaToggleProvider) + InspectableClass(L"QWinRTUiaToggleProvider", BaseTrust); + +public: + explicit QWinRTUiaToggleProvider(QAccessible::Id id); + virtual ~QWinRTUiaToggleProvider(); + + // IToggleProvider + HRESULT STDMETHODCALLTYPE get_ToggleState(ABI::Windows::UI::Xaml::Automation::ToggleState *value) override; + HRESULT STDMETHODCALLTYPE Toggle() override; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIATOGGLEPROVIDER_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp new file mode 100644 index 0000000000..98483216c0 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiautils.h" + +using namespace ABI::Windows::UI::Xaml::Automation::Peers; +using namespace ABI::Windows::UI::Xaml::Automation::Text; +using namespace ABI::Windows::Foundation::Collections; + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcQpaUiAutomation, "qt.qpa.uiautomation") + +namespace QWinRTUiAutomation { + +// 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; +} + +QAccessibleInterface *accessibleForId(QAccessible::Id id) +{ + QAccessibleInterface *accessible = QAccessible::accessibleInterface(id); + if (!accessible || !accessible->isValid()) + return nullptr; + return accessible; +} + +QAccessible::Id idForAccessible(QAccessibleInterface *accessible) +{ + if (!accessible) + return QAccessible::Id(0); + return QAccessible::uniqueId(accessible); +} + +// Maps an accessibility role ID to an UI Automation control type ID. +AutomationControlType roleToControlType(QAccessible::Role role) +{ + static const QHash mapping { + {QAccessible::TitleBar, AutomationControlType::AutomationControlType_TitleBar}, + {QAccessible::MenuBar, AutomationControlType::AutomationControlType_MenuBar}, + {QAccessible::ScrollBar, AutomationControlType::AutomationControlType_ScrollBar}, + {QAccessible::Grip, AutomationControlType::AutomationControlType_Thumb}, + {QAccessible::Sound, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::Cursor, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::Caret, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::AlertMessage, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::Window, AutomationControlType::AutomationControlType_Window}, + {QAccessible::Client, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::PopupMenu, AutomationControlType::AutomationControlType_Menu}, + {QAccessible::MenuItem, AutomationControlType::AutomationControlType_MenuItem}, + {QAccessible::ToolTip, AutomationControlType::AutomationControlType_ToolTip}, + {QAccessible::Application, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::Document, AutomationControlType::AutomationControlType_Document}, + {QAccessible::Pane, AutomationControlType::AutomationControlType_Pane}, + {QAccessible::Chart, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::Dialog, AutomationControlType::AutomationControlType_Window}, + {QAccessible::Border, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::Grouping, AutomationControlType::AutomationControlType_Group}, + {QAccessible::Separator, AutomationControlType::AutomationControlType_Separator}, + {QAccessible::ToolBar, AutomationControlType::AutomationControlType_ToolBar}, + {QAccessible::StatusBar, AutomationControlType::AutomationControlType_StatusBar}, + {QAccessible::Table, AutomationControlType::AutomationControlType_Table}, + {QAccessible::ColumnHeader, AutomationControlType::AutomationControlType_Header}, + {QAccessible::RowHeader, AutomationControlType::AutomationControlType_Header}, + {QAccessible::Column, AutomationControlType::AutomationControlType_HeaderItem}, + {QAccessible::Row, AutomationControlType::AutomationControlType_HeaderItem}, + {QAccessible::Cell, AutomationControlType::AutomationControlType_DataItem}, + {QAccessible::Link, AutomationControlType::AutomationControlType_Hyperlink}, + {QAccessible::HelpBalloon, AutomationControlType::AutomationControlType_ToolTip}, + {QAccessible::Assistant, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::List, AutomationControlType::AutomationControlType_List}, + {QAccessible::ListItem, AutomationControlType::AutomationControlType_ListItem}, + {QAccessible::Tree, AutomationControlType::AutomationControlType_Tree}, + {QAccessible::TreeItem, AutomationControlType::AutomationControlType_TreeItem}, + {QAccessible::PageTab, AutomationControlType::AutomationControlType_TabItem}, + {QAccessible::PropertyPage, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::Indicator, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::Graphic, AutomationControlType::AutomationControlType_Image}, + {QAccessible::StaticText, AutomationControlType::AutomationControlType_Edit}, + {QAccessible::EditableText, AutomationControlType::AutomationControlType_Edit}, + {QAccessible::Button, AutomationControlType::AutomationControlType_Button}, + {QAccessible::CheckBox, AutomationControlType::AutomationControlType_CheckBox}, + {QAccessible::RadioButton, AutomationControlType::AutomationControlType_RadioButton}, + {QAccessible::ComboBox, AutomationControlType::AutomationControlType_ComboBox}, + {QAccessible::ProgressBar, AutomationControlType::AutomationControlType_ProgressBar}, + {QAccessible::Dial, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::HotkeyField, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::Slider, AutomationControlType::AutomationControlType_Slider}, + {QAccessible::SpinBox, AutomationControlType::AutomationControlType_Spinner}, + {QAccessible::Canvas, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::Animation, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::Equation, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::ButtonDropDown, AutomationControlType::AutomationControlType_Button}, + {QAccessible::ButtonMenu, AutomationControlType::AutomationControlType_Button}, + {QAccessible::ButtonDropGrid, AutomationControlType::AutomationControlType_Button}, + {QAccessible::Whitespace, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::PageTabList, AutomationControlType::AutomationControlType_Tab}, + {QAccessible::Clock, AutomationControlType::AutomationControlType_Custom}, + {QAccessible::Splitter, AutomationControlType::AutomationControlType_Custom}, + }; + + return mapping.value(role, AutomationControlType::AutomationControlType_Custom); +} + +// 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')); +} + +HRESULT qHString(const QString &str, HSTRING *returnValue) +{ + if (!returnValue) + return E_INVALIDARG; + + const wchar_t *wstr = reinterpret_cast(str.utf16()); + return ::WindowsCreateString(wstr, static_cast(::wcslen(wstr)), returnValue); +} + +QString hStrToQStr(const HSTRING &hStr) +{ + quint32 len; + const wchar_t *wstr = ::WindowsGetStringRawBuffer(hStr, &len); + return QString::fromWCharArray(wstr, len); +} + +} // namespace QWinRTUiAutomation + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.h new file mode 100644 index 0000000000..9519cb4eb5 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIAUTILS_H +#define QWINRTUIAUTILS_H + +#include +#if QT_CONFIG(accessibility) + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(lcQpaUiAutomation) + +namespace QWinRTUiAutomation { + +QWindow *windowForAccessible(const QAccessibleInterface *accessible); + +QAccessibleInterface *accessibleForId(QAccessible::Id id); + +QAccessible::Id idForAccessible(QAccessibleInterface *accessible); + +ABI::Windows::UI::Xaml::Automation::Peers::AutomationControlType roleToControlType(QAccessible::Role role); + +bool isTextUnitSeparator(ABI::Windows::UI::Xaml::Automation::Text::TextUnit unit, const QChar &ch); + +HRESULT qHString(const QString &str, HSTRING *returnValue); + +QString hStrToQStr(const HSTRING &hStr); + +} // namespace QWinRTUiAutomation + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIAUTILS_H diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.cpp new file mode 100644 index 0000000000..21389b74d2 --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 +#if QT_CONFIG(accessibility) + +#include "qwinrtuiavalueprovider.h" +#include "qwinrtuiametadatacache.h" +#include "qwinrtuiautils.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWinRTUiAutomation; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::UI::Xaml::Automation::Provider; + +QWinRTUiaValueProvider::QWinRTUiaValueProvider(QAccessible::Id id) : + QWinRTUiaBaseProvider(id) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +QWinRTUiaValueProvider::~QWinRTUiaValueProvider() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; +} + +// True for read-only controls. +HRESULT STDMETHODCALLTYPE QWinRTUiaValueProvider::get_IsReadOnly(boolean *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + *value = (metadata->state().readOnly != 0); + return S_OK; +} + +// Returns the value in text form. +HRESULT STDMETHODCALLTYPE QWinRTUiaValueProvider::get_Value(HSTRING *value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!value) + return E_INVALIDARG; + QSharedPointer metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id()); + return qHString(metadata->value(), value); +} + +// Sets the value associated with the control. +HRESULT STDMETHODCALLTYPE QWinRTUiaValueProvider::SetValue(HSTRING value) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + auto accid = id(); + auto tmpValue = QSharedPointer(new QString); + auto ptrValue = new QSharedPointer(tmpValue); + + *tmpValue = hStrToQStr(value); + + QEventDispatcherWinRT::runOnMainThread([accid, ptrValue]() { + + if (QAccessibleInterface *accessible = accessibleForId(accid)) { + + // First sets the value as a text. + accessible->setText(QAccessible::Value, **ptrValue); + + // 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 = (*ptrValue)->toDouble(&ok); + if (ok) { + double minimum = valueInterface->minimumValue().toDouble(); + double maximum = valueInterface->maximumValue().toDouble(); + if ((numval >= minimum) && (numval <= maximum)) { + valueInterface->setCurrentValue(QVariant(numval)); + } + } + } + } + QWinRTUiaMetadataCache::instance()->load(accid); + delete ptrValue; + return S_OK; + }, 0); + + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.h new file mode 100644 index 0000000000..d9cd5d200d --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWINRTUIAVALUEPROVIDER_H +#define QWINRTUIAVALUEPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwinrtuiabaseprovider.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +// Implements the Value control pattern provider. +// Supported for all controls that can return text(QAccessible::Value). +class QWinRTUiaValueProvider : + public QWinRTUiaBaseProvider, + public Microsoft::WRL::RuntimeClass +{ + Q_OBJECT + Q_DISABLE_COPY(QWinRTUiaValueProvider) + InspectableClass(L"QWinRTUiaValueProvider", BaseTrust); + +public: + explicit QWinRTUiaValueProvider(QAccessible::Id id); + virtual ~QWinRTUiaValueProvider(); + + // IValueProvider + HRESULT STDMETHODCALLTYPE get_IsReadOnly(boolean *value) override; + HRESULT STDMETHODCALLTYPE get_Value(HSTRING *value) override; + HRESULT STDMETHODCALLTYPE SetValue(HSTRING value) override; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINRTUIAVALUEPROVIDER_H diff --git a/src/plugins/platforms/winrt/uiautomation/uiautomation.pri b/src/plugins/platforms/winrt/uiautomation/uiautomation.pri new file mode 100644 index 0000000000..ca0dfae53f --- /dev/null +++ b/src/plugins/platforms/winrt/uiautomation/uiautomation.pri @@ -0,0 +1,45 @@ + +SOURCES += \ + $$PWD/qwinrtuiaaccessibility.cpp \ + $$PWD/qwinrtuiabaseprovider.cpp \ + $$PWD/qwinrtuiacontrolmetadata.cpp \ + $$PWD/qwinrtuiagriditemprovider.cpp \ + $$PWD/qwinrtuiagridprovider.cpp \ + $$PWD/qwinrtuiainvokeprovider.cpp \ + $$PWD/qwinrtuiamainprovider.cpp \ + $$PWD/qwinrtuiametadatacache.cpp \ + $$PWD/qwinrtuiapeervector.cpp \ + $$PWD/qwinrtuiaprovidercache.cpp \ + $$PWD/qwinrtuiarangevalueprovider.cpp \ + $$PWD/qwinrtuiaselectionitemprovider.cpp \ + $$PWD/qwinrtuiaselectionprovider.cpp \ + $$PWD/qwinrtuiatableitemprovider.cpp \ + $$PWD/qwinrtuiatableprovider.cpp \ + $$PWD/qwinrtuiatextprovider.cpp \ + $$PWD/qwinrtuiatextrangeprovider.cpp \ + $$PWD/qwinrtuiatoggleprovider.cpp \ + $$PWD/qwinrtuiautils.cpp \ + $$PWD/qwinrtuiavalueprovider.cpp + +HEADERS += \ + $$PWD/qwinrtuiaaccessibility.h \ + $$PWD/qwinrtuiabaseprovider.h \ + $$PWD/qwinrtuiacontrolmetadata.h \ + $$PWD/qwinrtuiaemptypropertyvalue.h \ + $$PWD/qwinrtuiagriditemprovider.h \ + $$PWD/qwinrtuiagridprovider.h \ + $$PWD/qwinrtuiainvokeprovider.h \ + $$PWD/qwinrtuiamainprovider.h \ + $$PWD/qwinrtuiametadatacache.h \ + $$PWD/qwinrtuiapeervector.h \ + $$PWD/qwinrtuiaprovidercache.h \ + $$PWD/qwinrtuiarangevalueprovider.h \ + $$PWD/qwinrtuiaselectionitemprovider.h \ + $$PWD/qwinrtuiaselectionprovider.h \ + $$PWD/qwinrtuiatableitemprovider.h \ + $$PWD/qwinrtuiatableprovider.h \ + $$PWD/qwinrtuiatextprovider.h \ + $$PWD/qwinrtuiatextrangeprovider.h \ + $$PWD/qwinrtuiatoggleprovider.h \ + $$PWD/qwinrtuiautils.h \ + $$PWD/qwinrtuiavalueprovider.h diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro index 042b270cff..167c5b0448 100644 --- a/src/plugins/platforms/winrt/winrt.pro +++ b/src/plugins/platforms/winrt/winrt.pro @@ -13,6 +13,7 @@ LIBS += -lws2_32 -ld3d11 SOURCES = \ main.cpp \ qwinrtbackingstore.cpp \ + qwinrtcanvas.cpp \ qwinrtclipboard.cpp \ qwinrtcursor.cpp \ qwinrtdrag.cpp \ @@ -31,6 +32,7 @@ SOURCES = \ HEADERS = \ qwinrtbackingstore.h \ + qwinrtcanvas.h \ qwinrtclipboard.h \ qwinrtcursor.h \ qwinrtdrag.h \ @@ -58,6 +60,8 @@ contains(DEFINES, QT_NO_DRAGANDDROP) { HEADERS -= qwinrtdrag.h } +qtConfig(accessibility): include($$PWD/uiautomation/uiautomation.pri) + PLUGIN_TYPE = platforms PLUGIN_CLASS_NAME = QWinRTIntegrationPlugin !equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = - -- cgit v1.2.3