Source/WebCore: AccessibilityController should support listening to notifications...
[WebKit-https.git] / Tools / DumpRenderTree / mac / AccessibilityUIElementMac.mm
1 /*
2  * Copyright (C) 2008 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #import "config.h"
27 #import "DumpRenderTree.h"
28 #import "AccessibilityNotificationHandler.h"
29 #import "AccessibilityUIElement.h"
30
31 #import <Foundation/Foundation.h>
32 #import <JavaScriptCore/JSRetainPtr.h>
33 #import <JavaScriptCore/JSStringRef.h>
34 #import <JavaScriptCore/JSStringRefCF.h>
35 #import <WebKit/WebFrame.h>
36 #import <WebKit/WebHTMLView.h>
37 #import <WebKit/WebTypesInternal.h>
38 #import <wtf/RetainPtr.h>
39 #import <wtf/Vector.h>
40
41
42 #ifndef NSAccessibilityOwnsAttribute
43 #define NSAccessibilityOwnsAttribute @"AXOwns"
44 #endif
45
46 #ifndef NSAccessibilityGrabbedAttribute
47 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
48 #endif
49
50 #ifndef NSAccessibilityDropEffectsAttribute
51 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
52 #endif
53
54 // If an unsupported attribute is passed in, it will raise an accessibility exception. These are usually caught by the Accessibility Runtime to inform
55 // the AX client app of the error. However, DRT is the AX client app, so it must catch these exceptions.
56 #define BEGIN_AX_OBJC_EXCEPTIONS @try {
57 #define END_AX_OBJC_EXCEPTIONS } @catch(NSException *e) { if (![[e name] isEqualToString:NSAccessibilityException]) @throw; }
58
59
60 typedef void (*AXPostedNotificationCallback)(id element, NSString* notification, void* context);
61
62 @interface NSObject (WebKitAccessibilityAdditions)
63 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
64 - (NSUInteger)accessibilityIndexOfChild:(id)child;
65 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute;
66 @end
67
68 @interface NSString (JSStringRefAdditions)
69 + (NSString *)stringWithJSStringRef:(JSStringRef)jsStringRef;
70 - (JSStringRef)createJSStringRef;
71 @end
72
73 @implementation NSString (JSStringRefAdditions)
74
75 + (NSString *)stringWithJSStringRef:(JSStringRef)jsStringRef
76 {
77     if (!jsStringRef)
78         return NULL;
79     
80     CFStringRef cfString = JSStringCopyCFString(kCFAllocatorDefault, jsStringRef);
81     return [(NSString *)cfString autorelease];
82 }
83
84 - (JSStringRef)createJSStringRef
85 {
86     return JSStringCreateWithCFString((CFStringRef)self);
87 }
88
89 @end
90
91 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
92     : m_element(element)
93     , m_notificationHandler(0)
94 {
95     // FIXME: ap@webkit.org says ObjC objects need to be CFRetained/CFRelease to be GC-compliant on the mac.
96     [m_element retain];
97 }
98
99 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
100     : m_element(other.m_element)
101     , m_notificationHandler(0)
102 {
103     [m_element retain];
104 }
105
106 AccessibilityUIElement::~AccessibilityUIElement()
107 {
108     // The notification handler should be nil because removeNotificationListener() should have been called in the test.
109     ASSERT(!m_notificationHandler);
110     [m_element release];
111 }
112
113 static NSString* descriptionOfValue(id valueObject, id focusedAccessibilityObject)
114 {
115     if (!valueObject)
116         return NULL;
117
118     if ([valueObject isKindOfClass:[NSArray class]])
119         return [NSString stringWithFormat:@"<array of size %d>", [(NSArray*)valueObject count]];
120
121     if ([valueObject isKindOfClass:[NSNumber class]])
122         return [(NSNumber*)valueObject stringValue];
123
124     if ([valueObject isKindOfClass:[NSValue class]]) {
125         NSString* type = [NSString stringWithCString:[valueObject objCType] encoding:NSASCIIStringEncoding];
126         NSValue* value = (NSValue*)valueObject;
127         if ([type rangeOfString:@"NSRect"].length > 0)
128             return [NSString stringWithFormat:@"NSRect: %@", NSStringFromRect([value rectValue])];
129         if ([type rangeOfString:@"NSPoint"].length > 0)
130             return [NSString stringWithFormat:@"NSPoint: %@", NSStringFromPoint([value pointValue])];
131         if ([type rangeOfString:@"NSSize"].length > 0)
132             return [NSString stringWithFormat:@"NSSize: %@", NSStringFromSize([value sizeValue])];
133         if ([type rangeOfString:@"NSRange"].length > 0)
134             return [NSString stringWithFormat:@"NSRange: %@", NSStringFromRange([value rangeValue])];
135     }
136
137     // Strip absolute URL paths
138     NSString* description = [valueObject description];
139     NSRange range = [description rangeOfString:@"LayoutTests"];
140     if (range.length)
141         return [description substringFromIndex:range.location];
142
143     // Strip pointer locations
144     if ([description rangeOfString:@"0x"].length) {
145         NSString* role = [focusedAccessibilityObject accessibilityAttributeValue:NSAccessibilityRoleAttribute];
146         NSString* title = [focusedAccessibilityObject accessibilityAttributeValue:NSAccessibilityTitleAttribute];
147         if ([title length])
148             return [NSString stringWithFormat:@"<%@: '%@'>", role, title];
149         return [NSString stringWithFormat:@"<%@>", role];
150     }
151     
152     return [valueObject description];
153 }
154
155 static NSString* attributesOfElement(id accessibilityObject)
156 {
157     NSArray* supportedAttributes = [accessibilityObject accessibilityAttributeNames];
158
159     NSMutableString* attributesString = [NSMutableString string];
160     for (NSUInteger i = 0; i < [supportedAttributes count]; ++i) {
161         NSString* attribute = [supportedAttributes objectAtIndex:i];
162         
163         // Right now, position provides useless and screen-specific information, so we do not
164         // want to include it for the sake of universally passing tests.
165         if ([attribute isEqualToString:@"AXPosition"])
166             continue;
167         
168         // accessibilityAttributeValue: can throw an if an attribute is not returned.
169         // For DumpRenderTree's purpose, we should ignore those exceptions
170         BEGIN_AX_OBJC_EXCEPTIONS
171         id valueObject = [accessibilityObject accessibilityAttributeValue:attribute];
172         NSString* value = descriptionOfValue(valueObject, accessibilityObject);
173         [attributesString appendFormat:@"%@: %@\n", attribute, value];
174         END_AX_OBJC_EXCEPTIONS
175     }
176     
177     return attributesString;
178 }
179
180 static JSStringRef concatenateAttributeAndValue(NSString* attribute, NSString* value)
181 {
182     Vector<UniChar> buffer([attribute length]);
183     [attribute getCharacters:buffer.data()];
184     buffer.append(':');
185     buffer.append(' ');
186
187     Vector<UniChar> valueBuffer([value length]);
188     [value getCharacters:valueBuffer.data()];
189     buffer.append(valueBuffer);
190
191     return JSStringCreateWithCharacters(buffer.data(), buffer.size());
192 }
193
194 static void convertNSArrayToVector(NSArray* array, Vector<AccessibilityUIElement>& elementVector)
195 {
196     NSUInteger count = [array count];
197     for (NSUInteger i = 0; i < count; ++i)
198         elementVector.append(AccessibilityUIElement([array objectAtIndex:i]));
199 }
200
201 static JSStringRef descriptionOfElements(Vector<AccessibilityUIElement>& elementVector)
202 {
203     NSMutableString* allElementString = [NSMutableString string];
204     size_t size = elementVector.size();
205     for (size_t i = 0; i < size; ++i) {
206         NSString* attributes = attributesOfElement(elementVector[i].platformUIElement());
207         [allElementString appendFormat:@"%@\n------------\n", attributes];
208     }
209     
210     return [allElementString createJSStringRef];
211 }
212
213 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elementVector)
214 {
215     BEGIN_AX_OBJC_EXCEPTIONS
216     NSArray* linkedElements = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
217     convertNSArrayToVector(linkedElements, elementVector);
218     END_AX_OBJC_EXCEPTIONS
219 }
220
221 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>& elementVector)
222 {
223     BEGIN_AX_OBJC_EXCEPTIONS
224     NSArray* linkElements = [m_element accessibilityAttributeValue:@"AXLinkUIElements"];
225     convertNSArrayToVector(linkElements, elementVector);
226     END_AX_OBJC_EXCEPTIONS
227 }
228
229 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& elementVector)
230 {
231     BEGIN_AX_OBJC_EXCEPTIONS
232     NSArray* children = [m_element accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
233     convertNSArrayToVector(children, elementVector);
234     END_AX_OBJC_EXCEPTIONS
235 }
236
237 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned location, unsigned length)
238 {
239     BEGIN_AX_OBJC_EXCEPTIONS
240     NSArray* children = [m_element accessibilityArrayAttributeValues:NSAccessibilityChildrenAttribute index:location maxCount:length];
241     convertNSArrayToVector(children, elementVector);
242     END_AX_OBJC_EXCEPTIONS
243 }
244
245 int AccessibilityUIElement::childrenCount()
246 {
247     Vector<AccessibilityUIElement> children;
248     getChildren(children);
249     
250     return children.size();
251 }
252
253 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
254 {
255     id element = [m_element accessibilityHitTest:NSMakePoint(x, y)];
256     if (!element)
257         return nil;
258     
259     return AccessibilityUIElement(element); 
260 }
261
262 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
263 {
264     return [m_element accessibilityIndexOfChild:element->platformUIElement()];
265 }
266
267 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
268 {
269     Vector<AccessibilityUIElement> children;
270     getChildrenWithRange(children, index, 1);
271
272     if (children.size() == 1)
273         return children[0];
274     return 0;
275 }
276
277 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
278 {
279     BEGIN_AX_OBJC_EXCEPTIONS
280     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
281     if (index < [objects count])
282         return [objects objectAtIndex:index];
283     END_AX_OBJC_EXCEPTIONS
284     
285     return 0;
286 }
287
288 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
289 {
290     BEGIN_AX_OBJC_EXCEPTIONS
291     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityOwnsAttribute];
292     if (index < [objects count])
293         return [objects objectAtIndex:index];
294     END_AX_OBJC_EXCEPTIONS
295     
296     return 0;
297 }
298
299 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
300 {
301     BEGIN_AX_OBJC_EXCEPTIONS
302     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
303     if (index < [objects count])
304         return [objects objectAtIndex:index];
305     END_AX_OBJC_EXCEPTIONS
306     
307     return 0;
308 }
309
310 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
311 {
312     BEGIN_AX_OBJC_EXCEPTIONS
313     NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilityDisclosedRowsAttribute];
314     if (index < [rows count])
315         return [rows objectAtIndex:index];
316     END_AX_OBJC_EXCEPTIONS
317
318     return 0;
319 }
320
321 AccessibilityUIElement AccessibilityUIElement::selectedChildAtIndex(unsigned index) const
322 {
323     BEGIN_AX_OBJC_EXCEPTIONS
324     NSArray* array = [m_element accessibilityAttributeValue:NSAccessibilitySelectedChildrenAttribute];
325     if (index < [array count])
326         return [array objectAtIndex:index];
327     END_AX_OBJC_EXCEPTIONS
328     
329     return 0;
330 }
331
332 unsigned AccessibilityUIElement::selectedChildrenCount() const
333 {
334     BEGIN_AX_OBJC_EXCEPTIONS
335     return [m_element accessibilityArrayAttributeCount:NSAccessibilitySelectedChildrenAttribute];
336     END_AX_OBJC_EXCEPTIONS
337
338     return 0;
339 }
340
341 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
342 {
343     BEGIN_AX_OBJC_EXCEPTIONS
344     NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilitySelectedRowsAttribute];
345     if (index < [rows count])
346         return [rows objectAtIndex:index];
347     END_AX_OBJC_EXCEPTIONS
348     
349     return 0;
350 }
351
352 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
353 {
354     BEGIN_AX_OBJC_EXCEPTIONS
355     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityTitleUIElementAttribute];
356     if (accessibilityObject)
357         return AccessibilityUIElement(accessibilityObject);
358     END_AX_OBJC_EXCEPTIONS
359     
360     return 0;
361 }
362
363 AccessibilityUIElement AccessibilityUIElement::parentElement()
364 {
365     BEGIN_AX_OBJC_EXCEPTIONS
366     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityParentAttribute];
367     if (accessibilityObject)
368         return AccessibilityUIElement(accessibilityObject);
369     END_AX_OBJC_EXCEPTIONS
370     
371     return 0;
372 }
373
374 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
375 {
376     BEGIN_AX_OBJC_EXCEPTIONS
377     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityDisclosedByRowAttribute];
378     if (accessibilityObject)
379         return AccessibilityUIElement(accessibilityObject);
380     END_AX_OBJC_EXCEPTIONS
381     
382     return 0;
383 }
384
385 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
386 {
387     Vector<AccessibilityUIElement> linkedElements;
388     getLinkedUIElements(linkedElements);
389     return descriptionOfElements(linkedElements);
390 }
391
392 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
393 {
394     Vector<AccessibilityUIElement> linkElements;
395     getDocumentLinks(linkElements);
396     return descriptionOfElements(linkElements);
397 }
398
399 JSStringRef AccessibilityUIElement::attributesOfChildren()
400 {
401     Vector<AccessibilityUIElement> children;
402     getChildren(children);
403     return descriptionOfElements(children);
404 }
405
406 JSStringRef AccessibilityUIElement::allAttributes()
407 {
408     NSString* attributes = attributesOfElement(m_element);
409     return [attributes createJSStringRef];
410 }
411
412 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
413 {
414     BEGIN_AX_OBJC_EXCEPTIONS
415     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
416     if ([value isKindOfClass:[NSString class]])
417         return [value createJSStringRef];
418     END_AX_OBJC_EXCEPTIONS
419
420     return 0;
421 }
422
423 AccessibilityUIElement AccessibilityUIElement::uiElementAttributeValue(JSStringRef attribute) const
424 {
425     BEGIN_AX_OBJC_EXCEPTIONS
426     id uiElement = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
427     return AccessibilityUIElement(uiElement);
428     END_AX_OBJC_EXCEPTIONS
429     
430     return 0;
431 }
432
433
434 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
435 {
436     BEGIN_AX_OBJC_EXCEPTIONS
437     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
438     if ([value isKindOfClass:[NSNumber class]])
439         return [value doubleValue];
440     END_AX_OBJC_EXCEPTIONS
441     
442     return 0;
443 }
444
445 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
446 {
447     BEGIN_AX_OBJC_EXCEPTIONS
448     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
449     if ([value isKindOfClass:[NSNumber class]])
450         return [value boolValue];
451     END_AX_OBJC_EXCEPTIONS
452     
453     return false;
454 }
455
456 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
457 {
458     BEGIN_AX_OBJC_EXCEPTIONS
459     return [m_element accessibilityIsAttributeSettable:[NSString stringWithJSStringRef:attribute]];
460     END_AX_OBJC_EXCEPTIONS
461     
462     return false;
463 }
464
465 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
466 {
467     BEGIN_AX_OBJC_EXCEPTIONS
468     return [[m_element accessibilityAttributeNames] containsObject:[NSString stringWithJSStringRef:attribute]];
469     END_AX_OBJC_EXCEPTIONS
470     
471     return false;
472 }
473
474 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
475 {
476     NSArray* supportedParameterizedAttributes = [m_element accessibilityParameterizedAttributeNames];
477     
478     NSMutableString* attributesString = [NSMutableString string];
479     for (NSUInteger i = 0; i < [supportedParameterizedAttributes count]; ++i) {
480         [attributesString appendFormat:@"%@\n", [supportedParameterizedAttributes objectAtIndex:i]];
481     }
482     
483     return [attributesString createJSStringRef];
484 }
485
486 JSStringRef AccessibilityUIElement::role()
487 {
488     BEGIN_AX_OBJC_EXCEPTIONS
489     NSString *role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityRoleAttribute], m_element);
490     return concatenateAttributeAndValue(@"AXRole", role);
491     END_AX_OBJC_EXCEPTIONS
492     
493     return 0;
494 }
495
496 JSStringRef AccessibilityUIElement::subrole()
497 {
498     BEGIN_AX_OBJC_EXCEPTIONS
499     NSString* role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilitySubroleAttribute], m_element);
500     return concatenateAttributeAndValue(@"AXSubrole", role);
501     END_AX_OBJC_EXCEPTIONS
502
503     return 0;
504 }
505
506 JSStringRef AccessibilityUIElement::roleDescription()
507 {
508     BEGIN_AX_OBJC_EXCEPTIONS
509     NSString* role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute], m_element);
510     return concatenateAttributeAndValue(@"AXRoleDescription", role);
511     END_AX_OBJC_EXCEPTIONS
512     
513     return 0;
514 }
515
516 JSStringRef AccessibilityUIElement::title()
517 {
518     BEGIN_AX_OBJC_EXCEPTIONS
519     NSString* title = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityTitleAttribute], m_element);
520     return concatenateAttributeAndValue(@"AXTitle", title);
521     END_AX_OBJC_EXCEPTIONS
522
523     return 0;
524 }
525
526 JSStringRef AccessibilityUIElement::description()
527 {
528     BEGIN_AX_OBJC_EXCEPTIONS
529     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityDescriptionAttribute], m_element);
530     return concatenateAttributeAndValue(@"AXDescription", description);
531     END_AX_OBJC_EXCEPTIONS
532
533     return 0;
534 }
535
536 JSStringRef AccessibilityUIElement::orientation() const
537 {
538     BEGIN_AX_OBJC_EXCEPTIONS
539     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityOrientationAttribute], m_element);
540     return concatenateAttributeAndValue(@"AXOrientation", description);    
541     END_AX_OBJC_EXCEPTIONS
542
543     return 0;
544 }
545
546 JSStringRef AccessibilityUIElement::stringValue()
547 {
548     BEGIN_AX_OBJC_EXCEPTIONS
549     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityValueAttribute], m_element);
550     return concatenateAttributeAndValue(@"AXValue", description);
551     END_AX_OBJC_EXCEPTIONS
552
553     return 0;
554 }
555
556 JSStringRef AccessibilityUIElement::language()
557 {
558     BEGIN_AX_OBJC_EXCEPTIONS
559     id description = descriptionOfValue([m_element accessibilityAttributeValue:@"AXLanguage"], m_element);
560     return concatenateAttributeAndValue(@"AXLanguage", description);
561     END_AX_OBJC_EXCEPTIONS
562
563     return 0;
564 }
565
566 JSStringRef AccessibilityUIElement::helpText() const
567 {
568     BEGIN_AX_OBJC_EXCEPTIONS
569     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityHelpAttribute], m_element);
570     return concatenateAttributeAndValue(@"AXHelp", description);
571     END_AX_OBJC_EXCEPTIONS
572     
573     return 0;
574 }
575
576 double AccessibilityUIElement::x()
577 {
578     BEGIN_AX_OBJC_EXCEPTIONS
579     NSValue* positionValue = [m_element accessibilityAttributeValue:NSAccessibilityPositionAttribute];
580     return static_cast<double>([positionValue pointValue].x);    
581     END_AX_OBJC_EXCEPTIONS
582     
583     return 0.0f;
584 }
585
586 double AccessibilityUIElement::y()
587 {
588     BEGIN_AX_OBJC_EXCEPTIONS
589     NSValue* positionValue = [m_element accessibilityAttributeValue:NSAccessibilityPositionAttribute];
590     return static_cast<double>([positionValue pointValue].y);    
591     END_AX_OBJC_EXCEPTIONS
592     
593     return 0.0f;
594 }
595
596 double AccessibilityUIElement::width()
597 {
598     BEGIN_AX_OBJC_EXCEPTIONS
599     NSValue* sizeValue = [m_element accessibilityAttributeValue:NSAccessibilitySizeAttribute];
600     return static_cast<double>([sizeValue sizeValue].width);
601     END_AX_OBJC_EXCEPTIONS
602     
603     return 0.0f;
604 }
605
606 double AccessibilityUIElement::height()
607 {
608     BEGIN_AX_OBJC_EXCEPTIONS
609     NSValue* sizeValue = [m_element accessibilityAttributeValue:NSAccessibilitySizeAttribute];
610     return static_cast<double>([sizeValue sizeValue].height);
611     END_AX_OBJC_EXCEPTIONS
612     
613     return 0.0f;
614 }
615
616 double AccessibilityUIElement::clickPointX()
617 {
618     BEGIN_AX_OBJC_EXCEPTIONS
619     NSValue* positionValue = [m_element accessibilityAttributeValue:@"AXClickPoint"];
620     return static_cast<double>([positionValue pointValue].x);        
621     END_AX_OBJC_EXCEPTIONS
622     
623     return 0.0f;
624 }
625
626 double AccessibilityUIElement::clickPointY()
627 {
628     BEGIN_AX_OBJC_EXCEPTIONS
629     NSValue* positionValue = [m_element accessibilityAttributeValue:@"AXClickPoint"];
630     return static_cast<double>([positionValue pointValue].y);
631     END_AX_OBJC_EXCEPTIONS
632     
633     return 0.0f;
634 }
635
636 double AccessibilityUIElement::intValue() const
637 {
638     BEGIN_AX_OBJC_EXCEPTIONS
639     id value = [m_element accessibilityAttributeValue:NSAccessibilityValueAttribute];
640     if ([value isKindOfClass:[NSNumber class]])
641         return [(NSNumber*)value doubleValue]; 
642     END_AX_OBJC_EXCEPTIONS
643
644     return 0.0f;
645 }
646
647 double AccessibilityUIElement::minValue()
648 {
649     BEGIN_AX_OBJC_EXCEPTIONS
650     id value = [m_element accessibilityAttributeValue:NSAccessibilityMinValueAttribute];
651     if ([value isKindOfClass:[NSNumber class]])
652         return [(NSNumber*)value doubleValue]; 
653     END_AX_OBJC_EXCEPTIONS
654
655     return 0.0f;
656 }
657
658 double AccessibilityUIElement::maxValue()
659 {
660     BEGIN_AX_OBJC_EXCEPTIONS
661     id value = [m_element accessibilityAttributeValue:NSAccessibilityMaxValueAttribute];
662     if ([value isKindOfClass:[NSNumber class]])
663         return [(NSNumber*)value doubleValue]; 
664     END_AX_OBJC_EXCEPTIONS
665
666     return 0.0;
667 }
668
669 JSStringRef AccessibilityUIElement::valueDescription()
670 {
671     BEGIN_AX_OBJC_EXCEPTIONS
672     NSString* valueDescription = [m_element accessibilityAttributeValue:NSAccessibilityValueDescriptionAttribute];
673     if ([valueDescription isKindOfClass:[NSString class]])
674          return [valueDescription createJSStringRef];
675
676     END_AX_OBJC_EXCEPTIONS
677     return 0;
678 }
679
680 int AccessibilityUIElement::insertionPointLineNumber()
681 {
682     BEGIN_AX_OBJC_EXCEPTIONS
683     id value = [m_element accessibilityAttributeValue:NSAccessibilityInsertionPointLineNumberAttribute];
684     if ([value isKindOfClass:[NSNumber class]])
685         return [(NSNumber *)value intValue]; 
686     END_AX_OBJC_EXCEPTIONS
687     
688     return -1;
689 }
690
691 bool AccessibilityUIElement::isActionSupported(JSStringRef action)
692 {
693     BEGIN_AX_OBJC_EXCEPTIONS
694     NSArray* actions = [m_element accessibilityActionNames];
695     return [actions containsObject:[NSString stringWithJSStringRef:action]];
696     END_AX_OBJC_EXCEPTIONS
697     
698     return false;
699 }
700
701 bool AccessibilityUIElement::isEnabled()
702 {
703     BEGIN_AX_OBJC_EXCEPTIONS
704     id value = [m_element accessibilityAttributeValue:NSAccessibilityEnabledAttribute];
705     if ([value isKindOfClass:[NSNumber class]])
706         return [value boolValue];
707     END_AX_OBJC_EXCEPTIONS
708     
709     return false;
710 }
711
712 bool AccessibilityUIElement::isRequired() const
713 {
714     BEGIN_AX_OBJC_EXCEPTIONS
715     id value = [m_element accessibilityAttributeValue:@"AXRequired"];
716     if ([value isKindOfClass:[NSNumber class]])
717         return [value boolValue];
718     END_AX_OBJC_EXCEPTIONS
719     
720     return false;
721 }
722
723 bool AccessibilityUIElement::isFocused() const
724 {
725     // FIXME: implement
726     return false;
727 }
728
729 bool AccessibilityUIElement::isSelected() const
730 {
731     BEGIN_AX_OBJC_EXCEPTIONS
732     id value = [m_element accessibilityAttributeValue:NSAccessibilitySelectedAttribute];
733     if ([value isKindOfClass:[NSNumber class]])
734         return [value boolValue];
735     END_AX_OBJC_EXCEPTIONS
736     
737     return false;
738 }
739
740 bool AccessibilityUIElement::isExpanded() const
741 {
742     BEGIN_AX_OBJC_EXCEPTIONS
743     id value = [m_element accessibilityAttributeValue:NSAccessibilityExpandedAttribute];
744     if ([value isKindOfClass:[NSNumber class]])
745         return [value boolValue];
746     END_AX_OBJC_EXCEPTIONS
747     
748     return false;
749 }
750
751 bool AccessibilityUIElement::isChecked() const
752 {
753     // On the Mac, intValue()==1 if a a checkable control is checked.
754     return intValue() == 1;
755 }
756
757 int AccessibilityUIElement::hierarchicalLevel() const
758 {
759     BEGIN_AX_OBJC_EXCEPTIONS
760     id value = [m_element accessibilityAttributeValue:NSAccessibilityDisclosureLevelAttribute];
761     if ([value isKindOfClass:[NSNumber class]])
762         return [value intValue];
763     END_AX_OBJC_EXCEPTIONS
764
765     return 0;
766 }
767
768 JSStringRef AccessibilityUIElement::speak()
769 {
770     BEGIN_AX_OBJC_EXCEPTIONS
771     id value = [m_element accessibilityAttributeValue:@"AXDRTSpeechAttribute"];
772     if ([value isKindOfClass:[NSString class]])
773         return [value createJSStringRef];
774     END_AX_OBJC_EXCEPTIONS
775         
776     return 0;
777 }
778
779 bool AccessibilityUIElement::ariaIsGrabbed() const
780 {
781     BEGIN_AX_OBJC_EXCEPTIONS
782     id value = [m_element accessibilityAttributeValue:NSAccessibilityGrabbedAttribute];
783     if ([value isKindOfClass:[NSNumber class]])
784         return [value boolValue];
785     END_AX_OBJC_EXCEPTIONS
786
787     return false;
788 }
789
790 JSStringRef AccessibilityUIElement::ariaDropEffects() const
791 {
792     BEGIN_AX_OBJC_EXCEPTIONS
793     id value = [m_element accessibilityAttributeValue:NSAccessibilityDropEffectsAttribute];
794     if (![value isKindOfClass:[NSArray class]])
795         return 0;
796
797     NSMutableString* dropEffects = [NSMutableString string];
798     NSInteger length = [value count];
799     for (NSInteger k = 0; k < length; ++k) {
800         [dropEffects appendString:[value objectAtIndex:k]];
801         if (k < length - 1)
802             [dropEffects appendString:@","];
803     }
804     
805     return [dropEffects createJSStringRef];
806     END_AX_OBJC_EXCEPTIONS
807     
808     return 0;
809 }
810
811 // parameterized attributes
812 int AccessibilityUIElement::lineForIndex(int index)
813 {
814     BEGIN_AX_OBJC_EXCEPTIONS
815     id value = [m_element accessibilityAttributeValue:NSAccessibilityLineForIndexParameterizedAttribute forParameter:[NSNumber numberWithInt:index]];
816     if ([value isKindOfClass:[NSNumber class]])
817         return [(NSNumber *)value intValue]; 
818     END_AX_OBJC_EXCEPTIONS
819
820     return -1;
821 }
822
823 JSStringRef AccessibilityUIElement::rangeForLine(int line)
824 {
825     BEGIN_AX_OBJC_EXCEPTIONS
826     id value = [m_element accessibilityAttributeValue:NSAccessibilityRangeForLineParameterizedAttribute forParameter:[NSNumber numberWithInt:line]];
827     if ([value isKindOfClass:[NSValue class]]) {
828         return [NSStringFromRange([value rangeValue]) createJSStringRef];
829     }
830     END_AX_OBJC_EXCEPTIONS
831     
832     return 0;
833 }
834
835 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
836 {
837     NSRange range = NSMakeRange(location, length);
838     BEGIN_AX_OBJC_EXCEPTIONS
839     id value = [m_element accessibilityAttributeValue:NSAccessibilityBoundsForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
840     NSRect rect = NSMakeRect(0,0,0,0);
841     if ([value isKindOfClass:[NSValue class]])
842         rect = [value rectValue]; 
843     
844     // don't return position information because it is platform dependent
845     NSMutableString* boundsDescription = [NSMutableString stringWithFormat:@"{{%f, %f}, {%f, %f}}",-1.0f,-1.0f,rect.size.width,rect.size.height];
846     return [boundsDescription createJSStringRef];
847     END_AX_OBJC_EXCEPTIONS
848     
849     return 0;
850 }
851
852 JSStringRef AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
853 {
854     NSRange range = NSMakeRange(location, length);
855     BEGIN_AX_OBJC_EXCEPTIONS
856     id string = [m_element accessibilityAttributeValue:NSAccessibilityStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
857     if (![string isKindOfClass:[NSString class]])
858         return 0;
859     
860     return [string createJSStringRef];
861     END_AX_OBJC_EXCEPTIONS
862     
863     return 0;
864 }
865
866 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned location, unsigned length)
867 {
868     NSRange range = NSMakeRange(location, length);
869     BEGIN_AX_OBJC_EXCEPTIONS
870     NSAttributedString* string = [m_element accessibilityAttributeValue:NSAccessibilityAttributedStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
871     if (![string isKindOfClass:[NSAttributedString class]])
872         return 0;
873     
874     NSString* stringWithAttrs = [string description];
875     return [stringWithAttrs createJSStringRef];
876     END_AX_OBJC_EXCEPTIONS
877     
878     return 0;
879 }
880
881 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
882 {
883     NSRange range = NSMakeRange(location, length);
884     BEGIN_AX_OBJC_EXCEPTIONS
885     NSAttributedString* string = [m_element accessibilityAttributeValue:NSAccessibilityAttributedStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
886     if (![string isKindOfClass:[NSAttributedString class]])
887         return false;
888
889     NSDictionary* attrs = [string attributesAtIndex:0 effectiveRange:nil];
890     if([[attrs objectForKey:NSAccessibilityMisspelledTextAttribute] boolValue])
891         return true;    
892     END_AX_OBJC_EXCEPTIONS
893     
894     return false;
895 }
896
897 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(AccessibilityUIElement* startElement, bool isDirectionNext, JSStringRef searchKey, JSStringRef searchText)
898 {
899     BEGIN_AX_OBJC_EXCEPTIONS
900     NSMutableDictionary* parameter = [NSMutableDictionary dictionary];
901     [parameter setObject:(isDirectionNext) ? @"AXDirectionNext" : @"AXDirectionPrevious" forKey:@"AXDirection"];
902     [parameter setObject:[NSNumber numberWithInt:1] forKey:@"AXResultsLimit"];
903     if (startElement)
904         [parameter setObject:(id)startElement->platformUIElement() forKey:@"AXStartElement"];
905     if (searchKey)
906         [parameter setObject:[NSString stringWithJSStringRef:searchKey] forKey:@"AXSearchKey"];
907     if (searchText)
908         [parameter setObject:[NSString stringWithJSStringRef:searchText] forKey:@"AXSearchText"];
909     
910     id uiElement = [[m_element accessibilityAttributeValue:@"AXUIElementsForSearchPredicate" forParameter:parameter] lastObject];
911     return AccessibilityUIElement(uiElement);
912     END_AX_OBJC_EXCEPTIONS
913     
914     return 0;
915 }
916
917 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
918 {
919     // not yet defined in AppKit... odd
920     BEGIN_AX_OBJC_EXCEPTIONS
921     NSArray* columnHeadersArray = [m_element accessibilityAttributeValue:@"AXColumnHeaderUIElements"];
922     Vector<AccessibilityUIElement> columnHeadersVector;
923     convertNSArrayToVector(columnHeadersArray, columnHeadersVector);
924     return descriptionOfElements(columnHeadersVector);
925     END_AX_OBJC_EXCEPTIONS
926     
927     return 0;
928 }
929
930 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
931 {
932     BEGIN_AX_OBJC_EXCEPTIONS
933     NSArray* rowHeadersArray = [m_element accessibilityAttributeValue:@"AXRowHeaderUIElements"];
934     Vector<AccessibilityUIElement> rowHeadersVector;
935     convertNSArrayToVector(rowHeadersArray, rowHeadersVector);
936     return descriptionOfElements(rowHeadersVector);
937     END_AX_OBJC_EXCEPTIONS
938     
939     return 0;
940 }
941
942 JSStringRef AccessibilityUIElement::attributesOfColumns()
943 {
944     BEGIN_AX_OBJC_EXCEPTIONS
945     NSArray* columnsArray = [m_element accessibilityAttributeValue:NSAccessibilityColumnsAttribute];
946     Vector<AccessibilityUIElement> columnsVector;
947     convertNSArrayToVector(columnsArray, columnsVector);
948     return descriptionOfElements(columnsVector);
949     END_AX_OBJC_EXCEPTIONS
950     
951     return 0;
952 }
953
954 JSStringRef AccessibilityUIElement::attributesOfRows()
955 {
956     BEGIN_AX_OBJC_EXCEPTIONS
957     NSArray* rowsArray = [m_element accessibilityAttributeValue:NSAccessibilityRowsAttribute];
958     Vector<AccessibilityUIElement> rowsVector;
959     convertNSArrayToVector(rowsArray, rowsVector);
960     return descriptionOfElements(rowsVector);
961     END_AX_OBJC_EXCEPTIONS
962     
963     return 0;
964 }
965
966 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
967 {
968     BEGIN_AX_OBJC_EXCEPTIONS
969     NSArray* cellsArray = [m_element accessibilityAttributeValue:@"AXVisibleCells"];
970     Vector<AccessibilityUIElement> cellsVector;
971     convertNSArrayToVector(cellsArray, cellsVector);
972     return descriptionOfElements(cellsVector);
973     END_AX_OBJC_EXCEPTIONS
974     
975     return 0;
976 }
977
978 JSStringRef AccessibilityUIElement::attributesOfHeader()
979 {
980     BEGIN_AX_OBJC_EXCEPTIONS
981     id headerObject = [m_element accessibilityAttributeValue:NSAccessibilityHeaderAttribute];
982     if (!headerObject)
983         return [@"" createJSStringRef];
984     
985     Vector<AccessibilityUIElement> headerVector;
986     headerVector.append(headerObject);
987     return descriptionOfElements(headerVector);
988     END_AX_OBJC_EXCEPTIONS
989     
990     return 0;
991 }
992
993 int AccessibilityUIElement::rowCount()
994 {
995     BEGIN_AX_OBJC_EXCEPTIONS
996     return [m_element accessibilityArrayAttributeCount:NSAccessibilityRowsAttribute];
997     END_AX_OBJC_EXCEPTIONS
998     
999     return 0;
1000 }
1001
1002 int AccessibilityUIElement::columnCount()
1003 {
1004     BEGIN_AX_OBJC_EXCEPTIONS
1005     return [m_element accessibilityArrayAttributeCount:NSAccessibilityColumnsAttribute];
1006     END_AX_OBJC_EXCEPTIONS
1007     
1008     return 0;
1009 }
1010
1011 int AccessibilityUIElement::indexInTable()
1012 {
1013     BEGIN_AX_OBJC_EXCEPTIONS
1014     NSNumber* indexNumber = [m_element accessibilityAttributeValue:NSAccessibilityIndexAttribute];
1015     if (indexNumber)
1016         return [indexNumber intValue];
1017     END_AX_OBJC_EXCEPTIONS
1018
1019     return -1;
1020 }
1021
1022 JSStringRef AccessibilityUIElement::rowIndexRange()
1023 {
1024     NSRange range = NSMakeRange(0,0);
1025     BEGIN_AX_OBJC_EXCEPTIONS
1026     NSValue* indexRange = [m_element accessibilityAttributeValue:@"AXRowIndexRange"];
1027     if (indexRange)
1028         range = [indexRange rangeValue];
1029     NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%d, %d}",range.location, range.length];
1030     return [rangeDescription createJSStringRef];
1031     END_AX_OBJC_EXCEPTIONS
1032     
1033     return 0;
1034 }
1035
1036 JSStringRef AccessibilityUIElement::columnIndexRange()
1037 {
1038     NSRange range = NSMakeRange(0,0);
1039     BEGIN_AX_OBJC_EXCEPTIONS
1040     NSNumber* indexRange = [m_element accessibilityAttributeValue:@"AXColumnIndexRange"];
1041     if (indexRange)
1042         range = [indexRange rangeValue];
1043     NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%d, %d}",range.location, range.length];
1044     return [rangeDescription createJSStringRef];    
1045     END_AX_OBJC_EXCEPTIONS
1046     
1047     return 0;
1048 }
1049
1050 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row)
1051 {
1052     NSArray *colRowArray = [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:col], [NSNumber numberWithUnsignedInt:row], nil];
1053     BEGIN_AX_OBJC_EXCEPTIONS
1054     return [m_element accessibilityAttributeValue:@"AXCellForColumnAndRow" forParameter:colRowArray];
1055     END_AX_OBJC_EXCEPTIONS    
1056
1057     return 0;
1058 }
1059
1060 AccessibilityUIElement AccessibilityUIElement::horizontalScrollbar() const
1061 {
1062     BEGIN_AX_OBJC_EXCEPTIONS
1063     return AccessibilityUIElement([m_element accessibilityAttributeValue:NSAccessibilityHorizontalScrollBarAttribute]);
1064     END_AX_OBJC_EXCEPTIONS    
1065     
1066     return 0;
1067 }
1068
1069 AccessibilityUIElement AccessibilityUIElement::verticalScrollbar() const
1070 {
1071     BEGIN_AX_OBJC_EXCEPTIONS
1072     return AccessibilityUIElement([m_element accessibilityAttributeValue:NSAccessibilityVerticalScrollBarAttribute]);
1073     END_AX_OBJC_EXCEPTIONS        
1074
1075     return 0;
1076 }
1077
1078 JSStringRef AccessibilityUIElement::selectedTextRange()
1079 {
1080     NSRange range = NSMakeRange(NSNotFound, 0);
1081     BEGIN_AX_OBJC_EXCEPTIONS
1082     NSValue *indexRange = [m_element accessibilityAttributeValue:NSAccessibilitySelectedTextRangeAttribute];
1083     if (indexRange)
1084         range = [indexRange rangeValue];
1085     NSMutableString *rangeDescription = [NSMutableString stringWithFormat:@"{%d, %d}",range.location, range.length];
1086     return [rangeDescription createJSStringRef];    
1087     END_AX_OBJC_EXCEPTIONS
1088     
1089     return 0;
1090 }
1091
1092 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
1093 {
1094     NSRange textRange = NSMakeRange(location, length);
1095     NSValue *textRangeValue = [NSValue valueWithRange:textRange];
1096     BEGIN_AX_OBJC_EXCEPTIONS
1097     [m_element accessibilitySetValue:textRangeValue forAttribute:NSAccessibilitySelectedTextRangeAttribute];
1098     END_AX_OBJC_EXCEPTIONS
1099 }
1100
1101 void AccessibilityUIElement::increment()
1102 {
1103     BEGIN_AX_OBJC_EXCEPTIONS
1104     [m_element accessibilityPerformAction:NSAccessibilityIncrementAction];
1105     END_AX_OBJC_EXCEPTIONS
1106 }
1107
1108 void AccessibilityUIElement::decrement()
1109 {
1110     BEGIN_AX_OBJC_EXCEPTIONS
1111     [m_element accessibilityPerformAction:NSAccessibilityDecrementAction];
1112     END_AX_OBJC_EXCEPTIONS
1113 }
1114
1115 void AccessibilityUIElement::showMenu()
1116 {
1117     BEGIN_AX_OBJC_EXCEPTIONS
1118     [m_element accessibilityPerformAction:NSAccessibilityShowMenuAction];
1119     END_AX_OBJC_EXCEPTIONS
1120 }
1121
1122 void AccessibilityUIElement::press()
1123 {
1124     BEGIN_AX_OBJC_EXCEPTIONS
1125     [m_element accessibilityPerformAction:NSAccessibilityPressAction];
1126     END_AX_OBJC_EXCEPTIONS
1127 }
1128
1129 void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement* element) const
1130 {
1131     BEGIN_AX_OBJC_EXCEPTIONS
1132     NSArray* array = [NSArray arrayWithObject:element->platformUIElement()];
1133     [m_element accessibilitySetValue:array forAttribute:NSAccessibilitySelectedChildrenAttribute];
1134     END_AX_OBJC_EXCEPTIONS    
1135 }
1136
1137 JSStringRef AccessibilityUIElement::accessibilityValue() const
1138 {
1139     // FIXME: implement
1140     return JSStringCreateWithCharacters(0, 0);
1141 }
1142
1143 JSStringRef AccessibilityUIElement::documentEncoding()
1144 {
1145     return JSStringCreateWithCharacters(0, 0);
1146 }
1147
1148 JSStringRef AccessibilityUIElement::documentURI()
1149 {
1150     return JSStringCreateWithCharacters(0, 0);
1151 }
1152
1153 JSStringRef AccessibilityUIElement::url()
1154 {
1155     BEGIN_AX_OBJC_EXCEPTIONS
1156     NSURL *url = [m_element accessibilityAttributeValue:NSAccessibilityURLAttribute];
1157     return [[url absoluteString] createJSStringRef];    
1158     END_AX_OBJC_EXCEPTIONS
1159     
1160     return nil;
1161 }
1162
1163 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
1164 {
1165     if (!functionCallback)
1166         return false;
1167  
1168     // Mac programmers should not be adding more than one notification listener per element.
1169     // Other platforms may be different.
1170     if (m_notificationHandler)
1171         return false;
1172     m_notificationHandler = [[AccessibilityNotificationHandler alloc] init];
1173     [m_notificationHandler setPlatformElement:platformUIElement()];
1174     [m_notificationHandler setCallback:functionCallback];
1175     [m_notificationHandler startObserving];
1176
1177     return true;
1178 }
1179
1180 void AccessibilityUIElement::removeNotificationListener()
1181 {
1182     // Mac programmers should not be trying to remove a listener that's already removed.
1183     ASSERT(m_notificationHandler);
1184
1185     [m_notificationHandler release];
1186     m_notificationHandler = nil;
1187 }
1188
1189 bool AccessibilityUIElement::isFocusable() const
1190 {
1191     bool result = false;
1192     BEGIN_AX_OBJC_EXCEPTIONS
1193     result = [m_element accessibilityIsAttributeSettable:NSAccessibilityFocusedAttribute];
1194     END_AX_OBJC_EXCEPTIONS
1195     
1196     return result;
1197 }
1198
1199 bool AccessibilityUIElement::isSelectable() const
1200 {
1201     // FIXME: implement
1202     return false;
1203 }
1204
1205 bool AccessibilityUIElement::isMultiSelectable() const
1206 {
1207     // FIXME: implement
1208     return false;
1209 }
1210
1211 bool AccessibilityUIElement::isSelectedOptionActive() const
1212 {
1213     // FIXME: implement
1214     return false;
1215 }
1216
1217 bool AccessibilityUIElement::isVisible() const
1218 {
1219     // FIXME: implement
1220     return false;
1221 }
1222
1223 bool AccessibilityUIElement::isOffScreen() const
1224 {
1225     // FIXME: implement
1226     return false;
1227 }
1228
1229 bool AccessibilityUIElement::isCollapsed() const
1230 {
1231     // FIXME: implement
1232     return false;
1233 }
1234
1235 bool AccessibilityUIElement::isIgnored() const
1236 {
1237     BOOL result = NO;
1238     BEGIN_AX_OBJC_EXCEPTIONS
1239     result = [m_element accessibilityIsIgnored];
1240     END_AX_OBJC_EXCEPTIONS
1241     return result;
1242 }
1243
1244 bool AccessibilityUIElement::hasPopup() const
1245 {
1246     BEGIN_AX_OBJC_EXCEPTIONS
1247     id value = [m_element accessibilityAttributeValue:@"AXHasPopup"];
1248     if ([value isKindOfClass:[NSNumber class]])
1249         return [value boolValue];
1250     END_AX_OBJC_EXCEPTIONS
1251
1252     return false;
1253 }
1254
1255 void AccessibilityUIElement::takeFocus()
1256 {
1257     // FIXME: implement
1258 }
1259
1260 void AccessibilityUIElement::takeSelection()
1261 {
1262     // FIXME: implement
1263 }
1264
1265 void AccessibilityUIElement::addSelection()
1266 {
1267     // FIXME: implement
1268 }
1269
1270 void AccessibilityUIElement::removeSelection()
1271 {
1272     // FIXME: implement
1273 }
1274
1275 #if SUPPORTS_AX_TEXTMARKERS
1276
1277 // Text markers
1278 AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement* element)
1279 {
1280     BEGIN_AX_OBJC_EXCEPTIONS
1281     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXTextMarkerRangeForUIElement" forParameter:element->platformUIElement()];
1282     return AccessibilityTextMarkerRange(textMarkerRange);
1283     END_AX_OBJC_EXCEPTIONS
1284     
1285     return 0;
1286 }
1287
1288 int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange* range)
1289 {
1290     BEGIN_AX_OBJC_EXCEPTIONS
1291     NSNumber* lengthValue = [m_element accessibilityAttributeValue:@"AXLengthForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1292     return [lengthValue intValue];
1293     END_AX_OBJC_EXCEPTIONS
1294     
1295     return 0;
1296 }
1297
1298 AccessibilityTextMarker AccessibilityUIElement::previousTextMarker(AccessibilityTextMarker* textMarker)
1299 {
1300     BEGIN_AX_OBJC_EXCEPTIONS
1301     id previousMarker = [m_element accessibilityAttributeValue:@"AXPreviousTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1302     return AccessibilityTextMarker(previousMarker);
1303     END_AX_OBJC_EXCEPTIONS
1304     
1305     return 0;
1306 }
1307
1308 AccessibilityTextMarker AccessibilityUIElement::nextTextMarker(AccessibilityTextMarker* textMarker)
1309 {
1310     BEGIN_AX_OBJC_EXCEPTIONS
1311     id nextMarker = [m_element accessibilityAttributeValue:@"AXNextTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1312     return AccessibilityTextMarker(nextMarker);
1313     END_AX_OBJC_EXCEPTIONS
1314     
1315     return 0;
1316 }
1317
1318 JSStringRef AccessibilityUIElement::stringForTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
1319 {
1320     BEGIN_AX_OBJC_EXCEPTIONS
1321     id textString = [m_element accessibilityAttributeValue:@"AXStringForTextMarkerRange" forParameter:(id)markerRange->platformTextMarkerRange()];
1322     return [textString createJSStringRef];
1323     END_AX_OBJC_EXCEPTIONS
1324     
1325     return 0;
1326 }
1327
1328 AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker)
1329 {
1330     BEGIN_AX_OBJC_EXCEPTIONS
1331     NSArray* textMarkers = [NSArray arrayWithObjects:(id)startMarker->platformTextMarker(), (id)endMarker->platformTextMarker(), nil];
1332     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXTextMarkerRangeForUnorderedTextMarkers" forParameter:textMarkers];
1333     return AccessibilityTextMarkerRange(textMarkerRange);
1334     END_AX_OBJC_EXCEPTIONS
1335     
1336     return 0;
1337 }
1338
1339 AccessibilityTextMarker AccessibilityUIElement::startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1340 {
1341     BEGIN_AX_OBJC_EXCEPTIONS
1342     id textMarker = [m_element accessibilityAttributeValue:@"AXStartTextMarkerForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1343     return AccessibilityTextMarker(textMarker);
1344     END_AX_OBJC_EXCEPTIONS
1345     
1346     return 0;    
1347 }
1348
1349 AccessibilityTextMarker AccessibilityUIElement::endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1350 {
1351     BEGIN_AX_OBJC_EXCEPTIONS
1352     id textMarker = [m_element accessibilityAttributeValue:@"AXEndTextMarkerForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1353     return AccessibilityTextMarker(textMarker);
1354     END_AX_OBJC_EXCEPTIONS
1355     
1356     return 0;    
1357 }
1358
1359 AccessibilityTextMarker AccessibilityUIElement::textMarkerForPoint(int x, int y)
1360 {
1361     BEGIN_AX_OBJC_EXCEPTIONS
1362     id textMarker = [m_element accessibilityAttributeValue:@"AXTextMarkerForPosition" forParameter:[NSValue valueWithPoint:NSMakePoint(x, y)]];
1363     return AccessibilityTextMarker(textMarker);
1364     END_AX_OBJC_EXCEPTIONS
1365     
1366     return 0;    
1367 }
1368
1369 AccessibilityUIElement AccessibilityUIElement::accessibilityElementForTextMarker(AccessibilityTextMarker* marker)
1370 {
1371     BEGIN_AX_OBJC_EXCEPTIONS
1372     id uiElement = [m_element accessibilityAttributeValue:@"AXUIElementForTextMarker" forParameter:(id)marker->platformTextMarker()];
1373     return AccessibilityUIElement(uiElement);
1374     END_AX_OBJC_EXCEPTIONS
1375     
1376     return 0;  
1377 }
1378
1379 #endif // SUPPORTS_AX_TEXTMARKERS