Bug 1421144: Fix IAccessible::accFocus on the root accessible for remote content. r?Surkov
The base implementation of accFocus can't handle the case when a remote document has focus and just returns no focus (VT_EMPTY).
Override accFocus on the root accessible to try the accessible for the remote document in the active tab in this case.
This fixes focus loss with NVDA when dismissing the System menu.
MozReview-Commit-ID: 1jhAv08rDFU
--- a/accessible/windows/msaa/RootAccessibleWrap.cpp
+++ b/accessible/windows/msaa/RootAccessibleWrap.cpp
@@ -144,8 +144,57 @@ RootAccessibleWrap::accNavigate(
return E_FAIL;
}
VariantInit(pvarEndUpAt);
pvarEndUpAt->pdispVal = NativeAccessible(target);
pvarEndUpAt->vt = VT_DISPATCH;
return S_OK;
}
+
+STDMETHODIMP
+RootAccessibleWrap::get_accFocus(
+ /* [retval][out] */ VARIANT __RPC_FAR *pvarChild)
+{
+ HRESULT hr = DocAccessibleWrap::get_accFocus(pvarChild);
+ if (FAILED(hr) || pvarChild->vt != VT_EMPTY) {
+ // We got a definite result (either failure or an accessible).
+ return hr;
+ }
+
+ // The base implementation reported no focus.
+ // Focus might be in a remote document.
+ // (The base implementation can't handle this.)
+ // Get the document in the active tab.
+ ProxyAccessible* docProxy = GetPrimaryRemoteTopLevelContentDoc();
+ if (!docProxy) {
+ return hr;
+ }
+ Accessible* docAcc = WrapperFor(docProxy);
+ if (!docAcc) {
+ return E_FAIL;
+ }
+ RefPtr<IDispatch> docDisp = NativeAccessible(docAcc);
+ if (!docDisp) {
+ return E_FAIL;
+ }
+ RefPtr<IAccessible> docIa;
+ hr = docDisp->QueryInterface(IID_IAccessible, (void**)getter_AddRefs(docIa));
+ MOZ_ASSERT(SUCCEEDED(hr));
+ MOZ_ASSERT(docIa);
+
+ // Ask this document for its focused descendant.
+ // We return this as is to the client except for CHILDID_SELF (see below).
+ hr = docIa->get_accFocus(pvarChild);
+ if (FAILED(hr)) {
+ return hr;
+ }
+
+ if (pvarChild->vt == VT_I4 && pvarChild->lVal == CHILDID_SELF) {
+ // The document itself has focus.
+ // We're handling a call to accFocus on the root accessible,
+ // so replace CHILDID_SELF with the document accessible.
+ pvarChild->vt = VT_DISPATCH;
+ docDisp.forget(&pvarChild->pdispVal);
+ }
+
+ return S_OK;
+}
--- a/accessible/windows/msaa/RootAccessibleWrap.h
+++ b/accessible/windows/msaa/RootAccessibleWrap.h
@@ -38,16 +38,19 @@ public:
*/
already_AddRefed<IUnknown> GetInternalUnknown();
virtual /* [id] */ HRESULT STDMETHODCALLTYPE accNavigate(
/* [in] */ long navDir,
/* [optional][in] */ VARIANT varStart,
/* [retval][out] */ VARIANT __RPC_FAR *pvarEndUpAt) override;
+ virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accFocus(
+ /* [retval][out] */ VARIANT __RPC_FAR *pvarChild) override;
+
private:
// DECLARE_AGGREGATABLE declares the internal IUnknown methods as well as
// mInternalUnknown.
DECLARE_AGGREGATABLE(RootAccessibleWrap);
IUnknown* mOuter;
};
} // namespace a11y