[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.16-1409-g5afdf4d
cfleizach at apple.com
cfleizach at apple.com
Thu Dec 3 13:24:38 UTC 2009
The following commit has been merged in the webkit-1.1 branch:
commit 28d2677eed2eca890a0951d2ce83e6d943c7877a
Author: cfleizach at apple.com <cfleizach at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Mon Nov 2 16:57:47 2009 +0000
Support ARIA "tab" roles
https://bugs.webkit.org/show_bug.cgi?id=30842
Reviewed by Beth Dakin.
WebCore:
Implement support for ARIA "tab", "tabpanel" and "tablist".
As a consequence, we also needed to implement aria-selected
and aria-controls.
Tests: accessibility/aria-controls-with-tabs.html
accessibility/aria-tab-roles.html
* accessibility/AXObjectCache.cpp:
* accessibility/AccessibilityObject.h:
* accessibility/AccessibilityRenderObject.cpp:
* accessibility/AccessibilityRenderObject.h:
* accessibility/mac/AccessibilityObjectWrapper.mm:
* html/HTMLAttributeNames.in:
WebKit:
Add a localizable string for tab panel.
* English.lproj/Localizable.strings:
* StringsNotToBeLocalized.txt:
WebKit/mac:
* WebCoreSupport/WebViewFactory.mm:
(-[WebViewFactory AXARIAContentGroupText:]):
WebKitTools:
* DumpRenderTree/AccessibilityUIElement.cpp:
* DumpRenderTree/AccessibilityUIElement.h:
* DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp:
* DumpRenderTree/mac/AccessibilityUIElementMac.mm:
* DumpRenderTree/win/AccessibilityUIElementWin.cpp:
LayoutTests:
* accessibility/aria-controls-with-tabs-expected.txt: Added.
* accessibility/aria-controls-with-tabs.html: Added.
* accessibility/aria-tab-roles.html: Added.
* platform/gtk/Skipped:
* platform/mac/accessibility/aria-tab-roles-expected.txt: Added.
* platform/win/Skipped:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@50409 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index f80dff8..c9c7b42 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,17 @@
+2009-11-02 Chris Fleizach <cfleizach at apple.com>
+
+ Reviewed by Beth Dakin.
+
+ Support ARIA "tab" roles
+ https://bugs.webkit.org/show_bug.cgi?id=30842
+
+ * accessibility/aria-controls-with-tabs-expected.txt: Added.
+ * accessibility/aria-controls-with-tabs.html: Added.
+ * accessibility/aria-tab-roles.html: Added.
+ * platform/gtk/Skipped:
+ * platform/mac/accessibility/aria-tab-roles-expected.txt: Added.
+ * platform/win/Skipped:
+
2009-11-02 Roland Steiner <rolandsteiner at chromium.org>
Reviewed by Dave Hyatt.
diff --git a/LayoutTests/accessibility/aria-controls-with-tabs-expected.txt b/LayoutTests/accessibility/aria-controls-with-tabs-expected.txt
new file mode 100644
index 0000000..7e3bcbf
--- /dev/null
+++ b/LayoutTests/accessibility/aria-controls-with-tabs-expected.txt
@@ -0,0 +1,21 @@
+Crust
+Veges
+Test
+
+Select Crust
+
+Select Crust
+
+This tests that the aria tab item becomes selected if either aria-selected is used, or if aria-controls points to an item that contains KB focus.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS tab2.isSelected is true
+PASS tab1.isSelected is false
+PASS tab2.isSelected is false
+PASS tab1.isSelected is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/accessibility/aria-controls-with-tabs.html b/LayoutTests/accessibility/aria-controls-with-tabs.html
new file mode 100644
index 0000000..382e99e
--- /dev/null
+++ b/LayoutTests/accessibility/aria-controls-with-tabs.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../fast/js/resources/js-test-style.css">
+<script>
+var successfullyParsed = false;
+</script>
+<script src="../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body id="body">
+
+<ul id="tablist_1" role="tablist">
+<li id="tab_1" role="tab" tabindex="-1" class="">Crust</li>
+<li id="tab_2" role="tab" tabindex="-1" aria-controls="panel_2" class="">Veges</li>
+</ul>
+
+<h3 tabindex=0 id="elementOutsideTabs">Test</h3>
+
+<div id="panel_1" role="tabpanel" >
+<h3 tabindex=0>Select Crust</h3>
+</div>
+
+<div id="panel_2" role="tabpanel" >
+<h2 id="itemInPanel2" tabindex=0>Select Crust</h2>
+</div>
+
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+
+ description("This tests that the aria tab item becomes selected if either aria-selected is used, or if aria-controls points to an item that contains KB focus.");
+
+ if (window.accessibilityController) {
+
+ var body = accessibilityController.rootElement;
+ var tabList = body.childAtIndex(0).childAtIndex(0);
+ var tab1 = tabList.childAtIndex(0);
+ var tab2 = tabList.childAtIndex(1);
+
+ // we set KB focus to something in panel_2, which means that tab2 should become selected
+ // because it aria-controls panel_2
+ var panel2Item = document.getElementById("itemInPanel2");
+ panel2Item.focus();
+
+ shouldBe("tab2.isSelected", "true");
+
+ // reset KB focus and verify that neither tab is selected
+ document.getElementById("elementOutsideTabs").focus();
+ shouldBe("tab1.isSelected", "false");
+ shouldBe("tab2.isSelected", "false");
+
+ // Now we set aria-selected to be true on tab1 so that it should become selected
+ document.getElementById("tab_1").setAttribute("aria-selected", "true");
+ shouldBe("tab1.isSelected", "true");
+ }
+
+ successfullyParsed = true;
+</script>
+
+<script src="../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/accessibility/aria-tab-roles.html b/LayoutTests/accessibility/aria-tab-roles.html
new file mode 100644
index 0000000..d2a424b
--- /dev/null
+++ b/LayoutTests/accessibility/aria-tab-roles.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../fast/js/resources/js-test-style.css">
+<script>
+var successfullyParsed = false;
+</script>
+<script src="../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body id="body">
+
+<ul id="tablist_1" role="tablist">
+<li id="tab_1" role="tab" tabindex="0" class="">Crust</li>
+<li id="tab_2" role="tab" tabindex="0" class="">Veges</li>
+</ul>
+
+<div id="panel_1" role="tabpanel" aria-labelledby="tab_1" >
+<h3>Select Crust</h3>
+</div>
+
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+
+ description("This tests that the aria roles for tab, tabpanel and tablist work as expected correctly.");
+
+ if (window.accessibilityController) {
+
+ var body = document.getElementById("body");
+ body.focus();
+
+ var tabList = accessibilityController.focusedElement.childAtIndex(0);
+ var tab1 = tabList.childAtIndex(0);
+ var tab2 = tabList.childAtIndex(1);
+ var tabPanel = accessibilityController.focusedElement.childAtIndex(1);
+
+ shouldBe("tabList.role", "'AXRole: AXTabGroup'");
+ shouldBe("tab1.role", "'AXRole: AXRadioButton'");
+ shouldBe("tab1.title", "'AXTitle: Crust'");
+ shouldBe("tab1.childrenCount", "0");
+ shouldBe("tab2.role", "'AXRole: AXRadioButton'");
+ shouldBe("tab2.title", "'AXTitle: Veges'");
+ shouldBe("tabPanel.role", "'AXRole: AXGroup'");
+ shouldBe("tabPanel.subrole", "'AXSubrole: AXTabPanel'");
+ }
+
+ successfullyParsed = true;
+</script>
+
+<script src="../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/platform/gtk/Skipped b/LayoutTests/platform/gtk/Skipped
index bc0d2ad..c70dcf3 100644
--- a/LayoutTests/platform/gtk/Skipped
+++ b/LayoutTests/platform/gtk/Skipped
@@ -49,6 +49,7 @@ accessibility/aria-label.html
accessibility/aria-labelledby-stay-within.html
accessibility/aria-link-supports-press.html
accessibility/aria-readonly.html
+accessibility/aria-tab-roles.html
accessibility/button-press-action.html
accessibility/canvas.html
accessibility/editable-webarea-context-menu-point.html
diff --git a/LayoutTests/platform/mac/accessibility/aria-tab-roles-expected.txt b/LayoutTests/platform/mac/accessibility/aria-tab-roles-expected.txt
new file mode 100644
index 0000000..fd9cae3
--- /dev/null
+++ b/LayoutTests/platform/mac/accessibility/aria-tab-roles-expected.txt
@@ -0,0 +1,21 @@
+Crust
+Veges
+Select Crust
+
+This tests that the aria roles for tab, tabpanel and tablist work as expected correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS tabList.role is 'AXRole: AXTabGroup'
+PASS tab1.role is 'AXRole: AXRadioButton'
+PASS tab1.title is 'AXTitle: Crust'
+PASS tab1.childrenCount is 0
+PASS tab2.role is 'AXRole: AXRadioButton'
+PASS tab2.title is 'AXTitle: Veges'
+PASS tabPanel.role is 'AXRole: AXGroup'
+PASS tabPanel.subrole is 'AXSubrole: AXTabPanel'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/win/Skipped b/LayoutTests/platform/win/Skipped
index d8a7e32..2cb1413 100644
--- a/LayoutTests/platform/win/Skipped
+++ b/LayoutTests/platform/win/Skipped
@@ -363,6 +363,7 @@ accessibility/aria-presentational-role.html
accessibility/aria-readonly.html
accessibility/aria-roles.html
accessibility/aria-tables.html
+accessibility/aria-tab-roles.html
accessibility/button-press-action.html
accessibility/canvas.html
accessibility/editable-webarea-context-menu-point.html
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 0da74fc..4dee88d 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,24 @@
+2009-11-02 Chris Fleizach <cfleizach at apple.com>
+
+ Reviewed by Beth Dakin.
+
+ Support ARIA "tab" roles
+ https://bugs.webkit.org/show_bug.cgi?id=30842
+
+ Implement support for ARIA "tab", "tabpanel" and "tablist".
+ As a consequence, we also needed to implement aria-selected
+ and aria-controls.
+
+ Tests: accessibility/aria-controls-with-tabs.html
+ accessibility/aria-tab-roles.html
+
+ * accessibility/AXObjectCache.cpp:
+ * accessibility/AccessibilityObject.h:
+ * accessibility/AccessibilityRenderObject.cpp:
+ * accessibility/AccessibilityRenderObject.h:
+ * accessibility/mac/AccessibilityObjectWrapper.mm:
+ * html/HTMLAttributeNames.in:
+
2009-10-27 Stephen White <senorblanco at chromium.org>
Reviewed by Dmitry Titov.
diff --git a/WebCore/accessibility/AXObjectCache.cpp b/WebCore/accessibility/AXObjectCache.cpp
index 55199a3..5fff690 100644
--- a/WebCore/accessibility/AXObjectCache.cpp
+++ b/WebCore/accessibility/AXObjectCache.cpp
@@ -141,7 +141,10 @@ AccessibilityObject* AXObjectCache::getOrCreate(RenderObject* renderer)
RefPtr<AccessibilityObject> newObj = 0;
if (renderer->isListBox())
newObj = AccessibilityListBox::create(renderer);
- else if (node && (nodeIsAriaType(node, "list") || node->hasTagName(ulTag) || node->hasTagName(olTag) || node->hasTagName(dlTag)))
+
+ // If the node is aria role="list" or the aria role is empty and its a ul/ol/dl type (it shouldn't be a list if aria says otherwise).
+ else if (node && (nodeIsAriaType(node, "list")
+ || (nodeIsAriaType(node, nullAtom) && (node->hasTagName(ulTag) || node->hasTagName(olTag) || node->hasTagName(dlTag)))))
newObj = AccessibilityList::create(renderer);
// aria tables
diff --git a/WebCore/accessibility/AccessibilityObject.h b/WebCore/accessibility/AccessibilityObject.h
index cf5d676..d2cf3aa 100644
--- a/WebCore/accessibility/AccessibilityObject.h
+++ b/WebCore/accessibility/AccessibilityObject.h
@@ -161,6 +161,9 @@ enum AccessibilityRole {
AnnotationRole,
SliderThumbRole,
IgnoredRole,
+ TabRole,
+ TabListRole,
+ TabPanelRole,
// ARIA Grouping roles
LandmarkApplicationRole,
@@ -269,6 +272,8 @@ public:
virtual bool isTableCell() const { return false; };
virtual bool isFieldset() const { return false; };
virtual bool isGroup() const { return false; };
+ bool isTabList() const { return roleValue() == TabListRole; }
+ bool isTabItem() const { return roleValue() == TabRole; }
bool isRadioGroup() const { return roleValue() == RadioGroupRole; }
virtual bool isChecked() const { return false; };
@@ -304,6 +309,7 @@ public:
virtual float maxValueForRange() const { return 0.0f; }
virtual float minValueForRange() const { return 0.0f; }
virtual AccessibilityObject* selectedRadioButton() { return 0; }
+ virtual AccessibilityObject* selectedTabItem() { return 0; }
virtual int layoutCount() const { return 0; }
static bool isARIAControl(AccessibilityRole);
static bool isARIAInput(AccessibilityRole);
@@ -332,7 +338,6 @@ public:
void setRoleValue(AccessibilityRole role) { m_role = role; }
virtual AccessibilityRole roleValue() const { return m_role; }
- virtual String ariaAccessibilityName(const String&) const { return String(); }
virtual String ariaLabeledByAttribute() const { return String(); }
virtual String ariaDescribedByAttribute() const { return String(); }
virtual String accessibilityDescription() const { return String(); }
@@ -393,6 +398,7 @@ public:
virtual bool hasChildren() const { return m_haveChildren; }
virtual void selectedChildren(AccessibilityChildrenVector&) { }
virtual void visibleChildren(AccessibilityChildrenVector&) { }
+ virtual void tabChildren(AccessibilityChildrenVector&) { }
virtual bool shouldFocusActiveDescendant() const { return false; }
virtual AccessibilityObject* activeDescendant() const { return 0; }
virtual void handleActiveDescendantChanged() { }
diff --git a/WebCore/accessibility/AccessibilityRenderObject.cpp b/WebCore/accessibility/AccessibilityRenderObject.cpp
index c293dcd..2d22268 100644
--- a/WebCore/accessibility/AccessibilityRenderObject.cpp
+++ b/WebCore/accessibility/AccessibilityRenderObject.cpp
@@ -505,6 +505,24 @@ AccessibilityObject* AccessibilityRenderObject::selectedRadioButton()
}
return 0;
}
+
+AccessibilityObject* AccessibilityRenderObject::selectedTabItem()
+{
+ if (!isTabList())
+ return 0;
+
+ // Find the child tab item that is selected (ie. the intValue == 1).
+ AccessibilityObject::AccessibilityChildrenVector tabs;
+ tabChildren(tabs);
+
+ int count = tabs.size();
+ for (int i = 0; i < count; ++i) {
+ AccessibilityObject* object = m_children[i].get();
+ if (object->isTabItem() && object->intValue() == 1)
+ return object;
+ }
+ return 0;
+}
const AtomicString& AccessibilityRenderObject::getAttribute(const QualifiedName& attribute) const
{
@@ -864,56 +882,67 @@ static String accessibleNameForNode(Node* node)
return String();
}
-String AccessibilityRenderObject::ariaAccessibilityName(const String& s) const
+String AccessibilityRenderObject::accessibilityDescriptionForElements(Vector<Element*> &elements) const
+{
+ Vector<UChar> ariaLabel;
+ unsigned size = elements.size();
+ for (unsigned i = 0; i < size; ++i) {
+ Element* idElement = elements[i];
+
+ String nameFragment = accessibleNameForNode(idElement);
+ ariaLabel.append(nameFragment.characters(), nameFragment.length());
+ for (Node* n = idElement->firstChild(); n; n = n->traverseNextNode(idElement)) {
+ nameFragment = accessibleNameForNode(n);
+ ariaLabel.append(nameFragment.characters(), nameFragment.length());
+ }
+
+ if (i != size - 1)
+ ariaLabel.append(' ');
+ }
+ return String::adopt(ariaLabel);
+}
+
+
+void AccessibilityRenderObject::elementsFromAttribute(Vector<Element*>& elements, const QualifiedName& attribute) const
{
+ Node* node = m_renderer->node();
+ if (!node || !node->isElementNode())
+ return;
+
Document* document = m_renderer->document();
if (!document)
- return String();
-
- String idList = s;
+ return;
+
+ String idList = getAttribute(attribute).string();
+ if (idList.isEmpty())
+ return;
+
idList.replace('\n', ' ');
Vector<String> idVector;
idList.split(' ', idVector);
-
- Vector<UChar> ariaLabel;
+
unsigned size = idVector.size();
for (unsigned i = 0; i < size; ++i) {
String idName = idVector[i];
Element* idElement = document->getElementById(idName);
- if (idElement) {
- String nameFragment = accessibleNameForNode(idElement);
- ariaLabel.append(nameFragment.characters(), nameFragment.length());
- for (Node* n = idElement->firstChild(); n; n = n->traverseNextNode(idElement)) {
- nameFragment = accessibleNameForNode(n);
- ariaLabel.append(nameFragment.characters(), nameFragment.length());
- }
-
- if (i != size - 1)
- ariaLabel.append(' ');
- }
+ if (idElement)
+ elements.append(idElement);
}
- return String::adopt(ariaLabel);
}
-
+
+void AccessibilityRenderObject::ariaLabeledByElements(Vector<Element*>& elements) const
+{
+ elementsFromAttribute(elements, aria_labeledbyAttr);
+ if (!elements.size())
+ elementsFromAttribute(elements, aria_labelledbyAttr);
+}
+
String AccessibilityRenderObject::ariaLabeledByAttribute() const
{
- Node* node = m_renderer->node();
- if (!node)
- return String();
-
- if (!node->isElementNode())
- return String();
-
- // The ARIA spec uses the British spelling: "labelled." It seems prudent to support the American
- // spelling ("labeled") as well.
- String idList = getAttribute(aria_labeledbyAttr).string();
- if (idList.isEmpty()) {
- idList = getAttribute(aria_labelledbyAttr).string();
- if (idList.isEmpty())
- return String();
- }
-
- return ariaAccessibilityName(idList);
+ Vector<Element*> elements;
+ ariaLabeledByElements(elements);
+
+ return accessibilityDescriptionForElements(elements);
}
static HTMLLabelElement* labelForElement(Element* element)
@@ -990,6 +1019,7 @@ String AccessibilityRenderObject::title() const
|| ariaRole == MenuItemRole
|| ariaRole == MenuButtonRole
|| ariaRole == RadioButtonRole
+ || ariaRole == TabRole
|| isHeading())
return textUnderElement();
@@ -1001,11 +1031,10 @@ String AccessibilityRenderObject::title() const
String AccessibilityRenderObject::ariaDescribedByAttribute() const
{
- String idList = getAttribute(aria_describedbyAttr).string();
- if (idList.isEmpty())
- return String();
+ Vector<Element*> elements;
+ elementsFromAttribute(elements, aria_describedbyAttr);
- return ariaAccessibilityName(idList);
+ return accessibilityDescriptionForElements(elements);
}
String AccessibilityRenderObject::accessibilityDescription() const
@@ -1562,9 +1591,55 @@ bool AccessibilityRenderObject::isSelected() const
if (!node)
return false;
+ if (equalIgnoringCase(getAttribute(aria_selectedAttr).string(), "true"))
+ return true;
+
+ if (isTabItem() && isTabItemSelected())
+ return true;
+
return false;
}
+bool AccessibilityRenderObject::isTabItemSelected() const
+{
+ if (!isTabItem() || !m_renderer)
+ return false;
+
+ Node* node = m_renderer->node();
+ if (!node || !node->isElementNode())
+ return false;
+
+ // The ARIA spec says a tab item can also be selected if it is aria-labeled by a tabpanel
+ // that has keyboard focus inside of it, or if a tabpanel in its aria-controls list has KB
+ // focus inside of it.
+ AccessibilityObject* focusedElement = focusedUIElement();
+ if (!focusedElement)
+ return false;
+
+ Vector<Element*> elements;
+ elementsFromAttribute(elements, aria_controlsAttr);
+
+ unsigned count = elements.size();
+ for (unsigned k = 0; k < count; ++k) {
+ Element* element = elements[k];
+ AccessibilityObject* tabPanel = axObjectCache()->getOrCreate(element->renderer());
+
+ // A tab item should only control tab panels.
+ if (!tabPanel || tabPanel->roleValue() != TabPanelRole)
+ continue;
+
+ AccessibilityObject* checkFocusElement = focusedElement;
+ // Check if the focused element is a descendant of the element controlled by the tab item.
+ while (checkFocusElement) {
+ if (tabPanel == checkFocusElement)
+ return true;
+ checkFocusElement = checkFocusElement->parentObject();
+ }
+ }
+
+ return false;
+}
+
bool AccessibilityRenderObject::isFocused() const
{
if (!m_renderer)
@@ -2302,6 +2377,9 @@ static const ARIARoleMap& createARIARoleMap()
{ "slider", SliderRole },
{ "spinbutton", ProgressIndicatorRole },
{ "status", ApplicationStatusRole },
+ { "tab", TabRole },
+ { "tablist", TabListRole },
+ { "tabpanel", TabPanelRole },
{ "textbox", TextAreaRole },
{ "timer", ApplicationTimerRole },
{ "toolbar", ToolbarRole },
@@ -2536,6 +2614,7 @@ bool AccessibilityRenderObject::canHaveChildren() const
case PopUpButtonRole:
case CheckBoxRole:
case RadioButtonRole:
+ case TabRole:
case StaticTextRole:
case ListBoxOptionRole:
return false;
@@ -2625,7 +2704,7 @@ void AccessibilityRenderObject::ariaListboxSelectedChildren(AccessibilityChildre
if (childRenderer && ariaRole == ListBoxOptionRole) {
Element* childElement = static_cast<Element*>(childRenderer->node());
if (childElement && childElement->isElementNode()) { // do this check to ensure safety of static_cast above
- String selectedAttrString = childElement->getAttribute("aria-selected").string();
+ String selectedAttrString = childElement->getAttribute(aria_selectedAttr).string();
if (equalIgnoringCase(selectedAttrString, "true")) {
result.append(child);
if (isMultiselectable)
@@ -2673,6 +2752,17 @@ void AccessibilityRenderObject::visibleChildren(AccessibilityChildrenVector& res
return ariaListboxVisibleChildren(result);
}
+void AccessibilityRenderObject::tabChildren(AccessibilityChildrenVector& result)
+{
+ ASSERT(roleValue() == TabListRole);
+
+ unsigned length = m_children.size();
+ for (unsigned i = 0; i < length; ++i) {
+ if (m_children[i]->isTabItem())
+ result.append(m_children[i]);
+ }
+}
+
const String& AccessibilityRenderObject::actionVerb() const
{
// FIXME: Need to add verbs for select elements.
diff --git a/WebCore/accessibility/AccessibilityRenderObject.h b/WebCore/accessibility/AccessibilityRenderObject.h
index 14b7e34..f265fbe 100644
--- a/WebCore/accessibility/AccessibilityRenderObject.h
+++ b/WebCore/accessibility/AccessibilityRenderObject.h
@@ -120,6 +120,7 @@ public:
virtual float maxValueForRange() const;
virtual float minValueForRange() const;
virtual AccessibilityObject* selectedRadioButton();
+ virtual AccessibilityObject* selectedTabItem();
virtual int layoutCount() const;
virtual AccessibilityObject* doAccessibilityHitTest(const IntPoint&) const;
@@ -168,7 +169,6 @@ public:
virtual PlainTextRange selectedTextRange() const;
virtual VisibleSelection selection() const;
virtual String stringValue() const;
- virtual String ariaAccessibilityName(const String&) const;
virtual String ariaLabeledByAttribute() const;
virtual String title() const;
virtual String ariaDescribedByAttribute() const;
@@ -202,6 +202,7 @@ public:
virtual bool canHaveChildren() const;
virtual void selectedChildren(AccessibilityChildrenVector&);
virtual void visibleChildren(AccessibilityChildrenVector&);
+ virtual void tabChildren(AccessibilityChildrenVector&);
virtual bool shouldFocusActiveDescendant() const;
virtual AccessibilityObject* activeDescendant() const;
virtual void handleActiveDescendantChanged();
@@ -237,6 +238,7 @@ protected:
mutable bool m_childrenDirty;
void setRenderObject(RenderObject* renderer) { m_renderer = renderer; }
+ void ariaLabeledByElements(Vector<Element*>& elements) const;
virtual bool isDetached() const { return !m_renderer; }
@@ -251,12 +253,16 @@ private:
AccessibilityRole determineAccessibilityRole();
AccessibilityRole determineAriaRoleAttribute() const;
+ bool isTabItemSelected() const;
IntRect checkboxOrRadioRect() const;
void addRadioButtonGroupMembers(AccessibilityChildrenVector& linkedUIElements) const;
AccessibilityObject* internalLinkElement() const;
AccessibilityObject* accessibilityImageMapHitTest(HTMLAreaElement*, const IntPoint&) const;
AccessibilityObject* accessibilityParentForImageMap(HTMLMapElement* map) const;
+ String accessibilityDescriptionForElements(Vector<Element*> &elements) const;
+ void elementsFromAttribute(Vector<Element*>& elements, const QualifiedName& name) const;
+
void markChildrenDirty() const { m_childrenDirty = true; }
};
diff --git a/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm b/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm
index 58e5018..009986b 100644
--- a/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm
+++ b/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm
@@ -600,6 +600,7 @@ static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePositi
static NSArray* groupAttrs = nil;
static NSArray* inputImageAttrs = nil;
static NSArray* passwordFieldAttrs = nil;
+ static NSArray *tabListAttrs = nil;
NSMutableArray* tempArray;
if (attributes == nil) {
attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
@@ -794,6 +795,13 @@ static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePositi
passwordFieldAttrs = [[NSArray alloc] initWithArray:tempArray];
[tempArray release];
}
+ if (tabListAttrs == nil) {
+ tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+ [tempArray addObject:NSAccessibilityTabsAttribute];
+ [tempArray addObject:NSAccessibilityContentsAttribute];
+ tabListAttrs = [[NSArray alloc] initWithArray:tempArray];
+ [tempArray release];
+ }
if (m_object->isPasswordField())
return passwordFieldAttrs;
@@ -830,6 +838,8 @@ static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePositi
if (m_object->isGroup())
return groupAttrs;
+ if (m_object->isTabList())
+ return tabListAttrs;
if (m_object->isMenu())
return menuAttrs;
@@ -1001,8 +1011,9 @@ static const AccessibilityRoleMap& createAccessibilityRoleMap()
{ DocumentNoteRole, NSAccessibilityGroupRole },
{ DocumentRegionRole, NSAccessibilityGroupRole },
{ UserInterfaceTooltipRole, NSAccessibilityGroupRole },
-
-
+ { TabRole, NSAccessibilityRadioButtonRole },
+ { TabListRole, NSAccessibilityTabGroupRole },
+ { TabPanelRole, NSAccessibilityGroupRole },
};
AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;
@@ -1083,6 +1094,8 @@ static NSString* roleValueToNSString(AccessibilityRole value)
return @"AXDocumentRegion";
case UserInterfaceTooltipRole:
return @"AXUserInterfaceTooltip";
+ case TabPanelRole:
+ return @"AXTabPanel";
default:
return nil;
}
@@ -1140,6 +1153,8 @@ static NSString* roleValueToNSString(AccessibilityRole value)
return AXARIAContentGroupText(@"ARIADocumentRegion");
case UserInterfaceTooltipRole:
return AXARIAContentGroupText(@"ARIAUserInterfaceTooltip");
+ case TabPanelRole:
+ return AXARIAContentGroupText(@"ARIATabPanel");
}
}
@@ -1158,6 +1173,10 @@ static NSString* roleValueToNSString(AccessibilityRole value)
if ([axRole isEqualToString:@"AXHeading"])
return AXHeadingText();
+ // AppKit also returns AXTab for the role description for a tab item.
+ if (m_object->isTabItem())
+ return NSAccessibilityRoleDescription(@"AXTab", nil);
+
// We should try the system default role description for all other roles.
// If we get the same string back, then as a last resort, return unknown.
NSString* defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]);
@@ -1318,6 +1337,16 @@ static NSString* roleValueToNSString(AccessibilityRole value)
return radioButton->wrapper();
}
+ if (m_object->isTabList()) {
+ AccessibilityObject* tabItem = m_object->selectedTabItem();
+ if (!tabItem)
+ return nil;
+ return tabItem->wrapper();
+ }
+
+ if (m_object->isTabItem())
+ return [NSNumber numberWithInt:m_object->isSelected()];
+
return m_object->stringValue();
}
@@ -1359,6 +1388,31 @@ static NSString* roleValueToNSString(AccessibilityRole value)
return accessKey;
}
+ if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) {
+ if (m_object->isTabList()) {
+ AccessibilityObject::AccessibilityChildrenVector tabsChildren;
+ m_object->tabChildren(tabsChildren);
+ return convertToNSArray(tabsChildren);
+ }
+ }
+
+ if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) {
+ // The contents of a tab list are all the children except the tabs.
+ if (m_object->isTabList()) {
+ AccessibilityObject::AccessibilityChildrenVector children = m_object->children();
+ AccessibilityObject::AccessibilityChildrenVector tabsChildren;
+ m_object->tabChildren(tabsChildren);
+
+ AccessibilityObject::AccessibilityChildrenVector contents;
+ unsigned childrenSize = children.size();
+ for (unsigned k = 0; k < childrenSize; ++k) {
+ if (tabsChildren.find(children[k]) == WTF::notFound)
+ contents.append(children[k]);
+ }
+ return convertToNSArray(contents);
+ }
+ }
+
if (m_object->isDataTable()) {
// TODO: distinguish between visible and non-visible rows
if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] ||
diff --git a/WebCore/html/HTMLAttributeNames.in b/WebCore/html/HTMLAttributeNames.in
index 340779e..671125e 100644
--- a/WebCore/html/HTMLAttributeNames.in
+++ b/WebCore/html/HTMLAttributeNames.in
@@ -14,6 +14,7 @@ alt
archive
aria-activedescendant
aria-checked
+aria-controls
aria-describedby
aria-disabled
aria-hidden
@@ -24,6 +25,7 @@ aria-level
aria-pressed
aria-readonly
aria-required
+aria-selected
aria-valuemax
aria-valuemin
aria-valuenow
diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog
index 5006da7..e39f2dd 100644
--- a/WebKit/ChangeLog
+++ b/WebKit/ChangeLog
@@ -1,3 +1,15 @@
+2009-11-02 Chris Fleizach <cfleizach at apple.com>
+
+ Reviewed by Beth Dakin.
+
+ Support ARIA "tab" roles
+ https://bugs.webkit.org/show_bug.cgi?id=30842
+
+ Add a localizable string for tab panel.
+
+ * English.lproj/Localizable.strings:
+ * StringsNotToBeLocalized.txt:
+
2009-10-27 Dan Bernstein <mitz at apple.com>
Reviewed by Darin Adler.
diff --git a/WebKit/English.lproj/Localizable.strings b/WebKit/English.lproj/Localizable.strings
index e4a172b..3368a33 100644
Binary files a/WebKit/English.lproj/Localizable.strings and b/WebKit/English.lproj/Localizable.strings differ
diff --git a/WebKit/StringsNotToBeLocalized.txt b/WebKit/StringsNotToBeLocalized.txt
index 3f1964d..7951dd8 100644
--- a/WebKit/StringsNotToBeLocalized.txt
+++ b/WebKit/StringsNotToBeLocalized.txt
@@ -111,6 +111,7 @@
"ARIALandmarkMain"
"ARIALandmarkNavigation"
"ARIALandmarkSearch"
+"ARIATabPanel"
"ARIAUserInterfaceTooltip"
"AXEnhancedUserInterface"
"AccessibleBase"
diff --git a/WebKit/mac/ChangeLog b/WebKit/mac/ChangeLog
index dc26a96..a8c4d9a 100644
--- a/WebKit/mac/ChangeLog
+++ b/WebKit/mac/ChangeLog
@@ -1,3 +1,13 @@
+2009-11-02 Chris Fleizach <cfleizach at apple.com>
+
+ Reviewed by Beth Dakin.
+
+ Support ARIA "tab" roles
+ https://bugs.webkit.org/show_bug.cgi?id=30842
+
+ * WebCoreSupport/WebViewFactory.mm:
+ (-[WebViewFactory AXARIAContentGroupText:]):
+
2009-11-01 Dan Bernstein <mitz at apple.com>
Reviewed by Mark Rowe.
diff --git a/WebKit/mac/WebCoreSupport/WebViewFactory.mm b/WebKit/mac/WebCoreSupport/WebViewFactory.mm
index 79b2959..263ea03 100644
--- a/WebKit/mac/WebCoreSupport/WebViewFactory.mm
+++ b/WebKit/mac/WebCoreSupport/WebViewFactory.mm
@@ -587,6 +587,8 @@
return UI_STRING("search", "An ARIA accessibility group that contains a search feature of a website.");
if ([ariaType isEqualToString:@"ARIAUserInterfaceTooltip"])
return UI_STRING("tooltip", "An ARIA accessibility group that acts as a tooltip.");
+ if ([ariaType isEqualToString:@"ARIATabPanel"])
+ return UI_STRING("tab panel", "An ARIA accessibility group that contenst the content of a tab.");
return nil;
}
diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index 665ca49..b8feca3 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -1,3 +1,16 @@
+2009-11-02 Chris Fleizach <cfleizach at apple.com>
+
+ Reviewed by Beth Dakin.
+
+ Support ARIA "tab" roles
+ https://bugs.webkit.org/show_bug.cgi?id=30842
+
+ * DumpRenderTree/AccessibilityUIElement.cpp:
+ * DumpRenderTree/AccessibilityUIElement.h:
+ * DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp:
+ * DumpRenderTree/mac/AccessibilityUIElementMac.mm:
+ * DumpRenderTree/win/AccessibilityUIElementWin.cpp:
+
2009-11-01 Eric Seidel <eric at webkit.org>
Reviewed by David Levin.
diff --git a/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp b/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp
index 1ed8217..aca4a16 100644
--- a/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp
+++ b/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp
@@ -281,6 +281,12 @@ static JSValueRef getDescriptionCallback(JSContextRef context, JSObjectRef thisO
return JSValueMakeString(context, description.get());
}
+static JSValueRef getStringValueCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+{
+ JSRetainPtr<JSStringRef> stringValue(Adopt, toAXElement(thisObject)->stringValue());
+ return JSValueMakeString(context, stringValue.get());
+}
+
static JSValueRef getLanguageCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
{
JSRetainPtr<JSStringRef> language(Adopt, toAXElement(thisObject)->language());
@@ -358,6 +364,11 @@ static JSValueRef getIsRequiredCallback(JSContextRef context, JSObjectRef thisOb
return JSValueMakeBoolean(context, toAXElement(thisObject)->isRequired());
}
+static JSValueRef getIsSelectedCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef*)
+{
+ return JSValueMakeBoolean(context, toAXElement(thisObject)->isSelected());
+}
+
static JSValueRef getValueDescriptionCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
{
JSRetainPtr<JSStringRef> valueDescription(Adopt, toAXElement(thisObject)->valueDescription());
@@ -393,6 +404,7 @@ JSClassRef AccessibilityUIElement::getJSClass()
{ "title", getTitleCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "description", getDescriptionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "language", getLanguageCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "stringValue", getStringValueCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "x", getXCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "y", getYCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "width", getWidthCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -407,6 +419,7 @@ JSClassRef AccessibilityUIElement::getJSClass()
{ "selectedTextRange", getSelectedTextRangeCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "isEnabled", getIsEnabledCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "isRequired", getIsRequiredCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "isSelected", getIsSelectedCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "valueDescription", getValueDescriptionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ 0, 0, 0, 0 }
};
diff --git a/WebKitTools/DumpRenderTree/AccessibilityUIElement.h b/WebKitTools/DumpRenderTree/AccessibilityUIElement.h
index ea45a27..9a72d41 100644
--- a/WebKitTools/DumpRenderTree/AccessibilityUIElement.h
+++ b/WebKitTools/DumpRenderTree/AccessibilityUIElement.h
@@ -90,6 +90,7 @@ public:
JSStringRef title();
JSStringRef description();
JSStringRef language();
+ JSStringRef stringValue();
JSStringRef accessibilityValue() const;
double x();
double y();
@@ -103,6 +104,7 @@ public:
JSStringRef selectedTextRange();
bool isEnabled();
bool isRequired() const;
+ bool isSelected() const;
double clickPointX();
double clickPointY();
diff --git a/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp b/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp
index e5f26d2..925c658 100644
--- a/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp
+++ b/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp
@@ -181,6 +181,12 @@ JSStringRef AccessibilityUIElement::description()
return JSStringCreateWithUTF8CString(description);
}
+JSStringRef AccessibilityUIElement::stringValue()
+{
+ // FIXME: implement
+ return JSStringCreateWithCharacters(0, 0);
+}
+
JSStringRef AccessibilityUIElement::language()
{
// FIXME: implement
@@ -316,6 +322,12 @@ bool AccessibilityUIElement::isRequired() const
return false;
}
+bool AccessibilityUIElement::isSelected() const
+{
+ // FIXME: implement
+ return false;
+}
+
JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
{
// FIXME: implement
diff --git a/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm b/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm
index ef0f9da..6a41656 100644
--- a/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm
+++ b/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm
@@ -329,6 +329,12 @@ JSStringRef AccessibilityUIElement::description()
return concatenateAttributeAndValue(@"AXDescription", description);
}
+JSStringRef AccessibilityUIElement::stringValue()
+{
+ id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityValueAttribute], m_element);
+ return concatenateAttributeAndValue(@"AXValue", description);
+}
+
JSStringRef AccessibilityUIElement::language()
{
id description = descriptionOfValue([m_element accessibilityAttributeValue:@"AXLanguage"], m_element);
@@ -433,6 +439,14 @@ bool AccessibilityUIElement::isRequired() const
return false;
}
+bool AccessibilityUIElement::isSelected() const
+{
+ id value = [m_element accessibilityAttributeValue:NSAccessibilitySelectedAttribute];
+ if ([value isKindOfClass:[NSNumber class]])
+ return [value boolValue];
+ return false;
+}
+
// parameterized attributes
int AccessibilityUIElement::lineForIndex(int index)
{
diff --git a/WebKitTools/DumpRenderTree/win/AccessibilityUIElementWin.cpp b/WebKitTools/DumpRenderTree/win/AccessibilityUIElementWin.cpp
index 2a8eaf6..1714da1 100644
--- a/WebKitTools/DumpRenderTree/win/AccessibilityUIElementWin.cpp
+++ b/WebKitTools/DumpRenderTree/win/AccessibilityUIElementWin.cpp
@@ -196,6 +196,11 @@ JSStringRef AccessibilityUIElement::description()
return JSStringCreateWithCharacters(description.data(), description.length());
}
+JSStringRef AccessibilityUIElement::stringValue()
+{
+ return JSStringCreateWithCharacters(0, 0);
+}
+
JSStringRef AccessibilityUIElement::language()
{
return JSStringCreateWithCharacters(0, 0);
@@ -284,6 +289,11 @@ bool AccessibilityUIElement::isRequired() const
return false;
}
+bool AccessibilityUIElement::isSelected() const
+{
+ return false;
+}
+
int AccessibilityUIElement::insertionPointLineNumber()
{
return 0;
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list