Bug 530081 - Clean up our tree walker , r=marcoz, davidb

--HG--
rename : accessible/src/base/nsAccessibleTreeWalker.cpp => accessible/src/base/nsAccTreeWalker.cpp
rename : accessible/src/base/nsAccessibleTreeWalker.h => accessible/src/base/nsAccTreeWalker.h
This commit is contained in:
Alexander Surkov 2010-02-20 16:55:04 -08:00
Родитель 70f9774516
Коммит 2758ec302f
19 изменённых файлов: 384 добавлений и 500 удалений

Просмотреть файл

@ -61,7 +61,7 @@ CPPSRCS = \
nsAccessibilityService.cpp \
nsAccessible.cpp \
nsAccessibleRelation.cpp \
nsAccessibleTreeWalker.cpp \
nsAccTreeWalker.cpp \
nsBaseWidgetAccessible.cpp \
nsEventShell.cpp \
nsFormControlAccessible.cpp \

Просмотреть файл

@ -0,0 +1,155 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Leventhal <aaronleventhal@moonset.net> (original author)
* Alexander Surkov <surkov.alexander@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsAccTreeWalker.h"
#include "nsAccessibilityService.h"
////////////////////////////////////////////////////////////////////////////////
// WalkState
////////////////////////////////////////////////////////////////////////////////
struct WalkState
{
WalkState(nsIContent *aContent) :
content(aContent), childIdx(0), prevState(nsnull) {}
nsCOMPtr<nsIContent> content;
nsCOMPtr<nsINodeList> childList;
PRUint32 childIdx;
WalkState *prevState;
};
////////////////////////////////////////////////////////////////////////////////
// nsAccTreeWalker
////////////////////////////////////////////////////////////////////////////////
nsAccTreeWalker::
nsAccTreeWalker(nsIWeakReference* aShell, nsIContent* aContent,
PRBool aWalkAnonContent) :
mWeakShell(aShell), mState(nsnull)
{
NS_ASSERTION(aContent, "No node for the accessible tree walker!");
if (aContent)
mState = new WalkState(aContent);
mChildType = aWalkAnonContent ? nsIContent::eAllChildren :
nsIContent::eAllButXBL;
MOZ_COUNT_CTOR(nsAccTreeWalker);
}
nsAccTreeWalker::~nsAccTreeWalker()
{
// Clear state stack from memory
while (mState)
PopState();
MOZ_COUNT_DTOR(nsAccTreeWalker);
}
////////////////////////////////////////////////////////////////////////////////
// nsAccTreeWalker: private
already_AddRefed<nsIAccessible>
nsAccTreeWalker::GetNextChildInternal(PRBool aNoWalkUp)
{
if (!mState || !mState->content)
return nsnull;
if (!mState->childList)
mState->childList = mState->content->GetChildren(mChildType);
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
PRUint32 length = 0;
if (mState->childList)
mState->childList->GetLength(&length);
while (mState->childIdx < length;) {
nsIContent* childNode = mState->childList->GetNodeAt(mState->childIdx);
mState->childIdx++;
PRBool isHidden = PR_FALSE;
nsCOMPtr<nsIAccessible> accessible;
nsCOMPtr<nsIDOMNode> childDOMNode(do_QueryInterface(childNode));
GetAccService()->GetAccessible(childDOMNode, presShell, mWeakShell, nsnull,
&isHidden, getter_AddRefs(accessible));
if (accessible)
return accessible.forget();
// Walk down into subtree to find accessibles.
if (!isHidden) {
if (!PushState(childNode))
break;
accessible = GetNextChildInternal(PR_TRUE);
if (accessible)
return accessible.forget();
}
}
// No more children, get back to the parent.
PopState();
return aNoWalkUp ? nsnull : GetNextChildInternal(PR_FALSE);
}
void
nsAccTreeWalker::PopState()
{
WalkState* prevToLastState = mState->prevState;
delete mState;
mState = prevToLastState;
}
PRBool
nsAccTreeWalker::PushState(nsIContent* aContent)
{
WalkState* nextToLastState = new WalkState(aContent);
if (!nextToLastState)
return PR_FALSE;
nextToLastState->prevState = mState;
mState = nextToLastState;
return PR_TRUE;
}

