Bug 1886371 part 4: Implement IRawElementProviderFragmentRoot. r=nlapre

This identifies the root of our implementation and allows for focus querying and hit testing.
We also implement IRawElementProviderSimple::get_HostRawElementProvider to connect to UIA's HWND provider.

Differential Revision: https://phabricator.services.mozilla.com/D205182
This commit is contained in:
James Teh 2024-03-25 03:28:05 +00:00
parent a518e894f6
commit 12770de85d
6 changed files with 143 additions and 4 deletions

View File

@ -5,6 +5,7 @@
#include "mozilla/a11y/DocAccessibleParent.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/StaticPrefs_accessibility.h"
#include "mozilla/WindowsVersion.h"
#include "MsaaRootAccessible.h"
#include "Relation.h"
@ -36,6 +37,13 @@ MsaaRootAccessible::InternalQueryInterface(REFIID aIid, void** aOutInterface) {
return S_OK;
}
if (StaticPrefs::accessibility_uia_enable() &&
aIid == IID_IRawElementProviderFragmentRoot) {
RefPtr<IRawElementProviderFragmentRoot> root = this;
root.forget(aOutInterface);
return S_OK;
}
// ...Otherwise we pass through to the base COM implementation of
// QueryInterface which is provided by MsaaDocAccessible.
return MsaaDocAccessible::QueryInterface(aIid, aOutInterface);

View File

@ -8,12 +8,14 @@
#include "mozilla/mscom/Aggregation.h"
#include "MsaaDocAccessible.h"
#include "UiaRoot.h"
namespace mozilla {
namespace a11y {
class RootAccessible;
class MsaaRootAccessible : public MsaaDocAccessible {
class MsaaRootAccessible : public MsaaDocAccessible, public UiaRoot {
public:
explicit MsaaRootAccessible(Accessible* aAcc)
: MsaaDocAccessible(aAcc), mOuter(&mInternalUnknown) {}

View File

@ -0,0 +1,61 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "UiaRoot.h"
#include "MsaaRootAccessible.h"
#include "RootAccessible.h"
using namespace mozilla;
using namespace mozilla::a11y;
// UiaRoot
Accessible* UiaRoot::Acc() {
auto* mr = static_cast<MsaaRootAccessible*>(this);
return static_cast<MsaaAccessible*>(mr)->Acc();
}
// IRawElementProviderFragmentRoot
STDMETHODIMP
UiaRoot::ElementProviderFromPoint(
double aX, double aY,
__RPC__deref_out_opt IRawElementProviderFragment** aRetVal) {
if (!aRetVal) {
return E_INVALIDARG;
}
*aRetVal = nullptr;
Accessible* acc = Acc();
if (!acc) {
return CO_E_OBJNOTCONNECTED;
}
if (Accessible* target = acc->ChildAtPoint(
aX, aY, Accessible::EWhichChildAtPoint::DeepestChild)) {
RefPtr<IRawElementProviderFragment> fragment =
MsaaAccessible::GetFrom(target);
fragment.forget(aRetVal);
}
return S_OK;
}
STDMETHODIMP
UiaRoot::GetFocus(__RPC__deref_out_opt IRawElementProviderFragment** aRetVal) {
if (!aRetVal) {
return E_INVALIDARG;
}
*aRetVal = nullptr;
Accessible* acc = Acc();
if (!acc) {
return CO_E_OBJNOTCONNECTED;
}
if (Accessible* focus = acc->FocusedChild()) {
RefPtr<IRawElementProviderFragment> fragment =
MsaaAccessible::GetFrom(focus);
fragment.forget(aRetVal);
}
return S_OK;
}

View File

@ -0,0 +1,40 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_a11y_UiaRoot_h__
#define mozilla_a11y_UiaRoot_h__
#include "objbase.h"
#include "uiautomation.h"
namespace mozilla {
namespace a11y {
class Accessible;
/**
* IRawElementProviderFragmentRoot implementation.
*/
class UiaRoot : public IRawElementProviderFragmentRoot {
public:
// IRawElementProviderFragmentRoot
virtual HRESULT STDMETHODCALLTYPE ElementProviderFromPoint(
/* [in] */ double aX,
/* [in] */ double aY,
/* [retval][out] */
__RPC__deref_out_opt IRawElementProviderFragment** aRetVal);
virtual HRESULT STDMETHODCALLTYPE GetFocus(
/* [retval][out] */ __RPC__deref_out_opt IRawElementProviderFragment**
aRetVal);
private:
Accessible* Acc();
};
} // namespace a11y
} // namespace mozilla
#endif

View File

@ -6,6 +6,7 @@
SOURCES += [
"uiaRawElmProvider.cpp",
"UiaRoot.cpp",
]
LOCAL_INCLUDES += [

View File

@ -12,8 +12,10 @@
#include "LocalAccessible-inl.h"
#include "mozilla/a11y/RemoteAccessible.h"
#include "MsaaAccessible.h"
#include "MsaaRootAccessible.h"
#include "nsAccUtils.h"
#include "nsTextEquivUtils.h"
#include "RootAccessible.h"
using namespace mozilla;
using namespace mozilla::a11y;
@ -250,9 +252,15 @@ STDMETHODIMP
uiaRawElmProvider::get_HostRawElementProvider(
__RPC__deref_out_opt IRawElementProviderSimple** aRawElmProvider) {
if (!aRawElmProvider) return E_INVALIDARG;
// This method is not used with IAccessibleEx implementations.
*aRawElmProvider = nullptr;
Accessible* acc = Acc();
if (!acc) {
return CO_E_OBJNOTCONNECTED;
}
if (acc->IsRoot()) {
HWND hwnd = MsaaAccessible::GetHWNDFor(acc);
return UiaHostProviderFromHwnd(hwnd, aRawElmProvider);
}
return S_OK;
}
@ -346,7 +354,26 @@ uiaRawElmProvider::SetFocus() {
STDMETHODIMP
uiaRawElmProvider::get_FragmentRoot(
__RPC__deref_out_opt IRawElementProviderFragmentRoot** aRetVal) {
return E_NOTIMPL;
if (!aRetVal) {
return E_INVALIDARG;
}
*aRetVal = nullptr;
Accessible* acc = Acc();
if (!acc) {
return CO_E_OBJNOTCONNECTED;
}
LocalAccessible* localAcc = acc->AsLocal();
if (!localAcc) {
localAcc = acc->AsRemote()->OuterDocOfRemoteBrowser();
if (!localAcc) {
return CO_E_OBJNOTCONNECTED;
}
}
MsaaAccessible* msaa = MsaaAccessible::GetFrom(localAcc->RootAccessible());
RefPtr<IRawElementProviderFragmentRoot> fragRoot =
static_cast<MsaaRootAccessible*>(msaa);
fragRoot.forget(aRetVal);
return S_OK;
}
// Private methods