Backing out fix for bug 243313 because it fits regression window for bug 248378. The change appears to have exposed a difference between the vc98 and vcnet7.1 compilers

git-svn-id: svn://10.0.0.236/trunk@158480 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
aaronleventhal%moonset.net
2004-06-25 14:24:21 +00:00
parent e6d5988b57
commit ef439d23b5
7 changed files with 181 additions and 126 deletions

View File

@@ -59,6 +59,7 @@ class nsIFrame;
class nsIDOMNodeList;
enum { eChildCountUninitialized = 0xffff };
enum { eSiblingsUninitialized = -1, eSiblingsWalkNormalDOM = -2 };
#define ACCESSIBLE_BUNDLE_URL "chrome://global-platform/locale/accessible.properties"
#define PLATFORM_KEYS_BUNDLE_URL "chrome://global-platform/locale/platformKeys.properties"

View File

@@ -278,15 +278,6 @@ NS_IMETHODIMP nsAccessible::GetNextSibling(nsIAccessible * *aNextSibling)
// This node has been shut down
return NS_ERROR_FAILURE;
}
if (!mParent) {
nsCOMPtr<nsIAccessible> parent;
GetParent(getter_AddRefs(parent));
if (parent) {
PRInt32 numChildren;
parent->GetChildCount(&numChildren); // Make sure we cache all of the children
}
}
if (mNextSibling || !mParent) {
// If no parent, don't try to calculate a new sibling
// It either means we're at the root or shutting down the parent
@@ -296,7 +287,22 @@ NS_IMETHODIMP nsAccessible::GetNextSibling(nsIAccessible * *aNextSibling)
return NS_OK;
}
return NS_ERROR_FAILURE;
// Last argument of PR_TRUE indicates to walk anonymous content
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
if (NS_SUCCEEDED(walker.GetNextSibling())) {
*aNextSibling = walker.mState.accessible;
NS_ADDREF(*aNextSibling);
nsCOMPtr<nsPIAccessible> privateAcc(do_QueryInterface(*aNextSibling));
privateAcc->SetParent(mParent);
mNextSibling = *aNextSibling;
}
if (!mNextSibling)
mNextSibling = DEAD_END_ACCESSIBLE;
return NS_OK;
}
/* readonly attribute nsIAccessible previousSibling; */
@@ -309,26 +315,17 @@ NS_IMETHODIMP nsAccessible::GetPreviousSibling(nsIAccessible * *aPreviousSibling
return NS_ERROR_FAILURE;
}
if (!mParent) {
nsCOMPtr<nsIAccessible> parent;
if (NS_FAILED(GetParent(getter_AddRefs(parent)))) {
return NS_ERROR_FAILURE;
}
// Last argument of PR_TRUE indicates to walk anonymous content
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
if (NS_SUCCEEDED(walker.GetPreviousSibling())) {
*aPreviousSibling = walker.mState.accessible;
NS_ADDREF(*aPreviousSibling);
// Use last walker state to cache data on prev accessible
nsCOMPtr<nsPIAccessible> privateAcc(do_QueryInterface(*aPreviousSibling));
privateAcc->SetParent(mParent);
}
nsCOMPtr<nsIAccessible> testAccessible, prevSibling;
mParent->GetFirstChild(getter_AddRefs(testAccessible));
while (testAccessible) {
prevSibling = testAccessible;
prevSibling->GetNextSibling(getter_AddRefs(testAccessible));
}
if (!prevSibling) {
return NS_ERROR_FAILURE;
}
NS_ADDREF(*aPreviousSibling = prevSibling);
return NS_OK;
return NS_OK;
}
/* readonly attribute nsIAccessible firstChild; */
@@ -394,7 +391,7 @@ void nsAccessible::CacheChildren(PRBool aWalkAnonContent)
// 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.
walker.mState.frame = GetFrame();
walker.mState.frameHint = GetFrame();
nsCOMPtr<nsPIAccessible> privatePrevAccessible;
mAccChildCount = 0;

View File

