|
1 /* |
|
2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. |
|
3 * |
|
4 * Redistribution and use in source and binary forms, with or without |
|
5 * modification, are permitted provided that the following conditions |
|
6 * are met: |
|
7 * |
|
8 * 1. Redistributions of source code must retain the above copyright |
|
9 * notice, this list of conditions and the following disclaimer. |
|
10 * 2. Redistributions in binary form must reproduce the above copyright |
|
11 * notice, this list of conditions and the following disclaimer in the |
|
12 * documentation and/or other materials provided with the distribution. |
|
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
|
14 * its contributors may be used to endorse or promote products derived |
|
15 * from this software without specific prior written permission. |
|
16 * |
|
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
|
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
|
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
|
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
27 */ |
|
28 |
|
29 #import "config.h" |
|
30 #import "AccessibilityObjectWrapper.h" |
|
31 |
|
32 #if HAVE(ACCESSIBILITY) |
|
33 |
|
34 #import "AXObjectCache.h" |
|
35 #import "AccessibilityARIAGridRow.h" |
|
36 #import "AccessibilityListBox.h" |
|
37 #import "AccessibilityList.h" |
|
38 #import "AccessibilityRenderObject.h" |
|
39 #import "AccessibilityTable.h" |
|
40 #import "AccessibilityTableCell.h" |
|
41 #import "AccessibilityTableRow.h" |
|
42 #import "AccessibilityTableColumn.h" |
|
43 #import "ColorMac.h" |
|
44 #import "Frame.h" |
|
45 #import "HTMLAnchorElement.h" |
|
46 #import "HTMLAreaElement.h" |
|
47 #import "HTMLFrameOwnerElement.h" |
|
48 #import "HTMLImageElement.h" |
|
49 #import "HTMLInputElement.h" |
|
50 #import "HTMLTextAreaElement.h" |
|
51 #import "LocalizedStrings.h" |
|
52 #import "RenderTextControl.h" |
|
53 #import "RenderView.h" |
|
54 #import "RenderWidget.h" |
|
55 #import "SelectionController.h" |
|
56 #import "SimpleFontData.h" |
|
57 #import "TextIterator.h" |
|
58 #import "WebCoreFrameView.h" |
|
59 #import "WebCoreObjCExtras.h" |
|
60 #import "WebCoreViewFactory.h" |
|
61 #import "htmlediting.h" |
|
62 #import "visible_units.h" |
|
63 |
|
64 using namespace WebCore; |
|
65 using namespace HTMLNames; |
|
66 using namespace std; |
|
67 |
|
68 // Cell Tables |
|
69 #ifndef NSAccessibilitySelectedCellsAttribute |
|
70 #define NSAccessibilitySelectedCellsAttribute @"AXSelectedCells" |
|
71 #endif |
|
72 |
|
73 #ifndef NSAccessibilityVisibleCellsAttribute |
|
74 #define NSAccessibilityVisibleCellsAttribute @"AXVisibleCells" |
|
75 #endif |
|
76 |
|
77 #ifndef NSAccessibilityRowHeaderUIElementsAttribute |
|
78 #define NSAccessibilityRowHeaderUIElementsAttribute @"AXRowHeaderUIElements" |
|
79 #endif |
|
80 |
|
81 #ifndef NSAccessibilityRowIndexRangeAttribute |
|
82 #define NSAccessibilityRowIndexRangeAttribute @"AXRowIndexRange" |
|
83 #endif |
|
84 |
|
85 #ifndef NSAccessibilityColumnIndexRangeAttribute |
|
86 #define NSAccessibilityColumnIndexRangeAttribute @"AXColumnIndexRange" |
|
87 #endif |
|
88 |
|
89 #ifndef NSAccessibilityCellForColumnAndRowParameterizedAttribute |
|
90 #define NSAccessibilityCellForColumnAndRowParameterizedAttribute @"AXCellForColumnAndRow" |
|
91 #endif |
|
92 |
|
93 #ifndef NSAccessibilityCellRole |
|
94 #define NSAccessibilityCellRole @"AXCell" |
|
95 #endif |
|
96 |
|
97 // Lists |
|
98 #ifndef NSAccessibilityContentListSubrole |
|
99 #define NSAccessibilityContentListSubrole @"AXContentList" |
|
100 #endif |
|
101 |
|
102 #ifndef NSAccessibilityDefinitionListSubrole |
|
103 #define NSAccessibilityDefinitionListSubrole @"AXDefinitionList" |
|
104 #endif |
|
105 |
|
106 // Miscellaneous |
|
107 #ifndef NSAccessibilityBlockQuoteLevelAttribute |
|
108 #define NSAccessibilityBlockQuoteLevelAttribute @"AXBlockQuoteLevel" |
|
109 #endif |
|
110 |
|
111 #ifndef NSAccessibilityAccessKeyAttribute |
|
112 #define NSAccessibilityAccessKeyAttribute @"AXAccessKey" |
|
113 #endif |
|
114 |
|
115 #ifndef NSAccessibilityLanguageAttribute |
|
116 #define NSAccessibilityLanguageAttribute @"AXLanguage" |
|
117 #endif |
|
118 |
|
119 #ifndef NSAccessibilityRequiredAttribute |
|
120 #define NSAccessibilityRequiredAttribute @"AXRequired" |
|
121 #endif |
|
122 |
|
123 #ifndef NSAccessibilityOwnsAttribute |
|
124 #define NSAccessibilityOwnsAttribute @"AXOwns" |
|
125 #endif |
|
126 |
|
127 #ifndef NSAccessibilityGrabbedAttribute |
|
128 #define NSAccessibilityGrabbedAttribute @"AXGrabbed" |
|
129 #endif |
|
130 |
|
131 #ifndef NSAccessibilityDropEffectsAttribute |
|
132 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects" |
|
133 #endif |
|
134 |
|
135 #ifndef NSAccessibilityARIALiveAttribute |
|
136 #define NSAccessibilityARIALiveAttribute @"AXARIALive" |
|
137 #endif |
|
138 |
|
139 #ifndef NSAccessibilityARIAAtomicAttribute |
|
140 #define NSAccessibilityARIAAtomicAttribute @"AXARIAAtomic" |
|
141 #endif |
|
142 |
|
143 #ifndef NSAccessibilityARIARelevantAttribute |
|
144 #define NSAccessibilityARIARelevantAttribute @"AXARIARelevant" |
|
145 #endif |
|
146 |
|
147 #ifndef NSAccessibilityARIABusyAttribute |
|
148 #define NSAccessibilityARIABusyAttribute @"AXARIABusy" |
|
149 #endif |
|
150 |
|
151 #ifndef NSAccessibilityLoadingProgressAttribute |
|
152 #define NSAccessibilityLoadingProgressAttribute @"AXLoadingProgress" |
|
153 #endif |
|
154 |
|
155 #ifndef NSAccessibilityHasPopupAttribute |
|
156 #define NSAccessibilityHasPopupAttribute @"AXHasPopup" |
|
157 #endif |
|
158 |
|
159 #ifdef BUILDING_ON_TIGER |
|
160 typedef unsigned NSUInteger; |
|
161 #define NSAccessibilityValueDescriptionAttribute @"AXValueDescription" |
|
162 #define NSAccessibilityTimelineSubrole @"AXTimeline" |
|
163 #endif |
|
164 |
|
165 @interface NSObject (WebKitAccessibilityArrayCategory) |
|
166 |
|
167 - (NSUInteger)accessibilityIndexOfChild:(id)child; |
|
168 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute; |
|
169 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount; |
|
170 |
|
171 @end |
|
172 |
|
173 @implementation AccessibilityObjectWrapper |
|
174 |
|
175 - (id)initWithAccessibilityObject:(AccessibilityObject*)axObject |
|
176 { |
|
177 [super init]; |
|
178 |
|
179 m_object = axObject; |
|
180 return self; |
|
181 } |
|
182 |
|
183 - (void)unregisterUniqueIdForUIElement |
|
184 { |
|
185 [[WebCoreViewFactory sharedFactory] unregisterUniqueIdForUIElement:self]; |
|
186 } |
|
187 |
|
188 - (void)detach |
|
189 { |
|
190 // Send unregisterUniqueIdForUIElement unconditionally because if it is |
|
191 // ever accidentally not done (via other bugs in our AX implementation) you |
|
192 // end up with a crash like <rdar://problem/4273149>. It is safe and not |
|
193 // expensive to send even if the object is not registered. |
|
194 [self unregisterUniqueIdForUIElement]; |
|
195 m_object = 0; |
|
196 } |
|
197 |
|
198 - (AccessibilityObject*)accessibilityObject |
|
199 { |
|
200 return m_object; |
|
201 } |
|
202 |
|
203 - (NSView*)attachmentView |
|
204 { |
|
205 ASSERT(m_object->isAttachment()); |
|
206 Widget* widget = m_object->widgetForAttachmentView(); |
|
207 if (!widget) |
|
208 return nil; |
|
209 return NSAccessibilityUnignoredDescendant(widget->platformWidget()); |
|
210 } |
|
211 |
|
212 static WebCoreTextMarker* textMarkerForVisiblePosition(const VisiblePosition& visiblePos) |
|
213 { |
|
214 TextMarkerData textMarkerData; |
|
215 AXObjectCache::textMarkerDataForVisiblePosition(textMarkerData, visiblePos); |
|
216 if (!textMarkerData.axID) |
|
217 return nil; |
|
218 |
|
219 return [[WebCoreViewFactory sharedFactory] textMarkerWithBytes:&textMarkerData length:sizeof(textMarkerData)]; |
|
220 } |
|
221 |
|
222 static VisiblePosition visiblePositionForTextMarker(WebCoreTextMarker* textMarker) |
|
223 { |
|
224 if (!textMarker) |
|
225 return VisiblePosition(); |
|
226 TextMarkerData textMarkerData; |
|
227 if (![[WebCoreViewFactory sharedFactory] getBytes:&textMarkerData fromTextMarker:textMarker length:sizeof(textMarkerData)]) |
|
228 return VisiblePosition(); |
|
229 |
|
230 return AXObjectCache::visiblePositionForTextMarkerData(textMarkerData); |
|
231 } |
|
232 |
|
233 static VisiblePosition visiblePositionForStartOfTextMarkerRange(WebCoreTextMarkerRange* textMarkerRange) |
|
234 { |
|
235 return visiblePositionForTextMarker([[WebCoreViewFactory sharedFactory] startOfTextMarkerRange:textMarkerRange]); |
|
236 } |
|
237 |
|
238 static VisiblePosition visiblePositionForEndOfTextMarkerRange(WebCoreTextMarkerRange* textMarkerRange) |
|
239 { |
|
240 return visiblePositionForTextMarker([[WebCoreViewFactory sharedFactory] endOfTextMarkerRange:textMarkerRange]); |
|
241 } |
|
242 |
|
243 static WebCoreTextMarkerRange* textMarkerRangeFromMarkers(WebCoreTextMarker* textMarker1, WebCoreTextMarker* textMarker2) |
|
244 { |
|
245 if (!textMarker1 || !textMarker2) |
|
246 return nil; |
|
247 |
|
248 return [[WebCoreViewFactory sharedFactory] textMarkerRangeWithStart:textMarker1 end:textMarker2]; |
|
249 } |
|
250 |
|
251 static void AXAttributeStringSetFont(NSMutableAttributedString* attrString, NSString* attribute, NSFont* font, NSRange range) |
|
252 { |
|
253 NSDictionary* dict; |
|
254 |
|
255 if (font) { |
|
256 dict = [NSDictionary dictionaryWithObjectsAndKeys: |
|
257 [font fontName] , NSAccessibilityFontNameKey, |
|
258 [font familyName] , NSAccessibilityFontFamilyKey, |
|
259 [font displayName] , NSAccessibilityVisibleNameKey, |
|
260 [NSNumber numberWithFloat:[font pointSize]] , NSAccessibilityFontSizeKey, |
|
261 nil]; |
|
262 |
|
263 [attrString addAttribute:attribute value:dict range:range]; |
|
264 } else |
|
265 [attrString removeAttribute:attribute range:range]; |
|
266 |
|
267 } |
|
268 |
|
269 static CGColorRef CreateCGColorIfDifferent(NSColor* nsColor, CGColorRef existingColor) |
|
270 { |
|
271 // get color information assuming NSDeviceRGBColorSpace |
|
272 NSColor* rgbColor = [nsColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]; |
|
273 if (rgbColor == nil) |
|
274 rgbColor = [NSColor blackColor]; |
|
275 CGFloat components[4]; |
|
276 [rgbColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]]; |
|
277 |
|
278 // create a new CGColorRef to return |
|
279 CGColorSpaceRef cgColorSpace = CGColorSpaceCreateDeviceRGB(); |
|
280 CGColorRef cgColor = CGColorCreate(cgColorSpace, components); |
|
281 CGColorSpaceRelease(cgColorSpace); |
|
282 |
|
283 // check for match with existing color |
|
284 if (existingColor && CGColorEqualToColor(cgColor, existingColor)) { |
|
285 CGColorRelease(cgColor); |
|
286 cgColor = 0; |
|
287 } |
|
288 |
|
289 return cgColor; |
|
290 } |
|
291 |
|
292 static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range) |
|
293 { |
|
294 if (color) { |
|
295 CGColorRef existingColor = (CGColorRef) [attrString attribute:attribute atIndex:range.location effectiveRange:nil]; |
|
296 CGColorRef cgColor = CreateCGColorIfDifferent(color, existingColor); |
|
297 if (cgColor) { |
|
298 [attrString addAttribute:attribute value:(id)cgColor range:range]; |
|
299 CGColorRelease(cgColor); |
|
300 } |
|
301 } else |
|
302 [attrString removeAttribute:attribute range:range]; |
|
303 } |
|
304 |
|
305 static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range) |
|
306 { |
|
307 if (number) |
|
308 [attrString addAttribute:attribute value:number range:range]; |
|
309 else |
|
310 [attrString removeAttribute:attribute range:range]; |
|
311 } |
|
312 |
|
313 static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range) |
|
314 { |
|
315 RenderStyle* style = renderer->style(); |
|
316 |
|
317 // set basic font info |
|
318 AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style->font().primaryFont()->getNSFont(), range); |
|
319 |
|
320 // set basic colors |
|
321 AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyColor)), range); |
|
322 AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyBackgroundColor)), range); |
|
323 |
|
324 // set super/sub scripting |
|
325 EVerticalAlign alignment = style->verticalAlign(); |
|
326 if (alignment == SUB) |
|
327 AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:(-1)], range); |
|
328 else if (alignment == SUPER) |
|
329 AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:1], range); |
|
330 else |
|
331 [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range]; |
|
332 |
|
333 // set shadow |
|
334 if (style->textShadow()) |
|
335 AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, [NSNumber numberWithBool:YES], range); |
|
336 else |
|
337 [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range]; |
|
338 |
|
339 // set underline and strikethrough |
|
340 int decor = style->textDecorationsInEffect(); |
|
341 if ((decor & UNDERLINE) == 0) { |
|
342 [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range]; |
|
343 [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range]; |
|
344 } |
|
345 |
|
346 if ((decor & LINE_THROUGH) == 0) { |
|
347 [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range]; |
|
348 [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range]; |
|
349 } |
|
350 |
|
351 if ((decor & (UNDERLINE | LINE_THROUGH)) != 0) { |
|
352 // find colors using quirk mode approach (strict mode would use current |
|
353 // color for all but the root line box, which would use getTextDecorationColors) |
|
354 Color underline, overline, linethrough; |
|
355 renderer->getTextDecorationColors(decor, underline, overline, linethrough); |
|
356 |
|
357 if ((decor & UNDERLINE) != 0) { |
|
358 AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, [NSNumber numberWithBool:YES], range); |
|
359 AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(underline), range); |
|
360 } |
|
361 |
|
362 if ((decor & LINE_THROUGH) != 0) { |
|
363 AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, [NSNumber numberWithBool:YES], range); |
|
364 AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(linethrough), range); |
|
365 } |
|
366 } |
|
367 } |
|
368 |
|
369 static int blockquoteLevel(RenderObject* renderer) |
|
370 { |
|
371 if (!renderer) |
|
372 return 0; |
|
373 |
|
374 int result = 0; |
|
375 for (Node* node = renderer->node(); node; node = node->parent()) { |
|
376 if (node->hasTagName(blockquoteTag)) |
|
377 result += 1; |
|
378 } |
|
379 |
|
380 return result; |
|
381 } |
|
382 |
|
383 static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range) |
|
384 { |
|
385 int quoteLevel = blockquoteLevel(renderer); |
|
386 |
|
387 if (quoteLevel) |
|
388 [attrString addAttribute:NSAccessibilityBlockQuoteLevelAttribute value:[NSNumber numberWithInt:quoteLevel] range:range]; |
|
389 else |
|
390 [attrString removeAttribute:NSAccessibilityBlockQuoteLevelAttribute range:range]; |
|
391 } |
|
392 |
|
393 static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, int offset, NSRange range) |
|
394 { |
|
395 Vector<DocumentMarker> markers = node->renderer()->document()->markersForNode(node); |
|
396 Vector<DocumentMarker>::iterator markerIt = markers.begin(); |
|
397 |
|
398 unsigned endOffset = (unsigned)offset + range.length; |
|
399 for ( ; markerIt != markers.end(); markerIt++) { |
|
400 DocumentMarker marker = *markerIt; |
|
401 |
|
402 if (marker.type != DocumentMarker::Spelling) |
|
403 continue; |
|
404 |
|
405 if (marker.endOffset <= (unsigned)offset) |
|
406 continue; |
|
407 |
|
408 if (marker.startOffset > endOffset) |
|
409 break; |
|
410 |
|
411 // add misspelling attribute for the intersection of the marker and the range |
|
412 int rStart = range.location + (marker.startOffset - offset); |
|
413 int rLength = min(marker.endOffset, endOffset) - marker.startOffset; |
|
414 NSRange spellRange = NSMakeRange(rStart, rLength); |
|
415 AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange); |
|
416 |
|
417 if (marker.endOffset > endOffset + 1) |
|
418 break; |
|
419 } |
|
420 } |
|
421 |
|
422 static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range) |
|
423 { |
|
424 if (!renderer) |
|
425 return; |
|
426 |
|
427 AccessibilityObject* parentObject = renderer->document()->axObjectCache()->getOrCreate(renderer->parent()); |
|
428 int parentHeadingLevel = parentObject->headingLevel(); |
|
429 |
|
430 if (parentHeadingLevel) |
|
431 [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range]; |
|
432 else |
|
433 [attrString removeAttribute:@"AXHeadingLevel" range:range]; |
|
434 } |
|
435 |
|
436 static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range) |
|
437 { |
|
438 if (object && object->isAccessibilityRenderObject()) { |
|
439 // make a serializable AX object |
|
440 |
|
441 RenderObject* renderer = static_cast<AccessibilityRenderObject*>(object)->renderer(); |
|
442 if (!renderer) |
|
443 return; |
|
444 |
|
445 Document* doc = renderer->document(); |
|
446 if (!doc) |
|
447 return; |
|
448 |
|
449 AXObjectCache* cache = doc->axObjectCache(); |
|
450 if (!cache) |
|
451 return; |
|
452 |
|
453 AXUIElementRef axElement = [[WebCoreViewFactory sharedFactory] AXUIElementForElement:object->wrapper()]; |
|
454 if (axElement) { |
|
455 [attrString addAttribute:attribute value:(id)axElement range:range]; |
|
456 CFRelease(axElement); |
|
457 } |
|
458 } else |
|
459 [attrString removeAttribute:attribute range:range]; |
|
460 } |
|
461 |
|
462 static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, int offset, const UChar* chars, int length) |
|
463 { |
|
464 // skip invisible text |
|
465 if (!node->renderer()) |
|
466 return; |
|
467 |
|
468 // easier to calculate the range before appending the string |
|
469 NSRange attrStringRange = NSMakeRange([attrString length], length); |
|
470 |
|
471 // append the string from this node |
|
472 [[attrString mutableString] appendString:[NSString stringWithCharacters:chars length:length]]; |
|
473 |
|
474 // add new attributes and remove irrelevant inherited ones |
|
475 // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge |
|
476 // identical colors. Workaround is to not replace an existing color attribute if it matches what we are adding. This also means |
|
477 // we cannot just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually. |
|
478 |
|
479 // remove inherited attachment from prior AXAttributedStringAppendReplaced |
|
480 [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange]; |
|
481 |
|
482 // set new attributes |
|
483 AXAttributeStringSetStyle(attrString, node->renderer(), attrStringRange); |
|
484 AXAttributeStringSetHeadingLevel(attrString, node->renderer(), attrStringRange); |
|
485 AXAttributeStringSetBlockquoteLevel(attrString, node->renderer(), attrStringRange); |
|
486 AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AccessibilityObject::anchorElementForNode(node), attrStringRange); |
|
487 |
|
488 // do spelling last because it tends to break up the range |
|
489 AXAttributeStringSetSpelling(attrString, node, offset, attrStringRange); |
|
490 } |
|
491 |
|
492 static NSString* nsStringForReplacedNode(Node* replacedNode) |
|
493 { |
|
494 // we should always be given a rendered node and a replaced node, but be safe |
|
495 // replaced nodes are either attachments (widgets) or images |
|
496 if (!replacedNode || !replacedNode->renderer() || !replacedNode->renderer()->isReplaced() || replacedNode->isTextNode()) { |
|
497 ASSERT_NOT_REACHED(); |
|
498 return nil; |
|
499 } |
|
500 |
|
501 // create an AX object, but skip it if it is not supposed to be seen |
|
502 RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer()); |
|
503 if (obj->accessibilityIsIgnored()) |
|
504 return nil; |
|
505 |
|
506 // use the attachmentCharacter to represent the replaced node |
|
507 const UniChar attachmentChar = NSAttachmentCharacter; |
|
508 return [NSString stringWithCharacters:&attachmentChar length:1]; |
|
509 } |
|
510 |
|
511 - (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(WebCoreTextMarkerRange*)textMarkerRange |
|
512 { |
|
513 if (!m_object) |
|
514 return nil; |
|
515 |
|
516 // extract the start and end VisiblePosition |
|
517 VisiblePosition startVisiblePosition = visiblePositionForStartOfTextMarkerRange(textMarkerRange); |
|
518 if (startVisiblePosition.isNull()) |
|
519 return nil; |
|
520 |
|
521 VisiblePosition endVisiblePosition = visiblePositionForEndOfTextMarkerRange(textMarkerRange); |
|
522 if (endVisiblePosition.isNull()) |
|
523 return nil; |
|
524 |
|
525 VisiblePositionRange visiblePositionRange(startVisiblePosition, endVisiblePosition); |
|
526 // iterate over the range to build the AX attributed string |
|
527 NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init]; |
|
528 TextIterator it(makeRange(startVisiblePosition, endVisiblePosition).get()); |
|
529 while (!it.atEnd()) { |
|
530 // locate the node and starting offset for this range |
|
531 int exception = 0; |
|
532 Node* node = it.range()->startContainer(exception); |
|
533 ASSERT(node == it.range()->endContainer(exception)); |
|
534 int offset = it.range()->startOffset(exception); |
|
535 |
|
536 // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX) |
|
537 if (it.length() != 0) { |
|
538 // Add the text of the list marker item if necessary. |
|
539 String listMarkerText = m_object->listMarkerTextForNodeAndPosition(node, VisiblePosition(it.range()->startPosition())); |
|
540 if (!listMarkerText.isEmpty()) |
|
541 AXAttributedStringAppendText(attrString, node, offset, listMarkerText.characters(), listMarkerText.length()); |
|
542 |
|
543 AXAttributedStringAppendText(attrString, node, offset, it.characters(), it.length()); |
|
544 } else { |
|
545 Node* replacedNode = node->childNode(offset); |
|
546 NSString *attachmentString = nsStringForReplacedNode(replacedNode); |
|
547 if (attachmentString) { |
|
548 NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]); |
|
549 |
|
550 // append the placeholder string |
|
551 [[attrString mutableString] appendString:attachmentString]; |
|
552 |
|
553 // remove all inherited attributes |
|
554 [attrString setAttributes:nil range:attrStringRange]; |
|
555 |
|
556 // add the attachment attribute |
|
557 AccessibilityObject* obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer()); |
|
558 AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange); |
|
559 } |
|
560 } |
|
561 it.advance(); |
|
562 } |
|
563 |
|
564 return [attrString autorelease]; |
|
565 } |
|
566 |
|
567 static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePosition startPosition, VisiblePosition endPosition) |
|
568 { |
|
569 WebCoreTextMarker* startTextMarker = textMarkerForVisiblePosition(startPosition); |
|
570 WebCoreTextMarker* endTextMarker = textMarkerForVisiblePosition(endPosition); |
|
571 return textMarkerRangeFromMarkers(startTextMarker, endTextMarker); |
|
572 } |
|
573 |
|
574 - (NSArray*)accessibilityActionNames |
|
575 { |
|
576 if (!m_object) |
|
577 return nil; |
|
578 |
|
579 m_object->updateBackingStore(); |
|
580 if (!m_object) |
|
581 return nil; |
|
582 |
|
583 static NSArray* actionElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityPressAction, NSAccessibilityShowMenuAction, nil]; |
|
584 static NSArray* defaultElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityShowMenuAction, nil]; |
|
585 static NSArray* menuElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityCancelAction, NSAccessibilityPressAction, nil]; |
|
586 static NSArray* sliderActions = [[NSArray alloc] initWithObjects: NSAccessibilityIncrementAction, NSAccessibilityDecrementAction, nil]; |
|
587 |
|
588 NSArray *actions; |
|
589 if (m_object->actionElement()) |
|
590 actions = actionElementActions; |
|
591 else if (m_object->isMenuRelated()) |
|
592 actions = menuElementActions; |
|
593 else if (m_object->isSlider()) |
|
594 actions = sliderActions; |
|
595 else if (m_object->isAttachment()) |
|
596 actions = [[self attachmentView] accessibilityActionNames]; |
|
597 else |
|
598 actions = defaultElementActions; |
|
599 |
|
600 return actions; |
|
601 } |
|
602 |
|
603 - (NSArray*)additionalAccessibilityAttributeNames |
|
604 { |
|
605 if (!m_object) |
|
606 return nil; |
|
607 |
|
608 NSMutableArray *additional = [NSMutableArray array]; |
|
609 if (m_object->supportsARIAOwns()) |
|
610 [additional addObject:NSAccessibilityOwnsAttribute]; |
|
611 |
|
612 if (m_object->isScrollbar()) |
|
613 [additional addObject:NSAccessibilityOrientationAttribute]; |
|
614 |
|
615 if (m_object->supportsARIADragging()) |
|
616 [additional addObject:NSAccessibilityGrabbedAttribute]; |
|
617 |
|
618 if (m_object->supportsARIADropping()) |
|
619 [additional addObject:NSAccessibilityDropEffectsAttribute]; |
|
620 |
|
621 if (m_object->isDataTable() && static_cast<AccessibilityTable*>(m_object)->supportsSelectedRows()) |
|
622 [additional addObject:NSAccessibilitySelectedRowsAttribute]; |
|
623 |
|
624 if (m_object->supportsARIALiveRegion()) { |
|
625 [additional addObject:NSAccessibilityARIALiveAttribute]; |
|
626 [additional addObject:NSAccessibilityARIARelevantAttribute]; |
|
627 } |
|
628 |
|
629 // If an object is a child of a live region, then add these |
|
630 if (m_object->isInsideARIALiveRegion()) { |
|
631 [additional addObject:NSAccessibilityARIAAtomicAttribute]; |
|
632 [additional addObject:NSAccessibilityARIABusyAttribute]; |
|
633 } |
|
634 |
|
635 if (m_object->ariaHasPopup()) |
|
636 [additional addObject:NSAccessibilityHasPopupAttribute]; |
|
637 |
|
638 return additional; |
|
639 } |
|
640 |
|
641 - (NSArray*)accessibilityAttributeNames |
|
642 { |
|
643 if (!m_object) |
|
644 return nil; |
|
645 |
|
646 m_object->updateBackingStore(); |
|
647 if (!m_object) |
|
648 return nil; |
|
649 |
|
650 if (m_object->isAttachment()) |
|
651 return [[self attachmentView] accessibilityAttributeNames]; |
|
652 |
|
653 static NSArray* attributes = nil; |
|
654 static NSArray* anchorAttrs = nil; |
|
655 static NSArray* webAreaAttrs = nil; |
|
656 static NSArray* textAttrs = nil; |
|
657 static NSArray* listBoxAttrs = nil; |
|
658 static NSArray* rangeAttrs = nil; |
|
659 static NSArray* commonMenuAttrs = nil; |
|
660 static NSArray* menuAttrs = nil; |
|
661 static NSArray* menuBarAttrs = nil; |
|
662 static NSArray* menuItemAttrs = nil; |
|
663 static NSArray* menuButtonAttrs = nil; |
|
664 static NSArray* controlAttrs = nil; |
|
665 static NSArray* tableAttrs = nil; |
|
666 static NSArray* tableRowAttrs = nil; |
|
667 static NSArray* tableColAttrs = nil; |
|
668 static NSArray* tableCellAttrs = nil; |
|
669 static NSArray* groupAttrs = nil; |
|
670 static NSArray* inputImageAttrs = nil; |
|
671 static NSArray* passwordFieldAttrs = nil; |
|
672 static NSArray* tabListAttrs = nil; |
|
673 static NSArray* comboBoxAttrs = nil; |
|
674 static NSArray* outlineAttrs = nil; |
|
675 static NSArray* outlineRowAttrs = nil; |
|
676 static NSArray* buttonAttrs = nil; |
|
677 NSMutableArray* tempArray; |
|
678 if (attributes == nil) { |
|
679 attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute, |
|
680 NSAccessibilitySubroleAttribute, |
|
681 NSAccessibilityRoleDescriptionAttribute, |
|
682 NSAccessibilityChildrenAttribute, |
|
683 NSAccessibilityHelpAttribute, |
|
684 NSAccessibilityParentAttribute, |
|
685 NSAccessibilityPositionAttribute, |
|
686 NSAccessibilitySizeAttribute, |
|
687 NSAccessibilityTitleAttribute, |
|
688 NSAccessibilityDescriptionAttribute, |
|
689 NSAccessibilityValueAttribute, |
|
690 NSAccessibilityFocusedAttribute, |
|
691 NSAccessibilityEnabledAttribute, |
|
692 NSAccessibilityWindowAttribute, |
|
693 @"AXSelectedTextMarkerRange", |
|
694 @"AXStartTextMarker", |
|
695 @"AXEndTextMarker", |
|
696 @"AXVisited", |
|
697 NSAccessibilityLinkedUIElementsAttribute, |
|
698 NSAccessibilitySelectedAttribute, |
|
699 NSAccessibilityBlockQuoteLevelAttribute, |
|
700 NSAccessibilityTopLevelUIElementAttribute, |
|
701 nil]; |
|
702 } |
|
703 if (commonMenuAttrs == nil) { |
|
704 commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute, |
|
705 NSAccessibilityRoleDescriptionAttribute, |
|
706 NSAccessibilityChildrenAttribute, |
|
707 NSAccessibilityParentAttribute, |
|
708 NSAccessibilityEnabledAttribute, |
|
709 NSAccessibilityPositionAttribute, |
|
710 NSAccessibilitySizeAttribute, |
|
711 nil]; |
|
712 } |
|
713 if (anchorAttrs == nil) { |
|
714 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
715 [tempArray addObject:NSAccessibilityURLAttribute]; |
|
716 [tempArray addObject:NSAccessibilityAccessKeyAttribute]; |
|
717 anchorAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
718 [tempArray release]; |
|
719 } |
|
720 if (webAreaAttrs == nil) { |
|
721 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
722 [tempArray addObject:@"AXLinkUIElements"]; |
|
723 [tempArray addObject:@"AXLoaded"]; |
|
724 [tempArray addObject:@"AXLayoutCount"]; |
|
725 [tempArray addObject:NSAccessibilityLoadingProgressAttribute]; |
|
726 [tempArray addObject:NSAccessibilityURLAttribute]; |
|
727 webAreaAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
728 [tempArray release]; |
|
729 } |
|
730 if (textAttrs == nil) { |
|
731 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
732 [tempArray addObject:NSAccessibilityNumberOfCharactersAttribute]; |
|
733 [tempArray addObject:NSAccessibilitySelectedTextAttribute]; |
|
734 [tempArray addObject:NSAccessibilitySelectedTextRangeAttribute]; |
|
735 [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute]; |
|
736 [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute]; |
|
737 [tempArray addObject:NSAccessibilityTitleUIElementAttribute]; |
|
738 [tempArray addObject:NSAccessibilityAccessKeyAttribute]; |
|
739 [tempArray addObject:NSAccessibilityRequiredAttribute]; |
|
740 textAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
741 [tempArray release]; |
|
742 } |
|
743 if (listBoxAttrs == nil) { |
|
744 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
745 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute]; |
|
746 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute]; |
|
747 [tempArray addObject:NSAccessibilityOrientationAttribute]; |
|
748 [tempArray addObject:NSAccessibilityTitleUIElementAttribute]; |
|
749 [tempArray addObject:NSAccessibilityAccessKeyAttribute]; |
|
750 [tempArray addObject:NSAccessibilityRequiredAttribute]; |
|
751 listBoxAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
752 [tempArray release]; |
|
753 } |
|
754 if (rangeAttrs == nil) { |
|
755 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
756 [tempArray addObject:NSAccessibilityTopLevelUIElementAttribute]; |
|
757 [tempArray addObject:NSAccessibilityValueAttribute]; |
|
758 [tempArray addObject:NSAccessibilityMinValueAttribute]; |
|
759 [tempArray addObject:NSAccessibilityMaxValueAttribute]; |
|
760 [tempArray addObject:NSAccessibilityOrientationAttribute]; |
|
761 [tempArray addObject:NSAccessibilityValueDescriptionAttribute]; |
|
762 rangeAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
763 [tempArray release]; |
|
764 } |
|
765 if (menuBarAttrs == nil) { |
|
766 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs]; |
|
767 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute]; |
|
768 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute]; |
|
769 [tempArray addObject:NSAccessibilityTitleUIElementAttribute]; |
|
770 menuBarAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
771 [tempArray release]; |
|
772 } |
|
773 if (menuAttrs == nil) { |
|
774 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs]; |
|
775 [tempArray addObject:NSAccessibilitySelectedChildrenAttribute]; |
|
776 [tempArray addObject:NSAccessibilityVisibleChildrenAttribute]; |
|
777 [tempArray addObject:NSAccessibilityTitleUIElementAttribute]; |
|
778 menuAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
779 [tempArray release]; |
|
780 } |
|
781 if (menuItemAttrs == nil) { |
|
782 tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs]; |
|
783 [tempArray addObject:NSAccessibilityTitleAttribute]; |
|
784 [tempArray addObject:NSAccessibilityHelpAttribute]; |
|
785 [tempArray addObject:NSAccessibilitySelectedAttribute]; |
|
786 [tempArray addObject:(NSString*)kAXMenuItemCmdCharAttribute]; |
|
787 [tempArray addObject:(NSString*)kAXMenuItemCmdVirtualKeyAttribute]; |
|
788 [tempArray addObject:(NSString*)kAXMenuItemCmdGlyphAttribute]; |
|
789 [tempArray addObject:(NSString*)kAXMenuItemCmdModifiersAttribute]; |
|
790 [tempArray addObject:(NSString*)kAXMenuItemMarkCharAttribute]; |
|
791 [tempArray addObject:(NSString*)kAXMenuItemPrimaryUIElementAttribute]; |
|
792 [tempArray addObject:NSAccessibilityServesAsTitleForUIElementsAttribute]; |
|
793 menuItemAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
794 [tempArray release]; |
|
795 } |
|
796 if (menuButtonAttrs == nil) { |
|
797 menuButtonAttrs = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute, |
|
798 NSAccessibilityRoleDescriptionAttribute, |
|
799 NSAccessibilityParentAttribute, |
|
800 NSAccessibilityPositionAttribute, |
|
801 NSAccessibilitySizeAttribute, |
|
802 NSAccessibilityWindowAttribute, |
|
803 NSAccessibilityTopLevelUIElementAttribute, |
|
804 NSAccessibilityEnabledAttribute, |
|
805 NSAccessibilityFocusedAttribute, |
|
806 NSAccessibilityTitleAttribute, |
|
807 NSAccessibilityChildrenAttribute, nil]; |
|
808 } |
|
809 if (controlAttrs == nil) { |
|
810 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
811 [tempArray addObject:NSAccessibilityTitleUIElementAttribute]; |
|
812 [tempArray addObject:NSAccessibilityAccessKeyAttribute]; |
|
813 [tempArray addObject:NSAccessibilityRequiredAttribute]; |
|
814 controlAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
815 [tempArray release]; |
|
816 } |
|
817 if (buttonAttrs == nil) { |
|
818 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
819 // Buttons should not expose AXValue. |
|
820 [tempArray removeObject:NSAccessibilityValueAttribute]; |
|
821 [tempArray addObject:NSAccessibilityTitleUIElementAttribute]; |
|
822 [tempArray addObject:NSAccessibilityAccessKeyAttribute]; |
|
823 buttonAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
824 [tempArray release]; |
|
825 } |
|
826 if (comboBoxAttrs == nil) { |
|
827 tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs]; |
|
828 [tempArray addObject:NSAccessibilityExpandedAttribute]; |
|
829 comboBoxAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
830 [tempArray release]; |
|
831 } |
|
832 if (tableAttrs == nil) { |
|
833 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
834 [tempArray addObject:NSAccessibilityRowsAttribute]; |
|
835 [tempArray addObject:NSAccessibilityVisibleRowsAttribute]; |
|
836 [tempArray addObject:NSAccessibilityColumnsAttribute]; |
|
837 [tempArray addObject:NSAccessibilityVisibleColumnsAttribute]; |
|
838 [tempArray addObject:NSAccessibilityVisibleCellsAttribute]; |
|
839 [tempArray addObject:(NSString *)kAXColumnHeaderUIElementsAttribute]; |
|
840 [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute]; |
|
841 [tempArray addObject:NSAccessibilityHeaderAttribute]; |
|
842 tableAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
843 [tempArray release]; |
|
844 } |
|
845 if (tableRowAttrs == nil) { |
|
846 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
847 [tempArray addObject:NSAccessibilityIndexAttribute]; |
|
848 tableRowAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
849 [tempArray release]; |
|
850 } |
|
851 if (tableColAttrs == nil) { |
|
852 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
853 [tempArray addObject:NSAccessibilityIndexAttribute]; |
|
854 [tempArray addObject:NSAccessibilityHeaderAttribute]; |
|
855 [tempArray addObject:NSAccessibilityRowsAttribute]; |
|
856 [tempArray addObject:NSAccessibilityVisibleRowsAttribute]; |
|
857 tableColAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
858 [tempArray release]; |
|
859 } |
|
860 if (tableCellAttrs == nil) { |
|
861 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
862 [tempArray addObject:NSAccessibilityRowIndexRangeAttribute]; |
|
863 [tempArray addObject:NSAccessibilityColumnIndexRangeAttribute]; |
|
864 tableCellAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
865 [tempArray release]; |
|
866 } |
|
867 if (groupAttrs == nil) { |
|
868 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
869 [tempArray addObject:NSAccessibilityTitleUIElementAttribute]; |
|
870 groupAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
871 [tempArray release]; |
|
872 } |
|
873 if (inputImageAttrs == nil) { |
|
874 tempArray = [[NSMutableArray alloc] initWithArray:buttonAttrs]; |
|
875 [tempArray addObject:NSAccessibilityURLAttribute]; |
|
876 inputImageAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
877 [tempArray release]; |
|
878 } |
|
879 if (passwordFieldAttrs == nil) { |
|
880 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
881 [tempArray addObject:NSAccessibilityTitleUIElementAttribute]; |
|
882 [tempArray addObject:NSAccessibilityRequiredAttribute]; |
|
883 passwordFieldAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
884 [tempArray release]; |
|
885 } |
|
886 if (tabListAttrs == nil) { |
|
887 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
888 [tempArray addObject:NSAccessibilityTabsAttribute]; |
|
889 [tempArray addObject:NSAccessibilityContentsAttribute]; |
|
890 tabListAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
891 [tempArray release]; |
|
892 } |
|
893 if (outlineAttrs == nil) { |
|
894 tempArray = [[NSMutableArray alloc] initWithArray:attributes]; |
|
895 [tempArray addObject:NSAccessibilitySelectedRowsAttribute]; |
|
896 [tempArray addObject:NSAccessibilityRowsAttribute]; |
|
897 [tempArray addObject:NSAccessibilityColumnsAttribute]; |
|
898 outlineAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
899 [tempArray release]; |
|
900 } |
|
901 if (outlineRowAttrs == nil) { |
|
902 tempArray = [[NSMutableArray alloc] initWithArray:tableRowAttrs]; |
|
903 [tempArray addObject:NSAccessibilityDisclosingAttribute]; |
|
904 [tempArray addObject:NSAccessibilityDisclosedByRowAttribute]; |
|
905 [tempArray addObject:NSAccessibilityDisclosureLevelAttribute]; |
|
906 [tempArray addObject:NSAccessibilityDisclosedRowsAttribute]; |
|
907 outlineRowAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
908 [tempArray release]; |
|
909 } |
|
910 |
|
911 NSArray *objectAttributes = attributes; |
|
912 |
|
913 if (m_object->isPasswordField()) |
|
914 objectAttributes = passwordFieldAttrs; |
|
915 |
|
916 else if (m_object->isWebArea()) |
|
917 objectAttributes = webAreaAttrs; |
|
918 |
|
919 else if (m_object->isTextControl()) |
|
920 objectAttributes = textAttrs; |
|
921 |
|
922 else if (m_object->isAnchor() || m_object->isImage() || m_object->isLink()) |
|
923 objectAttributes = anchorAttrs; |
|
924 |
|
925 else if (m_object->isDataTable()) |
|
926 objectAttributes = tableAttrs; |
|
927 else if (m_object->isTableColumn()) |
|
928 objectAttributes = tableColAttrs; |
|
929 else if (m_object->isTableCell()) |
|
930 objectAttributes = tableCellAttrs; |
|
931 else if (m_object->isTableRow()) { |
|
932 // An ARIA table row can be collapsed and expanded, so it needs the extra attributes. |
|
933 if (m_object->isARIATreeGridRow()) |
|
934 objectAttributes = outlineRowAttrs; |
|
935 else |
|
936 objectAttributes = tableRowAttrs; |
|
937 } |
|
938 |
|
939 else if (m_object->isTree()) |
|
940 objectAttributes = outlineAttrs; |
|
941 else if (m_object->isTreeItem()) |
|
942 objectAttributes = outlineRowAttrs; |
|
943 |
|
944 else if (m_object->isListBox() || m_object->isList()) |
|
945 objectAttributes = listBoxAttrs; |
|
946 |
|
947 else if (m_object->isComboBox()) |
|
948 objectAttributes = comboBoxAttrs; |
|
949 |
|
950 else if (m_object->isProgressIndicator() || m_object->isSlider()) |
|
951 objectAttributes = rangeAttrs; |
|
952 |
|
953 // These are processed in order because an input image is a button, and a button is a control. |
|
954 else if (m_object->isInputImage()) |
|
955 objectAttributes = inputImageAttrs; |
|
956 else if (m_object->isButton()) |
|
957 objectAttributes = buttonAttrs; |
|
958 else if (m_object->isControl()) |
|
959 objectAttributes = controlAttrs; |
|
960 |
|
961 else if (m_object->isGroup() || m_object->isListItem()) |
|
962 objectAttributes = groupAttrs; |
|
963 else if (m_object->isTabList()) |
|
964 objectAttributes = tabListAttrs; |
|
965 |
|
966 else if (m_object->isMenu()) |
|
967 objectAttributes = menuAttrs; |
|
968 else if (m_object->isMenuBar()) |
|
969 objectAttributes = menuBarAttrs; |
|
970 else if (m_object->isMenuButton()) |
|
971 objectAttributes = menuButtonAttrs; |
|
972 else if (m_object->isMenuItem()) |
|
973 objectAttributes = menuItemAttrs; |
|
974 |
|
975 NSArray *additionalAttributes = [self additionalAccessibilityAttributeNames]; |
|
976 if ([additionalAttributes count]) |
|
977 objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:additionalAttributes]; |
|
978 |
|
979 return objectAttributes; |
|
980 } |
|
981 |
|
982 - (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(WebCoreTextMarkerRange*) textMarkerRange |
|
983 { |
|
984 if (!textMarkerRange) |
|
985 return VisiblePositionRange(); |
|
986 return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(textMarkerRange), visiblePositionForEndOfTextMarkerRange(textMarkerRange)); |
|
987 } |
|
988 |
|
989 - (NSArray*)renderWidgetChildren |
|
990 { |
|
991 Widget* widget = m_object->widget(); |
|
992 if (!widget) |
|
993 return nil; |
|
994 return [(widget->platformWidget()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute]; |
|
995 } |
|
996 |
|
997 static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector) |
|
998 { |
|
999 unsigned length = [array count]; |
|
1000 vector.reserveInitialCapacity(length); |
|
1001 for (unsigned i = 0; i < length; ++i) { |
|
1002 AccessibilityObject* obj = [[array objectAtIndex:i] accessibilityObject]; |
|
1003 if (obj) |
|
1004 vector.append(obj); |
|
1005 } |
|
1006 } |
|
1007 |
|
1008 static NSMutableArray* convertToNSArray(const AccessibilityObject::AccessibilityChildrenVector& vector) |
|
1009 { |
|
1010 unsigned length = vector.size(); |
|
1011 NSMutableArray* array = [NSMutableArray arrayWithCapacity: length]; |
|
1012 for (unsigned i = 0; i < length; ++i) { |
|
1013 AccessibilityObjectWrapper* wrapper = vector[i]->wrapper(); |
|
1014 ASSERT(wrapper); |
|
1015 if (wrapper) { |
|
1016 // we want to return the attachment view instead of the object representing the attachment. |
|
1017 // otherwise, we get palindrome errors in the AX hierarchy |
|
1018 if (vector[i]->isAttachment() && [wrapper attachmentView]) |
|
1019 [array addObject:[wrapper attachmentView]]; |
|
1020 else |
|
1021 [array addObject:wrapper]; |
|
1022 } |
|
1023 } |
|
1024 return array; |
|
1025 } |
|
1026 |
|
1027 - (WebCoreTextMarkerRange*)textMarkerRangeForSelection |
|
1028 { |
|
1029 VisibleSelection selection = m_object->selection(); |
|
1030 if (selection.isNone()) |
|
1031 return nil; |
|
1032 return textMarkerRangeFromVisiblePositions(selection.visibleStart(), selection.visibleEnd()); |
|
1033 } |
|
1034 |
|
1035 - (NSValue*)position |
|
1036 { |
|
1037 IntRect rect = m_object->elementRect(); |
|
1038 |
|
1039 // The Cocoa accessibility API wants the lower-left corner. |
|
1040 NSPoint point = NSMakePoint(rect.x(), rect.bottom()); |
|
1041 FrameView* frameView = m_object->documentFrameView(); |
|
1042 if (frameView) { |
|
1043 NSView* view = frameView->documentView(); |
|
1044 point = [[view window] convertBaseToScreen: [view convertPoint: point toView:nil]]; |
|
1045 } |
|
1046 |
|
1047 return [NSValue valueWithPoint: point]; |
|
1048 } |
|
1049 |
|
1050 typedef HashMap<int, NSString*> AccessibilityRoleMap; |
|
1051 |
|
1052 static const AccessibilityRoleMap& createAccessibilityRoleMap() |
|
1053 { |
|
1054 struct RoleEntry { |
|
1055 AccessibilityRole value; |
|
1056 NSString* string; |
|
1057 }; |
|
1058 |
|
1059 static const RoleEntry roles[] = { |
|
1060 { UnknownRole, NSAccessibilityUnknownRole }, |
|
1061 { ButtonRole, NSAccessibilityButtonRole }, |
|
1062 { RadioButtonRole, NSAccessibilityRadioButtonRole }, |
|
1063 { CheckBoxRole, NSAccessibilityCheckBoxRole }, |
|
1064 { SliderRole, NSAccessibilitySliderRole }, |
|
1065 { TabGroupRole, NSAccessibilityTabGroupRole }, |
|
1066 { TextFieldRole, NSAccessibilityTextFieldRole }, |
|
1067 { StaticTextRole, NSAccessibilityStaticTextRole }, |
|
1068 { TextAreaRole, NSAccessibilityTextAreaRole }, |
|
1069 { ScrollAreaRole, NSAccessibilityScrollAreaRole }, |
|
1070 { PopUpButtonRole, NSAccessibilityPopUpButtonRole }, |
|
1071 { MenuButtonRole, NSAccessibilityMenuButtonRole }, |
|
1072 { TableRole, NSAccessibilityTableRole }, |
|
1073 { ApplicationRole, NSAccessibilityApplicationRole }, |
|
1074 { GroupRole, NSAccessibilityGroupRole }, |
|
1075 { RadioGroupRole, NSAccessibilityRadioGroupRole }, |
|
1076 { ListRole, NSAccessibilityListRole }, |
|
1077 { DirectoryRole, NSAccessibilityListRole }, |
|
1078 { ScrollBarRole, NSAccessibilityScrollBarRole }, |
|
1079 { ValueIndicatorRole, NSAccessibilityValueIndicatorRole }, |
|
1080 { ImageRole, NSAccessibilityImageRole }, |
|
1081 { MenuBarRole, NSAccessibilityMenuBarRole }, |
|
1082 { MenuRole, NSAccessibilityMenuRole }, |
|
1083 { MenuItemRole, NSAccessibilityMenuItemRole }, |
|
1084 { ColumnRole, NSAccessibilityColumnRole }, |
|
1085 { RowRole, NSAccessibilityRowRole }, |
|
1086 { ToolbarRole, NSAccessibilityToolbarRole }, |
|
1087 { BusyIndicatorRole, NSAccessibilityBusyIndicatorRole }, |
|
1088 { ProgressIndicatorRole, NSAccessibilityProgressIndicatorRole }, |
|
1089 { WindowRole, NSAccessibilityWindowRole }, |
|
1090 { DrawerRole, NSAccessibilityDrawerRole }, |
|
1091 { SystemWideRole, NSAccessibilitySystemWideRole }, |
|
1092 { OutlineRole, NSAccessibilityOutlineRole }, |
|
1093 { IncrementorRole, NSAccessibilityIncrementorRole }, |
|
1094 { BrowserRole, NSAccessibilityBrowserRole }, |
|
1095 { ComboBoxRole, NSAccessibilityComboBoxRole }, |
|
1096 { SplitGroupRole, NSAccessibilitySplitGroupRole }, |
|
1097 { SplitterRole, NSAccessibilitySplitterRole }, |
|
1098 { ColorWellRole, NSAccessibilityColorWellRole }, |
|
1099 { GrowAreaRole, NSAccessibilityGrowAreaRole }, |
|
1100 { SheetRole, NSAccessibilitySheetRole }, |
|
1101 { HelpTagRole, NSAccessibilityHelpTagRole }, |
|
1102 { MatteRole, NSAccessibilityMatteRole }, |
|
1103 { RulerRole, NSAccessibilityRulerRole }, |
|
1104 { RulerMarkerRole, NSAccessibilityRulerMarkerRole }, |
|
1105 { LinkRole, NSAccessibilityLinkRole }, |
|
1106 #ifndef BUILDING_ON_TIGER |
|
1107 { DisclosureTriangleRole, NSAccessibilityDisclosureTriangleRole }, |
|
1108 { GridRole, NSAccessibilityGridRole }, |
|
1109 #endif |
|
1110 { WebCoreLinkRole, NSAccessibilityLinkRole }, |
|
1111 { ImageMapLinkRole, NSAccessibilityLinkRole }, |
|
1112 { ImageMapRole, @"AXImageMap" }, |
|
1113 { ListMarkerRole, @"AXListMarker" }, |
|
1114 { WebAreaRole, @"AXWebArea" }, |
|
1115 { HeadingRole, @"AXHeading" }, |
|
1116 { ListBoxRole, NSAccessibilityListRole }, |
|
1117 { ListBoxOptionRole, NSAccessibilityStaticTextRole }, |
|
1118 #if ACCESSIBILITY_TABLES |
|
1119 { CellRole, NSAccessibilityCellRole }, |
|
1120 #else |
|
1121 { CellRole, NSAccessibilityGroupRole }, |
|
1122 #endif |
|
1123 { TableHeaderContainerRole, NSAccessibilityGroupRole }, |
|
1124 { DefinitionListDefinitionRole, NSAccessibilityGroupRole }, |
|
1125 { DefinitionListTermRole, NSAccessibilityGroupRole }, |
|
1126 { SliderThumbRole, NSAccessibilityValueIndicatorRole }, |
|
1127 { LandmarkApplicationRole, NSAccessibilityGroupRole }, |
|
1128 { LandmarkBannerRole, NSAccessibilityGroupRole }, |
|
1129 { LandmarkComplementaryRole, NSAccessibilityGroupRole }, |
|
1130 { LandmarkContentInfoRole, NSAccessibilityGroupRole }, |
|
1131 { LandmarkMainRole, NSAccessibilityGroupRole }, |
|
1132 { LandmarkNavigationRole, NSAccessibilityGroupRole }, |
|
1133 { LandmarkSearchRole, NSAccessibilityGroupRole }, |
|
1134 { ApplicationAlertRole, NSAccessibilityGroupRole }, |
|
1135 { ApplicationAlertDialogRole, NSAccessibilityGroupRole }, |
|
1136 { ApplicationDialogRole, NSAccessibilityGroupRole }, |
|
1137 { ApplicationLogRole, NSAccessibilityGroupRole }, |
|
1138 { ApplicationMarqueeRole, NSAccessibilityGroupRole }, |
|
1139 { ApplicationStatusRole, NSAccessibilityGroupRole }, |
|
1140 { ApplicationTimerRole, NSAccessibilityGroupRole }, |
|
1141 { DocumentRole, NSAccessibilityGroupRole }, |
|
1142 { DocumentArticleRole, NSAccessibilityGroupRole }, |
|
1143 { DocumentMathRole, NSAccessibilityGroupRole }, |
|
1144 { DocumentNoteRole, NSAccessibilityGroupRole }, |
|
1145 { DocumentRegionRole, NSAccessibilityGroupRole }, |
|
1146 { UserInterfaceTooltipRole, NSAccessibilityGroupRole }, |
|
1147 { TabRole, NSAccessibilityRadioButtonRole }, |
|
1148 { TabListRole, NSAccessibilityTabGroupRole }, |
|
1149 { TabPanelRole, NSAccessibilityGroupRole }, |
|
1150 { TreeRole, NSAccessibilityOutlineRole }, |
|
1151 { TreeItemRole, NSAccessibilityRowRole }, |
|
1152 { ListItemRole, NSAccessibilityGroupRole } |
|
1153 }; |
|
1154 AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap; |
|
1155 |
|
1156 const unsigned numRoles = sizeof(roles) / sizeof(roles[0]); |
|
1157 for (unsigned i = 0; i < numRoles; ++i) |
|
1158 roleMap.set(roles[i].value, roles[i].string); |
|
1159 return roleMap; |
|
1160 } |
|
1161 |
|
1162 static NSString* roleValueToNSString(AccessibilityRole value) |
|
1163 { |
|
1164 ASSERT(value); |
|
1165 static const AccessibilityRoleMap& roleMap = createAccessibilityRoleMap(); |
|
1166 return roleMap.get(value); |
|
1167 } |
|
1168 |
|
1169 - (NSString*)role |
|
1170 { |
|
1171 if (m_object->isAttachment()) |
|
1172 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute]; |
|
1173 NSString* string = roleValueToNSString(m_object->roleValue()); |
|
1174 if (string != nil) |
|
1175 return string; |
|
1176 return NSAccessibilityUnknownRole; |
|
1177 } |
|
1178 |
|
1179 - (NSString*)subrole |
|
1180 { |
|
1181 if (m_object->isPasswordField()) |
|
1182 return NSAccessibilitySecureTextFieldSubrole; |
|
1183 |
|
1184 if (m_object->isAttachment()) { |
|
1185 NSView* attachView = [self attachmentView]; |
|
1186 if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute]) { |
|
1187 return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute]; |
|
1188 } |
|
1189 } |
|
1190 |
|
1191 if (m_object->isTreeItem()) |
|
1192 return NSAccessibilityOutlineRowSubrole; |
|
1193 |
|
1194 if (m_object->isList()) { |
|
1195 AccessibilityList* listObject = static_cast<AccessibilityList*>(m_object); |
|
1196 if (listObject->isUnorderedList() || listObject->isOrderedList()) |
|
1197 return NSAccessibilityContentListSubrole; |
|
1198 if (listObject->isDefinitionList()) |
|
1199 return NSAccessibilityDefinitionListSubrole; |
|
1200 } |
|
1201 |
|
1202 // ARIA content subroles. |
|
1203 switch (m_object->roleValue()) { |
|
1204 case LandmarkApplicationRole: |
|
1205 return @"AXLandmarkApplication"; |
|
1206 case LandmarkBannerRole: |
|
1207 return @"AXLandmarkBanner"; |
|
1208 case LandmarkComplementaryRole: |
|
1209 return @"AXLandmarkComplementary"; |
|
1210 case LandmarkContentInfoRole: |
|
1211 return @"AXLandmarkContentInfo"; |
|
1212 case LandmarkMainRole: |
|
1213 return @"AXLandmarkMain"; |
|
1214 case LandmarkNavigationRole: |
|
1215 return @"AXLandmarkNavigation"; |
|
1216 case LandmarkSearchRole: |
|
1217 return @"AXLandmarkSearch"; |
|
1218 case ApplicationAlertRole: |
|
1219 return @"AXApplicationAlert"; |
|
1220 case ApplicationAlertDialogRole: |
|
1221 return @"AXApplicationAlertDialog"; |
|
1222 case ApplicationDialogRole: |
|
1223 return @"AXApplicationDialog"; |
|
1224 case ApplicationLogRole: |
|
1225 return @"AXApplicationLog"; |
|
1226 case ApplicationMarqueeRole: |
|
1227 return @"AXApplicationMarquee"; |
|
1228 case ApplicationStatusRole: |
|
1229 return @"AXApplicationStatus"; |
|
1230 case ApplicationTimerRole: |
|
1231 return @"AXApplicationTimer"; |
|
1232 case DocumentRole: |
|
1233 return @"AXDocument"; |
|
1234 case DocumentArticleRole: |
|
1235 return @"AXDocumentArticle"; |
|
1236 case DocumentMathRole: |
|
1237 return @"AXDocumentMath"; |
|
1238 case DocumentNoteRole: |
|
1239 return @"AXDocumentNote"; |
|
1240 case DocumentRegionRole: |
|
1241 return @"AXDocumentRegion"; |
|
1242 case UserInterfaceTooltipRole: |
|
1243 return @"AXUserInterfaceTooltip"; |
|
1244 case TabPanelRole: |
|
1245 return @"AXTabPanel"; |
|
1246 case DefinitionListTermRole: |
|
1247 return @"AXTerm"; |
|
1248 case DefinitionListDefinitionRole: |
|
1249 return @"AXDefinition"; |
|
1250 // Default doesn't return anything, so roles defined below can be chosen. |
|
1251 default: |
|
1252 break; |
|
1253 } |
|
1254 |
|
1255 if (m_object->isMediaTimeline()) |
|
1256 return NSAccessibilityTimelineSubrole; |
|
1257 |
|
1258 return nil; |
|
1259 } |
|
1260 |
|
1261 - (NSString*)roleDescription |
|
1262 { |
|
1263 if (!m_object) |
|
1264 return nil; |
|
1265 |
|
1266 // attachments have the AXImage role, but a different subrole |
|
1267 if (m_object->isAttachment()) |
|
1268 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute]; |
|
1269 |
|
1270 NSString* axRole = [self role]; |
|
1271 |
|
1272 if ([axRole isEqualToString:NSAccessibilityGroupRole]) { |
|
1273 switch (m_object->roleValue()) { |
|
1274 default: |
|
1275 return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, [self subrole]); |
|
1276 case LandmarkApplicationRole: |
|
1277 return AXARIAContentGroupText(@"ARIALandmarkApplication"); |
|
1278 case LandmarkBannerRole: |
|
1279 return AXARIAContentGroupText(@"ARIALandmarkBanner"); |
|
1280 case LandmarkComplementaryRole: |
|
1281 return AXARIAContentGroupText(@"ARIALandmarkComplementary"); |
|
1282 case LandmarkContentInfoRole: |
|
1283 return AXARIAContentGroupText(@"ARIALandmarkContentInfo"); |
|
1284 case LandmarkMainRole: |
|
1285 return AXARIAContentGroupText(@"ARIALandmarkMain"); |
|
1286 case LandmarkNavigationRole: |
|
1287 return AXARIAContentGroupText(@"ARIALandmarkNavigation"); |
|
1288 case LandmarkSearchRole: |
|
1289 return AXARIAContentGroupText(@"ARIALandmarkSearch"); |
|
1290 case ApplicationAlertRole: |
|
1291 return AXARIAContentGroupText(@"ARIAApplicationAlert"); |
|
1292 case ApplicationAlertDialogRole: |
|
1293 return AXARIAContentGroupText(@"ARIAApplicationAlertDialog"); |
|
1294 case ApplicationDialogRole: |
|
1295 return AXARIAContentGroupText(@"ARIAApplicationDialog"); |
|
1296 case ApplicationLogRole: |
|
1297 return AXARIAContentGroupText(@"ARIAApplicationLog"); |
|
1298 case ApplicationMarqueeRole: |
|
1299 return AXARIAContentGroupText(@"ARIAApplicationMarquee"); |
|
1300 case ApplicationStatusRole: |
|
1301 return AXARIAContentGroupText(@"ARIAApplicationStatus"); |
|
1302 case ApplicationTimerRole: |
|
1303 return AXARIAContentGroupText(@"ARIAApplicationTimer"); |
|
1304 case DocumentRole: |
|
1305 return AXARIAContentGroupText(@"ARIADocument"); |
|
1306 case DocumentArticleRole: |
|
1307 return AXARIAContentGroupText(@"ARIADocumentArticle"); |
|
1308 case DocumentMathRole: |
|
1309 return AXARIAContentGroupText(@"ARIADocumentMath"); |
|
1310 case DocumentNoteRole: |
|
1311 return AXARIAContentGroupText(@"ARIADocumentNote"); |
|
1312 case DocumentRegionRole: |
|
1313 return AXARIAContentGroupText(@"ARIADocumentRegion"); |
|
1314 case UserInterfaceTooltipRole: |
|
1315 return AXARIAContentGroupText(@"ARIAUserInterfaceTooltip"); |
|
1316 case TabPanelRole: |
|
1317 return AXARIAContentGroupText(@"ARIATabPanel"); |
|
1318 case DefinitionListTermRole: |
|
1319 return AXDefinitionListTermText(); |
|
1320 case DefinitionListDefinitionRole: |
|
1321 return AXDefinitionListDefinitionText(); |
|
1322 } |
|
1323 } |
|
1324 |
|
1325 if ([axRole isEqualToString:@"AXWebArea"]) |
|
1326 return AXWebAreaText(); |
|
1327 |
|
1328 if ([axRole isEqualToString:@"AXLink"]) |
|
1329 return AXLinkText(); |
|
1330 |
|
1331 if ([axRole isEqualToString:@"AXListMarker"]) |
|
1332 return AXListMarkerText(); |
|
1333 |
|
1334 if ([axRole isEqualToString:@"AXImageMap"]) |
|
1335 return AXImageMapText(); |
|
1336 |
|
1337 if ([axRole isEqualToString:@"AXHeading"]) |
|
1338 return AXHeadingText(); |
|
1339 |
|
1340 // AppKit also returns AXTab for the role description for a tab item. |
|
1341 if (m_object->isTabItem()) |
|
1342 return NSAccessibilityRoleDescription(@"AXTab", nil); |
|
1343 |
|
1344 // We should try the system default role description for all other roles. |
|
1345 // If we get the same string back, then as a last resort, return unknown. |
|
1346 NSString* defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]); |
|
1347 if (![defaultRoleDescription isEqualToString:axRole]) |
|
1348 return defaultRoleDescription; |
|
1349 |
|
1350 return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil); |
|
1351 } |
|
1352 |
|
1353 // FIXME: split up this function in a better way. |
|
1354 // suggestions: Use a hash table that maps attribute names to function calls, |
|
1355 // or maybe pointers to member functions |
|
1356 - (id)accessibilityAttributeValue:(NSString*)attributeName |
|
1357 { |
|
1358 if (!m_object) |
|
1359 return nil; |
|
1360 |
|
1361 m_object->updateBackingStore(); |
|
1362 if (!m_object) |
|
1363 return nil; |
|
1364 |
|
1365 if ([attributeName isEqualToString: NSAccessibilityRoleAttribute]) |
|
1366 return [self role]; |
|
1367 |
|
1368 if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute]) |
|
1369 return [self subrole]; |
|
1370 |
|
1371 if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute]) |
|
1372 return [self roleDescription]; |
|
1373 |
|
1374 if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) { |
|
1375 if (m_object->isAccessibilityRenderObject()) { |
|
1376 FrameView* fv = static_cast<AccessibilityRenderObject*>(m_object)->frameViewIfRenderView(); |
|
1377 if (fv) |
|
1378 return fv->platformWidget(); |
|
1379 } |
|
1380 |
|
1381 // Tree item (changed to AXRows) can only report the tree (AXOutline) as its parent. |
|
1382 if (m_object->isTreeItem()) { |
|
1383 AccessibilityObject* parent = m_object->parentObjectUnignored(); |
|
1384 while (parent) { |
|
1385 if (parent->isTree()) |
|
1386 return parent->wrapper(); |
|
1387 parent = parent->parentObjectUnignored(); |
|
1388 } |
|
1389 } |
|
1390 |
|
1391 return m_object->parentObjectUnignored()->wrapper(); |
|
1392 } |
|
1393 |
|
1394 if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) { |
|
1395 if (m_object->children().isEmpty()) { |
|
1396 NSArray* children = [self renderWidgetChildren]; |
|
1397 if (children != nil) |
|
1398 return children; |
|
1399 } |
|
1400 |
|
1401 // The tree's (AXOutline) children are supposed to be its rows and columns. |
|
1402 // The ARIA spec doesn't have columns, so we just need rows. |
|
1403 if (m_object->isTree()) |
|
1404 return [self accessibilityAttributeValue:NSAccessibilityRowsAttribute]; |
|
1405 |
|
1406 // A tree item should only expose its content as its children (not its rows) |
|
1407 if (m_object->isTreeItem()) { |
|
1408 AccessibilityObject::AccessibilityChildrenVector contentCopy; |
|
1409 m_object->ariaTreeItemContent(contentCopy); |
|
1410 return convertToNSArray(contentCopy); |
|
1411 } |
|
1412 |
|
1413 return convertToNSArray(m_object->children()); |
|
1414 } |
|
1415 |
|
1416 if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) { |
|
1417 if (m_object->isListBox()) { |
|
1418 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy; |
|
1419 m_object->selectedChildren(selectedChildrenCopy); |
|
1420 return convertToNSArray(selectedChildrenCopy); |
|
1421 } |
|
1422 return nil; |
|
1423 } |
|
1424 |
|
1425 if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) { |
|
1426 if (m_object->isListBox()) { |
|
1427 AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy; |
|
1428 m_object->visibleChildren(visibleChildrenCopy); |
|
1429 return convertToNSArray(visibleChildrenCopy); |
|
1430 } |
|
1431 else if (m_object->isList()) |
|
1432 return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute]; |
|
1433 |
|
1434 return nil; |
|
1435 } |
|
1436 |
|
1437 |
|
1438 if (m_object->isWebArea()) { |
|
1439 if ([attributeName isEqualToString:@"AXLinkUIElements"]) { |
|
1440 AccessibilityObject::AccessibilityChildrenVector links; |
|
1441 static_cast<AccessibilityRenderObject*>(m_object)->getDocumentLinks(links); |
|
1442 return convertToNSArray(links); |
|
1443 } |
|
1444 if ([attributeName isEqualToString:@"AXLoaded"]) |
|
1445 return [NSNumber numberWithBool:m_object->isLoaded()]; |
|
1446 if ([attributeName isEqualToString:@"AXLayoutCount"]) |
|
1447 return [NSNumber numberWithInt:m_object->layoutCount()]; |
|
1448 if ([attributeName isEqualToString:NSAccessibilityLoadingProgressAttribute]) |
|
1449 return [NSNumber numberWithDouble:m_object->estimatedLoadingProgress()]; |
|
1450 } |
|
1451 |
|
1452 if (m_object->isTextControl()) { |
|
1453 if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) { |
|
1454 int length = m_object->textLength(); |
|
1455 if (length < 0) |
|
1456 return nil; |
|
1457 return [NSNumber numberWithUnsignedInt:length]; |
|
1458 } |
|
1459 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) { |
|
1460 String selectedText = m_object->selectedText(); |
|
1461 if (selectedText.isNull()) |
|
1462 return nil; |
|
1463 return (NSString*)selectedText; |
|
1464 } |
|
1465 if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) { |
|
1466 PlainTextRange textRange = m_object->selectedTextRange(); |
|
1467 if (textRange.isNull()) |
|
1468 return [NSValue valueWithRange:NSMakeRange(0, 0)]; |
|
1469 return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)]; |
|
1470 } |
|
1471 // TODO: Get actual visible range. <rdar://problem/4712101> |
|
1472 if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) |
|
1473 return m_object->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, m_object->textLength())]; |
|
1474 if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) { |
|
1475 // if selectionEnd > 0, then there is selected text and this question should not be answered |
|
1476 if (m_object->isPasswordField() || m_object->selectionEnd() > 0) |
|
1477 return nil; |
|
1478 int lineNumber = m_object->lineForPosition(m_object->visiblePositionForIndex(m_object->selectionStart(), true)); |
|
1479 if (lineNumber < 0) |
|
1480 return nil; |
|
1481 return [NSNumber numberWithInt:lineNumber]; |
|
1482 } |
|
1483 } |
|
1484 |
|
1485 if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) { |
|
1486 KURL url = m_object->url(); |
|
1487 if (url.isNull()) |
|
1488 return nil; |
|
1489 return (NSURL*)url; |
|
1490 } |
|
1491 |
|
1492 if ([attributeName isEqualToString: @"AXVisited"]) |
|
1493 return [NSNumber numberWithBool: m_object->isVisited()]; |
|
1494 |
|
1495 if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) { |
|
1496 if (m_object->isAttachment()) { |
|
1497 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute]) |
|
1498 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute]; |
|
1499 } |
|
1500 return m_object->title(); |
|
1501 } |
|
1502 |
|
1503 if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) { |
|
1504 if (m_object->isAttachment()) { |
|
1505 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute]) |
|
1506 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute]; |
|
1507 } |
|
1508 return m_object->accessibilityDescription(); |
|
1509 } |
|
1510 |
|
1511 if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) { |
|
1512 if (m_object->isAttachment()) { |
|
1513 if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute]) |
|
1514 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute]; |
|
1515 } |
|
1516 if (m_object->isProgressIndicator() || m_object->isSlider() || m_object->isScrollbar()) |
|
1517 return [NSNumber numberWithFloat:m_object->valueForRange()]; |
|
1518 if (m_object->hasIntValue()) |
|
1519 return [NSNumber numberWithInt:m_object->intValue()]; |
|
1520 |
|
1521 // radio groups return the selected radio button as the AXValue |
|
1522 if (m_object->isRadioGroup()) { |
|
1523 AccessibilityObject* radioButton = m_object->selectedRadioButton(); |
|
1524 if (!radioButton) |
|
1525 return nil; |
|
1526 return radioButton->wrapper(); |
|
1527 } |
|
1528 |
|
1529 if (m_object->isTabList()) { |
|
1530 AccessibilityObject* tabItem = m_object->selectedTabItem(); |
|
1531 if (!tabItem) |
|
1532 return nil; |
|
1533 return tabItem->wrapper(); |
|
1534 } |
|
1535 |
|
1536 if (m_object->isTabItem()) |
|
1537 return [NSNumber numberWithInt:m_object->isSelected()]; |
|
1538 |
|
1539 return m_object->stringValue(); |
|
1540 } |
|
1541 |
|
1542 if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute]) |
|
1543 return [NSNumber numberWithFloat:m_object->minValueForRange()]; |
|
1544 |
|
1545 if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute]) |
|
1546 return [NSNumber numberWithFloat:m_object->maxValueForRange()]; |
|
1547 |
|
1548 if ([attributeName isEqualToString: NSAccessibilityHelpAttribute]) |
|
1549 return m_object->helpText(); |
|
1550 |
|
1551 if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) |
|
1552 return [NSNumber numberWithBool: m_object->isFocused()]; |
|
1553 |
|
1554 if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute]) |
|
1555 return [NSNumber numberWithBool: m_object->isEnabled()]; |
|
1556 |
|
1557 if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) { |
|
1558 IntSize s = m_object->size(); |
|
1559 return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())]; |
|
1560 } |
|
1561 |
|
1562 if ([attributeName isEqualToString: NSAccessibilityPositionAttribute]) |
|
1563 return [self position]; |
|
1564 |
|
1565 if ([attributeName isEqualToString: NSAccessibilityWindowAttribute] || |
|
1566 [attributeName isEqualToString: NSAccessibilityTopLevelUIElementAttribute]) { |
|
1567 FrameView* fv = m_object->documentFrameView(); |
|
1568 if (fv) |
|
1569 return [fv->platformWidget() window]; |
|
1570 return nil; |
|
1571 } |
|
1572 |
|
1573 if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) { |
|
1574 AtomicString accessKey = m_object->accessKey(); |
|
1575 if (accessKey.isNull()) |
|
1576 return nil; |
|
1577 return accessKey; |
|
1578 } |
|
1579 |
|
1580 if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) { |
|
1581 if (m_object->isTabList()) { |
|
1582 AccessibilityObject::AccessibilityChildrenVector tabsChildren; |
|
1583 m_object->tabChildren(tabsChildren); |
|
1584 return convertToNSArray(tabsChildren); |
|
1585 } |
|
1586 } |
|
1587 |
|
1588 if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) { |
|
1589 // The contents of a tab list are all the children except the tabs. |
|
1590 if (m_object->isTabList()) { |
|
1591 AccessibilityObject::AccessibilityChildrenVector children = m_object->children(); |
|
1592 AccessibilityObject::AccessibilityChildrenVector tabsChildren; |
|
1593 m_object->tabChildren(tabsChildren); |
|
1594 |
|
1595 AccessibilityObject::AccessibilityChildrenVector contents; |
|
1596 unsigned childrenSize = children.size(); |
|
1597 for (unsigned k = 0; k < childrenSize; ++k) { |
|
1598 if (tabsChildren.find(children[k]) == WTF::notFound) |
|
1599 contents.append(children[k]); |
|
1600 } |
|
1601 return convertToNSArray(contents); |
|
1602 } |
|
1603 } |
|
1604 |
|
1605 if (m_object->isDataTable()) { |
|
1606 // TODO: distinguish between visible and non-visible rows |
|
1607 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] || |
|
1608 [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) { |
|
1609 return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->rows()); |
|
1610 } |
|
1611 // TODO: distinguish between visible and non-visible columns |
|
1612 if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute] || |
|
1613 [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute]) { |
|
1614 return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->columns()); |
|
1615 } |
|
1616 |
|
1617 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) { |
|
1618 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy; |
|
1619 m_object->selectedChildren(selectedChildrenCopy); |
|
1620 return convertToNSArray(selectedChildrenCopy); |
|
1621 } |
|
1622 |
|
1623 // HTML tables don't support these |
|
1624 if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute] || |
|
1625 [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute]) |
|
1626 return nil; |
|
1627 |
|
1628 if ([attributeName isEqualToString:(NSString *)kAXColumnHeaderUIElementsAttribute]) { |
|
1629 AccessibilityObject::AccessibilityChildrenVector columnHeaders; |
|
1630 static_cast<AccessibilityTable*>(m_object)->columnHeaders(columnHeaders); |
|
1631 return convertToNSArray(columnHeaders); |
|
1632 } |
|
1633 |
|
1634 if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) { |
|
1635 AccessibilityObject* headerContainer = static_cast<AccessibilityTable*>(m_object)->headerContainer(); |
|
1636 if (headerContainer) |
|
1637 return headerContainer->wrapper(); |
|
1638 return nil; |
|
1639 } |
|
1640 |
|
1641 if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) { |
|
1642 AccessibilityObject::AccessibilityChildrenVector rowHeaders; |
|
1643 static_cast<AccessibilityTable*>(m_object)->rowHeaders(rowHeaders); |
|
1644 return convertToNSArray(rowHeaders); |
|
1645 } |
|
1646 |
|
1647 if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute]) { |
|
1648 AccessibilityObject::AccessibilityChildrenVector cells; |
|
1649 static_cast<AccessibilityTable*>(m_object)->cells(cells); |
|
1650 return convertToNSArray(cells); |
|
1651 } |
|
1652 } |
|
1653 |
|
1654 if (m_object->isTableColumn()) { |
|
1655 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) |
|
1656 return [NSNumber numberWithInt:static_cast<AccessibilityTableColumn*>(m_object)->columnIndex()]; |
|
1657 |
|
1658 // rows attribute for a column is the list of all the elements in that column at each row |
|
1659 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] || |
|
1660 [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) { |
|
1661 return convertToNSArray(static_cast<AccessibilityTableColumn*>(m_object)->children()); |
|
1662 } |
|
1663 if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) { |
|
1664 AccessibilityObject* header = static_cast<AccessibilityTableColumn*>(m_object)->headerObject(); |
|
1665 if (!header) |
|
1666 return nil; |
|
1667 return header->wrapper(); |
|
1668 } |
|
1669 } |
|
1670 |
|
1671 if (m_object->isTableCell()) { |
|
1672 if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) { |
|
1673 pair<int, int> rowRange; |
|
1674 static_cast<AccessibilityTableCell*>(m_object)->rowIndexRange(rowRange); |
|
1675 return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)]; |
|
1676 } |
|
1677 if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) { |
|
1678 pair<int, int> columnRange; |
|
1679 static_cast<AccessibilityTableCell*>(m_object)->columnIndexRange(columnRange); |
|
1680 return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)]; |
|
1681 } |
|
1682 } |
|
1683 |
|
1684 if (m_object->isTree()) { |
|
1685 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) { |
|
1686 AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy; |
|
1687 m_object->selectedChildren(selectedChildrenCopy); |
|
1688 return convertToNSArray(selectedChildrenCopy); |
|
1689 } |
|
1690 if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) { |
|
1691 AccessibilityObject::AccessibilityChildrenVector rowsCopy; |
|
1692 m_object->ariaTreeRows(rowsCopy); |
|
1693 return convertToNSArray(rowsCopy); |
|
1694 } |
|
1695 |
|
1696 // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least. |
|
1697 if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute]) |
|
1698 return [NSArray array]; |
|
1699 } |
|
1700 |
|
1701 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) { |
|
1702 if (m_object->isTreeItem()) { |
|
1703 AccessibilityObject* parent = m_object->parentObject(); |
|
1704 for (; parent && !parent->isTree(); parent = parent->parentObject()) |
|
1705 { } |
|
1706 |
|
1707 if (!parent) |
|
1708 return nil; |
|
1709 |
|
1710 // Find the index of this item by iterating the parents. |
|
1711 AccessibilityObject::AccessibilityChildrenVector rowsCopy; |
|
1712 parent->ariaTreeRows(rowsCopy); |
|
1713 size_t count = rowsCopy.size(); |
|
1714 for (size_t k = 0; k < count; ++k) |
|
1715 if (rowsCopy[k]->wrapper() == self) |
|
1716 return [NSNumber numberWithUnsignedInt:k]; |
|
1717 |
|
1718 return nil; |
|
1719 } |
|
1720 if (m_object->isTableRow()) { |
|
1721 if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) |
|
1722 return [NSNumber numberWithInt:static_cast<AccessibilityTableRow*>(m_object)->rowIndex()]; |
|
1723 } |
|
1724 } |
|
1725 |
|
1726 // The rows that are considered inside this row. |
|
1727 if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) { |
|
1728 if (m_object->isTreeItem()) { |
|
1729 AccessibilityObject::AccessibilityChildrenVector rowsCopy; |
|
1730 m_object->ariaTreeItemDisclosedRows(rowsCopy); |
|
1731 return convertToNSArray(rowsCopy); |
|
1732 } else if (m_object->isARIATreeGridRow()) { |
|
1733 AccessibilityObject::AccessibilityChildrenVector rowsCopy; |
|
1734 static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedRows(rowsCopy); |
|
1735 return convertToNSArray(rowsCopy); |
|
1736 } |
|
1737 } |
|
1738 |
|
1739 // The row that contains this row. It should be the same as the first parent that is a treeitem. |
|
1740 if ([attributeName isEqualToString:NSAccessibilityDisclosedByRowAttribute]) { |
|
1741 if (m_object->isTreeItem()) { |
|
1742 AccessibilityObject* parent = m_object->parentObject(); |
|
1743 while (parent) { |
|
1744 if (parent->isTreeItem()) |
|
1745 return parent->wrapper(); |
|
1746 // If the parent is the tree itself, then this value == nil. |
|
1747 if (parent->isTree()) |
|
1748 return nil; |
|
1749 parent = parent->parentObject(); |
|
1750 } |
|
1751 return nil; |
|
1752 } else if (m_object->isARIATreeGridRow()) { |
|
1753 AccessibilityObject* row = static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedByRow(); |
|
1754 if (!row) |
|
1755 return nil; |
|
1756 return row->wrapper(); |
|
1757 } |
|
1758 } |
|
1759 |
|
1760 if ([attributeName isEqualToString:NSAccessibilityDisclosureLevelAttribute]) |
|
1761 return [NSNumber numberWithInt:m_object->hierarchicalLevel()]; |
|
1762 if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute]) |
|
1763 return [NSNumber numberWithBool:m_object->isExpanded()]; |
|
1764 |
|
1765 if ((m_object->isListBox() || m_object->isList()) && [attributeName isEqualToString:NSAccessibilityOrientationAttribute]) |
|
1766 return NSAccessibilityVerticalOrientationValue; |
|
1767 |
|
1768 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) |
|
1769 return [self textMarkerRangeForSelection]; |
|
1770 |
|
1771 if (m_object->isAccessibilityRenderObject()) { |
|
1772 RenderObject* renderer = static_cast<AccessibilityRenderObject*>(m_object)->renderer(); |
|
1773 if (!renderer) |
|
1774 return nil; |
|
1775 |
|
1776 if ([attributeName isEqualToString: @"AXStartTextMarker"]) |
|
1777 return textMarkerForVisiblePosition(startOfDocument(renderer->document())); |
|
1778 if ([attributeName isEqualToString: @"AXEndTextMarker"]) |
|
1779 return textMarkerForVisiblePosition(endOfDocument(renderer->document())); |
|
1780 |
|
1781 if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute]) |
|
1782 return [NSNumber numberWithInt:blockquoteLevel(renderer)]; |
|
1783 } else { |
|
1784 if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute]) { |
|
1785 AccessibilityObject* parent = m_object->parentObjectUnignored(); |
|
1786 if (!parent) |
|
1787 return [NSNumber numberWithInt:0]; |
|
1788 return [parent->wrapper() accessibilityAttributeValue:NSAccessibilityBlockQuoteLevelAttribute]; |
|
1789 } |
|
1790 } |
|
1791 |
|
1792 if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) { |
|
1793 AccessibilityObject::AccessibilityChildrenVector linkedUIElements; |
|
1794 m_object->linkedUIElements(linkedUIElements); |
|
1795 if (linkedUIElements.size() == 0) |
|
1796 return nil; |
|
1797 return convertToNSArray(linkedUIElements); |
|
1798 } |
|
1799 |
|
1800 if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute]) |
|
1801 return [NSNumber numberWithBool:m_object->isSelected()]; |
|
1802 |
|
1803 if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && m_object->isMenuButton()) { |
|
1804 AccessibilityObject* uiElement = static_cast<AccessibilityRenderObject*>(m_object)->menuForMenuButton(); |
|
1805 if (uiElement) |
|
1806 return [NSArray arrayWithObject:uiElement->wrapper()]; |
|
1807 } |
|
1808 |
|
1809 if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) { |
|
1810 AccessibilityObject* obj = m_object->titleUIElement(); |
|
1811 if (obj) |
|
1812 return obj->wrapper(); |
|
1813 return nil; |
|
1814 } |
|
1815 |
|
1816 if ([attributeName isEqualToString:NSAccessibilityValueDescriptionAttribute]) |
|
1817 return m_object->valueDescription(); |
|
1818 |
|
1819 if ([attributeName isEqualToString:NSAccessibilityOrientationAttribute]) { |
|
1820 AccessibilityOrientation elementOrientation = m_object->orientation(); |
|
1821 if (elementOrientation == AccessibilityOrientationVertical) |
|
1822 return NSAccessibilityVerticalOrientationValue; |
|
1823 if (elementOrientation == AccessibilityOrientationHorizontal) |
|
1824 return NSAccessibilityHorizontalOrientationValue; |
|
1825 return nil; |
|
1826 } |
|
1827 |
|
1828 if ([attributeName isEqualToString:NSAccessibilityLanguageAttribute]) |
|
1829 return m_object->language(); |
|
1830 |
|
1831 if ([attributeName isEqualToString:NSAccessibilityExpandedAttribute]) |
|
1832 return [NSNumber numberWithBool:m_object->isExpanded()]; |
|
1833 |
|
1834 if ([attributeName isEqualToString:NSAccessibilityRequiredAttribute]) |
|
1835 return [NSNumber numberWithBool:m_object->isRequired()]; |
|
1836 |
|
1837 if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) { |
|
1838 AccessibilityObject::AccessibilityChildrenVector ariaOwns; |
|
1839 m_object->ariaOwnsElements(ariaOwns); |
|
1840 return convertToNSArray(ariaOwns); |
|
1841 } |
|
1842 |
|
1843 if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute]) |
|
1844 return [NSNumber numberWithBool:m_object->isARIAGrabbed()]; |
|
1845 |
|
1846 if ([attributeName isEqualToString:NSAccessibilityDropEffectsAttribute]) { |
|
1847 Vector<String> dropEffects; |
|
1848 m_object->determineARIADropEffects(dropEffects); |
|
1849 size_t length = dropEffects.size(); |
|
1850 |
|
1851 NSMutableArray* dropEffectsArray = [NSMutableArray arrayWithCapacity:length]; |
|
1852 for (size_t i = 0; i < length; ++i) |
|
1853 [dropEffectsArray addObject:dropEffects[i]]; |
|
1854 return dropEffectsArray; |
|
1855 } |
|
1856 |
|
1857 if ([attributeName isEqualToString:NSAccessibilityHasPopupAttribute]) |
|
1858 return [NSNumber numberWithBool:m_object->ariaHasPopup()]; |
|
1859 |
|
1860 // ARIA Live region attributes. |
|
1861 if ([attributeName isEqualToString:NSAccessibilityARIALiveAttribute]) |
|
1862 return m_object->ariaLiveRegionStatus(); |
|
1863 if ([attributeName isEqualToString:NSAccessibilityARIARelevantAttribute]) |
|
1864 return m_object->ariaLiveRegionRelevant(); |
|
1865 if ([attributeName isEqualToString:NSAccessibilityARIAAtomicAttribute]) |
|
1866 return [NSNumber numberWithBool:m_object->ariaLiveRegionAtomic()]; |
|
1867 if ([attributeName isEqualToString:NSAccessibilityARIABusyAttribute]) |
|
1868 return [NSNumber numberWithBool:m_object->ariaLiveRegionBusy()]; |
|
1869 |
|
1870 // this is used only by DumpRenderTree for testing |
|
1871 if ([attributeName isEqualToString:@"AXClickPoint"]) |
|
1872 return [NSValue valueWithPoint:m_object->clickPoint()]; |
|
1873 |
|
1874 return nil; |
|
1875 } |
|
1876 |
|
1877 - (id)accessibilityFocusedUIElement |
|
1878 { |
|
1879 if (!m_object) |
|
1880 return nil; |
|
1881 |
|
1882 m_object->updateBackingStore(); |
|
1883 if (!m_object) |
|
1884 return nil; |
|
1885 |
|
1886 RefPtr<AccessibilityObject> focusedObj = m_object->focusedUIElement(); |
|
1887 |
|
1888 if (!focusedObj) |
|
1889 return nil; |
|
1890 |
|
1891 return focusedObj->wrapper(); |
|
1892 } |
|
1893 |
|
1894 - (id)accessibilityHitTest:(NSPoint)point |
|
1895 { |
|
1896 if (!m_object) |
|
1897 return nil; |
|
1898 |
|
1899 m_object->updateBackingStore(); |
|
1900 if (!m_object) |
|
1901 return nil; |
|
1902 |
|
1903 RefPtr<AccessibilityObject> axObject = m_object->doAccessibilityHitTest(IntPoint(point)); |
|
1904 if (axObject) |
|
1905 return NSAccessibilityUnignoredAncestor(axObject->wrapper()); |
|
1906 return NSAccessibilityUnignoredAncestor(self); |
|
1907 } |
|
1908 |
|
1909 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName |
|
1910 { |
|
1911 if (!m_object) |
|
1912 return nil; |
|
1913 |
|
1914 m_object->updateBackingStore(); |
|
1915 if (!m_object) |
|
1916 return nil; |
|
1917 |
|
1918 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) |
|
1919 return YES; |
|
1920 |
|
1921 if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) |
|
1922 return m_object->canSetFocusAttribute(); |
|
1923 |
|
1924 if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) |
|
1925 return m_object->canSetValueAttribute(); |
|
1926 |
|
1927 if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute]) |
|
1928 return m_object->canSetSelectedAttribute(); |
|
1929 |
|
1930 if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) |
|
1931 return m_object->canSetSelectedChildrenAttribute(); |
|
1932 |
|
1933 if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute]) |
|
1934 return m_object->canSetExpandedAttribute(); |
|
1935 |
|
1936 if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) |
|
1937 return YES; |
|
1938 |
|
1939 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute] || |
|
1940 [attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute] || |
|
1941 [attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) |
|
1942 return m_object->canSetTextRangeAttributes(); |
|
1943 |
|
1944 if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute]) |
|
1945 return YES; |
|
1946 |
|
1947 return NO; |
|
1948 } |
|
1949 |
|
1950 // accessibilityShouldUseUniqueId is an AppKit method we override so that |
|
1951 // objects will be given a unique ID, and therefore allow AppKit to know when they |
|
1952 // become obsolete (e.g. when the user navigates to a new web page, making this one |
|
1953 // unrendered but not deallocated because it is in the back/forward cache). |
|
1954 // It is important to call NSAccessibilityUnregisterUniqueIdForUIElement in the |
|
1955 // appropriate place (e.g. dealloc) to remove these non-retained references from |
|
1956 // AppKit's id mapping tables. We do this in detach by calling unregisterUniqueIdForUIElement. |
|
1957 // |
|
1958 // Registering an object is also required for observing notifications. Only registered objects can be observed. |
|
1959 - (BOOL)accessibilityIsIgnored |
|
1960 { |
|
1961 if (!m_object) |
|
1962 return nil; |
|
1963 |
|
1964 m_object->updateBackingStore(); |
|
1965 if (!m_object) |
|
1966 return nil; |
|
1967 |
|
1968 if (m_object->isAttachment()) |
|
1969 return [[self attachmentView] accessibilityIsIgnored]; |
|
1970 return m_object->accessibilityIsIgnored(); |
|
1971 } |
|
1972 |
|
1973 - (NSArray* )accessibilityParameterizedAttributeNames |
|
1974 { |
|
1975 if (!m_object) |
|
1976 return nil; |
|
1977 |
|
1978 m_object->updateBackingStore(); |
|
1979 if (!m_object) |
|
1980 return nil; |
|
1981 |
|
1982 if (m_object->isAttachment()) |
|
1983 return nil; |
|
1984 |
|
1985 static NSArray* paramAttrs = nil; |
|
1986 static NSArray* textParamAttrs = nil; |
|
1987 static NSArray* tableParamAttrs = nil; |
|
1988 if (paramAttrs == nil) { |
|
1989 paramAttrs = [[NSArray alloc] initWithObjects: |
|
1990 @"AXUIElementForTextMarker", |
|
1991 @"AXTextMarkerRangeForUIElement", |
|
1992 @"AXLineForTextMarker", |
|
1993 @"AXTextMarkerRangeForLine", |
|
1994 @"AXStringForTextMarkerRange", |
|
1995 @"AXTextMarkerForPosition", |
|
1996 @"AXBoundsForTextMarkerRange", |
|
1997 @"AXAttributedStringForTextMarkerRange", |
|
1998 @"AXTextMarkerRangeForUnorderedTextMarkers", |
|
1999 @"AXNextTextMarkerForTextMarker", |
|
2000 @"AXPreviousTextMarkerForTextMarker", |
|
2001 @"AXLeftWordTextMarkerRangeForTextMarker", |
|
2002 @"AXRightWordTextMarkerRangeForTextMarker", |
|
2003 @"AXLeftLineTextMarkerRangeForTextMarker", |
|
2004 @"AXRightLineTextMarkerRangeForTextMarker", |
|
2005 @"AXSentenceTextMarkerRangeForTextMarker", |
|
2006 @"AXParagraphTextMarkerRangeForTextMarker", |
|
2007 @"AXNextWordEndTextMarkerForTextMarker", |
|
2008 @"AXPreviousWordStartTextMarkerForTextMarker", |
|
2009 @"AXNextLineEndTextMarkerForTextMarker", |
|
2010 @"AXPreviousLineStartTextMarkerForTextMarker", |
|
2011 @"AXNextSentenceEndTextMarkerForTextMarker", |
|
2012 @"AXPreviousSentenceStartTextMarkerForTextMarker", |
|
2013 @"AXNextParagraphEndTextMarkerForTextMarker", |
|
2014 @"AXPreviousParagraphStartTextMarkerForTextMarker", |
|
2015 @"AXStyleTextMarkerRangeForTextMarker", |
|
2016 @"AXLengthForTextMarkerRange", |
|
2017 NSAccessibilityBoundsForRangeParameterizedAttribute, |
|
2018 NSAccessibilityStringForRangeParameterizedAttribute, |
|
2019 nil]; |
|
2020 } |
|
2021 |
|
2022 if (textParamAttrs == nil) { |
|
2023 NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs]; |
|
2024 [tempArray addObject:(NSString*)kAXLineForIndexParameterizedAttribute]; |
|
2025 [tempArray addObject:(NSString*)kAXRangeForLineParameterizedAttribute]; |
|
2026 [tempArray addObject:(NSString*)kAXStringForRangeParameterizedAttribute]; |
|
2027 [tempArray addObject:(NSString*)kAXRangeForPositionParameterizedAttribute]; |
|
2028 [tempArray addObject:(NSString*)kAXRangeForIndexParameterizedAttribute]; |
|
2029 [tempArray addObject:(NSString*)kAXBoundsForRangeParameterizedAttribute]; |
|
2030 [tempArray addObject:(NSString*)kAXRTFForRangeParameterizedAttribute]; |
|
2031 [tempArray addObject:(NSString*)kAXAttributedStringForRangeParameterizedAttribute]; |
|
2032 [tempArray addObject:(NSString*)kAXStyleRangeForIndexParameterizedAttribute]; |
|
2033 textParamAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
2034 [tempArray release]; |
|
2035 } |
|
2036 if (tableParamAttrs == nil) { |
|
2037 NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs]; |
|
2038 [tempArray addObject:NSAccessibilityCellForColumnAndRowParameterizedAttribute]; |
|
2039 tableParamAttrs = [[NSArray alloc] initWithArray:tempArray]; |
|
2040 [tempArray release]; |
|
2041 } |
|
2042 |
|
2043 if (m_object->isPasswordField()) |
|
2044 return [NSArray array]; |
|
2045 |
|
2046 if (!m_object->isAccessibilityRenderObject()) |
|
2047 return paramAttrs; |
|
2048 |
|
2049 if (m_object->isTextControl()) |
|
2050 return textParamAttrs; |
|
2051 |
|
2052 if (m_object->isDataTable()) |
|
2053 return tableParamAttrs; |
|
2054 |
|
2055 if (m_object->isMenuRelated()) |
|
2056 return nil; |
|
2057 |
|
2058 return paramAttrs; |
|
2059 } |
|
2060 |
|
2061 - (void)accessibilityPerformPressAction |
|
2062 { |
|
2063 if (!m_object) |
|
2064 return; |
|
2065 |
|
2066 m_object->updateBackingStore(); |
|
2067 if (!m_object) |
|
2068 return; |
|
2069 |
|
2070 if (m_object->isAttachment()) |
|
2071 [[self attachmentView] accessibilityPerformAction:NSAccessibilityPressAction]; |
|
2072 else |
|
2073 m_object->press(); |
|
2074 } |
|
2075 |
|
2076 - (void)accessibilityPerformIncrementAction |
|
2077 { |
|
2078 if (!m_object) |
|
2079 return; |
|
2080 |
|
2081 m_object->updateBackingStore(); |
|
2082 if (!m_object) |
|
2083 return; |
|
2084 |
|
2085 if (m_object->isAttachment()) |
|
2086 [[self attachmentView] accessibilityPerformAction:NSAccessibilityIncrementAction]; |
|
2087 else |
|
2088 m_object->increment(); |
|
2089 } |
|
2090 |
|
2091 - (void)accessibilityPerformDecrementAction |
|
2092 { |
|
2093 if (!m_object) |
|
2094 return; |
|
2095 |
|
2096 m_object->updateBackingStore(); |
|
2097 if (!m_object) |
|
2098 return; |
|
2099 |
|
2100 if (m_object->isAttachment()) |
|
2101 [[self attachmentView] accessibilityPerformAction:NSAccessibilityDecrementAction]; |
|
2102 else |
|
2103 m_object->decrement(); |
|
2104 } |
|
2105 |
|
2106 - (void)accessibilityPerformShowMenuAction |
|
2107 { |
|
2108 if (m_object->roleValue() == ComboBoxRole) |
|
2109 m_object->setIsExpanded(true); |
|
2110 else { |
|
2111 // This needs to be performed in an iteration of the run loop that did not start from an AX call. |
|
2112 // If it's the same run loop iteration, the menu open notification won't be sent |
|
2113 [self performSelector:@selector(accessibilityShowContextMenu) withObject:nil afterDelay:0.0]; |
|
2114 } |
|
2115 } |
|
2116 |
|
2117 - (void)accessibilityShowContextMenu |
|
2118 { |
|
2119 FrameView* frameView = m_object->documentFrameView(); |
|
2120 if (!frameView) |
|
2121 return; |
|
2122 |
|
2123 // simulate a click in the middle of the object |
|
2124 IntPoint clickPoint = m_object->clickPoint(); |
|
2125 NSPoint nsClickPoint = NSMakePoint(clickPoint.x(), clickPoint.y()); |
|
2126 |
|
2127 NSView* view = nil; |
|
2128 if (m_object->isAttachment()) |
|
2129 view = [self attachmentView]; |
|
2130 else |
|
2131 view = frameView->documentView(); |
|
2132 |
|
2133 if (!view) |
|
2134 return; |
|
2135 |
|
2136 NSPoint nsScreenPoint = [view convertPoint:nsClickPoint toView:nil]; |
|
2137 |
|
2138 // Show the contextual menu for this event. |
|
2139 NSEvent* event = [NSEvent mouseEventWithType:NSRightMouseDown location:nsScreenPoint modifierFlags:0 timestamp:0 windowNumber:[[view window] windowNumber] context:0 eventNumber:0 clickCount:1 pressure:1]; |
|
2140 NSMenu* menu = [view menuForEvent:event]; |
|
2141 |
|
2142 if (menu) |
|
2143 [NSMenu popUpContextMenu:menu withEvent:event forView:view]; |
|
2144 } |
|
2145 |
|
2146 - (void)accessibilityPerformAction:(NSString*)action |
|
2147 { |
|
2148 if (!m_object) |
|
2149 return; |
|
2150 |
|
2151 m_object->updateBackingStore(); |
|
2152 if (!m_object) |
|
2153 return; |
|
2154 |
|
2155 if ([action isEqualToString:NSAccessibilityPressAction]) |
|
2156 [self accessibilityPerformPressAction]; |
|
2157 |
|
2158 else if ([action isEqualToString:NSAccessibilityShowMenuAction]) |
|
2159 [self accessibilityPerformShowMenuAction]; |
|
2160 |
|
2161 else if ([action isEqualToString:NSAccessibilityIncrementAction]) |
|
2162 [self accessibilityPerformIncrementAction]; |
|
2163 |
|
2164 else if ([action isEqualToString:NSAccessibilityDecrementAction]) |
|
2165 [self accessibilityPerformDecrementAction]; |
|
2166 } |
|
2167 |
|
2168 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName |
|
2169 { |
|
2170 if (!m_object) |
|
2171 return; |
|
2172 |
|
2173 m_object->updateBackingStore(); |
|
2174 if (!m_object) |
|
2175 return; |
|
2176 |
|
2177 WebCoreTextMarkerRange* textMarkerRange = nil; |
|
2178 NSNumber* number = nil; |
|
2179 NSString* string = nil; |
|
2180 NSRange range = {0, 0}; |
|
2181 NSArray* array = nil; |
|
2182 |
|
2183 // decode the parameter |
|
2184 if ([[WebCoreViewFactory sharedFactory] objectIsTextMarkerRange:value]) |
|
2185 textMarkerRange = (WebCoreTextMarkerRange*) value; |
|
2186 |
|
2187 else if ([value isKindOfClass:[NSNumber self]]) |
|
2188 number = value; |
|
2189 |
|
2190 else if ([value isKindOfClass:[NSString self]]) |
|
2191 string = value; |
|
2192 |
|
2193 else if ([value isKindOfClass:[NSValue self]]) |
|
2194 range = [value rangeValue]; |
|
2195 |
|
2196 else if ([value isKindOfClass:[NSArray self]]) |
|
2197 array = value; |
|
2198 |
|
2199 // handle the command |
|
2200 if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) { |
|
2201 ASSERT(textMarkerRange); |
|
2202 m_object->setSelectedVisiblePositionRange([self visiblePositionRangeForTextMarkerRange:textMarkerRange]); |
|
2203 } else if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) { |
|
2204 ASSERT(number); |
|
2205 m_object->setFocused([number intValue] != 0); |
|
2206 } else if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) { |
|
2207 if (!string) |
|
2208 return; |
|
2209 m_object->setValue(string); |
|
2210 } else if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute]) { |
|
2211 if (!number) |
|
2212 return; |
|
2213 m_object->setSelected([number boolValue]); |
|
2214 } else if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) { |
|
2215 if (!array || m_object->roleValue() != ListBoxRole) |
|
2216 return; |
|
2217 AccessibilityObject::AccessibilityChildrenVector selectedChildren; |
|
2218 convertToVector(array, selectedChildren); |
|
2219 static_cast<AccessibilityListBox*>(m_object)->setSelectedChildren(selectedChildren); |
|
2220 } else if (m_object->isTextControl()) { |
|
2221 if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) { |
|
2222 m_object->setSelectedText(string); |
|
2223 } else if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) { |
|
2224 m_object->setSelectedTextRange(PlainTextRange(range.location, range.length)); |
|
2225 } else if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) { |
|
2226 m_object->makeRangeVisible(PlainTextRange(range.location, range.length)); |
|
2227 } |
|
2228 } else if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute]) |
|
2229 m_object->setIsExpanded([number boolValue]); |
|
2230 else if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) { |
|
2231 AccessibilityObject::AccessibilityChildrenVector selectedRows; |
|
2232 convertToVector(array, selectedRows); |
|
2233 if (m_object->isTree() || m_object->isDataTable()) |
|
2234 m_object->setSelectedRows(selectedRows); |
|
2235 } else if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute]) |
|
2236 m_object->setARIAGrabbed([number boolValue]); |
|
2237 } |
|
2238 |
|
2239 static RenderObject* rendererForView(NSView* view) |
|
2240 { |
|
2241 if (![view conformsToProtocol:@protocol(WebCoreFrameView)]) |
|
2242 return 0; |
|
2243 |
|
2244 NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view; |
|
2245 Frame* frame = [frameView _web_frame]; |
|
2246 if (!frame) |
|
2247 return 0; |
|
2248 |
|
2249 Node* node = frame->document()->ownerElement(); |
|
2250 if (!node) |
|
2251 return 0; |
|
2252 |
|
2253 return node->renderer(); |
|
2254 } |
|
2255 |
|
2256 - (id)_accessibilityParentForSubview:(NSView*)subview |
|
2257 { |
|
2258 RenderObject* renderer = rendererForView(subview); |
|
2259 if (!renderer) |
|
2260 return nil; |
|
2261 |
|
2262 AccessibilityObject* obj = renderer->document()->axObjectCache()->getOrCreate(renderer); |
|
2263 if (obj) |
|
2264 return obj->parentObjectUnignored()->wrapper(); |
|
2265 return nil; |
|
2266 } |
|
2267 |
|
2268 - (NSString*)accessibilityActionDescription:(NSString*)action |
|
2269 { |
|
2270 // we have no custom actions |
|
2271 return NSAccessibilityActionDescription(action); |
|
2272 } |
|
2273 |
|
2274 // The CFAttributedStringType representation of the text associated with this accessibility |
|
2275 // object that is specified by the given range. |
|
2276 - (NSAttributedString*)doAXAttributedStringForRange:(NSRange)range |
|
2277 { |
|
2278 PlainTextRange textRange = PlainTextRange(range.location, range.length); |
|
2279 VisiblePositionRange visiblePosRange = m_object->visiblePositionRangeForRange(textRange); |
|
2280 return [self doAXAttributedStringForTextMarkerRange:textMarkerRangeFromVisiblePositions(visiblePosRange.start, visiblePosRange.end)]; |
|
2281 } |
|
2282 |
|
2283 // The RTF representation of the text associated with this accessibility object that is |
|
2284 // specified by the given range. |
|
2285 - (NSData*)doAXRTFForRange:(NSRange)range |
|
2286 { |
|
2287 NSAttributedString* attrString = [self doAXAttributedStringForRange:range]; |
|
2288 return [attrString RTFFromRange: NSMakeRange(0, [attrString length]) documentAttributes: nil]; |
|
2289 } |
|
2290 |
|
2291 - (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter |
|
2292 { |
|
2293 WebCoreTextMarker* textMarker = nil; |
|
2294 WebCoreTextMarkerRange* textMarkerRange = nil; |
|
2295 NSNumber* number = nil; |
|
2296 NSArray* array = nil; |
|
2297 RefPtr<AccessibilityObject> uiElement = 0; |
|
2298 NSPoint point = NSZeroPoint; |
|
2299 bool pointSet = false; |
|
2300 NSRange range = {0, 0}; |
|
2301 bool rangeSet = false; |
|
2302 |
|
2303 // basic parameter validation |
|
2304 if (!m_object || !attribute || !parameter) |
|
2305 return nil; |
|
2306 |
|
2307 m_object->updateBackingStore(); |
|
2308 if (!m_object) |
|
2309 return nil; |
|
2310 |
|
2311 // common parameter type check/casting. Nil checks in handlers catch wrong type case. |
|
2312 // NOTE: This assumes nil is not a valid parameter, because it is indistinguishable from |
|
2313 // a parameter of the wrong type. |
|
2314 if ([[WebCoreViewFactory sharedFactory] objectIsTextMarker:parameter]) |
|
2315 textMarker = (WebCoreTextMarker*) parameter; |
|
2316 |
|
2317 else if ([[WebCoreViewFactory sharedFactory] objectIsTextMarkerRange:parameter]) |
|
2318 textMarkerRange = (WebCoreTextMarkerRange*) parameter; |
|
2319 |
|
2320 else if ([parameter isKindOfClass:[AccessibilityObjectWrapper self]]) |
|
2321 uiElement = [(AccessibilityObjectWrapper*)parameter accessibilityObject]; |
|
2322 |
|
2323 else if ([parameter isKindOfClass:[NSNumber self]]) |
|
2324 number = parameter; |
|
2325 |
|
2326 else if ([parameter isKindOfClass:[NSArray self]]) |
|
2327 array = parameter; |
|
2328 |
|
2329 else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSPoint)) == 0) { |
|
2330 pointSet = true; |
|
2331 point = [(NSValue*)parameter pointValue]; |
|
2332 |
|
2333 } else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSRange)) == 0) { |
|
2334 rangeSet = true; |
|
2335 range = [(NSValue*)parameter rangeValue]; |
|
2336 } else { |
|
2337 // Attribute type is not supported. Allow super to handle. |
|
2338 return [super accessibilityAttributeValue:attribute forParameter:parameter]; |
|
2339 } |
|
2340 |
|
2341 // dispatch |
|
2342 if ([attribute isEqualToString: @"AXUIElementForTextMarker"]) { |
|
2343 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2344 return m_object->accessibilityObjectForPosition(visiblePos)->wrapper(); |
|
2345 } |
|
2346 |
|
2347 if ([attribute isEqualToString: @"AXTextMarkerRangeForUIElement"]) { |
|
2348 VisiblePositionRange vpRange = uiElement.get()->visiblePositionRange(); |
|
2349 return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); |
|
2350 } |
|
2351 |
|
2352 if ([attribute isEqualToString: @"AXLineForTextMarker"]) { |
|
2353 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2354 return [NSNumber numberWithUnsignedInt:m_object->lineForPosition(visiblePos)]; |
|
2355 } |
|
2356 |
|
2357 if ([attribute isEqualToString: @"AXTextMarkerRangeForLine"]) { |
|
2358 VisiblePositionRange vpRange = m_object->visiblePositionRangeForLine([number intValue]); |
|
2359 return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); |
|
2360 } |
|
2361 |
|
2362 if ([attribute isEqualToString: @"AXStringForTextMarkerRange"]) { |
|
2363 VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange]; |
|
2364 return m_object->stringForVisiblePositionRange(visiblePosRange); |
|
2365 } |
|
2366 |
|
2367 if ([attribute isEqualToString: @"AXTextMarkerForPosition"]) { |
|
2368 IntPoint webCorePoint = IntPoint(point); |
|
2369 return pointSet ? textMarkerForVisiblePosition(m_object->visiblePositionForPoint(webCorePoint)) : nil; |
|
2370 } |
|
2371 |
|
2372 if ([attribute isEqualToString: @"AXBoundsForTextMarkerRange"]) { |
|
2373 VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange]; |
|
2374 NSRect rect = m_object->boundsForVisiblePositionRange(visiblePosRange); |
|
2375 return [NSValue valueWithRect:rect]; |
|
2376 } |
|
2377 |
|
2378 if ([attribute isEqualToString:NSAccessibilityBoundsForRangeParameterizedAttribute]) { |
|
2379 VisiblePosition start = m_object->visiblePositionForIndex(range.location); |
|
2380 VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length); |
|
2381 if (start.isNull() || end.isNull()) |
|
2382 return nil; |
|
2383 NSRect rect = m_object->boundsForVisiblePositionRange(VisiblePositionRange(start, end)); |
|
2384 return [NSValue valueWithRect:rect]; |
|
2385 } |
|
2386 |
|
2387 if ([attribute isEqualToString:NSAccessibilityStringForRangeParameterizedAttribute]) { |
|
2388 VisiblePosition start = m_object->visiblePositionForIndex(range.location); |
|
2389 VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length); |
|
2390 if (start.isNull() || end.isNull()) |
|
2391 return nil; |
|
2392 return m_object->stringForVisiblePositionRange(VisiblePositionRange(start, end)); |
|
2393 } |
|
2394 |
|
2395 if ([attribute isEqualToString: @"AXAttributedStringForTextMarkerRange"]) |
|
2396 return [self doAXAttributedStringForTextMarkerRange:textMarkerRange]; |
|
2397 |
|
2398 if ([attribute isEqualToString: @"AXTextMarkerRangeForUnorderedTextMarkers"]) { |
|
2399 if ([array count] < 2) |
|
2400 return nil; |
|
2401 |
|
2402 WebCoreTextMarker* textMarker1 = (WebCoreTextMarker*) [array objectAtIndex:0]; |
|
2403 WebCoreTextMarker* textMarker2 = (WebCoreTextMarker*) [array objectAtIndex:1]; |
|
2404 if (![[WebCoreViewFactory sharedFactory] objectIsTextMarker:textMarker1] |
|
2405 || ![[WebCoreViewFactory sharedFactory] objectIsTextMarker:textMarker2]) |
|
2406 return nil; |
|
2407 |
|
2408 VisiblePosition visiblePos1 = visiblePositionForTextMarker(textMarker1); |
|
2409 VisiblePosition visiblePos2 = visiblePositionForTextMarker(textMarker2); |
|
2410 VisiblePositionRange vpRange = m_object->visiblePositionRangeForUnorderedPositions(visiblePos1, visiblePos2); |
|
2411 return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); |
|
2412 } |
|
2413 |
|
2414 if ([attribute isEqualToString: @"AXNextTextMarkerForTextMarker"]) { |
|
2415 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2416 return textMarkerForVisiblePosition(m_object->nextVisiblePosition(visiblePos)); |
|
2417 } |
|
2418 |
|
2419 if ([attribute isEqualToString: @"AXPreviousTextMarkerForTextMarker"]) { |
|
2420 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2421 return textMarkerForVisiblePosition(m_object->previousVisiblePosition(visiblePos)); |
|
2422 } |
|
2423 |
|
2424 if ([attribute isEqualToString: @"AXLeftWordTextMarkerRangeForTextMarker"]) { |
|
2425 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2426 VisiblePositionRange vpRange = m_object->positionOfLeftWord(visiblePos); |
|
2427 return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); |
|
2428 } |
|
2429 |
|
2430 if ([attribute isEqualToString: @"AXRightWordTextMarkerRangeForTextMarker"]) { |
|
2431 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2432 VisiblePositionRange vpRange = m_object->positionOfRightWord(visiblePos); |
|
2433 return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); |
|
2434 } |
|
2435 |
|
2436 if ([attribute isEqualToString: @"AXLeftLineTextMarkerRangeForTextMarker"]) { |
|
2437 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2438 VisiblePositionRange vpRange = m_object->leftLineVisiblePositionRange(visiblePos); |
|
2439 return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); |
|
2440 } |
|
2441 |
|
2442 if ([attribute isEqualToString: @"AXRightLineTextMarkerRangeForTextMarker"]) { |
|
2443 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2444 VisiblePositionRange vpRange = m_object->rightLineVisiblePositionRange(visiblePos); |
|
2445 return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); |
|
2446 } |
|
2447 |
|
2448 if ([attribute isEqualToString: @"AXSentenceTextMarkerRangeForTextMarker"]) { |
|
2449 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2450 VisiblePositionRange vpRange = m_object->sentenceForPosition(visiblePos); |
|
2451 return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); |
|
2452 } |
|
2453 |
|
2454 if ([attribute isEqualToString: @"AXParagraphTextMarkerRangeForTextMarker"]) { |
|
2455 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2456 VisiblePositionRange vpRange = m_object->paragraphForPosition(visiblePos); |
|
2457 return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); |
|
2458 } |
|
2459 |
|
2460 if ([attribute isEqualToString: @"AXNextWordEndTextMarkerForTextMarker"]) { |
|
2461 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2462 return textMarkerForVisiblePosition(m_object->nextWordEnd(visiblePos)); |
|
2463 } |
|
2464 |
|
2465 if ([attribute isEqualToString: @"AXPreviousWordStartTextMarkerForTextMarker"]) { |
|
2466 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2467 return textMarkerForVisiblePosition(m_object->previousWordStart(visiblePos)); |
|
2468 } |
|
2469 |
|
2470 if ([attribute isEqualToString: @"AXNextLineEndTextMarkerForTextMarker"]) { |
|
2471 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2472 return textMarkerForVisiblePosition(m_object->nextLineEndPosition(visiblePos)); |
|
2473 } |
|
2474 |
|
2475 if ([attribute isEqualToString: @"AXPreviousLineStartTextMarkerForTextMarker"]) { |
|
2476 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2477 return textMarkerForVisiblePosition(m_object->previousLineStartPosition(visiblePos)); |
|
2478 } |
|
2479 |
|
2480 if ([attribute isEqualToString: @"AXNextSentenceEndTextMarkerForTextMarker"]) { |
|
2481 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2482 return textMarkerForVisiblePosition(m_object->nextSentenceEndPosition(visiblePos)); |
|
2483 } |
|
2484 |
|
2485 if ([attribute isEqualToString: @"AXPreviousSentenceStartTextMarkerForTextMarker"]) { |
|
2486 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2487 return textMarkerForVisiblePosition(m_object->previousSentenceStartPosition(visiblePos)); |
|
2488 } |
|
2489 |
|
2490 if ([attribute isEqualToString: @"AXNextParagraphEndTextMarkerForTextMarker"]) { |
|
2491 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2492 return textMarkerForVisiblePosition(m_object->nextParagraphEndPosition(visiblePos)); |
|
2493 } |
|
2494 |
|
2495 if ([attribute isEqualToString: @"AXPreviousParagraphStartTextMarkerForTextMarker"]) { |
|
2496 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2497 return textMarkerForVisiblePosition(m_object->previousParagraphStartPosition(visiblePos)); |
|
2498 } |
|
2499 |
|
2500 if ([attribute isEqualToString: @"AXStyleTextMarkerRangeForTextMarker"]) { |
|
2501 VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker); |
|
2502 VisiblePositionRange vpRange = m_object->styleRangeForPosition(visiblePos); |
|
2503 return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); |
|
2504 } |
|
2505 |
|
2506 if ([attribute isEqualToString: @"AXLengthForTextMarkerRange"]) { |
|
2507 VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange]; |
|
2508 int length = m_object->lengthForVisiblePositionRange(visiblePosRange); |
|
2509 if (length < 0) |
|
2510 return nil; |
|
2511 return [NSNumber numberWithInt:length]; |
|
2512 } |
|
2513 |
|
2514 if (m_object->isDataTable()) { |
|
2515 if ([attribute isEqualToString:NSAccessibilityCellForColumnAndRowParameterizedAttribute]) { |
|
2516 if (array == nil || [array count] != 2) |
|
2517 return nil; |
|
2518 AccessibilityTableCell* cell = static_cast<AccessibilityTable*>(m_object)->cellForColumnAndRow([[array objectAtIndex:0] unsignedIntValue], [[array objectAtIndex:1] unsignedIntValue]); |
|
2519 if (!cell) |
|
2520 return nil; |
|
2521 |
|
2522 return cell->wrapper(); |
|
2523 } |
|
2524 } |
|
2525 |
|
2526 if (m_object->isTextControl()) { |
|
2527 if ([attribute isEqualToString: (NSString *)kAXLineForIndexParameterizedAttribute]) { |
|
2528 int lineNumber = m_object->doAXLineForIndex([number intValue]); |
|
2529 if (lineNumber < 0) |
|
2530 return nil; |
|
2531 return [NSNumber numberWithUnsignedInt:lineNumber]; |
|
2532 } |
|
2533 |
|
2534 if ([attribute isEqualToString: (NSString *)kAXRangeForLineParameterizedAttribute]) { |
|
2535 PlainTextRange textRange = m_object->doAXRangeForLine([number intValue]); |
|
2536 return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)]; |
|
2537 } |
|
2538 |
|
2539 if ([attribute isEqualToString: (NSString*)kAXStringForRangeParameterizedAttribute]) { |
|
2540 PlainTextRange plainTextRange = PlainTextRange(range.location, range.length); |
|
2541 return rangeSet ? (id)(m_object->doAXStringForRange(plainTextRange)) : nil; |
|
2542 } |
|
2543 |
|
2544 if ([attribute isEqualToString: (NSString*)kAXRangeForPositionParameterizedAttribute]) { |
|
2545 if (!pointSet) |
|
2546 return nil; |
|
2547 IntPoint webCorePoint = IntPoint(point); |
|
2548 PlainTextRange textRange = m_object->doAXRangeForPosition(webCorePoint); |
|
2549 return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)]; |
|
2550 } |
|
2551 |
|
2552 if ([attribute isEqualToString: (NSString*)kAXRangeForIndexParameterizedAttribute]) { |
|
2553 PlainTextRange textRange = m_object->doAXRangeForIndex([number intValue]); |
|
2554 return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)]; |
|
2555 } |
|
2556 |
|
2557 if ([attribute isEqualToString: (NSString*)kAXBoundsForRangeParameterizedAttribute]) { |
|
2558 if (!rangeSet) |
|
2559 return nil; |
|
2560 PlainTextRange plainTextRange = PlainTextRange(range.location, range.length); |
|
2561 NSRect rect = m_object->doAXBoundsForRange(plainTextRange); |
|
2562 return [NSValue valueWithRect:rect]; |
|
2563 } |
|
2564 |
|
2565 if ([attribute isEqualToString: (NSString*)kAXRTFForRangeParameterizedAttribute]) |
|
2566 return rangeSet ? [self doAXRTFForRange:range] : nil; |
|
2567 |
|
2568 if ([attribute isEqualToString: (NSString*)kAXAttributedStringForRangeParameterizedAttribute]) |
|
2569 return rangeSet ? [self doAXAttributedStringForRange:range] : nil; |
|
2570 |
|
2571 if ([attribute isEqualToString: (NSString*)kAXStyleRangeForIndexParameterizedAttribute]) { |
|
2572 PlainTextRange textRange = m_object->doAXStyleRangeForIndex([number intValue]); |
|
2573 return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)]; |
|
2574 } |
|
2575 } |
|
2576 |
|
2577 // There are some parameters that super handles that are not explicitly returned by the list of the element's attributes. |
|
2578 // In that case it must be passed to super. |
|
2579 return [super accessibilityAttributeValue:attribute forParameter:parameter]; |
|
2580 } |
|
2581 |
|
2582 - (BOOL)accessibilityShouldUseUniqueId |
|
2583 { |
|
2584 return m_object->accessibilityShouldUseUniqueId(); |
|
2585 } |
|
2586 |
|
2587 // API that AppKit uses for faster access |
|
2588 - (NSUInteger)accessibilityIndexOfChild:(id)child |
|
2589 { |
|
2590 if (!m_object) |
|
2591 return NSNotFound; |
|
2592 |
|
2593 m_object->updateBackingStore(); |
|
2594 if (!m_object) |
|
2595 return NSNotFound; |
|
2596 |
|
2597 // Tree objects return their rows as their children. We can use the original method |
|
2598 // here, because we won't gain any speed up. |
|
2599 if (m_object->isTree()) |
|
2600 return [super accessibilityIndexOfChild:child]; |
|
2601 |
|
2602 const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children(); |
|
2603 |
|
2604 if (children.isEmpty()) |
|
2605 return [[self renderWidgetChildren] indexOfObject:child]; |
|
2606 |
|
2607 unsigned count = children.size(); |
|
2608 for (unsigned k = 0; k < count; ++k) { |
|
2609 AccessibilityObjectWrapper* wrapper = children[k]->wrapper(); |
|
2610 if (wrapper == child || (children[k]->isAttachment() && [wrapper attachmentView] == child)) |
|
2611 return k; |
|
2612 } |
|
2613 |
|
2614 return NSNotFound; |
|
2615 } |
|
2616 |
|
2617 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute |
|
2618 { |
|
2619 if (!m_object) |
|
2620 return 0; |
|
2621 |
|
2622 m_object->updateBackingStore(); |
|
2623 if (!m_object) |
|
2624 return 0; |
|
2625 |
|
2626 if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) { |
|
2627 // Tree items object returns a different set of children than those that are in children() |
|
2628 // because an AXOutline (the mac role is becomes) has some odd stipulations. |
|
2629 if (m_object->isTree() || m_object->isTreeItem()) |
|
2630 return [[self accessibilityAttributeValue:NSAccessibilityChildrenAttribute] count]; |
|
2631 |
|
2632 const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children(); |
|
2633 if (children.isEmpty()) |
|
2634 return [[self renderWidgetChildren] count]; |
|
2635 |
|
2636 return children.size(); |
|
2637 } |
|
2638 |
|
2639 return [super accessibilityArrayAttributeCount:attribute]; |
|
2640 } |
|
2641 |
|
2642 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount |
|
2643 { |
|
2644 if (!m_object) |
|
2645 return nil; |
|
2646 |
|
2647 m_object->updateBackingStore(); |
|
2648 if (!m_object) |
|
2649 return nil; |
|
2650 |
|
2651 if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) { |
|
2652 if (m_object->children().isEmpty()) { |
|
2653 NSArray *children = [self renderWidgetChildren]; |
|
2654 if (!children) |
|
2655 return nil; |
|
2656 |
|
2657 NSUInteger childCount = [children count]; |
|
2658 if (index >= childCount) |
|
2659 return nil; |
|
2660 |
|
2661 NSUInteger arrayLength = min(childCount - index, maxCount); |
|
2662 return [children subarrayWithRange:NSMakeRange(index, arrayLength)]; |
|
2663 } else if (m_object->isTree()) { |
|
2664 // Tree objects return their rows as their children. We can use the original method in this case. |
|
2665 return [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount]; |
|
2666 } |
|
2667 |
|
2668 const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children(); |
|
2669 unsigned childCount = children.size(); |
|
2670 if (index >= childCount) |
|
2671 return nil; |
|
2672 |
|
2673 unsigned available = min(childCount - index, maxCount); |
|
2674 |
|
2675 NSMutableArray *subarray = [NSMutableArray arrayWithCapacity:available]; |
|
2676 for (unsigned added = 0; added < available; ++index, ++added) { |
|
2677 AccessibilityObjectWrapper* wrapper = children[index]->wrapper(); |
|
2678 if (wrapper) { |
|
2679 // The attachment view should be returned, otherwise AX palindrome errors occur. |
|
2680 if (children[index]->isAttachment() && [wrapper attachmentView]) |
|
2681 [subarray addObject:[wrapper attachmentView]]; |
|
2682 else |
|
2683 [subarray addObject:wrapper]; |
|
2684 } |
|
2685 } |
|
2686 |
|
2687 return subarray; |
|
2688 } |
|
2689 |
|
2690 return [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount]; |
|
2691 } |
|
2692 |
|
2693 // This is set by DRT when it wants to listen for notifications. |
|
2694 static BOOL accessibilityShouldRepostNotifications; |
|
2695 - (void)accessibilitySetShouldRepostNotifications:(BOOL)repost |
|
2696 { |
|
2697 accessibilityShouldRepostNotifications = repost; |
|
2698 } |
|
2699 |
|
2700 - (void)accessibilityPostedNotification:(NSString *)notificationName |
|
2701 { |
|
2702 if (accessibilityShouldRepostNotifications) { |
|
2703 NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:notificationName, @"notificationName", nil]; |
|
2704 [[NSNotificationCenter defaultCenter] postNotificationName:@"AXDRTNotification" object:nil userInfo:userInfo]; |
|
2705 } |
|
2706 } |
|
2707 |
|
2708 @end |
|
2709 |
|
2710 #endif // HAVE(ACCESSIBILITY) |