diff options
Diffstat (limited to 'WebCore/rendering/RenderWidget.cpp')
-rw-r--r-- | WebCore/rendering/RenderWidget.cpp | 152 |
1 files changed, 94 insertions, 58 deletions
diff --git a/WebCore/rendering/RenderWidget.cpp b/WebCore/rendering/RenderWidget.cpp index 5a5c9f1..33f03e2 100644 --- a/WebCore/rendering/RenderWidget.cpp +++ b/WebCore/rendering/RenderWidget.cpp @@ -23,8 +23,8 @@ #include "config.h" #include "RenderWidget.h" -#include "AnimationController.h" #include "AXObjectCache.h" +#include "AnimationController.h" #include "GraphicsContext.h" #include "HitTestResult.h" #include "RenderView.h" @@ -40,18 +40,65 @@ static HashMap<const Widget*, RenderWidget*>& widgetRendererMap() return *staticWidgetRendererMap; } +static size_t widgetHierarchyUpdateSuspendCount; + +typedef HashMap<RefPtr<Widget>, FrameView*> WidgetToParentMap; + +static WidgetToParentMap& widgetNewParentMap() +{ + DEFINE_STATIC_LOCAL(WidgetToParentMap, map, ()); + return map; +} + +void RenderWidget::suspendWidgetHierarchyUpdates() +{ + widgetHierarchyUpdateSuspendCount++; +} + +void RenderWidget::resumeWidgetHierarchyUpdates() +{ + ASSERT(widgetHierarchyUpdateSuspendCount); + if (widgetHierarchyUpdateSuspendCount == 1) { + WidgetToParentMap map = widgetNewParentMap(); + widgetNewParentMap().clear(); + WidgetToParentMap::iterator end = map.end(); + for (WidgetToParentMap::iterator it = map.begin(); it != end; ++it) { + Widget* child = it->first.get(); + ScrollView* currentParent = child->parent(); + FrameView* newParent = it->second; + if (newParent != currentParent) { + if (currentParent) + currentParent->removeChild(child); + if (newParent) + newParent->addChild(child); + } + } + } + widgetHierarchyUpdateSuspendCount--; +} + +static void moveWidgetToParentSoon(Widget* child, FrameView* parent) +{ + if (!widgetHierarchyUpdateSuspendCount) { + if (parent) + parent->addChild(child); + else + child->removeFromParent(); + return; + } + widgetNewParentMap().set(child, parent); +} + RenderWidget::RenderWidget(Node* node) : RenderReplaced(node) , m_widget(0) , m_frameView(node->document()->view()) - , m_refCount(0) -{ - view()->addWidget(this); - // Reference counting is used to prevent the widget from being // destroyed while inside the Widget code, which might not be // able to handle that. - ref(); + , m_refCount(1) +{ + view()->addWidget(this); } void RenderWidget::destroy() @@ -62,14 +109,6 @@ void RenderWidget::destroy() // both RenderBox::destroy() and RenderObject::destroy(). // Fix originally made for <rdar://problem/4228818>. - // <rdar://problem/6937089> suggests that node() can be null by the time we call renderArena() - // in the end of this function. One way this might happen is if this function was invoked twice - // in a row, so bail out and turn a crash into an assertion failure in debug builds and a leak - // in release builds. - ASSERT(node()); - if (!node()) - return; - animation()->cancelAnimations(this); if (RenderView* v = view()) @@ -81,12 +120,8 @@ void RenderWidget::destroy() } remove(); - if (m_widget) { - if (m_frameView) - m_frameView->removeChild(m_widget.get()); - widgetRendererMap().remove(m_widget.get()); - } - + setWidget(0); + // removes from override size map if (hasOverrideSize()) setOverrideSize(-1); @@ -100,14 +135,6 @@ void RenderWidget::destroy() destroyLayer(); } - // <rdar://problem/6937089> suggests that node() can be null here. One way this might happen is - // if this function was re-entered (and therefore the null check at the beginning did not fail), - // so bail out and turn a crash into an assertion failure in debug builds and a leak in release - // builds. - ASSERT(node()); - if (!node()) - return; - // Grab the arena from node()->document()->renderArena() before clearing the node pointer. // Clear the node before deref-ing, as this may be deleted when deref is called. RenderArena* arena = renderArena(); @@ -121,39 +148,43 @@ RenderWidget::~RenderWidget() clearWidget(); } -void RenderWidget::setWidgetGeometry(const IntRect& frame) +bool RenderWidget::setWidgetGeometry(const IntRect& frame) { - if (node() && m_widget->frameRect() != frame) { - RenderWidgetProtector protector(this); - RefPtr<Node> protectedNode(node()); - m_widget->setFrameRect(frame); - } + ASSERT(!widgetHierarchyUpdateSuspendCount); + if (!node() || m_widget->frameRect() == frame) + return false; + + RenderWidgetProtector protector(this); + RefPtr<Node> protectedNode(node()); + m_widget->setFrameRect(frame); + return true; } void RenderWidget::setWidget(PassRefPtr<Widget> widget) { - if (widget != m_widget) { - if (m_widget) { - m_widget->removeFromParent(); - widgetRendererMap().remove(m_widget.get()); - clearWidget(); - } - m_widget = widget; - if (m_widget) { - widgetRendererMap().add(m_widget.get(), this); - // if we've already received a layout, apply the calculated space to the - // widget immediately, but we have to have really been full constructed (with a non-null - // style pointer). - if (style()) { - if (!needsLayout()) - setWidgetGeometry(absoluteContentBox()); - if (style()->visibility() != VISIBLE) - m_widget->hide(); - else - m_widget->show(); - } - m_frameView->addChild(m_widget.get()); + if (widget == m_widget) + return; + + if (m_widget) { + moveWidgetToParentSoon(m_widget.get(), 0); + widgetRendererMap().remove(m_widget.get()); + clearWidget(); + } + m_widget = widget; + if (m_widget) { + widgetRendererMap().add(m_widget.get(), this); + // If we've already received a layout, apply the calculated space to the + // widget immediately, but we have to have really been fully constructed (with a non-null + // style pointer). + if (style()) { + if (!needsLayout()) + setWidgetGeometry(absoluteContentBox()); + if (style()->visibility() != VISIBLE) + m_widget->hide(); + else + m_widget->show(); } + moveWidgetToParentSoon(m_widget.get(), m_frameView); } } @@ -229,11 +260,11 @@ void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty) // Tell the widget to paint now. This is the only time the widget is allowed // to paint itself. That way it will composite properly with z-indexed layers. if (m_substituteImage) - paintInfo.context->drawImage(m_substituteImage.get(), m_widget->frameRect()); + paintInfo.context->drawImage(m_substituteImage.get(), style()->colorSpace(), m_widget->frameRect()); else m_widget->paint(paintInfo.context, paintInfo.rect); - if (m_widget->isFrameView() && paintInfo.overlapTestRequests && !static_cast<FrameView*>(m_widget.get())->useSlowRepaints()) { + if (m_widget->isFrameView() && paintInfo.overlapTestRequests && !static_cast<FrameView*>(m_widget.get())->useSlowRepaintsIfNotOverlapped()) { ASSERT(!paintInfo.overlapTestRequests->contains(this)); paintInfo.overlapTestRequests->set(this, m_widget->frameRect()); } @@ -245,7 +276,7 @@ void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty) // Paint a partially transparent wash over selected widgets. if (isSelected() && !document()->printing()) { // FIXME: selectionRect() is in absolute, not painting coordinates. - paintInfo.context->fillRect(selectionRect(), selectionBackgroundColor()); + paintInfo.context->fillRect(selectionRect(), selectionBackgroundColor(), style()->colorSpace()); } } @@ -274,6 +305,7 @@ void RenderWidget::updateWidgetPosition() int w = width() - borderLeft() - borderRight() - paddingLeft() - paddingRight(); int h = height() - borderTop() - borderBottom() - paddingTop() - paddingBottom(); +<<<<<<< HEAD:WebCore/rendering/RenderWidget.cpp IntRect newBounds(absPos.x(), absPos.y(), w, h); IntRect oldBounds(m_widget->frameRect()); bool boundsChanged = newBounds != oldBounds; @@ -284,6 +316,10 @@ void RenderWidget::updateWidgetPosition() } #ifndef FLATTEN_IFRAME +======= + bool boundsChanged = setWidgetGeometry(IntRect(absPos.x(), absPos.y(), w, h)); + +>>>>>>> webkit.org at r51976:WebCore/rendering/RenderWidget.cpp // if the frame bounds got changed, or if view needs layout (possibly indicating // content size is wrong) we have to do a layout to set the right widget size if (m_widget->isFrameView()) { |