Bug 989958 - Expose PRESSED state on a native button element and remove CHECKABLE state from toggle buttons, r=surkov, r=eeejay

This commit is contained in:
Marco Zehe 2014-04-04 10:01:19 +02:00
parent 69a1f77b38
commit 1d98675396
16 changed files with 75 additions and 42 deletions

View File

@ -86,9 +86,9 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
ePressAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIAPressed
eButton,
kNoReqStates
// eARIAPressed is auto applied on any button
},
{ // checkbox
&nsGkAtoms::checkbox,

View File

@ -245,7 +245,7 @@ aria::MapToState(EStateRule aRule, dom::Element* aElement, uint64_t* aState)
{
static const TokenTypeData data(
nsGkAtoms::aria_pressed, eMixedType,
states::CHECKABLE, states::PRESSED);
0, states::PRESSED);
MapTokenType(aElement, aState, data);
return true;

View File

@ -69,16 +69,17 @@ enum AccType {
enum AccGenericType {
eAutoComplete = 1 << 0,
eAutoCompletePopup = 1 << 1,
eCombobox = 1 << 2,
eDocument = 1 << 3,
eHyperText = 1 << 4,
eList = 1 << 5,
eListControl = 1 << 6,
eMenuButton = 1 << 7,
eSelect = 1 << 8,
eTable = 1 << 9,
eTableCell = 1 << 10,
eTableRow = 1 << 11,
eButton = 1 << 2,
eCombobox = 1 << 3,
eDocument = 1 << 4,
eHyperText = 1 << 5,
eList = 1 << 6,
eListControl = 1 << 7,
eMenuButton = 1 << 8,
eSelect = 1 << 9,
eTable = 1 << 10,
eTableCell = 1 << 11,
eTableRow = 1 << 12,
eLastAccGenericType = eTableRow
};

View File

@ -1573,6 +1573,10 @@ Accessible::ApplyARIAState(uint64_t* aState) const
}
}
// special case: A native button element whose role got transformed by ARIA to a toggle button
if (IsButton())
aria::MapToState(aria::eARIAPressed, element, aState);
if (!mRoleMapEntry)
return;

View File