@@ -37,14 +37,13 @@
* ***** END LICENSE BLOCK ***** */
#include "nsAccessibleTreeWalker.h"
#include "nsAccessibilityAtoms.h"
#include "nsWeakReference.h"
#include "nsAccessNode.h"
#include "nsIServiceManager.h"
#include "nsIContent.h"
#include "nsIDOMXULElement.h"
#include "nsIPresShell.h"
#include "nsIFrame.h"
#include "nsWeakReference.h"
nsAccessibleTreeWalker::nsAccessibleTreeWalker(nsIWeakReference* aPresShell, nsIDOMNode* aNode, PRBool aWalkAnonContent):
mWeakShell(aPresShell),
@@ -55,7 +54,7 @@ nsAccessibleTreeWalker::nsAccessibleTreeWalker(nsIWeakReference* aPresShell, nsI
mState.siblingIndex = eSiblingsUninitialized;
mState.siblingList = nsnull;
mState.isHidden = false;
mState.frame = nsnull;
mState.frameHint = nsnull;
if (aWalkAnonContent) {
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
@@ -66,6 +65,7 @@ nsAccessibleTreeWalker::nsAccessibleTreeWalker(nsIWeakReference* aPresShell, nsI
}
}
MOZ_COUNT_CTOR(nsAccessibleTreeWalker);
mInitialState = mState; // deep copy
}
nsAccessibleTreeWalker::~nsAccessibleTreeWalker()
@@ -109,34 +109,33 @@ NS_IMETHODIMP nsAccessibleTreeWalker::GetFullTreeParentNode(nsIDOMNode *aChildNo
void nsAccessibleTreeWalker::GetKids(nsIDOMNode *aParentNode)
{
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(aParentNode));
if (!parentContent || !parentContent->IsContentOfType(nsIContent::eHTML)) {
mState.frame = nsnull; // Don't walk frames in non-HTML content, just walk the DOM.
}
nsCOMPtr<nsIContent> content(do_QueryInterface(aParentNode));
PushState();
UpdateFrame(PR_TRUE);
// 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
if (parentContent && !parentContent->IsContentOfType(nsIContent::eHTML) && mBindingManager) {
// Walk anonymous content
mBindingManager->GetXBLChildNodesFor(parentContent, getter_AddRefs(mState.siblingList)); // returns null if no anon nodes
if (mState.siblingList) {
mState.siblingIndex = 0; // Indicates our index into the sibling list
mState.siblingList->Item(0, getter_AddRefs(mState.domNode));
return;
}
}
// Walk normal DOM
mState.siblingIndex = eSiblingsWalkNormalDOM; // Default value - indicates no sibling list
if (aParentNode) {
aParentNode->GetFirstChild(getter_AddRefs(mState.domNode));
if (content && mBindingManager) {
mBindingManager->GetXBLChildNodesFor(content, getter_AddRefs(mState.siblingList)); // returns null if no anon nodes
if (mState.siblingList)
mState.siblingIndex = 0; // Indicates our index into the sibling list
}
}
void nsAccessibleTreeWalker::GetSiblings(nsIDOMNode *aOneOfTheSiblings)
{
nsCOMPtr<nsIDOMNode> node;
mState.siblingIndex = eSiblingsWalkNormalDOM; // Default value
if (NS_SUCCEEDED(GetFullTreeParentNode(aOneOfTheSiblings, getter_AddRefs(node)))) {
GetKids(node);
if (mState.siblingList) { // Init index by seeing how far we are into list
if (mState.domNode == mInitialState.domNode)
mInitialState = mState; // deep copy, we'll use sibling info for caching
while (NS_SUCCEEDED(mState.siblingList->Item(mState.siblingIndex, getter_AddRefs(node))) && node != mState.domNode) {
NS_ASSERTION(node, "Something is terribly wrong - the child is not in it's parent's children!");
++mState.siblingIndex;
}
}
}
}
@@ -158,19 +157,19 @@ NS_IMETHODIMP nsAccessibleTreeWalker::GetParent()
NS_IMETHODIMP nsAccessibleTreeWalker::PopState()
{
nsIFrame *frameParent = mState.frame? mState.frame->GetParent(): nsnull;
nsIFrame *frameHintParent = mState.frameHint? mState.frameHint->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) {
mState.frame = frameParent;
if (!mState.frameHint) {
mState.frameHint = frameHintParent;
}
delete toBeDeleted;
return NS_OK;
}
ClearState();
mState.frame = frameParent;
mState.frameHint = frameHintParent;
mState.isHidden = PR_FALSE;
return NS_ERROR_FAILURE;
}
@@ -195,42 +194,54 @@ NS_IMETHODIMP nsAccessibleTreeWalker::PushState()
return NS_OK;
}
void nsAccessibleTreeWalker::GetNextDOMNode()
{
// Get next DOM node
if (mState.siblingIndex == eSiblingsWalkNormalDOM) {
mState.domNode->GetNextSibling(getter_AddRefs(mState.domNode));
}
else if (mState.siblingIndex == eSiblingsWalkFrames) {
mState.domNode = mState.frame? do_QueryInterface(mState.frame->GetContent()): nsnull;
}
else {
mState.siblingList->Item(++mState.siblingIndex, getter_AddRefs(mState.domNode));
}
}
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
UpdateFrame(PR_FALSE);
GetNextDOMNode();
// Make sure mState.siblingIndex and mState.siblingList are initialized
if (mState.siblingIndex == eSiblingsUninitialized)
GetSiblings(mState.domNode);
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) {
// get next sibling
nsCOMPtr<nsIDOMNode> next;
while (PR_TRUE) {
if (mState.siblingIndex == eSiblingsWalkNormalDOM)
mState.domNode->GetNextSibling(getter_AddRefs(next));
else
mState.siblingList->Item(++mState.siblingIndex, getter_AddRefs(next));
if (!next) { // Done with siblings
// if no DOM parent or DOM parent is accessible fail
nsCOMPtr<nsIDOMNode> parent;
if (NS_FAILED(GetFullTreeParentNode(mState.domNode, getter_AddRefs(parent))))
break; // Failed - can't get parent node, we're at the top
if (NS_FAILED(PopState())) { // Use parent - go up in stack
mState.domNode = parent;
}
if (mState.siblingIndex == eSiblingsUninitialized)
GetSiblings(mState.domNode);
if (GetAccessible()) {
mState.accessible = nsnull;
break; // Back to original accessible that we did GetFirstChild() from
break; // Failed - anything after this in the tree is in a new group of siblings
}
}
else if ((mState.domNode != mState.prevState->domNode && GetAccessible()) ||
NS_SUCCEEDED(GetFirstChild())) {
return NS_OK; // if next is accessible, use it
else {
UpdateFrameHint(next, false);
// if next is accessible, use it
mState.domNode = next;
if (GetAccessible())
return NS_OK;
// otherwise call first on next
mState.domNode = next;
if (NS_SUCCEEDED(GetFirstChild()))
return NS_OK;
// If no results, keep recursiom going - call next on next
mState.domNode = next;
}
}
return NS_ERROR_FAILURE;
@@ -238,38 +249,87 @@ NS_IMETHODIMP nsAccessibleTreeWalker::GetNextSibling()
NS_IMETHODIMP nsAccessibleTreeWalker::GetFirstChild()
{
mState.accessible = nsnull;
if (mState.isHidden || !mState.domNode) {
if (mState.isHidden) {
return NS_ERROR_FAILURE;
}
mState.accessible = nsnull;
nsCOMPtr<nsIDOMNode> parent(mState.domNode);
GetKids(parent); // Side effects change our state (mState)
if (!mState.domNode)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMNode> next, parent(mState.domNode);
PushState(); // Save old state
GetKids(parent); // Side effects change our state
if (mState.siblingIndex == eSiblingsWalkNormalDOM) // Indicates we must use normal DOM calls to traverse here
parent->GetFirstChild(getter_AddRefs(next));
else // Use the sibling list - there are anonymous content nodes in here
mState.siblingList->Item(0, getter_AddRefs(next));
UpdateFrameHint(next, true);
// Recursive loop: depth first search for first accessible child
while (mState.domNode) {
if ((mState.domNode != parent && GetAccessible()) || NS_SUCCEEDED(GetFirstChild()))
while (next) {
mState.domNode = next;
if (GetAccessible() || NS_SUCCEEDED(GetFirstChild()))
return NS_OK;
UpdateFrame(PR_FALSE);
GetNextDOMNode();
if (mState.siblingIndex == eSiblingsWalkNormalDOM) // Indicates we must use normal DOM calls to traverse here
mState.domNode->GetNextSibling(getter_AddRefs(next));
else
mState.siblingList->Item(++mState.siblingIndex, getter_AddRefs(next));
UpdateFrameHint(next, false);
}
PopState(); // Return to previous state
return NS_ERROR_FAILURE;
}
void nsAccessibleTreeWalker::UpdateFrame(PRBool aTryFirstChild)
NS_IMETHODIMP nsAccessibleTreeWalker::GetChildBefore(nsIDOMNode* aParent, nsIDOMNode* aChild)
{
if (mState.frame) {
mState.frame = aTryFirstChild? mState.frame->GetFirstChild(nsnull) :
mState.frame->GetNextSibling();
#ifndef MOZ_ACCESSIBILITY_ATK
if (mState.frame && mState.siblingIndex <0 &&
mState.frame->IsGeneratedContentFrame()) {
mState.domNode = do_QueryInterface(mState.frame->GetContent());
mState.siblingIndex = eSiblingsWalkFrames;
mState.accessible = nsnull;
mState.domNode = aParent;
if (!mState.domNode || NS_FAILED(GetFirstChild()) || mState.domNode == aChild)
return NS_ERROR_FAILURE; // if the first child is us, then we fail, because there is no child before the first
nsCOMPtr<nsIDOMNode> prevDOMNode(mState.domNode);
nsCOMPtr<nsIAccessible> prevAccessible(mState.accessible);
while (mState.domNode && NS_SUCCEEDED(GetNextSibling()) && mState.domNode != aChild) {
prevDOMNode = mState.domNode;
prevAccessible = mState.accessible;
}
mState.accessible = prevAccessible;
mState.domNode = prevDOMNode;
return NS_OK;
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetPreviousSibling()
{
nsCOMPtr<nsIDOMNode> child(mState.domNode);
nsresult rv = GetParent();
if (NS_SUCCEEDED(rv))
rv = GetChildBefore(mState.domNode, child);
return rv;
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetLastChild()
{
return GetChildBefore(mState.domNode, nsnull);
}
void nsAccessibleTreeWalker::UpdateFrameHint(nsIDOMNode *aStartNode, PRBool aTryFirstChild)
{
if (mState.frameHint) {
nsIFrame *testFrame = aTryFirstChild? mState.frameHint->GetFirstChild(nsnull) :
mState.frameHint->GetNextSibling();
nsCOMPtr<nsIContent> content(do_QueryInterface(aStartNode));
if (testFrame && content && content == testFrame->GetContent()) {
mState.frameHint = testFrame;
}
#endif
}
}
@@ -286,7 +346,7 @@ PRBool nsAccessibleTreeWalker::GetAccessible()
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
if (NS_SUCCEEDED(mAccService->GetAccessible(mState.domNode, presShell, mWeakShell,
&mState.frame, &mState.isHidden,
&mState.frameHint, &mState.isHidden,
getter_AddRefs(mState.accessible)))) {
NS_ASSERTION(mState.accessible, "No accessible but no failure return code");
return true;

View File

@@ -50,14 +50,12 @@
#include "nsIBindingManager.h"
#include "nsIWeakReference.h"
enum { eSiblingsUninitialized = -1, eSiblingsWalkNormalDOM = -2, eSiblingsWalkFrames = -3 };
struct WalkState {
nsCOMPtr<nsIAccessible> accessible;
nsCOMPtr<nsIDOMNode> domNode;
nsCOMPtr<nsIDOMNodeList> siblingList;
WalkState *prevState;
nsIFrame *frame; // Helps avoid GetPrimaryFrameFor() calls
nsIFrame *frameHint; // Helps avoid GetPrimaryFrameFor() calls
PRInt32 siblingIndex; // Holds a state flag or an index into the siblingList
PRBool isHidden; // Don't enter subtree if hidden
};
@@ -74,22 +72,26 @@ public:
virtual ~nsAccessibleTreeWalker();
NS_IMETHOD GetNextSibling();
NS_IMETHOD GetPreviousSibling();
NS_IMETHOD GetParent();
NS_IMETHOD GetFirstChild();
NS_IMETHOD GetLastChild();
WalkState mState;
WalkState mInitialState;
protected:
NS_IMETHOD GetChildBefore(nsIDOMNode* aParent, nsIDOMNode* aChild);
PRBool GetAccessible();
NS_IMETHOD GetFullTreeParentNode(nsIDOMNode *aChildNode, nsIDOMNode **aParentNodeOut);
void GetSiblings(nsIDOMNode *aOneOfTheSiblings);
void GetKids(nsIDOMNode *aParent);
void ClearState();
NS_IMETHOD PushState();
NS_IMETHOD PopState();
void UpdateFrame(PRBool aTryFirstChild);
void GetNextDOMNode();
void UpdateFrameHint(nsIDOMNode *aStartNode, PRBool aTryFirstChild);
nsCOMPtr<nsIWeakReference> mWeakShell;
nsCOMPtr<nsIAccessibilityService> mAccService;

View File

@@ -475,7 +475,7 @@ void nsHTMLGroupboxAccessible::CacheChildren(PRBool aWalkAnonContent)
if (mAccChildCount == eChildCountUninitialized) {
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, aWalkAnonContent);
walker.mState.frame = GetFrame();
walker.mState.frameHint = GetFrame();
mAccChildCount = 0;
walker.GetFirstChild();
// Check for <legend> and skip it if it's there

View File

@@ -228,7 +228,7 @@ void nsHTMLLIAccessible::CacheChildren(PRBool aWalkAnonContent)
SetFirstChild(mBulletAccessible);
mAccChildCount = 1;
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, aWalkAnonContent);
walker.mState.frame = GetFrame();
walker.mState.frameHint = GetFrame();
walker.GetFirstChild();
nsCOMPtr<nsPIAccessible> privatePrevAccessible = do_QueryInterface(mBulletAccessible);

View File

@@ -163,22 +163,17 @@ NS_IMETHODIMP nsXULButtonAccessible::GetFirstChild(nsIAccessible **aResult)
{
if (!mFirstChild) {
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
walker.GetFirstChild();
nsCOMPtr<nsIAccessible> dropMarkerAccessible;
while (walker.mState.accessible) {
dropMarkerAccessible = walker.mState.accessible;
walker.GetNextSibling();
}
walker.GetLastChild();
// If the anonymous tree walker can find accessible children,
// and the last one is a push button, then use it as the only accessible
// child -- because this is the scenario where we have a dropmarker child
if (dropMarkerAccessible) {
if (walker.mState.accessible) {
PRUint32 role;
if (NS_SUCCEEDED(dropMarkerAccessible->GetRole(&role)) && role == ROLE_PUSHBUTTON) {
mFirstChild = dropMarkerAccessible;
nsCOMPtr<nsPIAccessible> privChildAcc = do_QueryInterface(dropMarkerAccessible);
if (NS_SUCCEEDED(walker.mState.accessible->GetRole(&role)) && role == ROLE_PUSHBUTTON) {
mFirstChild = walker.mState.accessible;
nsCOMPtr<nsPIAccessible> privChildAcc = do_QueryInterface(mFirstChild);
privChildAcc->SetNextSibling(nsnull);
}
}