diff options
author | Kristian Monsen <kristianm@google.com> | 2010-06-28 16:42:48 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2010-07-02 10:29:56 +0100 |
commit | 06ea8e899e48f1f2f396b70e63fae369f2f23232 (patch) | |
tree | 20c1428cd05c76f32394ab354ea35ed99acd86d8 /WebCore/accessibility | |
parent | 72aad67af14193199e29cdd5c4ddc095a8b9a8a8 (diff) | |
download | external_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.zip external_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.tar.gz external_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.tar.bz2 |
Merge WebKit at r61871: Initial merge by git.
Change-Id: I6cff43abca9cc4782e088a469ad4f03f166a65d5
Diffstat (limited to 'WebCore/accessibility')
-rw-r--r-- | WebCore/accessibility/AXObjectCache.cpp | 9 | ||||
-rw-r--r-- | WebCore/accessibility/AXObjectCache.h | 8 | ||||
-rw-r--r-- | WebCore/accessibility/AccessibilityObject.cpp | 4 | ||||
-rw-r--r-- | WebCore/accessibility/AccessibilityObject.h | 6 | ||||
-rw-r--r-- | WebCore/accessibility/AccessibilityRenderObject.cpp | 104 | ||||
-rw-r--r-- | WebCore/accessibility/AccessibilityRenderObject.h | 13 | ||||
-rw-r--r-- | WebCore/accessibility/AccessibilityTableCell.cpp | 2 | ||||
-rw-r--r-- | WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp | 36 | ||||
-rw-r--r-- | WebCore/accessibility/mac/AXObjectCacheMac.mm | 13 | ||||
-rw-r--r-- | WebCore/accessibility/mac/AccessibilityObjectMac.mm | 5 | ||||
-rw-r--r-- | WebCore/accessibility/mac/AccessibilityObjectWrapper.mm | 3 |
11 files changed, 155 insertions, 48 deletions
diff --git a/WebCore/accessibility/AXObjectCache.cpp b/WebCore/accessibility/AXObjectCache.cpp index b7622b8..750c611 100644 --- a/WebCore/accessibility/AXObjectCache.cpp +++ b/WebCore/accessibility/AXObjectCache.cpp @@ -456,6 +456,15 @@ void AXObjectCache::selectedChildrenChanged(RenderObject* renderer) #endif #if HAVE(ACCESSIBILITY) +void AXObjectCache::handleAriaExpandedChange(RenderObject *renderer) +{ + if (!renderer) + return; + AccessibilityObject* obj = getOrCreate(renderer); + if (obj) + obj->handleAriaExpandedChanged(); +} + void AXObjectCache::handleActiveDescendantChanged(RenderObject* renderer) { if (!renderer) diff --git a/WebCore/accessibility/AXObjectCache.h b/WebCore/accessibility/AXObjectCache.h index 25f5347..8d98fa3 100644 --- a/WebCore/accessibility/AXObjectCache.h +++ b/WebCore/accessibility/AXObjectCache.h @@ -88,7 +88,8 @@ public: void handleAriaRoleChanged(RenderObject*); void handleFocusedUIElementChanged(RenderObject* oldFocusedRenderer, RenderObject* newFocusedRenderer); void handleScrolledToAnchor(const Node* anchorNode); - + void handleAriaExpandedChange(RenderObject*); + static void enableAccessibility() { gAccessibilityEnabled = true; } static void enableEnhancedUserInterfaceAccessibility() { gAccessibilityEnhancedUserInterfaceEnabled = true; } @@ -116,6 +117,9 @@ public: AXScrolledToAnchor, AXLiveRegionChanged, AXMenuListValueChanged, + AXRowCountChanged, + AXRowCollapsed, + AXRowExpanded, }; void postNotification(RenderObject*, AXNotification, bool postToElement, PostType = PostAsynchronously); @@ -150,10 +154,12 @@ inline void AXObjectCache::detachWrapper(AccessibilityObject*) { } inline void AXObjectCache::attachWrapper(AccessibilityObject*) { } inline void AXObjectCache::selectedChildrenChanged(RenderObject*) { } inline void AXObjectCache::postNotification(RenderObject*, AXNotification, bool postToElement, PostType) { } +inline void AXObjectCache::postNotification(AccessibilityObject*, Document*, AXNotification, bool postToElement, PostType) { } inline void AXObjectCache::postPlatformNotification(AccessibilityObject*, AXNotification) { } inline void AXObjectCache::handleFocusedUIElementChanged(RenderObject*, RenderObject*) { } inline void AXObjectCache::handleScrolledToAnchor(const Node*) { } inline void AXObjectCache::contentChanged(RenderObject*) { } +inline void AXObjectCache::handleAriaExpandedChange(RenderObject*) { } #endif } diff --git a/WebCore/accessibility/AccessibilityObject.cpp b/WebCore/accessibility/AccessibilityObject.cpp index 8dedc36..555ba6f 100644 --- a/WebCore/accessibility/AccessibilityObject.cpp +++ b/WebCore/accessibility/AccessibilityObject.cpp @@ -902,7 +902,7 @@ static ARIARoleMap* createARIARoleMap() { "img", ImageRole }, { "link", WebCoreLinkRole }, { "list", ListRole }, - { "listitem", GroupRole }, + { "listitem", ListItemRole }, { "listbox", ListBoxRole }, { "log", ApplicationLogRole }, // "option" isn't here because it may map to different roles depending on the parent element's role @@ -917,7 +917,7 @@ static ARIARoleMap* createARIARoleMap() { "note", DocumentNoteRole }, { "navigation", LandmarkNavigationRole }, { "option", ListBoxOptionRole }, - { "presentation", IgnoredRole }, + { "presentation", PresentationalRole }, { "progressbar", ProgressIndicatorRole }, { "radio", RadioButtonRole }, { "radiogroup", RadioGroupRole }, diff --git a/WebCore/accessibility/AccessibilityObject.h b/WebCore/accessibility/AccessibilityObject.h index 8b4923a..3c8d392 100644 --- a/WebCore/accessibility/AccessibilityObject.h +++ b/WebCore/accessibility/AccessibilityObject.h @@ -160,6 +160,7 @@ enum AccessibilityRole { AnnotationRole, SliderThumbRole, IgnoredRole, + PresentationalRole, TabRole, TabListRole, TabPanelRole, @@ -296,6 +297,7 @@ public: bool isTreeItem() const { return roleValue() == TreeItemRole; } bool isScrollbar() const { return roleValue() == ScrollBarRole; } bool isButton() const { return roleValue() == ButtonRole; } + bool isListItem() const { return roleValue() == ListItemRole; } virtual bool isChecked() const { return false; } virtual bool isEnabled() const { return false; } @@ -442,13 +444,15 @@ public: virtual void addChildren() { } virtual bool canHaveChildren() const { return true; } virtual bool hasChildren() const { return m_haveChildren; } + virtual void updateChildrenIfNecessary() { } 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() { } - + virtual void handleAriaExpandedChanged() { } + static AccessibilityRole ariaRoleToWebCoreRole(const String&); static const AtomicString& getAttribute(Node*, const QualifiedName&); diff --git a/WebCore/accessibility/AccessibilityRenderObject.cpp b/WebCore/accessibility/AccessibilityRenderObject.cpp index ffe62f8..1ef6e09 100644 --- a/WebCore/accessibility/AccessibilityRenderObject.cpp +++ b/WebCore/accessibility/AccessibilityRenderObject.cpp @@ -1256,11 +1256,11 @@ static HTMLLabelElement* labelForElement(Element* element) HTMLLabelElement* AccessibilityRenderObject::labelElementContainer() const { if (!m_renderer) - return false; + return 0; // the control element should not be considered part of the label if (isControl()) - return false; + return 0; // find if this has a parent that is a label for (Node* parentNode = m_renderer->node(); parentNode; parentNode = parentNode->parentNode()) { @@ -1735,6 +1735,9 @@ bool AccessibilityRenderObject::accessibilityIsIgnored() const if (roleValue() == IgnoredRole) return true; + if (roleValue() == PresentationalRole || inheritsPresentationalRole()) + return true; + // An ARIA tree can only have tree items and static text as children. if (!isAllowedChildOfTree()) return true; @@ -2829,6 +2832,39 @@ AccessibilityObject* AccessibilityRenderObject::activeDescendant() const return 0; } +void AccessibilityRenderObject::handleAriaExpandedChanged() +{ + // Find if a parent of this object should handle aria-expanded changes. + AccessibilityObject* containerParent = this->parentObject(); + while (containerParent) { + bool foundParent = false; + + switch (containerParent->roleValue()) { + case TreeRole: + case TreeGridRole: + case GridRole: + case TableRole: + case BrowserRole: + foundParent = true; + break; + default: + break; + } + + if (foundParent) + break; + + containerParent = containerParent->parentObject(); + } + + // Post that the row count changed. + if (containerParent) + axObjectCache()->postNotification(containerParent, document(), AXObjectCache::AXRowCountChanged, true); + + // Post that the specific row either collapsed or expanded. + if (roleValue() == RowRole || roleValue() == TreeItemRole) + axObjectCache()->postNotification(this, document(), isExpanded() ? AXObjectCache::AXRowExpanded : AXObjectCache::AXRowCollapsed, true); +} void AccessibilityRenderObject::handleActiveDescendantChanged() { @@ -2954,6 +2990,8 @@ AccessibilityRole AccessibilityRenderObject::determineAccessibilityRole() return ImageMapRole; return WebCoreLinkRole; } + if (m_renderer->isListItem()) + return ListItemRole; if (m_renderer->isListMarker()) return ListMarkerRole; if (node && node->hasTagName(buttonTag)) @@ -3046,6 +3084,49 @@ AccessibilityOrientation AccessibilityRenderObject::orientation() const return AccessibilityObject::orientation(); } +bool AccessibilityRenderObject::inheritsPresentationalRole() const +{ + // ARIA spec says that when a parent object is presentational, and it has required child elements, + // those child elements are also presentational. For example, <li> becomes presentational from <ul>. + // http://www.w3.org/WAI/PF/aria/complete#presentation + DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, listItemParents, ()); + + HashSet<QualifiedName>* possibleParentTagNames = 0; + switch (roleValue()) { + case ListItemRole: + case ListMarkerRole: + if (listItemParents.isEmpty()) { + listItemParents.add(ulTag); + listItemParents.add(olTag); + listItemParents.add(dlTag); + } + possibleParentTagNames = &listItemParents; + break; + default: + break; + } + + // Not all elements need to check for this, only ones that are required children. + if (!possibleParentTagNames) + return false; + + for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) { + if (!parent->isAccessibilityRenderObject()) + continue; + + Node* elementNode = static_cast<AccessibilityRenderObject*>(parent)->node(); + if (!elementNode || !elementNode->isElementNode()) + continue; + + // If native tag of the parent element matches an acceptable name, then return + // based on its presentational status. + if (possibleParentTagNames->contains(static_cast<Element*>(elementNode)->tagQName())) + return parent->roleValue() == PresentationalRole; + } + + return false; +} + bool AccessibilityRenderObject::isPresentationalChildOfAriaRole() const { // Walk the parent chain looking for a parent that has presentational children @@ -3142,18 +3223,16 @@ void AccessibilityRenderObject::contentChanged() void AccessibilityRenderObject::childrenChanged() { - // this method is meant as a quick way of marking dirty - // a portion of the accessibility tree - + // This method is meant as a quick way of marking a portion of the accessibility tree dirty. if (!m_renderer) return; - // Go up the render parent chain, marking children as dirty. - // We can't rely on the accessibilityParent() because it may not exist and we must not create an AX object here either + // Go up the accessibility parent chain, but only if the element already exists. This method is + // called during render layouts, minimal work should be done. + // If AX elements are created now, they could interrogate the render tree while it's in a funky state. // At the same time, process ARIA live region changes. - for (RenderObject* renderParent = m_renderer; renderParent; renderParent = renderParent->parent()) { - AccessibilityObject* parent = m_renderer->document()->axObjectCache()->get(renderParent); - if (!parent || !parent->isAccessibilityRenderObject()) + for (AccessibilityObject* parent = this; parent; parent = parent->parentObjectIfExists()) { + if (!parent->isAccessibilityRenderObject()) continue; AccessibilityRenderObject* axParent = static_cast<AccessibilityRenderObject*>(parent); @@ -3165,7 +3244,7 @@ void AccessibilityRenderObject::childrenChanged() // If this element supports ARIA live regions, then notify the AT of changes. if (axParent->supportsARIALiveRegion()) - axObjectCache()->postNotification(renderParent, AXObjectCache::AXLiveRegionChanged, true); + axObjectCache()->postNotification(axParent->renderer(), AXObjectCache::AXLiveRegionChanged, true); } } } @@ -3232,8 +3311,7 @@ void AccessibilityRenderObject::addChildren() // add all unignored acc children for (RefPtr<AccessibilityObject> obj = firstChild(); obj; obj = obj->nextSibling()) { if (obj->accessibilityIsIgnored()) { - if (!obj->hasChildren()) - obj->addChildren(); + obj->updateChildrenIfNecessary(); AccessibilityChildrenVector children = obj->children(); unsigned length = children.size(); for (unsigned i = 0; i < length; ++i) diff --git a/WebCore/accessibility/AccessibilityRenderObject.h b/WebCore/accessibility/AccessibilityRenderObject.h index 494e6bb..d4f798a 100644 --- a/WebCore/accessibility/AccessibilityRenderObject.h +++ b/WebCore/accessibility/AccessibilityRenderObject.h @@ -30,6 +30,7 @@ #define AccessibilityRenderObject_h #include "AccessibilityObject.h" +#include "RenderObject.h" namespace WebCore { @@ -47,7 +48,6 @@ class HTMLSelectElement; class IntPoint; class IntSize; class Node; -class RenderObject; class RenderListBox; class RenderTextControl; class RenderView; @@ -169,6 +169,11 @@ public: void setRenderer(RenderObject* renderer) { m_renderer = renderer; } RenderObject* renderer() const { return m_renderer; } + Node* node() const + { + return m_renderer ? m_renderer->node() : 0; + }; + RenderView* topRenderer() const; RenderTextControl* textControl() const; Document* document() const; @@ -199,7 +204,7 @@ public: virtual const AccessibilityChildrenVector& children(); virtual void clearChildren(); - void updateChildrenIfNecessary(); + virtual void updateChildrenIfNecessary(); virtual void setFocused(bool); virtual void setSelectedTextRange(const PlainTextRange&); @@ -222,7 +227,8 @@ public: virtual bool shouldFocusActiveDescendant() const; virtual AccessibilityObject* activeDescendant() const; virtual void handleActiveDescendantChanged(); - + virtual void handleAriaExpandedChanged(); + virtual VisiblePositionRange visiblePositionRange() const; virtual VisiblePositionRange visiblePositionRangeForLine(unsigned) const; virtual IntRect boundsForVisiblePositionRange(const VisiblePositionRange&) const; @@ -305,6 +311,7 @@ private: virtual bool ariaLiveRegionAtomic() const; virtual bool ariaLiveRegionBusy() const; + bool inheritsPresentationalRole() const; void setNeedsToUpdateChildren() const { m_childrenDirty = true; } mutable AccessibilityRole m_roleForMSAA; diff --git a/WebCore/accessibility/AccessibilityTableCell.cpp b/WebCore/accessibility/AccessibilityTableCell.cpp index 318c619..7fadb88 100644 --- a/WebCore/accessibility/AccessibilityTableCell.cpp +++ b/WebCore/accessibility/AccessibilityTableCell.cpp @@ -71,7 +71,7 @@ bool AccessibilityTableCell::accessibilityIsIgnored() const AccessibilityObject* AccessibilityTableCell::parentTable() const { if (!m_renderer || !m_renderer->isTableCell()) - return false; + return 0; return axObjectCache()->getOrCreate(toRenderTableCell(m_renderer)->table()); } diff --git a/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp b/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp index 5158774..8e2aa2c 100644 --- a/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp +++ b/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp @@ -143,18 +143,7 @@ static AccessibilityObject* core(AtkDocument* document) return core(ATK_OBJECT(document)); } -static const gchar* nameFromChildren(AccessibilityObject* object) -{ - if (!object) - return 0; - - AccessibilityRenderObject::AccessibilityChildrenVector children = object->children(); - // Currently, object->stringValue() should be an empty String. This might not be the case down the road. - String name = object->stringValue(); - for (unsigned i = 0; i < children.size(); ++i) - name += children.at(i).get()->stringValue(); - return returnString(name); -} +static gchar* webkit_accessible_text_get_text(AtkText* text, gint startOffset, gint endOffset); static const gchar* webkit_accessible_get_name(AtkObject* object) { @@ -165,8 +154,11 @@ static const gchar* webkit_accessible_get_name(AtkObject* object) AccessibilityRenderObject* renderObject = static_cast<AccessibilityRenderObject*>(coreObject); if (coreObject->isControl()) { AccessibilityObject* label = renderObject->correspondingLabelForControlElement(); - if (label) - return returnString(nameFromChildren(label)); + if (label) { + AtkObject* atkObject = label->wrapper(); + if (ATK_IS_TEXT(atkObject)) + return webkit_accessible_text_get_text(ATK_TEXT(atkObject), 0, -1); + } } if (renderObject->isImage() || renderObject->isInputImage()) { @@ -422,6 +414,7 @@ static AtkRole atkRole(AccessibilityRole role) return ATK_ROLE_HEADING; case ListBoxRole: return ATK_ROLE_LIST; + case ListItemRole: case ListBoxOptionRole: return ATK_ROLE_LIST_ITEM; default: @@ -436,13 +429,6 @@ static AtkRole webkit_accessible_get_role(AtkObject* object) if (!axObject) return ATK_ROLE_UNKNOWN; - // WebCore does not seem to have a role for list items - if (axObject->isGroup()) { - AccessibilityObject* parent = axObject->parentObjectUnignored(); - if (parent && parent->isList()) - return ATK_ROLE_LIST_ITEM; - } - // WebCore does not know about paragraph role, label role, or section role if (axObject->isAccessibilityRenderObject()) { Node* node = static_cast<AccessibilityRenderObject*>(axObject)->renderer()->node(); @@ -1501,8 +1487,8 @@ static AtkObject* webkit_accessible_table_get_caption(AtkTable* table) static const gchar* webkit_accessible_table_get_column_description(AtkTable* table, gint column) { AtkObject* columnHeader = atk_table_get_column_header(table, column); - if (columnHeader) - return returnString(nameFromChildren(core(columnHeader))); + if (columnHeader && ATK_IS_TEXT(columnHeader)) + return webkit_accessible_text_get_text(ATK_TEXT(columnHeader), 0, -1); return 0; } @@ -1510,8 +1496,8 @@ static const gchar* webkit_accessible_table_get_column_description(AtkTable* tab static const gchar* webkit_accessible_table_get_row_description(AtkTable* table, gint row) { AtkObject* rowHeader = atk_table_get_row_header(table, row); - if (rowHeader) - return returnString(nameFromChildren(core(rowHeader))); + if (rowHeader && ATK_IS_TEXT(rowHeader)) + return webkit_accessible_text_get_text(ATK_TEXT(rowHeader), 0, -1); return 0; } diff --git a/WebCore/accessibility/mac/AXObjectCacheMac.mm b/WebCore/accessibility/mac/AXObjectCacheMac.mm index 6f886fe..a02bc75 100644 --- a/WebCore/accessibility/mac/AXObjectCacheMac.mm +++ b/WebCore/accessibility/mac/AXObjectCacheMac.mm @@ -91,7 +91,18 @@ void AXObjectCache::postPlatformNotification(AccessibilityObject* obj, AXNotific case AXLiveRegionChanged: macNotification = NSAccessibilityLiveRegionChangedNotification; break; - // Does not exist on Mac. + case AXRowCountChanged: + macNotification = NSAccessibilityRowCountChangedNotification; + break; +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) + case AXRowExpanded: + macNotification = NSAccessibilityRowExpandedNotification; + break; + case AXRowCollapsed: + macNotification = NSAccessibilityRowCollapsedNotification; + break; +#endif + // Does not exist on Mac. case AXCheckedStateChanged: default: return; diff --git a/WebCore/accessibility/mac/AccessibilityObjectMac.mm b/WebCore/accessibility/mac/AccessibilityObjectMac.mm index 37fa65a..1076972 100644 --- a/WebCore/accessibility/mac/AccessibilityObjectMac.mm +++ b/WebCore/accessibility/mac/AccessibilityObjectMac.mm @@ -46,6 +46,11 @@ AccessibilityObjectInclusion AccessibilityObject::accessibilityPlatformIncludesO if (isMenuListPopup() || isMenuListOption()) return IgnoreObject; + // Never expose an unknown object on the Mac. Clients of the AX API will not know what to do with it. + // Special case is when the unknown object is actually an attachment. + if (roleValue() == UnknownRole && !isAttachment()) + return IgnoreObject; + return DefaultBehavior; } diff --git a/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm b/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm index 1fdb0cc..9de7e4d 100644 --- a/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm +++ b/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm @@ -957,7 +957,7 @@ static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePositi else if (m_object->isControl()) objectAttributes = controlAttrs; - else if (m_object->isGroup()) + else if (m_object->isGroup() || m_object->isListItem()) objectAttributes = groupAttrs; else if (m_object->isTabList()) objectAttributes = tabListAttrs; @@ -1148,6 +1148,7 @@ static const AccessibilityRoleMap& createAccessibilityRoleMap() { TabPanelRole, NSAccessibilityGroupRole }, { TreeRole, NSAccessibilityOutlineRole }, { TreeItemRole, NSAccessibilityRowRole }, + { ListItemRole, NSAccessibilityGroupRole } }; AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap; |