summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/RenderWidget.cpp
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebCore/rendering/RenderWidget.cpp
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
downloadqtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/WebCore/rendering/RenderWidget.cpp')
-rw-r--r--Source/WebCore/rendering/RenderWidget.cpp274
1 files changed, 134 insertions, 140 deletions
diff --git a/Source/WebCore/rendering/RenderWidget.cpp b/Source/WebCore/rendering/RenderWidget.cpp
index 271b8cfe3..924ea33ef 100644
--- a/Source/WebCore/rendering/RenderWidget.cpp
+++ b/Source/WebCore/rendering/RenderWidget.cpp
@@ -24,21 +24,15 @@
#include "RenderWidget.h"
#include "AXObjectCache.h"
-#include "AnimationController.h"
+#include "FloatRoundedRect.h"
#include "Frame.h"
-#include "GraphicsContext.h"
+#include "HTMLFrameOwnerElement.h"
#include "HitTestResult.h"
-#include "RenderCounter.h"
#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
#include "RenderView.h"
-#include "RenderWidgetProtector.h"
#include <wtf/StackStats.h>
-
-#if USE(ACCELERATED_COMPOSITING)
-#include "RenderLayerBacking.h"
-#endif
-
-using namespace std;
+#include <wtf/Ref.h>
namespace WebCore {
@@ -52,7 +46,7 @@ unsigned WidgetHierarchyUpdatesSuspensionScope::s_widgetHierarchyUpdateSuspendCo
WidgetHierarchyUpdatesSuspensionScope::WidgetToParentMap& WidgetHierarchyUpdatesSuspensionScope::widgetNewParentMap()
{
- DEFINE_STATIC_LOCAL(WidgetToParentMap, map, ());
+ static NeverDestroyed<WidgetToParentMap> map;
return map;
}
@@ -67,7 +61,7 @@ void WidgetHierarchyUpdatesSuspensionScope::moveWidgets()
FrameView* newParent = it->value;
if (newParent != currentParent) {
if (currentParent)
- currentParent->removeChild(child);
+ currentParent->removeChild(*child);
if (newParent)
newParent->addChild(child);
}
@@ -86,48 +80,33 @@ static void moveWidgetToParentSoon(Widget* child, FrameView* parent)
WidgetHierarchyUpdatesSuspensionScope::scheduleWidgetToMove(child, parent);
}
-RenderWidget::RenderWidget(Element* element)
- : RenderReplaced(element)
- , m_widget(0)
- , m_frameView(element->document()->view())
- // Reference counting is used to prevent the widget from being
- // destroyed while inside the Widget code, which might not be
- // able to handle that.
- , m_refCount(1)
+RenderWidget::RenderWidget(HTMLFrameOwnerElement& element, Ref<RenderStyle>&& style)
+ : RenderReplaced(element, WTFMove(style))
+ , m_weakPtrFactory(this)
{
- view()->addWidget(this);
+ setInline(false);
}
void RenderWidget::willBeDestroyed()
{
- if (RenderView* v = view())
- v->removeWidget(this);
-
- if (AXObjectCache* cache = document()->existingAXObjectCache()) {
+#if PLATFORM(IOS)
+ if (hasLayer())
+ layer()->willBeDestroyed();
+#endif
+
+ if (AXObjectCache* cache = document().existingAXObjectCache()) {
cache->childrenChanged(this->parent());
cache->remove(this);
}
- setWidget(0);
+ setWidget(nullptr);
RenderReplaced::willBeDestroyed();
}
-void RenderWidget::destroy()
-{
- willBeDestroyed();
-
- // 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();
- clearNode();
- deref(arena);
-}
-
RenderWidget::~RenderWidget()
{
- ASSERT(m_refCount <= 0);
- clearWidget();
+ ASSERT(!m_refCount);
}
// Widgets are always placed on integer boundaries, so rounding the size is actually
@@ -140,40 +119,39 @@ static inline IntRect roundedIntRect(const LayoutRect& rect)
bool RenderWidget::setWidgetGeometry(const LayoutRect& frame)
{
- if (!node())
- return false;
-
IntRect clipRect = roundedIntRect(enclosingLayer()->childrenClipRect());
- IntRect newFrame = roundedIntRect(frame);
+ IntRect newFrameRect = roundedIntRect(frame);
+ IntRect oldFrameRect = m_widget->frameRect();
bool clipChanged = m_clipRect != clipRect;
- bool boundsChanged = m_widget->frameRect() != newFrame;
+ bool boundsChanged = oldFrameRect != newFrameRect;
if (!boundsChanged && !clipChanged)
return false;
m_clipRect = clipRect;
- RenderWidgetProtector protector(this);
- RefPtr<Node> protectedNode(node());
- m_widget->setFrameRect(newFrame);
-
- if (clipChanged && !boundsChanged)
+ WeakPtr<RenderWidget> weakThis = createWeakPtr();
+ // These calls *may* cause this renderer to disappear from underneath...
+ if (boundsChanged)
+ m_widget->setFrameRect(newFrameRect);
+ else if (clipChanged)
m_widget->clipRectChanged();
-
-#if USE(ACCELERATED_COMPOSITING)
- if (hasLayer() && layer()->isComposited())
+ // ...so we follow up with a sanity check.
+ if (!weakThis)
+ return true;
+
+ if (boundsChanged && isComposited())
layer()->backing()->updateAfterWidgetResize();
-#endif
-
- return boundsChanged;
+
+ return oldFrameRect.size() != newFrameRect.size();
}
bool RenderWidget::updateWidgetGeometry()
{
- LayoutRect contentBox = contentBoxRect();
if (!m_widget->transformsAffectFrameRect())
return setWidgetGeometry(absoluteContentBox());
+ LayoutRect contentBox = contentBoxRect();
LayoutRect absoluteContentBox(localToAbsoluteQuad(FloatQuad(contentBox)).boundingBox());
if (m_widget->isFrameView()) {
contentBox.setLocation(absoluteContentBox.location());
@@ -190,27 +168,32 @@ void RenderWidget::setWidget(PassRefPtr<Widget> widget)
if (m_widget) {
moveWidgetToParentSoon(m_widget.get(), 0);
+ view().frameView().willRemoveWidgetFromRenderTree(*m_widget);
widgetRendererMap().remove(m_widget.get());
- clearWidget();
+ m_widget = nullptr;
}
m_widget = widget;
if (m_widget) {
widgetRendererMap().add(m_widget.get(), this);
+ view().frameView().didAddWidgetToRenderTree(*m_widget);
// 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())
+ // widget immediately, but we have to have really been fully constructed.
+ if (hasInitializedStyle()) {
+ if (!needsLayout()) {
+ WeakPtr<RenderWidget> weakThis = createWeakPtr();
updateWidgetGeometry();
+ if (!weakThis)
+ return;
+ }
- if (style()->visibility() != VISIBLE)
+ if (style().visibility() != VISIBLE)
m_widget->hide();
else {
m_widget->show();
repaint();
}
}
- moveWidgetToParentSoon(m_widget.get(), m_frameView);
+ moveWidgetToParentSoon(m_widget.get(), &view().frameView());
}
}
@@ -219,52 +202,44 @@ void RenderWidget::layout()
StackStats::LayoutCheckPoint layoutCheckPoint;
ASSERT(needsLayout());
- setNeedsLayout(false);
+ clearNeedsLayout();
}
void RenderWidget::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderReplaced::styleDidChange(diff, oldStyle);
if (m_widget) {
- if (style()->visibility() != VISIBLE)
+ if (style().visibility() != VISIBLE)
m_widget->hide();
else
m_widget->show();
}
}
-void RenderWidget::notifyWidget(WidgetNotification notification)
-{
- if (m_widget)
- m_widget->notifyWidget(notification);
-}
-
void RenderWidget::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- LayoutPoint adjustedPaintOffset = paintOffset + location();
-
+ IntPoint contentPaintOffset = roundedIntPoint(paintOffset + location() + contentBoxRect().location());
// 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.
- IntPoint widgetLocation = m_widget->frameRect().location();
- IntPoint paintLocation(roundToInt(adjustedPaintOffset.x() + borderLeft() + paddingLeft()),
- roundToInt(adjustedPaintOffset.y() + borderTop() + paddingTop()));
- IntRect paintRect = paintInfo.rect;
+ LayoutRect paintRect = paintInfo.rect;
- IntSize widgetPaintOffset = paintLocation - widgetLocation;
+ IntPoint widgetLocation = m_widget->frameRect().location();
+ IntSize widgetPaintOffset = contentPaintOffset - widgetLocation;
// When painting widgets into compositing layers, tx and ty are relative to the enclosing compositing layer,
// not the root. In this case, shift the CTM and adjust the paintRect to be root-relative to fix plug-in drawing.
if (!widgetPaintOffset.isZero()) {
- paintInfo.context->translate(widgetPaintOffset);
+ paintInfo.context().translate(widgetPaintOffset);
paintRect.move(-widgetPaintOffset);
}
- m_widget->paint(paintInfo.context, paintRect);
+ // FIXME: Remove repaintrect encolsing/integral snapping when RenderWidget becomes device pixel snapped.
+ m_widget->paint(paintInfo.context(), snappedIntRect(paintRect));
if (!widgetPaintOffset.isZero())
- paintInfo.context->translate(-widgetPaintOffset);
+ paintInfo.context().translate(-widgetPaintOffset);
- if (m_widget->isFrameView()) {
- FrameView* frameView = toFrameView(m_widget.get());
- bool runOverlapTests = !frameView->useSlowRepaintsIfNotOverlapped() || frameView->hasCompositedContentIncludingDescendants();
+ if (is<FrameView>(*m_widget)) {
+ FrameView& frameView = downcast<FrameView>(*m_widget);
+ bool runOverlapTests = !frameView.useSlowRepaintsIfNotOverlapped();
if (paintInfo.overlapTestRequests && runOverlapTests) {
ASSERT(!paintInfo.overlapTestRequests->contains(this));
paintInfo.overlapTestRequests->set(this, m_widget->frameRect());
@@ -290,86 +265,68 @@ void RenderWidget::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && hasOutline())
paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, size()));
- if (!m_frameView || paintInfo.phase != PaintPhaseForeground)
+ if (paintInfo.phase != PaintPhaseForeground)
return;
-#if PLATFORM(MAC)
- if (style()->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
- paintCustomHighlight(paintOffset, style()->highlight(), true);
-#endif
-
- if (style()->hasBorderRadius()) {
+ if (style().hasBorderRadius()) {
LayoutRect borderRect = LayoutRect(adjustedPaintOffset, size());
if (borderRect.isEmpty())
return;
// Push a clip if we have a border radius, since we want to round the foreground content that gets painted.
- paintInfo.context->save();
- RoundedRect roundedInnerRect = style()->getRoundedInnerBorderFor(borderRect,
- paddingTop() + borderTop(), paddingBottom() + borderBottom(), paddingLeft() + borderLeft(), paddingRight() + borderRight(), true, true);
- clipRoundedInnerRect(paintInfo.context, borderRect, roundedInnerRect);
+ paintInfo.context().save();
+ FloatRoundedRect roundedInnerRect = FloatRoundedRect(style().getRoundedInnerBorderFor(borderRect,
+ paddingTop() + borderTop(), paddingBottom() + borderBottom(), paddingLeft() + borderLeft(), paddingRight() + borderRight(), true, true));
+ clipRoundedInnerRect(paintInfo.context(), borderRect, roundedInnerRect);
}
if (m_widget)
paintContents(paintInfo, paintOffset);
- if (style()->hasBorderRadius())
- paintInfo.context->restore();
+ if (style().hasBorderRadius())
+ paintInfo.context().restore();
// Paint a partially transparent wash over selected widgets.
- if (isSelected() && !document()->printing()) {
+ if (isSelected() && !document().printing()) {
// FIXME: selectionRect() is in absolute, not painting coordinates.
- paintInfo.context->fillRect(pixelSnappedIntRect(selectionRect()), selectionBackgroundColor(), style()->colorSpace());
+ paintInfo.context().fillRect(snappedIntRect(selectionRect()), selectionBackgroundColor());
}
if (hasLayer() && layer()->canResize())
- layer()->paintResizer(paintInfo.context, roundedIntPoint(adjustedPaintOffset), paintInfo.rect);
+ layer()->paintResizer(paintInfo.context(), roundedIntPoint(adjustedPaintOffset), paintInfo.rect);
}
void RenderWidget::setOverlapTestResult(bool isOverlapped)
{
ASSERT(m_widget);
- ASSERT(m_widget->isFrameView());
- toFrameView(m_widget.get())->setIsOverlapped(isOverlapped);
+ downcast<FrameView>(*m_widget).setIsOverlapped(isOverlapped);
}
-void RenderWidget::deref(RenderArena *arena)
+RenderWidget::ChildWidgetState RenderWidget::updateWidgetPosition()
{
- if (--m_refCount <= 0)
- arenaDelete(arena, this);
-}
+ if (!m_widget)
+ return ChildWidgetState::Destroyed;
-void RenderWidget::updateWidgetPosition()
-{
- if (!m_widget || !node()) // Check the node in case destroy() has been called.
- return;
+ WeakPtr<RenderWidget> weakThis = createWeakPtr();
+ bool widgetSizeChanged = updateWidgetGeometry();
+ if (!weakThis || !m_widget)
+ return ChildWidgetState::Destroyed;
- bool boundsChanged = updateWidgetGeometry();
-
- // 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 && m_widget->isFrameView()) {
- FrameView* frameView = toFrameView(m_widget.get());
+ // if the frame size 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 (is<FrameView>(*m_widget)) {
+ FrameView& frameView = downcast<FrameView>(*m_widget);
// Check the frame's page to make sure that the frame isn't in the process of being destroyed.
- if ((boundsChanged || frameView->needsLayout()) && frameView->frame()->page())
- frameView->layout();
+ if ((widgetSizeChanged || frameView.needsLayout()) && frameView.frame().page())
+ frameView.layout();
}
-}
-
-void RenderWidget::widgetPositionsUpdated()
-{
- if (!m_widget)
- return;
- m_widget->widgetPositionsUpdated();
+ return ChildWidgetState::Valid;
}
IntRect RenderWidget::windowClipRect() const
{
- if (!m_frameView)
- return IntRect();
-
- return intersection(m_frameView->contentsToWindow(m_clipRect), m_frameView->windowClipRect());
+ return intersection(view().frameView().contentsToWindow(m_clipRect), view().frameView().windowClipRect());
}
void RenderWidget::setSelectionState(SelectionState state)
@@ -381,11 +338,6 @@ void RenderWidget::setSelectionState(SelectionState state)
m_widget->setIsSelected(isSelected());
}
-void RenderWidget::clearWidget()
-{
- m_widget = 0;
-}
-
RenderWidget* RenderWidget::find(const Widget* widget)
{
return widgetRendererMap().get(widget);
@@ -393,22 +345,64 @@ RenderWidget* RenderWidget::find(const Widget* widget)
bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
{
+ if (request.allowsChildFrameContent() && is<FrameView>(widget()) && downcast<FrameView>(*widget()).renderView()) {
+ FrameView& childFrameView = downcast<FrameView>(*widget());
+ RenderView& childRoot = *childFrameView.renderView();
+
+ LayoutPoint adjustedLocation = accumulatedOffset + location();
+ LayoutPoint contentOffset = LayoutPoint(borderLeft() + paddingLeft(), borderTop() + paddingTop()) - toIntSize(childFrameView.scrollPosition());
+ HitTestLocation newHitTestLocation(locationInContainer, -adjustedLocation - contentOffset);
+ HitTestRequest newHitTestRequest(request.type() | HitTestRequest::ChildFrameHitTest);
+ HitTestResult childFrameResult(newHitTestLocation);
+
+ bool isInsideChildFrame = childRoot.hitTest(newHitTestRequest, newHitTestLocation, childFrameResult);
+
+ if (newHitTestLocation.isRectBasedTest())
+ result.append(childFrameResult);
+ else if (isInsideChildFrame)
+ result = childFrameResult;
+
+ if (isInsideChildFrame)
+ return true;
+ }
+
bool hadResult = result.innerNode();
bool inside = RenderReplaced::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action);
// Check to see if we are really over the widget itself (and not just in the border/padding area).
- if ((inside || result.isRectBasedTest()) && !hadResult && result.innerNode() == node())
+ if ((inside || result.isRectBasedTest()) && !hadResult && result.innerNode() == &frameOwnerElement())
result.setIsOverWidget(contentBoxRect().contains(result.localPoint()));
return inside;
}
-CursorDirective RenderWidget::getCursor(const LayoutPoint& point, Cursor& cursor) const
+bool RenderWidget::requiresLayer() const
+{
+ return RenderReplaced::requiresLayer() || requiresAcceleratedCompositing();
+}
+
+bool RenderWidget::requiresAcceleratedCompositing() const
{
- if (widget() && widget()->isPluginViewBase()) {
- // A plug-in is responsible for setting the cursor when the pointer is over it.
- return DoNotSetCursor;
+ // If this is a renderer with a contentDocument and that document needs a layer, then we need a layer.
+ if (Document* contentDocument = frameOwnerElement().contentDocument()) {
+ if (RenderView* view = contentDocument->renderView())
+ return view->usesCompositing();
}
- return RenderReplaced::getCursor(point, cursor);
+
+ return false;
+}
+
+bool RenderWidget::needsPreferredWidthsRecalculation() const
+{
+ if (RenderReplaced::needsPreferredWidthsRecalculation())
+ return true;
+ return embeddedContentBox();
+}
+
+RenderBox* RenderWidget::embeddedContentBox() const
+{
+ if (!is<FrameView>(widget()))
+ return nullptr;
+ return downcast<FrameView>(*widget()).embeddedContentBox();
}
} // namespace WebCore