зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
70f9774516
Коммит
2758ec302f
|
@ -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>
|
Загрузка…
Ссылка в новой задаче