summaryrefslogtreecommitdiffstats
path: root/WebCore/accessibility
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-09-29 17:32:26 +0100
committerSteve Block <steveblock@google.com>2010-09-29 17:35:08 +0100
commit68513a70bcd92384395513322f1b801e7bf9c729 (patch)
tree161b50f75a5921d61731bb25e730005994fcec85 /WebCore/accessibility
parentfd5c6425ce58eb75211be7718d5dee960842a37e (diff)
downloadexternal_webkit-68513a70bcd92384395513322f1b801e7bf9c729.zip
external_webkit-68513a70bcd92384395513322f1b801e7bf9c729.tar.gz
external_webkit-68513a70bcd92384395513322f1b801e7bf9c729.tar.bz2
Merge WebKit at r67908: Initial merge by Git
Change-Id: I43a553e7b3299b28cb6ee8aa035ed70fe342b972
Diffstat (limited to 'WebCore/accessibility')
-rw-r--r--[-rwxr-xr-x]WebCore/accessibility/AccessibilityAllInOne.cpp0
-rw-r--r--WebCore/accessibility/AccessibilityObject.cpp17
-rw-r--r--WebCore/accessibility/AccessibilityObject.h2
-rw-r--r--WebCore/accessibility/AccessibilityRenderObject.cpp33
-rw-r--r--WebCore/accessibility/AccessibilityTableRow.cpp3
-rw-r--r--WebCore/accessibility/chromium/AXObjectCacheChromium.cpp50
-rw-r--r--WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp25
-rw-r--r--WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp141
-rw-r--r--WebCore/accessibility/mac/AccessibilityObjectWrapper.mm9
9 files changed, 194 insertions, 86 deletions
diff --git a/WebCore/accessibility/AccessibilityAllInOne.cpp b/WebCore/accessibility/AccessibilityAllInOne.cpp
index 28b1c9b..28b1c9b 100755..100644
--- a/WebCore/accessibility/AccessibilityAllInOne.cpp
+++ b/WebCore/accessibility/AccessibilityAllInOne.cpp
diff --git a/WebCore/accessibility/AccessibilityObject.cpp b/WebCore/accessibility/AccessibilityObject.cpp
index a6bb033..3ddcdc5 100644
--- a/WebCore/accessibility/AccessibilityObject.cpp
+++ b/WebCore/accessibility/AccessibilityObject.cpp
@@ -373,22 +373,7 @@ VisiblePositionRange AccessibilityObject::styleRangeForPosition(const VisiblePos
// NOTE: Consider providing this utility method as AX API
VisiblePositionRange AccessibilityObject::visiblePositionRangeForRange(const PlainTextRange& range) const
{
- unsigned textLength = text().length();
-#if PLATFORM(GTK)
- // Gtk ATs need this for all text objects; not just text controls.
- if (!textLength) {
- Node* node = this->node();
- RenderObject* renderer = node ? node->renderer() : 0;
- if (renderer && renderer->isText()) {
- RenderText* renderText = toRenderText(renderer);
- textLength = renderText ? renderText->textLength() : 0;
- }
- // Get the text length from the elements under the
- // accessibility object if the value is still zero.
- if (!textLength && allowsTextRanges())
- textLength = textUnderElement().length();
- }
-#endif
+ unsigned textLength = getLengthForTextRange();
if (range.start + range.length > textLength)
return VisiblePositionRange();
diff --git a/WebCore/accessibility/AccessibilityObject.h b/WebCore/accessibility/AccessibilityObject.h
index 0e44d1b..e8f6d1b 100644
--- a/WebCore/accessibility/AccessibilityObject.h
+++ b/WebCore/accessibility/AccessibilityObject.h
@@ -574,8 +574,10 @@ protected:
#if PLATFORM(GTK)
bool allowsTextRanges() const;
+ unsigned getLengthForTextRange() const;
#else
bool allowsTextRanges() const { return isTextControl(); }
+ unsigned getLengthForTextRange() const { return text().length(); }
#endif
#if PLATFORM(MAC)
diff --git a/WebCore/accessibility/AccessibilityRenderObject.cpp b/WebCore/accessibility/AccessibilityRenderObject.cpp
index e292971..5ca78ca 100644
--- a/WebCore/accessibility/AccessibilityRenderObject.cpp
+++ b/WebCore/accessibility/AccessibilityRenderObject.cpp
@@ -503,7 +503,7 @@ bool AccessibilityRenderObject::isFileUploadButton() const
{
if (m_renderer && m_renderer->node() && m_renderer->node()->hasTagName(inputTag)) {
HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->node());
- return input->inputType() == HTMLInputElement::FILE;
+ return input->isFileUpload();
}
return false;
@@ -514,7 +514,7 @@ bool AccessibilityRenderObject::isInputImage() const
Node* elementNode = node();
if (roleValue() == ButtonRole && elementNode && elementNode->hasTagName(inputTag)) {
HTMLInputElement* input = static_cast<HTMLInputElement*>(elementNode);
- return input->inputType() == HTMLInputElement::IMAGE;
+ return input->isImageButton();
}
return false;
@@ -1025,7 +1025,7 @@ String AccessibilityRenderObject::textUnderElement() const
// catch stale WebCoreAXObject (see <rdar://problem/3960196>)
if (frame->document() != node->document())
return String();
- return plainText(rangeOfContents(node).get());
+ return plainText(rangeOfContents(node).get(), TextIteratorIgnoresStyleVisibility);
}
}
@@ -1140,7 +1140,7 @@ String AccessibilityRenderObject::stringValue() const
if (startVisiblePosition.isNull() || endVisiblePosition.isNull())
return String();
- return plainText(makeRange(startVisiblePosition, endVisiblePosition).get());
+ return plainText(makeRange(startVisiblePosition, endVisiblePosition).get(), TextIteratorIgnoresStyleVisibility);
}
if (isTextControl())
@@ -1310,10 +1310,9 @@ String AccessibilityRenderObject::title() const
|| ariaRole == RadioButtonRole
|| ariaRole == CheckBoxRole
|| ariaRole == TabRole
- || isHeading())
- return textUnderElement();
-
- if (isLink())
+ || ariaRole == PopUpButtonRole
+ || isHeading()
+ || isLink())
return textUnderElement();
return String();
@@ -1393,7 +1392,9 @@ IntRect AccessibilityRenderObject::boundingBoxRect() const
// absoluteFocusRingQuads will query the hierarchy below this element, which for large webpages can be very slow.
// For a web area, which will have the most elements of any element, absoluteQuads should be used.
Vector<FloatQuad> quads;
- if (obj->isText() || isWebArea())
+ if (obj->isText())
+ toRenderText(obj)->absoluteQuads(quads, RenderText::ClipToEllipsis);
+ else if (isWebArea())
obj->absoluteQuads(quads);
else
obj->absoluteFocusRingQuads(quads);
@@ -2538,6 +2539,9 @@ void AccessibilityRenderObject::setSelectedVisiblePositionRange(const VisiblePos
VisiblePosition AccessibilityRenderObject::visiblePositionForPoint(const IntPoint& point) const
{
+ if (!m_renderer)
+ return VisiblePosition();
+
// convert absolute point to view coordinates
FrameView* frameView = m_renderer->document()->topDocument()->renderer()->view()->frameView();
RenderView* renderView = topRenderer();
@@ -2557,13 +2561,16 @@ VisiblePosition AccessibilityRenderObject::visiblePositionForPoint(const IntPoin
HitTestResult result(ourpoint);
renderView->layer()->hitTest(request, result);
innerNode = result.innerNode();
- if (!innerNode || !innerNode->renderer())
+ if (!innerNode)
+ return VisiblePosition();
+
+ RenderObject* renderer = innerNode->renderer();
+ if (!renderer)
return VisiblePosition();
pointResult = result.localPoint();
// done if hit something other than a widget
- RenderBoxModelObject* renderer = innerNode->renderBoxModelObject();
if (!renderer->isWidget())
break;
@@ -3029,9 +3036,9 @@ AccessibilityRole AccessibilityRenderObject::determineAccessibilityRole()
if (node && node->hasTagName(inputTag)) {
HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
- if (input->inputType() == HTMLInputElement::CHECKBOX)
+ if (input->isCheckbox())
return CheckBoxRole;
- if (input->inputType() == HTMLInputElement::RADIO)
+ if (input->isRadioButton())
return RadioButtonRole;
if (input->isTextButton())
return ButtonRole;
diff --git a/WebCore/accessibility/AccessibilityTableRow.cpp b/WebCore/accessibility/AccessibilityTableRow.cpp
index e2a1157..5e9f05c 100644
--- a/WebCore/accessibility/AccessibilityTableRow.cpp
+++ b/WebCore/accessibility/AccessibilityTableRow.cpp
@@ -93,7 +93,8 @@ AccessibilityObject* AccessibilityTableRow::parentTable() const
if (!m_renderer || !m_renderer->isTableRow())
return 0;
- return axObjectCache()->getOrCreate(toRenderTableRow(m_renderer)->table());
+ // Do not use getOrCreate. parentTable() can be called while the render tree is being modified.
+ return axObjectCache()->get(toRenderTableRow(m_renderer)->table());
}
AccessibilityObject* AccessibilityTableRow::headerObject()
diff --git a/WebCore/accessibility/chromium/AXObjectCacheChromium.cpp b/WebCore/accessibility/chromium/AXObjectCacheChromium.cpp
index d906a91..3ff0837 100644
--- a/WebCore/accessibility/chromium/AXObjectCacheChromium.cpp
+++ b/WebCore/accessibility/chromium/AXObjectCacheChromium.cpp
@@ -60,30 +60,34 @@ void AXObjectCache::postPlatformNotification(AccessibilityObject* obj, AXNotific
return;
ChromeClientChromium* client = toChromeClientChromium(obj->documentFrameView());
- if (client) {
- switch (notification) {
- case AXCheckedStateChanged:
- client->didChangeAccessibilityObjectState(obj);
- break;
- case AXChildrenChanged:
- client->didChangeAccessibilityObjectChildren(obj);
- break;
- case AXActiveDescendantChanged:
- case AXFocusedUIElementChanged:
- case AXLayoutComplete:
- case AXLiveRegionChanged:
- case AXLoadComplete:
- case AXMenuListValueChanged:
- case AXRowCollapsed:
- case AXRowCountChanged:
- case AXRowExpanded:
- case AXScrolledToAnchor:
- case AXSelectedChildrenChanged:
- case AXSelectedTextChanged:
- case AXValueChanged:
- break;
- }
+ if (!client)
+ return;
+
+ // TODO: Remove after the new postAccessibilityNotification is used downstream.
+ switch (notification) {
+ case AXCheckedStateChanged:
+ client->didChangeAccessibilityObjectState(obj);
+ break;
+ case AXChildrenChanged:
+ client->didChangeAccessibilityObjectChildren(obj);
+ break;
+ case AXActiveDescendantChanged:
+ case AXFocusedUIElementChanged:
+ case AXLayoutComplete:
+ case AXLiveRegionChanged:
+ case AXLoadComplete:
+ case AXMenuListValueChanged:
+ case AXRowCollapsed:
+ case AXRowCountChanged:
+ case AXRowExpanded:
+ case AXScrolledToAnchor:
+ case AXSelectedChildrenChanged:
+ case AXSelectedTextChanged:
+ case AXValueChanged:
+ break;
}
+
+ client->postAccessibilityNotification(obj, notification);
}
void AXObjectCache::handleFocusedUIElementChanged(RenderObject*, RenderObject*)
diff --git a/WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp b/WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp
index b22a51e..7f9fd1a 100644
--- a/WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp
+++ b/WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp
@@ -20,6 +20,8 @@
#include "config.h"
#include "AccessibilityObject.h"
+#include "RenderObject.h"
+#include "RenderText.h"
#include <glib-object.h>
@@ -102,6 +104,29 @@ bool AccessibilityObject::allowsTextRanges() const
return isTextControl() || isWebArea() || isGroup() || isLink() || isHeading();
}
+unsigned AccessibilityObject::getLengthForTextRange() const
+{
+ unsigned textLength = text().length();
+
+ if (textLength)
+ return textLength;
+
+ // Gtk ATs need this for all text objects; not just text controls.
+ Node* node = this->node();
+ RenderObject* renderer = node ? node->renderer() : 0;
+ if (renderer && renderer->isText()) {
+ RenderText* renderText = toRenderText(renderer);
+ textLength = renderText ? renderText->textLength() : 0;
+ }
+
+ // Get the text length from the elements under the
+ // accessibility object if the value is still zero.
+ if (!textLength && allowsTextRanges())
+ textLength = textUnderElement().length();
+
+ return textLength;
+}
+
} // namespace WebCore
#endif // HAVE(ACCESSIBILITY)
diff --git a/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp b/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp
index 90f363f..01dddd1 100644
--- a/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp
+++ b/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp
@@ -58,6 +58,7 @@
#include "RenderListMarker.h"
#include "RenderText.h"
#include "TextEncoding.h"
+#include "TextIterator.h"
#include <wtf/text/CString.h>
#include <wtf/text/AtomicString.h>
@@ -1342,8 +1343,64 @@ static bool selectionBelongsToObject(AccessibilityObject* coreObject, VisibleSel
if (!coreObject->isAccessibilityRenderObject())
return false;
- Node* node = static_cast<AccessibilityRenderObject*>(coreObject)->renderer()->node();
- return node == selection.base().containerNode();
+ RefPtr<Range> range = selection.toNormalizedRange();
+ if (!range)
+ return false;
+
+ // We want to check that both the selection intersects the node
+ // AND that the selection is not just "touching" one of the
+ // boundaries for the selected node. We want to check whether the
+ // node is actually inside the region, at least partially
+ Node* node = coreObject->node();
+ Node* lastDescendant = node->lastDescendant();
+ ExceptionCode ec = 0;
+ return (range->intersectsNode(node, ec)
+ && (range->endContainer() != node || range->endOffset())
+ && (range->startContainer() != lastDescendant || range->startOffset() != lastOffsetInNode(lastDescendant)));
+}
+
+static void getSelectionOffsetsForObject(AccessibilityObject* coreObject, VisibleSelection& selection, gint& startOffset, gint& endOffset)
+{
+ if (!coreObject->isAccessibilityRenderObject())
+ return;
+
+ // Early return if the selection doesn't affect the selected node
+ if (!selectionBelongsToObject(coreObject, selection))
+ return;
+
+ // We need to find the exact start and end positions in the
+ // selected node that intersects the selection, to later on get
+ // the right values for the effective start and end offsets
+ ExceptionCode ec = 0;
+ Position nodeRangeStart;
+ Position nodeRangeEnd;
+ Node* node = coreObject->node();
+ RefPtr<Range> selRange = selection.toNormalizedRange();
+
+ // If the selection affects the selected node and its first
+ // possible position is also in the selection, we must set
+ // nodeRangeStart to that position, otherwise to the selection's
+ // start position (it would belong to the node anyway)
+ Node* firstLeafNode = node->firstDescendant();
+ if (selRange->isPointInRange(firstLeafNode, 0, ec))
+ nodeRangeStart = firstPositionInNode(firstLeafNode);
+ else
+ nodeRangeStart = selRange->startPosition();
+
+ // If the selection affects the selected node and its last
+ // possible position is also in the selection, we must set
+ // nodeRangeEnd to that position, otherwise to the selection's
+ // end position (it would belong to the node anyway)
+ Node* lastLeafNode = node->lastDescendant();
+ if (selRange->isPointInRange(lastLeafNode, lastOffsetInNode(lastLeafNode), ec))
+ nodeRangeEnd = lastPositionInNode(lastLeafNode);
+ else
+ nodeRangeEnd = selRange->endPosition();
+
+ // Set values for start and end offsets
+ RefPtr<Range> nodeRange = Range::create(node->document(), nodeRangeStart, nodeRangeEnd);
+ startOffset = nodeRangeStart.offsetInContainerNode();
+ endOffset = startOffset + TextIterator::rangeLength(nodeRange.get());
}
static gint webkit_accessible_text_get_n_selections(AtkText* text)
@@ -1351,6 +1408,10 @@ static gint webkit_accessible_text_get_n_selections(AtkText* text)
AccessibilityObject* coreObject = core(text);
VisibleSelection selection = coreObject->selection();
+ // Only range selections are needed for the purpose of this method
+ if (!selection.isRange())
+ return 0;
+
// We don't support multiple selections for now, so there's only
// two possibilities
// Also, we don't want to do anything if the selection does not
@@ -1360,25 +1421,26 @@ static gint webkit_accessible_text_get_n_selections(AtkText* text)
return !selectionBelongsToObject(coreObject, selection) || selection.isNone() ? 0 : 1;
}
-static gchar* webkit_accessible_text_get_selection(AtkText* text, gint selection_num, gint* start_offset, gint* end_offset)
+static gchar* webkit_accessible_text_get_selection(AtkText* text, gint selectionNum, gint* startOffset, gint* endOffset)
{
- AccessibilityObject* coreObject = core(text);
- VisibleSelection selection = coreObject->selection();
+ // Default values, unless the contrary is proved
+ *startOffset = *endOffset = 0;
// WebCore does not support multiple selection, so anything but 0 does not make sense for now.
- // Also, we don't want to do anything if the selection does not
- // belong to the currently selected object. We have to check since
- // there's no way to get the selection for a given object, only
- // the global one (the API is a bit confusing)
- if (selection_num != 0 || !selectionBelongsToObject(coreObject, selection)) {
- *start_offset = *end_offset = 0;
+ if (selectionNum)
return 0;
- }
- *start_offset = selection.start().offsetInContainerNode();
- *end_offset = selection.end().offsetInContainerNode();
+ // Get the offsets of the selection for the selected object
+ AccessibilityObject* coreObject = core(text);
+ VisibleSelection selection = coreObject->selection();
+ getSelectionOffsetsForObject(coreObject, selection, *startOffset, *endOffset);
+
+ // Return 0 instead of "", as that's the expected result for
+ // this AtkText method when there's no selection
+ if (*startOffset == *endOffset)
+ return 0;
- return webkit_accessible_text_get_text(text, *start_offset, *end_offset);
+ return webkit_accessible_text_get_text(text, *startOffset, *endOffset);
}
static gboolean webkit_accessible_text_add_selection(AtkText* text, gint start_offset, gint end_offset)
@@ -1387,32 +1449,51 @@ static gboolean webkit_accessible_text_add_selection(AtkText* text, gint start_o
return FALSE;
}
-static gboolean webkit_accessible_text_remove_selection(AtkText* text, gint selection_num)
+static gboolean webkit_accessible_text_set_selection(AtkText* text, gint selectionNum, gint startOffset, gint endOffset)
{
- notImplemented();
- return FALSE;
+ // WebCore does not support multiple selection, so anything but 0 does not make sense for now.
+ if (selectionNum)
+ return FALSE;
+
+ // Consider -1 and out-of-bound values and correct them to length
+ gint textCount = webkit_accessible_text_get_character_count(text);
+ if (startOffset < 0 || startOffset > textCount)
+ startOffset = textCount;
+ if (endOffset < 0 || endOffset > textCount)
+ endOffset = textCount;
+
+ AccessibilityObject* coreObject = core(text);
+ PlainTextRange textRange(startOffset, endOffset - startOffset);
+ VisiblePositionRange range = coreObject->visiblePositionRangeForRange(textRange);
+ coreObject->setSelectedVisiblePositionRange(range);
+
+ return TRUE;
}
-static gboolean webkit_accessible_text_set_selection(AtkText* text, gint selection_num, gint start_offset, gint end_offset)
+static gboolean webkit_accessible_text_remove_selection(AtkText* text, gint selectionNum)
{
- notImplemented();
- return FALSE;
+ // WebCore does not support multiple selection, so anything but 0 does not make sense for now.
+ if (selectionNum)
+ return FALSE;
+
+ // Do nothing if current selection doesn't belong to the object
+ if (!webkit_accessible_text_get_n_selections(text))
+ return FALSE;
+
+ // Set a new 0-sized selection to the caret position, in order
+ // to simulate selection removal (GAIL style)
+ gint caretOffset = webkit_accessible_text_get_caret_offset(text);
+ return webkit_accessible_text_set_selection(text, selectionNum, caretOffset, caretOffset);
}
static gboolean webkit_accessible_text_set_caret_offset(AtkText* text, gint offset)
{
AccessibilityObject* coreObject = core(text);
- // FIXME: We need to reimplement visiblePositionRangeForRange here
- // because the actual function checks the offset is within the
- // boundaries of text().length(), but text() only works for text
- // controls...
- VisiblePosition startPosition = coreObject->visiblePositionForIndex(offset);
- startPosition.setAffinity(DOWNSTREAM);
- VisiblePosition endPosition = coreObject->visiblePositionForIndex(offset);
- VisiblePositionRange range = VisiblePositionRange(startPosition, endPosition);
-
+ PlainTextRange textRange(offset, 0);
+ VisiblePositionRange range = coreObject->visiblePositionRangeForRange(textRange);
coreObject->setSelectedVisiblePositionRange(range);
+
return TRUE;
}
diff --git a/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm b/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm
index 859a799..e3e28d7 100644
--- a/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm
+++ b/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm
@@ -1972,11 +1972,11 @@ static NSString* roleValueToNSString(AccessibilityRole value)
- (BOOL)accessibilityIsIgnored
{
if (!m_object)
- return nil;
+ return YES;
m_object->updateBackingStore();
if (!m_object)
- return nil;
+ return YES;
if (m_object->isAttachment())
return [[self attachmentView] accessibilityIsIgnored];
@@ -2354,7 +2354,10 @@ static RenderObject* rendererForView(NSView* view)
// dispatch
if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) {
VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
- return m_object->accessibilityObjectForPosition(visiblePos)->wrapper();
+ AccessibilityObject* axObject = m_object->accessibilityObjectForPosition(visiblePos);
+ if (!axObject)
+ return nil;
+ return axObject->wrapper();
}
if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) {