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

Unified Diff: ui/accessibility/ax_position.h

Issue 2806773002: Switched to using |AXPosition| for calculating word and line boundaries on Windows. (Closed)
Patch Set: Fixed line boundaries. Created 3 years, 8 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: ui/accessibility/ax_position.h
diff --git a/ui/accessibility/ax_position.h b/ui/accessibility/ax_position.h
index bbce7f3a8d7b2483378ed65e63f6741f46e424a3..bd45c3e3c1330cb497b73ef8d760832bd43506f1 100644
--- a/ui/accessibility/ax_position.h
+++ b/ui/accessibility/ax_position.h
@@ -131,6 +131,7 @@ class AXPosition {
str = "TreePosition tree_id=" + base::IntToString(tree_id_) +
" anchor_id=" + base::IntToString(anchor_id_) + " child_index=" +
str_child_index;
+ break;
}
case AXPositionKind::TEXT_POSITION: {
std::string str_text_offset;
@@ -143,6 +144,7 @@ class AXPosition {
" anchor_id=" + base::IntToString(anchor_id_) + " text_offset=" +
str_text_offset + " affinity=" +
ui::ToString(static_cast<AXTextAffinity>(affinity_));
+ break;
}
}
@@ -225,6 +227,80 @@ class AXPosition {
return false;
}
+ bool AtStartOfWord() const {
+ AXPositionInstance text_position = AsLeafTextPosition();
+ switch (text_position->kind_) {
+ case AXPositionKind::NULL_POSITION:
+ return false;
+ case AXPositionKind::TREE_POSITION:
+ NOTREACHED();
+ return false;
+ case AXPositionKind::TEXT_POSITION: {
+ const std::vector<int32_t> word_starts =
+ text_position->GetWordStartOffsets();
+ auto iterator =
+ std::find(word_starts.begin(), word_starts.end(),
+ static_cast<int32_t>(text_position->text_offset_));
+ return iterator != word_starts.end();
+ }
+ }
+ return false;
+ }
+
+ bool AtEndOfWord() const {
+ AXPositionInstance text_position = AsLeafTextPosition();
+ switch (text_position->kind_) {
+ case AXPositionKind::NULL_POSITION:
+ return false;
+ case AXPositionKind::TREE_POSITION:
+ NOTREACHED();
+ return false;
+ case AXPositionKind::TEXT_POSITION: {
+ const std::vector<int32_t> word_ends =
+ text_position->GetWordEndOffsets();
+ auto iterator =
+ std::find(word_ends.begin(), word_ends.end(),
+ static_cast<int32_t>(text_position->text_offset_));
+ return iterator != word_ends.end();
+ }
+ }
+ return false;
+ }
+
+ bool AtStartOfLine() const {
+ AXPositionInstance text_position = AsLeafTextPosition();
+ switch (text_position->kind_) {
+ case AXPositionKind::NULL_POSITION:
+ return false;
+ case AXPositionKind::TREE_POSITION:
+ NOTREACHED();
+ return false;
+ case AXPositionKind::TEXT_POSITION:
+ return !text_position->IsInLineBreak() &&
+ GetPreviousOnLineID(text_position->anchor_id_) ==
+ INVALID_ANCHOR_ID &&
+ text_position->AtStartOfAnchor();
+ }
+ return false;
+ }
+
+ bool AtEndOfLine() const {
+ AXPositionInstance text_position = AsLeafTextPosition();
+ switch (text_position->kind_) {
+ case AXPositionKind::NULL_POSITION:
+ return false;
+ case AXPositionKind::TREE_POSITION:
+ NOTREACHED();
+ return false;
+ case AXPositionKind::TEXT_POSITION:
+ return !text_position->IsInLineBreak() &&
+ GetNextOnLineID(text_position->anchor_id_) ==
+ INVALID_ANCHOR_ID &&
+ text_position->AtEndOfAnchor();
+ }
+ return false;
+ }
+
// This method returns a position instead of a node because this allows us to
// return the corresponding text offset or child index in the ancestor that
// relates to the current position.
@@ -449,20 +525,28 @@ class AXPosition {
if (tree_id == INVALID_TREE_ID || parent_id == INVALID_ANCHOR_ID)
return CreateNullPosition();
- DCHECK_NE(tree_id, INVALID_TREE_ID);
- DCHECK_NE(parent_id, INVALID_ANCHOR_ID);
switch (kind_) {
case AXPositionKind::NULL_POSITION:
NOTREACHED();
return CreateNullPosition();
case AXPositionKind::TREE_POSITION:
return CreateTreePosition(tree_id, parent_id, AnchorIndexInParent());
- case AXPositionKind::TEXT_POSITION:
- // Make sure that our affinity is propagated to our parent because by
- // design our parent includes all our text.
- return CreateTextPosition(tree_id, parent_id,
- AnchorTextOffsetInParent() + text_offset_,
- affinity_);
+ case AXPositionKind::TEXT_POSITION: {
+ // If our parent contains all our text, we need to maintain the affinity
+ // and the text offset. Otherwise, we return a position that is either
+ // before or after the child and we don't maintain the affinity when the
+ // position is after the child.
+ int parent_offset = AnchorTextOffsetInParent();
+ AXTextAffinity parent_affinity = affinity_;
+ if (MaxTextOffset() == MaxTextOffsetInParent()) {
+ parent_offset += text_offset_;
+ } else if (text_offset_ > 0) {
+ parent_offset += MaxTextOffsetInParent();
+ parent_affinity = AX_TEXT_AFFINITY_DOWNSTREAM;
+ }
+ return CreateTextPosition(tree_id, parent_id, parent_offset,
+ parent_affinity);
+ }
}
return CreateNullPosition();
@@ -548,22 +632,13 @@ class AXPosition {
if (text_position->IsNullPosition())
return text_position;
- // Ignore any nodes with no text or no word boundaries.
- while (!text_position->IsNullPosition() &&
- (!text_position->MaxTextOffset() ||
- text_position->GetWordStartOffsets().empty())) {
- text_position = text_position->CreateNextTextAnchorPosition();
- }
-
- if (text_position->IsNullPosition())
- return text_position;
-
const std::vector<int32_t> word_starts =
text_position->GetWordStartOffsets();
auto iterator =
std::upper_bound(word_starts.begin(), word_starts.end(),
static_cast<int32_t>(text_position->text_offset_));
if (iterator == word_starts.end()) {
+ // Ignore any nodes with no text or no word boundaries.
do {
text_position = text_position->CreateNextTextAnchorPosition();
} while (!text_position->IsNullPosition() &&
@@ -572,10 +647,9 @@ class AXPosition {
if (text_position->IsNullPosition())
return text_position;
- // In case there are some non-word characters in front of the first word
- // in this text node.
const std::vector<int32_t> word_starts =
text_position->GetWordStartOffsets();
+ DCHECK(!word_starts.empty());
text_position->text_offset_ = static_cast<int>(word_starts[0]);
} else {
text_position->text_offset_ = static_cast<int>(*iterator);
@@ -589,7 +663,7 @@ class AXPosition {
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
if (GetAnchor() == common_ancestor->GetAnchor())
- return common_ancestor;
+ text_position = std::move(common_ancestor);
if (was_tree_position)
text_position = text_position->AsTreePosition();
@@ -599,22 +673,11 @@ class AXPosition {
AXPositionInstance CreatePreviousWordStartPosition() const {
bool was_tree_position = IsTreePosition();
AXPositionInstance text_position = AsLeafTextPosition();
- if (text_position->IsNullPosition())
- return text_position;
if (text_position->AtStartOfAnchor()) {
text_position = text_position->CreatePreviousTextAnchorPosition();
text_position = text_position->CreatePositionAtEndOfAnchor();
}
-
- // Ignore any nodes with no text or no word boundaries.
- while (!text_position->IsNullPosition() &&
- (!text_position->MaxTextOffset() ||
- text_position->GetWordStartOffsets().empty())) {
- text_position = text_position->CreatePreviousTextAnchorPosition();
- text_position = text_position->CreatePositionAtEndOfAnchor();
- }
-
if (text_position->IsNullPosition())
return text_position;
@@ -623,9 +686,8 @@ class AXPosition {
auto iterator =
std::lower_bound(word_starts.begin(), word_starts.end(),
static_cast<int32_t>(text_position->text_offset_));
- if (iterator == word_starts.begin()) {
- // There must be some non-word characters in front of the first word in
- // this text node.
+ if (word_starts.empty() || iterator == word_starts.begin()) {
+ // Ignore any nodes with no text or no word boundaries.
do {
text_position = text_position->CreatePreviousTextAnchorPosition();
} while (!text_position->IsNullPosition() &&
@@ -636,6 +698,7 @@ class AXPosition {
const std::vector<int32_t> word_starts =
text_position->GetWordStartOffsets();
+ DCHECK(!word_starts.empty());
text_position->text_offset_ = static_cast<int>(*(word_starts.end() - 1));
} else {
text_position->text_offset_ = static_cast<int>(*(--iterator));
@@ -649,7 +712,7 @@ class AXPosition {
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
if (GetAnchor() == common_ancestor->GetAnchor())
- return common_ancestor;
+ text_position = std::move(common_ancestor);
if (was_tree_position)
text_position = text_position->AsTreePosition();
@@ -660,27 +723,18 @@ class AXPosition {
AXPositionInstance CreateNextWordEndPosition() const {
bool was_tree_position = IsTreePosition();
AXPositionInstance text_position = AsLeafTextPosition();
- if (text_position->IsNullPosition())
- return text_position;
if (text_position->AtEndOfAnchor())
text_position = text_position->CreateNextTextAnchorPosition();
-
- // Ignore any nodes with no text or no word boundaries.
- while (!text_position->IsNullPosition() &&
- (!text_position->MaxTextOffset() ||
- text_position->GetWordEndOffsets().empty())) {
- text_position = text_position->CreateNextTextAnchorPosition();
- }
-
if (text_position->IsNullPosition())
return text_position;
- const std::vector<int> word_ends = text_position->GetWordEndOffsets();
- auto iterator = std::upper_bound(word_ends.begin(), word_ends.end(),
- text_position->text_offset_);
+ const std::vector<int32_t> word_ends = text_position->GetWordEndOffsets();
+ auto iterator =
+ std::upper_bound(word_ends.begin(), word_ends.end(),
+ static_cast<int32_t>(text_position->text_offset_));
if (iterator == word_ends.end()) {
- // We should be in the last word of this text node.
+ // Ignore any nodes with no text or no word boundaries.
do {
text_position = text_position->CreateNextTextAnchorPosition();
} while (!text_position->IsNullPosition() &&
@@ -689,10 +743,11 @@ class AXPosition {
if (text_position->IsNullPosition())
return text_position;
- const std::vector<int> word_ends = text_position->GetWordEndOffsets();
- text_position->text_offset_ = word_ends[0];
+ const std::vector<int32_t> word_ends = text_position->GetWordEndOffsets();
+ DCHECK(!word_ends.empty());
+ text_position->text_offset_ = static_cast<int>(word_ends[0]);
} else {
- text_position->text_offset_ = *iterator;
+ text_position->text_offset_ = static_cast<int>(*iterator);
text_position->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM;
}
@@ -703,7 +758,7 @@ class AXPosition {
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
if (GetAnchor() == common_ancestor->GetAnchor())
- return common_ancestor;
+ text_position = std::move(common_ancestor);
if (was_tree_position)
text_position = text_position->AsTreePosition();
@@ -714,21 +769,11 @@ class AXPosition {
AXPositionInstance CreatePreviousWordEndPosition() const {
bool was_tree_position = IsTreePosition();
AXPositionInstance text_position = AsLeafTextPosition();
- if (text_position->IsNullPosition())
- return text_position;
if (text_position->AtStartOfAnchor()) {
text_position = text_position->CreatePreviousTextAnchorPosition();
text_position = text_position->CreatePositionAtEndOfAnchor();
}
-
- // Ignore any nodes with no text or no word boundaries.
- while (!text_position->IsNullPosition() &&
- (!text_position->MaxTextOffset() ||
- text_position->GetWordStartOffsets().empty())) {
- text_position = text_position->CreatePreviousTextAnchorPosition();
- }
-
if (text_position->IsNullPosition())
return text_position;
@@ -736,9 +781,8 @@ class AXPosition {
auto iterator =
std::lower_bound(word_ends.begin(), word_ends.end(),
static_cast<int32_t>(text_position->text_offset_));
- if (iterator == word_ends.begin()) {
- // We must be anywhere up to and including the end of the first word in
- // this node.
+ if (word_ends.empty() || iterator == word_ends.begin()) {
+ // Ignore any nodes with no text or no word boundaries.
do {
text_position = text_position->CreatePreviousTextAnchorPosition();
} while (!text_position->IsNullPosition() &&
@@ -748,6 +792,7 @@ class AXPosition {
return text_position;
const std::vector<int32_t> word_ends = text_position->GetWordEndOffsets();
+ DCHECK(!word_ends.empty());
text_position->text_offset_ = static_cast<int>(*(word_ends.end() - 1));
} else {
text_position->text_offset_ = static_cast<int>(*(--iterator));
@@ -761,7 +806,7 @@ class AXPosition {
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
if (GetAnchor() == common_ancestor->GetAnchor())
- return common_ancestor;
+ text_position = std::move(common_ancestor);
if (was_tree_position)
text_position = text_position->AsTreePosition();
@@ -783,6 +828,9 @@ class AXPosition {
AX_TEXT_AFFINITY_DOWNSTREAM);
text_position =
text_position->AsLeafTextPosition()->CreateNextTextAnchorPosition();
+ while (text_position->IsInLineBreak()) {
+ text_position = text_position->CreateNextTextAnchorPosition();
+ }
dmazzoni 2017/04/10 22:39:49 nit: no brackets needed here?
if (text_position->IsNullPosition())
return text_position;
@@ -793,7 +841,7 @@ class AXPosition {
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
if (GetAnchor() == common_ancestor->GetAnchor())
- return common_ancestor;
+ text_position = std::move(common_ancestor);
if (was_tree_position)
text_position = text_position->AsTreePosition();
@@ -803,7 +851,7 @@ class AXPosition {
AXPositionInstance CreatePreviousLineStartPosition() const {
bool was_tree_position = IsTreePosition();
AXPositionInstance text_position = AsLeafTextPosition();
- if (text_position->AtStartOfAnchor())
+ if (text_position->IsInLineBreak() || text_position->AtStartOfAnchor())
text_position = text_position->CreatePreviousTextAnchorPosition();
if (text_position->IsNullPosition())
return text_position;
@@ -825,7 +873,7 @@ class AXPosition {
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
if (GetAnchor() == common_ancestor->GetAnchor())
- return common_ancestor;
+ text_position = std::move(common_ancestor);
if (was_tree_position)
text_position = text_position->AsTreePosition();
@@ -866,7 +914,7 @@ class AXPosition {
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
if (GetAnchor() == common_ancestor->GetAnchor())
- return common_ancestor;
+ text_position = std::move(common_ancestor);
if (was_tree_position)
text_position = text_position->AsTreePosition();
@@ -903,7 +951,7 @@ class AXPosition {
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
if (GetAnchor() == common_ancestor->GetAnchor())
- return common_ancestor;
+ text_position = std::move(common_ancestor);
if (was_tree_position)
text_position = text_position->AsTreePosition();

Powered by Google App Engine
This is Rietveld 408576698