NodeLists should not invalidate on irreleavnt attribute changes
[WebKit-https.git] / Source / WebCore / dom / ContainerNode.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include "config.h"
24 #include "ContainerNode.h"
25
26 #include "ChildListMutationScope.h"
27 #include "ContainerNodeAlgorithms.h"
28 #include "DeleteButtonController.h"
29 #include "EventNames.h"
30 #include "ExceptionCode.h"
31 #include "FloatRect.h"
32 #include "Frame.h"
33 #include "FrameView.h"
34 #include "InlineTextBox.h"
35 #include "InspectorInstrumentation.h"
36 #include "MemoryCache.h"
37 #include "MutationEvent.h"
38 #include "ResourceLoadScheduler.h"
39 #include "Page.h"
40 #include "RenderBox.h"
41 #include "RenderTheme.h"
42 #include "RootInlineBox.h"
43 #include <wtf/CurrentTime.h>
44 #include <wtf/Vector.h>
45
46 using namespace std;
47
48 namespace WebCore {
49
50 static void dispatchChildInsertionEvents(Node*);
51 static void dispatchChildRemovalEvents(Node*);
52 static void updateTreeAfterInsertion(ContainerNode*, Node*, bool shouldLazyAttach);
53
54 typedef pair<RefPtr<Node>, unsigned> CallbackParameters;
55 typedef pair<NodeCallback, CallbackParameters> CallbackInfo;
56 typedef Vector<CallbackInfo> NodeCallbackQueue;
57
58 static NodeCallbackQueue* s_postAttachCallbackQueue;
59
60 static size_t s_attachDepth;
61 static bool s_shouldReEnableMemoryCacheCallsAfterAttach;
62
63 static void collectTargetNodes(Node* node, NodeVector& nodes)
64 {
65     if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) {
66         nodes.append(node);
67         return;
68     }
69     getChildNodes(node, nodes);
70 }
71
72 static void collectChildrenAndRemoveFromOldParent(Node* node, NodeVector& nodes, ExceptionCode& ec)
73 {
74     if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) {
75         nodes.append(node);
76         if (ContainerNode* oldParent = node->parentNode())
77             oldParent->removeChild(node, ec);
78         return;
79     }
80     getChildNodes(node, nodes);
81     toContainerNode(node)->removeChildren();
82 }
83
84 void ContainerNode::removeAllChildren()
85 {
86     removeAllChildrenInContainer<Node, ContainerNode>(this);
87 }
88
89 void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent)
90 {
91     NodeVector children;
92     getChildNodes(oldParent, children);
93     oldParent->removeAllChildren();
94
95     for (unsigned i = 0; i < children.size(); ++i) {
96         ExceptionCode ec = 0;
97         if (children[i]->attached())
98             children[i]->detach();
99         // FIXME: We need a no mutation event version of adoptNode.
100         RefPtr<Node> child = document()->adoptNode(children[i].release(), ec);
101         ASSERT(!ec);
102         parserAddChild(child.get());
103         // FIXME: Together with adoptNode above, the tree scope might get updated recursively twice
104         // (if the document changed or oldParent was in a shadow tree, AND *this is in a shadow tree).
105         // Can we do better?
106         treeScope()->adoptIfNeeded(child.get());
107         if (attached() && !child->attached())
108             child->attach();
109     }
110 }
111
112 ContainerNode::~ContainerNode()
113 {
114     removeAllChildren();
115 }
116
117 bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach)
118 {
119     // Check that this node is not "floating".
120     // If it is, it can be deleted as a side effect of sending mutation events.
121     ASSERT(refCount() || parentOrHostNode());
122
123     RefPtr<Node> protect(this);
124
125     ec = 0;
126
127     // insertBefore(node, 0) is equivalent to appendChild(node)
128     if (!refChild)
129         return appendChild(newChild, ec, shouldLazyAttach);
130
131     // Make sure adding the new child is OK.
132     checkAddChild(newChild.get(), ec);
133     if (ec)
134         return false;
135
136     // NOT_FOUND_ERR: Raised if refChild is not a child of this node
137     if (refChild->parentNode() != this) {
138         ec = NOT_FOUND_ERR;
139         return false;
140     }
141
142     if (refChild->previousSibling() == newChild || refChild == newChild) // nothing to do
143         return true;
144
145     RefPtr<Node> next = refChild;
146
147     NodeVector targets;
148     collectChildrenAndRemoveFromOldParent(newChild.get(), targets, ec);
149     if (ec)
150         return false;
151     if (targets.isEmpty())
152         return true;
153
154     InspectorInstrumentation::willInsertDOMNode(document(), this);
155
156 #if ENABLE(MUTATION_OBSERVERS)
157     ChildListMutationScope mutation(this);
158 #endif
159
160     for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
161         Node* child = it->get();
162
163         // Due to arbitrary code running in response to a DOM mutation event it's
164         // possible that "next" is no longer a child of "this".
165         // It's also possible that "child" has been inserted elsewhere.
166         // In either of those cases, we'll just stop.
167         if (next->parentNode() != this)
168             break;
169         if (child->parentNode())
170             break;
171
172         treeScope()->adoptIfNeeded(child);
173
174         insertBeforeCommon(next.get(), child);
175
176         updateTreeAfterInsertion(this, child, shouldLazyAttach);
177     }
178
179     dispatchSubtreeModifiedEvent();
180     return true;
181 }
182
183 void ContainerNode::insertBeforeCommon(Node* nextChild, Node* newChild)
184 {
185     ASSERT(newChild);
186     ASSERT(!newChild->parentNode()); // Use insertBefore if you need to handle reparenting (and want DOM mutation events).
187     ASSERT(!newChild->nextSibling());
188     ASSERT(!newChild->previousSibling());
189     ASSERT(!newChild->isShadowRoot());
190
191     forbidEventDispatch();
192     Node* prev = nextChild->previousSibling();
193     ASSERT(m_lastChild != prev);
194     nextChild->setPreviousSibling(newChild);
195     if (prev) {
196         ASSERT(m_firstChild != nextChild);
197         ASSERT(prev->nextSibling() == nextChild);
198         prev->setNextSibling(newChild);
199     } else {
200         ASSERT(m_firstChild == nextChild);
201         m_firstChild = newChild;
202     }
203     newChild->setParentOrHostNode(this);
204     newChild->setPreviousSibling(prev);
205     newChild->setNextSibling(nextChild);
206     allowEventDispatch();
207 }
208
209 void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node* nextChild)
210 {
211     ASSERT(newChild);
212     ASSERT(nextChild);
213     ASSERT(nextChild->parentNode() == this);
214
215     NodeVector targets;
216     collectTargetNodes(newChild.get(), targets);
217     if (targets.isEmpty())
218         return;
219
220     if (nextChild->previousSibling() == newChild || nextChild == newChild) // nothing to do
221         return;
222
223     RefPtr<Node> next = nextChild;
224     RefPtr<Node> nextChildPreviousSibling = nextChild->previousSibling();
225     for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
226         Node* child = it->get();
227
228         insertBeforeCommon(next.get(), child);
229
230         childrenChanged(true, nextChildPreviousSibling.get(), nextChild, 1);
231         ChildNodeInsertionNotifier(this).notify(child);
232     }
233 }
234
235 bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, bool shouldLazyAttach)
236 {
237     // Check that this node is not "floating".
238     // If it is, it can be deleted as a side effect of sending mutation events.
239     ASSERT(refCount() || parentOrHostNode());
240
241     RefPtr<Node> protect(this);
242
243     ec = 0;
244
245     if (oldChild == newChild) // nothing to do
246         return true;
247
248     // Make sure replacing the old child with the new is ok
249     checkReplaceChild(newChild.get(), oldChild, ec);
250     if (ec)
251         return false;
252
253     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
254     if (!oldChild || oldChild->parentNode() != this) {
255         ec = NOT_FOUND_ERR;
256         return false;
257     }
258
259 #if ENABLE(MUTATION_OBSERVERS)
260     ChildListMutationScope mutation(this);
261 #endif
262
263     RefPtr<Node> next = oldChild->nextSibling();
264
265     // Remove the node we're replacing
266     RefPtr<Node> removedChild = oldChild;
267     removeChild(oldChild, ec);
268     if (ec)
269         return false;
270
271     if (next && (next->previousSibling() == newChild || next == newChild)) // nothing to do
272         return true;
273
274     NodeVector targets;
275     collectChildrenAndRemoveFromOldParent(newChild.get(), targets, ec);
276     if (ec)
277         return false;
278
279     InspectorInstrumentation::willInsertDOMNode(document(), this);
280
281     // Add the new child(ren)
282     for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
283         Node* child = it->get();
284
285         // Due to arbitrary code running in response to a DOM mutation event it's
286         // possible that "next" is no longer a child of "this".
287         // It's also possible that "child" has been inserted elsewhere.
288         // In either of those cases, we'll just stop.
289         if (next && next->parentNode() != this)
290             break;
291         if (child->parentNode())
292             break;
293
294         treeScope()->adoptIfNeeded(child);
295
296         // Add child before "next".
297         forbidEventDispatch();
298         if (next)
299             insertBeforeCommon(next.get(), child);
300         else
301             appendChildToContainer(child, this);
302         allowEventDispatch();
303
304         updateTreeAfterInsertion(this, child, shouldLazyAttach);
305     }
306
307     dispatchSubtreeModifiedEvent();
308     return true;
309 }
310
311 static void willRemoveChild(Node* child)
312 {
313 #if ENABLE(MUTATION_OBSERVERS)
314     ASSERT(child->parentNode());
315     ChildListMutationScope(child->parentNode()).willRemoveChild(child);
316     child->notifyMutationObserversNodeWillDetach();
317 #endif
318
319     dispatchChildRemovalEvents(child);
320     child->document()->nodeWillBeRemoved(child); // e.g. mutation event listener can create a new range.
321     ChildFrameDisconnector(child).disconnect();
322 }
323
324 static void willRemoveChildren(ContainerNode* container)
325 {
326     NodeVector children;
327     getChildNodes(container, children);
328
329     container->document()->nodeChildrenWillBeRemoved(container);
330
331 #if ENABLE(MUTATION_OBSERVERS)
332     ChildListMutationScope mutation(container);
333 #endif
334
335     for (NodeVector::const_iterator it = children.begin(); it != children.end(); it++) {
336         Node* child = it->get();
337
338 #if ENABLE(MUTATION_OBSERVERS)
339         mutation.willRemoveChild(child);
340         child->notifyMutationObserversNodeWillDetach();
341 #endif
342
343         // fire removed from document mutation events.
344         dispatchChildRemovalEvents(child);
345         ChildFrameDisconnector(child).disconnect();
346     }
347 }
348
349 void ContainerNode::disconnectDescendantFrames()
350 {
351     ChildFrameDisconnector(this).disconnect();
352 }
353
354 bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec)
355 {
356     // Check that this node is not "floating".
357     // If it is, it can be deleted as a side effect of sending mutation events.
358     ASSERT(refCount() || parentOrHostNode());
359
360     RefPtr<Node> protect(this);
361
362     ec = 0;
363
364     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
365     if (isReadOnlyNode()) {
366         ec = NO_MODIFICATION_ALLOWED_ERR;
367         return false;
368     }
369
370     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
371     if (!oldChild || oldChild->parentNode() != this) {
372         ec = NOT_FOUND_ERR;
373         return false;
374     }
375
376     RefPtr<Node> child = oldChild;
377     willRemoveChild(child.get());
378
379     // Mutation events might have moved this child into a different parent.
380     if (child->parentNode() != this) {
381         ec = NOT_FOUND_ERR;
382         return false;
383     }
384
385     document()->removeFocusedNodeOfSubtree(child.get());
386
387 #if ENABLE(FULLSCREEN_API)
388     document()->removeFullScreenElementOfSubtree(child.get());
389 #endif
390
391     // Events fired when blurring currently focused node might have moved this
392     // child into a different parent.
393     if (child->parentNode() != this) {
394         ec = NOT_FOUND_ERR;
395         return false;
396     }
397
398     Node* prev = child->previousSibling();
399     Node* next = child->nextSibling();
400     removeBetween(prev, next, child.get());
401
402     childrenChanged(false, prev, next, -1);
403
404     ChildNodeRemovalNotifier(this).notify(child.get());
405     dispatchSubtreeModifiedEvent();
406
407     return child;
408 }
409
410 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node* oldChild)
411 {
412     ASSERT(oldChild);
413     ASSERT(oldChild->parentNode() == this);
414
415     forbidEventDispatch();
416
417     // Remove from rendering tree
418     if (oldChild->attached())
419         oldChild->detach();
420
421     if (nextChild)
422         nextChild->setPreviousSibling(previousChild);
423     if (previousChild)
424         previousChild->setNextSibling(nextChild);
425     if (m_firstChild == oldChild)
426         m_firstChild = nextChild;
427     if (m_lastChild == oldChild)
428         m_lastChild = previousChild;
429
430     oldChild->setPreviousSibling(0);
431     oldChild->setNextSibling(0);
432     oldChild->setParentOrHostNode(0);
433
434     document()->adoptIfNeeded(oldChild);
435
436     allowEventDispatch();
437 }
438
439 void ContainerNode::parserRemoveChild(Node* oldChild)
440 {
441     ASSERT(oldChild);
442     ASSERT(oldChild->parentNode() == this);
443
444     Node* prev = oldChild->previousSibling();
445     Node* next = oldChild->nextSibling();
446
447     removeBetween(prev, next, oldChild);
448
449     childrenChanged(true, prev, next, -1);
450     ChildNodeRemovalNotifier(this).notify(oldChild);
451 }
452
453 // this differs from other remove functions because it forcibly removes all the children,
454 // regardless of read-only status or event exceptions, e.g.
455 void ContainerNode::removeChildren()
456 {
457     if (!m_firstChild)
458         return;
459
460     // The container node can be removed from event handlers.
461     RefPtr<ContainerNode> protect(this);
462
463     // Do any prep work needed before actually starting to detach
464     // and remove... e.g. stop loading frames, fire unload events.
465     willRemoveChildren(protect.get());
466
467     // exclude this node when looking for removed focusedNode since only children will be removed
468     document()->removeFocusedNodeOfSubtree(this, true);
469
470 #if ENABLE(FULLSCREEN_API)
471     document()->removeFullScreenElementOfSubtree(this, true);
472 #endif
473
474     forbidEventDispatch();
475     Vector<RefPtr<Node>, 10> removedChildren;
476     removedChildren.reserveInitialCapacity(childNodeCount());
477     while (RefPtr<Node> n = m_firstChild) {
478         Node* next = n->nextSibling();
479
480         // Remove the node from the tree before calling detach or removedFromDocument (4427024, 4129744).
481         // removeChild() does this after calling detach(). There is no explanation for
482         // this discrepancy between removeChild() and its optimized version removeChildren().
483         n->setPreviousSibling(0);
484         n->setNextSibling(0);
485         n->setParentOrHostNode(0);
486         document()->adoptIfNeeded(n.get());
487
488         m_firstChild = next;
489         if (n == m_lastChild)
490             m_lastChild = 0;
491         removedChildren.append(n.release());
492     }
493
494     size_t removedChildrenCount = removedChildren.size();
495     size_t i;
496
497     // Detach the nodes only after properly removed from the tree because
498     // a. detaching requires a proper DOM tree (for counters and quotes for
499     // example) and during the previous loop the next sibling still points to
500     // the node being removed while the node being removed does not point back
501     // and does not point to the same parent as its next sibling.
502     // b. destroying Renderers of standalone nodes is sometimes faster.
503     for (i = 0; i < removedChildrenCount; ++i) {
504         Node* removedChild = removedChildren[i].get();
505         if (removedChild->attached())
506             removedChild->detach();
507     }
508
509     childrenChanged(false, 0, 0, -static_cast<int>(removedChildrenCount));
510
511     for (i = 0; i < removedChildrenCount; ++i)
512         ChildNodeRemovalNotifier(this).notify(removedChildren[i].get());
513
514     allowEventDispatch();
515     dispatchSubtreeModifiedEvent();
516 }
517
518 bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach)
519 {
520     RefPtr<ContainerNode> protect(this);
521
522     // Check that this node is not "floating".
523     // If it is, it can be deleted as a side effect of sending mutation events.
524     ASSERT(refCount() || parentOrHostNode());
525
526     ec = 0;
527
528     // Make sure adding the new child is ok
529     checkAddChild(newChild.get(), ec);
530     if (ec)
531         return false;
532
533     if (newChild == m_lastChild) // nothing to do
534         return newChild;
535
536     NodeVector targets;
537     collectChildrenAndRemoveFromOldParent(newChild.get(), targets, ec);
538     if (ec)
539         return false;
540
541     if (targets.isEmpty())
542         return true;
543
544     InspectorInstrumentation::willInsertDOMNode(document(), this);
545
546 #if ENABLE(MUTATION_OBSERVERS)
547     ChildListMutationScope mutation(this);
548 #endif
549
550     // Now actually add the child(ren)
551     for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
552         Node* child = it->get();
553
554         // If the child has a parent again, just stop what we're doing, because
555         // that means someone is doing something with DOM mutation -- can't re-parent
556         // a child that already has a parent.
557         if (child->parentNode())
558             break;
559
560         treeScope()->adoptIfNeeded(child);
561
562         // Append child to the end of the list
563         forbidEventDispatch();
564         appendChildToContainer(child, this);
565         allowEventDispatch();
566
567         updateTreeAfterInsertion(this, child, shouldLazyAttach);
568     }
569
570     dispatchSubtreeModifiedEvent();
571     return true;
572 }
573
574 void ContainerNode::parserAddChild(PassRefPtr<Node> newChild)
575 {
576     ASSERT(newChild);
577     ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events).
578
579     forbidEventDispatch();
580     Node* last = m_lastChild;
581     // FIXME: This method should take a PassRefPtr.
582     appendChildToContainer(newChild.get(), this);
583     treeScope()->adoptIfNeeded(newChild.get());
584     
585     allowEventDispatch();
586
587     childrenChanged(true, last, 0, 1);
588     ChildNodeInsertionNotifier(this).notify(newChild.get());
589 }
590
591 void ContainerNode::suspendPostAttachCallbacks()
592 {
593     if (!s_attachDepth) {
594         ASSERT(!s_shouldReEnableMemoryCacheCallsAfterAttach);
595         if (Page* page = document()->page()) {
596             // FIXME: How can this call be specific to one Page, while the
597             // s_attachDepth is a global? Doesn't make sense.
598             if (page->areMemoryCacheClientCallsEnabled()) {
599                 page->setMemoryCacheClientCallsEnabled(false);
600                 s_shouldReEnableMemoryCacheCallsAfterAttach = true;
601             }
602         }
603         resourceLoadScheduler()->suspendPendingRequests();
604     }
605     ++s_attachDepth;
606 }
607
608 void ContainerNode::resumePostAttachCallbacks()
609 {
610     if (s_attachDepth == 1) {
611         RefPtr<ContainerNode> protect(this);
612
613         if (s_postAttachCallbackQueue)
614             dispatchPostAttachCallbacks();
615         if (s_shouldReEnableMemoryCacheCallsAfterAttach) {
616             s_shouldReEnableMemoryCacheCallsAfterAttach = false;
617             if (Page* page = document()->page())
618                 page->setMemoryCacheClientCallsEnabled(true);
619         }
620         resourceLoadScheduler()->resumePendingRequests();
621     }
622     --s_attachDepth;
623 }
624
625 void ContainerNode::queuePostAttachCallback(NodeCallback callback, Node* node, unsigned callbackData)
626 {
627     if (!s_postAttachCallbackQueue)
628         s_postAttachCallbackQueue = new NodeCallbackQueue;
629     
630     s_postAttachCallbackQueue->append(CallbackInfo(callback, CallbackParameters(node, callbackData)));
631 }
632
633 bool ContainerNode::postAttachCallbacksAreSuspended()
634 {
635     return s_attachDepth;
636 }
637
638 void ContainerNode::dispatchPostAttachCallbacks()
639 {
640     // We recalculate size() each time through the loop because a callback
641     // can add more callbacks to the end of the queue.
642     for (size_t i = 0; i < s_postAttachCallbackQueue->size(); ++i) {
643         const CallbackInfo& info = (*s_postAttachCallbackQueue)[i];
644         NodeCallback callback = info.first;
645         CallbackParameters params = info.second;
646
647         callback(params.first.get(), params.second);
648     }
649     s_postAttachCallbackQueue->clear();
650 }
651
652 static void needsStyleRecalcCallback(Node* node, unsigned data)
653 {
654     node->setNeedsStyleRecalc(static_cast<StyleChangeType>(data));
655 }
656
657 void ContainerNode::scheduleSetNeedsStyleRecalc(StyleChangeType changeType)
658 {
659     if (postAttachCallbacksAreSuspended())
660         queuePostAttachCallback(needsStyleRecalcCallback, this, static_cast<unsigned>(changeType));
661     else
662         setNeedsStyleRecalc(changeType);
663 }
664
665 void ContainerNode::attach()
666 {
667     attachChildren();
668     Node::attach();
669 }
670
671 void ContainerNode::detach()
672 {
673     detachChildren();
674     clearChildNeedsStyleRecalc();
675     Node::detach();
676 }
677
678 void ContainerNode::childrenChanged(bool changedByParser, Node*, Node*, int childCountDelta)
679 {
680     document()->incDOMTreeVersion();
681     if (!changedByParser && childCountDelta)
682         document()->updateRangesAfterChildrenChanged(this);
683     invalidateNodeListCachesInAncestors();
684 }
685
686 void ContainerNode::cloneChildNodes(ContainerNode *clone)
687 {
688     // disable the delete button so it's elements are not serialized into the markup
689     bool isEditorEnabled = false;
690     if (document()->frame() && document()->frame()->editor()->canEdit()) {
691         FrameSelection* selection = document()->frame()->selection();
692         Element* root = selection ? selection->rootEditableElement() : 0;
693         isEditorEnabled = root && isDescendantOf(root);
694
695         if (isEditorEnabled)
696             document()->frame()->editor()->deleteButtonController()->disable();
697     }
698     
699     ExceptionCode ec = 0;
700     for (Node* n = firstChild(); n && !ec; n = n->nextSibling())
701         clone->appendChild(n->cloneNode(true), ec);
702     if (isEditorEnabled && document()->frame())
703         document()->frame()->editor()->deleteButtonController()->enable();
704 }
705
706 bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const
707 {
708     if (!renderer())
709         return false;
710     // What is this code really trying to do?
711     RenderObject *o = renderer();
712     RenderObject *p = o;
713
714     if (!o->isInline() || o->isReplaced()) {
715         point = o->localToAbsolute(FloatPoint(), false, true);
716         return true;
717     }
718
719     // find the next text/image child, to get a position
720     while (o) {
721         p = o;
722         if (o->firstChild())
723             o = o->firstChild();
724         else if (o->nextSibling())
725             o = o->nextSibling();
726         else {
727             RenderObject *next = 0;
728             while (!next && o->parent()) {
729                 o = o->parent();
730                 next = o->nextSibling();
731             }
732             o = next;
733
734             if (!o)
735                 break;
736         }
737         ASSERT(o);
738
739         if (!o->isInline() || o->isReplaced()) {
740             point = o->localToAbsolute(FloatPoint(), false, true);
741             return true;
742         }
743
744         if (p->node() && p->node() == this && o->isText() && !o->isBR() && !toRenderText(o)->firstTextBox()) {
745                 // do nothing - skip unrendered whitespace that is a child or next sibling of the anchor
746         } else if ((o->isText() && !o->isBR()) || o->isReplaced()) {
747             point = FloatPoint();
748             if (o->isText() && toRenderText(o)->firstTextBox()) {
749                 point.move(toRenderText(o)->linesBoundingBox().x(),
750                            toRenderText(o)->firstTextBox()->root()->lineTop());
751             } else if (o->isBox()) {
752                 RenderBox* box = toRenderBox(o);
753                 point.moveBy(box->location());
754             }
755             point = o->container()->localToAbsolute(point, false, true);
756             return true;
757         }
758     }
759     
760     // If the target doesn't have any children or siblings that could be used to calculate the scroll position, we must be
761     // at the end of the document.  Scroll to the bottom. FIXME: who said anything about scrolling?
762     if (!o && document()->view()) {
763         point = FloatPoint(0, document()->view()->contentsHeight());
764         return true;
765     }
766     return false;
767 }
768
769 bool ContainerNode::getLowerRightCorner(FloatPoint& point) const
770 {
771     if (!renderer())
772         return false;
773
774     RenderObject* o = renderer();
775     if (!o->isInline() || o->isReplaced()) {
776         RenderBox* box = toRenderBox(o);
777         point = o->localToAbsolute(LayoutPoint(box->size()), false, true);
778         return true;
779     }
780
781     // find the last text/image child, to get a position
782     while (o) {
783         if (o->lastChild())
784             o = o->lastChild();
785         else if (o->previousSibling())
786             o = o->previousSibling();
787         else {
788             RenderObject* prev = 0;
789             while (!prev) {
790                 o = o->parent();
791                 if (!o)
792                     return false;
793                 prev = o->previousSibling();
794             }
795             o = prev;
796         }
797         ASSERT(o);
798         if (o->isText() || o->isReplaced()) {
799             point = FloatPoint();
800             if (o->isText()) {
801                 RenderText* text = toRenderText(o);
802                 IntRect linesBox = text->linesBoundingBox();
803                 if (!linesBox.maxX() && !linesBox.maxY())
804                     continue;
805                 point.moveBy(linesBox.maxXMaxYCorner());
806             } else {
807                 RenderBox* box = toRenderBox(o);
808                 point.moveBy(box->frameRect().maxXMaxYCorner());
809             }
810             point = o->container()->localToAbsolute(point, false, true);
811             return true;
812         }
813     }
814     return true;
815 }
816
817 LayoutRect ContainerNode::getRect() const
818 {
819     FloatPoint  upperLeft, lowerRight;
820     bool foundUpperLeft = getUpperLeftCorner(upperLeft);
821     bool foundLowerRight = getLowerRightCorner(lowerRight);
822     
823     // If we've found one corner, but not the other,
824     // then we should just return a point at the corner that we did find.
825     if (foundUpperLeft != foundLowerRight) {
826         if (foundUpperLeft)
827             lowerRight = upperLeft;
828         else
829             upperLeft = lowerRight;
830     } 
831
832     return enclosingLayoutRect(FloatRect(upperLeft, lowerRight.expandedTo(upperLeft) - upperLeft));
833 }
834
835 void ContainerNode::setFocus(bool received)
836 {
837     if (focused() == received)
838         return;
839
840     Node::setFocus(received);
841
842     // note that we need to recalc the style
843     setNeedsStyleRecalc();
844 }
845
846 void ContainerNode::setActive(bool down, bool pause)
847 {
848     if (down == active()) return;
849
850     Node::setActive(down);
851
852     // note that we need to recalc the style
853     // FIXME: Move to Element
854     if (renderer()) {
855         bool reactsToPress = renderer()->style()->affectedByActiveRules();
856         if (reactsToPress)
857             setNeedsStyleRecalc();
858         if (renderer() && renderer()->style()->hasAppearance()) {
859             if (renderer()->theme()->stateChanged(renderer(), PressedState))
860                 reactsToPress = true;
861         }
862         if (reactsToPress && pause) {
863             // The delay here is subtle.  It relies on an assumption, namely that the amount of time it takes
864             // to repaint the "down" state of the control is about the same time as it would take to repaint the
865             // "up" state.  Once you assume this, you can just delay for 100ms - that time (assuming that after you
866             // leave this method, it will be about that long before the flush of the up state happens again).
867 #ifdef HAVE_FUNC_USLEEP
868             double startTime = currentTime();
869 #endif
870
871             // Ensure there are no pending changes
872             Document::updateStyleForAllDocuments();
873             // Do an immediate repaint.
874             if (renderer())
875                 renderer()->repaint(true);
876             
877             // FIXME: Find a substitute for usleep for Win32.
878             // Better yet, come up with a way of doing this that doesn't use this sort of thing at all.            
879 #ifdef HAVE_FUNC_USLEEP
880             // Now pause for a small amount of time (1/10th of a second from before we repainted in the pressed state)
881             double remainingTime = 0.1 - (currentTime() - startTime);
882             if (remainingTime > 0)
883                 usleep(static_cast<useconds_t>(remainingTime * 1000000.0));
884 #endif
885         }
886     }
887 }
888
889 void ContainerNode::setHovered(bool over)
890 {
891     if (over == hovered()) return;
892
893     Node::setHovered(over);
894
895     // note that we need to recalc the style
896     // FIXME: Move to Element
897     if (renderer()) {
898         if (renderer()->style()->affectedByHoverRules())
899             setNeedsStyleRecalc();
900         if (renderer() && renderer()->style()->hasAppearance())
901             renderer()->theme()->stateChanged(renderer(), HoverState);
902     }
903 }
904
905 unsigned ContainerNode::childNodeCount() const
906 {
907     unsigned count = 0;
908     Node *n;
909     for (n = firstChild(); n; n = n->nextSibling())
910         count++;
911     return count;
912 }
913
914 Node *ContainerNode::childNode(unsigned index) const
915 {
916     unsigned i;
917     Node *n = firstChild();
918     for (i = 0; n != 0 && i < index; i++)
919         n = n->nextSibling();
920     return n;
921 }
922
923
924 static void dispatchChildInsertionEvents(Node* child)
925 {
926     if (child->isInShadowTree())
927         return;
928
929     ASSERT(!eventDispatchForbidden());
930
931     RefPtr<Node> c = child;
932     RefPtr<Document> document = child->document();
933
934     if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
935         c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
936
937     // dispatch the DOMNodeInsertedIntoDocument event to all descendants
938     if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) {
939         for (; c; c = c->traverseNextNode(child))
940             c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false));
941     }
942 }
943
944 static void dispatchChildRemovalEvents(Node* child)
945 {
946     if (child->isInShadowTree())
947         return;
948
949     ASSERT(!eventDispatchForbidden());
950
951     InspectorInstrumentation::willRemoveDOMNode(child->document(), child);
952
953     RefPtr<Node> c = child;
954     RefPtr<Document> document = child->document();
955
956     // dispatch pre-removal mutation events
957     if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER))
958         c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode()));
959
960     // dispatch the DOMNodeRemovedFromDocument event to all descendants
961     if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) {
962         for (; c; c = c->traverseNextNode(child))
963             c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false));
964     }
965 }
966
967 static void updateTreeAfterInsertion(ContainerNode* parent, Node* child, bool shouldLazyAttach)
968 {
969     ASSERT(parent->refCount());
970     ASSERT(child->refCount());
971
972 #if ENABLE(MUTATION_OBSERVERS)
973     ChildListMutationScope(parent).childAdded(child);
974 #endif
975
976     parent->childrenChanged(false, child->previousSibling(), child->nextSibling(), 1);
977
978     ChildNodeInsertionNotifier(parent).notify(child);
979
980     // FIXME: Attachment should be the first operation in this function, but some code
981     // (for example, HTMLFormControlElement's autofocus support) requires this ordering.
982     if (parent->attached() && !child->attached() && child->parentNode() == parent) {
983         if (shouldLazyAttach)
984             child->lazyAttach();
985         else
986             child->attach();
987     }
988
989     dispatchChildInsertionEvents(child);
990 }
991
992 } // namespace WebCore