Bug 741398 - make ARIA state map extensible, r=tbsaunde

This commit is contained in:
Alexander Surkov 2012-04-06 01:23:30 +09:00
parent 80f0b96a3a
commit 01482115ce
10 changed files with 436 additions and 405 deletions

View File

@ -0,0 +1,343 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ARIAStateMap.h"
#include "States.h"
#include "mozilla/dom/Element.h"
using namespace mozilla;
using namespace mozilla::a11y;
using namespace mozilla::a11y::aria;
/**
* Used to store state map rule data for ARIA attribute of enum type.
*/
struct EnumTypeData
{
EnumTypeData(nsIAtom* aAttrName,
nsIAtom** aValue1, PRUint64 aState1,
nsIAtom** aValue2, PRUint64 aState2,
nsIAtom** aValue3 = 0, PRUint64 aState3 = 0) :
mState1(aState1), mState2(aState2), mState3(aState3), mDefaultState(0),
mAttrName(aAttrName), mValue1(aValue1), mValue2(aValue2), mValue3(aValue3),
mNullValue(nsnull)
{ }
EnumTypeData(nsIAtom* aAttrName, PRUint64 aDefaultState,
nsIAtom** aValue1, PRUint64 aState1) :
mState1(aState1), mState2(0), mState3(0), mDefaultState(aDefaultState),
mAttrName(aAttrName), mValue1(aValue1), mValue2(nsnull), mValue3(nsnull),
mNullValue(nsnull)
{ }
// States applied if corresponding enum values are matched.
const PRUint64 mState1;
const PRUint64 mState2;
const PRUint64 mState3;
// Default state if no one enum value is matched.
const PRUint64 mDefaultState;
// ARIA attribute name.
nsIAtom* const mAttrName;
// States if the attribute value is matched to the enum value. Used as
// nsIContent::AttrValuesArray.
nsIAtom* const* const mValue1;
nsIAtom* const* const mValue2;
nsIAtom* const* const mValue3;
nsIAtom* const* const mNullValue;
};
enum ETokenType
{
eBoolType = 0,
eMixedType = 1, // can take 'mixed' value
eDefinedIfAbsent = 2 // permanent and false state are applied if absent
};
/**
* Used to store state map rule data for ARIA attribute of token type (including
* mixed value).
*/
struct TokenTypeData
{
TokenTypeData(nsIAtom* aAttrName, PRUint32 aType,
PRUint64 aPermanentState,
PRUint64 aTrueState,
PRUint64 aFalseState = 0) :
mAttrName(aAttrName), mType(aType), mPermanentState(aPermanentState),
mTrueState(aTrueState), mFalseState(aFalseState)
{ }
// ARIA attribute name.
nsIAtom* const mAttrName;
// Type.
const PRUint32 mType;
// State applied if the attribute is defined or mType doesn't have
// eDefinedIfAbsent flag set.
const PRUint64 mPermanentState;
// States applied if the attribute value is true/false.
const PRUint64 mTrueState;
const PRUint64 mFalseState;
};
/**
* Map enum type attribute value to accessible state.
*/
static void MapEnumType(dom::Element* aElement, PRUint64* aState,
const EnumTypeData& aData);
/**
* Map token type attribute value to states.
*/
static void MapTokenType(dom::Element* aContent, PRUint64* aState,
const TokenTypeData& aData);
bool
aria::MapToState(EStateRule aRule, dom::Element* aElement, PRUint64* aState)
{
switch (aRule) {
case eARIAAutoComplete:
{
static const EnumTypeData data(
nsGkAtoms::aria_autocomplete,
&nsGkAtoms::inlinevalue, states::SUPPORTS_AUTOCOMPLETION,
&nsGkAtoms::list, states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION,
&nsGkAtoms::both, states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION);
MapEnumType(aElement, aState, data);
return true;
}
case eARIABusy:
{
static const EnumTypeData data(
nsGkAtoms::aria_busy,
&nsGkAtoms::_true, states::BUSY,
&nsGkAtoms::error, states::INVALID);
MapEnumType(aElement, aState, data);
return true;
}
case eARIACheckableBool:
{
static const TokenTypeData data(
nsGkAtoms::aria_checked, eBoolType | eDefinedIfAbsent,
states::CHECKABLE, states::CHECKED);
MapTokenType(aElement, aState, data);
return true;
}
case eARIACheckableMixed:
{
static const TokenTypeData data(
nsGkAtoms::aria_checked, eMixedType | eDefinedIfAbsent,
states::CHECKABLE, states::CHECKED);
MapTokenType(aElement, aState, data);
return true;
}
case eARIACheckedMixed:
{
static const TokenTypeData data(
nsGkAtoms::aria_checked, eMixedType,
states::CHECKABLE, states::CHECKED);
MapTokenType(aElement, aState, data);
return true;
}
case eARIADisabled:
{
static const TokenTypeData data(
nsGkAtoms::aria_disabled, eBoolType,
0, states::UNAVAILABLE);
MapTokenType(aElement, aState, data);
return true;
}
case eARIAExpanded:
{
static const TokenTypeData data(
nsGkAtoms::aria_expanded, eBoolType,
0, states::EXPANDED, states::COLLAPSED);
MapTokenType(aElement, aState, data);
return true;
}
case eARIAHasPopup:
{
static const TokenTypeData data(
nsGkAtoms::aria_haspopup, eBoolType,
0, states::HASPOPUP);
MapTokenType(aElement, aState, data);
return true;
}
case eARIAInvalid:
{
static const TokenTypeData data(
nsGkAtoms::aria_invalid, eBoolType,
0, states::INVALID);
MapTokenType(aElement, aState, data);
return true;
}
case eARIAMultiline:
{
static const TokenTypeData data(
nsGkAtoms::aria_multiline, eBoolType | eDefinedIfAbsent,
0, states::MULTI_LINE, states::SINGLE_LINE);
MapTokenType(aElement, aState, data);
return true;
}
case eARIAMultiSelectable:
{
static const TokenTypeData data(
nsGkAtoms::aria_multiselectable, eBoolType,
0, states::MULTISELECTABLE | states::EXTSELECTABLE);
MapTokenType(aElement, aState, data);
return true;
}
case eARIAOrientation:
{
static const EnumTypeData data(
nsGkAtoms::aria_orientation, states::HORIZONTAL,
&nsGkAtoms::vertical, states::VERTICAL);
MapEnumType(aElement, aState, data);
return true;
}
case eARIAPressed:
{
static const TokenTypeData data(
nsGkAtoms::aria_pressed, eMixedType,
states::CHECKABLE, states::PRESSED);
MapTokenType(aElement, aState, data);
return true;
}
case eARIAReadonly:
{
static const TokenTypeData data(
nsGkAtoms::aria_readonly, eBoolType,
0, states::READONLY);
MapTokenType(aElement, aState, data);
return true;
}
case eARIAReadonlyOrEditable:
{
static const TokenTypeData data(
nsGkAtoms::aria_readonly, eBoolType | eDefinedIfAbsent,
0, states::READONLY, states::EDITABLE);
MapTokenType(aElement, aState, data);
return true;
}
case eARIARequired:
{
static const TokenTypeData data(
nsGkAtoms::aria_required, eBoolType,
0, states::REQUIRED);
MapTokenType(aElement, aState, data);
return true;
}
case eARIASelectable:
{
static const TokenTypeData data(
nsGkAtoms::aria_selected, eBoolType | eDefinedIfAbsent,
states::SELECTABLE, states::SELECTED);
MapTokenType(aElement, aState, data);
return true;
}
case eReadonlyUntilEditable:
{
if (!(*aState & states::EDITABLE))
*aState |= states::READONLY;
return true;
}
default:
return false;
}
}
static void
MapEnumType(dom::Element* aElement, PRUint64* aState, const EnumTypeData& aData)
{
switch (aElement->FindAttrValueIn(kNameSpaceID_None, aData.mAttrName,
&aData.mValue1, eCaseMatters)) {
case 0:
*aState |= aData.mState1;
return;
case 1:
*aState |= aData.mState2;
return;
case 2:
*aState |= aData.mState3;
return;
}
*aState |= aData.mDefaultState;
}
static void
MapTokenType(dom::Element* aElement, PRUint64* aState,
const TokenTypeData& aData)
{
if (aElement->HasAttr(kNameSpaceID_None, aData.mAttrName)) {
if ((aData.mType & eMixedType) &&
aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
nsGkAtoms::mixed, eCaseMatters)) {
*aState |= aData.mPermanentState | states::MIXED;
return;
}
if (aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
nsGkAtoms::_false, eCaseMatters)) {
*aState |= aData.mPermanentState | aData.mFalseState;
return;
}
if (!aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
nsGkAtoms::_undefined, eCaseMatters) &&
!aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
nsGkAtoms::_empty, eCaseMatters)) {
*aState |= aData.mPermanentState | aData.mTrueState;
}
return;
}
if (aData.mType & eDefinedIfAbsent)
*aState |= aData.mPermanentState | aData.mFalseState;
}

