Bug 540892 - Stop using nsIDOMNode tree traversals, r=davidb, sr=bz

This commit is contained in:
Alexander Surkov 2010-01-27 19:43:25 +08:00
parent 0dbd68dca1
commit 0c0d4576fe
11 changed files with 83 additions and 66 deletions

View File

@ -90,7 +90,7 @@ nsAccEvent::nsAccEvent(PRUint32 aEventType, nsIDOMNode *aDOMNode,
PRBool aIsAsync, EIsFromUserInput aIsFromUserInput,
EEventRule aEventRule) :
mEventType(aEventType), mEventRule(aEventRule), mIsAsync(aIsAsync),
mDOMNode(aDOMNode)
mNode(do_QueryInterface(aDOMNode))
{
CaptureIsFromUserInput(aIsFromUserInput);
}
@ -138,13 +138,19 @@ nsAccEvent::GetDOMNode(nsIDOMNode **aDOMNode)
NS_ENSURE_ARG_POINTER(aDOMNode);
*aDOMNode = nsnull;
if (!mDOMNode) {
if (!mNode) {
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(mAccessible));
NS_ENSURE_TRUE(accessNode, NS_ERROR_FAILURE);
accessNode->GetDOMNode(getter_AddRefs(mDOMNode));
nsCOMPtr<nsIDOMNode> DOMNode;
accessNode->GetDOMNode(getter_AddRefs(DOMNode));
mNode = do_QueryInterface(DOMNode);
}
NS_IF_ADDREF(*aDOMNode = mDOMNode);
if (mNode)
CallQueryInterface(mNode, aDOMNode);
return NS_OK;
}
@ -175,7 +181,7 @@ nsAccEvent::GetAccessibleDocument(nsIAccessibleDocument **aDocAccessible)
already_AddRefed<nsIAccessible>
nsAccEvent::GetAccessibleByNode()
{
if (!mDOMNode)
if (!mNode)
return nsnull;
nsCOMPtr<nsIAccessibilityService> accService =
@ -183,19 +189,23 @@ nsAccEvent::GetAccessibleByNode()
if (!accService)
return nsnull;
nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(mNode));
nsCOMPtr<nsIAccessible> accessible;
accService->GetAccessibleFor(mDOMNode, getter_AddRefs(accessible));
accService->GetAccessibleFor(DOMNode, getter_AddRefs(accessible));
#ifdef MOZ_XUL
// hack for xul tree table. We need a better way for firing delayed event
// against xul tree table. see bug 386821.
// There will be problem if some day we want to fire delayed event against
// the xul tree itself or an unselected treeitem.
nsAutoString localName;
mDOMNode->GetLocalName(localName);
if (localName.EqualsLiteral("tree")) {
nsCOMPtr<nsIContent> content(do_QueryInterface(mNode));
if (content && content->NodeInfo()->Equals(nsAccessibilityAtoms::tree,
kNameSpaceID_XUL)) {
nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelect =
do_QueryInterface(mDOMNode);
do_QueryInterface(mNode);
if (multiSelect) {
PRInt32 treeIndex = -1;
multiSelect->GetCurrentIndex(&treeIndex);

View File

@ -138,7 +138,7 @@ protected:
EEventRule mEventRule;
PRPackedBool mIsAsync;
nsCOMPtr<nsIAccessible> mAccessible;
nsCOMPtr<nsIDOMNode> mDOMNode;
nsCOMPtr<nsINode> mNode;
nsCOMPtr<nsIAccessibleDocument> mDocAccessible;
friend class nsAccEventQueue;

View File

@ -153,6 +153,7 @@ ACCESSIBILITY_ATOM(toolbarspring, "toolbarspring") // XUL
ACCESSIBILITY_ATOM(toolbarspacer, "toolbarspacer") // XUL
ACCESSIBILITY_ATOM(tooltip, "tooltip") // XUL
ACCESSIBILITY_ATOM(tr, "tr")
ACCESSIBILITY_ATOM(tree, "tree")
ACCESSIBILITY_ATOM(ul, "ul")
// Alphabetical list of attributes (DOM)

View File

@ -448,8 +448,8 @@ nsAccessible::GetKeyboardShortcut(nsAString& aAccessKey)
// Copy access key from label node unless it is labeled
// via an ancestor <label>, in which case that would be redundant
nsCOMPtr<nsIContent> labelContent(nsCoreUtils::GetLabelContent(content));
nsCOMPtr<nsIDOMNode> labelNode = do_QueryInterface(labelContent);
if (labelNode && !nsCoreUtils::IsAncestorOf(labelNode, mDOMNode))
nsCOMPtr<nsINode> thisNode = do_QueryInterface(mDOMNode);
if (labelContent && !nsCoreUtils::IsAncestorOf(labelContent, thisNode))
key = nsCoreUtils::GetAccessKeyFor(labelContent);
}
@ -1708,11 +1708,13 @@ nsAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
if (nsAccUtils::Role(tabPanel) == nsIAccessibleRole::ROLE_PROPERTYPAGE) {
nsCOMPtr<nsIAccessNode> tabPanelAccessNode(do_QueryInterface(tabPanel));
nsCOMPtr<nsIDOMNode> tabPanelNode;
tabPanelAccessNode->GetDOMNode(getter_AddRefs(tabPanelNode));
NS_ENSURE_STATE(tabPanelNode);
nsCOMPtr<nsIDOMNode> tabPanelDOMNode;
tabPanelAccessNode->GetDOMNode(getter_AddRefs(tabPanelDOMNode));
NS_ENSURE_STATE(tabPanelDOMNode);
if (nsCoreUtils::IsAncestorOf(tabPanelNode, gLastFocusedNode))
nsCOMPtr<nsINode> tabPanelNode(do_QueryInterface(tabPanelDOMNode));
nsCOMPtr<nsINode> lastFocusedNode(do_QueryInterface(gLastFocusedNode));
if (nsCoreUtils::IsAncestorOf(tabPanelNode, lastFocusedNode))
*aState |= nsIAccessibleStates::STATE_SELECTED;
}
}

View File

@ -313,36 +313,26 @@ nsCoreUtils::GetRoleContent(nsIDOMNode *aDOMNode)
}
PRBool
nsCoreUtils::IsAncestorOf(nsIDOMNode *aPossibleAncestorNode,
nsIDOMNode *aPossibleDescendantNode)
nsCoreUtils::IsAncestorOf(nsINode *aPossibleAncestorNode,
nsINode *aPossibleDescendantNode)
{
NS_ENSURE_TRUE(aPossibleAncestorNode && aPossibleDescendantNode, PR_FALSE);
nsCOMPtr<nsIDOMNode> loopNode = aPossibleDescendantNode;
nsCOMPtr<nsIDOMNode> parentNode;
while (NS_SUCCEEDED(loopNode->GetParentNode(getter_AddRefs(parentNode))) &&
parentNode) {
if (parentNode == aPossibleAncestorNode) {
nsINode *parentNode = aPossibleDescendantNode;
while ((parentNode = parentNode->GetNodeParent())) {
if (parentNode == aPossibleAncestorNode)
return PR_TRUE;
}
loopNode.swap(parentNode);
}
return PR_FALSE;
}
PRBool
nsCoreUtils::AreSiblings(nsIDOMNode *aDOMNode1,
nsIDOMNode *aDOMNode2)
nsCoreUtils::AreSiblings(nsINode *aNode1, nsINode *aNode2)
{
NS_ENSURE_TRUE(aDOMNode1 && aDOMNode2, PR_FALSE);
NS_ENSURE_TRUE(aNode1 && aNode2, PR_FALSE);
nsCOMPtr<nsIDOMNode> parentNode1, parentNode2;
if (NS_SUCCEEDED(aDOMNode1->GetParentNode(getter_AddRefs(parentNode1))) &&
NS_SUCCEEDED(aDOMNode2->GetParentNode(getter_AddRefs(parentNode2))) &&
parentNode1 == parentNode2) {
return PR_TRUE;
}
return PR_FALSE;
return aNode1->GetNodeParent() == aNode2->GetNodeParent();
}
nsresult

View File

@ -140,19 +140,23 @@ public:
/**
* Is the first passed in node an ancestor of the second?
* Note: A node is not considered to be the ancestor of itself.
* @param aPossibleAncestorNode -- node to test for ancestor-ness of aPossibleDescendantNode
* @param aPossibleDescendantNode -- node to test for descendant-ness of aPossibleAncestorNode
* @return PR_TRUE if aPossibleAncestorNode is an ancestor of aPossibleDescendantNode
*
* @param aPossibleAncestorNode [in] node to test for ancestor-ness of
* aPossibleDescendantNode
* @param aPossibleDescendantNode [in] node to test for descendant-ness of
* aPossibleAncestorNode
* @return PR_TRUE if aPossibleAncestorNode is an ancestor of
* aPossibleDescendantNode
*/
static PRBool IsAncestorOf(nsIDOMNode *aPossibleAncestorNode,
nsIDOMNode *aPossibleDescendantNode);
static PRBool IsAncestorOf(nsINode *aPossibleAncestorNode,
nsINode *aPossibleDescendantNode);
/**
* Are the first node and the second siblings?
*
* @return PR_TRUE if aDOMNode1 and aDOMNode2 have same parent
*/
static PRBool AreSiblings(nsIDOMNode *aDOMNode1,
nsIDOMNode *aDOMNode2);
static PRBool AreSiblings(nsINode *aNode1, nsINode *aNode2);
/**
* Helper method to scroll range into view, used for implementation of

View File

@ -1532,13 +1532,18 @@ nsDocAccessible::CreateTextChangeEventForNode(nsIAccessible *aContainerAccessibl
if (!changeAccessible) {
return nsnull; // No descendant content that represents any text in the hypertext parent
}
nsCOMPtr<nsINode> changeNode(do_QueryInterface(aChangeNode));
nsCOMPtr<nsIAccessible> child = changeAccessible;
while (PR_TRUE) {
nsCOMPtr<nsIAccessNode> childAccessNode =
do_QueryInterface(changeAccessible);
nsCOMPtr<nsIDOMNode> childNode;
childAccessNode->GetDOMNode(getter_AddRefs(childNode));
if (!nsCoreUtils::IsAncestorOf(aChangeNode, childNode)) {
nsCOMPtr<nsIDOMNode> childDOMNode;
childAccessNode->GetDOMNode(getter_AddRefs(childDOMNode));
nsCOMPtr<nsINode> childNode(do_QueryInterface(childDOMNode));
if (!nsCoreUtils::IsAncestorOf(changeNode, childNode)) {
break; // We only want accessibles with DOM nodes as children of this node
}
length += nsAccUtils::TextLength(child);

View File

@ -243,7 +243,7 @@ nsAccEventQueue::CoalesceEvents()
thisEvent->mEventRule == nsAccEvent::eDoNotEmit)
continue; // Do not need to check
if (thisEvent->mDOMNode == tailEvent->mDOMNode) {
if (thisEvent->mNode == tailEvent->mNode) {
if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
CoalesceReorderEventsFromSameSource(thisEvent, tailEvent);
continue;
@ -253,8 +253,7 @@ nsAccEventQueue::CoalesceEvents()
thisEvent->mEventRule = nsAccEvent::eDoNotEmit;
continue;
}
if (nsCoreUtils::IsAncestorOf(tailEvent->mDOMNode,
thisEvent->mDOMNode)) {
if (nsCoreUtils::IsAncestorOf(tailEvent->mNode, thisEvent->mNode)) {
// thisDOMNode is a descendant of tailDOMNode
if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
CoalesceReorderEventsFromSameTree(tailEvent, thisEvent);
@ -265,11 +264,10 @@ nsAccEventQueue::CoalesceEvents()
// nodes of thisDOMNode.
thisEvent->mEventRule = nsAccEvent::eDoNotEmit;
ApplyToSiblings(0, index, thisEvent->mEventType,
thisEvent->mDOMNode, nsAccEvent::eDoNotEmit);
thisEvent->mNode, nsAccEvent::eDoNotEmit);
continue;
}
if (nsCoreUtils::IsAncestorOf(thisEvent->mDOMNode,
tailEvent->mDOMNode)) {
if (nsCoreUtils::IsAncestorOf(thisEvent->mNode, tailEvent->mNode)) {
// tailDOMNode is a descendant of thisDOMNode
if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
CoalesceReorderEventsFromSameTree(thisEvent, tailEvent);
@ -280,7 +278,7 @@ nsAccEventQueue::CoalesceEvents()
// nodes of tailDOMNode.
tailEvent->mEventRule = nsAccEvent::eDoNotEmit;
ApplyToSiblings(0, tail, tailEvent->mEventType,
tailEvent->mDOMNode, nsAccEvent::eDoNotEmit);
tailEvent->mNode, nsAccEvent::eDoNotEmit);
break;
}
} // for (index)
@ -291,7 +289,7 @@ nsAccEventQueue::CoalesceEvents()
// This event should be emitted
// Apply this result to sibling nodes of tailDOMNode
ApplyToSiblings(0, tail, tailEvent->mEventType,
tailEvent->mDOMNode, nsAccEvent::eAllowDupes);
tailEvent->mNode, nsAccEvent::eAllowDupes);
}
} break; // case eCoalesceFromSameSubtree
@ -302,7 +300,7 @@ nsAccEventQueue::CoalesceEvents()
nsAccEvent* accEvent = mEvents[index];
if (accEvent->mEventType == tailEvent->mEventType &&
accEvent->mEventRule == tailEvent->mEventRule &&
accEvent->mDOMNode == tailEvent->mDOMNode) {
accEvent->mNode == tailEvent->mNode) {
accEvent->mEventRule = nsAccEvent::eDoNotEmit;
}
}
@ -315,14 +313,14 @@ nsAccEventQueue::CoalesceEvents()
void
nsAccEventQueue::ApplyToSiblings(PRUint32 aStart, PRUint32 aEnd,
PRUint32 aEventType, nsIDOMNode* aDOMNode,
PRUint32 aEventType, nsINode* aNode,
nsAccEvent::EEventRule aEventRule)
{
for (PRUint32 index = aStart; index < aEnd; index ++) {
nsAccEvent* accEvent = mEvents[index];
if (accEvent->mEventType == aEventType &&
accEvent->mEventRule != nsAccEvent::eDoNotEmit &&
nsCoreUtils::AreSiblings(accEvent->mDOMNode, aDOMNode)) {
nsCoreUtils::AreSiblings(accEvent->mNode, aNode)) {
accEvent->mEventRule = aEventRule;
}
}

View File

@ -135,7 +135,7 @@ private:
* (should be eDoNotEmit or eAllowDupes)
*/
void ApplyToSiblings(PRUint32 aStart, PRUint32 aEnd,
PRUint32 aEventType, nsIDOMNode* aDOMNode,
PRUint32 aEventType, nsINode* aNode,
nsAccEvent::EEventRule aEventRule);
/**

View File

@ -1141,8 +1141,11 @@ nsRootAccessible::HandlePopupHidingEvent(nsIDOMNode *aNode,
// DOMMenuItemActive events inside of a combo box that closes. The real focus
// is on the combo box. It's also the case when a popup gets focus in ATK --
// when it closes we need to fire an event to restore focus to where it was.
nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
nsCOMPtr<nsINode> lastFocusedNode(do_QueryInterface(gLastFocusedNode));
if (gLastFocusedNode &&
nsCoreUtils::IsAncestorOf(aNode, gLastFocusedNode)) {
nsCoreUtils::IsAncestorOf(node, lastFocusedNode)) {
// Focus was on or inside of a popup that's being hidden
FireCurrentFocusEvent();
}
@ -1168,7 +1171,6 @@ nsRootAccessible::HandlePopupHidingEvent(nsIDOMNode *aNode,
PR_FALSE, PR_FALSE);
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(comboboxAcc));
nsEventShell::FireEvent(event);
return NS_OK;
}

View File

@ -1602,11 +1602,13 @@ nsHyperTextAccessible::GetCaretOffset(PRInt32 *aCaretOffset)
// No caret if the focused node is not inside this DOM node and this DOM node
// is not inside of focused node.
nsCOMPtr<nsINode> thisNode(do_QueryInterface(mDOMNode));
nsCOMPtr<nsINode> lastFocusedNode(do_QueryInterface(gLastFocusedNode));
PRBool isInsideOfFocusedNode =
nsCoreUtils::IsAncestorOf(gLastFocusedNode, mDOMNode);
nsCoreUtils::IsAncestorOf(lastFocusedNode, thisNode);
if (!isInsideOfFocusedNode && mDOMNode != gLastFocusedNode &&
!nsCoreUtils::IsAncestorOf(mDOMNode, gLastFocusedNode))
!nsCoreUtils::IsAncestorOf(thisNode, lastFocusedNode))
return NS_OK;
// Turn the focus node and offset of the selection into caret hypretext
@ -1627,10 +1629,12 @@ nsHyperTextAccessible::GetCaretOffset(PRInt32 *aCaretOffset)
// No caret if this DOM node is inside of focused node but the selection's
// focus point is not inside of this DOM node.
if (isInsideOfFocusedNode) {
nsCOMPtr<nsIDOMNode> resultNode =
nsCOMPtr<nsIDOMNode> resultDOMNode =
nsCoreUtils::GetDOMNodeFromDOMPoint(focusNode, focusOffset);
if (resultNode != mDOMNode &&
!nsCoreUtils::IsAncestorOf(mDOMNode, resultNode))
nsCOMPtr<nsINode> resultNode(do_QueryInterface(resultDOMNode));
if (resultNode != thisNode &&
!nsCoreUtils::IsAncestorOf(thisNode, resultNode))
return NS_OK;
}
@ -1653,7 +1657,8 @@ PRInt32 nsHyperTextAccessible::GetCaretLineNumber()
nsCOMPtr<nsIDOMNode> caretNode;
domSel->GetFocusNode(getter_AddRefs(caretNode));
nsCOMPtr<nsIContent> caretContent = do_QueryInterface(caretNode);
if (!caretContent || !nsCoreUtils::IsAncestorOf(mDOMNode, caretNode)) {
nsCOMPtr<nsINode> thisNode(do_QueryInterface(mDOMNode));
if (!caretContent || !nsCoreUtils::IsAncestorOf(thisNode, caretContent)) {
return -1;
}