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

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

Issue 2745713002: WIP: Modified AXPosition to work with objects with both embedded object characters and text. (Closed)
Patch Set: Simplified and cleaned up selection code in Blink > Accessibility. Created 3 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: 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 b5aec8edff793ec59181233ac71434ae9484578d..50d23d71df04d06bde367ca4b1228810907691c4 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
@@ -37,7 +37,6 @@
#include "core/dom/shadow/ShadowRoot.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/FrameSelection.h"
-#include "core/editing/RenderedPosition.h"
#include "core/editing/TextAffinity.h"
#include "core/editing/VisibleUnits.h"
#include "core/editing/iterators/CharacterIterator.h"
@@ -1723,313 +1722,6 @@ Element* AXLayoutObject::AnchorElement() const {
return 0;
}
-//
-// Functions that retrieve the current selection.
-//
-
-AXObjectImpl::AXRange AXLayoutObject::Selection() const {
- AXRange text_selection = TextControlSelection();
- if (text_selection.IsValid())
- return text_selection;
-
- if (!GetLayoutObject() || !GetLayoutObject()->GetFrame())
- return AXRange();
-
- VisibleSelection selection =
- GetLayoutObject()
- ->GetFrame()
- ->Selection()
- .ComputeVisibleSelectionInDOMTreeDeprecated();
- if (selection.IsNone())
- return AXRange();
-
- VisiblePosition visible_start = selection.VisibleStart();
- Position start = visible_start.ToParentAnchoredPosition();
- TextAffinity start_affinity = visible_start.Affinity();
- VisiblePosition visible_end = selection.VisibleEnd();
- Position end = visible_end.ToParentAnchoredPosition();
- TextAffinity end_affinity = visible_end.Affinity();
-
- Node* anchor_node = start.AnchorNode();
- DCHECK(anchor_node);
-
- AXLayoutObject* anchor_object = nullptr;
- // Find the closest node that has a corresponding AXObjectImpl.
- // This is because some nodes may be aria hidden or might not even have
- // a layout object if they are part of the shadow DOM.
- while (anchor_node) {
- anchor_object = GetUnignoredObjectFromNode(*anchor_node);
- if (anchor_object)
- break;
-
- if (anchor_node->nextSibling())
- anchor_node = anchor_node->nextSibling();
- else
- anchor_node = anchor_node->parentNode();
- }
-
- Node* focus_node = end.AnchorNode();
- DCHECK(focus_node);
-
- AXLayoutObject* focus_object = nullptr;
- while (focus_node) {
- focus_object = GetUnignoredObjectFromNode(*focus_node);
- if (focus_object)
- break;
-
- if (focus_node->previousSibling())
- focus_node = focus_node->previousSibling();
- else
- focus_node = focus_node->parentNode();
- }
-
- if (!anchor_object || !focus_object)
- return AXRange();
-
- int anchor_offset = anchor_object->IndexForVisiblePosition(visible_start);
- DCHECK_GE(anchor_offset, 0);
- int focus_offset = focus_object->IndexForVisiblePosition(visible_end);
- DCHECK_GE(focus_offset, 0);
- return AXRange(anchor_object, anchor_offset, start_affinity, focus_object,
- focus_offset, end_affinity);
-}
-
-// 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.
-AXObjectImpl::AXRange AXLayoutObject::SelectionUnderObject() const {
- AXRange text_selection = TextControlSelection();
- if (text_selection.IsValid())
- return text_selection;
-
- if (!GetNode() || !GetLayoutObject()->GetFrame())
- return AXRange();
-
- VisibleSelection selection =
- GetLayoutObject()
- ->GetFrame()
- ->Selection()
- .ComputeVisibleSelectionInDOMTreeDeprecated();
- Range* selection_range = CreateRange(FirstEphemeralRangeOf(selection));
- ContainerNode* parent_node = GetNode()->parentNode();
- int node_index = GetNode()->NodeIndex();
- if (!selection_range
- // Selection is contained in node.
- || !(parent_node &&
- selection_range->comparePoint(parent_node, node_index,
- IGNORE_EXCEPTION_FOR_TESTING) < 0 &&
- selection_range->comparePoint(parent_node, node_index + 1,
- IGNORE_EXCEPTION_FOR_TESTING) > 0)) {
- return AXRange();
- }
-
- int start = IndexForVisiblePosition(selection.VisibleStart());
- DCHECK_GE(start, 0);
- int end = IndexForVisiblePosition(selection.VisibleEnd());
- DCHECK_GE(end, 0);
-
- return AXRange(start, end);
-}
-
-AXObjectImpl::AXRange AXLayoutObject::TextControlSelection() const {
- if (!GetLayoutObject())
- return AXRange();
-
- LayoutObject* layout = nullptr;
- if (GetLayoutObject()->IsTextControl()) {
- layout = GetLayoutObject();
- } else {
- Element* focused_element = GetDocument()->FocusedElement();
- if (focused_element && focused_element->GetLayoutObject() &&
- focused_element->GetLayoutObject()->IsTextControl())
- layout = focused_element->GetLayoutObject();
- }
-
- if (!layout)
- return AXRange();
-
- AXObjectImpl* ax_object = AxObjectCache().GetOrCreate(layout);
- if (!ax_object || !ax_object->IsAXLayoutObject())
- return AXRange();
-
- VisibleSelection selection =
- layout->GetFrame()
- ->Selection()
- .ComputeVisibleSelectionInDOMTreeDeprecated();
- TextControlElement* text_control =
- ToLayoutTextControl(layout)->GetTextControlElement();
- DCHECK(text_control);
- int start = text_control->selectionStart();
- int end = text_control->selectionEnd();
-
- return AXRange(ax_object, start, selection.VisibleStart().Affinity(),
- ax_object, end, selection.VisibleEnd().Affinity());
-}
-
-int AXLayoutObject::IndexForVisiblePosition(
- const VisiblePosition& position) const {
- if (GetLayoutObject() && GetLayoutObject()->IsTextControl()) {
- TextControlElement* text_control =
- ToLayoutTextControl(GetLayoutObject())->GetTextControlElement();
- return text_control->IndexForVisiblePosition(position);
- }
-
- if (!GetNode())
- return 0;
-
- Position index_position = position.DeepEquivalent();
- if (index_position.IsNull())
- return 0;
-
- Range* range = Range::Create(*GetDocument());
- range->setStart(GetNode(), 0, IGNORE_EXCEPTION_FOR_TESTING);
- range->setEnd(index_position, IGNORE_EXCEPTION_FOR_TESTING);
-
- return TextIterator::RangeLength(range->StartPosition(),
- range->EndPosition());
-}
-
-AXLayoutObject* AXLayoutObject::GetUnignoredObjectFromNode(Node& node) const {
- if (IsDetached())
- return nullptr;
-
- AXObjectImpl* ax_object = AxObjectCache().GetOrCreate(&node);
- if (!ax_object)
- return nullptr;
-
- if (ax_object->IsAXLayoutObject() && !ax_object->AccessibilityIsIgnored())
- return ToAXLayoutObject(ax_object);
-
- return nullptr;
-}
-
-//
-// Modify or take an action on an object.
-//
-
-// Convert from an accessible object and offset to a VisiblePosition.
-static VisiblePosition ToVisiblePosition(AXObjectImpl* obj, int offset) {
- if (!obj->GetNode())
- return VisiblePosition();
-
- Node* node = obj->GetNode();
- if (!node->IsTextNode()) {
- int child_count = obj->Children().size();
-
- // Place position immediately before the container node, if there was no
- // children.
- if (child_count == 0) {
- if (!obj->ParentObject())
- return VisiblePosition();
- return ToVisiblePosition(obj->ParentObject(), obj->IndexInParent());
- }
-
- // 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 || offset > child_count)
- return VisiblePosition();
-
- // Clamp to between 0 and child count - 1.
- int clamped_offset =
- static_cast<unsigned>(offset) > (obj->Children().size() - 1)
- ? offset - 1
- : offset;
- AXObjectImpl* child_obj = obj->Children()[clamped_offset];
- Node* child_node = child_obj->GetNode();
- if (!child_node || !child_node->parentNode())
- return VisiblePosition();
-
- // The index in parent.
- int adjusted_offset = child_node->NodeIndex();
-
- // If we had to clamp the offset above, the client wants to select the
- // end of the node.
- if (clamped_offset != offset)
- adjusted_offset++;
-
- return CreateVisiblePosition(
- Position::EditingPositionOf(child_node->parentNode(), adjusted_offset));
- }
-
- // 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 visible character at position |offset|.
- ContainerNode* parent = node->parentNode();
- if (!parent)
- return VisiblePosition();
-
- VisiblePosition node_position = blink::VisiblePositionBeforeNode(*node);
- int node_index = blink::IndexForVisiblePosition(node_position, parent);
- return blink::VisiblePositionForIndex(node_index + offset, parent);
-}
-
-void AXLayoutObject::SetSelection(const AXRange& selection) {
- if (!GetLayoutObject() || !selection.IsValid())
- return;
-
- AXObjectImpl* anchor_object =
- selection.anchor_object ? selection.anchor_object.Get() : this;
- AXObjectImpl* focus_object =
- selection.focus_object ? selection.focus_object.Get() : this;
-
- if (!IsValidSelectionBound(anchor_object) ||
- !IsValidSelectionBound(focus_object)) {
- return;
- }
-
- // The selection offsets are offsets into the accessible value.
- if (anchor_object == focus_object &&
- anchor_object->GetLayoutObject()->IsTextControl()) {
- TextControlElement* text_control =
- ToLayoutTextControl(anchor_object->GetLayoutObject())
- ->GetTextControlElement();
- if (selection.anchor_offset <= selection.focus_offset) {
- text_control->SetSelectionRange(selection.anchor_offset,
- selection.focus_offset,
- kSelectionHasForwardDirection);
- } else {
- text_control->SetSelectionRange(selection.focus_offset,
- selection.anchor_offset,
- kSelectionHasBackwardDirection);
- }
- return;
- }
-
- LocalFrame* frame = GetLayoutObject()->GetFrame();
- if (!frame)
- return;
-
- // TODO(editing-dev): Use of updateStyleAndLayoutIgnorePendingStylesheets
- // needs to be audited. see http://crbug.com/590369 for more details.
- // This callsite should probably move up the stack.
- frame->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
-
- // Set the selection based on visible positions, because the offsets in
- // accessibility nodes are based on visible indexes, which often skips
- // redundant whitespace, for example.
- VisiblePosition anchor_visible_position =
- ToVisiblePosition(anchor_object, selection.anchor_offset);
- VisiblePosition focus_visible_position =
- ToVisiblePosition(focus_object, selection.focus_offset);
- if (anchor_visible_position.IsNull() || focus_visible_position.IsNull())
- return;
-
- frame->Selection().SetSelection(
- SelectionInDOMTree::Builder()
- .Collapse(anchor_visible_position.ToPositionWithAffinity())
- .Extend(focus_visible_position.DeepEquivalent())
- .Build());
-}
-
-bool AXLayoutObject::IsValidSelectionBound(
- const AXObjectImpl* bound_object) const {
- return GetLayoutObject() && bound_object && !bound_object->IsDetached() &&
- bound_object->IsAXLayoutObject() && bound_object->GetLayoutObject() &&
- bound_object->GetLayoutObject()->GetFrame() ==
- GetLayoutObject()->GetFrame() &&
- &bound_object->AxObjectCache() == &AxObjectCache();
-}
-
void AXLayoutObject::SetValue(const String& string) {
if (!GetNode() || !GetNode()->IsElementNode())
return;

Powered by Google App Engine
This is Rietveld 408576698