diff options
Diffstat (limited to 'WebCore/accessibility/AccessibilityObject.cpp')
-rw-r--r-- | WebCore/accessibility/AccessibilityObject.cpp | 80 |
1 files changed, 79 insertions, 1 deletions
diff --git a/WebCore/accessibility/AccessibilityObject.cpp b/WebCore/accessibility/AccessibilityObject.cpp index d6fd969..d7093e4 100644 --- a/WebCore/accessibility/AccessibilityObject.cpp +++ b/WebCore/accessibility/AccessibilityObject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -41,6 +41,7 @@ #include "NotImplemented.h" #include "Page.h" #include "RenderImage.h" +#include "RenderListItem.h" #include "RenderListMarker.h" #include "RenderMenuList.h" #include "RenderTextControl.h" @@ -89,6 +90,35 @@ AccessibilityObject* AccessibilityObject::parentObjectUnignored() const return parent; } +AccessibilityObject* AccessibilityObject::firstAccessibleObjectFromNode(const Node* node) +{ + ASSERT(AXObjectCache::accessibilityEnabled()); + + if (!node) + return 0; + + Document* document = node->document(); + if (!document) + return 0; + + AXObjectCache* cache = document->axObjectCache(); + + AccessibilityObject* accessibleObject = cache->getOrCreate(node->renderer()); + while (accessibleObject && accessibleObject->accessibilityIsIgnored()) { + node = node->traverseNextNode(); + + while (node && !node->renderer()) + node = node->traverseNextSibling(); + + if (!node) + return 0; + + accessibleObject = cache->getOrCreate(node->renderer()); + } + + return accessibleObject; +} + bool AccessibilityObject::isARIAInput(AccessibilityRole ariaRole) { return ariaRole == RadioButtonRole || ariaRole == CheckBoxRole || ariaRole == TextFieldRole; @@ -363,6 +393,49 @@ static bool replacedNodeNeedsCharacter(Node* replacedNode) return true; } +// Finds a RenderListItem parent give a node. +RenderListItem* AccessibilityObject::renderListItemContainerForNode(Node* node) const +{ + for (Node* stringNode = node; stringNode; stringNode = stringNode->parent()) { + RenderObject* renderObject = stringNode->renderer(); + if (!renderObject || !renderObject->isListItem()) + continue; + + return toRenderListItem(renderObject); + } + + return 0; +} + +// Returns the text associated with a list marker if this node is contained within a list item. +String AccessibilityObject::listMarkerTextForNodeAndPosition(Node* node, const VisiblePosition& visiblePositionStart) const +{ + // If the range does not contain the start of the line, the list marker text should not be included. + if (!isStartOfLine(visiblePositionStart)) + return String(); + + RenderListItem* listItem = renderListItemContainerForNode(node); + if (!listItem) + return String(); + + // If this is in a list item, we need to manually add the text for the list marker + // because a RenderListMarker does not have a Node equivalent and thus does not appear + // when iterating text. + const String& markerText = listItem->markerText(); + if (markerText.isEmpty()) + return String(); + + // Append text, plus the period that follows the text. + // FIXME: Not all list marker styles are followed by a period, but this + // sounds much better when there is a synthesized pause because of a period. + Vector<UChar> resultVector; + resultVector.append(markerText.characters(), markerText.length()); + resultVector.append('.'); + resultVector.append(' '); + + return String::adopt(resultVector); +} + String AccessibilityObject::stringForVisiblePositionRange(const VisiblePositionRange& visiblePositionRange) const { if (visiblePositionRange.isNull()) @@ -373,6 +446,11 @@ String AccessibilityObject::stringForVisiblePositionRange(const VisiblePositionR for (TextIterator it(range.get()); !it.atEnd(); it.advance()) { // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX) if (it.length() != 0) { + // Add a textual representation for list marker text + String listMarkerText = listMarkerTextForNodeAndPosition(it.node(), visiblePositionRange.start); + if (!listMarkerText.isEmpty()) + resultVector.append(listMarkerText.characters(), listMarkerText.length()); + resultVector.append(it.characters(), it.length()); } else { // locate the node and starting offset for this replaced range |