View File

@ -0,0 +1,62 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _mozilla_a11y_aria_ARIAStateMap_h_
#define _mozilla_a11y_aria_ARIAStateMap_h_
#include "prtypes.h"
namespace mozilla {
namespace dom {
class Element;
}
namespace a11y {
namespace aria {
/**
* List of the ARIA state mapping rules.
*/
enum EStateRule
{
eARIANone,
eARIAAutoComplete,
eARIABusy,
eARIACheckableBool,
eARIACheckableMixed,
eARIACheckedMixed,
eARIADisabled,
eARIAExpanded,
eARIAHasPopup,
eARIAInvalid,
eARIAMultiline,
eARIAMultiSelectable,
eARIAOrientation,
eARIAPressed,
eARIAReadonly,
eARIAReadonlyOrEditable,
eARIARequired,
eARIASelectable,
eReadonlyUntilEditable
};
/**
* Expose the accessible states for the given element accordingly to state
* mapping rule.
*
* @param aRule [in] state mapping rule ID
* @param aElement [in] node of the accessible
* @param aState [in/out] accessible states
* @return true if state map rule ID is valid
*/
bool MapToState(EStateRule aRule, dom::Element* aElement, PRUint64* aState);
} // namespace aria
} // namespace a11y
} // namespace mozilla
#endif

