Index: third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp |
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp |
index 53f06146bff17b7a26e867933cf7a84d34990354..dd55c690d7328fe78d0b948ca9ca54552743de47 100644 |
--- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp |
+++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp |
@@ -1817,21 +1817,44 @@ AXLayoutObject* AXLayoutObject::getUnignoredObjectFromNode(Node& node) const |
// Convert from an accessible object and offset to a VisiblePosition. |
static VisiblePosition toVisiblePosition(AXObject* obj, int offset) |
{ |
- // First walk up until we find an accessible object with an associated node. |
- AXObject* runner = obj; |
- Node* node = nullptr; |
- while (runner && !node) { |
- node = runner->getNode(); |
- runner = runner->parentObject(); |
- } |
- |
- if (!node) |
+ if (!obj->getNode()) |
return VisiblePosition(); |
- // If it's not a text node, no conversion is necessary, just create a VisiblePosition |
- // with this node and offset. |
- if (!node->isTextNode()) |
- return createVisiblePosition(Position(node, offset)); |
+ Node* node = obj->getNode(); |
+ if (!node->isTextNode()) { |
dmazzoni
2016/09/15 16:32:36
It's possible to call AXObject::setSelection on an
|
+ // The offsets are child offsets over the AX tree. Note that we allow |
+ // for the offset to equal the number of children as |Range| does. |
+ if (offset < 0 || static_cast<unsigned>(offset) > obj->children().size()) |
+ return VisiblePosition(); |
+ |
+ // Clamp to between 0 and child count - 1. |
+ int clampedOffset = |
+ static_cast<unsigned>(offset) > (obj->children().size() - 1) ? offset - 1 : offset; |
dmazzoni
2016/09/15 16:32:36
Clearer using std::min?
|
+ AXObject* childObj = obj->children()[clampedOffset]; |
+ Node* childNode = childObj->getNode(); |
+ if (!childNode || !childNode->parentNode()) |
+ return VisiblePosition(); |
+ |
+ // The index in parent. |
+ int adjustedOffset = -1; |
+ NodeList* childNodes = childNode->parentNode()->childNodes(); |
+ for (unsigned i = 0; i < childNodes->length(); ++i) { |
+ if (childNodes->item(i) == childNode) { |
+ adjustedOffset = i; |
+ break; |
+ } |
+ } |
+ |
+ if (adjustedOffset == -1) |
+ return VisiblePosition(); |
+ |
+ // If we had to clamp the offset above, the client wants to select the |
+ // end of the node. |
+ if (clampedOffset != offset) |
+ adjustedOffset++; |
+ |
+ return createVisiblePosition(Position::editingPositionOf(childNode->parentNode(), adjustedOffset)); |
dmazzoni
2016/09/15 16:32:36
Instead of computing the index in parent in the DO
|
+ } |
// If it is a text node, we need to call some utility functions that use a TextIterator |
// to walk the characters of the node and figure out the position corresponding to the |
@@ -1860,6 +1883,7 @@ void AXLayoutObject::setSelection(const AXRange& selection) |
return; |
} |
+ // The selection offsets are offsets into the accessible value. |
if (anchorObject == focusObject |
&& anchorObject->getLayoutObject()->isTextControl()) { |
HTMLTextFormControlElement* textControl = toLayoutTextControl( |