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.
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.
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.
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.
24 #include "ContainerNode.h"
26 #include "BeforeLoadEvent.h"
27 #include "ChildListMutationScope.h"
28 #include "ContainerNodeAlgorithms.h"
29 #include "DeleteButtonController.h"
30 #include "EventNames.h"
31 #include "ExceptionCode.h"
32 #include "FloatRect.h"
34 #include "FrameView.h"
35 #include "InlineTextBox.h"
36 #include "InspectorInstrumentation.h"
37 #include "MemoryCache.h"
38 #include "MutationEvent.h"
39 #include "ResourceLoadScheduler.h"
41 #include "RenderBox.h"
42 #include "RenderTheme.h"
43 #include "RootInlineBox.h"
44 #include <wtf/CurrentTime.h>
45 #include <wtf/Vector.h>
51 static void notifyChildInserted(Node*);
52 static void dispatchChildInsertionEvents(Node*);
53 static void dispatchChildRemovalEvents(Node*);
55 typedef pair<RefPtr<Node>, unsigned> CallbackParameters;
56 typedef pair<NodeCallback, CallbackParameters> CallbackInfo;
57 typedef Vector<CallbackInfo> NodeCallbackQueue;
59 typedef Vector<RefPtr<Node>, 1> NodeVector;
60 static NodeCallbackQueue* s_postAttachCallbackQueue;
62 static size_t s_attachDepth;
63 static bool s_shouldReEnableMemoryCacheCallsAfterAttach;
65 static inline void collectNodes(Node* node, NodeVector& nodes)
67 for (Node* child = node->firstChild(); child; child = child->nextSibling())
71 static void collectTargetNodes(Node* node, NodeVector& nodes)
73 if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) {
77 collectNodes(node, nodes);
80 void ContainerNode::removeAllChildren()
82 removeAllChildrenInContainer<Node, ContainerNode>(this);
85 void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent)
88 collectNodes(oldParent, children);
89 oldParent->removeAllChildren();
91 for (unsigned i = 0; i < children.size(); ++i) {
93 if (children[i]->attached())
94 children[i]->detach();
95 // FIXME: We need a no mutation event version of adoptNode.
96 RefPtr<Node> child = document()->adoptNode(children[i].release(), ec);
98 parserAddChild(child.get());
99 // FIXME: Together with adoptNode above, the tree scope might get updated recursively twice
100 // (if the document changed or oldParent was in a shadow tree, AND *this is in a shadow tree).
102 child->setTreeScopeRecursively(treeScope());
103 if (attached() && !child->attached())
108 ContainerNode::~ContainerNode()
113 bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach)
115 // Check that this node is not "floating".
116 // If it is, it can be deleted as a side effect of sending mutation events.
117 ASSERT(refCount() || parentOrHostNode());
121 // insertBefore(node, 0) is equivalent to appendChild(node)
123 return appendChild(newChild, ec, shouldLazyAttach);
125 // Make sure adding the new child is OK.
126 checkAddChild(newChild.get(), ec);
130 // NOT_FOUND_ERR: Raised if refChild is not a child of this node
131 if (refChild->parentNode() != this) {
137 collectTargetNodes(newChild.get(), targets);
138 if (targets.isEmpty())
141 // Now actually add the child(ren)
142 if (refChild->previousSibling() == newChild || refChild == newChild) // nothing to do
145 #if ENABLE(MUTATION_OBSERVERS)
146 ChildListMutationScope mutation(this);
149 RefPtr<Node> next = refChild;
150 RefPtr<Node> refChildPreviousSibling = refChild->previousSibling();
151 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
152 Node* child = it->get();
154 // If child is already present in the tree, first remove it from the old location.
155 if (ContainerNode* oldParent = child->parentNode())
156 oldParent->removeChild(child, ec);
160 // FIXME: After sending the mutation events, "this" could be destroyed.
161 // We can prevent that by doing a "ref", but first we have to make sure
162 // that no callers call with ref count == 0 and parent = 0 (as of this
163 // writing, there are definitely callers who call that way).
165 // Due to arbitrary code running in response to a DOM mutation event it's
166 // possible that "next" is no longer a child of "this".
167 // It's also possible that "child" has been inserted elsewhere.
168 // In either of those cases, we'll just stop.
169 if (next->parentNode() != this)
171 if (child->parentNode())
174 #if ENABLE(INSPECTOR)
175 InspectorInstrumentation::willInsertDOMNode(document(), child, this);
178 child->setTreeScopeRecursively(treeScope());
180 insertBeforeCommon(next.get(), child);
182 // Send notification about the children change.
183 childrenChanged(false, refChildPreviousSibling.get(), next.get(), 1);
184 notifyChildInserted(child);
186 // Add child to the rendering tree.
187 if (attached() && !child->attached() && child->parentNode() == this) {
188 if (shouldLazyAttach)
194 // Now that the child is attached to the render tree, dispatch
195 // the relevant mutation events.
196 dispatchChildInsertionEvents(child);
199 dispatchSubtreeModifiedEvent();
203 void ContainerNode::insertBeforeCommon(Node* nextChild, Node* newChild)
206 ASSERT(!newChild->parentNode()); // Use insertBefore if you need to handle reparenting (and want DOM mutation events).
207 ASSERT(!newChild->nextSibling());
208 ASSERT(!newChild->previousSibling());
210 forbidEventDispatch();
211 Node* prev = nextChild->previousSibling();
212 ASSERT(m_lastChild != prev);
213 nextChild->setPreviousSibling(newChild);
215 ASSERT(m_firstChild != nextChild);
216 ASSERT(prev->nextSibling() == nextChild);
217 prev->setNextSibling(newChild);
219 ASSERT(m_firstChild == nextChild);
220 m_firstChild = newChild;
222 newChild->setParent(this);
223 newChild->setPreviousSibling(prev);
224 newChild->setNextSibling(nextChild);
225 allowEventDispatch();
228 void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node* nextChild)
232 ASSERT(nextChild->parentNode() == this);
235 collectTargetNodes(newChild.get(), targets);
236 if (targets.isEmpty())
239 if (nextChild->previousSibling() == newChild || nextChild == newChild) // nothing to do
242 RefPtr<Node> next = nextChild;
243 RefPtr<Node> nextChildPreviousSibling = nextChild->previousSibling();
244 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
245 Node* child = it->get();
247 #if ENABLE(INSPECTOR)
248 InspectorInstrumentation::willInsertDOMNode(document(), child, this);
251 insertBeforeCommon(next.get(), child);
253 childrenChanged(true, nextChildPreviousSibling.get(), nextChild, 1);
254 notifyChildInserted(child);
258 bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, bool shouldLazyAttach)
260 // Check that this node is not "floating".
261 // If it is, it can be deleted as a side effect of sending mutation events.
262 ASSERT(refCount() || parentOrHostNode());
266 if (oldChild == newChild) // nothing to do
269 // Make sure replacing the old child with the new is ok
270 checkReplaceChild(newChild.get(), oldChild, ec);
274 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
275 if (!oldChild || oldChild->parentNode() != this) {
280 #if ENABLE(MUTATION_OBSERVERS)
281 ChildListMutationScope mutation(this);
284 RefPtr<Node> prev = oldChild->previousSibling();
285 RefPtr<Node> next = oldChild->nextSibling();
287 // Remove the node we're replacing
288 RefPtr<Node> removedChild = oldChild;
289 removeChild(oldChild, ec);
293 // FIXME: After sending the mutation events, "this" could be destroyed.
294 // We can prevent that by doing a "ref", but first we have to make sure
295 // that no callers call with ref count == 0 and parent = 0 (as of this
296 // writing, there are definitely callers who call that way).
298 bool isFragment = newChild->nodeType() == DOCUMENT_FRAGMENT_NODE;
300 // Add the new child(ren)
301 RefPtr<Node> child = isFragment ? newChild->firstChild() : newChild;
303 // If the new child is already in the right place, we're done.
304 if (prev && (prev == child || prev == child->previousSibling()))
307 // For a fragment we have more children to do.
308 RefPtr<Node> nextChild = isFragment ? child->nextSibling() : 0;
310 // Remove child from its old position.
311 if (ContainerNode* oldParent = child->parentNode())
312 oldParent->removeChild(child.get(), ec);
316 // Due to arbitrary code running in response to a DOM mutation event it's
317 // possible that "prev" is no longer a child of "this".
318 // It's also possible that "child" has been inserted elsewhere.
319 // In either of those cases, we'll just stop.
320 if (prev && prev->parentNode() != this)
322 if (child->parentNode())
325 ASSERT(!child->nextSibling());
326 ASSERT(!child->previousSibling());
328 #if ENABLE(INSPECTOR)
329 InspectorInstrumentation::willInsertDOMNode(document(), child.get(), this);
332 child->setTreeScopeRecursively(treeScope());
334 // Add child after "prev".
335 forbidEventDispatch();
338 next = prev->nextSibling();
339 ASSERT(m_firstChild != next);
340 prev->setNextSibling(child.get());
343 m_firstChild = child.get();
346 ASSERT(m_lastChild != prev);
347 ASSERT(next->previousSibling() == prev);
348 next->setPreviousSibling(child.get());
350 ASSERT(m_lastChild == prev);
351 m_lastChild = child.get();
353 child->setParent(this);
354 child->setPreviousSibling(prev.get());
355 child->setNextSibling(next);
356 allowEventDispatch();
358 childrenChanged(false, prev.get(), next, 1);
359 notifyChildInserted(child.get());
361 // Add child to the rendering tree
362 if (attached() && !child->attached() && child->parentNode() == this) {
363 if (shouldLazyAttach)
369 // Now that the child is attached to the render tree, dispatch
370 // the relevant mutation events.
371 dispatchChildInsertionEvents(child.get());
374 child = nextChild.release();
377 dispatchSubtreeModifiedEvent();
381 void ContainerNode::willRemove()
383 RefPtr<Node> protect(this);
385 for (RefPtr<Node> child = firstChild(); child; child = child->nextSibling()) {
386 if (child->parentNode() != this) // Check for child being removed from subtree while removing.
393 static void willRemoveChild(Node* child)
395 // update auxiliary doc info (e.g. iterators) to note that node is being removed
396 child->document()->nodeWillBeRemoved(child);
397 child->document()->incDOMTreeVersion();
399 // fire removed from document mutation events.
400 dispatchChildRemovalEvents(child);
404 static void willRemoveChildren(ContainerNode* container)
406 container->document()->nodeChildrenWillBeRemoved(container);
407 container->document()->incDOMTreeVersion();
410 collectNodes(container, children);
412 #if ENABLE(MUTATION_OBSERVERS)
413 ChildListMutationScope mutation(container);
416 for (NodeVector::const_iterator it = children.begin(); it != children.end(); it++) {
417 Node* child = it->get();
418 // fire removed from document mutation events.
419 dispatchChildRemovalEvents(child);
424 bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec)
426 // Check that this node is not "floating".
427 // If it is, it can be deleted as a side effect of sending mutation events.
428 ASSERT(refCount() || parentOrHostNode());
432 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
433 if (isReadOnlyNode()) {
434 ec = NO_MODIFICATION_ALLOWED_ERR;
438 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
439 if (!oldChild || oldChild->parentNode() != this) {
444 RefPtr<Node> child = oldChild;
445 willRemoveChild(child.get());
447 // Mutation events might have moved this child into a different parent.
448 if (child->parentNode() != this) {
453 document()->removeFocusedNodeOfSubtree(child.get());
455 #if ENABLE(FULLSCREEN_API)
456 document()->removeFullScreenElementOfSubtree(child.get());
460 // Events fired when blurring currently focused node might have moved this
461 // child into a different parent.
462 if (child->parentNode() != this) {
467 // FIXME: After sending the mutation events, "this" could be destroyed.
468 // We can prevent that by doing a "ref", but first we have to make sure
469 // that no callers call with ref count == 0 and parent = 0 (as of this
470 // writing, there are definitely callers who call that way).
472 Node* prev = child->previousSibling();
473 Node* next = child->nextSibling();
474 removeBetween(prev, next, child.get());
476 // Dispatch post-removal mutation events
477 childrenChanged(false, prev, next, -1);
478 dispatchSubtreeModifiedEvent();
480 if (child->inDocument())
481 child->removedFromDocument();
483 child->removedFromTree(true);
488 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node* oldChild)
491 ASSERT(oldChild->parentNode() == this);
493 forbidEventDispatch();
495 // Remove from rendering tree
496 if (oldChild->attached())
500 nextChild->setPreviousSibling(previousChild);
502 previousChild->setNextSibling(nextChild);
503 if (m_firstChild == oldChild)
504 m_firstChild = nextChild;
505 if (m_lastChild == oldChild)
506 m_lastChild = previousChild;
508 oldChild->setPreviousSibling(0);
509 oldChild->setNextSibling(0);
510 oldChild->setParent(0);
512 oldChild->setTreeScopeRecursively(document());
514 allowEventDispatch();
517 void ContainerNode::parserRemoveChild(Node* oldChild)
520 ASSERT(oldChild->parentNode() == this);
522 Node* prev = oldChild->previousSibling();
523 Node* next = oldChild->nextSibling();
525 removeBetween(prev, next, oldChild);
527 childrenChanged(true, prev, next, -1);
528 if (oldChild->inDocument())
529 oldChild->removedFromDocument();
531 oldChild->removedFromTree(true);
534 // this differs from other remove functions because it forcibly removes all the children,
535 // regardless of read-only status or event exceptions, e.g.
536 void ContainerNode::removeChildren()
541 // The container node can be removed from event handlers.
542 RefPtr<ContainerNode> protect(this);
544 // Do any prep work needed before actually starting to detach
545 // and remove... e.g. stop loading frames, fire unload events.
546 willRemoveChildren(protect.get());
548 // exclude this node when looking for removed focusedNode since only children will be removed
549 document()->removeFocusedNodeOfSubtree(this, true);
551 #if ENABLE(FULLSCREEN_API)
552 document()->removeFullScreenElementOfSubtree(this, true);
555 forbidEventDispatch();
556 Vector<RefPtr<Node>, 10> removedChildren;
557 removedChildren.reserveInitialCapacity(childNodeCount());
558 while (RefPtr<Node> n = m_firstChild) {
559 Node* next = n->nextSibling();
561 // Remove the node from the tree before calling detach or removedFromDocument (4427024, 4129744).
562 // removeChild() does this after calling detach(). There is no explanation for
563 // this discrepancy between removeChild() and its optimized version removeChildren().
564 n->setPreviousSibling(0);
565 n->setNextSibling(0);
567 n->setTreeScopeRecursively(document());
570 if (n == m_lastChild)
572 removedChildren.append(n.release());
575 size_t removedChildrenCount = removedChildren.size();
578 // Detach the nodes only after properly removed from the tree because
579 // a. detaching requires a proper DOM tree (for counters and quotes for
580 // example) and during the previous loop the next sibling still points to
581 // the node being removed while the node being removed does not point back
582 // and does not point to the same parent as its next sibling.
583 // b. destroying Renderers of standalone nodes is sometimes faster.
584 for (i = 0; i < removedChildrenCount; ++i) {
585 Node* removedChild = removedChildren[i].get();
586 if (removedChild->attached())
587 removedChild->detach();
590 allowEventDispatch();
592 // Dispatch a single post-removal mutation event denoting a modified subtree.
593 childrenChanged(false, 0, 0, -static_cast<int>(removedChildrenCount));
594 dispatchSubtreeModifiedEvent();
596 for (i = 0; i < removedChildrenCount; ++i) {
597 Node* removedChild = removedChildren[i].get();
598 if (removedChild->inDocument())
599 removedChild->removedFromDocument();
600 // removeChild() calls removedFromTree(true) if the child was not in the
601 // document. There is no explanation for this discrepancy between removeChild()
602 // and its optimized version removeChildren().
606 bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach)
608 // Check that this node is not "floating".
609 // If it is, it can be deleted as a side effect of sending mutation events.
610 ASSERT(refCount() || parentOrHostNode());
614 // Make sure adding the new child is ok
615 checkAddChild(newChild.get(), ec);
619 if (newChild == m_lastChild) // nothing to do
623 collectTargetNodes(newChild.get(), targets);
624 if (targets.isEmpty())
627 #if ENABLE(MUTATION_OBSERVERS)
628 ChildListMutationScope mutation(this);
631 // Now actually add the child(ren)
632 RefPtr<Node> prev = lastChild();
633 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
634 Node* child = it->get();
635 // If child is already present in the tree, first remove it
636 if (ContainerNode* oldParent = child->parentNode()) {
637 oldParent->removeChild(child, ec);
641 // If the child has a parent again, just stop what we're doing, because
642 // that means someone is doing something with DOM mutation -- can't re-parent
643 // a child that already has a parent.
644 if (child->parentNode())
648 #if ENABLE(INSPECTOR)
649 InspectorInstrumentation::willInsertDOMNode(document(), child, this);
652 child->setTreeScopeRecursively(treeScope());
654 // Append child to the end of the list
655 forbidEventDispatch();
656 child->setParent(this);
658 child->setPreviousSibling(m_lastChild);
659 m_lastChild->setNextSibling(child);
661 m_firstChild = child;
663 allowEventDispatch();
665 // Send notification about the children change.
666 childrenChanged(false, prev.get(), 0, 1);
667 notifyChildInserted(child);
669 // Add child to the rendering tree
670 if (attached() && !child->attached() && child->parentNode() == this) {
671 if (shouldLazyAttach)
677 // Now that the child is attached to the render tree, dispatch
678 // the relevant mutation events.
679 dispatchChildInsertionEvents(child);
683 dispatchSubtreeModifiedEvent();
687 void ContainerNode::parserAddChild(PassRefPtr<Node> newChild)
690 ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events).
692 #if ENABLE(INSPECTOR)
693 InspectorInstrumentation::willInsertDOMNode(document(), newChild.get(), this);
696 forbidEventDispatch();
697 Node* last = m_lastChild;
698 // FIXME: This method should take a PassRefPtr.
699 appendChildToContainer<Node, ContainerNode>(newChild.get(), this);
700 newChild->setTreeScopeRecursively(treeScope());
702 allowEventDispatch();
704 // FIXME: Why doesn't this use notifyChildInserted(newChild) instead?
705 document()->incDOMTreeVersion();
707 newChild->insertedIntoDocument();
708 childrenChanged(true, last, 0, 1);
711 void ContainerNode::suspendPostAttachCallbacks()
713 if (!s_attachDepth) {
714 ASSERT(!s_shouldReEnableMemoryCacheCallsAfterAttach);
715 if (Page* page = document()->page()) {
716 if (page->areMemoryCacheClientCallsEnabled()) {
717 page->setMemoryCacheClientCallsEnabled(false);
718 s_shouldReEnableMemoryCacheCallsAfterAttach = true;
721 resourceLoadScheduler()->suspendPendingRequests();
726 void ContainerNode::resumePostAttachCallbacks()
728 if (s_attachDepth == 1) {
729 if (s_postAttachCallbackQueue)
730 dispatchPostAttachCallbacks();
731 if (s_shouldReEnableMemoryCacheCallsAfterAttach) {
732 s_shouldReEnableMemoryCacheCallsAfterAttach = false;
733 if (Page* page = document()->page())
734 page->setMemoryCacheClientCallsEnabled(true);
736 resourceLoadScheduler()->resumePendingRequests();
741 void ContainerNode::queuePostAttachCallback(NodeCallback callback, Node* node, unsigned callbackData)
743 if (!s_postAttachCallbackQueue)
744 s_postAttachCallbackQueue = new NodeCallbackQueue;
746 s_postAttachCallbackQueue->append(CallbackInfo(callback, CallbackParameters(node, callbackData)));
749 bool ContainerNode::postAttachCallbacksAreSuspended()
751 return s_attachDepth;
754 void ContainerNode::dispatchPostAttachCallbacks()
756 // We recalculate size() each time through the loop because a callback
757 // can add more callbacks to the end of the queue.
758 for (size_t i = 0; i < s_postAttachCallbackQueue->size(); ++i) {
759 const CallbackInfo& info = (*s_postAttachCallbackQueue)[i];
760 NodeCallback callback = info.first;
761 CallbackParameters params = info.second;
763 callback(params.first.get(), params.second);
765 s_postAttachCallbackQueue->clear();
768 static void needsStyleRecalcCallback(Node* node, unsigned data)
770 node->setNeedsStyleRecalc(static_cast<StyleChangeType>(data));
773 void ContainerNode::scheduleSetNeedsStyleRecalc(StyleChangeType changeType)
775 if (postAttachCallbacksAreSuspended())
776 queuePostAttachCallback(needsStyleRecalcCallback, this, static_cast<unsigned>(changeType));
778 setNeedsStyleRecalc(changeType);
781 void ContainerNode::attach()
783 for (Node* child = m_firstChild; child; child = child->nextSibling())
788 void ContainerNode::detach()
790 for (Node* child = m_firstChild; child; child = child->nextSibling())
792 clearChildNeedsStyleRecalc();
796 void ContainerNode::insertedIntoDocument()
798 RefPtr<Node> protect(this);
800 Node::insertedIntoDocument();
801 insertedIntoTree(false);
803 for (RefPtr<Node> child = m_firstChild; child; child = child->nextSibling()) {
804 // Guard against mutation during re-parenting.
805 if (!inDocument()) // Check for self being removed from document while reparenting.
807 if (child->parentNode() != this) // Check for child being removed from subtree while reparenting.
809 child->insertedIntoDocument();
813 void ContainerNode::removedFromDocument()
815 Node::removedFromDocument();
816 if (document()->cssTarget() == this)
817 document()->setCSSTarget(0);
819 removedFromTree(false);
820 for (Node* child = m_firstChild; child; child = child->nextSibling())
821 child->removedFromDocument();
824 void ContainerNode::insertedIntoTree(bool deep)
828 for (Node* child = m_firstChild; child; child = child->nextSibling())
829 child->insertedIntoTree(true);
832 void ContainerNode::removedFromTree(bool deep)
836 for (Node* child = m_firstChild; child; child = child->nextSibling())
837 child->removedFromTree(true);
840 void ContainerNode::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
842 Node::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
843 if (!changedByParser && childCountDelta)
844 document()->nodeChildrenChanged(this);
845 if (treeScope()->hasNodeListCaches())
846 notifyNodeListsChildrenChanged();
849 void ContainerNode::cloneChildNodes(ContainerNode *clone)
851 // disable the delete button so it's elements are not serialized into the markup
852 bool isEditorEnabled = false;
853 if (document()->frame() && document()->frame()->editor()->canEdit()) {
854 FrameSelection* selection = document()->frame()->selection();
855 Element* root = selection ? selection->rootEditableElement() : 0;
856 isEditorEnabled = root && isDescendantOf(root);
859 document()->frame()->editor()->deleteButtonController()->disable();
862 ExceptionCode ec = 0;
863 for (Node* n = firstChild(); n && !ec; n = n->nextSibling())
864 clone->appendChild(n->cloneNode(true), ec);
865 if (isEditorEnabled && document()->frame())
866 document()->frame()->editor()->deleteButtonController()->enable();
869 bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const
873 // What is this code really trying to do?
874 RenderObject *o = renderer();
877 if (!o->isInline() || o->isReplaced()) {
878 point = o->localToAbsolute(FloatPoint(), false, true);
882 // find the next text/image child, to get a position
887 else if (o->nextSibling())
888 o = o->nextSibling();
890 RenderObject *next = 0;
891 while (!next && o->parent()) {
893 next = o->nextSibling();
902 if (!o->isInline() || o->isReplaced()) {
903 point = o->localToAbsolute(FloatPoint(), false, true);
907 if (p->node() && p->node() == this && o->isText() && !o->isBR() && !toRenderText(o)->firstTextBox()) {
908 // do nothing - skip unrendered whitespace that is a child or next sibling of the anchor
909 } else if ((o->isText() && !o->isBR()) || o->isReplaced()) {
910 point = FloatPoint();
911 if (o->isText() && toRenderText(o)->firstTextBox()) {
912 point.move(toRenderText(o)->linesBoundingBox().x(),
913 toRenderText(o)->firstTextBox()->root()->lineTop());
914 } else if (o->isBox()) {
915 RenderBox* box = toRenderBox(o);
916 point.moveBy(box->location());
918 point = o->container()->localToAbsolute(point, false, true);
923 // If the target doesn't have any children or siblings that could be used to calculate the scroll position, we must be
924 // at the end of the document. Scroll to the bottom. FIXME: who said anything about scrolling?
925 if (!o && document()->view()) {
926 point = FloatPoint(0, document()->view()->contentsHeight());
932 // FIXME: This doesn't work correctly with transforms.
933 bool ContainerNode::getLowerRightCorner(FloatPoint& point) const
938 RenderObject* o = renderer();
939 if (!o->isInline() || o->isReplaced()) {
940 RenderBox* box = toRenderBox(o);
941 point = o->localToAbsolute(FloatPoint(), false, true);
942 point.move(box->size());
946 // find the last text/image child, to get a position
950 else if (o->previousSibling())
951 o = o->previousSibling();
953 RenderObject* prev = 0;
958 prev = o->previousSibling();
963 if (o->isText() || o->isReplaced()) {
964 point = FloatPoint();
966 RenderText* text = toRenderText(o);
967 LayoutRect linesBox = text->linesBoundingBox();
968 if (!linesBox.maxX() && !linesBox.maxY())
970 point.moveBy(linesBox.maxXMaxYCorner());
972 RenderBox* box = toRenderBox(o);
973 point.moveBy(box->frameRect().maxXMaxYCorner());
975 point = o->container()->localToAbsolute(point, false, true);
982 LayoutRect ContainerNode::getRect() const
984 FloatPoint upperLeft, lowerRight;
985 bool foundUpperLeft = getUpperLeftCorner(upperLeft);
986 bool foundLowerRight = getLowerRightCorner(lowerRight);
988 // If we've found one corner, but not the other,
989 // then we should just return a point at the corner that we did find.
990 if (foundUpperLeft != foundLowerRight) {
992 lowerRight = upperLeft;
994 upperLeft = lowerRight;
997 return enclosingLayoutRect(FloatRect(upperLeft, lowerRight.expandedTo(upperLeft) - upperLeft));
1000 void ContainerNode::setFocus(bool received)
1002 if (focused() == received)
1005 Node::setFocus(received);
1007 // note that we need to recalc the style
1008 setNeedsStyleRecalc();
1011 void ContainerNode::setActive(bool down, bool pause)
1013 if (down == active()) return;
1015 Node::setActive(down);
1017 // note that we need to recalc the style
1018 // FIXME: Move to Element
1020 bool reactsToPress = renderer()->style()->affectedByActiveRules();
1022 setNeedsStyleRecalc();
1023 if (renderer() && renderer()->style()->hasAppearance()) {
1024 if (renderer()->theme()->stateChanged(renderer(), PressedState))
1025 reactsToPress = true;
1027 if (reactsToPress && pause) {
1028 // The delay here is subtle. It relies on an assumption, namely that the amount of time it takes
1029 // to repaint the "down" state of the control is about the same time as it would take to repaint the
1030 // "up" state. Once you assume this, you can just delay for 100ms - that time (assuming that after you
1031 // leave this method, it will be about that long before the flush of the up state happens again).
1032 #ifdef HAVE_FUNC_USLEEP
1033 double startTime = currentTime();
1036 // Ensure there are no pending changes
1037 Document::updateStyleForAllDocuments();
1038 // Do an immediate repaint.
1040 renderer()->repaint(true);
1042 // FIXME: Find a substitute for usleep for Win32.
1043 // Better yet, come up with a way of doing this that doesn't use this sort of thing at all.
1044 #ifdef HAVE_FUNC_USLEEP
1045 // Now pause for a small amount of time (1/10th of a second from before we repainted in the pressed state)
1046 double remainingTime = 0.1 - (currentTime() - startTime);
1047 if (remainingTime > 0)
1048 usleep(static_cast<useconds_t>(remainingTime * 1000000.0));
1054 void ContainerNode::setHovered(bool over)
1056 if (over == hovered()) return;
1058 Node::setHovered(over);
1060 // note that we need to recalc the style
1061 // FIXME: Move to Element
1063 if (renderer()->style()->affectedByHoverRules())
1064 setNeedsStyleRecalc();
1065 if (renderer() && renderer()->style()->hasAppearance())
1066 renderer()->theme()->stateChanged(renderer(), HoverState);
1070 unsigned ContainerNode::childNodeCount() const
1074 for (n = firstChild(); n; n = n->nextSibling())
1079 Node *ContainerNode::childNode(unsigned index) const
1082 Node *n = firstChild();
1083 for (i = 0; n != 0 && i < index; i++)
1084 n = n->nextSibling();
1088 static void notifyChildInserted(Node* child)
1090 ASSERT(!eventDispatchForbidden());
1092 #if ENABLE(INSPECTOR)
1093 InspectorInstrumentation::didInsertDOMNode(child->document(), child);
1096 RefPtr<Node> c = child;
1097 RefPtr<Document> document = child->document();
1099 Node* parentOrHostNode = c->parentOrHostNode();
1100 if (parentOrHostNode && parentOrHostNode->inDocument())
1101 c->insertedIntoDocument();
1103 c->insertedIntoTree(true);
1105 document->incDOMTreeVersion();
1108 static void dispatchChildInsertionEvents(Node* child)
1110 ASSERT(!eventDispatchForbidden());
1112 RefPtr<Node> c = child;
1113 RefPtr<Document> document = child->document();
1115 #if ENABLE(MUTATION_OBSERVERS)
1116 if (c->parentNode()) {
1117 ChildListMutationScope mutation(c->parentNode());
1118 mutation.childAdded(c.get());
1122 if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
1123 c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
1125 // dispatch the DOMNodeInsertedIntoDocument event to all descendants
1126 if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) {
1127 for (; c; c = c->traverseNextNode(child))
1128 c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false));
1132 static void dispatchChildRemovalEvents(Node* child)
1134 ASSERT(!eventDispatchForbidden());
1136 #if ENABLE(INSPECTOR)
1137 InspectorInstrumentation::willRemoveDOMNode(child->document(), child);
1140 RefPtr<Node> c = child;
1141 RefPtr<Document> document = child->document();
1143 #if ENABLE(MUTATION_OBSERVERS)
1144 if (c->parentNode()) {
1145 ChildListMutationScope mutation(c->parentNode());
1146 mutation.willRemoveChild(c.get());
1147 c->notifyMutationObserversNodeWillDetach();
1151 // dispatch pre-removal mutation events
1152 if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER))
1153 c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode()));
1155 // dispatch the DOMNodeRemovedFromDocument event to all descendants
1156 if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) {
1157 for (; c; c = c->traverseNextNode(child))
1158 c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false));
1162 bool ContainerNode::dispatchBeforeLoadEvent(const String& sourceURL)
1164 if (!document()->hasListenerType(Document::BEFORELOAD_LISTENER))
1167 RefPtr<ContainerNode> protector(this);
1168 RefPtr<BeforeLoadEvent> beforeLoadEvent = BeforeLoadEvent::create(sourceURL);
1169 dispatchEvent(beforeLoadEvent.get());
1170 return !beforeLoadEvent->defaultPrevented();
1173 } // namespace WebCore