5#ifndef UI_ACCESSIBILITY_AX_POSITION_H_
6#define UI_ACCESSIBILITY_AX_POSITION_H_
119template <
class AXPositionType,
class AXNodeType>
121template <
class AXPositionType>
123template <
class AXPositionType,
class AXNodeType>
126template <
class AXPositionType,
class AXNodeType>
159template <
class AXPositionType,
class AXNodeType>
163 std::unique_ptr<AXPosition<AXPositionType, AXNodeType>>;
185 new_position->Initialize(
236 "SerializedPosition must be POD");
243 std::string tree_id_string = tree_id_.
ToString();
245 strncpy(
result.tree_id, tree_id_string.c_str(), 32);
248 result.anchor_id = anchor_id_;
249 result.child_index = child_index_;
250 result.text_offset = text_offset_;
251 result.affinity = affinity_;
258 new_position->Initialize(serialization.
kind,
269 return "NullPosition";
271 std::string str_child_index;
273 str_child_index =
"before_text";
275 str_child_index =
"invalid";
279 str =
"TreePosition tree_id=" + tree_id_.
ToString() +
281 " child_index=" + str_child_index;
285 std::string str_text_offset;
287 str_text_offset =
"invalid";
292 " text_offset=" + str_text_offset +
" affinity=" +
305 std::u16string annotated_text;
306 if (text_offset_ == max_text_offset) {
307 annotated_text =
text + u
"<>";
309 annotated_text =
text.substr(0, text_offset_) + u
"<" +
310 text[text_offset_] + u
">" +
311 text.substr(text_offset_ + 1);
351 <<
"\"Before text\" and \"after text\" tree positions are only "
352 "valid on leaf nodes.";
379 BASE_DCHECK(child_position && !child_position->IsNullPosition());
380 return child_position->GetAnchor()->IsIgnored();
440 return text_offset_ == 0 ||
454 if (text_offset_ > 0)
456 if (!
IsLeaf() || text_offset_ == 0)
457 return child_index_ == 0;
460 return text_offset_ == 0;
479 switch (text_position->kind_) {
486 const std::vector<int32_t> word_starts =
487 text_position->GetWordStartOffsets();
489 int32_t{text_position->text_offset_});
496 switch (text_position->kind_) {
503 const std::vector<int32_t> word_ends =
504 text_position->GetWordEndOffsets();
505 return base::Contains(word_ends, int32_t{text_position->text_offset_});
512 switch (text_position->kind_) {
542 if (text_position->AtEndOfAnchor() &&
543 !text_position->AtEndOfTextSpan() &&
544 text_position->IsInWhiteSpace() &&
552 text_position->AtStartOfAnchor();
558 switch (text_position->kind_) {
570 if (!text_position->MaxTextOffset())
610 return (!text_position->AtEndOfTextSpan() &&
611 text_position->IsInWhiteSpace() &&
614 ? text_position->AtStartOfAnchor()
615 : text_position->AtEndOfAnchor();
619 return text_position->AtEndOfAnchor() &&
620 text_position->CreateNextLeafTextPosition()->AtEndOfLine();
641 switch (text_position->kind_) {
650 if (text_position->IsIgnored() || !text_position->AtStartOfAnchor())
655 if (text_position->IsInWhiteSpace()) {
656 return text_position->CreatePreviousLeafTextPosition()
671 bool crossed_line_breaking_object_token =
false;
672 auto abort_move_predicate =
673 [&crossed_line_breaking_object_token](
675 const AXMoveType
type,
const AXMoveDirection direction) {
676 return AbortMoveAtParagraphBoundary(
677 crossed_line_breaking_object_token, move_from, move_to,
type,
683 previous_text_position =
684 previous_text_position->CreatePreviousTextAnchorPosition(
685 abort_move_predicate);
692 }
while (previous_text_position->IsInWhiteSpace() ||
693 previous_text_position->IsIgnored());
694 return previous_text_position->IsNullPosition();
720 switch (text_position->kind_) {
729 if (text_position->IsIgnored() || !text_position->AtEndOfAnchor())
748 bool crossed_line_breaking_object_token =
false;
749 auto abort_move_predicate =
750 [&crossed_line_breaking_object_token](
752 const AXMoveType
type,
const AXMoveDirection direction) {
753 return AbortMoveAtParagraphBoundary(
754 crossed_line_breaking_object_token, move_from, move_to,
type,
760 next_text_position = next_text_position->CreateNextTextAnchorPosition(
761 abort_move_predicate);
762 }
while (next_text_position->IsIgnored());
763 if (next_text_position->IsNullPosition())
768 if (next_text_position->IsInWhiteSpace())
785 return next_text_position->CreatePositionAtStartOfAnchor()
786 ->AtStartOfParagraph();
793 switch (text_position->kind_) {
800 if (!text_position->AtStartOfAnchor())
810 text_position->CreatePreviousTextAnchorPosition(
811 AbortMoveAtPageBoundary);
812 return previous_text_position->IsNullPosition();
819 switch (text_position->kind_) {
826 if (!text_position->AtEndOfAnchor())
836 text_position->CreateNextTextAnchorPosition(
837 AbortMoveAtPageBoundary);
838 return next_text_position->IsNullPosition();
851 if (previous_anchor->IsNullPosition())
854 return previous_anchor->tree_id() !=
tree_id();
867 if (next_anchor->IsNullPosition())
870 return next_anchor->tree_id() !=
tree_id();
894 previous_position = previous_position->CreatePreviousLeafTreePosition(
895 AbortMoveAtFormatBoundary);
896 }
while (previous_position->IsIgnored());
898 if (previous_position->IsNullPosition())
928 next_position->CreateNextLeafTreePosition(AbortMoveAtFormatBoundary);
929 }
while (next_position->IsIgnored());
931 if (next_position->IsNullPosition())
943 switch (text_position->kind_) {
950 if (text_position->AtStartOfAnchor()) {
952 text_position->CreatePreviousLeafTreePosition();
955 if (!previous_position->IsNullPosition()) {
956 previous_position = text_position->CreatePreviousLeafTreePosition(
957 &AbortMoveAtStartOfInlineBlock);
961 if (previous_position->IsNullPosition())
965 if (text_position->AtEndOfAnchor()) {
967 text_position->CreateNextLeafTreePosition();
970 if (!next_position->IsNullPosition()) {
971 next_position = text_position->CreateNextLeafTreePosition(
972 &AbortMoveAtStartOfInlineBlock);
976 if (next_position->IsNullPosition())
1006 return tree_position->CreateNextAnchorPosition()->IsNullPosition();
1019 AXNodeType* common_anchor =
nullptr;
1020 while (!our_ancestors.empty() && !other_ancestors.empty() &&
1021 our_ancestors.top() == other_ancestors.top()) {
1022 common_anchor = our_ancestors.top();
1023 our_ancestors.pop();
1024 other_ancestors.pop();
1026 return common_anchor;
1042 const AXNodeType* ancestor_anchor,
1045 if (!ancestor_anchor) {
1050 while (!ancestor_position->IsNullPosition() &&
1051 ancestor_position->GetAnchor() != ancestor_anchor) {
1053 ancestor_position->CreateParentPosition(move_direction);
1055 return ancestor_position;
1062 switch (position->kind_) {
1067 if (!position->GetAnchor())
1078 position->tree_id(),
GetAnchorID(empty_object_node),
1085 if (position->child_index_ < 0)
1086 position->child_index_ = 0;
1087 else if (position->child_index_ > position->AnchorChildCount())
1088 position->child_index_ = position->AnchorChildCount();
1092 if (!position->GetAnchor())
1107 position->text_offset() > 0 ? 1 : 0,
1111 if (position->text_offset_ <= 0) {
1114 position->text_offset_ = 0;
1117 int max_text_offset = position->MaxTextOffset();
1118 if (position->text_offset_ > max_text_offset) {
1119 position->text_offset_ = max_text_offset;
1137 if (
copy->IsLeaf()) {
1138 const int max_text_offset =
copy->MaxTextOffset();
1139 copy->child_index_ =
1140 (max_text_offset != 0 &&
copy->text_offset_ != max_text_offset)
1154 int current_offset = 0;
1159 int child_length = child->MaxTextOffsetInParent();
1175 if (
copy->text_offset_ >= current_offset &&
1176 (
copy->text_offset_ < (current_offset + child_length) ||
1178 copy->text_offset_ == (current_offset + child_length)))) {
1182 current_offset += child_length;
1216 if (tree_position->child_index_ == tree_position->AnchorChildCount()) {
1219 ->CreateChildPositionAt(tree_position->child_index_ - 1)
1220 ->CreatePositionAtEndOfAnchor();
1223 tree_position->CreateChildPositionAt(tree_position->child_index_);
1225 BASE_DCHECK(tree_position && !tree_position->IsNullPosition());
1226 }
while (!tree_position->IsLeaf());
1228 BASE_DCHECK(tree_position && tree_position->IsLeafTreePosition());
1229 return tree_position;
1250 (
copy->text_offset_ > 0 &&
1251 copy->text_offset_ >=
copy->MaxTextOffset())) {
1252 copy->text_offset_ = 0;
1254 }
else if (
copy->child_index_ ==
copy->AnchorChildCount()) {
1255 copy->text_offset_ =
copy->MaxTextOffset();
1260 for (
int i = 0;
i <= child_index_; ++
i) {
1269 if (
i == child_index_ &&
copy->text_offset_ <= new_offset) {
1270 copy->text_offset_ = new_offset;
1274 int child_length = child->MaxTextOffsetInParent();
1277 if (
i == child_index_ &&
1278 (
copy->text_offset_ > (new_offset + child_length) ||
1281 (!
copy->AtEndOfAnchor() &&
1282 copy->text_offset_ == (new_offset + child_length)))) {
1283 copy->text_offset_ = new_offset;
1287 new_offset += child_length;
1310 int adjusted_offset = text_position->text_offset_;
1313 text_position->CreateChildPositionAt(0);
1320 i < text_position->AnchorChildCount() && adjusted_offset > 0; ++
i) {
1321 const int max_text_offset_in_parent =
1322 child_position->MaxTextOffsetInParent();
1323 if (adjusted_offset < max_text_offset_in_parent) {
1327 adjusted_offset == max_text_offset_in_parent) {
1334 child_position = std::move(text_position->CreateChildPositionAt(
i));
1335 adjusted_offset -= max_text_offset_in_parent;
1338 text_position = std::move(child_position);
1339 }
while (!text_position->IsLeaf());
1343 text_position->text_offset_ = adjusted_offset;
1348 return text_position;
1387 !leaf_tree_position->IsIgnored()) {
1389 while (!unignored_position->IsNullPosition()) {
1392 if (!unignored_position->GetAnchor()->IsIgnored()) {
1394 return unignored_position;
1396 unignored_position = unignored_position->CreateParentPosition();
1403 while (leaf_tree_position->IsIgnored()) {
1404 switch (adjustment_behavior) {
1406 leaf_tree_position = leaf_tree_position->CreateNextLeafTreePosition();
1409 leaf_tree_position =
1410 leaf_tree_position->CreatePreviousLeafTreePosition();
1415 leaf_tree_position =
1416 leaf_tree_position->CreatePositionAtEndOfAnchor();
1422 return leaf_tree_position->AsTextPosition();
1423 return leaf_tree_position;
1447 switch (expand_behavior) {
1452 left_position->CreatePositionAtTextBoundary(
1455 return AXRangeType(std::move(left_position), std::move(right_position));
1461 right_position->CreatePositionAtTextBoundary(
1464 return AXRangeType(std::move(left_position), std::move(right_position));
1482 switch (direction) {
1484 resulting_position =
1494 switch (direction) {
1496 resulting_position =
1506 switch (direction) {
1508 resulting_position =
1518 switch (direction) {
1520 resulting_position =
1530 switch (direction) {
1532 resulting_position =
1542 switch (direction) {
1553 switch (direction) {
1555 resulting_position =
1565 switch (direction) {
1567 resulting_position =
1577 switch (direction) {
1579 resulting_position =
1589 switch (direction) {
1591 resulting_position =
1595 resulting_position =
1602 switch (direction) {
1604 resulting_position =
1608 resulting_position =
1615 switch (direction) {
1617 resulting_position =
1621 resulting_position =
1628 BASE_LOG() <<
"Sentence boundaries are not yet supported.";
1633 BASE_LOG() <<
"Sentence boundaries are not yet supported.";
1638 BASE_LOG() <<
"Sentence boundaries are not yet supported.";
1644 BASE_LOG() <<
"We can't reach the start of the document if we "
1646 "from crossing boundaries.";
1649 switch (direction) {
1660 switch (direction) {
1662 resulting_position =
1672 switch (direction) {
1674 resulting_position =
1684 switch (direction) {
1686 resulting_position =
1695 return resulting_position;
1719 tree_id_, anchor_id_,
1740 previous_position = previous_position->CreatePreviousAnchorPosition();
1741 }
while (!previous_position->AtStartOfAXTree());
1747 previous_position = previous_position->AsTextPosition();
1748 return previous_position;
1763 next_position = next_position->CreateNextAnchorPosition()
1764 ->CreatePositionAtEndOfAnchor();
1765 }
while (!next_position->AtEndOfAXTree());
1771 next_position = next_position->AsTextPosition();
1772 return next_position->CreatePositionAtEndOfAnchor();
1788 if (!position->IsNullPosition()) {
1789 position = position->CreatePositionAtStartOfAnchor();
1791 position = position->AsTextPosition();
1808 if (!position->IsNullPosition()) {
1809 while (!position->IsLeaf()) {
1811 position->CreateChildPositionAt(position->AnchorChildCount() - 1);
1813 position = position->CreatePositionAtEndOfAnchor();
1815 position = position->AsTextPosition();
1841 if (child_position->IsLeaf())
1843 return child_position;
1920 int max_text_offset_in_parent =
1924 if (max_text_offset == max_text_offset_in_parent) {
1927 parent_offset += text_offset_;
1928 }
else if (text_offset_ > 0) {
1935 switch (move_direction) {
1942 parent_offset += max_text_offset_in_parent;
1957 max_text_offset_in_parent = dummy_position->MaxTextOffset();
1958 if (parent_offset > max_text_offset_in_parent) {
1959 parent_offset = max_text_offset_in_parent;
1962 tree_id, parent_id, parent_offset, parent_affinity);
1980 if (text_offset_ == max_text_offset &&
1981 !parent_position->AtEndOfAnchor() &&
1982 parent_position->AtStartOfLine()) {
1985 return parent_position;
2010 bool* crossed_line_breaking_object =
nullptr)
const {
2011 if (crossed_line_breaking_object)
2012 *crossed_line_breaking_object =
false;
2017 std::function<AbortMovePredicate> abort_move_predicate;
2018 if (crossed_line_breaking_object) {
2019 abort_move_predicate = [crossed_line_breaking_object](
2022 const AXMoveType
type,
2023 const AXMoveDirection direction) {
2024 return UpdateCrossedLineBreakingObjectToken(
2025 *crossed_line_breaking_object, move_from, move_to,
type, direction);
2028 abort_move_predicate =
2030 const AXMoveType
type,
const AXMoveDirection direction) {
2031 return AXPosition::DefaultAbortMovePredicate(move_from, move_to,
2041 return CreatePreviousTextAnchorPosition(DefaultAbortMovePredicate);
2079 text_position = text_position->AsLeafTextPosition();
2081 <<
"Adjusting to a leaf position should never turn a non-null position "
2083 if (!text_position->IsIgnored() && !text_position->AtEndOfAnchor()) {
2085 return text_position;
2088 text_position = text_position->CreateNextLeafTextPosition();
2089 while (!text_position->IsNullPosition() &&
2090 (text_position->IsIgnored() || !text_position->MaxTextOffset())) {
2091 text_position = text_position->CreateNextLeafTextPosition();
2093 return text_position;
2113 text_position = text_position->AsLeafTextPosition();
2115 <<
"Adjusting to a leaf position should never turn a non-null position "
2117 if (!text_position->IsIgnored() && !text_position->AtStartOfAnchor()) {
2129 return text_position;
2131 text_position = text_position->CreatePreviousLeafTextPosition();
2132 while (!text_position->IsNullPosition() &&
2133 (text_position->IsIgnored() || !text_position->MaxTextOffset())) {
2134 text_position = text_position->CreatePreviousLeafTextPosition();
2136 return text_position->CreatePositionAtEndOfAnchor();
2157 if (text_position->IsNullPosition()) {
2160 text_position =
Clone();
2162 return text_position;
2166 *text_position == *
this) {
2169 BASE_DCHECK(text_position->text_offset_ < text_position->MaxTextOffset());
2171 ++text_position->text_offset_;
2173 BASE_DCHECK(text_position->text_offset_ <= text_position->MaxTextOffset());
2178 const AXNodeType* common_anchor = text_position->LowestCommonAnchor(*
this);
2180 text_position = text_position->CreateAncestorPosition(
2192 return text_position->AsTreePosition();
2193 return text_position;
2211 if (text_position->IsNullPosition()) {
2214 text_position =
Clone();
2216 return text_position;
2220 *text_position == *
this) {
2225 --text_position->text_offset_;
2227 BASE_DCHECK(text_position->text_offset_ < text_position->MaxTextOffset());
2232 const AXNodeType* common_anchor = text_position->LowestCommonAnchor(*
this);
2234 text_position = text_position->CreateAncestorPosition(
2246 return text_position->AsTreePosition();
2247 return text_position;
2254 &AtStartOfWordPredicate, &AtEndOfWordPredicate,
2255 &GetWordStartOffsetsFunc);
2262 &AtStartOfWordPredicate, &AtEndOfWordPredicate,
2263 &GetWordStartOffsetsFunc);
2271 &AtStartOfWordPredicate, &AtEndOfWordPredicate, &GetWordEndOffsetsFunc);
2279 &AtStartOfWordPredicate, &AtEndOfWordPredicate, &GetWordEndOffsetsFunc);
2286 &AtStartOfLinePredicate, &AtEndOfLinePredicate);
2293 &AtStartOfLinePredicate, &AtEndOfLinePredicate);
2302 &AtStartOfLinePredicate, &AtEndOfLinePredicate);
2311 &AtStartOfLinePredicate, &AtEndOfLinePredicate);
2341 tree_position->CreatePreviousLeafTreePosition();
2348 tree_position = std::move(previous_tree_position);
2349 previous_tree_position = tree_position->CreatePreviousLeafTreePosition();
2355 !previous_tree_position->IsNullPosition() &&
2356 !tree_position->AtStartOfFormat()) {
2357 tree_position = std::move(previous_tree_position);
2358 previous_tree_position = tree_position->CreatePreviousLeafTreePosition();
2365 const AXNodeType* common_anchor = tree_position->LowestCommonAnchor(*
this);
2367 tree_position = tree_position->CreateAncestorPosition(
2374 return tree_position->AsTextPosition();
2375 return tree_position;
2405 tree_position->CreateNextLeafTreePosition()
2406 ->CreatePositionAtEndOfAnchor();
2412 tree_position = std::move(next_tree_position);
2413 next_tree_position = tree_position->CreateNextLeafTreePosition()
2414 ->CreatePositionAtEndOfAnchor();
2420 !next_tree_position->IsNullPosition() &&
2421 !tree_position->AtEndOfFormat()) {
2422 tree_position = std::move(next_tree_position);
2423 next_tree_position = tree_position->CreateNextLeafTreePosition()
2424 ->CreatePositionAtEndOfAnchor();
2431 const AXNodeType* common_anchor = tree_position->LowestCommonAnchor(*
this);
2433 tree_position = tree_position->CreateAncestorPosition(
2440 return tree_position->AsTextPosition();
2441 return tree_position;
2448 &AtStartOfParagraphPredicate, &AtEndOfParagraphPredicate);
2455 &AtStartOfParagraphPredicate, &AtEndOfParagraphPredicate);
2462 &AtStartOfParagraphPredicate, &AtEndOfParagraphPredicate);
2469 &AtStartOfParagraphPredicate, &AtEndOfParagraphPredicate);
2502 while (!previous_position->IsNullPosition()) {
2504 previous_position->AsLeafTextPosition()
2505 ->CreatePreviousLeafTextPosition()
2506 ->CreatePositionAtEndOfAnchor();
2507 if (look_back_position->IsNullPosition()) {
2513 look_back_position->CreateNextLeafTextPosition()
2514 ->CreatePositionAtEndOfAnchor();
2515 if (*forward_step_position == *previous_position)
2518 previous_position = previous_position->CreateBoundaryEndPosition(
2520 &AtStartOfParagraphPredicate, &AtEndOfParagraphPredicate);
2524 return previous_position;
2531 &AtStartOfPagePredicate, &AtEndOfPagePredicate);
2538 &AtStartOfPagePredicate, &AtEndOfPagePredicate);
2545 &AtStartOfPagePredicate, &AtEndOfPagePredicate);
2552 &AtStartOfPagePredicate, &AtEndOfPagePredicate);
2562 if (text_position->IsNullPosition())
2563 return text_position;
2567 text_position->CreateAdjacentLeafTextPosition(move_direction);
2568 if (text_position->IsNullPosition()) {
2573 return text_position;
2578 if (!at_start_condition(text_position)) {
2579 text_position = text_position->CreatePositionAtNextOffsetBoundary(
2580 move_direction, get_start_offsets);
2582 while (!at_start_condition(text_position)) {
2585 next_position = text_position->CreateNextLeafTextPosition();
2587 if (text_position->AtStartOfAnchor()) {
2588 next_position = text_position->CreatePreviousLeafTextPosition();
2590 text_position = text_position->CreatePositionAtStartOfAnchor();
2596 if (next_position->IsNullPosition()) {
2598 switch (move_direction) {
2608 if (boundary_behavior ==
2612 switch (move_direction) {
2614 text_position = text_position->CreatePositionAtEndOfAnchor();
2617 text_position = text_position->CreatePositionAtStartOfAnchor();
2624 return next_position->AsUnignoredPosition(
2625 AdjustmentBehaviorFromBoundaryDirection(move_direction));
2630 text_position = next_position->CreatePositionAtFirstOffsetBoundary(
2631 move_direction, get_start_offsets);
2638 const AXNodeType* common_anchor = text_position->LowestCommonAnchor(*
this);
2641 text_position->CreateAncestorPosition(common_anchor, move_direction);
2643 switch (move_direction) {
2657 text_position = text_position->AsTreePosition();
2659 AdjustmentBehaviorFromBoundaryDirection(move_direction));
2666 if (unignored_position->IsNullPosition() &&
2668 unignored_position =
2669 text_position->AsUnignoredPosition(OppositeAdjustmentBehavior(
2670 AdjustmentBehaviorFromBoundaryDirection(move_direction)));
2672 return unignored_position;
2682 if (text_position->IsNullPosition())
2683 return text_position;
2687 text_position->CreateAdjacentLeafTextPosition(move_direction);
2688 if (text_position->IsNullPosition()) {
2693 return text_position;
2698 if (!at_end_condition(text_position)) {
2699 text_position = text_position->CreatePositionAtNextOffsetBoundary(
2700 move_direction, get_end_offsets);
2702 while (!at_end_condition(text_position)) {
2705 if (text_position->AtEndOfAnchor()) {
2706 next_position = text_position->CreateNextLeafTextPosition();
2708 text_position = text_position->CreatePositionAtEndOfAnchor();
2713 next_position = text_position->CreatePreviousLeafTextPosition()
2714 ->CreatePositionAtEndOfAnchor();
2717 if (next_position->IsNullPosition()) {
2719 switch (move_direction) {
2729 if (boundary_behavior ==
2733 switch (move_direction) {
2735 text_position = text_position->CreatePositionAtEndOfAnchor();
2738 text_position = text_position->CreatePositionAtStartOfAnchor();
2745 return next_position->AsUnignoredPosition(
2746 AdjustmentBehaviorFromBoundaryDirection(move_direction));
2751 text_position = next_position->CreatePositionAtFirstOffsetBoundary(
2752 move_direction, get_end_offsets);
2759 const AXNodeType* common_anchor = text_position->LowestCommonAnchor(*
this);
2762 text_position->CreateAncestorPosition(common_anchor, move_direction);
2764 switch (move_direction) {
2785 if (downstream_position->AtStartOfAnchor() ||
2786 downstream_position->AtEndOfAnchor() ||
2787 !at_start_condition(downstream_position)) {
2793 text_position = text_position->AsTreePosition();
2795 AdjustmentBehaviorFromBoundaryDirection(move_direction));
2802 if (unignored_position->IsNullPosition() &&
2804 unignored_position =
2805 text_position->AsUnignoredPosition(OppositeAdjustmentBehavior(
2806 AdjustmentBehaviorFromBoundaryDirection(move_direction)));
2808 return unignored_position;
2835 return std::optional<int>(0);
2837 return std::optional<int>(std::nullopt);
2866 if (normalized_this_position->IsTextPosition()) {
2867 normalized_this_position =
2868 normalized_this_position->AsLeafTextPositionBeforeCharacter();
2872 if (normalized_other_position->IsTextPosition()) {
2873 normalized_other_position =
2874 normalized_other_position->AsLeafTextPositionBeforeCharacter();
2877 if (normalized_this_position->IsNullPosition()) {
2878 if (normalized_other_position->IsNullPosition()) {
2886 }
else if (normalized_other_position->IsNullPosition()) {
2895 const AXNodeType* common_anchor =
nullptr;
2896 std::stack<AXNodeType*> our_ancestors =
2897 normalized_this_position->GetAncestorAnchors();
2898 std::stack<AXNodeType*> other_ancestors =
2899 normalized_other_position->GetAncestorAnchors();
2900 while (!our_ancestors.empty() && !other_ancestors.empty() &&
2901 our_ancestors.top() == other_ancestors.top()) {
2902 common_anchor = our_ancestors.top();
2903 our_ancestors.pop();
2904 other_ancestors.pop();
2908 return std::optional<int>(std::nullopt);
2912 if (!our_ancestors.empty() && !other_ancestors.empty()) {
2916 int this_uncommon_ancestor_index =
2917 this_uncommon_tree_position->AnchorIndexInParent();
2921 int other_uncommon_ancestor_index =
2922 other_uncommon_tree_position->AnchorIndexInParent();
2924 other_uncommon_ancestor_index);
2925 int result = this_uncommon_ancestor_index - other_uncommon_ancestor_index;
2967 if (!normalized_this_position->AtStartOfAnchor() &&
2968 this_uncommon_tree_position->IsEmbeddedObjectInParent()) {
2971 if (!normalized_other_position->AtStartOfAnchor() &&
2972 other_uncommon_tree_position->IsEmbeddedObjectInParent()) {
2981 (
result < 0 && slow_result < 0) ||
2982 (
result > 0 && slow_result > 0));
3006 return std::optional<int>(std::nullopt);
3013 if (this->
GetAnchor() == common_anchor) {
3016 return std::optional<int>(this->text_offset_ -
3017 other_text_position->text_offset_);
3022 if (other.
GetAnchor() == common_anchor) {
3025 return std::optional<int>(this_text_position->text_offset_ -
3026 other.text_offset_);
3035 BASE_DCHECK(this_text_position_ancestor->IsTextPosition());
3036 BASE_DCHECK(other_text_position_ancestor->IsTextPosition());
3037 BASE_DCHECK(common_anchor == this_text_position_ancestor->GetAnchor());
3038 BASE_DCHECK(common_anchor == other_text_position_ancestor->GetAnchor());
3061 return std::optional<int>(this_text_position_ancestor->text_offset_ -
3062 other_text_position_ancestor->text_offset_);
3071 BASE_DCHECK(this_tree_position_ancestor->IsTreePosition());
3072 BASE_DCHECK(other_tree_position_ancestor->IsTreePosition());
3073 BASE_DCHECK(common_anchor == this_tree_position_ancestor->GetAnchor());
3074 BASE_DCHECK(common_anchor == other_tree_position_ancestor->GetAnchor());
3076 return std::optional<int>(this_tree_position_ancestor->child_index() -
3077 other_tree_position_ancestor->child_index());
3086 if (text_offset_ > max_text_offset)
3087 text_offset_ = max_text_offset;
3104 if (
GetAnchor()->IsCollapsedMenuListPopUpButton())
3149 if (AXNodeType* popup_button =
3150 GetAnchor()->GetCollapsedMenuListPopUpButtonAncestor()) {
3151 return popup_button;
3165 if (position && position->IsEmptyObjectReplacedByCharacter())
3166 return ancestor_node;
3174 std::swap(anchor_id_, other.anchor_id_);
3175 std::swap(child_index_, other.child_index_);
3176 std::swap(text_offset_, other.text_offset_);
3210 return static_cast<int>(
GetText().length());
3217 anchor_id_(
AXNode::kInvalidAXID),
3224 : kind_(other.kind_),
3225 tree_id_(other.tree_id_),
3226 anchor_id_(other.anchor_id_),
3227 child_index_(other.child_index_),
3228 text_offset_(other.text_offset_),
3229 affinity_(other.affinity_) {}
3242 if (parent_position->IsNullPosition())
3245 int offset_in_parent = 0;
3246 for (
int i = 0;
i < parent_position->child_index(); ++
i) {
3249 offset_in_parent += child->MaxTextOffsetInParent();
3251 return offset_in_parent;
3281 int32_t* child_id)
const = 0;
3298 int32_t node_id)
const = 0;
3328 enum class AXMoveType {
3335 enum class AXMoveDirection {
3343 typedef bool AbortMovePredicate(
const AXPosition& move_from,
3345 const AXMoveType
type,
3346 const AXMoveDirection direction);
3350 bool AtEndOfTextSpan()
const {
3357 const bool is_last_child =
3366 std::function<AbortMovePredicate> abort_predicate)
const {
3374 const int child_index = current_position->child_index_;
3377 current_position->CreateChildPositionAt(
child_index);
3379 if (abort_predicate(*current_position, *child_position,
3380 AXMoveType::kDescendant,
3381 AXMoveDirection::kNextInTree)) {
3384 return child_position;
3389 current_position->CreateParentPosition();
3393 while (!parent_position->IsNullPosition()) {
3394 const int index_in_parent = current_position->AnchorIndexInParent();
3395 if (index_in_parent + 1 < parent_position->AnchorChildCount()) {
3397 parent_position->CreateChildPositionAt(index_in_parent + 1);
3400 if (abort_predicate(*current_position, *next_sibling,
3401 AXMoveType::kSibling,
3402 AXMoveDirection::kNextInTree)) {
3405 return next_sibling;
3408 if (abort_predicate(*current_position, *parent_position,
3409 AXMoveType::kAncestor,
3410 AXMoveDirection::kNextInTree)) {
3414 current_position = std::move(parent_position);
3415 parent_position = current_position->CreateParentPosition();
3422 std::function<AbortMovePredicate> abort_predicate)
const {
3430 current_position->CreateParentPosition();
3431 if (parent_position->IsNullPosition())
3432 return parent_position;
3435 const int index_in_parent = current_position->AnchorIndexInParent();
3436 if (index_in_parent <= 0) {
3437 if (abort_predicate(*current_position, *parent_position,
3438 AXMoveType::kAncestor,
3439 AXMoveDirection::kPreviousInTree)) {
3442 return parent_position;
3447 parent_position->CreateChildPositionAt(index_in_parent - 1);
3450 if (abort_predicate(*current_position, *rightmost_leaf,
3451 AXMoveType::kSibling,
3452 AXMoveDirection::kPreviousInTree)) {
3456 while (!rightmost_leaf->IsLeaf()) {
3457 parent_position = std::move(rightmost_leaf);
3458 rightmost_leaf = parent_position->CreateChildPositionAt(
3459 parent_position->AnchorChildCount() - 1);
3462 if (abort_predicate(*parent_position, *rightmost_leaf,
3463 AXMoveType::kDescendant,
3464 AXMoveDirection::kPreviousInTree)) {
3468 return rightmost_leaf;
3474 std::function<AbortMovePredicate> abort_predicate)
const {
3480 while (!next_leaf->IsNullPosition() && !next_leaf->IsLeaf())
3481 next_leaf = next_leaf->CreateNextAnchorPosition(abort_predicate);
3484 return next_leaf->AsLeafTextPosition();
3490 std::function<AbortMovePredicate> abort_predicate)
const {
3497 while (!previous_leaf->IsNullPosition() && !previous_leaf->IsLeaf()) {
3499 previous_leaf->CreatePreviousAnchorPosition(abort_predicate);
3503 return previous_leaf->AsLeafTextPosition();
3509 std::function<AbortMovePredicate> abort_predicate)
const {
3512 while (!next_leaf->IsNullPosition() && !next_leaf->IsLeaf())
3513 next_leaf = next_leaf->CreateNextAnchorPosition(abort_predicate);
3522 std::function<AbortMovePredicate> abort_predicate)
const {
3525 while (!previous_leaf->IsNullPosition() && !previous_leaf->IsLeaf()) {
3527 previous_leaf->CreatePreviousAnchorPosition(abort_predicate);
3531 return previous_leaf;
3541 return !position->IsIgnored() && position->AtStartOfPage();
3547 return !position->IsIgnored() && position->AtEndOfPage();
3552 return position->AtStartOfParagraph();
3557 return position->AtEndOfParagraph();
3562 return position->AtStartOfLine();
3567 return position->AtEndOfLine();
3575 return !position->IsIgnored() && position->AtStartOfWord();
3583 return !position->IsIgnored() && position->AtEndOfWord();
3586 static bool DefaultAbortMovePredicate(
const AXPosition& move_from,
3588 const AXMoveType move_type,
3589 const AXMoveDirection direction) {
3595 static bool AbortMoveAtFormatBoundary(
const AXPosition& move_from,
3597 const AXMoveType move_type,
3598 const AXMoveDirection direction) {
3599 if (move_from.IsNullPosition() || move_to.IsNullPosition() ||
3600 move_from.IsEmptyObjectReplacedByCharacter() ||
3601 move_to.IsEmptyObjectReplacedByCharacter()) {
3608 if (from_role != to_role) {
3614 return move_from.AsLeafTreePosition()->GetTextStyles() !=
3615 move_to.AsLeafTreePosition()->GetTextStyles();
3618 static bool MoveCrossesLineBreakingObject(
const AXPosition& move_from,
3620 const AXMoveType move_type,
3621 const AXMoveDirection direction) {
3622 const bool move_from_break = move_from.IsInLineBreakingObject();
3623 const bool move_to_break = move_to.IsInLineBreakingObject();
3625 switch (move_type) {
3626 case AXMoveType::kAncestor:
3630 return move_from_break;
3631 case AXMoveType::kDescendant:
3635 return move_to_break;
3636 case AXMoveType::kSibling:
3639 return move_from_break || move_to_break;
3651 static bool AbortMoveAtParagraphBoundary(
3652 bool& crossed_line_breaking_object_token,
3655 const AXMoveType move_type,
3656 const AXMoveDirection direction) {
3657 if (move_from.IsNullPosition() || move_to.IsNullPosition() ||
3658 move_from.IsEmptyObjectReplacedByCharacter() ||
3659 move_to.IsEmptyObjectReplacedByCharacter()) {
3663 if (!crossed_line_breaking_object_token) {
3664 crossed_line_breaking_object_token = MoveCrossesLineBreakingObject(
3665 move_from, move_to, move_type, direction);
3668 if (crossed_line_breaking_object_token && move_to.IsLeaf()) {
3671 return direction != AXMoveDirection::kNextInTree ||
3672 !move_to.IsInWhiteSpace();
3679 static bool UpdateCrossedLineBreakingObjectToken(
3680 bool& crossed_line_breaking_object_token,
3683 const AXMoveType move_type,
3684 const AXMoveDirection direction) {
3685 if (!crossed_line_breaking_object_token) {
3686 crossed_line_breaking_object_token = MoveCrossesLineBreakingObject(
3687 move_from, move_to, move_type, direction);
3693 static bool AbortMoveAtPageBoundary(
const AXPosition& move_from,
3695 const AXMoveType move_type,
3696 const AXMoveDirection direction) {
3697 if (move_from.IsNullPosition() || move_to.IsNullPosition())
3700 const bool move_from_break = move_from.GetAnchor()->GetBoolAttribute(
3702 const bool move_to_break = move_to.GetAnchor()->GetBoolAttribute(
3705 switch (move_type) {
3706 case AXMoveType::kAncestor:
3710 return move_from_break;
3711 case AXMoveType::kDescendant:
3715 return move_to_break;
3716 case AXMoveType::kSibling:
3719 return move_from_break && move_to_break;
3725 static bool AbortMoveAtStartOfInlineBlock(
const AXPosition& move_from,
3727 const AXMoveType move_type,
3728 const AXMoveDirection direction) {
3729 if (move_from.IsNullPosition() || move_to.IsNullPosition())
3733 const bool move_from_is_inline_block =
3734 move_from.GetAnchor()->GetStringAttribute(
3736 const bool move_to_is_inline_block =
3737 move_to.GetAnchor()->GetStringAttribute(
3740 switch (direction) {
3741 case AXMoveDirection::kNextInTree:
3743 return move_to_is_inline_block &&
3744 (move_type == AXMoveType::kDescendant ||
3745 move_type == AXMoveType::kSibling);
3746 case AXMoveDirection::kPreviousInTree:
3748 return move_from_is_inline_block &&
3749 (move_type == AXMoveType::kAncestor ||
3750 move_type == AXMoveType::kSibling);
3758 switch (move_direction) {
3768 switch (adjustment_behavior) {
3776 static std::vector<int32_t> GetWordStartOffsetsFunc(
3778 return position->GetWordStartOffsets();
3781 static std::vector<int32_t> GetWordEndOffsetsFunc(
3783 return position->GetWordEndOffsets();
3788 while (!iterator->IsNullPosition()) {
3790 iterator->CreateParentPosition()->IsNullPosition()) {
3793 iterator = iterator->CreateParentPosition();
3809 const std::vector<int32_t> boundary_offsets = get_offsets(text_position);
3810 if (boundary_offsets.empty())
3811 return text_position;
3813 switch (move_direction) {
3815 const auto offsets_iterator =
3816 std::upper_bound(boundary_offsets.begin(), boundary_offsets.end(),
3817 int32_t{text_position->text_offset_});
3819 if (offsets_iterator < boundary_offsets.end()) {
3820 text_position->text_offset_ =
static_cast<int>(*offsets_iterator);
3826 auto offsets_iterator =
3827 std::lower_bound(boundary_offsets.begin(), boundary_offsets.end(),
3828 int32_t{text_position->text_offset_});
3831 if (offsets_iterator > boundary_offsets.begin()) {
3836 text_position->text_offset_ =
static_cast<int>(*offsets_iterator);
3843 return text_position;
3860 const std::vector<int32_t> boundary_offsets = get_offsets(text_position);
3861 switch (move_direction) {
3863 if (boundary_offsets.empty()) {
3864 return text_position->CreatePositionAtEndOfAnchor();
3866 text_position->text_offset_ =
static_cast<int>(boundary_offsets[0]);
3867 return text_position;
3871 if (boundary_offsets.empty()) {
3872 return text_position->CreatePositionAtStartOfAnchor();
3874 text_position->text_offset_ =
3875 static_cast<int>(boundary_offsets[boundary_offsets.size() - 1]);
3876 return text_position;
3906 switch (move_direction) {
3917 while (text_position->AtEndOfAnchor()) {
3918 text_position = text_position->CreateNextLeafTextPosition();
3920 if (!text_position->IsNullPosition())
3921 ++text_position->text_offset_;
3930 while (text_position->AtStartOfAnchor()) {
3931 text_position = text_position->CreatePreviousLeafTextPosition()
3932 ->CreatePositionAtEndOfAnchor();
3934 if (!text_position->IsNullPosition())
3935 --text_position->text_offset_;
3940 return text_position;
3972template <
class AXPositionType,
class AXNodeType>
3974template <
class AXPositionType,
class AXNodeType>
3976template <
class AXPositionType,
class AXNodeType>
3979template <
class AXPositionType,
class AXNodeType>
3982 const std::optional<int> compare_to_optional = first.
CompareTo(second);
3983 return compare_to_optional.has_value() && compare_to_optional.value() == 0;
3986template <
class AXPositionType,
class AXNodeType>
3989 const std::optional<int> compare_to_optional = first.
CompareTo(second);
3990 return compare_to_optional.has_value() && compare_to_optional.value() != 0;
3993template <
class AXPositionType,
class AXNodeType>
3996 const std::optional<int> compare_to_optional = first.
CompareTo(second);
3997 return compare_to_optional.has_value() && compare_to_optional.value() < 0;
4000template <
class AXPositionType,
class AXNodeType>
4003 const std::optional<int> compare_to_optional = first.
CompareTo(second);
4004 return compare_to_optional.has_value() && compare_to_optional.value() <= 0;
4007template <
class AXPositionType,
class AXNodeType>
4010 const std::optional<int> compare_to_optional = first.
CompareTo(second);
4011 return compare_to_optional.has_value() && compare_to_optional.value() > 0;
4014template <
class AXPositionType,
class AXNodeType>
4017 const std::optional<int> compare_to_optional = first.
CompareTo(second);
4018 return compare_to_optional.has_value() && compare_to_optional.value() >= 0;
4021template <
class AXPositionType,
class AXNodeType>
4027template <
class AXPositionType,
class AXNodeType>
void swap(sk_sp< T > &a, sk_sp< T > &b)
static void copy(void *dst, const uint8_t *src, int width, int bpp, int deltaSrc, int offset, const SkPMColor ctable[])
static constexpr AXID kInvalidAXID
bool AtStartOfWord() const
bool AtStartOfParagraph() const
AXPositionInstance CreatePreviousParagraphEndPosition(AXBoundaryBehavior boundary_behavior) const
virtual AXTreeID GetTreeID(AXNodeType *node) const =0
AXPositionInstance CreateNextWordStartPosition(AXBoundaryBehavior boundary_behavior) const
bool AtEndOfParagraph() const
AXPositionInstance CreatePositionAtStartOfAXTree() const
bool AtStartOfPage() const
bool IsLeafTreePosition() const
virtual bool IsEmbeddedObjectInParent() const =0
AXPositionInstance CreateAncestorPosition(const AXNodeType *ancestor_anchor, ax::mojom::MoveDirection move_direction=ax::mojom::MoveDirection::kForward) const
AXPositionInstance CreatePreviousLeafTreePosition() const
AXPositionInstance AsLeafTextPositionBeforeCharacter() const
virtual ~AXPosition()=default
virtual bool IsInTextObject() const =0
AXRange< AXPosition< AXPositionType, AXNodeType > > AXRangeType
AXPositionInstance CreatePreviousLineStartPosition(AXBoundaryBehavior boundary_behavior) const
AXPositionInstance LowestCommonAncestor(const AXPosition &second) const
AXPositionInstance CreateNextParagraphEndPosition(AXBoundaryBehavior boundary_behavior) const
AXNodeType * LowestCommonAnchor(const AXPosition &second) const
bool AtStartOfAXTree() const
AXPositionInstance CreateNextWordEndPosition(AXBoundaryBehavior boundary_behavior) const
AXPositionInstance AsTreePosition() const
AXPositionInstance CreatePreviousAnchorPosition() const
virtual int MaxTextOffset() const
AXPosition & operator=(const AXPosition &other)
AXPositionKind kind() const
virtual AXNodeType * GetLowestUnignoredAncestor() const =0
static AXPositionInstance Unserialize(const SerializedPosition &serialization)
virtual int AnchorUnignoredChildCount() const =0
virtual void AnchorChild(int child_index, AXTreeID *tree_id, int32_t *child_id) const =0
AXNodeType * GetEmptyObjectAncestorNode() const
bool AtLastNodeInTree() const
virtual int32_t GetNextOnLineID(int32_t node_id) const =0
AXPositionInstance AsTextPosition() const
static constexpr char16_t kEmbeddedCharacter
AXPositionInstance CreatePositionAtStartOfAnchor() const
bool AtStartOfLine() const
virtual AXNodeType * GetNodeInTree(AXTreeID tree_id, int32_t node_id) const =0
virtual bool IsInLineBreak() const =0
AXPositionInstance CreatePositionAtEndOfAnchor() const
AXPositionInstance CreateNextFormatEndPosition(AXBoundaryBehavior boundary_behavior) const
AXPositionInstance AsLeafTextPositionAfterCharacter() const
AXPositionInstance AsLeafTreePosition() const
bool AtStartOfDocument() const
bool AtEndOfAXTree() const
virtual void AnchorParent(AXTreeID *tree_id, int32_t *parent_id) const =0
AXPositionInstance CreatePreviousWordEndPosition(AXBoundaryBehavior boundary_behavior) const
AXPositionInstance CreateBoundaryStartPosition(AXBoundaryBehavior boundary_behavior, ax::mojom::MoveDirection move_direction, BoundaryConditionPredicate at_start_condition, BoundaryConditionPredicate at_end_condition, BoundaryTextOffsetsFunc get_start_offsets={}) const
AXPositionInstance CreateChildPositionAt(int child_index) const
AXPositionInstance CreateBoundaryEndPosition(AXBoundaryBehavior boundary_behavior, ax::mojom::MoveDirection move_direction, BoundaryConditionPredicate at_start_condition, BoundaryConditionPredicate at_end_condition, BoundaryTextOffsetsFunc get_end_offsets={}) const
virtual int AnchorChildCount() const =0
std::unique_ptr< AXPosition< AXPositionType, AXNodeType > > AXPositionInstance
int MaxTextOffsetInParent() const
AXPositionInstance CreatePreviousCharacterPosition(AXBoundaryBehavior boundary_behavior) const
bool IsLeafTextPosition() const
static const int INVALID_OFFSET
void swap(AXPosition &other)
AXPositionInstance AsLeafTextPosition() const
AXRangeType ExpandToEnclosingTextBoundary(ax::mojom::TextBoundary boundary, AXRangeExpandBehavior expand_behavior) const
virtual ax::mojom::Role GetRole(AXNodeType *node) const =0
std::optional< int > CompareTo(const AXPosition &other) const
AXPositionInstance CreateNextLeafTextPosition(bool *crossed_line_breaking_object=nullptr) const
bool AtStartOfFormat() const
AXPositionInstance CreatePositionAtTextBoundary(ax::mojom::TextBoundary boundary, ax::mojom::MoveDirection direction, AXBoundaryBehavior boundary_behavior) const
std::optional< int > SlowCompareTo(const AXPosition &other) const
std::vector< int32_t > BoundaryTextOffsetsFunc(const AXPositionInstance &)
void Initialize(AXPositionKind kind, AXTreeID tree_id, int32_t anchor_id, int child_index, int text_offset, ax::mojom::TextAffinity affinity)
bool IsTreePosition() const
virtual int AnchorIndexInParent() const =0
virtual std::u16string GetText() const =0
AXPositionInstance CreatePositionAtEndOfAXTree() const
AXPosition(const AXPosition &other)
AXPositionInstance CreatePreviousPageStartPosition(AXBoundaryBehavior boundary_behavior) const
AXPositionInstance CreateNextAnchorPosition() const
static AXPositionInstance CreateNullPosition()
bool AtEndOfFormat() const
bool IsInDescendantOfEmptyObject() const
AXPositionInstance CreateNextPageStartPosition(AXBoundaryBehavior boundary_behavior) const
bool AtEndOfDocument() const
AXNode::AXID anchor_id() const
AXPositionInstance CreatePreviousLineEndPosition(AXBoundaryBehavior boundary_behavior) const
AXPositionInstance CreateNextLineEndPosition(AXBoundaryBehavior boundary_behavior) const
SerializedPosition Serialize()
AXPositionInstance AsValidPosition() const
AXPositionInstance CreatePreviousPageEndPosition(AXBoundaryBehavior boundary_behavior) const
bool AtStartOfAnchor() const
AXPositionInstance CreateNextLineStartPosition(AXBoundaryBehavior boundary_behavior) const
AXPositionInstance CreateNextCharacterPosition(AXBoundaryBehavior boundary_behavior) const
AXPositionInstance CreatePreviousLeafTextPosition() const
bool IsTextPosition() const
AXPositionInstance CreatePreviousFormatStartPosition(AXBoundaryBehavior boundary_behavior) const
virtual std::vector< int32_t > GetWordStartOffsets() const =0
virtual AXNodeTextStyles GetTextStyles() const =0
AXNodeType * GetAnchor() const
AXPositionInstance CreateNextPageEndPosition(AXBoundaryBehavior boundary_behavior) const
void SnapToMaxTextOffsetIfBeyond()
int AnchorTextOffsetInParent() const
bool IsNullPosition() const
virtual int AnchorSiblingCount() const =0
virtual bool IsInLineBreakingObject() const =0
std::string ToString() const
AXBoundaryType GetFormatEndBoundaryType() const
virtual int32_t GetPreviousOnLineID(int32_t node_id) const =0
static AXPositionInstance CreateTreePosition(AXTreeID tree_id, AXNode::AXID anchor_id, int child_index)
virtual std::stack< AXNodeType * > GetAncestorAnchors() const =0
AXPositionInstance CreateNextLeafTreePosition() const
static const int BEFORE_TEXT
ax::mojom::TextAffinity affinity() const
virtual AXPositionInstance Clone() const =0
AXPositionInstance CreatePreviousWordStartPosition(AXBoundaryBehavior boundary_behavior) const
AXPositionInstance CreateParentPosition(ax::mojom::MoveDirection move_direction=ax::mojom::MoveDirection::kForward) const
virtual ax::mojom::Role GetAnchorRole() const =0
AXPositionInstance CreatePositionAtEndOfDocument() const
AXPositionInstance AsUnignoredPosition(AXPositionAdjustmentBehavior adjustment_behavior) const
static const int INVALID_INDEX
bool AtStartOfInlineBlock() const
AXPositionInstance CreateNextParagraphStartPosition(AXBoundaryBehavior boundary_behavior) const
bool AtEndOfAnchor() const
AXBoundaryType GetFormatStartBoundaryType() const
virtual bool IsInWhiteSpace() const =0
bool IsEmptyObjectReplacedByCharacter() const
AXPositionInstance CreatePositionAtStartOfDocument() const
virtual std::vector< int32_t > GetWordEndOffsets() const =0
static AXPositionInstance CreateTextPosition(AXTreeID tree_id, AXNode::AXID anchor_id, int text_offset, ax::mojom::TextAffinity affinity)
virtual int32_t GetAnchorID(AXNodeType *node) const =0
AXPositionInstance CreatePreviousParagraphStartPosition(AXBoundaryBehavior boundary_behavior) const
bool BoundaryConditionPredicate(const AXPositionInstance &)
static AXTreeID FromString(const std::string &string)
std::string ToString() const
std::string UTF16ToUTF8(std::u16string src)
bool Contains(const Container &container, const Value &value)
std::string NumberToString(int32_t number)
SIN Vec< N, float > abs(const Vec< N, float > &x)
AXPositionAdjustmentBehavior
bool operator==(const AXEventIntent &a, const AXEventIntent &b)
bool operator>=(const AXPosition< AXPositionType, AXNodeType > &first, const AXPosition< AXPositionType, AXNodeType > &second)
const char * ToString(ax::mojom::Event event)
const AXTreeID & AXTreeIDUnknown()
void swap(AXPosition< AXPositionType, AXNodeType > &first, AXPosition< AXPositionType, AXNodeType > &second)
bool IsIframe(ax::mojom::Role role)
std::ostream & operator<<(std::ostream &os, AXEventGenerator::Event event)
AXEmbeddedObjectBehavior g_ax_embedded_object_behavior
@ StopIfAlreadyAtBoundary
@ StopAtLastAnchorBoundary
bool operator!=(const AXEventIntent &a, const AXEventIntent &b)
bool IsFormatBoundary(const ax::mojom::Role role)
bool operator<=(const AXPosition< AXPositionType, AXNodeType > &first, const AXPosition< AXPositionType, AXNodeType > &second)
bool operator>(const AXPosition< AXPositionType, AXNodeType > &first, const AXPosition< AXPositionType, AXNodeType > &second)
bool IsDocument(const ax::mojom::Role role)
bool operator<(const AXPosition< AXPositionType, AXNodeType > &first, const AXPosition< AXPositionType, AXNodeType > &second)
ax::mojom::TextAffinity affinity
#define BASE_DCHECK(condition)
#define BASE_UNREACHABLE()