Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1943)

Unified Diff: Source/modules/accessibility/AXLayoutObject.cpp

Issue 1185343003: Implements the ability to get and set the caret position and the current selection from anywhere in… (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Fixed some compiler errors. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/modules/accessibility/AXLayoutObject.cpp
diff --git a/Source/modules/accessibility/AXLayoutObject.cpp b/Source/modules/accessibility/AXLayoutObject.cpp
index 63b98a2f16d6dff009536f948c0fd6faf42f08b4..1a109b3f13a590651099e7e5e24cc1ca26f39a21 100644
--- a/Source/modules/accessibility/AXLayoutObject.cpp
+++ b/Source/modules/accessibility/AXLayoutObject.cpp
@@ -1834,46 +1834,165 @@ Widget* AXLayoutObject::widgetForAttachmentView() const
}
//
-// Selected text.
+// Get the current selection.
//
-AXObject::PlainTextRange AXLayoutObject::selectedTextRange() const
+AXObject::AXRange AXLayoutObject::selection() const
{
- if (!isTextControl())
- return PlainTextRange();
+ AXRange textSelection = textControlSelection();
+ if (!textSelection.isNull())
+ return textSelection;
- if (m_layoutObject->isTextControl()) {
- HTMLTextFormControlElement* textControl = toLayoutTextControl(m_layoutObject)->textFormControlElement();
- return PlainTextRange(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
- }
+ // Find the closest parent that has a node.
dmazzoni 2015/06/22 17:13:35 I don't think you need to find a parent with a nod
+ const AXObject* axObject = this;
+ while (axObject
+ && (!axObject->isAXLayoutObject() || !axObject->node()
+ || axObject->accessibilityIsIgnored()))
+ axObject = axObject->parentObject();
+ if (!axObject)
+ return AXRange();
+
+ VisibleSelection selection = axObject->visibleSelection();
+ RefPtrWillBeRawPtr<Range> selectionRange = selection.firstRange();
+ if (!selectionRange)
+ return AXRange();
+
+ Node* anchorNode = selectionRange->startContainer();
+ ASSERT(anchorNode);
+ RefPtrWillBeRawPtr<AXObject> anchorObject = axObjectCache()->get(anchorNode);
+ Node* focusNode = selectionRange->endContainer();
+ ASSERT(focusNode);
+ RefPtrWillBeRawPtr<AXObject> focusObject = axObjectCache()->get(focusNode);
+
+ if (!anchorObject || !focusObject)
dmazzoni 2015/06/22 17:13:35 Here's where you need to walk up the tree. anchorN
+ return AXRange();
- return visibleSelectionUnderObject();
+ int anchorOffset = selectionRange->startOffset();
+ ASSERT(anchorOffset >= 0);
+ int focusOffset = selectionRange->endOffset();
+ ASSERT(focusOffset >= 0);
+
+ return AXRange(
+ anchorObject, anchorOffset,
+ focusObject, focusOffset);
}
-VisibleSelection AXLayoutObject::selection() const
+// Gets only the start and end offsets of the selection computed using the
+// current object as the starting point. Returns a null selection if there is
+// no selection in the subtree rooted at this object.
+AXObject::AXRange AXLayoutObject::selectionUnderObject() const
{
- return m_layoutObject->frame()->selection().selection();
+ AXRange textSelection = textControlSelection();
+ if (!textSelection.isNull())
+ return textSelection;
+
+ if (!node())
+ return AXRange();
+
+ VisibleSelection selection = visibleSelection();
+ RefPtrWillBeRawPtr<Range> selectionRange = selection.firstRange();
+ if (!selectionRange
+ || !selectionRange->intersectsNode(node(), IGNORE_EXCEPTION))
dmazzoni 2015/06/22 17:13:35 It looks like selectionUnderObject returns a selec
+ return AXRange();
+
+ int start = indexForVisiblePosition(selection.visibleStart());
+ int end = indexForVisiblePosition(selection.visibleEnd());
+
+ return AXRange(start, end);
+}
+
+AXObject::AXRange AXLayoutObject::textControlSelection() const
+{
+ if (!layoutObject())
+ return AXRange();
+
+ Node* node = isHTMLTextFormControlElement(node()) ? node() :
+ document()->focusedElement();
+
+ if (!node)
+ return AXRange();
+
+ AXObject axObject = axObjectCache()->get(node);
+ if (!axObject)
+ return AXRange();
+
+ HTMLTextFormControlElement* textControl = toHTMLTextFormControlElement(node);
+ int start = textControl->selectionStart();
+ int end = textControl->selectionEnd();
+ return AXRange(axObject, start, axObject, end);
+}
+
+VisibleSelection AXLayoutObject::visibleSelection() const
dmazzoni 2015/06/22 17:13:35 I'd just delete this helper, because any function
+{
+ return layoutObject() ?
+ layoutObject()->frame()->selection().selection() : VisibleSelection();
+}
+
+int AXLayoutObject::indexForVisiblePosition(const VisiblePosition& position) const
+{
+ if (layoutObject() && layoutObject()->isTextControl()) {
+ HTMLTextFormControlElement* textControl = toLayoutTextControl(
+ layoutObject())->textFormControlElement();
+ return textControl->indexForVisiblePosition(position);
+ }
+
+ if (!node())
+ return 0;
+
+ Position indexPosition = position.deepEquivalent();
+ if (indexPosition.isNull())
+ return 0;
+
+ RefPtrWillBeRawPtr<Range> range = Range::create(*document());
+ range->setStart(node(), 0, IGNORE_EXCEPTION);
+ range->setEnd(indexPosition, IGNORE_EXCEPTION);
+
+ return TextIterator::rangeLength(range->startPosition(), range->endPosition());
}
//
// Modify or take an action on an object.
//
-void AXLayoutObject::setSelectedTextRange(const PlainTextRange& range)
+void AXLayoutObject::setSelection(const AXRange& selection)
{
- if (m_layoutObject->isTextControl()) {
- HTMLTextFormControlElement* textControl = toLayoutTextControl(m_layoutObject)->textFormControlElement();
- textControl->setSelectionRange(range.start, range.start + range.length, SelectionHasNoDirection, NotDispatchSelectEvent);
+ if (selection.isNull())
+ return;
+
+ AXObject* anchorObject = this;
+ if (selection.anchorObject
+ && axObjectCache()->isIDinUse(selection.anchorObject->axObjectID()))
dmazzoni 2015/06/22 17:13:35 Rather than isIDinUse, just check selection.anchor
+ anchorObject = selection.anchorObject.get();
+
+ AXObject* focusObject = this;
+ if (selection.focusObject
+ && axObjectCache()->isIDinUse(selection.focusObject->axObjectID()))
+ focusObject = selection.focusObject.get();
+
+ if (anchorObject == this && anchorObject == focusObject
+ && layoutObject() && layoutObject()->isTextControl()) {
+ HTMLTextFormControlElement* textControl = toLayoutTextControl(
+ layoutObject())->textFormControlElement();
+ textControl->setSelectionRange(selection.anchorOffset, selection.focusOffset,
+ SelectionHasNoDirection, NotDispatchSelectEvent);
return;
}
- Document& document = m_layoutObject->document();
- LocalFrame* frame = document.frame();
+ Node* anchorNode = anchorObject->node();
dmazzoni 2015/06/22 17:13:35 Need to walk up the tree here - someone might want
+ Node* focusNode = focusObject->node();
+ if (!anchorNode || !focusNode)
+ return;
+
+ Document* objectDocument = document();
+ ASSERT(objectDocument);
+ LocalFrame* frame = objectDocument->frame();
if (!frame)
return;
- Node* node = m_layoutObject->node();
- frame->selection().setSelection(VisibleSelection(Position(node, range.start, Position::PositionIsOffsetInAnchor),
- Position(node, range.start + range.length, Position::PositionIsOffsetInAnchor), DOWNSTREAM));
+
+ frame->selection().setSelection(VisibleSelection(Position(anchorNode,
+ selection.anchorOffset, Position::PositionIsOffsetInAnchor),
+ Position(focusNode, selection.focusOffset,
+ Position::PositionIsOffsetInAnchor), DOWNSTREAM));
}
void AXLayoutObject::setValue(const String& string)
@@ -2008,33 +2127,6 @@ VisiblePosition AXLayoutObject::visiblePositionForIndex(int index) const
return VisiblePosition(Position(it.currentContainer(), it.endOffset(), Position::PositionIsOffsetInAnchor), UPSTREAM);
}
-int AXLayoutObject::indexForVisiblePosition(const VisiblePosition& pos) const
-{
- if (m_layoutObject->isTextControl()) {
- HTMLTextFormControlElement* textControl = toLayoutTextControl(m_layoutObject)->textFormControlElement();
- return textControl->indexForVisiblePosition(pos);
- }
-
- if (!isTextControl())
- return 0;
-
- Node* node = m_layoutObject->node();
- if (!node)
- return 0;
-
- Position indexPosition = pos.deepEquivalent();
- if (indexPosition.isNull()
- || (highestEditableRoot(indexPosition) != node
- && highestEditableRoot(indexPosition, HasEditableAXRole) != node))
- return 0;
-
- RefPtrWillBeRawPtr<Range> range = Range::create(m_layoutObject->document());
- range->setStart(node, 0, IGNORE_EXCEPTION);
- range->setEnd(indexPosition, IGNORE_EXCEPTION);
-
- return TextIterator::rangeLength(range->startPosition(), range->endPosition());
-}
-
void AXLayoutObject::addInlineTextBoxChildren(bool force)
{
Settings* settings = document()->settings();
@@ -2116,23 +2208,6 @@ void AXLayoutObject::ariaListboxSelectedChildren(AccessibilityChildrenVector& re
}
}
-AXObject::PlainTextRange AXLayoutObject::visibleSelectionUnderObject() const
-{
- Node* node = m_layoutObject->node();
- if (!node)
- return PlainTextRange();
-
- VisibleSelection visibleSelection = selection();
- RefPtrWillBeRawPtr<Range> currentSelectionRange = visibleSelection.toNormalizedRange();
- if (!currentSelectionRange || !currentSelectionRange->intersectsNode(node, IGNORE_EXCEPTION))
- return PlainTextRange();
-
- int start = indexForVisiblePosition(visibleSelection.visibleStart());
- int end = indexForVisiblePosition(visibleSelection.visibleEnd());
-
- return PlainTextRange(start, end - start);
-}
-
bool AXLayoutObject::nodeIsTextControl(const Node* node) const
{
if (!node)

Powered by Google App Engine
This is Rietveld 408576698