Bug 1274381 - scope accessible elements search to inserted nodes, r=yzen, f=marcoz

This commit is contained in:
Alexander Surkov 2016-06-21 10:53:06 -04:00
parent 410f3e5382
commit d219d06d6d
3 changed files with 52 additions and 30 deletions

View File

@ -57,14 +57,29 @@ TreeWalker::~TreeWalker()
MOZ_COUNT_DTOR(TreeWalker);
}
Accessible*
TreeWalker::Scope(nsIContent* aAnchorNode)
{
Reset();
mAnchorNode = aAnchorNode;
bool skipSubtree = false;
Accessible* acc = AccessibleFor(aAnchorNode, 0, &skipSubtree);
if (acc) {
mPhase = eAtEnd;
return acc;
}
return skipSubtree ? nullptr : Next();
}
bool
TreeWalker::Seek(nsIContent* aChildNode)
{
MOZ_ASSERT(aChildNode, "Child cannot be null");
mPhase = eAtStart;
mStateStack.Clear();
mARIAOwnsIdx = 0;
Reset();
nsIContent* childNode = nullptr;
nsINode* parentNode = aChildNode;
@ -110,7 +125,7 @@ TreeWalker::Seek(nsIContent* aChildNode)
}
Accessible*
TreeWalker::Next(nsIContent* aStopNode)
TreeWalker::Next()
{
if (mStateStack.IsEmpty()) {
if (mPhase == eAtEnd) {
@ -139,10 +154,6 @@ TreeWalker::Next(nsIContent* aStopNode)
dom::AllChildrenIterator* top = &mStateStack[mStateStack.Length() - 1];
while (top) {
if (aStopNode && top->Get() == aStopNode) {
return nullptr;
}
while (nsIContent* childNode = top->GetNextChild()) {
bool skipSubtree = false;
Accessible* child = AccessibleFor(childNode, mFlags, &skipSubtree);
@ -150,14 +161,10 @@ TreeWalker::Next(nsIContent* aStopNode)
return child;
}
// Walk down the subtree if allowed, otherwise check if we have reached
// a stop node.
// Walk down the subtree if allowed.
if (!skipSubtree && childNode->IsElement()) {
top = PushState(childNode, true);
}
else if (childNode == aStopNode) {
return nullptr;
}
}
top = PopState();
}
@ -171,7 +178,7 @@ TreeWalker::Next(nsIContent* aStopNode)
mPhase = eAtEnd;
return nullptr;
}
return Next(aStopNode);
return Next();
}
nsINode* contextNode = mContext->GetNode();
@ -184,7 +191,7 @@ TreeWalker::Next(nsIContent* aStopNode)
top = PushState(parent, true);
if (top->Seek(mAnchorNode)) {
mAnchorNode = parent;
return Next(aStopNode);
return Next();
}
// XXX We really should never get here, it means we're trying to find an
@ -194,7 +201,7 @@ TreeWalker::Next(nsIContent* aStopNode)
mAnchorNode = parent;
}
return Next(aStopNode);
return Next();
}
Accessible*

View File

@ -50,8 +50,23 @@ public:
~TreeWalker();
/**
* Clears the tree walker state and resets it to the given child within
* the anchor.
* Resets the walker state, and sets the given node as an anchor. Returns a
* first accessible element within the node including the node itself.
*/
Accessible* Scope(nsIContent* aAnchorNode);
/**
* Resets the walker state.
*/
void Reset()
{
mPhase = eAtStart;
mStateStack.Clear();
mARIAOwnsIdx = 0;
}
/**
* Sets the walker state to the given child node if it's within the anchor.
*/
bool Seek(nsIContent* aChildNode);
@ -62,7 +77,7 @@ public:
* rejected during tree creation then the caller should be unbind it
* from the document.
*/
Accessible* Next(nsIContent* aStopNode = nullptr);
Accessible* Next();
Accessible* Prev();
Accessible* Context() const { return mContext; }

View File

@ -1663,7 +1663,7 @@ public:
InsertIterator(Accessible* aContext,
const nsTArray<nsCOMPtr<nsIContent> >* aNodes) :
mChild(nullptr), mChildBefore(nullptr), mWalker(aContext),
mStopNode(nullptr), mNodes(aNodes), mNodesIdx(0)
mNodes(aNodes), mNodesIdx(0)
{
MOZ_ASSERT(aContext, "No context");
MOZ_ASSERT(aNodes, "No nodes to search for accessible elements");
@ -1685,7 +1685,6 @@ private:
Accessible* mChild;
Accessible* mChildBefore;
TreeWalker mWalker;
nsIContent* mStopNode;
const nsTArray<nsCOMPtr<nsIContent> >* mNodes;
uint32_t mNodesIdx;
@ -1695,7 +1694,7 @@ bool
InsertIterator::Next()
{
if (mNodesIdx > 0) {
Accessible* nextChild = mWalker.Next(mStopNode);
Accessible* nextChild = mWalker.Next();
if (nextChild) {
mChildBefore = mChild;
mChild = nextChild;
@ -1737,20 +1736,21 @@ InsertIterator::Next()
// If inserted nodes are siblings then just move the walker next.
if (prevNode && prevNode->GetNextSibling() == node) {
mStopNode = node;
Accessible* nextChild = mWalker.Next(mStopNode);
Accessible* nextChild = mWalker.Scope(node);
if (nextChild) {
mChildBefore = mChild;
mChild = nextChild;
return true;
}
}
else if (mWalker.Seek(node)) {
mStopNode = node;
mChildBefore = mWalker.Prev();
mChild = mWalker.Next(mStopNode);
if (mChild) {
return true;
else {
TreeWalker finder(container);
if (finder.Seek(node)) {
mChild = mWalker.Scope(node);
if (mChild) {
mChildBefore = finder.Prev();
return true;
}
}
}
}