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

Side by Side Diff: ui/accessibility/platform/text_marker_helper_mac.mm

Issue 2940923003: a11y: Move CreateTextMarker[Range] to TextMarkerHelperMac.
Patch Set: the idea. nits, rebase [keep - I linked to this] Created 3 years, 6 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
« no previous file with comments | « ui/accessibility/platform/text_marker_helper_mac.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 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 #import "ui/accessibility/platform/text_marker_helper_mac.h"
6
7 #import <Cocoa/Cocoa.h>
8
9 #import "base/mac/foundation_util.h"
10 #include "base/mac/scoped_cftyperef.h"
11 #include "ui/accessibility/ax_position.h"
12 #include "ui/accessibility/ax_range.h"
13
14 using ui::AXPositionPointer;
15 using ui::AXRangePointer;
16 using ui::AXPositionData;
17
18 extern "C" {
19
20 // The following are private accessibility APIs required for cursor navigation
21 // and text selection. VoiceOver started relying on them in Mac OS X 10.11.
22 AXTextMarkerRef AXTextMarkerCreate(CFAllocatorRef allocator,
23 const UInt8* bytes,
24 CFIndex length);
25
26 AXTextMarkerRangeRef AXTextMarkerRangeCreate(CFAllocatorRef allocator,
27 AXTextMarkerRef start_marker,
28 AXTextMarkerRef end_marker);
29 const UInt8* AXTextMarkerGetBytePtr(AXTextMarkerRef text_marker);
30 size_t AXTextMarkerGetLength(AXTextMarkerRef text_marker);
31 AXTextMarkerRef AXTextMarkerRangeCopyStartMarker(
32 AXTextMarkerRangeRef text_marker_range);
33 AXTextMarkerRef AXTextMarkerRangeCopyEndMarker(
34 AXTextMarkerRangeRef text_marker_range);
35
36 } // extern "C"
37
38 namespace {
39
40 constexpr size_t kDataSize = sizeof(AXPositionData);
41
42 // to call |release| on it to transfer ownership of the position to the text
43 // marker object.
44 id CreateTextMarker(AXPositionPointer position) {
45 AXPositionData data;
46 position->ToData(&data);
47
48 AXTextMarkerRef text_marker = AXTextMarkerCreate(
49 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(&data), kDataSize);
50 return static_cast<id>(
51 base::mac::CFTypeRefToNSObjectAutorelease(text_marker));
52 }
53
54 // |range| is destructed at the end of this method and ownership of its |anchor|
55 // and |focus| are transfered to the marker range object.
56 id CreateTextMarkerRange(AXRangePointer range) {
57 AXPositionData anchor, focus;
58 range.first->ToData(&anchor);
59 range.second->ToData(&focus);
60
61 base::ScopedCFTypeRef<AXTextMarkerRef> start_marker(AXTextMarkerCreate(
62 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(&anchor), kDataSize));
63 base::ScopedCFTypeRef<AXTextMarkerRef> end_marker(AXTextMarkerCreate(
64 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(&focus), kDataSize));
65 AXTextMarkerRangeRef marker_range =
66 AXTextMarkerRangeCreate(kCFAllocatorDefault, start_marker, end_marker);
67 return static_cast<id>(
68 base::mac::CFTypeRefToNSObjectAutorelease(marker_range));
69 }
70
71 bool ExtractData(AXTextMarkerRef text_marker, AXPositionData* data) {
72 DCHECK(text_marker);
73
74 if (AXTextMarkerGetLength(text_marker) != kDataSize)
75 return false;
76
77 const UInt8* source_buffer = AXTextMarkerGetBytePtr(text_marker);
78 if (!source_buffer)
79 return false;
80
81 UInt8* destination_buffer = reinterpret_cast<UInt8*>(data);
82 std::memcpy(destination_buffer, source_buffer, kDataSize);
83 return true;
84 }
85
86 // Of two positions, returns the one that comes first (destroys the other).
87 AXPositionPointer FirstOf(AXPositionPointer a, AXPositionPointer b) {
88 return b->Compare(a) ? std::move(b) : std::move(a);
89 }
90
91 } // namespace
92
93 @interface TextMarkerHelperMac ()
94 - (AXPositionPointer)extractFrom:(id)parameter;
95 @end
96
97 @implementation TextMarkerHelperMac {
98 std::unique_ptr<ui::PositionFactory> factory_;
99 }
100
101 - (instancetype)initWithFactory:(std::unique_ptr<ui::PositionFactory>)factory {
102 if ((self = [super init])) {
103 factory_ = std::move(factory);
104 }
105 return self;
106 }
107
108 - (id)startTextMarker {
109 AXPositionPointer root = factory_->GetRoot();
110 return root ? CreateTextMarker(root->PositionAtStartOfAnchor()) : nil;
111 }
112
113 - (id)endTextMarker {
114 AXPositionPointer root = factory_->GetRoot();
115 return root ? CreateTextMarker(root->PositionAtEndOfAnchor()) : nil;
116 }
117
118 - (id)selectedTextMarkerRange {
119 AXRangePointer selection = factory_->GetSelection();
120 if (!selection.first || !selection.second)
121 return nil;
122 return CreateTextMarkerRange(std::move(selection));
123 }
124
125 - (AXPositionPointer)extractFrom:(id)parameter {
126 AXPositionData data;
127 if (ExtractData(base::mac::CFCastStrict<AXTextMarkerRef>(parameter), &data))
128 return factory_->GetFromData(data);
129 return factory_->GetFromData(ui::AXAbstractPosition::kNullData);
130 }
131
132 - (id)AXTextMarkerRangeForUIElement:(id)parameter {
133 AXPositionPointer startPosition = factory_->GetRoot();
134 AXPositionPointer endPosition = startPosition->PositionAtEndOfAnchor();
135 AXRangePointer range =
136 AXRangePointer(std::move(startPosition), std::move(endPosition));
137 return CreateTextMarkerRange(std::move(range));
138 }
139
140 - (id)AXUIElementForTextMarker:(id)parameter {
141 AXPositionData data;
142 if (ExtractData(base::mac::CFCastStrict<AXTextMarkerRef>(parameter), &data))
143 return factory_->GetAccessibilityObject(data);
144 return nil;
145 }
146
147 - (id)AXNextTextMarkerForTextMarker:(id)parameter {
148 AXPositionPointer position = [self extractFrom:parameter];
149 if (position->IsNull())
150 return nil;
151 return CreateTextMarker(position->NextCharacterPosition());
152 }
153
154 - (id)AXPreviousTextMarkerForTextMarker:(id)parameter {
155 AXPositionPointer position = [self extractFrom:parameter];
156 if (position->IsNull())
157 return nil;
158 return CreateTextMarker(position->PreviousCharacterPosition());
159 }
160
161 - (id)AXLeftWordTextMarkerRangeForTextMarker:(id)parameter {
162 AXPositionPointer endPosition = [self extractFrom:parameter];
163 if (endPosition->IsNull())
164 return nil;
165
166 AXPositionPointer startPosition =
167 FirstOf(endPosition->PreviousWordStartPosition(),
168 endPosition->PreviousWordEndPosition());
169 AXRangePointer range(std::move(startPosition), std::move(endPosition));
170 return CreateTextMarkerRange(std::move(range));
171 }
172
173 - (id)AXRightWordTextMarkerRangeForTextMarker:(id)parameter {
174 AXPositionPointer startPosition = [self extractFrom:parameter];
175 if (startPosition->IsNull())
176 return nil;
177
178 AXPositionPointer endPosition =
179 FirstOf(startPosition->NextWordEndPosition(),
180 startPosition->NextWordStartPosition());
181 AXRangePointer range(std::move(startPosition), std::move(endPosition));
182 return CreateTextMarkerRange(std::move(range));
183 }
184
185 - (id)AXNextWordEndTextMarkerForTextMarker:(id)parameter {
186 AXPositionPointer position = [self extractFrom:parameter];
187 if (position->IsNull())
188 return nil;
189 return CreateTextMarker(position->NextWordEndPosition());
190 }
191
192 - (id)AXPreviousWordStartTextMarkerForTextMarker:(id)parameter {
193 AXPositionPointer position = [self extractFrom:parameter];
194 if (position->IsNull())
195 return nil;
196 return CreateTextMarker(position->PreviousWordStartPosition());
197 }
198
199 - (id)AXTextMarkerRangeForLine:(id)parameter {
200 AXPositionPointer position = [self extractFrom:parameter];
201 if (position->IsNull())
202 return nil;
203
204 AXPositionPointer startPosition = position->PreviousLineStartPosition();
205 AXPositionPointer endPosition = position->NextLineEndPosition();
206 AXRangePointer range(std::move(startPosition), std::move(endPosition));
207 return CreateTextMarkerRange(std::move(range));
208 }
209
210 - (id)AXLeftLineTextMarkerRangeForTextMarker:(id)parameter {
211 AXPositionPointer endPosition = [self extractFrom:parameter];
212 if (endPosition->IsNull())
213 return nil;
214
215 AXPositionPointer startPosition =
216 FirstOf(endPosition->PreviousLineStartPosition(),
217 endPosition->PreviousLineEndPosition());
218 AXRangePointer range(std::move(startPosition), std::move(endPosition));
219 return CreateTextMarkerRange(std::move(range));
220 }
221
222 - (id)AXRightLineTextMarkerRangeForTextMarker:(id)parameter {
223 AXPositionPointer startPosition = [self extractFrom:parameter];
224 if (startPosition->IsNull())
225 return nil;
226
227 AXPositionPointer endPosition =
228 FirstOf(startPosition->NextLineStartPosition(),
229 startPosition->NextLineEndPosition());
230 AXRangePointer range(std::move(startPosition), std::move(endPosition));
231 return CreateTextMarkerRange(std::move(range));
232 }
233
234 - (id)AXNextLineEndTextMarkerForTextMarker:(id)parameter {
235 AXPositionPointer position = [self extractFrom:parameter];
236 if (position->IsNull())
237 return nil;
238 return CreateTextMarker(position->NextLineEndPosition());
239 }
240
241 - (id)AXPreviousLineStartTextMarkerForTextMarker:(id)parameter {
242 AXPositionPointer position = [self extractFrom:parameter];
243 if (position->IsNull())
244 return nil;
245 return CreateTextMarker(position->PreviousLineStartPosition());
246 }
247
248 - (id)AXLineTextMarkerRangeForTextMarker:(id)parameter {
249 AXPositionPointer position = [self extractFrom:parameter];
250 if (position->IsNull())
251 return nil;
252
253 AXRangePointer range(position->PreviousLineStartPosition(),
254 position->NextLineEndPosition());
255 return CreateTextMarkerRange(std::move(range));
256 }
257
258 - (id)AXTextMarkerRangeForUnorderedTextMarkers:(id)parameter {
259 if (![parameter isKindOfClass:[NSArray class]])
260 return nil;
261
262 NSArray* textMarkerArray = parameter;
263 if ([textMarkerArray count] != 2)
264 return nil;
265
266 AXPositionPointer startPosition =
267 [self extractFrom:[textMarkerArray objectAtIndex:0]];
268 AXPositionPointer endPosition =
269 [self extractFrom:[textMarkerArray objectAtIndex:1]];
270 if (endPosition->Compare(startPosition)) {
271 return CreateTextMarkerRange(
272 AXRangePointer(std::move(endPosition), std::move(startPosition)));
273 }
274 return CreateTextMarkerRange(
275 AXRangePointer(std::move(startPosition), std::move(endPosition)));
276 }
277
278 + (BOOL)getRangeDataFromMarkerRange:(id)parameter
279 start:(ui::AXPositionData*)start
280 end:(ui::AXPositionData*)end {
281 AXTextMarkerRangeRef markerRange =
282 base::mac::CFCastStrict<AXTextMarkerRangeRef>(parameter);
283 DCHECK(markerRange);
284
285 base::ScopedCFTypeRef<AXTextMarkerRef> startMarker(
286 AXTextMarkerRangeCopyStartMarker(markerRange));
287 base::ScopedCFTypeRef<AXTextMarkerRef> endMarker(
288 AXTextMarkerRangeCopyEndMarker(markerRange));
289 if (!startMarker || !endMarker)
290 return NO;
291
292 return ExtractData(startMarker, start) && ExtractData(endMarker, end);
293 }
294
295 @end
OLDNEW
« no previous file with comments | « ui/accessibility/platform/text_marker_helper_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698