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..c55697199002170066df1c2a3e1069dfc666cf23 100644 |
--- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp |
+++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp |
@@ -1817,21 +1817,46 @@ 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()) { |
+ // 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. |
+ int childCount = obj->children().size(); |
+ // Figure out what it means when |childCount| is 0. |
dmazzoni
2016/09/16 18:10:56
Is this a TODO/FIXME?
Maybe it should just select
David Tseng
2016/09/16 20:50:31
This isn't a selection but a position.
It's not q
|
+ if (childCount == 0 || offset < 0 || offset > childCount) |
+ return VisiblePosition(); |
+ |
+ // Clamp to between 0 and child count - 1. |
+ int clampedOffset = |
+ static_cast<unsigned>(offset) > (obj->children().size() - 1) ? offset - 1 : offset; |
+ 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)); |
+ } |
// 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 +1885,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( |