Chromium Code Reviews| 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( |