@ -521,6 +521,8 @@ public:
bool IsAutoCompletePopup() const
{ return HasGenericType(eAutoCompletePopup); }
bool IsButton() const { return HasGenericType(eButton); }
bool IsCombobox() const { return HasGenericType(eCombobox); }
bool IsDoc() const { return HasGenericType(eDocument); }
@ -990,7 +992,7 @@ protected:
static const uint8_t kStateFlagsBits = 7;
static const uint8_t kContextFlagsBits = 1;
static const uint8_t kTypeBits = 6;
static const uint8_t kGenericTypesBits = 12;
static const uint8_t kGenericTypesBits = 13;
/**
* Keep in sync with ChildrenFlags, StateFlags, ContextFlags, and AccTypes.

View File

@ -1066,17 +1066,10 @@ DocAccessible::ARIAAttributeChanged(Accessible* aAccessible, nsIAtom* aAttribute
aAccessible);
nsIContent* elm = aAccessible->GetContent();
if (!elm->HasAttr(kNameSpaceID_None, nsGkAtoms::role)) {
// We don't care about these other ARIA attribute changes unless there is
// an ARIA role set for the element
// XXX: we should check the role map to see if the changed property is
// relevant for that particular role.
return;
}
// The following ARIA attributes only take affect when dynamic content role is present
if (aAttribute == nsGkAtoms::aria_checked ||
aAttribute == nsGkAtoms::aria_pressed) {
(aAccessible->IsButton() &&
aAttribute == nsGkAtoms::aria_pressed)) {
const uint64_t kState = (aAttribute == nsGkAtoms::aria_checked) ?
states::CHECKED : states::PRESSED;
nsRefPtr<AccEvent> event = new AccStateChangeEvent(aAccessible, kState);

View File

@ -180,6 +180,7 @@ HTMLButtonAccessible::
HTMLButtonAccessible(nsIContent* aContent, DocAccessible* aDoc) :
HyperTextAccessibleWrap(aContent, aDoc)
{
mGenericTypes |= eButton;
}
uint8_t

View File

@ -632,6 +632,11 @@ this.UtteranceGenerator = {
stateUtterances.push(Utils.stringBundle.GetStringFromName(statetr));
}
if (aState.contains(States.PRESSED)) {
stateUtterances.push(
Utils.stringBundle.GetStringFromName('statePressed'));
}
if (aState.contains(States.EXPANDABLE)) {
let statetr = aState.contains(States.EXPANDED) ?
'stateExpanded' : 'stateCollapsed';
@ -783,7 +788,7 @@ this.BrailleGenerator = {
_useStateNotRole: function _useStateNotRole(aAccessible, aRoleStr, aState, aFlags) {
let braille = [];
let desc = this._getLocalizedState(aState);
let desc = this._getLocalizedState(aState, aAccessible.role);
braille.push(desc.join(' '));
this._addName(braille, aAccessible, aFlags);
@ -831,24 +836,25 @@ this.BrailleGenerator = {
}
},
_getLocalizedState: function _getLocalizedState(aState) {
_getLocalizedState: function _getLocalizedState(aState, aRole) {
let stateBraille = [];
let getCheckedState = function getCheckedState() {
let getResultMarker = function getResultMarker(aMarker) {
// aMarker is a simple boolean.
let resultMarker = [];
let state = aState;
let fill = state.contains(States.CHECKED) ||
state.contains(States.PRESSED);
resultMarker.push('(');
resultMarker.push(fill ? 'x' : ' ');
resultMarker.push(aMarker ? 'x' : ' ');
resultMarker.push(')');
return resultMarker.join('');
};
if (aState.contains(States.CHECKABLE)) {
stateBraille.push(getCheckedState());
stateBraille.push(getResultMarker(aState.contains(States.CHECKED)));
}
if (aRole === Roles.TOGGLE_BUTTON) {
stateBraille.push(getResultMarker(aState.contains(States.PRESSED)));
}
return stateBraille;

View File

@ -40,8 +40,11 @@ XULButtonAccessible::
XULButtonAccessible(nsIContent* aContent, DocAccessible* aDoc) :
AccessibleWrap(aContent, aDoc)
{
if (ContainsMenu())
if (ContainsMenu()) {
mGenericTypes |= eMenuButton;
} else {
mGenericTypes |= eButton;
}
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -133,6 +133,7 @@
gQueue.push(new busyify("aria_doc", false));
buildQueueForAttrOfMixedType(gQueue, "pressable", setPressed);
buildQueueForAttrOfMixedType(gQueue, "pressable_native", setPressed);
buildQueueForAttrOfMixedType(gQueue, "checkable", setChecked);
gQueue.invoke(); // Will call SimpleTest.finish();
@ -160,6 +161,11 @@
title="mixed state change event is fired for focused accessible only"
Mozilla Bug 467143
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=989958"
title="Pressed state is not exposed on a button element with aria-pressed attribute"
Mozilla Bug 989958
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
@ -176,6 +182,7 @@
<!-- aria-pressed -->
<div id="pressable" role="button"></div>
<button id="pressable_native"></button>
<!-- aria-checked -->
<div id="checkable" role="checkbox"></div>

View File

@ -329,14 +329,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984
["a unique radio button", "(x)"]]
},{
accOrElmOrID: "togglebutton_notpressed",
expectedUtterance: [["not checked toggle button", "I ain't pressed"],
["I ain't pressed", "not checked toggle button"]],
expectedUtterance: [["toggle button", "I ain't pressed"],
["I ain't pressed", "toggle button"]],
expectedBraille: [["( )", "I ain't pressed"],
["I ain't pressed", "( )"]]
},{
accOrElmOrID: "togglebutton_pressed",
expectedUtterance: [["not checked toggle button", "I am pressed!"],
["I am pressed!", "not checked toggle button"]],
expectedUtterance: [["pressed toggle button", "I am pressed!"],
["I am pressed!", "pressed toggle button"]],
expectedBraille: [["(x)", "I am pressed!"],
["I am pressed!", "(x)"]]
}

View File

@ -140,7 +140,8 @@ function testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState,
}
// checked/mixed/checkable
if (state & STATE_CHECKED || state & STATE_MIXED && role != ROLE_PROGRESSBAR)
if (state & STATE_CHECKED || state & STATE_MIXED &&
role != ROLE_TOGGLE_BUTTON && role != ROLE_PROGRESSBAR)
isState(state & STATE_CHECKABLE, STATE_CHECKABLE, false,
"Checked or mixed element must be checkable!");

View File

@ -105,7 +105,8 @@
STATE_MULTISELECTABLE | STATE_EXTSELECTABLE);
// aria-pressed
testStates("aria_pressed_button", STATE_PRESSED | STATE_CHECKABLE);
testStates("aria_pressed_button", STATE_PRESSED, 0, STATE_CHECKABLE);
testStates("aria_pressed_native_button", STATE_PRESSED, 0, STATE_CHECKABLE);
// aria-readonly
testStates("aria_readonly_textbox", STATE_READONLY);
@ -313,6 +314,11 @@
title="ARIA grid should be editable by default">
Mozilla Bug 835121
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=989958"
title="Pressed state is not exposed on a button element with aria-pressed attribute"
Mozilla Bug 989958
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
@ -349,6 +355,7 @@
<div id="aria_multiline_textbox" role="textbox" aria-multiline="true"></div>
<div id="aria_multiselectable_listbox" role="listbox" aria-multiselectable="true"></div>
<div id="aria_pressed_button" role="button" aria-pressed="true">Button</div>
<button id="aria_pressed_native_button" aria-pressed="true">Button</button>
<div id="aria_readonly_textbox"
role="textbox" aria-readonly="true">This text should be readonly</div>

View File

@ -28,8 +28,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
testRole("button_pressed_absent", ROLE_PUSHBUTTON);
// test button aria-pressed states
testStates("button_pressed_true", STATE_PRESSED | STATE_CHECKABLE);
testStates("button_pressed_false", STATE_CHECKABLE, 0, STATE_PRESSED);
testStates("button_pressed_true", STATE_PRESSED, 0, STATE_CHECKABLE);
testStates("button_pressed_false", 0, 0, STATE_CHECKABLE | STATE_PRESSED);
testStates("button_pressed_empty", 0, 0, STATE_PRESSED | STATE_CHECKABLE);
testStates("button_pressed_undefined", 0, 0, STATE_PRESSED | STATE_CHECKABLE);
testStates("button_pressed_absent", 0, 0, STATE_PRESSED | STATE_CHECKABLE);
@ -183,6 +183,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
title="Unify ARIA state attributes mapping rules">
Mozilla Bug 499653
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=989958"
title="Pressed state is not exposed on a button element with aria-pressed attribute"
Mozilla Bug 989958
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">

View File

@ -580,6 +580,7 @@ GK_ATOM(minimum_scale, "minimum-scale")
GK_ATOM(minpos, "minpos")
GK_ATOM(minusSign, "minus-sign")
GK_ATOM(minwidth, "minwidth")
GK_ATOM(_mixed, "mixed")
GK_ATOM(mod, "mod")
GK_ATOM(mode, "mode")
GK_ATOM(modifiers, "modifiers")

View File

@ -156,6 +156,8 @@ tabReload = reloading
# Object states
stateChecked = checked
stateNotChecked = not checked
statePressed = pressed
# No string for a not pressed toggle button
stateExpanded = expanded
stateCollapsed = collapsed
stateUnavailable = unavailable