View File

@ -52,6 +52,7 @@ CPPSRCS = \
AccEvent.cpp \
AccGroupInfo.cpp \
AccIterator.cpp \
ARIAStateMap.cpp \
filters.cpp \
FocusManager.cpp \
NotificationController.cpp \
@ -91,6 +92,7 @@ EXPORTS = \
EXPORTS_NAMESPACES = mozilla/a11y
EXPORTS_mozilla/a11y = \
ARIAStateMap.h \
FocusManager.h \
States.h \
Role.h \

View File

@ -39,20 +39,20 @@
#include "nsARIAMap.h"
#include "nsIAccessibleRole.h"
#include "Role.h"
#include "States.h"
#include "nsIContent.h"
using namespace mozilla::a11y;
using namespace mozilla::a11y::aria;
/**
* This list of WAI-defined roles are currently hardcoded.
* Eventually we will most likely be loading an RDF resource that contains this information
* Using RDF will also allow for role extensibility. See bug 280138.
*
* Definition of nsRoleMapEntry and nsStateMapEntry contains comments explaining this table.
* Definition of nsRoleMapEntry contains comments explaining this table.
*
* When no nsIAccessibleRole enum mapping exists for an ARIA role, the
* role will be exposed via the object attribute "xml-roles".
@ -607,92 +607,12 @@ nsRoleMapEntry nsARIAMap::gEmptyRoleMap = {
kNoReqStates
};
nsStateMapEntry nsARIAMap::gWAIStateMap[] = {
// eARIANone
nsStateMapEntry(),
// eARIAAutoComplete
nsStateMapEntry(&nsGkAtoms::aria_autocomplete,
"inline", states::SUPPORTS_AUTOCOMPLETION,
"list", states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION,
"both", states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION),
// eARIABusy
nsStateMapEntry(&nsGkAtoms::aria_busy,
"true", states::BUSY,
"error", states::INVALID),
// eARIACheckableBool
nsStateMapEntry(&nsGkAtoms::aria_checked, kBoolType,
states::CHECKABLE, states::CHECKED, 0, true),
// eARIACheckableMixed
nsStateMapEntry(&nsGkAtoms::aria_checked, kMixedType,
states::CHECKABLE, states::CHECKED, 0, true),
// eARIACheckedMixed
nsStateMapEntry(&nsGkAtoms::aria_checked, kMixedType,
states::CHECKABLE, states::CHECKED, 0),
// eARIADisabled
nsStateMapEntry(&nsGkAtoms::aria_disabled, kBoolType,
0, states::UNAVAILABLE),
// eARIAExpanded
nsStateMapEntry(&nsGkAtoms::aria_expanded, kBoolType,
0, states::EXPANDED, states::COLLAPSED),
// eARIAHasPopup
nsStateMapEntry(&nsGkAtoms::aria_haspopup, kBoolType,
0, states::HASPOPUP),
// eARIAInvalid
nsStateMapEntry(&nsGkAtoms::aria_invalid, kBoolType,
0, states::INVALID),
// eARIAMultiline
nsStateMapEntry(&nsGkAtoms::aria_multiline, kBoolType,
0, states::MULTI_LINE, states::SINGLE_LINE, true),
// eARIAMultiSelectable
nsStateMapEntry(&nsGkAtoms::aria_multiselectable, kBoolType,
0, states::MULTISELECTABLE | states::EXTSELECTABLE),
// eARIAOrientation
nsStateMapEntry(&nsGkAtoms::aria_orientation, eUseFirstState,
"horizontal", states::HORIZONTAL,
"vertical", states::VERTICAL),
// eARIAPressed
nsStateMapEntry(&nsGkAtoms::aria_pressed, kMixedType,
states::CHECKABLE, states::PRESSED),
// eARIAReadonly
nsStateMapEntry(&nsGkAtoms::aria_readonly, kBoolType,
0, states::READONLY),
// eARIAReadonlyOrEditable
nsStateMapEntry(&nsGkAtoms::aria_readonly, kBoolType,
0, states::READONLY, states::EDITABLE, true),
// eARIARequired
nsStateMapEntry(&nsGkAtoms::aria_required, kBoolType,
0, states::REQUIRED),
// eARIASelectable
nsStateMapEntry(&nsGkAtoms::aria_selected, kBoolType,
states::SELECTABLE, states::SELECTED, 0, true),
// eReadonlyUntilEditable
nsStateMapEntry(states::READONLY, states::EDITABLE)
};
/**
* Universal (Global) states:
* The following state rules are applied to any accessible element,
* whether there is an ARIA role or not:
*/
eStateMapEntryID nsARIAMap::gWAIUnivStateMap[] = {
EStateRule nsARIAMap::gWAIUnivStateMap[] = {
eARIABusy,
eARIADisabled,
eARIAExpanded, // Currently under spec review but precedent exists
@ -746,182 +666,3 @@ nsAttributeCharacteristics nsARIAMap::gWAIUnivAttrMap[] = {
};
PRUint32 nsARIAMap::gWAIUnivAttrMapLength = NS_ARRAY_LENGTH(nsARIAMap::gWAIUnivAttrMap);
////////////////////////////////////////////////////////////////////////////////
// nsStateMapEntry
nsStateMapEntry::nsStateMapEntry() :
mAttributeName(nsnull),
mIsToken(false),
mPermanentState(0),
mValue1(nsnull),
mState1(0),
mValue2(nsnull),
mState2(0),
mValue3(nsnull),
mState3(0),
mDefaultState(0),
mDefinedIfAbsent(false)
{}
nsStateMapEntry::nsStateMapEntry(PRUint64 aDefaultState,
PRUint64 aExclusingState) :
mAttributeName(nsnull),
mIsToken(false),
mPermanentState(0),
mValue1(nsnull),
mState1(0),
mValue2(nsnull),
mState2(0),
mValue3(nsnull),
mState3(0),
mDefaultState(aDefaultState),
mDefinedIfAbsent(false),
mExcludingState(aExclusingState)
{
}
nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName, eStateValueType aType,
PRUint64 aPermanentState,
PRUint64 aTrueState,
PRUint64 aFalseState,
bool aDefinedIfAbsent) :
mAttributeName(aAttrName),
mIsToken(true),
mPermanentState(aPermanentState),
mValue1("false"),
mState1(aFalseState),
mValue2(nsnull),
mState2(0),
mValue3(nsnull),
mState3(0),
mDefaultState(aTrueState),
mDefinedIfAbsent(aDefinedIfAbsent),
mExcludingState(0)
{
if (aType == kMixedType) {
mValue2 = "mixed";
mState2 = states::MIXED;
}
}
nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName,
const char* aValue1, PRUint64 aState1,
const char* aValue2, PRUint64 aState2,
const char* aValue3, PRUint64 aState3) :
mAttributeName(aAttrName), mIsToken(false), mPermanentState(0),
mValue1(aValue1), mState1(aState1),
mValue2(aValue2), mState2(aState2),
mValue3(aValue3), mState3(aState3),
mDefaultState(0), mDefinedIfAbsent(false), mExcludingState(0)
{
}
nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName,
EDefaultStateRule aDefaultStateRule,
const char* aValue1, PRUint64 aState1,
const char* aValue2, PRUint64 aState2,
const char* aValue3, PRUint64 aState3) :
mAttributeName(aAttrName), mIsToken(true), mPermanentState(0),
mValue1(aValue1), mState1(aState1),
mValue2(aValue2), mState2(aState2),
mValue3(aValue3), mState3(aState3),
mDefaultState(0), mDefinedIfAbsent(true), mExcludingState(0)
{
if (aDefaultStateRule == eUseFirstState)
mDefaultState = aState1;
}
bool
nsStateMapEntry::MapToStates(nsIContent* aContent, PRUint64* aState,
eStateMapEntryID aStateMapEntryID)
{
// Return true if we should continue.
if (aStateMapEntryID == eARIANone)
return false;
const nsStateMapEntry& entry = nsARIAMap::gWAIStateMap[aStateMapEntryID];
// Non ARIA attribute case. Expose default state until excluding state is
// presented.
if (!entry.mAttributeName) {
if (!(*aState & entry.mExcludingState))
*aState |= entry.mDefaultState;
return true;
}
if (entry.mIsToken) {
// If attribute is considered as defined when it's absent then let's act
// attribute value is "false" supposedly.
bool hasAttr = aContent->HasAttr(kNameSpaceID_None, *entry.mAttributeName);
if (entry.mDefinedIfAbsent && !hasAttr) {
if (entry.mPermanentState)
*aState |= entry.mPermanentState;
if (entry.mState1)
*aState |= entry.mState1;
return true;
}
// We only have attribute state mappings for NMTOKEN (and boolean) based
// ARIA attributes. According to spec, a value of "undefined" is to be
// treated equivalent to "", or the absence of the attribute. We bail out
// for this case here.
// Note: If this method happens to be called with a non-token based
// attribute, for example: aria-label="" or aria-label="undefined", we will
// bail out and not explore a state mapping, which is safe.
if (!hasAttr ||
aContent->AttrValueIs(kNameSpaceID_None, *entry.mAttributeName,
nsGkAtoms::_empty, eCaseMatters) ||
aContent->AttrValueIs(kNameSpaceID_None, *entry.mAttributeName,
nsGkAtoms::_undefined, eCaseMatters)) {
if (entry.mPermanentState)
*aState &= ~entry.mPermanentState;
return true;
}
if (entry.mPermanentState)
*aState |= entry.mPermanentState;
}
nsAutoString attrValue;
if (!aContent->GetAttr(kNameSpaceID_None, *entry.mAttributeName, attrValue))
return true;
// Apply states for matched value. If no values was matched then apply default
// states.
bool applyDefaultStates = true;
if (entry.mValue1) {
if (attrValue.EqualsASCII(entry.mValue1)) {
applyDefaultStates = false;
if (entry.mState1)
*aState |= entry.mState1;
} else if (entry.mValue2) {
if (attrValue.EqualsASCII(entry.mValue2)) {
applyDefaultStates = false;
if (entry.mState2)
*aState |= entry.mState2;
} else if (entry.mValue3) {
if (attrValue.EqualsASCII(entry.mValue3)) {
applyDefaultStates = false;
if (entry.mState3)
*aState |= entry.mState3;
}
}
}
}
if (applyDefaultStates) {
if (entry.mDefaultState)
*aState |= entry.mDefaultState;
}
return true;
}