Просмотреть файл

@ -0,0 +1,97 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Leventhal <aaronleventhal@moonset.net> (original author)
* Alexander Surkov <surkov.alexander@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _nsAccTreeWalker_H_
#define _nsAccTreeWalker_H_
#include "nsIAccessible.h"
#include "nsIContent.h"
#include "nsIWeakReference.h"
struct WalkState;
/**
* This class is used to walk the DOM tree to create accessible tree.
*/
class nsAccTreeWalker
{
public:
nsAccTreeWalker(nsIWeakReference *aShell, nsIContent *aNode,
PRBool aWalkAnonymousContent);
virtual ~nsAccTreeWalker();
/**
* Return the next child accessible.
*/
already_AddRefed<nsIAccessible> GetNextChild()
{
return GetNextChildInternal(PR_FALSE);
}
private:
/**
* Return the next child accessible.
*
* @param aNoWalkUp [in] specifies the walk direction, true means we
* shouldn't go up through the tree if we failed find
* accessible children.
*/
already_AddRefed<nsIAccessible>
GetNextChildInternal(PRBool aNoWalkUp = PR_FALSE);
/**
* Create new state for the given node and push it on top of stack.
*
* @note State stack is used to navigate up/down the DOM subtree during
* accessible children search.
*/
PRBool PushState(nsIContent *aNode);
/**
* Pop state from stack.
*/
void PopState();
nsCOMPtr<nsIWeakReference> mWeakShell;
PRInt32 mChildType;
WalkState* mState;
};
#endif

Просмотреть файл

@ -47,7 +47,7 @@
#include "nsHTMLTableAccessible.h"
#include "nsDocAccessible.h"
#include "nsAccessibilityAtoms.h"
#include "nsAccessibleTreeWalker.h"
#include "nsAccTreeWalker.h"
#include "nsAccessible.h"
#include "nsARIAMap.h"
#include "nsXULTreeGridAccessible.h"
@ -362,14 +362,12 @@ nsAccUtils::HasAccessibleChildren(nsIDOMNode *aNode)
nsIFrame *frame = content->GetPrimaryFrame();
if (!frame)
return PR_FALSE;
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
nsAccessibleTreeWalker walker(weakShell, aNode, PR_FALSE);
nsAccTreeWalker walker(weakShell, content, PR_FALSE);
walker.mState.frame = frame;
walker.GetFirstChild();
return walker.mState.accessible ? PR_TRUE : PR_FALSE;
nsCOMPtr<nsIAccessible> accessible = walker.GetNextChild();
return accessible ? PR_TRUE : PR_FALSE;
}
already_AddRefed<nsIAccessible>

Просмотреть файл

@ -44,7 +44,7 @@
#include "nsIAccessibleDocument.h"
#include "nsIAccessibleHyperText.h"
#include "nsIXBLAccessible.h"
#include "nsAccessibleTreeWalker.h"
#include "nsAccTreeWalker.h"
#include "nsIDOMElement.h"
#include "nsIDOMDocument.h"
@ -2987,25 +2987,17 @@ nsAccessible::GetCachedFirstChild()
void
nsAccessible::CacheChildren()
{
PRBool allowsAnonChildren = GetAllowsAnonChildAccessibles();
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, allowsAnonChildren);
nsAccTreeWalker walker(mWeakShell, nsCoreUtils::GetRoleContent(mDOMNode),
GetAllowsAnonChildAccessibles());
// Seed the frame hint early while we're still on a container node.
// This is better than doing the GetPrimaryFrameFor() later on
// a text node, because text nodes aren't in the frame map.
// XXXbz is this code still needed?
walker.mState.frame = GetFrame();
walker.GetFirstChild();
while (walker.mState.accessible) {
nsCOMPtr<nsIAccessible> child;
while ((child = walker.GetNextChild())) {
nsRefPtr<nsAccessible> acc =
nsAccUtils::QueryObject<nsAccessible>(walker.mState.accessible);
nsAccUtils::QueryObject<nsAccessible>(child);
mChildren.AppendElement(acc);
acc->SetParent(this);
walker.GetNextSibling();
}
}

