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

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: Added overrides for parent and childAtIndex for BrowserAccessibility. 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,
12 int32_t anchor_id,
13 int child_index,
14 int text_offset,
15 AXPositionType type)
16 : tree_id_(tree_id),
17 anchor_id_(anchor_id),
18 child_index_(child_index),
19 text_offset_(text_offset),
20 type_(type) {
21 if (GetAnchor() && child_index_ >= 0 || child_index_ >= AnchorChildCount() ||
22 text_offset_ >= 0 || text_offset_ <= MaxTextOffset()) {
23 return;
24 }
25
26 // Reset to the null position.
27 tree_id_ = -1;
28 anchor_id_ = -1;
29 child_index_ = -1;
30 text_offset_ = -1;
31 type_ = AXPositionType::NullPosition;
32 }
33
34 AXPosition::~AXPosition() {}
35
36 // static
37 AXNodeType::AXPosition* AXPosition::CreateNullPosition() {
38 return new AXNodeType::AXPosition(-1 /* tree_id */, -1 /* anchor_id */,
39 -1 /* child_index */, -1 /* text_offset */,
40 ui::AXPositionType::NullPosition);
41 }
42
43 // static
44 AXNodeType::AXPosition* AXPosition::CreateTreePosition(int tree_id,
45 int32_t anchor_id,
46 int child_index) {
47 return new AXNodeType::AXPosition(tree_id, anchor_id, child_index,
48 -1 /* text_offset */,
49 ui::AXPositionType::TreePosition);
50 }
51
52 // static
53 AXNodeType::AXPosition* AXPosition::CreateTextPosition(int tree_id,
54 int32_t anchor_id,
55 int text_offset) {
56 return new AXNodeType::AXPosition(tree_id, anchor_id, -1 /* child_index */,
57 text_offset,
58 ui::AXPositionType::TextPosition);
59 }
60
61 AXNodeType* AXPosition::GetAnchor() const {
62 if (tree_id_ == -1 || anchor_id_ == -1)
63 return nullptr;
64 DCHECK_GE(tree_id_, 0);
65 DCHECK_GE(anchor_id_, 0);
66 return GetNodeInTree(tree_id_, anchor_id_);
67 }
68
69 bool AXPosition::AtStartOfAnchor() const {
70 if (!GetAnchor())
71 return false;
72
73 switch (type_) {
74 case AXPositionType::NullPosition:
75 return false;
76 case AXPositionType::TreePosition:
77 return child_index_ == 0;
78 case AXPositionType::TextPosition:
79 return text_offset_ == 0;
80 }
81 }
82
83 bool AXPosition::AtEndOfAnchor() const {
84 if (!GetAnchor())
85 return false;
86
87 switch (type_) {
88 case AXPositionType::NullPosition:
89 return false;
90 case AXPositionType::TreePosition:
91 return child_index_ == AnchorChildCount();
92 case AXPositionType::TextPosition:
93 return text_offset_ == MaxTextOffset();
94 }
95 }
96
97 AXPosition* AXPosition::CommonAncestor(const AXPosition& second) const {
98 std::queue<AXPosition*> ancestors1;
99 ancestors1.push(this);
100 while (!ancestors1.back() || !ancestors1.back()->IsNullPosition())
101 ancestors1.push(ancestors1.back()->GetParentPosition());
102 ancestors1.pop();
103 if (ancestors1.empty())
104 return CreateNullPosition();
105
106 std::queue<AXPosition> ancestors2;
107 ancestors2.push(&second);
108 while (!ancestors2.back() || !ancestors2.back()->IsNullPosition())
109 ancestors2.push(ancestors2.back()->GetParentPosition());
110 ancestors2.pop();
111 if (ancestors2.empty())
112 return CreateNullPosition();
113
114 AXPosition* commonAncestor = CreateNullPosition();
115 do {
116 if (*ancestors1.front() == *ancestors2.front()) {
117 commonAncestor = ancestors1.front();
118 ancestors1.pop();
119 ancestors2.pop();
120 } else {
121 break;
122 }
123 } while (!ancestors1.empty() && !ancestors2.empty());
124 return commonAncestor;
125 }
126
127 bool AXPosition::operator<(const AXPosition& position) const {
128 if (IsNullPosition() || position.IsNullPosition())
129 return false;
130
131 AXPosition* other = &position;
132 do {
133 other = other->GetPreviousAnchorPosition();
134 if (other->IsNullPosition())
135 return false;
136 } while (*this != *other);
137 return true;
138 }
139
140 bool AXPosition::operator<=(const AXPosition& position) const {
141 if (IsNullPosition() || position.IsNullPosition())
142 return false;
143 return *this == position || *this < position;
144 }
145
146 bool AXPosition::operator>(const AXPosition& position) const {
147 if (IsNullPosition() || position.IsNullPosition())
148 return false;
149
150 AXPosition* other = &position;
151 do {
152 other = other->GetNextAnchorPosition();
153 if (other->IsNullPosition())
154 return false;
155 } while (*this != *other);
156 return true;
157 }
158
159 bool AXPosition::operator>=(const AXPosition& position) const {
160 if (IsNullPosition() || position.IsNullPosition())
161 return false;
162 return *this == position || *this > position;
163 }
164
165 AXPosition* AXPosition::GetPositionAtStartOfAnchor() const {
166 switch (type_) {
167 case AXPositionType::NullPosition:
168 return CreateNullPosition();
169 case AXPositionType::TreePosition:
170 return CreateTreePosition(tree_id_, anchor_id_, 0 /* child_index */);
171 case AXPositionType::TextPosition:
172 return CreateTextPosition(tree_id_, anchor_id_, 0 /* text_offset */);
173 }
174 }
175
176 AXPosition* AXPosition::GetPositionAtEndOfAnchor() const {
177 switch (type_) {
178 case AXPositionType::NullPosition:
179 return CreateNullPosition();
180 case AXPositionType::TreePosition:
181 return CreateTreePosition(tree_id_, anchor_id_, AnchorChildCount());
182 case AXPositionType::TextPosition:
183 return CreateTextPosition(tree_id_, anchor_id_, MaxTextOffset());
184 }
185 }
186
187 // Not yet implemented for tree positions.
188 AXPosition* AXPosition::GetNextCharacterPosition() const {
189 if (IsNullPosition())
190 return CreateNullPosition();
191
192 if (text_offset_ + 1 < MaxTextOffset())
193 return CreateTextPosition(tree_id_, anchor_id_, text_offset_ + 1);
194
195 AXPosition* next_leaf = GetNextAnchorPosition();
196 while (next_leaf && next_leaf->AnchorChildCount())
197 next_leaf = next_leaf->GetNextAnchorPosition();
198 return next_leaf;
199 }
200
201 // Not yet implemented for tree positions.
202 AXPosition* AXPosition::GetPreviousCharacterPosition() const {
203 if (IsNullPosition())
204 return CreateNullPosition();
205
206 if (text_offset_ > 0)
207 return CreateTextPosition(tree_id_, anchor_id_, text_offset_ - 1);
208
209 AXPosition* previous_leaf = GetPreviousAnchorPosition();
210 while (previous_leaf && previous_leaf->AnchorChildCount())
211 previous_leaf = previous_leaf->GetNextAnchorPosition();
212 return previous_leaf;
213 }
214
215 AXPosition* AXPosition::GetNextAnchorPosition() const {
216 if (IsNullPosition())
217 return CreateNullPosition();
218
219 if (AnchorChildCount())
220 return GetChildPositionAt(0);
221
222 AXPosition* current_position = this;
223 AXPosition* parent_position = GetParentPosition();
224 while (parent_position && !parent_position->IsNullPosition()) {
225 // Get the next sibling if it exists, otherwise move up to the parent's next
226 // sibling.
227 int index_in_parent = current_position->AnchorIndexInParent();
228 if (index_in_parent < parent_position->AnchorChildCount() - 1) {
229 AXPosition* next_sibling =
230 parent_position->GetChildPositionAt(index_in_parent + 1);
231 DCHECK(next_sibling && !next_sibling.IsNullPosition());
232 return next_sibling;
233 }
234
235 current_position = parent_position;
236 parent_position = current_position->GetParentPosition();
237 }
238
239 return CreateNullPosition();
240 }
241
242 AXPosition* AXPosition::GetPreviousAnchorPosition() const {
243 if (IsNullPosition())
244 return CreateNullPosition();
245
246 AXPosition* parent_position = GetParentPosition();
247 if (!parent_position || parent_position.IsNullPosition())
248 return CreateNullPosition();
249
250 // Get the previous sibling's deepest first child if a previous sibling
251 // exists, otherwise move up to the parent.
252 int index_in_parent = AnchorIndexInParent();
253 if (index_in_parent <= 0)
254 return parent_position;
255
256 AXPosition* leaf = parent_position->GetChildPositionAt(index_in_parent - 1);
257 while (leaf && !leaf->IsNullPosition() && leaf->AnchorChildCount())
258 leaf->GetChildPositionAt(0);
259
260 return leaf;
261 }
262
263 bool operator==(const AXPosition& first, const AXPosition& second) {
264 if (first.IsNullPosition() && second.IsNullPosition())
265 return true;
266 return first == second;
267 }
268
269 bool operator!=(const AXPosition& first, const AXPosition& second) {
270 return !operator==(first, second);
271 }
272
273 AXNodePosition::AXNodePosition(int tree_id,
274 int32_t anchor_id,
275 int child_index,
276 int text_offset,
277 AXPositionType type)
278 : AXPosition(tree_id, anchor_id, child_index, text_offset, type) {}
279
280 AXNodePosition::~AXNodePosition() {}
281
282 AXPosition* AXNodePosition::GetChildPositionAt(int child_index) const {
283 if (IsNullPosition())
284 return CreateNullPosition();
285
286 if (child_index < 0 || child_index >= AnchorChildCount())
287 return CreateNullPosition();
288
289 AXNodeType* child_anchor = GetAnchor()->ChildAtIndex(child_index);
290 DCHECK(child_anchor);
291 switch (type_) {
292 case AXPositionType::NullPosition:
293 NOTREACHED();
294 return CreateNullPosition();
295 case AXPositionType::TreePosition:
296 return CreateTreePosition(tree_id_, child_anchor->id(),
297 0 /* child_index */);
298 case AXPositionType::TextPosition:
299 return CreateTextPosition(tree_id_, child_anchor->id(),
300 0 /* text_offset */);
301 }
302 }
303
304 AXPosition* AXNodePosition::GetParentPosition() const {
305 if (IsNullPosition())
306 return CreateNullPosition();
307
308 AXNodeType* parent_anchor = GetAnchor()->parent();
309 if (!parent_anchor)
310 return CreateNullPosition();
311
312 switch (type_) {
313 case AXPositionType::NullPosition:
314 NOTREACHED();
315 return CreateNullPosition();
316 case AXPositionType::TreePosition:
317 return CreateTreePosition(tree_id_, parent_anchor->id(),
318 0 /* child_index */);
319 case AXPositionType::TextPosition:
320 return CreateTextPosition(tree_id_, parent_anchor->id(),
321 0 /* text_offset */);
322 }
323 }
324
325 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698