summaryrefslogtreecommitdiffstats
path: root/WebCore/rendering/RenderWidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/rendering/RenderWidget.cpp')
-rw-r--r--WebCore/rendering/RenderWidget.cpp152
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()) {