+2009-11-02 Chris Fleizach <cfleizach@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@chromium.org>
Reviewed by Dave Hyatt.
--- /dev/null
+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
+
--- /dev/null
+<!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>
--- /dev/null
+<!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>
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
--- /dev/null
+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
+
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
+2009-11-02 Chris Fleizach <cfleizach@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@chromium.org>
Reviewed by Dmitry Titov.
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
AnnotationRole,
SliderThumbRole,
IgnoredRole,
+ TabRole,
+ TabListRole,
+ TabPanelRole,
// ARIA Grouping roles
LandmarkApplicationRole,
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; };
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);
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(); }
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() { }
}
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
{
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)
|| ariaRole == MenuItemRole
|| ariaRole == MenuButtonRole
|| ariaRole == RadioButtonRole
+ || ariaRole == TabRole
|| isHeading())
return textUnderElement();
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
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)
{ "slider", SliderRole },
{ "spinbutton", ProgressIndicatorRole },
{ "status", ApplicationStatusRole },
+ { "tab", TabRole },
+ { "tablist", TabListRole },
+ { "tabpanel", TabPanelRole },
{ "textbox", TextAreaRole },
{ "timer", ApplicationTimerRole },
{ "toolbar", ToolbarRole },
case PopUpButtonRole:
case CheckBoxRole:
case RadioButtonRole:
+ case TabRole:
case StaticTextRole:
case ListBoxOptionRole:
return false;
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)
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.
virtual float maxValueForRange() const;
virtual float minValueForRange() const;
virtual AccessibilityObject* selectedRadioButton();
+ virtual AccessibilityObject* selectedTabItem();
virtual int layoutCount() const;
virtual AccessibilityObject* doAccessibilityHitTest(const IntPoint&) const;
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;
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();
mutable bool m_childrenDirty;
void setRenderObject(RenderObject* renderer) { m_renderer = renderer; }
+ void ariaLabeledByElements(Vector<Element*>& elements) const;
virtual bool isDetached() const { return !m_renderer; }
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; }
};
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,
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;
if (m_object->isGroup())
return groupAttrs;
+ if (m_object->isTabList())
+ return tabListAttrs;
if (m_object->isMenu())
return menuAttrs;
{ DocumentNoteRole, NSAccessibilityGroupRole },
{ DocumentRegionRole, NSAccessibilityGroupRole },
{ UserInterfaceTooltipRole, NSAccessibilityGroupRole },
-
-
+ { TabRole, NSAccessibilityRadioButtonRole },
+ { TabListRole, NSAccessibilityTabGroupRole },
+ { TabPanelRole, NSAccessibilityGroupRole },
};
AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;
return @"AXDocumentRegion";
case UserInterfaceTooltipRole:
return @"AXUserInterfaceTooltip";
+ case TabPanelRole:
+ return @"AXTabPanel";
default:
return nil;
}
return AXARIAContentGroupText(@"ARIADocumentRegion");
case UserInterfaceTooltipRole:
return AXARIAContentGroupText(@"ARIAUserInterfaceTooltip");
+ case TabPanelRole:
+ return AXARIAContentGroupText(@"ARIATabPanel");
}
}
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]);
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();
}
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] ||
archive
aria-activedescendant
aria-checked
+aria-controls
aria-describedby
aria-disabled
aria-hidden
aria-pressed
aria-readonly
aria-required
+aria-selected
aria-valuemax
aria-valuemin
aria-valuenow
+2009-11-02 Chris Fleizach <cfleizach@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@apple.com>
Reviewed by Darin Adler.
"ARIALandmarkMain"
"ARIALandmarkNavigation"
"ARIALandmarkSearch"
+"ARIATabPanel"
"ARIAUserInterfaceTooltip"
"AXEnhancedUserInterface"
"AccessibleBase"
+2009-11-02 Chris Fleizach <cfleizach@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@apple.com>
Reviewed by Mark Rowe.
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;
}
+2009-11-02 Chris Fleizach <cfleizach@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@webkit.org>
Reviewed by David Levin.
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());
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());
{ "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 },
{ "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 }
};
JSStringRef title();
JSStringRef description();
JSStringRef language();
+ JSStringRef stringValue();
JSStringRef accessibilityValue() const;
double x();
double y();
JSStringRef selectedTextRange();
bool isEnabled();
bool isRequired() const;
+ bool isSelected() const;
double clickPointX();
double clickPointY();
return JSStringCreateWithUTF8CString(description);
}
+JSStringRef AccessibilityUIElement::stringValue()
+{
+ // FIXME: implement
+ return JSStringCreateWithCharacters(0, 0);
+}
+
JSStringRef AccessibilityUIElement::language()
{
// FIXME: implement
return false;
}
+bool AccessibilityUIElement::isSelected() const
+{
+ // FIXME: implement
+ return false;
+}
+
JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
{
// FIXME: implement
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);
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)
{
return JSStringCreateWithCharacters(description.data(), description.length());
}
+JSStringRef AccessibilityUIElement::stringValue()
+{
+ return JSStringCreateWithCharacters(0, 0);
+}
+
JSStringRef AccessibilityUIElement::language()
{
return JSStringCreateWithCharacters(0, 0);
return false;
}
+bool AccessibilityUIElement::isSelected() const
+{
+ return false;
+}
+
int AccessibilityUIElement::insertionPointLineNumber()
{
return 0;