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

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: 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..702142a1cf0bb4e4bda973f9495b795fa20a9714 100644
--- a/Source/modules/accessibility/AXLayoutObject.cpp
+++ b/Source/modules/accessibility/AXLayoutObject.cpp
@@ -1834,46 +1834,152 @@ Widget* AXLayoutObject::widgetForAttachmentView() const
}
//
-// Selected text.
+// Get the current selection.
//
-AXObject::PlainTextRange AXLayoutObject::selectedTextRange() const
+AXObject::AXSelection AXLayoutObject::selection() const
{
- if (!isTextControl())
- return PlainTextRange();
+ AXSelection textSelection = textControlSelection();
dmazzoni 2015/06/16 17:24:03 This only seems to work if *this* is a text contro
+ if (!textSelection.isNull())
+ return textSelection;
+
+ if (!node())
+ return AXSelection();
+
+ VisibleSelection selection = visibleSelection();
+ RefPtrWillBeRawPtr<Range> selectionRange = selection.firstRange();
+ if (!selectionRange)
+ return AXSelection();
+
+ Node* anchorNode = selectionRange->startContainer();
+ ASSERT(anchorNode);
+ AXObject* anchorObject = axObjectCache()->get(anchorNode);
dmazzoni 2015/06/16 17:24:03 I think you need to handle the case where this obj
+ Node* focusNode = selectionRange->endContainer();
+ ASSERT(focusNode);
+ AXObject* focusObject = axObjectCache()->get(focusNode);
+
+ if (!anchorObject || !focusObject)
+ return AXSelection();
+
+ AXID anchorId = anchorObject->axObjectID();
+ AXID focusId = focusObject->axObjectID();
+
+ int anchorOffset = selectionRange->startOffset();
+ ASSERT(anchorOffset >= 0);
+ int focusOffset = selectionRange->endOffset();
+ ASSERT(focusOffset >= 0);
+
+ return AXSelection(
+ anchorId, static_cast<unsigned>(anchorOffset),
+ focusId, static_cast<unsigned>(focusOffset));
+}
- if (m_layoutObject->isTextControl()) {
- HTMLTextFormControlElement* textControl = toLayoutTextControl(m_layoutObject)->textFormControlElement();
- return PlainTextRange(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
+AXObject::AXSelection AXLayoutObject::selectionUnderObject() const
dmazzoni 2015/06/16 17:24:03 Can you explain what this does?
+{
+ AXSelection textSelection = textControlSelection();
+ if (!textSelection.isNull())
+ return textSelection;
+
+ if (!node())
+ return AXSelection();
+
+ VisibleSelection selection = visibleSelection();
+ RefPtrWillBeRawPtr<Range> selectionRange = selection.firstRange();
+ if (!selectionRange)
+ return AXSelection();
+
+ int start = indexForVisiblePosition(selection.visibleStart());
+ int end = indexForVisiblePosition(selection.visibleEnd());
+
+ return AXSelection(start, end);
+}
+
+AXObject::AXSelection AXLayoutObject::textControlSelection() const
+{
+ if (layoutObject() && layoutObject()->isTextControl()) {
+ HTMLTextFormControlElement* textControl = toLayoutTextControl(
+ layoutObject())->textFormControlElement();
+ AXID id = axObjectID();
+ unsigned start = textControl->selectionStart();
+ unsigned end = textControl->selectionEnd();
+ return AXSelection(id, start, id, end);
}
- return visibleSelectionUnderObject();
+ return AXSelection();
}
-VisibleSelection AXLayoutObject::selection() const
+VisibleSelection AXLayoutObject::visibleSelection() const
{
- return m_layoutObject->frame()->selection().selection();
+ 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 AXSelection& 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.hasAnchor())
+ anchorObject = axObjectCache()->objectFromAXID(selection.anchorId);
+
+ AXObject* focusObject = this;
+ if (selection.hasFocus())
+ focusObject = axObjectCache()->objectFromAXID(selection.focusId);
+
+ if (!anchorObject || !focusObject)
+ return;
+
+ 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();
+ Node* focusNode = focusObject->node();
+ if (!anchorNode || !focusNode)
dmazzoni 2015/06/16 17:24:03 Some objects in the tree have a layoutObject but n
+ 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,
dmazzoni 2015/06/16 17:24:03 I think you need to check that both the anchorNode
+ selection.anchorOffset, Position::PositionIsOffsetInAnchor),
+ Position(focusNode, selection.focusOffset,
+ Position::PositionIsOffsetInAnchor), DOWNSTREAM));
}
void AXLayoutObject::setValue(const String& string)
@@ -2008,33 +2114,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 +2195,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