View File

@ -40,6 +40,7 @@
#ifndef _nsARIAMap_H_
#define _nsARIAMap_H_
#include "mozilla/a11y/ARIAStateMap.h"
#include "mozilla/a11y/Role.h"
#include "prtypes.h"
@ -153,126 +154,12 @@ struct nsAttributeCharacteristics
*/
#define kNoReqStates 0
enum eStateValueType
{
kBoolType,
kMixedType
};
enum EDefaultStateRule
{
//eNoDefaultState,
eUseFirstState
};
/**
* ID for state map entry, used in nsRoleMapEntry.
*/
enum eStateMapEntryID
{
eARIANone,
eARIAAutoComplete,
eARIABusy,
eARIACheckableBool,
eARIACheckableMixed,
eARIACheckedMixed,
eARIADisabled,
eARIAExpanded,
eARIAHasPopup,
eARIAInvalid,
eARIAMultiline,
eARIAMultiSelectable,
eARIAOrientation,
eARIAPressed,
eARIAReadonly,
eARIAReadonlyOrEditable,
eARIARequired,
eARIASelectable,
eReadonlyUntilEditable
};
class nsStateMapEntry
{
public:
/**
* Used to create stub.
*/
nsStateMapEntry();
/**
* Used to expose permanent states presented until accessible has an excluding
* state.
*/
nsStateMapEntry(PRUint64 aDefaultState, PRUint64 aExclusingState);
/**
* Used for ARIA attributes having boolean or mixed values.
*/
nsStateMapEntry(nsIAtom** aAttrName, eStateValueType aType,
PRUint64 aPermanentState,
PRUint64 aTrueState,
PRUint64 aFalseState = 0,
bool aDefinedIfAbsent = false);
/**
* Used for ARIA attributes having enumerated values.
*/
nsStateMapEntry(nsIAtom** aAttrName,
const char* aValue1, PRUint64 aState1,
const char* aValue2, PRUint64 aState2,
const char* aValue3 = 0, PRUint64 aState3 = 0);
/**
* Used for ARIA attributes having enumerated values, and where a default
* attribute state should be assumed when not supplied by the author.
*/
nsStateMapEntry(nsIAtom** aAttrName, EDefaultStateRule aDefaultStateRule,
const char* aValue1, PRUint64 aState1,
const char* aValue2, PRUint64 aState2,
const char* aValue3 = 0, PRUint64 aState3 = 0);
/**
* Maps ARIA state map pointed by state map entry ID to accessible states.
*
* @param aContent [in] node of the accessible
* @param aState [in/out] accessible states
* @param aStateMapEntryID [in] state map entry ID
* @return true if state map entry ID is valid
*/
static bool MapToStates(nsIContent* aContent, PRUint64* aState,
eStateMapEntryID aStateMapEntryID);
private:
// ARIA attribute name
nsIAtom** mAttributeName;
// Indicates if attribute is token (can be undefined)
bool mIsToken;
// State applied always if attribute is defined
PRUint64 mPermanentState;
// States applied if attribute value is matched to the stored value
const char* mValue1;
PRUint64 mState1;
const char* mValue2;
PRUint64 mState2;
const char* mValue3;
PRUint64 mState3;
// States applied if no stored values above are matched
PRUint64 mDefaultState;
// Permanent and false states are applied if attribute is absent
bool mDefinedIfAbsent;
// If this state is presented in state bits then default state is not exposed.
PRUint64 mExcludingState;
};
////////////////////////////////////////////////////////////////////////////////
// Role map entry
@ -302,15 +189,15 @@ struct nsRoleMapEntry
// Automatic state mapping rule: always include in nsIAccessibleStates
PRUint64 state; // or kNoReqStates if no nsIAccessibleStates are automatic for this role.
// ARIA properties supported for this role
// (in other words, the aria-foo attribute to nsIAccessibleStates mapping rules)
// Currently you cannot have unlimited mappings, because
// a variable sized array would not allow the use of
// C++'s struct initialization feature.
eStateMapEntryID attributeMap1;
eStateMapEntryID attributeMap2;
eStateMapEntryID attributeMap3;
mozilla::a11y::aria::EStateRule attributeMap1;
mozilla::a11y::aria::EStateRule attributeMap2;
mozilla::a11y::aria::EStateRule attributeMap3;
};
@ -343,17 +230,12 @@ struct nsARIAMap
*/
static nsRoleMapEntry gEmptyRoleMap;
/**
* State map of ARIA state attributes.
*/
static nsStateMapEntry gWAIStateMap[];
/**
* State map of ARIA states applied to any accessible not depending on
* the role.
*/
static eStateMapEntryID gWAIUnivStateMap[];
static mozilla::a11y::aria::EStateRule gWAIUnivStateMap[];
/**
* Map of attribute to attribute characteristics.
*/
@ -364,11 +246,12 @@ struct nsARIAMap
* Return accessible state from ARIA universal states applied to the given
* element.
*/
static PRUint64 UniversalStatesFor(nsIContent* aContent)
static PRUint64 UniversalStatesFor(mozilla::dom::Element* aElement)
{
PRUint64 state = 0;
PRUint32 index = 0;
while (nsStateMapEntry::MapToStates(aContent, &state, gWAIUnivStateMap[index]))
while (mozilla::a11y::aria::MapToState(gWAIUnivStateMap[index],
aElement, &state))
index++;
return state;

View File

@ -1609,8 +1609,13 @@ nsAccessible::State()
void
nsAccessible::ApplyARIAState(PRUint64* aState)
{
if (!mContent->IsElement())
return;
dom::Element* element = mContent->AsElement();
// Test for universal states first
*aState |= nsARIAMap::UniversalStatesFor(mContent);
*aState |= nsARIAMap::UniversalStatesFor(element);
if (mRoleMapEntry) {
@ -1650,16 +1655,11 @@ nsAccessible::ApplyARIAState(PRUint64* aState)
return;
*aState |= mRoleMapEntry->state;
if (nsStateMapEntry::MapToStates(mContent, aState,
mRoleMapEntry->attributeMap1) &&
nsStateMapEntry::MapToStates(mContent, aState,
mRoleMapEntry->attributeMap2)) {
nsStateMapEntry::MapToStates(mContent, aState,
mRoleMapEntry->attributeMap3);
}
}
// Not implemented by this class
if (aria::MapToState(mRoleMapEntry->attributeMap1, element, aState) &&
aria::MapToState(mRoleMapEntry->attributeMap2, element, aState))
aria::MapToState(mRoleMapEntry->attributeMap3, element, aState);
}
/* DOMString getValue (); */
NS_IMETHODIMP
@ -2825,9 +2825,9 @@ nsAccessible::IsSelect()
// accessible so that we can follow COM identity rules.
return mRoleMapEntry &&
(mRoleMapEntry->attributeMap1 == eARIAMultiSelectable ||
mRoleMapEntry->attributeMap2 == eARIAMultiSelectable ||
mRoleMapEntry->attributeMap3 == eARIAMultiSelectable);
(mRoleMapEntry->attributeMap1 == aria::eARIAMultiSelectable ||
mRoleMapEntry->attributeMap2 == aria::eARIAMultiSelectable ||
mRoleMapEntry->attributeMap3 == aria::eARIAMultiSelectable);
}
already_AddRefed<nsIArray>

