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

Side by Side Diff: ui/accessibility/ax_position.cc

Issue 2271893002: Creates AXPosition to uniquely identify a position in the accessibility tree (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Re-wrote implementation to include tree_id and platform specific AXPosition. Created 4 years, 2 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 unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "ui/accessibility/ax_position.h"
6
7 #include <queue>
8
9 namespace ui {
10
11 AXPosition::AXPosition(int tree_id, int32_t anchor_id, int child_index, int text _offset, AXPositionType type) : tree_id_(tree_id), anchor_id_(anchor_id), child_ index_(child_index), text_offset_(text_offset), type_(type) {
12 if (!GetAnchor() || child_index_ < 0 || child_index_ > AnchorChildCount() || t ext_offset_ < 0 || text_offset_ > MaxTextOffset()) {
13 // Reset to the null position.
14 tree_id_ = -1;
15 anchor_id_ = -1;
16 child_index_ = -1;
17 text_offset_ = -1;
18 type_ = AXPositionType::TreePosition;
19 }
20 }
21
22 AXPosition::~AXPosition() {
23 }
24
25 AXPosition AXPosition::CreateNullPosition() {
26 return AXPosition(-1 /* tree_id */, -1 /* anchor_id */, -1 /* child_index */, -1 /* text_offset */, AXPositionType::TreePosition);
27 }
28
29 AXPosition AXPosition::CreateTreePosition(int tree_id, int32_t anchor_id, int ch ild_index) {
30 return AXPosition(tree_id, anchor_id, child_index, -1 /* text_offset */, AXPos itionType::TreePosition);
31 }
32
33 AXPosition AXPosition::CreateTextPosition(int tree_id, int32_t anchor_id, int te xt_offset) {
34 return AXPosition(tree_id, anchor_id, -1 /* child_index */, text_offset, AXPos itionType::TextPosition);
35 }
36
37 AXNode* AXPosition::GetAnchor() const {
38 if (tree_id_ == -1 || anchor_id_ == -1)
39 return nullptr;
40 DCHECK_GE(tree_id_, 0);
41 DCHECK_GE(anchor_id_, 0);
42 return GetNodeFromTree(tree_id_, anchor_id_);
43 }
44
45 // static
46 AXPosition AXPosition::CommonAncestor(const AXPosition& first, const AXPosition& second) {
47 std::queue<AXPosition> ancestors1;
48 ancestors1.push(first);
49 while (!ancestors1.back().IsNullPosition())
50 ancestors1.push(ancestors1.back().GetParentPosition());
51 ancestors1.pop();
52 if (ancestors1.empty())
53 return CreateNullPosition();
54
55 std::queue<AXPosition> ancestors2;
56 ancestors2.push(second);
57 while (!ancestors2.back().IsNullPosition())
58 ancestors2.push(ancestors2.back().GetParentPosition());
59 ancestors2.pop();
60 if (ancestors2.empty())
61 return CreateNullPosition();
62
63 AXPosition commonAncestor = CreateNullPosition();
64 do {
65 if (ancestors1.front() == ancestors2.front()) {
66 commonAncestor = ancestors1.pop(), ancestors2.pop();
67 } else {
68 break;
69 }
70 } while (!ancestors1.empty() && !ancestors2.empty());
71 return commonAncestor;
72 }
73
74 bool AXPosition::AtStartOfAnchor() const {
75 if (IsNullPosition())
76 return false;
77
78 switch (type_) {
79 case AXPositionType::TreePosition:
80 return child_index_ == 0;
81 case AXPositionType:TextPosition:
82 return text_offset_ == 0;
83 }
84 }
85
86 bool AXPosition::AtEndOfAnchor() const {
87 if (IsNullPosition())
88 return false;
89
90 switch (type_) {
91 case AXPositionType::TreePosition:
92 return child_index_ == AnchorChildCount();
93 case AXPositionType:TextPosition:
94 return text_offset_ == MaxTextOffset();
95 }
96 }
97
98 bool AXPosition::operator<(const AXPosition& position) const {
99 if (IsNullPosition() || position.IsNullPosition())
100 return false;
101
102 Position other = position;
103 do {
104 other = other.GetPreviousPosition();
105 if (other.IsNullPosition())
106 return false;
107 } while (*this != position);
108 return true;
109 }
110
111 bool AXPosition::operator<=(const AXPosition& position) const {
112 if (IsNullPosition() || position.IsNullPosition())
113 return false;
114 return *this == position || *this < position;
115 }
116
117 bool AXPosition::operator>(const AXPosition& position) const {
118 if (IsNullPosition() || position.IsNullPosition())
119 return false;
120
121 Position other = position;
122 do {
123 other = other.GetNextPosition();
124 if (other.IsNullPosition())
125 return false;
126 } while (*this != position);
127 return true;
128 }
129
130 bool AXPosition::operator>=(const AXPosition& position) const {
131 if (IsNullPosition() || position.IsNullPosition())
132 return false;
133 return *this == position || *this > position;
134 }
135
136 AXPosition AXPosition::GetPositionAtStartOfAnchor() const {
137 if (IsNullPosition())
138 return CreateNullPosition();
139
140 switch (type_) {
141 case AXPositionType::TreePosition:
142 return CreateTreePosition(tree_id_, anchor_id_, 0 /* child_index */);
143 case AXPositionType:TextPosition:
144 return CreateTextPosition(tree_id_, anchor_id_, 0, /* text_offset */);
145 }
146 }
147
148 AXPosition AXPosition::GetPositionAtEndOfAnchor() const {
149 if (IsNullPosition())
150 return CreateNullPosition();
151
152 switch (type_) {
153 case AXPositionType::TreePosition:
154 return CreateTreePosition(tree_id_, anchor_id_, AnchorChildCount());
155 case AXPositionType:TextPosition:
156 return CreateTextPosition(tree_id_, anchor_id_, MaxTextOffset());
157 }
158 }
159
160 // Not yet implemented for tree positions.
161 AXPosition AXPosition::GetNextCharacterPosition() const {
162 if (IsNullPosition())
163 return CreateNullPosition();
164
165 if (text_offset_ + 1 < MaxTextOffset())
166 return CreateTextPosition(tree_id_, anchor_id_, text_offset_ + 1);
167
168 Position next_leaf = GetNextAnchorPosition();
169 while (next_leaf.AnchorChildCount())
170 next_leaf = next_leaf.GetNextAnchorPosition();
171 return next_leaf;
172 }
173
174 // Not yet implemented for tree positions.
175 AXPosition AXPosition::GetPreviousCharacterPosition() const {
176 if (IsNullPosition())
177 return CreateNullPosition();
178
179 if (text_offset_ > 0)
180 return CreateTextPosition(tree_id_, anchor_id_, text_offset_ - 1);
181
182 Position previous_leaf = GetPreviousAnchorPosition();
183 while (previous_leaf.AnchorChildCount())
184 previous_leaf = previous_leaf.GetNextAnchorPosition();
185 return previous_leaf;
186 }
187
188 AXPosition AXPosition::GetChildPositionAt(int child_index) const {
189 if (IsNullPosition())
190 return CreateNullPosition();
191
192 if (child_index < 0 || child_index >= AnchorChildCount())
193 return CreateNullPosition();
194
195 AXNode* child_anchor = GetAnchor()->ChildAtIndex(child_index);
196 DCHECK(child_anchor);
197 switch (type_) {
198 case AXPositionType::TreePosition:
199 return CreateTreePosition(tree_id_, child_anchor->id());
200 case AXPositionType::TextPosition:
201 return CreateTextPosition(tree_id_, child_anchor->id());
202 }
203 }
204
205 AXPosition AXPosition::GetParentPosition() const {
206 if (IsNullPosition())
207 return CreateNullPosition();
208
209 AXNode* parent_anchor = GetAnchor()->parent();
210 if (!parent_anchor)
211 return CreateNullPosition();
212
213 switch (type_) {
214 case AXPositionType::TreePosition:
215 return CreateTreePosition(tree_id_, parent_anchor->id());
216 case AXPositionType::TextPosition:
217 return CreateTextPosition(tree_id_, parent_anchor->id());
218 }
219 }
220
221 AXPosition AXPosition::GetNextAnchorPosition() const {
222 if (IsNullPosition()
223 return CreateNullPosition();
224
225 if (AnchorChildCount())
226 return GetChildPositionAt(0);
227
228 AXPosition current_position = *this;
229 AXPosition parent_position = GetParentPosition();
230 while (!parent_position.IsNullPosition()) {
231 // Get the next sibling if it exists, otherwise move up to the parent's next sibling.
232 int index_in_parent = current_position.AnchorIndexInParent();
233 if (indexInParent < parentPosition.AnchorChildCount() - 1) {
234 Position next_sibling = parent_position.GetChildPositionAt(index_in_parent + 1);
235 DCHECK(!next_sibling.IsNullPosition());
236 return next_sibling;
237 }
238
239 current_position = parent_position;
240 parent_position = current_position.GetParentPosition();
241 }
242
243 return CreateNullPosition();
244 }
245
246 AXPosition AXPosition::GetPreviousAnchorPosition() const {
247 if (IsNullPosition()
248 return CreateNullPosition();
249
250 AXPosition parent_position = GetParentPosition();
251 if (parent_position.IsNullPosition())
252 return CreateNullPosition();
253
254 // Get the previous sibling's deepest first child if a previous sibling exists , otherwise move up to the parent.
255 int index_in_parent = AnchorIndexInParent();
256 if (index_in_parent <= 0)
257 return parent_position;
258 Position leaf = parent_position.GetChildPositionAt(index_in_parent - 1);
259 while (!leaf.IsNullPosition() && leaf.AnchorChildCount())
260 leaf.GetChildPosition(0);
261
262 return leaf;
263 }
264
265 bool operator==(const AXPosition& first, const AXPosition& second) {
266 if (first.IsNullPosition() && second.IsNullPosition())
267 return true;
268 return first == second;
269 }
270
271 bool operator!=(const AXPosition& first, const AXPosition& second) {
272 return !operator==(first, second);
273 }
274
275 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698