mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 1572677: Correct a11y exposure for HTML elements with associated XUL labels. r=MarcoZ
A XUL <label control="id"> can refer to an HTML element. Keyboard and mouse support for this already works, but previously, this wasn't being exposed via accessibility APIs. 1. Split the code to get the name from an associated XUL label out of Accessible::XULElmName into a new function Accessible::NameFromAssociatedXULLabel. 2. Use NameFromAssociatedXULLabel for HTMl elements. 3. Update AccessKey and RelationByType to support HTML elements with associated XUL labels. 4. Rename accessible/tests/mochitest/actions/test_keys_menu.xhtml to test_keys.xhtml so it can cover accessKey outside of menus. 5. Add tests. Differential Revision: https://phabricator.services.mozilla.com/D55057 --HG-- rename : accessible/tests/mochitest/actions/test_keys_menu.xhtml => accessible/tests/mochitest/actions/test_keys.xhtml extra : moz-landing-system : lando
This commit is contained in:
parent
42c2ecdc42
commit
8d5f485ca6
@ -230,8 +230,8 @@ KeyBinding Accessible::AccessKey() const {
|
||||
HTMLLabelIterator iter(Document(), this,
|
||||
HTMLLabelIterator::eSkipAncestorLabel);
|
||||
label = iter.Next();
|
||||
|
||||
} else if (mContent->IsXULElement()) {
|
||||
}
|
||||
if (!label) {
|
||||
XULLabelIterator iter(Document(), mContent);
|
||||
label = iter.Next();
|
||||
}
|
||||
@ -753,6 +753,21 @@ void Accessible::TakeFocus() const {
|
||||
}
|
||||
}
|
||||
|
||||
void Accessible::NameFromAssociatedXULLabel(DocAccessible* aDocument,
|
||||
nsIContent* aElm, nsString& aName) {
|
||||
Accessible* label = nullptr;
|
||||
XULLabelIterator iter(aDocument, aElm);
|
||||
while ((label = iter.Next())) {
|
||||
// Check if label's value attribute is used
|
||||
label->Elm()->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName);
|
||||
if (aName.IsEmpty()) {
|
||||
// If no value attribute, a non-empty label must contain
|
||||
// children that define its text -- possibly using HTML
|
||||
nsTextEquivUtils::AppendTextEquivFromContent(label, label->Elm(), &aName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Accessible::XULElmName(DocAccessible* aDocument, nsIContent* aElm,
|
||||
nsString& aName) {
|
||||
/**
|
||||
@ -786,18 +801,7 @@ void Accessible::XULElmName(DocAccessible* aDocument, nsIContent* aElm,
|
||||
// CASES #2 and #3 ------ label as a child or <label control="id" ... >
|
||||
// </label>
|
||||
if (aName.IsEmpty()) {
|
||||
Accessible* label = nullptr;
|
||||
XULLabelIterator iter(aDocument, aElm);
|
||||
while ((label = iter.Next())) {
|
||||
// Check if label's value attribute is used
|
||||
label->Elm()->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName);
|
||||
if (aName.IsEmpty()) {
|
||||
// If no value attribute, a non-empty label must contain
|
||||
// children that define its text -- possibly using HTML
|
||||
nsTextEquivUtils::AppendTextEquivFromContent(label, label->Elm(),
|
||||
&aName);
|
||||
}
|
||||
}
|
||||
NameFromAssociatedXULLabel(aDocument, aElm, aName);
|
||||
}
|
||||
|
||||
aName.CompressWhitespace();
|
||||
@ -1620,9 +1624,8 @@ Relation Accessible::RelationByType(RelationType aType) const {
|
||||
new IDRefsIterator(mDoc, mContent, nsGkAtoms::aria_labelledby));
|
||||
if (mContent->IsHTMLElement()) {
|
||||
rel.AppendIter(new HTMLLabelIterator(Document(), this));
|
||||
} else if (mContent->IsXULElement()) {
|
||||
rel.AppendIter(new XULLabelIterator(Document(), mContent));
|
||||
}
|
||||
rel.AppendIter(new XULLabelIterator(Document(), mContent));
|
||||
|
||||
return rel;
|
||||
}
|
||||
@ -1979,6 +1982,11 @@ ENameValueFlag Accessible::NativeName(nsString& aName) const {
|
||||
|
||||
if (!aName.IsEmpty()) return eNameOK;
|
||||
|
||||
NameFromAssociatedXULLabel(mDoc, mContent, aName);
|
||||
if (!aName.IsEmpty()) {
|
||||
return eNameOK;
|
||||
}
|
||||
|
||||
nsTextEquivUtils::GetNameFromSubtree(this, aName);
|
||||
return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
|
||||
}
|
||||
|
@ -1075,6 +1075,13 @@ class Accessible : public nsISupports {
|
||||
*/
|
||||
void ARIAName(nsString& aName) const;
|
||||
|
||||
/**
|
||||
* Returns the accessible name specified for this control using XUL
|
||||
* <label control="id" ...>.
|
||||
*/
|
||||
static void NameFromAssociatedXULLabel(DocAccessible* aDocument,
|
||||
nsIContent* aElm, nsString& aName);
|
||||
|
||||
/**
|
||||
* Return the name for XUL element.
|
||||
*/
|
||||
|
@ -9,7 +9,7 @@ support-files =
|
||||
[test_general.html]
|
||||
[test_general.xhtml]
|
||||
[test_keys.html]
|
||||
[test_keys_menu.xhtml]
|
||||
[test_keys.xhtml]
|
||||
[test_link.html]
|
||||
[test_media.html]
|
||||
[test_select.html]
|
||||
|
@ -4,6 +4,7 @@
|
||||
type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
title="Accessible XUL access keys and shortcut keys tests">
|
||||
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
@ -17,8 +18,8 @@
|
||||
<![CDATA[
|
||||
function openMenu(aMenuID, aMenuitemID)
|
||||
{
|
||||
this.menuNode = getNode(aMenuID),
|
||||
this.menuitemNode = getNode(aMenuitemID),
|
||||
this.menuNode = getNode(aMenuID);
|
||||
this.menuitemNode = getNode(aMenuitemID);
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_FOCUS, this.menuNode)
|
||||
@ -53,6 +54,11 @@
|
||||
var gQueue = null;
|
||||
function doTest()
|
||||
{
|
||||
// HTML element should get accessKey from associated XUL label.
|
||||
let input = getAccessible("input");
|
||||
is(input.accessKey, (MAC ? "⌃⌥i" : "Alt+Shift+i"),
|
||||
"Wrong accessKey on input");
|
||||
|
||||
gQueue = new eventQueue();
|
||||
gQueue.push(new openMenu("menu", "menuitem"));
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
@ -78,6 +84,9 @@
|
||||
</body>
|
||||
|
||||
<vbox flex="1">
|
||||
<label control="input" accesskey="i">input</label>
|
||||
<html:input id="input"/>
|
||||
|
||||
<keyset>
|
||||
<key key="l" modifiers="control" id="key1"/>
|
||||
</keyset>
|
@ -100,6 +100,9 @@
|
||||
// Multiple labels for single button: XUL button takes the last one.
|
||||
testName("btn_label_4", "label5");
|
||||
|
||||
// Label associated with HTML element.
|
||||
testName("input_label", "input label");
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// tooltiptext (if nothing above isn't presented then tooltiptext is used)
|
||||
@ -267,6 +270,9 @@
|
||||
<label control="btn_label_4">label4</label>
|
||||
<label control="btn_label_4">label5</label>
|
||||
<button id="btn_label_4"/>
|
||||
|
||||
<label control="input_label">input label</label>
|
||||
<html:input id="input_label"/>
|
||||
</hbox>
|
||||
|
||||
<!-- tooltiptext -->
|
||||
|
@ -4,6 +4,7 @@
|
||||
type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
title="nsIAccessible::getAccessibleRelated() tests">
|
||||
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
@ -38,6 +39,10 @@
|
||||
testRelation("label4", RELATION_LABEL_FOR, "checkbox3");
|
||||
testRelation("checkbox3", RELATION_LABELLED_BY, ["label3", "label4"]);
|
||||
|
||||
// xul:label@control referring to HTML element
|
||||
testRelation("label_input", RELATION_LABEL_FOR, "input");
|
||||
testRelation("input", RELATION_LABELLED_BY, "label_input");
|
||||
|
||||
// aria-describedby
|
||||
testRelation("descr1", RELATION_DESCRIPTION_FOR, "checkbox4");
|
||||
testRelation("checkbox4", RELATION_DESCRIBED_BY, "descr1");
|
||||
@ -158,6 +163,9 @@
|
||||
<description role="checkbox" id="checkbox3"
|
||||
aria-labelledby="label3 label4"/>
|
||||
|
||||
<label id="label_input" control="input">label</label>
|
||||
<html:input id="input"/>
|
||||
|
||||
<description id="descr1">description</description>
|
||||
<description role="checkbox" id="checkbox4" aria-describedby="descr1"/>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user