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