mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 754879 - reorg IEnumVariant implementation to traverse accessible children, r=tbsaunde, f=marcoz
This commit is contained in:
parent
c2094d8c7f
commit
346d10aff6
146
accessible/src/msaa/EnumVariant.cpp
Normal file
146
accessible/src/msaa/EnumVariant.cpp
Normal file
@ -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<IEnumVARIANT*>(this);
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (aIID == IID_IUnknown) {
|
||||
*aObject = static_cast<IUnknown*>(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;
|
||||
}
|
67
accessible/src/msaa/EnumVariant.h
Normal file
67
accessible/src/msaa/EnumVariant.h
Normal file
@ -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<nsAccessibleWrap> mAnchorAcc;
|
||||
nsAccessible* mCurAcc;
|
||||
PRUint32 mCurIndex;
|
||||
|
||||
private:
|
||||
ULONG mRefCnt;
|
||||
};
|
||||
|
||||
} // a11y namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif
|
@ -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)
|
||||
|
@ -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<IAccessible*>(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<IEnumVARIANT*>(this);
|
||||
// Don't support this interface for leaf elements.
|
||||
if (!HasChildren() || nsAccUtils::MustPrune(this))
|
||||
return E_NOINTERFACE;
|
||||
|
||||
*ppv = static_cast<IEnumVARIANT*>(new ChildrenEnumVariant(this));
|
||||
} else if (IID_IServiceProvider == iid)
|
||||
*ppv = static_cast<IServiceProvider*>(this);
|
||||
else if (IID_IAccessible2 == iid && !Compatibility::IsIA2Off())
|
||||
@ -127,6 +113,7 @@ __try {
|
||||
|
||||
(reinterpret_cast<IUnknown*>(*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<PRInt32>(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<nsIArray> 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<IDispatch*>(msaaAccessible);
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibleWrap::UnattachIEnumVariant()
|
||||
{
|
||||
if (mEnumVARIANTPosition > 0)
|
||||
mEnumVARIANTPosition = kIEnumVariantDisconnected;
|
||||
}
|
||||
|
||||
nsAccessible*
|
||||
nsAccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
|
||||
{
|
||||
|
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user