diff --git a/accessible/src/msaa/EnumVariant.cpp b/accessible/src/msaa/EnumVariant.cpp new file mode 100644 index 000000000000..64d544d5fd41 --- /dev/null +++ b/accessible/src/msaa/EnumVariant.cpp @@ -0,0 +1,146 @@ +/* -*- 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 "EnumVariant.h" + +using namespace mozilla; +using namespace mozilla::a11y; + +//////////////////////////////////////////////////////////////////////////////// +// ChildrenEnumVariant +//////////////////////////////////////////////////////////////////////////////// + +STDMETHODIMP +ChildrenEnumVariant::QueryInterface(REFIID aIID, void** aObject) +{ +__try { + if (!aObject) + return E_INVALIDARG; + + if (aIID == IID_IEnumVARIANT) { + *aObject = static_cast(this); + AddRef(); + return S_OK; + } + + if (aIID == IID_IUnknown) { + *aObject = static_cast(this); + AddRef(); + return S_OK; + } + + // Redirect QI to IAccessible this enum was retrieved for. + if (!mAnchorAcc->IsDefunct()) + return mAnchorAcc->QueryInterface(aIID, aObject); + +} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), + GetExceptionInformation())) { } + + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE +ChildrenEnumVariant::AddRef() +{ + return ++mRefCnt; +} + +ULONG STDMETHODCALLTYPE +ChildrenEnumVariant::Release() +{ + mRefCnt--; + ULONG r = mRefCnt; + if (r == 0) + delete this; + + return r; +} + +STDMETHODIMP +ChildrenEnumVariant::Next(ULONG aCount, VARIANT FAR* aItems, + ULONG FAR* aCountFetched) +{ +__try { + if (!aItems || !aCountFetched) + return E_INVALIDARG; + + *aCountFetched = 0; + + if (mAnchorAcc->IsDefunct() || mAnchorAcc->GetChildAt(mCurIndex) != mCurAcc) + return CO_E_OBJNOTCONNECTED; + + ULONG countFetched = 0; + for (; mCurAcc && countFetched < aCount; countFetched++) { + VariantInit(aItems + countFetched); + aItems[countFetched].pdispVal = nsAccessibleWrap::NativeAccessible(mCurAcc); + aItems[countFetched].vt = VT_DISPATCH; + + mCurIndex++; + mCurAcc = mAnchorAcc->GetChildAt(mCurIndex); + } + + (*aCountFetched) = countFetched; + + return countFetched < aCount ? S_FALSE : S_OK; + +} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), + GetExceptionInformation())) { } + + return E_FAIL; +} + +STDMETHODIMP +ChildrenEnumVariant::Skip(ULONG aCount) +{ +__try { + if (mAnchorAcc->IsDefunct() || mAnchorAcc->GetChildAt(mCurIndex) != mCurAcc) + return CO_E_OBJNOTCONNECTED; + + mCurIndex += aCount; + mCurAcc = mAnchorAcc->GetChildAt(mCurIndex); + + return mCurAcc ? S_OK : S_FALSE; + +} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), + GetExceptionInformation())) { } + + return E_FAIL; +} + +STDMETHODIMP +ChildrenEnumVariant::Reset() +{ +__try { + if (mAnchorAcc->IsDefunct()) + return CO_E_OBJNOTCONNECTED; + + mCurIndex = 0; + mCurAcc = mAnchorAcc->GetChildAt(0); + + return S_OK; + +} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), + GetExceptionInformation())) { } + return E_FAIL; +} + +STDMETHODIMP +ChildrenEnumVariant::Clone(IEnumVARIANT** aEnumVariant) +{ +__try { + if (!aEnumVariant) + return E_INVALIDARG; + + *aEnumVariant = new ChildrenEnumVariant(*this); + (*aEnumVariant)->AddRef(); + + return S_OK; + +} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), + GetExceptionInformation())) { } + + return E_FAIL; +} diff --git a/accessible/src/msaa/EnumVariant.h b/accessible/src/msaa/EnumVariant.h new file mode 100644 index 000000000000..1a9528f28d96 --- /dev/null +++ b/accessible/src/msaa/EnumVariant.h @@ -0,0 +1,67 @@ +/* -*- 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_EnumVariant_h__ +#define mozilla_a11y_EnumVariant_h__ + +#include "nsAccessibleWrap.h" + +namespace mozilla { +namespace a11y { + +/** + * Used to fetch accessible children. + */ +class ChildrenEnumVariant MOZ_FINAL : public IEnumVARIANT +{ +public: + ChildrenEnumVariant(nsAccessibleWrap* aAnchor) : mAnchorAcc(aAnchor), + mCurAcc(mAnchorAcc->GetChildAt(0)), mCurIndex(0), mRefCnt(0) { } + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID aRefIID, + /* [annotation][iid_is][out] */ void** aObject); + + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); + + // IEnumVariant + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG aCount, + /* [length_is][size_is][out] */ VARIANT* aItems, + /* [out] */ ULONG* aCountFetched); + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG aCount); + + virtual HRESULT STDMETHODCALLTYPE Reset(); + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IEnumVARIANT** aEnumVaraint); + +private: + ChildrenEnumVariant() MOZ_DELETE; + ChildrenEnumVariant& operator =(const ChildrenEnumVariant&) MOZ_DELETE; + + ChildrenEnumVariant(const ChildrenEnumVariant& aEnumVariant) : + mAnchorAcc(aEnumVariant.mAnchorAcc), mCurAcc(aEnumVariant.mCurAcc), + mCurIndex(aEnumVariant.mCurIndex), mRefCnt(0) { } + virtual ~ChildrenEnumVariant() { } + +protected: + nsRefPtr mAnchorAcc; + nsAccessible* mCurAcc; + PRUint32 mCurIndex; + +private: + ULONG mRefCnt; +}; + +} // a11y namespace +} // mozilla namespace + +#endif diff --git a/accessible/src/msaa/Makefile.in b/accessible/src/msaa/Makefile.in index d24701dc8588..54793b00a791 100644 --- a/accessible/src/msaa/Makefile.in +++ b/accessible/src/msaa/Makefile.in @@ -29,18 +29,19 @@ CPPSRCS = \ nsHTMLImageAccessibleWrap.cpp \ nsHTMLTableAccessibleWrap.cpp \ nsWinUtils.cpp \ - ia2AccessibleAction.cpp \ - ia2AccessibleComponent.cpp \ - ia2AccessibleImage.cpp \ CAccessibleText.cpp \ CAccessibleEditableText.cpp \ CAccessibleHyperlink.cpp \ - ia2AccessibleHypertext.cpp \ - ia2AccessibleRelation.cpp \ CAccessibleTable.cpp \ CAccessibleTableCell.cpp \ CAccessibleValue.cpp \ Compatibility.cpp \ + EnumVariant.cpp \ + ia2AccessibleAction.cpp \ + ia2AccessibleComponent.cpp \ + ia2AccessibleImage.cpp \ + ia2AccessibleHypertext.cpp \ + ia2AccessibleRelation.cpp \ RootAccessibleWrap.cpp \ TextLeafAccessibleWrap.cpp \ $(NULL) diff --git a/accessible/src/msaa/nsAccessibleWrap.cpp b/accessible/src/msaa/nsAccessibleWrap.cpp index aa576cc66ba0..daea2d6c2bf3 100644 --- a/accessible/src/msaa/nsAccessibleWrap.cpp +++ b/accessible/src/msaa/nsAccessibleWrap.cpp @@ -6,6 +6,7 @@ #include "nsAccessibleWrap.h" #include "Compatibility.h" +#include "EnumVariant.h" #include "nsAccUtils.h" #include "nsCoreUtils.h" #include "nsWinUtils.h" @@ -64,22 +65,6 @@ static const PRInt32 kIEnumVariantDisconnected = -1; ITypeInfo* nsAccessibleWrap::gTypeInfo = NULL; -//----------------------------------------------------- -// construction -//----------------------------------------------------- -nsAccessibleWrap:: - nsAccessibleWrap(nsIContent* aContent, nsDocAccessible* aDoc) : - nsAccessible(aContent, aDoc), mEnumVARIANTPosition(0) -{ -} - -//----------------------------------------------------- -// destruction -//----------------------------------------------------- -nsAccessibleWrap::~nsAccessibleWrap() -{ -} - NS_IMPL_ISUPPORTS_INHERITED0(nsAccessibleWrap, nsAccessible); //----------------------------------------------------- @@ -95,10 +80,11 @@ __try { if (IID_IUnknown == iid || IID_IDispatch == iid || IID_IAccessible == iid) *ppv = static_cast(this); else if (IID_IEnumVARIANT == iid) { - long numChildren; - get_accChildCount(&numChildren); - if (numChildren > 0) // Don't support this interface for leaf elements - *ppv = static_cast(this); + // Don't support this interface for leaf elements. + if (!HasChildren() || nsAccUtils::MustPrune(this)) + return E_NOINTERFACE; + + *ppv = static_cast(new ChildrenEnumVariant(this)); } else if (IID_IServiceProvider == iid) *ppv = static_cast(this); else if (IID_IAccessible2 == iid && !Compatibility::IsIA2Off()) @@ -127,6 +113,7 @@ __try { (reinterpret_cast(*ppv))->AddRef(); } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { } + return S_OK; } @@ -998,91 +985,6 @@ STDMETHODIMP nsAccessibleWrap::put_accValue( return E_NOTIMPL; } -#include "mshtml.h" - -//////////////////////////////////////////////////////////////////////////////// -// nsAccessibleWrap. IEnumVariant - -STDMETHODIMP -nsAccessibleWrap::Next(ULONG aNumElementsRequested, VARIANT FAR* aPVar, - ULONG FAR* aNumElementsFetched) -{ - // Children already cached via QI to IEnumVARIANT -__try { - *aNumElementsFetched = 0; - - if (aNumElementsRequested <= 0 || !aPVar) - return E_INVALIDARG; - - if (mEnumVARIANTPosition == kIEnumVariantDisconnected) - return CO_E_OBJNOTCONNECTED; - - PRUint32 numElementsFetched = 0; - for (; numElementsFetched < aNumElementsRequested; - numElementsFetched++, mEnumVARIANTPosition++) { - - nsAccessible* accessible = GetChildAt(mEnumVARIANTPosition); - if (!accessible) - break; - - VariantInit(&aPVar[numElementsFetched]); - - aPVar[numElementsFetched].pdispVal = NativeAccessible(accessible); - aPVar[numElementsFetched].vt = VT_DISPATCH; - } - - (*aNumElementsFetched) = numElementsFetched; - - return numElementsFetched < aNumElementsRequested ? S_FALSE : S_OK; - -} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { } - return E_FAIL; -} - -STDMETHODIMP -nsAccessibleWrap::Skip(ULONG aNumElements) -{ -__try { - if (mEnumVARIANTPosition == kIEnumVariantDisconnected) - return CO_E_OBJNOTCONNECTED; - - mEnumVARIANTPosition += aNumElements; - - PRUint32 childCount = ChildCount(); - if (mEnumVARIANTPosition > static_cast(childCount)) - { - mEnumVARIANTPosition = childCount; - return S_FALSE; - } -} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { } - return NOERROR; -} - -STDMETHODIMP -nsAccessibleWrap::Reset(void) -{ - mEnumVARIANTPosition = 0; - return NOERROR; -} - -STDMETHODIMP -nsAccessibleWrap::Clone(IEnumVARIANT FAR* FAR* ppenum) -{ -__try { - *ppenum = nsnull; - - nsCOMPtr childArray; - nsresult rv = GetChildren(getter_AddRefs(childArray)); - - *ppenum = new AccessibleEnumerator(childArray); - if (!*ppenum) - return E_OUTOFMEMORY; - NS_ADDREF(*ppenum); - -} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { } - return NOERROR; -} - //////////////////////////////////////////////////////////////////////////////// // nsAccessibleWrap. IAccessible2 @@ -1610,11 +1512,6 @@ nsAccessibleWrap::FirePlatformEvent(AccEvent* aEvent) if (eventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED || eventType == nsIAccessibleEvent::EVENT_FOCUS) { UpdateSystemCaret(); - - } else if (eventType == nsIAccessibleEvent::EVENT_REORDER) { - // If the accessible children are changed then drop the IEnumVariant current - // position of the accessible. - UnattachIEnumVariant(); } PRInt32 childID = GetChildIDFor(accessible); // get the id for the accessible @@ -1782,13 +1679,6 @@ nsAccessibleWrap::NativeAccessible(nsIAccessible* aAccessible) return static_cast(msaaAccessible); } -void -nsAccessibleWrap::UnattachIEnumVariant() -{ - if (mEnumVARIANTPosition > 0) - mEnumVARIANTPosition = kIEnumVariantDisconnected; -} - nsAccessible* nsAccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild) { diff --git a/accessible/src/msaa/nsAccessibleWrap.h b/accessible/src/msaa/nsAccessibleWrap.h index 144fa6fa70cd..1bfc433f71a0 100644 --- a/accessible/src/msaa/nsAccessibleWrap.h +++ b/accessible/src/msaa/nsAccessibleWrap.h @@ -67,12 +67,12 @@ class nsAccessibleWrap : public nsAccessible, public ia2AccessibleComponent, public CAccessibleHyperlink, public CAccessibleValue, - public IAccessible2, - public IEnumVARIANT + public IAccessible2 { public: // construction, destruction - nsAccessibleWrap(nsIContent* aContent, nsDocAccessible* aDoc); - virtual ~nsAccessibleWrap(); + nsAccessibleWrap(nsIContent* aContent, nsDocAccessible* aDoc) : + nsAccessible(aContent, aDoc) { } + virtual ~nsAccessibleWrap() { } // nsISupports NS_DECL_ISUPPORTS_INHERITED @@ -235,25 +235,6 @@ public: // construction, destruction virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_attributes( /* [retval][out] */ BSTR *attributes); - public: // IEnumVariant - // If there are two clients using this at the same time, and they are - // each using a different mEnumVariant position it would be bad, because - // we have only 1 object and can only keep of mEnumVARIANT position once. - - virtual /* [local] */ HRESULT STDMETHODCALLTYPE Next( - /* [in] */ ULONG celt, - /* [length_is][size_is][out] */ VARIANT __RPC_FAR *rgVar, - /* [out] */ ULONG __RPC_FAR *pCeltFetched); - - virtual HRESULT STDMETHODCALLTYPE Skip( - /* [in] */ ULONG celt); - - virtual HRESULT STDMETHODCALLTYPE Reset( void); - - virtual HRESULT STDMETHODCALLTYPE Clone( - /* [out] */ IEnumVARIANT __RPC_FAR *__RPC_FAR *ppEnum); - - // IDispatch (support of scripting languages like VB) virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo); @@ -300,21 +281,9 @@ public: // construction, destruction static IDispatch *NativeAccessible(nsIAccessible *aXPAccessible); - /** - * Drops the IEnumVariant current position so that navigation methods - * Next() and Skip() doesn't work until Reset() method is called. The method - * is used when children of the accessible are changed. - */ - void UnattachIEnumVariant(); - protected: virtual nsresult FirePlatformEvent(AccEvent* aEvent); - // mEnumVARIANTPosition not the current accessible's position, but a "cursor" of - // where we are in the current list of children, with respect to - // nsIEnumVariant::Reset(), Skip() and Next(). - PRInt32 mEnumVARIANTPosition; - /** * Creates ITypeInfo for LIBID_Accessibility if it's needed and returns it. */