diff --git a/accessible/ipc/DocAccessibleParent.cpp b/accessible/ipc/DocAccessibleParent.cpp index da1ad5f1ecab..a79fc92d4e33 100644 --- a/accessible/ipc/DocAccessibleParent.cpp +++ b/accessible/ipc/DocAccessibleParent.cpp @@ -12,6 +12,13 @@ #include "nsAccUtils.h" #include "nsCoreUtils.h" +#if defined(XP_WIN) +#include "AccessibleWrap.h" +#include "Compatibility.h" +#include "nsWinUtils.h" +#include "RootAccessible.h" +#endif + namespace mozilla { namespace a11y { @@ -525,7 +532,43 @@ DocAccessibleParent::SetCOMProxy(const RefPtr& aCOMProxy) IAccessibleHolder::COMPtrType ptr(rawNative); IAccessibleHolder holder(Move(ptr)); - Unused << SendParentCOMProxy(holder); + + if (nsWinUtils::IsWindowEmulationStarted()) { + RootAccessible* rootDocument = outerDoc->RootAccessible(); + MOZ_ASSERT(rootDocument); + + bool isActive = true; + nsIntRect rect(CW_USEDEFAULT, CW_USEDEFAULT, 0, 0); + if (Compatibility::IsDolphin()) { + rect = Bounds(); + nsIntRect rootRect = rootDocument->Bounds(); + rect.x = rootRect.x - rect.x; + rect.y -= rootRect.y; + tab->GetDocShellIsActive(&isActive); + } + + HWND parentWnd = reinterpret_cast(rootDocument->GetNativeWindow()); + HWND hWnd = nsWinUtils::CreateNativeWindow(kClassNameTabContent, + parentWnd, rect.x, rect.y, + rect.width, rect.height, + isActive); + if (hWnd) { + // Attach accessible document to the emulated native window + ::SetPropW(hWnd, kPropNameDocAccParent, (HANDLE)this); + SetEmulatedWindowHandle(hWnd); + } + } + Unused << SendParentCOMProxy(holder, reinterpret_cast( + mEmulatedWindowHandle)); +} + +void +DocAccessibleParent::SetEmulatedWindowHandle(HWND aWindowHandle) +{ + if (!aWindowHandle && mEmulatedWindowHandle && IsTopLevel()) { + ::DestroyWindow(mEmulatedWindowHandle); + } + mEmulatedWindowHandle = aWindowHandle; } mozilla::ipc::IPCResult diff --git a/accessible/ipc/DocAccessibleParent.h b/accessible/ipc/DocAccessibleParent.h index c617a691f963..59c7ec934199 100644 --- a/accessible/ipc/DocAccessibleParent.h +++ b/accessible/ipc/DocAccessibleParent.h @@ -30,6 +30,9 @@ public: DocAccessibleParent() : ProxyAccessible(this), mParentDoc(nullptr), mTopLevel(false), mShutdown(false) +#if defined(XP_WIN) + , mEmulatedWindowHandle(nullptr) +#endif // defined(XP_WIN) { MOZ_COUNT_CTOR_INHERITED(DocAccessibleParent, ProxyAccessible); } ~DocAccessibleParent() { @@ -151,6 +154,13 @@ public: virtual mozilla::ipc::IPCResult RecvGetWindowedPluginIAccessible( const WindowsHandle& aHwnd, IAccessibleHolder* aPluginCOMProxy) override; + + /** + * Set emulated native window handle for a document. + * @param aWindowHandle emulated native window handle + */ + void SetEmulatedWindowHandle(HWND aWindowHandle); + HWND GetEmulatedWindowHandle() const { return mEmulatedWindowHandle; } #endif private: @@ -187,6 +197,11 @@ private: nsTArray mChildDocs; DocAccessibleParent* mParentDoc; +#if defined(XP_WIN) + // The handle associated with the emulated window that contains this document + HWND mEmulatedWindowHandle; +#endif + /* * Conceptually this is a map from IDs to proxies, but we store the ID in the * proxy object so we can't use a real map. diff --git a/accessible/ipc/win/DocAccessibleChild.cpp b/accessible/ipc/win/DocAccessibleChild.cpp index 5506b472d925..dd924651bcb3 100644 --- a/accessible/ipc/win/DocAccessibleChild.cpp +++ b/accessible/ipc/win/DocAccessibleChild.cpp @@ -18,6 +18,7 @@ static StaticAutoPtr sPlatformChild; DocAccessibleChild::DocAccessibleChild(DocAccessible* aDoc) : DocAccessibleChildBase(aDoc) + , mEmulatedWindowHandle(nullptr) , mIsRemoteConstructed(false) { MOZ_COUNT_CTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase); @@ -45,11 +46,13 @@ DocAccessibleChild::Shutdown() } ipc::IPCResult -DocAccessibleChild::RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy) +DocAccessibleChild::RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy, + const WindowsHandle& aEmulatedWindowHandle) { MOZ_ASSERT(!mParentProxy && !aParentCOMProxy.IsNull()); mParentProxy.reset(const_cast(aParentCOMProxy).Release()); SetConstructedInParentProcess(); + mEmulatedWindowHandle = reinterpret_cast(aEmulatedWindowHandle); for (uint32_t i = 0, l = mDeferredEvents.Length(); i < l; ++i) { mDeferredEvents[i]->Dispatch(); diff --git a/accessible/ipc/win/DocAccessibleChild.h b/accessible/ipc/win/DocAccessibleChild.h index 93c15a71ffcf..877ed4cd2d3f 100644 --- a/accessible/ipc/win/DocAccessibleChild.h +++ b/accessible/ipc/win/DocAccessibleChild.h @@ -28,7 +28,10 @@ public: virtual void Shutdown() override; virtual ipc::IPCResult - RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy) override; + RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy, + const WindowsHandle& aEmulatedWindowHandle) override; + + HWND GetEmulatedWindowHandle() const { return mEmulatedWindowHandle; } IAccessible* GetParentIAccessible() const { return mParentProxy.get(); } @@ -310,6 +313,7 @@ private: bool mIsRemoteConstructed; mscom::ProxyUniquePtr mParentProxy; nsTArray> mDeferredEvents; + HWND mEmulatedWindowHandle; }; } // namespace a11y diff --git a/accessible/ipc/win/PDocAccessible.ipdl b/accessible/ipc/win/PDocAccessible.ipdl index 3389abd23467..13032d6bf362 100644 --- a/accessible/ipc/win/PDocAccessible.ipdl +++ b/accessible/ipc/win/PDocAccessible.ipdl @@ -66,7 +66,8 @@ parent: returns (IAccessibleHolder aPluginCOMProxy); child: - async ParentCOMProxy(IAccessibleHolder aParentCOMProxy); + async ParentCOMProxy(IAccessibleHolder aParentCOMProxy, + WindowsHandle aEmulatedWindowHandle); async __delete__(); }; diff --git a/accessible/windows/msaa/DocAccessibleWrap.cpp b/accessible/windows/msaa/DocAccessibleWrap.cpp index ef46cc445c80..621c6c68c1ad 100644 --- a/accessible/windows/msaa/DocAccessibleWrap.cpp +++ b/accessible/windows/msaa/DocAccessibleWrap.cpp @@ -120,6 +120,11 @@ DocAccessibleWrap::GetNativeWindow() const { if (XRE_IsContentProcess()) { DocAccessibleChild* ipcDoc = IPCDoc(); + HWND hWnd = ipcDoc->GetEmulatedWindowHandle(); + if (hWnd) { + return hWnd; + } + auto tab = static_cast(ipcDoc->Manager()); MOZ_ASSERT(tab); return reinterpret_cast(tab->GetNativeWindowHandle()); diff --git a/accessible/windows/msaa/Platform.cpp b/accessible/windows/msaa/Platform.cpp index dc6acd3ad6fd..ea6cec4359d7 100644 --- a/accessible/windows/msaa/Platform.cpp +++ b/accessible/windows/msaa/Platform.cpp @@ -85,6 +85,10 @@ a11y::ProxyDestroyed(ProxyAccessible* aProxy) if (!wrapper) return; + if (aProxy->IsDoc() && nsWinUtils::IsWindowEmulationStarted()) { + aProxy->AsDoc()->SetEmulatedWindowHandle(nullptr); + } + wrapper->Shutdown(); aProxy->SetWrapper(0); wrapper->Release(); diff --git a/accessible/windows/msaa/moz.build b/accessible/windows/msaa/moz.build index 4d716e4552a7..2886aff01a7f 100644 --- a/accessible/windows/msaa/moz.build +++ b/accessible/windows/msaa/moz.build @@ -14,6 +14,7 @@ EXPORTS.mozilla.a11y += [ 'HyperTextAccessibleWrap.h', 'IDSet.h', 'MsaaIdGenerator.h', + 'nsWinUtils.h', ] UNIFIED_SOURCES += [ diff --git a/accessible/windows/msaa/nsWinUtils.cpp b/accessible/windows/msaa/nsWinUtils.cpp index b49cd0263842..2ee162937151 100644 --- a/accessible/windows/msaa/nsWinUtils.cpp +++ b/accessible/windows/msaa/nsWinUtils.cpp @@ -12,6 +12,7 @@ #include "nsAccessibilityService.h" #include "nsCoreUtils.h" +#include "mozilla/a11y/DocAccessibleParent.h" #include "mozilla/Preferences.h" #include "nsArrayUtils.h" #include "nsIArray.h" @@ -20,6 +21,7 @@ #include "nsIDocShellTreeItem.h" #include "mozilla/dom/Element.h" #include "nsXULAppAPI.h" +#include "ProxyWrappers.h" using namespace mozilla; using namespace mozilla::a11y; @@ -153,18 +155,25 @@ WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) // for details). int32_t objId = static_cast(lParam); if (objId == OBJID_CLIENT) { + IAccessible* msaaAccessible = nullptr; DocAccessible* document = reinterpret_cast(::GetPropW(hWnd, kPropNameDocAcc)); if (document) { - IAccessible* msaaAccessible = nullptr; document->GetNativeInterface((void**)&msaaAccessible); // does an addref - if (msaaAccessible) { - LRESULT result = ::LresultFromObject(IID_IAccessible, wParam, - msaaAccessible); // does an addref - msaaAccessible->Release(); // release extra addref - return result; + } else { + DocAccessibleParent* docParent = static_cast( + ::GetPropW(hWnd, kPropNameDocAccParent)); + if (docParent) { + auto wrapper = WrapperFor(docParent); + wrapper->GetNativeInterface((void**)&msaaAccessible); // does an addref } } + if (msaaAccessible) { + LRESULT result = ::LresultFromObject(IID_IAccessible, wParam, + msaaAccessible); // does an addref + msaaAccessible->Release(); // release extra addref + return result; + } } return 0; } diff --git a/accessible/windows/msaa/nsWinUtils.h b/accessible/windows/msaa/nsWinUtils.h index 55089e722b3e..55ff21a2636a 100644 --- a/accessible/windows/msaa/nsWinUtils.h +++ b/accessible/windows/msaa/nsWinUtils.h @@ -23,6 +23,7 @@ class DocAccessible; const LPCWSTR kClassNameRoot = L"MozillaUIWindowClass"; const LPCWSTR kClassNameTabContent = L"MozillaContentWindowClass"; const LPCWSTR kPropNameDocAcc = L"MozDocAccessible"; +const LPCWSTR kPropNameDocAccParent = L"MozDocAccessibleParent"; class nsWinUtils { diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 3e83695e729a..32cb5596bd13 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -102,6 +102,7 @@ #if defined(XP_WIN) && defined(ACCESSIBILITY) #include "mozilla/a11y/AccessibleWrap.h" +#include "mozilla/a11y/nsWinUtils.h" #endif using namespace mozilla::dom; @@ -269,6 +270,16 @@ TabParent::SetOwnerElement(Element* aElement) reinterpret_cast(widget->GetNativeData(NS_NATIVE_WINDOW)); } Unused << SendUpdateNativeWindowHandle(newWindowHandle); + a11y::DocAccessibleParent* doc = GetTopLevelDocAccessible(); + if (doc) { + HWND hWnd = reinterpret_cast(doc->GetEmulatedWindowHandle()); + if (hWnd) { + HWND parentHwnd = reinterpret_cast(newWindowHandle); + if (parentHwnd != ::GetParent(hWnd)) { + ::SetParent(hWnd, parentHwnd); + } + } + } } #endif @@ -921,6 +932,9 @@ TabParent::RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc, MOZ_ASSERT(aDocCOMProxy.IsNull()); if (added) { a11y::WrapperFor(doc)->SetID(aMsaaID); + if (a11y::nsWinUtils::IsWindowEmulationStarted()) { + doc->SetEmulatedWindowHandle(parentDoc->GetEmulatedWindowHandle()); + } } #endif if (!added) {