814b9d82ff968c033121057d4f7e3e4a55db6751
[WebKit-https.git] / WebCore / kwq / KWQAccObject.mm
1 /*
2  * Copyright (C) 2004 Apple Computer, 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 COMPUTER, 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 COMPUTER, 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 "KWQAccObject.h"
27
28 #import "KWQAccObjectCache.h"
29 #import "KWQWidget.h"
30
31 #import "dom_docimpl.h"
32 #import "dom_elementimpl.h"
33 #import "html_inlineimpl.h"
34 #import "html_imageimpl.h"
35 #import "dom_string.h"
36 #import "dom2_range.h"
37 #import "htmlattrs.h"
38 #import "htmltags.h"
39 #import "khtmlview.h"
40 #import "khtml_part.h"
41 #import "render_canvas.h"
42 #import "render_object.h"
43 #import "render_image.h"
44 #import "render_list.h"
45 #import "render_style.h"
46 #import "render_text.h"
47 #import "kjs_html.h"
48 #import "html_miscimpl.h"
49 #import "qptrstack.h"
50
51 using DOM::DocumentImpl;
52 using DOM::ElementImpl;
53 using DOM::HTMLAnchorElementImpl;
54 using DOM::HTMLMapElementImpl;
55 using DOM::HTMLAreaElementImpl;
56 using DOM::HTMLCollection;
57 using DOM::HTMLCollectionImpl;
58 using DOM::Node;
59 using DOM::NodeImpl;
60 using DOM::Range;
61 using DOM::DOMString;
62
63 using khtml::RenderObject;
64 using khtml::RenderWidget;
65 using khtml::RenderCanvas;
66 using khtml::RenderText;
67 using khtml::RenderBlock;
68 using khtml::RenderListMarker;
69 using khtml::RenderImage;
70
71 /* NSAccessibilityDescriptionAttribute is only defined on 10.4 and newer */
72 #if BUILDING_ON_PANTHER
73 #define ACCESSIBILITY_DESCRIPTION_ATTRIBUTE @"AXDescription"
74 #else
75 #define ACCESSIBILITY_DESCRIPTION_ATTRIBUTE NSAccessibilityDescriptionAttribute
76 #endif
77
78 // FIXME: This will eventually need to really localize.
79 #define UI_STRING(string, comment) ((NSString *)[NSString stringWithUTF8String:(string)])
80
81 @implementation KWQAccObject
82
83 -(id)initWithRenderer:(RenderObject*)renderer
84 {
85     [super init];
86     m_renderer = renderer;
87     return self;
88 }
89
90 -(BOOL)detached
91 {
92     return !m_renderer;
93 }
94
95 -(void)detach
96 {
97     [m_data release];
98     m_data = 0;
99     m_renderer = 0;
100     [self clearChildren];
101 }
102
103 -(id)data
104 {
105     return m_data;
106 }
107
108 -(void)setData:(id)data
109 {
110     if (!m_renderer)
111         return;
112
113     [data retain];
114     [m_data release];
115     m_data = data;
116 }
117
118 -(HTMLAnchorElementImpl*)anchorElement
119 {
120     if (m_areaElement)
121         return m_areaElement;
122
123     RenderObject* currRenderer;
124     for (currRenderer = m_renderer; currRenderer && !currRenderer->element(); currRenderer = currRenderer->parent())
125         if (currRenderer->continuation())
126             return [currRenderer->document()->getOrCreateAccObjectCache()->accObject(currRenderer->continuation()) anchorElement];
127     
128     if (!currRenderer || !currRenderer->element())
129         return 0;
130     
131     NodeImpl* elt = currRenderer->element();
132     for ( ; elt; elt = elt->parentNode()) {
133         if (elt->hasAnchor() && elt->renderer() && !elt->renderer()->isImage())
134             return static_cast<HTMLAnchorElementImpl*>(elt);
135     }
136   
137     return 0;
138 }
139
140 -(KWQAccObject*)firstChild
141 {
142     if (!m_renderer || !m_renderer->firstChild())
143         return nil;
144     return m_renderer->document()->getOrCreateAccObjectCache()->accObject(m_renderer->firstChild());
145 }
146
147 -(KWQAccObject*)lastChild
148 {
149     if (!m_renderer || !m_renderer->lastChild())
150         return nil;
151     return m_renderer->document()->getOrCreateAccObjectCache()->accObject(m_renderer->lastChild());
152 }
153
154 -(KWQAccObject*)previousSibling
155 {
156     if (!m_renderer || !m_renderer->previousSibling())
157         return nil;
158     return m_renderer->document()->getOrCreateAccObjectCache()->accObject(m_renderer->previousSibling());
159 }
160
161 -(KWQAccObject*)nextSibling
162 {
163     if (!m_renderer || !m_renderer->nextSibling())
164         return nil;
165     return m_renderer->document()->getOrCreateAccObjectCache()->accObject(m_renderer->nextSibling());
166 }
167
168 -(KWQAccObject*)parentObject
169 {
170     if (m_areaElement)
171         return m_renderer->document()->getOrCreateAccObjectCache()->accObject(m_renderer);
172
173     if (!m_renderer || !m_renderer->parent())
174         return nil;
175     return m_renderer->document()->getOrCreateAccObjectCache()->accObject(m_renderer->parent());
176 }
177
178 -(KWQAccObject*)parentObjectUnignored
179 {
180     KWQAccObject* obj = [self parentObject];
181     if ([obj accessibilityIsIgnored])
182         return [obj parentObjectUnignored];
183     else
184         return obj;
185 }
186
187 -(void)addChildrenToArray:(NSMutableArray*)array
188 {
189     if (!m_renderer)
190         return;
191     
192     if (m_renderer->isWidget()) {
193         RenderWidget* renderWidget = static_cast<RenderWidget*>(m_renderer);
194         QWidget* widget = renderWidget->widget();
195         if (widget) {
196             NSArray* childArr = [(widget->getView()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute];
197             [array addObjectsFromArray: childArr];
198             return;
199         }
200     }
201     
202     for (KWQAccObject* obj = [self firstChild]; obj; obj = [obj nextSibling]) {
203         if ([obj accessibilityIsIgnored])
204             [obj addChildrenToArray: array];
205         else
206             [array addObject: obj];
207     }
208     
209     if (m_renderer->isImage() && !m_areaElement) {
210         HTMLMapElementImpl* map = static_cast<RenderImage*>(m_renderer)->imageMap();
211         if (map) {
212             // Need to add the <area> elements as individual accessibility objects.
213             QPtrStack<NodeImpl> nodeStack;
214             NodeImpl *current = map->firstChild();
215             while (1) {
216                 if (!current) {
217                     if(nodeStack.isEmpty()) break;
218                     current = nodeStack.pop();
219                     current = current->nextSibling();
220                     continue;
221                 }
222                 if (current->hasAnchor()) {
223                     KWQAccObject* obj = [[[KWQAccObject alloc] initWithRenderer: m_renderer] autorelease];
224                     obj->m_areaElement = static_cast<HTMLAreaElementImpl*>(current);
225                     [array addObject: obj];
226                 }
227                 NodeImpl *child = current->firstChild();
228                 if (child) {
229                     nodeStack.push(current);
230                     current = child;
231                 }
232                 else
233                     current = current->nextSibling();
234             }
235         }
236     }
237 }
238
239 -(NSString*)role
240 {
241     if (!m_renderer)
242         return NSAccessibilityUnknownRole;
243
244     if (m_areaElement)
245         return @"AXLink";
246     if (m_renderer->element() && m_renderer->element()->hasAnchor()) {
247         if (m_renderer->isImage())
248             return @"AXImageMap";
249         return @"AXLink";
250     }
251     if (m_renderer->isListMarker())
252         return @"AXListMarker";
253     if (m_renderer->element() && m_renderer->element()->isHTMLElement() &&
254         Node(m_renderer->element()).elementId() == ID_BUTTON)
255         return NSAccessibilityButtonRole;
256     if (m_renderer->isText())
257         return NSAccessibilityStaticTextRole;
258     if (m_renderer->isImage())
259         return NSAccessibilityImageRole;
260     if (m_renderer->isCanvas())
261         return @"AXWebArea";
262     if (m_renderer->isBlockFlow())
263         return NSAccessibilityGroupRole;
264
265     return NSAccessibilityUnknownRole;
266 }
267
268 -(NSString*)roleDescription
269 {
270 #if OMIT_TIGER_FEATURES
271     // We don't need role descriptions on Panther and we don't have the call
272     // to get at localized ones anyway. At some point we may want to conditionally
273     // compile this entire file instead, but this is OK too.
274     return nil;
275 #else
276     if (!m_renderer)
277         return nil;
278     
279     // FIXME 3517227: These need to be localized (UI_STRING here is a dummy macro)
280     // FIXME 3447564: It would be better to call some AppKit API to get these strings
281     // (which would be the best way to localize them)
282     
283     NSString *role = [self role];
284     if ([role isEqualToString:NSAccessibilityButtonRole])
285         return NSAccessibilityRoleDescription(NSAccessibilityButtonRole, nil);
286     
287     if ([role isEqualToString:NSAccessibilityStaticTextRole])
288         return NSAccessibilityRoleDescription(NSAccessibilityStaticTextRole, nil);
289
290     if ([role isEqualToString:NSAccessibilityImageRole])
291         return NSAccessibilityRoleDescription(NSAccessibilityImageRole, nil);
292     
293     if ([role isEqualToString:NSAccessibilityGroupRole])
294         return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, nil);
295     
296     if ([role isEqualToString:@"AXWebArea"])
297         return UI_STRING("web area", "accessibility role description for web area");
298     
299     if ([role isEqualToString:@"AXLink"])
300         return UI_STRING("link", "accessibility role description for link");
301     
302     if ([role isEqualToString:@"AXListMarker"])
303         return UI_STRING("list marker", "accessibility role description for list marker");
304     
305     if ([role isEqualToString:@"AXImageMap"])
306         return UI_STRING("image map", "accessibility role description for image map");
307     
308     return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);
309 #endif
310 }
311
312 -(NSString*)helpText
313 {
314     if (!m_renderer)
315         return nil;
316
317     if (m_areaElement) {
318         QString summary = static_cast<ElementImpl*>(m_areaElement)->getAttribute(ATTR_SUMMARY).string();
319         if (!summary.isEmpty())
320             return summary.getNSString();
321         QString title = static_cast<ElementImpl*>(m_areaElement)->getAttribute(ATTR_TITLE).string();
322         if (!title.isEmpty())
323             return title.getNSString();
324     }
325
326     for (RenderObject* curr = m_renderer; curr; curr = curr->parent()) {
327         if (curr->element() && curr->element()->isHTMLElement()) {
328             QString summary = static_cast<ElementImpl*>(curr->element())->getAttribute(ATTR_SUMMARY).string();
329             if (!summary.isEmpty())
330                 return summary.getNSString();
331             QString title = static_cast<ElementImpl*>(curr->element())->getAttribute(ATTR_TITLE).string();
332             if (!title.isEmpty())
333                 return title.getNSString();
334         }
335     }
336
337     return nil;
338 }
339
340 -(NSString*)textUnderElement
341 {
342     if (!m_renderer)
343         return nil;
344
345     NodeImpl* e = m_renderer->element();
346     DocumentImpl* d = m_renderer->document();
347     if (e && d) {
348         KHTMLPart* p = d->part();
349         if (p) {
350             Range r(p->document());
351             if (m_renderer->isText()) {
352                 r.setStartBefore(e);
353                 r.setEndAfter(e);
354                 return p->text(r).getNSString();
355             }
356             if (e->firstChild()) {
357                 r.setStartBefore(e->firstChild());
358                 r.setEndAfter(e->lastChild());
359                 return p->text(r).getNSString();
360             }
361         }
362     }
363
364     return nil;
365 }
366
367 -(NSString*)value
368 {
369     if (!m_renderer || m_areaElement)
370         return nil;
371
372     if (m_renderer->isText())
373         return [self textUnderElement];
374     
375     if (m_renderer->isListMarker())
376         return static_cast<RenderListMarker*>(m_renderer)->text().getNSString();
377
378     // FIXME: We might need to implement a value here for more types
379     // FIXME: It would be better not to advertise a value at all for the types for which we don't implement one;
380     // this would require subclassing or making accessibilityAttributeNames do something other than return a
381     // single static array.
382     return nil;
383 }
384
385 -(NSString*)title
386 {
387     if (!m_renderer || m_areaElement)
388         return nil;
389     
390     if (m_renderer->element() && m_renderer->element()->isHTMLElement() &&
391              Node(m_renderer->element()).elementId() == ID_BUTTON)
392         return [self textUnderElement];
393     else if (m_renderer->element() && m_renderer->element()->hasAnchor())
394         return [self textUnderElement];
395     
396     return nil;
397 }
398
399 -(NSString*)accessibilityDescription
400 {
401     if (!m_renderer || m_areaElement)
402         return nil;
403     
404     if (m_renderer->isImage()) {
405         if (m_renderer->element() && m_renderer->element()->isHTMLElement()) {
406             QString alt = static_cast<ElementImpl*>(m_renderer->element())->getAttribute(ATTR_ALT).string();
407             return !alt.isEmpty() ? alt.getNSString() : nil;
408         }
409     }
410     
411     return nil;
412 }
413
414 static QRect boundingBoxRect(RenderObject* obj)
415 {
416     QRect rect(0,0,0,0);
417     if (obj) {
418         if (obj->isInlineContinuation())
419             obj = obj->element()->renderer();
420         QValueList<QRect> rects;
421         int x = 0, y = 0;
422         obj->absolutePosition(x, y);
423         obj->absoluteRects(rects, x, y);
424         for (QValueList<QRect>::ConstIterator it = rects.begin(); it != rects.end(); ++it) {
425             QRect r = *it;
426             if (r.isValid()) {
427                 if (rect.isEmpty())
428                     rect = r;
429                 else
430                     rect.unite(r);
431             }
432         }
433     }
434     return rect;
435 }
436
437 -(NSValue*)position
438 {
439     QRect rect = m_areaElement ? m_areaElement->getRect(m_renderer) : boundingBoxRect(m_renderer);
440     
441     // The Cocoa accessibility API wants the lower-left corner, not the upper-left, so we add in our height.
442     NSPoint point = NSMakePoint(rect.x(), rect.y() + rect.height());
443     if (m_renderer && m_renderer->canvas() && m_renderer->canvas()->view()) {
444         NSView* view = m_renderer->canvas()->view()->getDocumentView();
445         point = [[view window] convertBaseToScreen: [view convertPoint: point toView:nil]];
446     }
447     return [NSValue valueWithPoint: point];
448 }
449
450 -(NSValue*)size
451 {
452     QRect rect = m_areaElement ? m_areaElement->getRect(m_renderer) : boundingBoxRect(m_renderer);
453     return [NSValue valueWithSize: NSMakeSize(rect.width(), rect.height())];
454 }
455
456 -(BOOL)accessibilityIsIgnored
457 {
458     if (!m_renderer || m_renderer->style()->visibility() != khtml::VISIBLE)
459         return YES;
460
461     if (m_renderer->isText())
462         return m_renderer->isBR() || !static_cast<RenderText*>(m_renderer)->firstTextBox();
463     
464     if (m_areaElement || (m_renderer->element() && m_renderer->element()->hasAnchor()))
465         return NO;
466
467     if (m_renderer->isBlockFlow() && m_renderer->childrenInline())
468         return !static_cast<RenderBlock*>(m_renderer)->firstLineBox();
469
470     return (!m_renderer->isListMarker() && !m_renderer->isCanvas() && 
471             !m_renderer->isImage() &&
472             !(m_renderer->element() && m_renderer->element()->isHTMLElement() &&
473               Node(m_renderer->element()).elementId() == ID_BUTTON));
474 }
475
476 - (NSArray *)accessibilityAttributeNames
477 {
478     static NSArray* attributes = nil;
479     static NSArray* anchorAttrs = nil;
480     static NSArray* webAreaAttrs = nil;
481     if (attributes == nil) {
482         attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
483             NSAccessibilityRoleDescriptionAttribute,
484             NSAccessibilityChildrenAttribute,
485             NSAccessibilityHelpAttribute,
486             NSAccessibilityParentAttribute,
487             NSAccessibilityPositionAttribute,
488             NSAccessibilitySizeAttribute,
489             NSAccessibilityTitleAttribute,
490             ACCESSIBILITY_DESCRIPTION_ATTRIBUTE,
491             NSAccessibilityValueAttribute,
492             NSAccessibilityFocusedAttribute,
493             NSAccessibilityEnabledAttribute,
494             NSAccessibilityWindowAttribute,
495             nil];
496     }
497     if (anchorAttrs == nil) {
498         anchorAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
499             NSAccessibilityRoleDescriptionAttribute,
500             NSAccessibilityChildrenAttribute,
501             NSAccessibilityHelpAttribute,
502             NSAccessibilityParentAttribute,
503             NSAccessibilityPositionAttribute,
504             NSAccessibilitySizeAttribute,
505             NSAccessibilityTitleAttribute,
506             NSAccessibilityValueAttribute,
507             NSAccessibilityFocusedAttribute,
508             NSAccessibilityEnabledAttribute,
509             NSAccessibilityWindowAttribute,
510             @"AXURL",
511             nil];
512     }
513     if (webAreaAttrs == nil) {
514         webAreaAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
515             NSAccessibilityRoleDescriptionAttribute,
516             NSAccessibilityChildrenAttribute,
517             NSAccessibilityHelpAttribute,
518             NSAccessibilityParentAttribute,
519             NSAccessibilityPositionAttribute,
520             NSAccessibilitySizeAttribute,
521             NSAccessibilityTitleAttribute,
522             NSAccessibilityValueAttribute,
523             NSAccessibilityFocusedAttribute,
524             NSAccessibilityEnabledAttribute,
525             NSAccessibilityWindowAttribute,
526             @"AXLinkUIElements",
527             @"AXLoaded",
528             @"AXLayoutCount",
529             nil];
530     }
531     
532     if (m_renderer && m_renderer->isCanvas())
533         return webAreaAttrs;
534     if (m_areaElement || (m_renderer && !m_renderer->isImage() && m_renderer->element() && m_renderer->element()->hasAnchor()))
535         return anchorAttrs;
536     return attributes;
537 }
538
539 - (NSArray*)accessibilityActionNames
540 {
541     static NSArray* actions = nil;
542     if ([self anchorElement]) {
543         if (actions == nil)
544             actions = [[NSArray alloc] initWithObjects: NSAccessibilityPressAction, nil];
545         return actions;
546     }
547     return nil;
548 }
549
550 - (NSString *)accessibilityActionDescription:(NSString *)action
551 {
552 #if OMIT_TIGER_FEATURES
553     // We don't need action descriptions on Panther and we don't have the call
554     // to get at localized ones anyway. At some point we may want to conditionally
555     // compile this entire file instead, but this is OK too.
556     return nil;
557 #else
558     // We only have the one action (press).
559     return NSAccessibilityActionDescription(NSAccessibilityPressAction);
560 #endif
561 }
562
563 - (void)accessibilityPerformAction:(NSString *)action
564 {
565     // We only have the one action (press).
566
567     // Locate the anchor element. If it doesn't exist, just bail.
568     HTMLAnchorElementImpl* anchorElt = [self anchorElement];
569     if (!anchorElt) return;
570
571     DocumentImpl* d = anchorElt->getDocument();
572     if (d) {
573         KHTMLPart* p = d->part();
574         if (p) {
575             KWQ(p)->prepareForUserAction();
576         }
577     }
578
579     anchorElt->click();
580 }
581
582 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName
583 {
584     return NO;
585 }
586
587 - (id)accessibilityAttributeValue:(NSString *)attributeName
588 {
589     if (!m_renderer)
590         return nil;
591
592     if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])
593         return [self role];
594
595     if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])
596         return [self roleDescription];
597     
598     if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {
599         if (m_renderer->isCanvas())
600             return m_renderer->canvas()->view()->getView();
601         return [self parentObjectUnignored];
602     }
603
604     if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) {
605         if (!m_children) {
606             m_children = [NSMutableArray arrayWithCapacity: 8];
607             [m_children retain];
608             [self addChildrenToArray: m_children];
609         }
610         return m_children;
611     }
612
613     if (m_renderer->isCanvas()) {
614         if ([attributeName isEqualToString: @"AXLinkUIElements"]) {
615             NSMutableArray* links = [NSMutableArray arrayWithCapacity: 32];
616             HTMLCollection coll(m_renderer->document(), HTMLCollectionImpl::DOC_LINKS);
617             if (coll.isNull())
618                 return links;
619             Node curr = coll.firstItem();
620             while (!curr.isNull()) {
621                 RenderObject* obj = curr.handle()->renderer();
622                 if (obj)
623                     [links addObject: obj->document()->getOrCreateAccObjectCache()->accObject(obj)];
624                 curr = coll.nextItem();
625             }
626             return links;
627         }
628         else if ([attributeName isEqualToString: @"AXLoaded"])
629             return [NSNumber numberWithBool: (!m_renderer->document()->tokenizer())];
630         else if ([attributeName isEqualToString: @"AXLayoutCount"])
631             return [NSNumber numberWithInt: (static_cast<RenderCanvas*>(m_renderer)->view()->layoutCount())];
632     }
633     
634     if ([attributeName isEqualToString: @"AXURL"] && 
635         (m_areaElement || (!m_renderer->isImage() && m_renderer->element() && m_renderer->element()->hasAnchor()))) {
636         HTMLAnchorElementImpl* anchor = [self anchorElement];
637         if (anchor) {
638             QString s = anchor->getAttribute(ATTR_HREF).string();
639             if (!s.isNull()) {
640                 s = anchor->getDocument()->completeURL(s);
641                 return s.getNSString();
642             }
643         }
644     }
645     
646     if ([attributeName isEqualToString: NSAccessibilityTitleAttribute])
647         return [self title];
648     
649     if ([attributeName isEqualToString: ACCESSIBILITY_DESCRIPTION_ATTRIBUTE])
650         return [self accessibilityDescription];
651     
652     if ([attributeName isEqualToString: NSAccessibilityValueAttribute])
653         return [self value];
654
655     if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])
656         return [self helpText];
657     
658     if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
659         return [NSNumber numberWithBool: (m_renderer->element() && m_renderer->document()->focusNode() == m_renderer->element())];
660
661     if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])
662         return [NSNumber numberWithBool: YES];
663     
664     if ([attributeName isEqualToString: NSAccessibilitySizeAttribute])
665         return [self size];
666
667     if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])
668         return [self position];
669
670     if ([attributeName isEqualToString: NSAccessibilityWindowAttribute])
671         return [m_renderer->canvas()->view()->getView() window];
672
673     return nil;
674 }
675
676 - (id)accessibilityHitTest:(NSPoint)point
677 {
678     if (!m_renderer)
679         return self;
680     
681     RenderObject::NodeInfo nodeInfo(true, true);
682     m_renderer->layer()->hitTest(nodeInfo, (int)point.x, (int)point.y);
683     if (!nodeInfo.innerNode())
684         return self;
685     RenderObject* obj = nodeInfo.innerNode()->renderer();
686     if (!obj)
687         return self;
688     return obj->document()->getOrCreateAccObjectCache()->accObject(obj);
689 }
690
691 - (void)childrenChanged
692 {
693     [self clearChildren];
694     
695     if ([self accessibilityIsIgnored])
696         [[self parentObject] childrenChanged];
697 }
698
699 - (void)clearChildren
700 {
701     [m_children release];
702     m_children = nil;
703 }
704
705 @end