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 "MemoryCache.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 "MutationEvent.h"
38 #include "ResourceLoadScheduler.h"
40 #include "RenderBox.h"
41 #include "RenderTheme.h"
42 #include "RootInlineBox.h"
43 #include <wtf/CurrentTime.h>
44 #include <wtf/Vector.h>
50 static void notifyChildInserted(Node*);
51 static void dispatchChildInsertionEvents(Node*);
52 static void dispatchChildRemovalEvents(Node*);
54 typedef pair<RefPtr<Node>, unsigned> CallbackParameters;
55 typedef pair<NodeCallback, CallbackParameters> CallbackInfo;
56 typedef Vector<CallbackInfo> NodeCallbackQueue;
58 typedef Vector<RefPtr<Node>, 1> NodeVector;
59 static NodeCallbackQueue* s_postAttachCallbackQueue;
61 static size_t s_attachDepth;
62 static bool s_shouldReEnableMemoryCacheCallsAfterAttach;
64 static inline void collectNodes(Node* node, NodeVector& nodes)
66 for (Node* child = node->firstChild(); child; child = child->nextSibling())
70 static void collectTargetNodes(Node* node, NodeVector& nodes)
72 if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) {
76 collectNodes(node, nodes);
79 void ContainerNode::removeAllChildren()
81 removeAllChildrenInContainer<Node, ContainerNode>(this);
84 void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent)
87 collectNodes(oldParent, children);
88 oldParent->removeAllChildren();
90 for (unsigned i = 0; i < children.size(); ++i) {
92 if (children[i]->attached())
93 children[i]->detach();
94 // FIXME: We need a no mutation event version of adoptNode.
95 RefPtr<Node> child = document()->adoptNode(children[i].release(), ec);
97 parserAddChild(child.get());
98 // FIXME: Together with adoptNode above, the tree scope might get updated recursively twice
99 // (if the document changed or oldParent was in a shadow tree, AND *this is in a shadow tree).
101 child->setTreeScopeRecursively(treeScope());
102 if (attached() && !child->attached())
107 ContainerNode::~ContainerNode()
112 bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach)
114 // Check that this node is not "floating".
115 // If it is, it can be deleted as a side effect of sending mutation events.
116 ASSERT(refCount() || parentOrHostNode());
120 // insertBefore(node, 0) is equivalent to appendChild(node)
122 return appendChild(newChild, ec, shouldLazyAttach);
124 // Make sure adding the new child is OK.
125 checkAddChild(newChild.get(), ec);
129 // NOT_FOUND_ERR: Raised if refChild is not a child of this node
130 if (refChild->parentNode() != this) {
136 collectTargetNodes(newChild.get(), targets);
137 if (targets.isEmpty())
140 // Now actually add the child(ren)
141 if (refChild->previousSibling() == newChild || refChild == newChild) // nothing to do
144 RefPtr<Node> next = refChild;
145 RefPtr<Node> refChildPreviousSibling = refChild->previousSibling();
146 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
147 Node* child = it->get();
149 // If child is already present in the tree, first remove it from the old location.
150 if (ContainerNode* oldParent = child->parentNode())
151 oldParent->removeChild(child, ec);
155 // FIXME: After sending the mutation events, "this" could be destroyed.
156 // We can prevent that by doing a "ref", but first we have to make sure
157 // that no callers call with ref count == 0 and parent = 0 (as of this
158 // writing, there are definitely callers who call that way).
160 // Due to arbitrary code running in response to a DOM mutation event it's
161 // possible that "next" is no longer a child of "this".
162 // It's also possible that "child" has been inserted elsewhere.
163 // In either of those cases, we'll just stop.
164 if (next->parentNode() != this)
166 if (child->parentNode())
169 #if ENABLE(INSPECTOR)
170 InspectorInstrumentation::willInsertDOMNode(document(), child, this);
173 child->setTreeScopeRecursively(treeScope());
175 insertBeforeCommon(next.get(), child);
177 // Send notification about the children change.
178 childrenChanged(false, refChildPreviousSibling.get(), next.get(), 1);
179 notifyChildInserted(child);
181 // Add child to the rendering tree.
182 if (attached() && !child->attached() && child->parentNode() == this) {
183 if (shouldLazyAttach)
189 // Now that the child is attached to the render tree, dispatch
190 // the relevant mutation events.
191 dispatchChildInsertionEvents(child);
194 dispatchSubtreeModifiedEvent();
198 void ContainerNode::insertBeforeCommon(Node* nextChild, Node* newChild)
201 ASSERT(!newChild->parentNode()); // Use insertBefore if you need to handle reparenting (and want DOM mutation events).
202 ASSERT(!newChild->nextSibling());
203 ASSERT(!newChild->previousSibling());
205 forbidEventDispatch();
206 Node* prev = nextChild->previousSibling();
207 ASSERT(m_lastChild != prev);
208 nextChild->setPreviousSibling(newChild);
210 ASSERT(m_firstChild != nextChild);
211 ASSERT(prev->nextSibling() == nextChild);
212 prev->setNextSibling(newChild);
214 ASSERT(m_firstChild == nextChild);
215 m_firstChild = newChild;
217 newChild->setParent(this);
218 newChild->setPreviousSibling(prev);
219 newChild->setNextSibling(nextChild);
220 allowEventDispatch();
223 void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node* nextChild)
227 ASSERT(nextChild->parentNode() == this);
230 collectTargetNodes(newChild.get(), targets);
231 if (targets.isEmpty())
234 if (nextChild->previousSibling() == newChild || nextChild == newChild) // nothing to do
237 RefPtr<Node> next = nextChild;
238 RefPtr<Node> nextChildPreviousSibling = nextChild->previousSibling();
239 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
240 Node* child = it->get();
242 #if ENABLE(INSPECTOR)
243 InspectorInstrumentation::willInsertDOMNode(document(), child, this);
246 insertBeforeCommon(next.get(), child);
248 childrenChanged(true, nextChildPreviousSibling.get(), nextChild, 1);
249 notifyChildInserted(child);
253 bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, bool shouldLazyAttach)
255 // Check that this node is not "floating".
256 // If it is, it can be deleted as a side effect of sending mutation events.
257 ASSERT(refCount() || parentOrHostNode());
261 if (oldChild == newChild) // nothing to do
264 // Make sure replacing the old child with the new is ok
265 checkReplaceChild(newChild.get(), oldChild, ec);
269 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
270 if (!oldChild || oldChild->parentNode() != this) {
275 RefPtr<Node> prev = oldChild->previousSibling();
276 RefPtr<Node> next = oldChild->nextSibling();
278 // Remove the node we're replacing
279 RefPtr<Node> removedChild = oldChild;
280 removeChild(oldChild, ec);
284 // FIXME: After sending the mutation events, "this" could be destroyed.
285 // We can prevent that by doing a "ref", but first we have to make sure
286 // that no callers call with ref count == 0 and parent = 0 (as of this
287 // writing, there are definitely callers who call that way).
289 bool isFragment = newChild->nodeType() == DOCUMENT_FRAGMENT_NODE;
291 // Add the new child(ren)
292 RefPtr<Node> child = isFragment ? newChild->firstChild() : newChild;
294 // If the new child is already in the right place, we're done.
295 if (prev && (prev == child || prev == child->previousSibling()))
298 // For a fragment we have more children to do.
299 RefPtr<Node> nextChild = isFragment ? child->nextSibling() : 0;
301 // Remove child from its old position.
302 if (ContainerNode* oldParent = child->parentNode())
303 oldParent->removeChild(child.get(), ec);
307 // Due to arbitrary code running in response to a DOM mutation event it's
308 // possible that "prev" is no longer a child of "this".
309 // It's also possible that "child" has been inserted elsewhere.
310 // In either of those cases, we'll just stop.
311 if (prev && prev->parentNode() != this)
313 if (child->parentNode())
316 ASSERT(!child->nextSibling());
317 ASSERT(!child->previousSibling());
319 #if ENABLE(INSPECTOR)
320 InspectorInstrumentation::willInsertDOMNode(document(), child.get(), this);
323 child->setTreeScopeRecursively(treeScope());
325 // Add child after "prev".
326 forbidEventDispatch();
329 next = prev->nextSibling();
330 ASSERT(m_firstChild != next);
331 prev->setNextSibling(child.get());
334 m_firstChild = child.get();
337 ASSERT(m_lastChild != prev);
338 ASSERT(next->previousSibling() == prev);
339 next->setPreviousSibling(child.get());
341 ASSERT(m_lastChild == prev);
342 m_lastChild = child.get();
344 child->setParent(this);
345 child->setPreviousSibling(prev.get());
346 child->setNextSibling(next);
347 allowEventDispatch();
349 childrenChanged(false, prev.get(), next, 1);
350 notifyChildInserted(child.get());
352 // Add child to the rendering tree
353 if (attached() && !child->attached() && child->parentNode() == this) {
354 if (shouldLazyAttach)
360 // Now that the child is attached to the render tree, dispatch
361 // the relevant mutation events.
362 dispatchChildInsertionEvents(child.get());
365 child = nextChild.release();
368 dispatchSubtreeModifiedEvent();
372 void ContainerNode::willRemove()
374 RefPtr<Node> protect(this);
376 for (RefPtr<Node> child = firstChild(); child; child = child->nextSibling()) {
377 if (child->parentNode() != this) // Check for child being removed from subtree while removing.
384 static void willRemoveChild(Node* child)
386 // update auxiliary doc info (e.g. iterators) to note that node is being removed
387 child->document()->nodeWillBeRemoved(child);
388 child->document()->incDOMTreeVersion();
390 // fire removed from document mutation events.
391 dispatchChildRemovalEvents(child);
395 static void willRemoveChildren(ContainerNode* container)
397 container->document()->nodeChildrenWillBeRemoved(container);
398 container->document()->incDOMTreeVersion();
401 collectNodes(container, children);
403 for (NodeVector::const_iterator it = children.begin(); it != children.end(); it++) {
404 Node* child = it->get();
405 // fire removed from document mutation events.
406 dispatchChildRemovalEvents(child);
411 bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec)
413 // Check that this node is not "floating".
414 // If it is, it can be deleted as a side effect of sending mutation events.
415 ASSERT(refCount() || parentOrHostNode());
419 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
420 if (isReadOnlyNode()) {
421 ec = NO_MODIFICATION_ALLOWED_ERR;
425 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
426 if (!oldChild || oldChild->parentNode() != this) {
431 RefPtr<Node> child = oldChild;
432 willRemoveChild(child.get());
434 // Mutation events might have moved this child into a different parent.
435 if (child->parentNode() != this) {
440 document()->removeFocusedNodeOfSubtree(child.get());
442 #if ENABLE(FULLSCREEN_API)
443 document()->removeFullScreenElementOfSubtree(child.get());
447 // Events fired when blurring currently focused node might have moved this
448 // child into a different parent.
449 if (child->parentNode() != this) {
454 // FIXME: After sending the mutation events, "this" could be destroyed.
455 // We can prevent that by doing a "ref", but first we have to make sure
456 // that no callers call with ref count == 0 and parent = 0 (as of this
457 // writing, there are definitely callers who call that way).
459 Node* prev = child->previousSibling();
460 Node* next = child->nextSibling();
461 removeBetween(prev, next, child.get());
463 // Dispatch post-removal mutation events
464 childrenChanged(false, prev, next, -1);
465 dispatchSubtreeModifiedEvent();
467 if (child->inDocument())
468 child->removedFromDocument();
470 child->removedFromTree(true);
475 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node* oldChild)
478 ASSERT(oldChild->parentNode() == this);
480 forbidEventDispatch();
482 // Remove from rendering tree
483 if (oldChild->attached())
487 nextChild->setPreviousSibling(previousChild);
489 previousChild->setNextSibling(nextChild);
490 if (m_firstChild == oldChild)
491 m_firstChild = nextChild;
492 if (m_lastChild == oldChild)
493 m_lastChild = previousChild;
495 oldChild->setPreviousSibling(0);
496 oldChild->setNextSibling(0);
497 oldChild->setParent(0);
499 oldChild->setTreeScopeRecursively(document());
501 allowEventDispatch();
504 void ContainerNode::parserRemoveChild(Node* oldChild)
507 ASSERT(oldChild->parentNode() == this);
509 Node* prev = oldChild->previousSibling();
510 Node* next = oldChild->nextSibling();
512 removeBetween(prev, next, oldChild);
514 childrenChanged(true, prev, next, -1);
515 if (oldChild->inDocument())
516 oldChild->removedFromDocument();
518 oldChild->removedFromTree(true);
521 // this differs from other remove functions because it forcibly removes all the children,
522 // regardless of read-only status or event exceptions, e.g.
523 void ContainerNode::removeChildren()
528 // The container node can be removed from event handlers.
529 RefPtr<ContainerNode> protect(this);
531 // Do any prep work needed before actually starting to detach
532 // and remove... e.g. stop loading frames, fire unload events.
533 willRemoveChildren(protect.get());
535 // exclude this node when looking for removed focusedNode since only children will be removed
536 document()->removeFocusedNodeOfSubtree(this, true);
538 #if ENABLE(FULLSCREEN_API)
539 document()->removeFullScreenElementOfSubtree(this, true);
542 forbidEventDispatch();
543 Vector<RefPtr<Node>, 10> removedChildren;
544 removedChildren.reserveInitialCapacity(childNodeCount());
545 while (RefPtr<Node> n = m_firstChild) {
546 Node* next = n->nextSibling();
548 // Remove the node from the tree before calling detach or removedFromDocument (4427024, 4129744).
549 // removeChild() does this after calling detach(). There is no explanation for
550 // this discrepancy between removeChild() and its optimized version removeChildren().
551 n->setPreviousSibling(0);
552 n->setNextSibling(0);
554 n->setTreeScopeRecursively(document());
557 if (n == m_lastChild)
559 removedChildren.append(n.release());
562 size_t removedChildrenCount = removedChildren.size();
565 // Detach the nodes only after properly removed from the tree because
566 // a. detaching requires a proper DOM tree (for counters and quotes for
567 // example) and during the previous loop the next sibling still points to
568 // the node being removed while the node being removed does not point back
569 // and does not point to the same parent as its next sibling.
570 // b. destroying Renderers of standalone nodes is sometimes faster.
571 for (i = 0; i < removedChildrenCount; ++i) {
572 Node* removedChild = removedChildren[i].get();
573 if (removedChild->attached())
574 removedChild->detach();
577 allowEventDispatch();
579 // Dispatch a single post-removal mutation event denoting a modified subtree.
580 childrenChanged(false, 0, 0, -static_cast<int>(removedChildrenCount));
581 dispatchSubtreeModifiedEvent();
583 for (i = 0; i < removedChildrenCount; ++i) {
584 Node* removedChild = removedChildren[i].get();
585 if (removedChild->inDocument())
586 removedChild->removedFromDocument();
587 // removeChild() calls removedFromTree(true) if the child was not in the
588 // document. There is no explanation for this discrepancy between removeChild()
589 // and its optimized version removeChildren().
593 bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach)
595 // Check that this node is not "floating".
596 // If it is, it can be deleted as a side effect of sending mutation events.
597 ASSERT(refCount() || parentOrHostNode());
601 // Make sure adding the new child is ok
602 checkAddChild(newChild.get(), ec);
606 if (newChild == m_lastChild) // nothing to do
610 collectTargetNodes(newChild.get(), targets);
611 if (targets.isEmpty())
614 // Now actually add the child(ren)
615 RefPtr<Node> prev = lastChild();
616 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
617 Node* child = it->get();
618 // If child is already present in the tree, first remove it
619 if (ContainerNode* oldParent = child->parentNode()) {
620 oldParent->removeChild(child, ec);
624 // If the child has a parent again, just stop what we're doing, because
625 // that means someone is doing something with DOM mutation -- can't re-parent
626 // a child that already has a parent.
627 if (child->parentNode())
631 #if ENABLE(INSPECTOR)
632 InspectorInstrumentation::willInsertDOMNode(document(), child, this);
635 child->setTreeScopeRecursively(treeScope());
637 // Append child to the end of the list
638 forbidEventDispatch();
639 child->setParent(this);
641 child->setPreviousSibling(m_lastChild);
642 m_lastChild->setNextSibling(child);
644 m_firstChild = child;
646 allowEventDispatch();
648 // Send notification about the children change.
649 childrenChanged(false, prev.get(), 0, 1);
650 notifyChildInserted(child);
652 // Add child to the rendering tree
653 if (attached() && !child->attached() && child->parentNode() == this) {
654 if (shouldLazyAttach)
660 // Now that the child is attached to the render tree, dispatch
661 // the relevant mutation events.
662 dispatchChildInsertionEvents(child);
666 dispatchSubtreeModifiedEvent();
670 void ContainerNode::parserAddChild(PassRefPtr<Node> newChild)
673 ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events).
675 #if ENABLE(INSPECTOR)
676 InspectorInstrumentation::willInsertDOMNode(document(), newChild.get(), this);
679 forbidEventDispatch();
680 Node* last = m_lastChild;
681 // FIXME: This method should take a PassRefPtr.
682 appendChildToContainer<Node, ContainerNode>(newChild.get(), this);
683 newChild->setTreeScopeRecursively(treeScope());
685 allowEventDispatch();
687 // FIXME: Why doesn't this use notifyChildInserted(newChild) instead?
688 document()->incDOMTreeVersion();
690 newChild->insertedIntoDocument();
691 childrenChanged(true, last, 0, 1);
694 void ContainerNode::suspendPostAttachCallbacks()
696 if (!s_attachDepth) {
697 ASSERT(!s_shouldReEnableMemoryCacheCallsAfterAttach);
698 if (Page* page = document()->page()) {
699 if (page->areMemoryCacheClientCallsEnabled()) {
700 page->setMemoryCacheClientCallsEnabled(false);
701 s_shouldReEnableMemoryCacheCallsAfterAttach = true;
704 resourceLoadScheduler()->suspendPendingRequests();
709 void ContainerNode::resumePostAttachCallbacks()
711 if (s_attachDepth == 1) {
712 if (s_postAttachCallbackQueue)
713 dispatchPostAttachCallbacks();
714 if (s_shouldReEnableMemoryCacheCallsAfterAttach) {
715 s_shouldReEnableMemoryCacheCallsAfterAttach = false;
716 if (Page* page = document()->page())
717 page->setMemoryCacheClientCallsEnabled(true);
719 resourceLoadScheduler()->resumePendingRequests();
724 void ContainerNode::queuePostAttachCallback(NodeCallback callback, Node* node, unsigned callbackData)
726 if (!s_postAttachCallbackQueue)
727 s_postAttachCallbackQueue = new NodeCallbackQueue;
729 s_postAttachCallbackQueue->append(CallbackInfo(callback, CallbackParameters(node, callbackData)));
732 bool ContainerNode::postAttachCallbacksAreSuspended()
734 return s_attachDepth;
737 void ContainerNode::dispatchPostAttachCallbacks()
739 // We recalculate size() each time through the loop because a callback
740 // can add more callbacks to the end of the queue.
741 for (size_t i = 0; i < s_postAttachCallbackQueue->size(); ++i) {
742 const CallbackInfo& info = (*s_postAttachCallbackQueue)[i];
743 NodeCallback callback = info.first;
744 CallbackParameters params = info.second;
746 callback(params.first.get(), params.second);
748 s_postAttachCallbackQueue->clear();
751 static void needsStyleRecalcCallback(Node* node, unsigned data)
753 node->setNeedsStyleRecalc(static_cast<StyleChangeType>(data));
756 void ContainerNode::scheduleSetNeedsStyleRecalc(StyleChangeType changeType)
758 if (postAttachCallbacksAreSuspended())
759 queuePostAttachCallback(needsStyleRecalcCallback, this, static_cast<unsigned>(changeType));
761 setNeedsStyleRecalc(changeType);
764 void ContainerNode::attach()
766 for (Node* child = m_firstChild; child; child = child->nextSibling())
771 void ContainerNode::detach()
773 for (Node* child = m_firstChild; child; child = child->nextSibling())
775 clearChildNeedsStyleRecalc();
779 void ContainerNode::insertedIntoDocument()
781 RefPtr<Node> protect(this);
783 Node::insertedIntoDocument();
784 insertedIntoTree(false);
786 for (RefPtr<Node> child = m_firstChild; child; child = child->nextSibling()) {
787 // Guard against mutation during re-parenting.
788 if (!inDocument()) // Check for self being removed from document while reparenting.
790 if (child->parentNode() != this) // Check for child being removed from subtree while reparenting.
792 child->insertedIntoDocument();
796 void ContainerNode::removedFromDocument()
798 Node::removedFromDocument();
799 if (document()->cssTarget() == this)
800 document()->setCSSTarget(0);
802 removedFromTree(false);
803 for (Node* child = m_firstChild; child; child = child->nextSibling())
804 child->removedFromDocument();
807 void ContainerNode::insertedIntoTree(bool deep)
811 for (Node* child = m_firstChild; child; child = child->nextSibling())
812 child->insertedIntoTree(true);
815 void ContainerNode::removedFromTree(bool deep)
819 for (Node* child = m_firstChild; child; child = child->nextSibling())
820 child->removedFromTree(true);
823 void ContainerNode::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
825 Node::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
826 if (!changedByParser && childCountDelta)
827 document()->nodeChildrenChanged(this);
828 if (treeScope()->hasNodeListCaches())
829 notifyNodeListsChildrenChanged();
832 void ContainerNode::cloneChildNodes(ContainerNode *clone)
834 // disable the delete button so it's elements are not serialized into the markup
835 bool isEditorEnabled = false;
836 if (document()->frame() && document()->frame()->editor()->canEdit()) {
837 FrameSelection* selection = document()->frame()->selection();
838 Element* root = selection ? selection->rootEditableElement() : 0;
839 isEditorEnabled = root && isDescendantOf(root);
842 document()->frame()->editor()->deleteButtonController()->disable();
845 ExceptionCode ec = 0;
846 for (Node* n = firstChild(); n && !ec; n = n->nextSibling())
847 clone->appendChild(n->cloneNode(true), ec);
848 if (isEditorEnabled && document()->frame())
849 document()->frame()->editor()->deleteButtonController()->enable();
852 bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const
856 // What is this code really trying to do?
857 RenderObject *o = renderer();
860 if (!o->isInline() || o->isReplaced()) {
861 point = o->localToAbsolute(FloatPoint(), false, true);
865 // find the next text/image child, to get a position
870 else if (o->nextSibling())
871 o = o->nextSibling();
873 RenderObject *next = 0;
874 while (!next && o->parent()) {
876 next = o->nextSibling();
885 if (!o->isInline() || o->isReplaced()) {
886 point = o->localToAbsolute(FloatPoint(), false, true);
890 if (p->node() && p->node() == this && o->isText() && !o->isBR() && !toRenderText(o)->firstTextBox()) {
891 // do nothing - skip unrendered whitespace that is a child or next sibling of the anchor
892 } else if ((o->isText() && !o->isBR()) || o->isReplaced()) {
893 point = FloatPoint();
894 if (o->isText() && toRenderText(o)->firstTextBox()) {
895 point.move(toRenderText(o)->linesBoundingBox().x(),
896 toRenderText(o)->firstTextBox()->root()->lineTop());
897 } else if (o->isBox()) {
898 RenderBox* box = toRenderBox(o);
899 point.moveBy(box->location());
901 point = o->container()->localToAbsolute(point, false, true);
906 // If the target doesn't have any children or siblings that could be used to calculate the scroll position, we must be
907 // at the end of the document. Scroll to the bottom. FIXME: who said anything about scrolling?
908 if (!o && document()->view()) {
909 point = FloatPoint(0, document()->view()->contentsHeight());
915 // FIXME: This doesn't work correctly with transforms.
916 bool ContainerNode::getLowerRightCorner(FloatPoint& point) const
921 RenderObject* o = renderer();
922 if (!o->isInline() || o->isReplaced()) {
923 RenderBox* box = toRenderBox(o);
924 point = o->localToAbsolute(FloatPoint(), false, true);
925 point.move(box->size());
929 // find the last text/image child, to get a position
933 else if (o->previousSibling())
934 o = o->previousSibling();
936 RenderObject* prev = 0;
941 prev = o->previousSibling();
946 if (o->isText() || o->isReplaced()) {
947 point = FloatPoint();
949 RenderText* text = toRenderText(o);
950 LayoutRect linesBox = text->linesBoundingBox();
951 if (!linesBox.maxX() && !linesBox.maxY())
953 point.moveBy(linesBox.maxXMaxYCorner());
955 RenderBox* box = toRenderBox(o);
956 point.moveBy(box->frameRect().maxXMaxYCorner());
958 point = o->container()->localToAbsolute(point, false, true);
965 LayoutRect ContainerNode::getRect() const
967 FloatPoint upperLeft, lowerRight;
968 bool foundUpperLeft = getUpperLeftCorner(upperLeft);
969 bool foundLowerRight = getLowerRightCorner(lowerRight);
971 // If we've found one corner, but not the other,
972 // then we should just return a point at the corner that we did find.
973 if (foundUpperLeft != foundLowerRight) {
975 lowerRight = upperLeft;
977 upperLeft = lowerRight;
980 return enclosingLayoutRect(FloatRect(upperLeft, lowerRight.expandedTo(upperLeft) - upperLeft));
983 void ContainerNode::setFocus(bool received)
985 if (focused() == received)
988 Node::setFocus(received);
990 // note that we need to recalc the style
991 setNeedsStyleRecalc();
994 void ContainerNode::setActive(bool down, bool pause)
996 if (down == active()) return;
998 Node::setActive(down);
1000 // note that we need to recalc the style
1001 // FIXME: Move to Element
1003 bool reactsToPress = renderer()->style()->affectedByActiveRules();
1005 setNeedsStyleRecalc();
1006 if (renderer() && renderer()->style()->hasAppearance()) {
1007 if (renderer()->theme()->stateChanged(renderer(), PressedState))
1008 reactsToPress = true;
1010 if (reactsToPress && pause) {
1011 // The delay here is subtle. It relies on an assumption, namely that the amount of time it takes
1012 // to repaint the "down" state of the control is about the same time as it would take to repaint the
1013 // "up" state. Once you assume this, you can just delay for 100ms - that time (assuming that after you
1014 // leave this method, it will be about that long before the flush of the up state happens again).
1015 #ifdef HAVE_FUNC_USLEEP
1016 double startTime = currentTime();
1019 // Ensure there are no pending changes
1020 Document::updateStyleForAllDocuments();
1021 // Do an immediate repaint.
1023 renderer()->repaint(true);
1025 // FIXME: Find a substitute for usleep for Win32.
1026 // Better yet, come up with a way of doing this that doesn't use this sort of thing at all.
1027 #ifdef HAVE_FUNC_USLEEP
1028 // Now pause for a small amount of time (1/10th of a second from before we repainted in the pressed state)
1029 double remainingTime = 0.1 - (currentTime() - startTime);
1030 if (remainingTime > 0)
1031 usleep(static_cast<useconds_t>(remainingTime * 1000000.0));
1037 void ContainerNode::setHovered(bool over)
1039 if (over == hovered()) return;
1041 Node::setHovered(over);
1043 // note that we need to recalc the style
1044 // FIXME: Move to Element
1046 if (renderer()->style()->affectedByHoverRules())
1047 setNeedsStyleRecalc();
1048 if (renderer() && renderer()->style()->hasAppearance())
1049 renderer()->theme()->stateChanged(renderer(), HoverState);
1053 unsigned ContainerNode::childNodeCount() const
1057 for (n = firstChild(); n; n = n->nextSibling())
1062 Node *ContainerNode::childNode(unsigned index) const
1065 Node *n = firstChild();
1066 for (i = 0; n != 0 && i < index; i++)
1067 n = n->nextSibling();
1071 static void notifyChildInserted(Node* child)
1073 ASSERT(!eventDispatchForbidden());
1075 #if ENABLE(INSPECTOR)
1076 InspectorInstrumentation::didInsertDOMNode(child->document(), child);
1079 RefPtr<Node> c = child;
1080 RefPtr<Document> document = child->document();
1082 Node* parentOrHostNode = c->parentOrHostNode();
1083 if (parentOrHostNode && parentOrHostNode->inDocument())
1084 c->insertedIntoDocument();
1086 c->insertedIntoTree(true);
1088 document->incDOMTreeVersion();
1091 static void dispatchChildInsertionEvents(Node* child)
1093 ASSERT(!eventDispatchForbidden());
1095 RefPtr<Node> c = child;
1096 RefPtr<Document> document = child->document();
1098 if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
1099 c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
1101 // dispatch the DOMNodeInsertedIntoDocument event to all descendants
1102 if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) {
1103 for (; c; c = c->traverseNextNode(child))
1104 c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false));
1108 static void dispatchChildRemovalEvents(Node* child)
1110 ASSERT(!eventDispatchForbidden());
1112 #if ENABLE(INSPECTOR)
1113 InspectorInstrumentation::willRemoveDOMNode(child->document(), child);
1116 RefPtr<Node> c = child;
1117 RefPtr<Document> document = child->document();
1119 // dispatch pre-removal mutation events
1120 if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER))
1121 c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode()));
1123 // dispatch the DOMNodeRemovedFromDocument event to all descendants
1124 if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) {
1125 for (; c; c = c->traverseNextNode(child))
1126 c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false));
1130 bool ContainerNode::dispatchBeforeLoadEvent(const String& sourceURL)
1132 if (!document()->hasListenerType(Document::BEFORELOAD_LISTENER))
1135 RefPtr<ContainerNode> protector(this);
1136 RefPtr<BeforeLoadEvent> beforeLoadEvent = BeforeLoadEvent::create(sourceURL);
1137 dispatchEvent(beforeLoadEvent.get());
1138 return !beforeLoadEvent->defaultPrevented();
1141 } // namespace WebCore