diff --git a/accessible/windows/msaa/MsaaRootAccessible.cpp b/accessible/windows/msaa/MsaaRootAccessible.cpp index ac747ff3d1e0..2b28edb9b597 100644 --- a/accessible/windows/msaa/MsaaRootAccessible.cpp +++ b/accessible/windows/msaa/MsaaRootAccessible.cpp @@ -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 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); diff --git a/accessible/windows/msaa/MsaaRootAccessible.h b/accessible/windows/msaa/MsaaRootAccessible.h index a51533d7ba44..efc42bc09496 100644 --- a/accessible/windows/msaa/MsaaRootAccessible.h +++ b/accessible/windows/msaa/MsaaRootAccessible.h @@ -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) {} diff --git a/accessible/windows/uia/UiaRoot.cpp b/accessible/windows/uia/UiaRoot.cpp new file mode 100644 index 000000000000..0e8c86ce6a32 --- /dev/null +++ b/accessible/windows/uia/UiaRoot.cpp @@ -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(this); + return static_cast(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 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 fragment = + MsaaAccessible::GetFrom(focus); + fragment.forget(aRetVal); + } + return S_OK; +} diff --git a/accessible/windows/uia/UiaRoot.h b/accessible/windows/uia/UiaRoot.h new file mode 100644 index 000000000000..91d1c00b3dad --- /dev/null +++ b/accessible/windows/uia/UiaRoot.h @@ -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 diff --git a/accessible/windows/uia/moz.build b/accessible/windows/uia/moz.build index 058aacc579ef..c52a24d61231 100644 --- a/accessible/windows/uia/moz.build +++ b/accessible/windows/uia/moz.build @@ -6,6 +6,7 @@ SOURCES += [ "uiaRawElmProvider.cpp", + "UiaRoot.cpp", ] LOCAL_INCLUDES += [ diff --git a/accessible/windows/uia/uiaRawElmProvider.cpp b/accessible/windows/uia/uiaRawElmProvider.cpp index 6b2e936df1a0..00a326c85167 100644 --- a/accessible/windows/uia/uiaRawElmProvider.cpp +++ b/accessible/windows/uia/uiaRawElmProvider.cpp @@ -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 fragRoot = + static_cast(msaa); + fragRoot.forget(aRetVal); + return S_OK; } // Private methods