OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef UI_ACCESSIBILITY_AX_POSITION_H_ | 5 #ifndef UI_ACCESSIBILITY_AX_POSITION_H_ |
6 #define UI_ACCESSIBILITY_AX_POSITION_H_ | 6 #define UI_ACCESSIBILITY_AX_POSITION_H_ |
7 | 7 |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
269 | 269 |
270 bool AtStartOfLine() const { | 270 bool AtStartOfLine() const { |
271 AXPositionInstance text_position = AsLeafTextPosition(); | 271 AXPositionInstance text_position = AsLeafTextPosition(); |
272 switch (text_position->kind_) { | 272 switch (text_position->kind_) { |
273 case AXPositionKind::NULL_POSITION: | 273 case AXPositionKind::NULL_POSITION: |
274 return false; | 274 return false; |
275 case AXPositionKind::TREE_POSITION: | 275 case AXPositionKind::TREE_POSITION: |
276 NOTREACHED(); | 276 NOTREACHED(); |
277 return false; | 277 return false; |
278 case AXPositionKind::TEXT_POSITION: | 278 case AXPositionKind::TEXT_POSITION: |
279 return !text_position->IsInLineBreak() && | 279 // Special case, when the caret is right after a line break and the next |
280 GetPreviousOnLineID(text_position->anchor_id_) == | 280 // position is not another line break. We should return |true| because |
281 // visually the caret is at the beginning of a new line. | |
282 if (text_position->IsInLineBreak()) { | |
283 return text_position->AtEndOfAnchor() && | |
284 !text_position->CreateNextTextAnchorPosition() | |
285 ->IsInLineBreak(); | |
286 } | |
287 return GetPreviousOnLineID(text_position->anchor_id_) == | |
281 INVALID_ANCHOR_ID && | 288 INVALID_ANCHOR_ID && |
282 text_position->AtStartOfAnchor(); | 289 text_position->AtStartOfAnchor(); |
283 } | 290 } |
284 return false; | 291 return false; |
285 } | 292 } |
286 | 293 |
287 bool AtEndOfLine() const { | 294 bool AtEndOfLine() const { |
288 AXPositionInstance text_position = AsLeafTextPosition(); | 295 AXPositionInstance text_position = AsLeafTextPosition(); |
289 switch (text_position->kind_) { | 296 switch (text_position->kind_) { |
290 case AXPositionKind::NULL_POSITION: | 297 case AXPositionKind::NULL_POSITION: |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
578 } | 585 } |
579 | 586 |
580 // The following methods work across anchors. | 587 // The following methods work across anchors. |
581 | 588 |
582 AXPositionInstance CreateNextCharacterPosition() const { | 589 AXPositionInstance CreateNextCharacterPosition() const { |
583 bool was_tree_position = IsTreePosition(); | 590 bool was_tree_position = IsTreePosition(); |
584 AXPositionInstance text_position = AsTextPosition(); | 591 AXPositionInstance text_position = AsTextPosition(); |
585 if (text_position->IsNullPosition()) | 592 if (text_position->IsNullPosition()) |
586 return text_position; | 593 return text_position; |
587 | 594 |
588 if ((text_position->text_offset_ + 1) < text_position->MaxTextOffset()) { | 595 if ((text_position->text_offset_ + 1) < text_position->MaxTextOffset()) { |
dmazzoni
2017/05/25 21:28:41
David noticed that this +1 isn't safe because the
| |
589 text_position->text_offset_ += 1; | 596 text_position->text_offset_ += 1; |
590 // Even if our affinity was upstream, moving to the next character should | 597 // Even if our affinity was upstream, moving to the next character should |
591 // inevitably reset it to downstream. | 598 // inevitably reset it to downstream. |
592 text_position->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM; | 599 text_position->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM; |
593 } else { | 600 } else { |
594 // Moving to the end of the current anchor first is essential. Otherwise | 601 // Moving to the end of the current anchor first is essential. Otherwise |
595 // |CreateNextAnchorPosition| might return our deepest left-most child | 602 // |CreateNextAnchorPosition| might return our deepest left-most child |
596 // because we are using pre-order traversal. | 603 // because we are using pre-order traversal. |
597 text_position = text_position->CreatePositionAtEndOfAnchor(); | 604 text_position = text_position->CreatePositionAtEndOfAnchor(); |
598 text_position = text_position->CreateNextTextAnchorPosition(); | 605 text_position = text_position->CreateNextTextAnchorPosition(); |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1186 | 1193 |
1187 template <class AXPositionType, class AXNodeType> | 1194 template <class AXPositionType, class AXNodeType> |
1188 bool operator>=(const AXPosition<AXPositionType, AXNodeType>& first, | 1195 bool operator>=(const AXPosition<AXPositionType, AXNodeType>& first, |
1189 const AXPosition<AXPositionType, AXNodeType>& second) { | 1196 const AXPosition<AXPositionType, AXNodeType>& second) { |
1190 return first == second || first > second; | 1197 return first == second || first > second; |
1191 } | 1198 } |
1192 | 1199 |
1193 } // namespace ui | 1200 } // namespace ui |
1194 | 1201 |
1195 #endif // UI_ACCESSIBILITY_AX_POSITION_H_ | 1202 #endif // UI_ACCESSIBILITY_AX_POSITION_H_ |
OLD | NEW |