Просмотреть файл

@ -1,306 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Original Author: Aaron Leventhal (aaronl@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsAccessibleTreeWalker.h"
#include "nsAccessibilityAtoms.h"
#include "nsAccessNode.h"
#include "nsIAnonymousContentCreator.h"
#include "nsIServiceManager.h"
#include "nsIContent.h"
#include "nsIDOMXULElement.h"
#include "nsIPresShell.h"
#include "nsAccessibilityService.h"
#include "nsWeakReference.h"
nsAccessibleTreeWalker::nsAccessibleTreeWalker(nsIWeakReference* aPresShell, nsIDOMNode* aNode, PRBool aWalkAnonContent):
mWeakShell(aPresShell),
mWalkAnonContent(aWalkAnonContent)
{
mState.domNode = aNode;
mState.prevState = nsnull;
mState.siblingIndex = eSiblingsUninitialized;
mState.siblingList = nsnull;
mState.isHidden = false;
MOZ_COUNT_CTOR(nsAccessibleTreeWalker);
}
nsAccessibleTreeWalker::~nsAccessibleTreeWalker()
{
// Clear state stack from memory
while (NS_SUCCEEDED(PopState()))
/* do nothing */ ;
MOZ_COUNT_DTOR(nsAccessibleTreeWalker);
}
void nsAccessibleTreeWalker::GetKids(nsIDOMNode *aParentNode)
{
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(aParentNode));
if (!parentContent || !parentContent->IsHTML()) {
mState.frame = nsnull; // Don't walk frames in non-HTML content, just walk the DOM.
}
WalkFrames();
// Walk frames? UpdateFrame() sets this when it sees anonymous frames
if (mState.siblingIndex == eSiblingsWalkFrames) {
return;
}
// Walk anonymous content? Not currently used for HTML -- anonymous content there uses frame walking
mState.siblingIndex = 0; // Indicates our index into the sibling list
if (parentContent) {
if (mWalkAnonContent) {
// Walk anonymous content
nsIDocument* doc = parentContent->GetOwnerDoc();
if (doc) {
// returns null if no anon nodes
doc->GetXBLChildNodesFor(parentContent,
getter_AddRefs(mState.siblingList));
}
}
if (!mState.siblingList) {
// Walk normal DOM. Just use nsIContent -- it doesn't require
// the mallocs that GetChildNodes() needs
//aParentNode->GetChildNodes(getter_AddRefs(mState.siblingList));
mState.parentContent = parentContent;
mState.domNode = do_QueryInterface(parentContent->GetChildAt(0 /* 0 == mState.siblingIndex */));
return;
}
}
else {
// We're on document node, that's why we could not QI to nsIContent.
// So, use nsIDOMNodeList method to walk content.
aParentNode->GetChildNodes(getter_AddRefs(mState.siblingList));
if (!mState.siblingList) {
return;
}
}
mState.siblingList->Item(0 /* 0 == mState.siblingIndex */, getter_AddRefs(mState.domNode));
}
NS_IMETHODIMP nsAccessibleTreeWalker::PopState()
{
nsIFrame *frameParent =
mState.frame.GetFrame() ? mState.frame.GetFrame()->GetParent() : nsnull;
if (mState.prevState) {
WalkState *toBeDeleted = mState.prevState;
mState = *mState.prevState; // deep copy
mState.isHidden = PR_FALSE; // If we were in a child, the parent wasn't hidden
if (!mState.frame.GetFrame()) {
mState.frame = frameParent;
}
delete toBeDeleted;
return NS_OK;
}
ClearState();
mState.frame = frameParent;
mState.isHidden = PR_FALSE;
return NS_ERROR_FAILURE;
}
void nsAccessibleTreeWalker::ClearState()
{
mState.siblingList = nsnull;
mState.parentContent = nsnull;
mState.accessible = nsnull;
mState.domNode = nsnull;
mState.siblingIndex = eSiblingsUninitialized;
}
NS_IMETHODIMP nsAccessibleTreeWalker::PushState()
{
// Duplicate mState and put right before end; reset mState; make mState the new end of the stack
WalkState* nextToLastState= new WalkState();
if (!nextToLastState)
return NS_ERROR_OUT_OF_MEMORY;
*nextToLastState = mState; // Deep copy - copy contents of struct to new state that will be added to end of our stack
ClearState();
mState.prevState = nextToLastState; // Link to previous state
return NS_OK;
}
void nsAccessibleTreeWalker::GetNextDOMNode()
{
// Get next DOM node and its frame.
if (mState.parentContent) {
mState.domNode =
do_QueryInterface(mState.parentContent->GetChildAt(++mState.siblingIndex));
} else if (mState.siblingIndex == eSiblingsWalkFrames) {
if (mState.frame.IsAlive()) {
mState.frame = mState.frame.GetFrame()->GetNextSibling();
if (mState.frame.IsAlive()) {
mState.domNode = do_QueryInterface(mState.frame.GetFrame()->GetContent());
return;
}
}
mState.domNode = nsnull;
return;
} else {
mState.siblingList->Item(++mState.siblingIndex,
getter_AddRefs(mState.domNode));
}
// Update the frame.
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
NS_ASSERTION(presShell, "Huh? No presshell?");
if (!presShell)
return;
nsCOMPtr<nsIContent> content = do_QueryInterface(mState.domNode);
if (content)
mState.frame = presShell->GetRealPrimaryFrameFor(content);
else
mState.frame = presShell->GetRootFrame();
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetNextSibling()
{
// Make sure mState.prevState and mState.siblingIndex are initialized so we can walk forward
NS_ASSERTION(mState.prevState && mState.siblingIndex != eSiblingsUninitialized,
"Error - GetNextSibling() only works after a GetFirstChild(), so we must have a prevState.");
mState.accessible = nsnull;
while (PR_TRUE) {
// Get next frame
GetNextDOMNode();
if (!mState.domNode) { // Done with current siblings
PopState(); // Use parent - go up in stack. Can always pop state because we have to start with a GetFirstChild().
if (!mState.prevState) {
mState.accessible = nsnull;
break; // Back to original accessible that we did GetFirstChild() from
}
}
else if ((mState.domNode != mState.prevState->domNode && GetAccessible()) ||
NS_SUCCEEDED(GetFirstChild())) {
return NS_OK; // if next is accessible, use it
}
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetFirstChild()
{
mState.accessible = nsnull;
if (mState.isHidden || !mState.domNode) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMNode> parent(mState.domNode);
PushState();
GetKids(parent); // Side effects change our state (mState)
// Recursive loop: depth first search for first accessible child
while (mState.domNode) {
if ((mState.domNode != parent && GetAccessible()) || NS_SUCCEEDED(GetFirstChild()))
return NS_OK;
GetNextDOMNode();
}
PopState(); // Return to previous state
return NS_ERROR_FAILURE;
}
void
nsAccessibleTreeWalker::WalkFrames()
{
nsIFrame *curFrame = mState.frame.GetFrame();
if (!curFrame) {
return;
}
// If the frame implements nsIAnonymousContentCreator interface then go down
// through the frames and obtain anonymous nodes for them.
nsIAnonymousContentCreator* creator = do_QueryFrame(curFrame);
nsIFrame *child = curFrame->GetFirstChild(nsnull);
if (creator && child && mState.siblingIndex < 0) {
mState.frame = child;
mState.domNode = do_QueryInterface(child->GetContent());
mState.siblingIndex = eSiblingsWalkFrames;
}
// temporary workaround for Bug 359210. We never want to walk frames.
// Aaron Leventhal will refix :before and :after content later without walking frames.
#if 0
if (mState.frame && mState.siblingIndex < 0) {
// Container frames can contain generated content frames from
// :before and :after style rules, so we walk their frame trees
// instead of content trees
// XXX Walking the frame tree doesn't get us Aural CSS nodes, e.g.
// @media screen { display: none; }
// Asking the style system might be better (with ProbePseudoStyleFor(),
// except that we need to ask only for those display types that support
// :before and :after (which roughly means non-replaced elements)
// Here's some code to see if there is an :after rule for an element
// nsRefPtr<nsStyleContext> pseudoContext;
// nsStyleContext *styleContext = primaryFrame->GetStyleContext();
// if (aContent) {
// pseudoContext = presContext->StyleSet()->
// ProbePseudoStyleFor(content, nsAccessibilityAtoms::after, aStyleContext);
mState.domNode = do_QueryInterface(mState.frame->GetContent());
mState.siblingIndex = eSiblingsWalkFrames;
}
#endif
}
/**
* If the DOM node's frame has an accessible or the DOMNode
* itself implements nsIAccessible return it.
*/
PRBool nsAccessibleTreeWalker::GetAccessible()
{
mState.accessible = nsnull;
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
GetAccService()->GetAccessible(mState.domNode, presShell, mWeakShell,
mState.frame.GetFrame(), &mState.isHidden,
getter_AddRefs(mState.accessible));
return mState.accessible ? PR_TRUE : PR_FALSE;
}

Просмотреть файл

@ -1,137 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Original Author: Aaron Leventhal (aaronl@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _nsAccessibleTreeWalker_H_
#define _nsAccessibleTreeWalker_H_
/* For documentation of the accessibility architecture, see
* http://www.mozilla.org/access/architecture
*/
#include "nsCOMPtr.h"
#include "nsIDocument.h"
#include "nsIAccessible.h"
#include "nsIDOMNode.h"
#include "nsIDOMNodeList.h"
#include "nsIWeakReference.h"
#include "nsIFrame.h"
enum { eSiblingsUninitialized = -1, eSiblingsWalkFrames = -2 };
struct WalkState {
nsCOMPtr<nsIAccessible> accessible;
nsCOMPtr<nsIDOMNode> domNode;
nsCOMPtr<nsIDOMNodeList> siblingList;
nsIContent *parentContent; // For walking normal DOM
WalkState *prevState;
// XXXbz is |frame| still needed?
nsWeakFrame frame; // Helps avoid GetPrimaryFrameFor() calls
PRInt32 siblingIndex; // Holds a state flag or an index into the siblingList
PRBool isHidden; // Don't enter subtree if hidden
};
/** This class is used to walk the DOM tree. It skips
* everything but nodes that either implement nsIAccessibleProvider
* or have primary frames that implement "GetAccessible"
*/
class nsAccessibleTreeWalker {
public:
nsAccessibleTreeWalker(nsIWeakReference* aShell, nsIDOMNode* aContent,
PRBool mWalkAnonymousContent);
virtual ~nsAccessibleTreeWalker();
/**
* Moves current state to point to the next child accessible.
*/
NS_IMETHOD GetNextSibling();
/**
* Moves current state to point to the first child accessible.
*/
NS_IMETHOD GetFirstChild();
/**
* Current state. Used to initialize a11y tree walker and to get an accessible
* current state points to.
*/
WalkState mState;
protected:
/**
* Return true if currently navigated node/frame is accessible.
*/
PRBool GetAccessible();
/**
* Prepares current state to navigate through children of node/frame.
*/
void GetKids(nsIDOMNode *aParent);
/**
* Clears the current state.
*/
void ClearState();
/**
* Push current state on top of stack. State stack is used to navigate down to
* DOM/frame subtree during searching of accessible children.
*/
NS_IMETHOD PushState();
/**
* Pop state from stack and make it current.
*/
NS_IMETHOD PopState();
/**
* Make treewalker traverse by frame tree if necessary.
*/
void WalkFrames();
/**
* Change current state so that its node is changed to next node.
*/
void GetNextDOMNode();
nsCOMPtr<nsIWeakReference> mWeakShell;
PRBool mWalkAnonContent;
};
#endif

Просмотреть файл

@ -37,7 +37,6 @@
* ***** END LICENSE BLOCK ***** */
// NOTE: alphabetically ordered
#include "nsAccessibleTreeWalker.h"
#include "nsAccessibilityAtoms.h"
#include "nsHTMLFormControlAccessible.h"
#include "nsIDOMDocument.h"

Просмотреть файл

@ -45,7 +45,6 @@
#include "nsIDOMHTMLOptionsCollection.h"
#include "nsIDOMHTMLOptionElement.h"
#include "nsIDOMNode.h"
#include "nsAccessibleTreeWalker.h"
class nsIMutableArray;

Просмотреть файл

@ -39,7 +39,6 @@
#include "nsHTMLTableAccessible.h"
#include "nsAccessibilityAtoms.h"
#include "nsAccessibleTreeWalker.h"
#include "nsIDOMElement.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentRange.h"

Просмотреть файл

@ -38,7 +38,6 @@
* ***** END LICENSE BLOCK ***** */
#include "nsHTMLTextAccessible.h"
#include "nsAccessibleTreeWalker.h"
#include "nsIAccessibleDocument.h"
#include "nsIAccessibleEvent.h"
#include "nsIFrame.h"

Просмотреть файл

@ -40,7 +40,6 @@
#include "nsHyperTextAccessible.h"
#include "nsAccessibilityAtoms.h"
#include "nsAccessibilityService.h"
#include "nsAccessibleTreeWalker.h"
#include "nsTextAttrs.h"
#include "nsIClipboard.h"

Просмотреть файл

@ -38,7 +38,7 @@
#include "nsXULColorPickerAccessible.h"
#include "nsAccessibleTreeWalker.h"
#include "nsAccTreeWalker.h"
#include "nsIDOMElement.h"
@ -166,24 +166,22 @@ nsXULColorPickerAccessible::GetRoleInternal(PRUint32 *aRole)
void
nsXULColorPickerAccessible::CacheChildren()
{
nsCOMPtr<nsIAccessible> menupopupAccessible;
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
walker.GetFirstChild();
nsCOMPtr<nsIContent> node(do_QueryInterface(mDOMNode));
nsAccTreeWalker walker(mWeakShell, node, PR_TRUE);
while (walker.mState.accessible) {
PRUint32 role = nsAccUtils::Role(walker.mState.accessible);
nsCOMPtr<nsIAccessible> child;
while ((child = walker.GetNextChild())) {
PRUint32 role = nsAccUtils::Role(child);
// Get an accessbile for menupopup or panel elements.
if (role == nsIAccessibleRole::ROLE_ALERT) {
nsRefPtr<nsAccessible> menupopupAcc =
nsAccUtils::QueryObject<nsAccessible>(walker.mState.accessible);
nsAccUtils::QueryObject<nsAccessible>(child);
mChildren.AppendElement(menupopupAcc);
menupopupAcc->SetParent(this);
return;
}
walker.GetNextSibling();
}
}

Просмотреть файл

@ -41,7 +41,7 @@
#include "nsXULFormControlAccessible.h"
#include "nsHTMLFormControlAccessible.h"
#include "nsAccessibilityAtoms.h"
#include "nsAccessibleTreeWalker.h"
#include "nsAccTreeWalker.h"
#include "nsXULMenuAccessible.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMNSEditableElement.h"
@ -207,24 +207,22 @@ nsXULButtonAccessible::CacheChildren()
nsCOMPtr<nsIAccessible> buttonAccessible;
nsCOMPtr<nsIAccessible> menupopupAccessible;
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
walker.GetFirstChild();
nsAccTreeWalker walker(mWeakShell, content, PR_TRUE);
while (walker.mState.accessible) {
PRUint32 role = nsAccUtils::Role(walker.mState.accessible);
nsCOMPtr<nsIAccessible> child;
while ((child = walker.GetNextChild())) {
PRUint32 role = nsAccUtils::Role(child);
if (role == nsIAccessibleRole::ROLE_MENUPOPUP) {
// Get an accessbile for menupopup or panel elements.
menupopupAccessible = walker.mState.accessible;
child.swap(menupopupAccessible);
} else if (isMenuButton && role == nsIAccessibleRole::ROLE_PUSHBUTTON) {
// Button type="menu-button" contains a real button. Get an accessible
// for it. Ignore dropmarker button what is placed as a last child.
buttonAccessible = walker.mState.accessible;
child.swap(buttonAccessible);
break;
}
walker.GetNextSibling();
}
if (!menupopupAccessible)
@ -1080,18 +1078,15 @@ nsXULTextFieldAccessible::CacheChildren()
if (!inputContent)
return;
nsAccessibleTreeWalker walker(mWeakShell, inputNode, PR_FALSE);
walker.mState.frame = inputContent->GetPrimaryFrame();
nsAccTreeWalker walker(mWeakShell, inputContent, PR_FALSE);
walker.GetFirstChild();
while (walker.mState.accessible) {
nsCOMPtr<nsIAccessible> child;
while ((child = walker.GetNextChild())) {
nsRefPtr<nsAccessible> acc =
nsAccUtils::QueryObject<nsAccessible>(walker.mState.accessible);
nsAccUtils::QueryObject<nsAccessible>(child);
mChildren.AppendElement(acc);
acc->SetParent(this);
walker.GetNextSibling();
}
}

Просмотреть файл

@ -40,7 +40,6 @@
#define _nsXULMenuAccessible_H_
#include "nsAccessibleWrap.h"
#include "nsAccessibleTreeWalker.h"
#include "nsIAccessibleSelectable.h"
#include "nsIDOMXULSelectCntrlEl.h"

Просмотреть файл

@ -73,7 +73,7 @@
// Note: if input have label elements then the name isn't calculated
// from them.
testName("btn_labelledby_mixed_input",
"input button Submit Query Reset input image");
"input button Submit Query Reset Submit Query");
// Gets the name from the title of object element.
testName("btn_labelledby_mixed_object", "object");
@ -147,6 +147,12 @@
testName("textareawithchild", "Story Bar is ended.");
//////////////////////////////////////////////////////////////////////////
// button name (specific cases not covered by test_name_markup.html)
testName("submit", "Submit Query");
testName("image_submit", "Submit Query");
/////////////////////////////////////////////////////////////////////////
// label with nested combobox (test for 'f' item of name computation guide)
@ -184,6 +190,11 @@
href="https://bugzilla.mozilla.org/show_bug.cgi?id=444279"
title="mochitest for accessible name calculating">
Mozilla Bug 444279
</a><br>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=530081"
title="Clean up our tree walker ">
Mozilla Bug 530081
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
@ -357,6 +368,10 @@
</label>
</form>
<!-- submit buttons -->
<input type="submit" id="submit">
<input type="image" id="image_submit">
<!-- a label with a nested control in the start, middle and end -->
<form>
<!-- at the start (without and with whitespaces) -->

Просмотреть файл

@ -52,6 +52,7 @@ _TEST_FILES =\
test_filectrl.html \
test_formctrl.html \
test_formctrl.xul \
test_gencontent.html \
test_groupbox.xul \
test_iframe.html \
test_img.html \

Просмотреть файл

@ -35,16 +35,14 @@
testAccessibleTree("radio", accTree);
// input@type="button" and button
// input@type="button" and input@type="submit"
accTree = {
role: ROLE_PUSHBUTTON,
children: [ ]
};
testAccessibleTree("btn1", accTree);
testAccessibleTree("submit", accTree);
testAccessibleTree("image_submit", accTree);
// button
accTree = {
@ -58,6 +56,17 @@
testAccessibleTree("btn2", accTree);
// input@type="image"
accTree = {
role: ROLE_PUSHBUTTON,
children: [
{
role: ROLE_STATICTEXT
}
]
};
testAccessibleTree("image_submit", accTree);
SimpleTest.finish();
}

Просмотреть файл

@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<title>Generated content tests</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<style>
.gentext:before {
content: "START"
}
.gentext:after {
content: "END"
}
</style>
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/role.js"></script>
<script type="application/javascript">
function doTest()
{
// :before and :after pseudo styles
var accTree = {
role: ROLE_SECTION,
children: [
{
role: ROLE_STATICTEXT,
name: "START"
},
{
role: ROLE_TEXT_LEAF,
name: "MIDDLE"
},
{
role: ROLE_STATICTEXT,
name: "END"
}
]
};
testAccessibleTree("gentext", accTree);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
title="Clean up our tree walker"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=530081">
Mozilla Bug 530081
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div class="gentext" id="gentext">MIDDLE</div>
</body>
</html>