View File

@ -64,7 +64,6 @@ class nsHyperTextAccessible;
class nsHTMLImageAccessible;
class nsHTMLImageMapAccessible;
class nsHTMLLIAccessible;
struct nsRoleMapEntry;
class Relation;
namespace mozilla {
namespace a11y {

View File

@ -432,7 +432,7 @@ nsHTMLTextFieldAccessible::ApplyARIAState(PRUint64* aState)
{
nsHyperTextAccessibleWrap::ApplyARIAState(aState);
nsStateMapEntry::MapToStates(mContent, aState, eARIAAutoComplete);
aria::MapToState(aria::eARIAAutoComplete, mContent->AsElement(), aState);
}
PRUint64

View File

@ -754,7 +754,7 @@ nsXULTextFieldAccessible::ApplyARIAState(PRUint64* aState)
{
nsHyperTextAccessibleWrap::ApplyARIAState(aState);
nsStateMapEntry::MapToStates(mContent, aState, eARIAAutoComplete);
aria::MapToState(aria::eARIAAutoComplete, mContent->AsElement(), aState);
}

View File

@ -2037,6 +2037,7 @@ GK_ATOM(datatable, "datatable")
GK_ATOM(droppable, "droppable")
GK_ATOM(eventFromInput, "event-from-input")
GK_ATOM(InlineBlockFrame, "InlineBlockFrame")
GK_ATOM(inlinevalue, "inline")
GK_ATOM(invalid, "invalid")
GK_ATOM(item, "item")
GK_ATOM(itemset, "itemset")