2008-10-16 02:12:05 -07:00
|
|
|
/* -*- 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
|
|
|
|
* Mozilla Foundation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2007
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
|
|
|
|
*
|
|
|
|
* 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 "nsCoreUtils.h"
|
|
|
|
#include "nsAccUtils.h"
|
|
|
|
|
|
|
|
#include "nsIAccessibleStates.h"
|
|
|
|
#include "nsIAccessibleTypes.h"
|
|
|
|
|
2008-10-17 03:10:43 -07:00
|
|
|
#include "nsAccessibleEventData.h"
|
|
|
|
#include "nsHyperTextAccessible.h"
|
2009-05-13 22:31:09 -07:00
|
|
|
#include "nsHTMLTableAccessible.h"
|
2008-10-16 02:12:05 -07:00
|
|
|
#include "nsAccessibilityAtoms.h"
|
2009-02-04 22:23:18 -08:00
|
|
|
#include "nsAccessibleTreeWalker.h"
|
2008-10-16 02:12:05 -07:00
|
|
|
#include "nsAccessible.h"
|
|
|
|
#include "nsARIAMap.h"
|
2008-10-17 03:10:43 -07:00
|
|
|
|
2008-10-16 02:12:05 -07:00
|
|
|
#include "nsIDOMXULContainerElement.h"
|
|
|
|
#include "nsIDOMXULSelectCntrlEl.h"
|
|
|
|
#include "nsIDOMXULSelectCntrlItemEl.h"
|
|
|
|
#include "nsWhitespaceTokenizer.h"
|
|
|
|
|
|
|
|
void
|
|
|
|
nsAccUtils::GetAccAttr(nsIPersistentProperties *aAttributes,
|
|
|
|
nsIAtom *aAttrName, nsAString& aAttrValue)
|
|
|
|
{
|
|
|
|
aAttrValue.Truncate();
|
|
|
|
|
|
|
|
nsCAutoString attrName;
|
|
|
|
aAttrName->ToUTF8String(attrName);
|
|
|
|
aAttributes->GetStringProperty(attrName, aAttrValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsAccUtils::SetAccAttr(nsIPersistentProperties *aAttributes,
|
|
|
|
nsIAtom *aAttrName, const nsAString& aAttrValue)
|
|
|
|
{
|
|
|
|
nsAutoString oldValue;
|
|
|
|
nsCAutoString attrName;
|
|
|
|
|
|
|
|
aAttrName->ToUTF8String(attrName);
|
|
|
|
aAttributes->SetStringProperty(attrName, aAttrValue, oldValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsAccUtils::GetAccGroupAttrs(nsIPersistentProperties *aAttributes,
|
|
|
|
PRInt32 *aLevel, PRInt32 *aPosInSet,
|
|
|
|
PRInt32 *aSetSize)
|
|
|
|
{
|
|
|
|
*aLevel = 0;
|
|
|
|
*aPosInSet = 0;
|
|
|
|
*aSetSize = 0;
|
|
|
|
|
|
|
|
nsAutoString value;
|
|
|
|
PRInt32 error = NS_OK;
|
|
|
|
|
|
|
|
GetAccAttr(aAttributes, nsAccessibilityAtoms::level, value);
|
|
|
|
if (!value.IsEmpty()) {
|
|
|
|
PRInt32 level = value.ToInteger(&error);
|
|
|
|
if (NS_SUCCEEDED(error))
|
|
|
|
*aLevel = level;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetAccAttr(aAttributes, nsAccessibilityAtoms::posinset, value);
|
|
|
|
if (!value.IsEmpty()) {
|
|
|
|
PRInt32 posInSet = value.ToInteger(&error);
|
|
|
|
if (NS_SUCCEEDED(error))
|
|
|
|
*aPosInSet = posInSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetAccAttr(aAttributes, nsAccessibilityAtoms::setsize, value);
|
|
|
|
if (!value.IsEmpty()) {
|
|
|
|
PRInt32 sizeSet = value.ToInteger(&error);
|
|
|
|
if (NS_SUCCEEDED(error))
|
|
|
|
*aSetSize = sizeSet;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsAccUtils::HasAccGroupAttrs(nsIPersistentProperties *aAttributes)
|
|
|
|
{
|
|
|
|
nsAutoString value;
|
|
|
|
|
|
|
|
GetAccAttr(aAttributes, nsAccessibilityAtoms::setsize, value);
|
|
|
|
if (!value.IsEmpty()) {
|
|
|
|
GetAccAttr(aAttributes, nsAccessibilityAtoms::posinset, value);
|
|
|
|
return !value.IsEmpty();
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsAccUtils::SetAccGroupAttrs(nsIPersistentProperties *aAttributes,
|
|
|
|
PRInt32 aLevel, PRInt32 aPosInSet,
|
|
|
|
PRInt32 aSetSize)
|
|
|
|
{
|
|
|
|
nsAutoString value;
|
|
|
|
|
|
|
|
if (aLevel) {
|
|
|
|
value.AppendInt(aLevel);
|
|
|
|
SetAccAttr(aAttributes, nsAccessibilityAtoms::level, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aSetSize && aPosInSet) {
|
|
|
|
value.Truncate();
|
|
|
|
value.AppendInt(aPosInSet);
|
|
|
|
SetAccAttr(aAttributes, nsAccessibilityAtoms::posinset, value);
|
|
|
|
|
|
|
|
value.Truncate();
|
|
|
|
value.AppendInt(aSetSize);
|
|
|
|
SetAccAttr(aAttributes, nsAccessibilityAtoms::setsize, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsAccUtils::SetAccAttrsForXULSelectControlItem(nsIDOMNode *aNode,
|
|
|
|
nsIPersistentProperties *aAttributes)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMXULSelectControlItemElement> item(do_QueryInterface(aNode));
|
|
|
|
if (!item)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMXULSelectControlElement> control;
|
|
|
|
item->GetControl(getter_AddRefs(control));
|
|
|
|
if (!control)
|
|
|
|
return;
|
|
|
|
|
|
|
|
PRUint32 itemsCount = 0;
|
|
|
|
control->GetItemCount(&itemsCount);
|
|
|
|
|
|
|
|
PRInt32 indexOf = 0;
|
|
|
|
control->GetIndexOfItem(item, &indexOf);
|
|
|
|
|
|
|
|
PRUint32 setSize = itemsCount, posInSet = indexOf;
|
|
|
|
for (PRUint32 index = 0; index < itemsCount; index++) {
|
|
|
|
nsCOMPtr<nsIDOMXULSelectControlItemElement> currItem;
|
|
|
|
control->GetItemAtIndex(index, getter_AddRefs(currItem));
|
|
|
|
nsCOMPtr<nsIDOMNode> currNode(do_QueryInterface(currItem));
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessible> itemAcc;
|
|
|
|
nsAccessNode::GetAccService()->GetAccessibleFor(currNode,
|
|
|
|
getter_AddRefs(itemAcc));
|
|
|
|
if (!itemAcc ||
|
2008-10-17 03:10:43 -07:00
|
|
|
State(itemAcc) & nsIAccessibleStates::STATE_INVISIBLE) {
|
2008-10-16 02:12:05 -07:00
|
|
|
setSize--;
|
|
|
|
if (index < static_cast<PRUint32>(indexOf))
|
|
|
|
posInSet--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SetAccGroupAttrs(aAttributes, 0, posInSet + 1, setSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsAccUtils::SetAccAttrsForXULContainerItem(nsIDOMNode *aNode,
|
|
|
|
nsIPersistentProperties *aAttributes)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMXULContainerItemElement> item(do_QueryInterface(aNode));
|
|
|
|
if (!item)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMXULContainerElement> container;
|
|
|
|
item->GetParentContainer(getter_AddRefs(container));
|
|
|
|
if (!container)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Get item count.
|
|
|
|
PRUint32 itemsCount = 0;
|
|
|
|
container->GetItemCount(&itemsCount);
|
|
|
|
|
|
|
|
// Get item index.
|
|
|
|
PRInt32 indexOf = 0;
|
|
|
|
container->GetIndexOfItem(item, &indexOf);
|
|
|
|
|
|
|
|
// Calculate set size and position in the set.
|
|
|
|
PRUint32 setSize = 0, posInSet = 0;
|
|
|
|
for (PRInt32 index = indexOf; index >= 0; index--) {
|
|
|
|
nsCOMPtr<nsIDOMXULElement> item;
|
|
|
|
container->GetItemAtIndex(index, getter_AddRefs(item));
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessible> itemAcc;
|
|
|
|
nsAccessNode::GetAccService()->GetAccessibleFor(item,
|
|
|
|
getter_AddRefs(itemAcc));
|
|
|
|
|
|
|
|
if (itemAcc) {
|
2008-10-17 03:10:43 -07:00
|
|
|
PRUint32 itemRole = Role(itemAcc);
|
2008-10-16 02:12:05 -07:00
|
|
|
if (itemRole == nsIAccessibleRole::ROLE_SEPARATOR)
|
|
|
|
break; // We reached the beginning of our group.
|
|
|
|
|
2008-10-17 03:10:43 -07:00
|
|
|
PRUint32 itemState = State(itemAcc);
|
2008-10-16 02:12:05 -07:00
|
|
|
if (!(itemState & nsIAccessibleStates::STATE_INVISIBLE)) {
|
|
|
|
setSize++;
|
|
|
|
posInSet++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (PRInt32 index = indexOf + 1; index < static_cast<PRInt32>(itemsCount);
|
|
|
|
index++) {
|
|
|
|
nsCOMPtr<nsIDOMXULElement> item;
|
|
|
|
container->GetItemAtIndex(index, getter_AddRefs(item));
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessible> itemAcc;
|
|
|
|
nsAccessNode::GetAccService()->GetAccessibleFor(item,
|
|
|
|
getter_AddRefs(itemAcc));
|
|
|
|
|
|
|
|
if (itemAcc) {
|
2008-10-17 03:10:43 -07:00
|
|
|
PRUint32 itemRole = Role(itemAcc);
|
2008-10-16 02:12:05 -07:00
|
|
|
if (itemRole == nsIAccessibleRole::ROLE_SEPARATOR)
|
|
|
|
break; // We reached the end of our group.
|
|
|
|
|
2008-10-17 03:10:43 -07:00
|
|
|
PRUint32 itemState = State(itemAcc);
|
2008-10-16 02:12:05 -07:00
|
|
|
if (!(itemState & nsIAccessibleStates::STATE_INVISIBLE))
|
|
|
|
setSize++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get level of the item.
|
|
|
|
PRInt32 level = -1;
|
|
|
|
while (container) {
|
|
|
|
level++;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMXULContainerElement> parentContainer;
|
|
|
|
container->GetParentContainer(getter_AddRefs(parentContainer));
|
|
|
|
parentContainer.swap(container);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetAccGroupAttrs(aAttributes, level, posInSet, setSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsAccUtils::SetLiveContainerAttributes(nsIPersistentProperties *aAttributes,
|
|
|
|
nsIContent *aStartContent,
|
|
|
|
nsIContent *aTopContent)
|
|
|
|
{
|
2009-01-12 22:08:46 -08:00
|
|
|
nsAutoString atomic, live, relevant, busy;
|
2008-10-16 02:12:05 -07:00
|
|
|
nsIContent *ancestor = aStartContent;
|
|
|
|
while (ancestor) {
|
2009-02-18 22:56:19 -08:00
|
|
|
|
|
|
|
// container-relevant attribute
|
2008-10-16 02:12:05 -07:00
|
|
|
if (relevant.IsEmpty() &&
|
2009-01-12 09:20:34 -08:00
|
|
|
nsAccUtils::HasDefinedARIAToken(ancestor, nsAccessibilityAtoms::aria_relevant) &&
|
2008-10-16 02:12:05 -07:00
|
|
|
ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_relevant, relevant))
|
|
|
|
SetAccAttr(aAttributes, nsAccessibilityAtoms::containerRelevant, relevant);
|
|
|
|
|
2009-02-18 22:56:19 -08:00
|
|
|
// container-live attribute
|
|
|
|
if (live.IsEmpty()) {
|
|
|
|
if (nsAccUtils::HasDefinedARIAToken(ancestor,
|
|
|
|
nsAccessibilityAtoms::aria_live)) {
|
|
|
|
ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_live,
|
|
|
|
live);
|
|
|
|
SetAccAttr(aAttributes, nsAccessibilityAtoms::containerLive, live);
|
|
|
|
} else {
|
|
|
|
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(ancestor));
|
|
|
|
nsRoleMapEntry *role = GetRoleMapEntry(node);
|
|
|
|
if (role) {
|
|
|
|
nsAutoString live;
|
|
|
|
GetLiveAttrValue(role->liveAttRule, live);
|
|
|
|
SetAccAttr(aAttributes, nsAccessibilityAtoms::containerLive, live);
|
2009-06-17 07:22:23 -07:00
|
|
|
|
|
|
|
// For default live containers, expose the container-live-role attribute
|
|
|
|
nsAccUtils::SetAccAttr(aAttributes,
|
|
|
|
nsAccessibilityAtoms::containerLiveRole,
|
|
|
|
NS_ConvertASCIItoUTF16(role->roleString));
|
2009-02-18 22:56:19 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-10-16 02:12:05 -07:00
|
|
|
|
2009-02-18 22:56:19 -08:00
|
|
|
// container-atomic attribute
|
2008-10-16 02:12:05 -07:00
|
|
|
if (atomic.IsEmpty() &&
|
2009-01-12 09:20:34 -08:00
|
|
|
nsAccUtils::HasDefinedARIAToken(ancestor, nsAccessibilityAtoms::aria_atomic) &&
|
2008-10-16 02:12:05 -07:00
|
|
|
ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_atomic, atomic))
|
|
|
|
SetAccAttr(aAttributes, nsAccessibilityAtoms::containerAtomic, atomic);
|
|
|
|
|
2009-02-18 22:56:19 -08:00
|
|
|
// container-busy attribute
|
2008-10-16 02:12:05 -07:00
|
|
|
if (busy.IsEmpty() &&
|
2009-01-12 09:20:34 -08:00
|
|
|
nsAccUtils::HasDefinedARIAToken(ancestor, nsAccessibilityAtoms::aria_busy) &&
|
2008-10-16 02:12:05 -07:00
|
|
|
ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_busy, busy))
|
|
|
|
SetAccAttr(aAttributes, nsAccessibilityAtoms::containerBusy, busy);
|
|
|
|
|
|
|
|
if (ancestor == aTopContent)
|
|
|
|
break;
|
|
|
|
|
|
|
|
ancestor = ancestor->GetParent();
|
|
|
|
if (!ancestor)
|
|
|
|
ancestor = aTopContent; // Use <body>/<frameset>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-12 09:20:34 -08:00
|
|
|
PRBool
|
|
|
|
nsAccUtils::HasDefinedARIAToken(nsIContent *aContent, nsIAtom *aAtom)
|
|
|
|
{
|
2009-04-19 23:06:19 -07:00
|
|
|
NS_ASSERTION(aContent, "aContent is null in call to HasDefinedARIAToken!");
|
|
|
|
|
2009-01-12 09:20:34 -08:00
|
|
|
if (!aContent->HasAttr(kNameSpaceID_None, aAtom) ||
|
|
|
|
aContent->AttrValueIs(kNameSpaceID_None, aAtom,
|
|
|
|
nsAccessibilityAtoms::_empty, eCaseMatters) ||
|
|
|
|
aContent->AttrValueIs(kNameSpaceID_None, aAtom,
|
|
|
|
nsAccessibilityAtoms::_undefined, eCaseMatters)) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2008-10-16 02:12:05 -07:00
|
|
|
nsresult
|
|
|
|
nsAccUtils::FireAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
|
|
|
|
PRBool aIsAsynch)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG(aAccessible);
|
|
|
|
|
2009-06-18 00:37:38 -07:00
|
|
|
nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(aAccessible));
|
2008-10-16 02:12:05 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessibleEvent> event =
|
|
|
|
new nsAccEvent(aEventType, aAccessible, aIsAsynch);
|
|
|
|
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
2009-06-18 00:37:38 -07:00
|
|
|
return acc->FireAccessibleEvent(event);
|
2008-10-16 02:12:05 -07:00
|
|
|
}
|
|
|
|
|
2009-02-04 22:23:18 -08:00
|
|
|
PRBool
|
|
|
|
nsAccUtils::HasAccessibleChildren(nsIDOMNode *aNode)
|
|
|
|
{
|
|
|
|
if (!aNode)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
|
|
|
|
if (!content)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> presShell = nsCoreUtils::GetPresShellFor(aNode);
|
|
|
|
if (!presShell)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
nsIFrame *frame = presShell->GetPrimaryFrameFor(content);
|
|
|
|
if (!frame)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
|
|
|
|
nsAccessibleTreeWalker walker(weakShell, aNode, PR_FALSE);
|
|
|
|
|
|
|
|
walker.mState.frame = frame;
|
|
|
|
|
|
|
|
walker.GetFirstChild();
|
|
|
|
return walker.mState.accessible ? PR_TRUE : PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2008-10-16 02:12:05 -07:00
|
|
|
already_AddRefed<nsIAccessible>
|
|
|
|
nsAccUtils::GetAncestorWithRole(nsIAccessible *aDescendant, PRUint32 aRole)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAccessible> parentAccessible = aDescendant, testRoleAccessible;
|
|
|
|
while (NS_SUCCEEDED(parentAccessible->GetParent(getter_AddRefs(testRoleAccessible))) &&
|
|
|
|
testRoleAccessible) {
|
2009-03-07 07:38:58 -08:00
|
|
|
PRUint32 testRole = nsAccUtils::Role(testRoleAccessible);
|
2008-10-16 02:12:05 -07:00
|
|
|
if (testRole == aRole) {
|
|
|
|
nsIAccessible *returnAccessible = testRoleAccessible;
|
|
|
|
NS_ADDREF(returnAccessible);
|
|
|
|
return returnAccessible;
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIAccessibleDocument> docAccessible = do_QueryInterface(testRoleAccessible);
|
|
|
|
if (docAccessible) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
parentAccessible.swap(testRoleAccessible);
|
|
|
|
}
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsAccUtils::GetARIATreeItemParent(nsIAccessible *aStartTreeItem,
|
|
|
|
nsIContent *aStartContent,
|
|
|
|
nsIAccessible **aTreeItemParentResult)
|
|
|
|
{
|
|
|
|
*aTreeItemParentResult = nsnull;
|
|
|
|
nsAutoString levelStr;
|
|
|
|
PRInt32 level = 0;
|
2009-01-12 09:20:34 -08:00
|
|
|
if (nsAccUtils::HasDefinedARIAToken(aStartContent, nsAccessibilityAtoms::aria_level) &&
|
|
|
|
aStartContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_level, levelStr)) {
|
2008-10-16 02:12:05 -07:00
|
|
|
// 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
|
|
|
|
}
|
2009-03-07 07:38:58 -08:00
|
|
|
PRUint32 role = nsAccUtils::Role(currentAccessible);
|
2008-10-16 02:12:05 -07:00
|
|
|
if (role != nsIAccessibleRole::ROLE_OUTLINEITEM)
|
|
|
|
continue;
|
|
|
|
nsCOMPtr<nsIDOMNode> treeItemNode;
|
|
|
|
accessNode->GetDOMNode(getter_AddRefs(treeItemNode));
|
|
|
|
nsCOMPtr<nsIContent> treeItemContent = do_QueryInterface(treeItemNode);
|
|
|
|
if (treeItemContent &&
|
2009-01-12 09:20:34 -08:00
|
|
|
nsAccUtils::HasDefinedARIAToken(treeItemContent,
|
|
|
|
nsAccessibilityAtoms::aria_level) &&
|
2008-10-16 02:12:05 -07:00
|
|
|
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;
|
2009-03-07 07:38:58 -08:00
|
|
|
PRUint32 role = nsAccUtils::Role(parentAccessible);
|
2008-10-16 02:12:05 -07:00
|
|
|
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;
|
2009-03-07 07:38:58 -08:00
|
|
|
role = nsAccUtils::Role(prevAccessible);
|
2008-10-16 02:12:05 -07:00
|
|
|
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;
|
2009-03-07 07:38:58 -08:00
|
|
|
role = nsAccUtils::Role(prevAccessible);
|
2008-10-16 02:12:05 -07:00
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-28 01:43:07 -07:00
|
|
|
already_AddRefed<nsIAccessibleText>
|
|
|
|
nsAccUtils::GetTextAccessibleFromSelection(nsISelection *aSelection,
|
|
|
|
nsIDOMNode **aNode)
|
|
|
|
{
|
|
|
|
// Get accessible from selection's focus DOM point (the DOM point where
|
|
|
|
// selection is ended).
|
|
|
|
|
2008-12-16 02:14:20 -08:00
|
|
|
nsCOMPtr<nsIDOMNode> focusNode;
|
|
|
|
aSelection->GetFocusNode(getter_AddRefs(focusNode));
|
|
|
|
if (!focusNode)
|
2008-10-28 01:43:07 -07:00
|
|
|
return nsnull;
|
|
|
|
|
2008-12-16 02:14:20 -08:00
|
|
|
PRInt32 focusOffset = 0;
|
|
|
|
aSelection->GetFocusOffset(&focusOffset);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> resultNode =
|
|
|
|
nsCoreUtils::GetDOMNodeFromDOMPoint(focusNode, focusOffset);
|
2008-10-28 01:43:07 -07:00
|
|
|
|
|
|
|
nsIAccessibilityService *accService = nsAccessNode::GetAccService();
|
|
|
|
|
|
|
|
// Get text accessible containing the result node.
|
|
|
|
while (resultNode) {
|
|
|
|
// Make sure to get the correct starting node for selection events inside
|
|
|
|
// XBL content trees.
|
|
|
|
nsCOMPtr<nsIDOMNode> relevantNode;
|
|
|
|
nsresult rv = accService->
|
|
|
|
GetRelevantContentNodeFor(resultNode, getter_AddRefs(relevantNode));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return nsnull;
|
|
|
|
|
|
|
|
if (relevantNode)
|
|
|
|
resultNode.swap(relevantNode);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> content = do_QueryInterface(resultNode);
|
|
|
|
if (!content || !content->IsNodeOfType(nsINode::eTEXT)) {
|
|
|
|
nsCOMPtr<nsIAccessible> accessible;
|
|
|
|
accService->GetAccessibleFor(resultNode, getter_AddRefs(accessible));
|
|
|
|
if (accessible) {
|
|
|
|
nsIAccessibleText *textAcc = nsnull;
|
|
|
|
CallQueryInterface(accessible, &textAcc);
|
|
|
|
if (textAcc) {
|
|
|
|
if (aNode)
|
|
|
|
NS_ADDREF(*aNode = resultNode);
|
|
|
|
|
|
|
|
return textAcc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> parentNode;
|
|
|
|
resultNode->GetParentNode(getter_AddRefs(parentNode));
|
|
|
|
resultNode.swap(parentNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_NOTREACHED("No nsIAccessibleText for selection change event!");
|
|
|
|
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
2008-10-16 02:12:05 -07:00
|
|
|
nsresult
|
|
|
|
nsAccUtils::ConvertToScreenCoords(PRInt32 aX, PRInt32 aY,
|
|
|
|
PRUint32 aCoordinateType,
|
|
|
|
nsIAccessNode *aAccessNode,
|
|
|
|
nsIntPoint *aCoords)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aCoords);
|
|
|
|
|
|
|
|
aCoords->MoveTo(aX, aY);
|
|
|
|
|
|
|
|
switch (aCoordinateType) {
|
|
|
|
case nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE:
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG(aAccessNode);
|
|
|
|
*aCoords += GetScreenCoordsForWindow(aAccessNode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE:
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG(aAccessNode);
|
|
|
|
*aCoords += GetScreenCoordsForParent(aAccessNode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsAccUtils::ConvertScreenCoordsTo(PRInt32 *aX, PRInt32 *aY,
|
|
|
|
PRUint32 aCoordinateType,
|
|
|
|
nsIAccessNode *aAccessNode)
|
|
|
|
{
|
|
|
|
switch (aCoordinateType) {
|
|
|
|
case nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE:
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG(aAccessNode);
|
|
|
|
nsIntPoint coords = nsAccUtils::GetScreenCoordsForWindow(aAccessNode);
|
|
|
|
*aX -= coords.x;
|
|
|
|
*aY -= coords.y;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE:
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG(aAccessNode);
|
|
|
|
nsIntPoint coords = nsAccUtils::GetScreenCoordsForParent(aAccessNode);
|
|
|
|
*aX -= coords.x;
|
|
|
|
*aY -= coords.y;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIntPoint
|
|
|
|
nsAccUtils::GetScreenCoordsForWindow(nsIAccessNode *aAccessNode)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> DOMNode;
|
|
|
|
aAccessNode->GetDOMNode(getter_AddRefs(DOMNode));
|
|
|
|
if (DOMNode)
|
|
|
|
return nsCoreUtils::GetScreenCoordsForWindow(DOMNode);
|
|
|
|
|
|
|
|
return nsIntPoint(0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIntPoint
|
|
|
|
nsAccUtils::GetScreenCoordsForParent(nsIAccessNode *aAccessNode)
|
|
|
|
{
|
2008-10-31 20:58:07 -07:00
|
|
|
nsRefPtr<nsAccessNode> parent;
|
2008-10-16 02:12:05 -07:00
|
|
|
nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(aAccessNode));
|
|
|
|
if (accessible) {
|
|
|
|
nsCOMPtr<nsIAccessible> parentAccessible;
|
|
|
|
accessible->GetParent(getter_AddRefs(parentAccessible));
|
2008-10-31 20:58:07 -07:00
|
|
|
parent = nsAccUtils::QueryAccessNode(parentAccessible);
|
2008-10-16 02:12:05 -07:00
|
|
|
} else {
|
|
|
|
nsCOMPtr<nsIAccessNode> parentAccessNode;
|
|
|
|
aAccessNode->GetParentNode(getter_AddRefs(parentAccessNode));
|
2008-10-31 20:58:07 -07:00
|
|
|
parent = nsAccUtils::QueryAccessNode(parentAccessNode);
|
2008-10-16 02:12:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!parent)
|
|
|
|
return nsIntPoint(0, 0);
|
|
|
|
|
|
|
|
nsIFrame *parentFrame = parent->GetFrame();
|
|
|
|
if (!parentFrame)
|
|
|
|
return nsIntPoint(0, 0);
|
|
|
|
|
|
|
|
nsIntRect parentRect = parentFrame->GetScreenRectExternal();
|
|
|
|
return nsIntPoint(parentRect.x, parentRect.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRoleMapEntry*
|
|
|
|
nsAccUtils::GetRoleMapEntry(nsIDOMNode *aNode)
|
|
|
|
{
|
2008-10-17 03:10:43 -07:00
|
|
|
nsIContent *content = nsCoreUtils::GetRoleContent(aNode);
|
2008-10-16 02:12:05 -07:00
|
|
|
nsAutoString roleString;
|
|
|
|
if (!content || !content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::role, roleString)) {
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsWhitespaceTokenizer tokenizer(roleString);
|
|
|
|
while (tokenizer.hasMoreTokens()) {
|
|
|
|
// Do a binary search through table for the next role in role list
|
|
|
|
const char *role = NS_LossyConvertUTF16toASCII(tokenizer.nextToken()).get();
|
|
|
|
PRInt32 low = 0;
|
|
|
|
PRInt32 high = nsARIAMap::gWAIRoleMapLength;
|
|
|
|
while (low <= high) {
|
|
|
|
PRInt32 index = low + ((high - low) / 2);
|
|
|
|
PRInt32 compare = PL_strcmp(role, nsARIAMap::gWAIRoleMap[index].roleString);
|
|
|
|
if (compare == 0) {
|
|
|
|
// The role attribute maps to an entry in the role table
|
|
|
|
return &nsARIAMap::gWAIRoleMap[index];
|
|
|
|
}
|
|
|
|
if (compare < 0) {
|
|
|
|
high = index - 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
low = index + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Always use some entry if there is a role string
|
|
|
|
// To ensure an accessible object is created
|
|
|
|
return &nsARIAMap::gLandmarkRoleMap;
|
|
|
|
}
|
2008-10-17 03:10:43 -07:00
|
|
|
|
2009-03-07 07:38:58 -08:00
|
|
|
PRUint32
|
|
|
|
nsAccUtils::RoleInternal(nsIAccessible *aAcc)
|
|
|
|
{
|
|
|
|
PRUint32 role = nsIAccessibleRole::ROLE_NOTHING;
|
|
|
|
if (aAcc) {
|
|
|
|
nsAccessible* accessible = nsnull;
|
|
|
|
CallQueryInterface(aAcc, &accessible);
|
|
|
|
|
2009-03-07 09:27:10 -08:00
|
|
|
if (accessible) {
|
2009-03-07 07:38:58 -08:00
|
|
|
accessible->GetRoleInternal(&role);
|
2009-03-07 09:27:10 -08:00
|
|
|
NS_RELEASE(accessible);
|
|
|
|
}
|
2009-03-07 07:38:58 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return role;
|
|
|
|
}
|
|
|
|
|
2009-02-15 00:15:31 -08:00
|
|
|
PRUint8
|
|
|
|
nsAccUtils::GetAttributeCharacteristics(nsIAtom* aAtom)
|
|
|
|
{
|
|
|
|
for (PRUint32 i = 0; i < nsARIAMap::gWAIUnivAttrMapLength; i++)
|
|
|
|
if (*nsARIAMap::gWAIUnivAttrMap[i].attributeName == aAtom)
|
|
|
|
return nsARIAMap::gWAIUnivAttrMap[i].characteristics;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-18 22:56:19 -08:00
|
|
|
void
|
|
|
|
nsAccUtils::GetLiveAttrValue(PRUint32 aRule, nsAString& aValue)
|
|
|
|
{
|
|
|
|
switch (aRule) {
|
|
|
|
case eOffLiveAttr:
|
|
|
|
aValue = NS_LITERAL_STRING("off");
|
|
|
|
break;
|
|
|
|
case ePoliteLiveAttr:
|
|
|
|
aValue = NS_LITERAL_STRING("polite");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-10-17 03:10:43 -07:00
|
|
|
|
2009-05-11 03:57:28 -07:00
|
|
|
already_AddRefed<nsAccessible>
|
|
|
|
nsAccUtils::QueryAccessible(nsIAccessible *aAccessible)
|
|
|
|
{
|
2009-06-18 00:37:38 -07:00
|
|
|
nsAccessible* acc = nsnull;
|
2009-05-11 03:57:28 -07:00
|
|
|
if (aAccessible)
|
2009-06-18 00:37:38 -07:00
|
|
|
CallQueryInterface(aAccessible, &acc);
|
|
|
|
|
|
|
|
return acc;
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsAccessible>
|
|
|
|
nsAccUtils::QueryAccessible(nsIAccessNode *aAccessNode)
|
|
|
|
{
|
|
|
|
nsAccessible* acc = nsnull;
|
|
|
|
if (aAccessNode)
|
|
|
|
CallQueryInterface(aAccessNode, &acc);
|
|
|
|
|
|
|
|
return acc;
|
2009-05-11 03:57:28 -07:00
|
|
|
}
|
|
|
|
|
2009-05-13 22:31:09 -07:00
|
|
|
already_AddRefed<nsHTMLTableAccessible>
|
|
|
|
nsAccUtils::QueryAccessibleTable(nsIAccessibleTable *aAccessibleTable)
|
|
|
|
{
|
|
|
|
nsHTMLTableAccessible* accessible = nsnull;
|
|
|
|
if (aAccessibleTable)
|
|
|
|
CallQueryInterface(aAccessibleTable, &accessible);
|
|
|
|
|
|
|
|
return accessible;
|
|
|
|
}
|
|
|
|
|
2008-10-17 03:10:43 -07:00
|
|
|
#ifdef DEBUG_A11Y
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsAccUtils::IsTextInterfaceSupportCorrect(nsIAccessible *aAccessible)
|
|
|
|
{
|
|
|
|
PRBool foundText = PR_FALSE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessibleDocument> accDoc = do_QueryInterface(aAccessible);
|
|
|
|
if (accDoc) {
|
|
|
|
// Don't test for accessible docs, it makes us create accessibles too
|
|
|
|
// early and fire mutation events before we need to
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessible> child, nextSibling;
|
|
|
|
aAccessible->GetFirstChild(getter_AddRefs(child));
|
|
|
|
while (child) {
|
|
|
|
if (IsText(child)) {
|
|
|
|
foundText = PR_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
child->GetNextSibling(getter_AddRefs(nextSibling));
|
|
|
|
child.swap(nextSibling);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (foundText) {
|
|
|
|
// found text child node
|
|
|
|
nsCOMPtr<nsIAccessibleText> text = do_QueryInterface(aAccessible);
|
|
|
|
if (!text)
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
PRInt32
|
|
|
|
nsAccUtils::TextLength(nsIAccessible *aAccessible)
|
|
|
|
{
|
|
|
|
if (!IsText(aAccessible))
|
|
|
|
return 1;
|
|
|
|
|
2008-10-31 20:58:07 -07:00
|
|
|
nsRefPtr<nsAccessNode> accNode = nsAccUtils::QueryAccessNode(aAccessible);
|
2008-10-17 03:10:43 -07:00
|
|
|
|
2008-10-31 20:58:07 -07:00
|
|
|
nsIFrame *frame = accNode->GetFrame();
|
2008-10-17 03:10:43 -07:00
|
|
|
if (frame && frame->GetType() == nsAccessibilityAtoms::textFrame) {
|
|
|
|
// Ensure that correct text length is calculated (with non-rendered
|
|
|
|
// whitespace chars not counted).
|
|
|
|
nsIContent *content = frame->GetContent();
|
|
|
|
if (content) {
|
|
|
|
PRUint32 length;
|
|
|
|
nsresult rv = nsHyperTextAccessible::
|
|
|
|
ContentToRenderedOffset(frame, content->TextLength(), &length);
|
|
|
|
return NS_SUCCEEDED(rv) ? static_cast<PRInt32>(length) : -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// For list bullets (or anything other accessible which would compute its own
|
|
|
|
// text. They don't have their own frame.
|
|
|
|
// XXX In the future, list bullets may have frame and anon content, so
|
|
|
|
// we should be able to remove this at that point
|
2009-06-18 00:37:38 -07:00
|
|
|
nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(aAccessible));
|
|
|
|
|
2008-10-17 03:10:43 -07:00
|
|
|
nsAutoString text;
|
2009-06-18 00:37:38 -07:00
|
|
|
acc->AppendTextTo(text, 0, PR_UINT32_MAX); // Get all the text
|
2008-10-17 03:10:43 -07:00
|
|
|
return text.Length();
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsAccUtils::MustPrune(nsIAccessible *aAccessible)
|
|
|
|
{
|
|
|
|
PRUint32 role = nsAccUtils::Role(aAccessible);
|
|
|
|
|
|
|
|
return role == nsIAccessibleRole::ROLE_MENUITEM ||
|
|
|
|
role == nsIAccessibleRole::ROLE_COMBOBOX_OPTION ||
|
|
|
|
role == nsIAccessibleRole::ROLE_OPTION ||
|
|
|
|
role == nsIAccessibleRole::ROLE_ENTRY ||
|
|
|
|
role == nsIAccessibleRole::ROLE_FLAT_EQUATION ||
|
|
|
|
role == nsIAccessibleRole::ROLE_PASSWORD_TEXT ||
|
|
|
|
role == nsIAccessibleRole::ROLE_PUSHBUTTON ||
|
|
|
|
role == nsIAccessibleRole::ROLE_TOGGLE_BUTTON ||
|
|
|
|
role == nsIAccessibleRole::ROLE_GRAPHIC ||
|
|
|
|
role == nsIAccessibleRole::ROLE_SLIDER ||
|
|
|
|
role == nsIAccessibleRole::ROLE_PROGRESSBAR ||
|
|
|
|
role == nsIAccessibleRole::ROLE_SEPARATOR;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsAccUtils::IsNodeRelevant(nsIDOMNode *aNode)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> relevantNode;
|
|
|
|
nsAccessNode::GetAccService()->GetRelevantContentNodeFor(aNode,
|
|
|
|
getter_AddRefs(relevantNode));
|
|
|
|
return aNode == relevantNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsIAccessible>
|
|
|
|
nsAccUtils::GetMultiSelectFor(nsIDOMNode *aNode)
|
|
|
|
{
|
|
|
|
if (!aNode)
|
|
|
|
return nsnull;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessible> accessible;
|
|
|
|
nsAccessNode::GetAccService()->GetAccessibleFor(aNode,
|
|
|
|
getter_AddRefs(accessible));
|
|
|
|
if (!accessible)
|
|
|
|
return nsnull;
|
|
|
|
|
|
|
|
PRUint32 state = State(accessible);
|
|
|
|
if (0 == (state & nsIAccessibleStates::STATE_SELECTABLE))
|
|
|
|
return nsnull;
|
|
|
|
|
|
|
|
while (0 == (state & nsIAccessibleStates::STATE_MULTISELECTABLE)) {
|
|
|
|
nsIAccessible *current = accessible;
|
|
|
|
current->GetParent(getter_AddRefs(accessible));
|
2009-03-07 07:38:58 -08:00
|
|
|
if (!accessible ||
|
|
|
|
nsAccUtils::Role(accessible) == nsIAccessibleRole::ROLE_PANE) {
|
2008-10-17 03:10:43 -07:00
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
state = State(accessible);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIAccessible *returnAccessible = nsnull;
|
|
|
|
accessible.swap(returnAccessible);
|
|
|
|
return returnAccessible;
|
|
|
|
}
|