Chromium Code Reviews| 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 |