Bug 414976 - Support RELATION_NODE_CHILD_OF for ARIA tree views, patch=aaronlev, r=me, a=mtschrep

This commit is contained in:
surkov.alexander@gmail.com 2008-02-08 18:14:03 -08:00
parent dab96fa561
commit 7b5d8d141d
4 changed files with 95 additions and 8 deletions

View File

@ -304,6 +304,81 @@ nsAccUtils::GetAncestorWithRole(nsIAccessible *aDescendant, PRUint32 aRole)
return nsnull;
}
void
nsAccUtils::GetARIATreeItemParent(nsIAccessible *aStartTreeItem, nsIContent *aStartContent,
nsIAccessible **aTreeItemParentResult)
{
*aTreeItemParentResult = nsnull;
nsAutoString levelStr;
PRInt32 level = 0;
if (aStartContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_level, levelStr)) {
// This is a tree that uses aria-level to define levels, so find the first previous
// sibling accessible where level is defined to be less than the current level
PRInt32 success;
level = levelStr.ToInteger(&success);
if (level > 1 && NS_SUCCEEDED(success)) {
nsCOMPtr<nsIAccessible> currentAccessible = aStartTreeItem, prevAccessible;
while (PR_TRUE) {
currentAccessible->GetPreviousSibling(getter_AddRefs(prevAccessible));
currentAccessible.swap(prevAccessible);
nsCOMPtr<nsIAccessNode> accessNode = do_QueryInterface(currentAccessible);
if (!accessNode) {
break; // Reached top of tree, no higher level found
}
PRUint32 role;
currentAccessible->GetFinalRole(&role);
if (role != nsIAccessibleRole::ROLE_OUTLINEITEM)
continue;
nsCOMPtr<nsIDOMNode> treeItemNode;
accessNode->GetDOMNode(getter_AddRefs(treeItemNode));
nsCOMPtr<nsIContent> treeItemContent = do_QueryInterface(treeItemNode);
if (treeItemContent &&
treeItemContent->GetAttr(kNameSpaceID_None,
nsAccessibilityAtoms::aria_level, levelStr)) {
if (levelStr.ToInteger(&success) < level && NS_SUCCEEDED(success)) {
NS_ADDREF(*aTreeItemParentResult = currentAccessible);
return;
}
}
}
}
}
// Possibly a tree arranged by using role="group" to organize levels
// In this case the parent of the tree item will be a group and the
// previous sibling of that should be the tree item parent.
// Or, if the parent is something other than a tree we will return that.
nsCOMPtr<nsIAccessible> parentAccessible;
aStartTreeItem->GetParent(getter_AddRefs(parentAccessible));
if (!parentAccessible)
return;
PRUint32 role;
parentAccessible->GetFinalRole(&role);
if (role != nsIAccessibleRole::ROLE_GROUPING) {
NS_ADDREF(*aTreeItemParentResult = parentAccessible);
return; // The container for the tree items
}
nsCOMPtr<nsIAccessible> prevAccessible;
parentAccessible->GetPreviousSibling(getter_AddRefs(prevAccessible));
if (!prevAccessible)
return;
prevAccessible->GetFinalRole(&role);
if (role == nsIAccessibleRole::ROLE_TEXT_LEAF) {
// XXX Sometimes an empty text accessible is in the hierarchy here,
// although the text does not appear to be rendered, GetRenderedText() says that it is
// so we need to skip past it to find the true previous sibling
nsCOMPtr<nsIAccessible> tempAccessible = prevAccessible;
tempAccessible->GetPreviousSibling(getter_AddRefs(prevAccessible));
if (!prevAccessible)
return;
prevAccessible->GetFinalRole(&role);
}
if (role == nsIAccessibleRole::ROLE_OUTLINEITEM) {
// Previous sibling of parent group is a tree item -- this is the conceptual tree item parent
NS_ADDREF(*aTreeItemParentResult = prevAccessible);
}
}
nsresult
nsAccUtils::ScrollSubstringTo(nsIFrame *aFrame,
nsIDOMNode *aStartNode, PRInt32 aStartIndex,

View File

@ -147,6 +147,19 @@ public:
static already_AddRefed<nsIAccessible>
GetAncestorWithRole(nsIAccessible *aDescendant, PRUint32 aRole);
/**
* For an ARIA tree item , get the accessible that represents its conceptual parent.
* This method will use the correct method for the given way the tree is constructed.
* The conceptual parent is what the user sees as the parent, not the DOM or accessible parent.
* @param aStartTreeItem The tree item to get the parent for
* @param aStartTreeItemContent The content node for the tree item
* @param The tree item's parent, or null if none
*/
static void
GetARIATreeItemParent(nsIAccessible *aStartTreeItem,
nsIContent *aStartTreeItemContent,
nsIAccessible **aTreeItemParent);
/**
* Helper method to scroll range into view, used for implementation of
* nsIAccessibleText::scrollSubstringTo().

View File

@ -2674,6 +2674,11 @@ NS_IMETHODIMP nsAccessible::GetAccessibleRelated(PRUint32 aRelationType, nsIAcce
{
relatedNode =
do_QueryInterface(nsAccUtils::FindNeighbourPointingToNode(content, nsAccessibilityAtoms::aria_owns));
if (!relatedNode && mRoleMapEntry && mRoleMapEntry->role == nsIAccessibleRole::ROLE_OUTLINEITEM) {
// This is an ARIA tree that doesn't use owns, so we need to get the parent the hard way
nsAccUtils::GetARIATreeItemParent(this, content, aRelated);
return NS_OK;
}
break;
}
case nsIAccessibleRelation::RELATION_CONTROLLED_BY:

View File

@ -1236,10 +1236,7 @@ NS_IMETHODIMP nsXULTreeitemAccessible::GetAccessibleRelated(PRUint32 aRelationTy
if (IsDefunct())
return NS_ERROR_FAILURE;
//currentlly only for ATK. and in the future, we'll sync MSAA and ATK same.
//that's why ATK specific code shows here
*aRelated = nsnull;
#ifdef MOZ_ACCESSIBILITY_ATK
if (aRelationType == nsIAccessibleRelation::RELATION_NODE_CHILD_OF) {
PRInt32 columnIndex;
if (NS_SUCCEEDED(mColumn->GetIndex(&columnIndex)) && columnIndex == 0) {
@ -1256,12 +1253,9 @@ NS_IMETHODIMP nsXULTreeitemAccessible::GetAccessibleRelated(PRUint32 aRelationTy
}
}
return NS_OK;
} else {
#endif
return nsAccessible::GetAccessibleRelated(aRelationType, aRelated);
#ifdef MOZ_ACCESSIBILITY_ATK
}
#endif
return nsAccessible::GetAccessibleRelated(aRelationType, aRelated);
}
// attribute AString nsIAccessibleTreeItem::cachedName