diff options
author | Konstantin Tokarev <annulen@yandex.ru> | 2016-08-25 19:20:41 +0300 |
---|---|---|
committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-02-02 12:30:55 +0000 |
commit | 6882a04fb36642862b11efe514251d32070c3d65 (patch) | |
tree | b7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebCore/rendering/RenderWidget.cpp | |
parent | ab6df191029eeeb0b0f16f127d553265659f739e (diff) | |
download | qtwebkit-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.cpp | 274 |
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 |