summaryrefslogtreecommitdiff
path: root/Source/WebCore/page/FrameView.cpp
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2013-09-13 12:51:20 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-19 20:50:05 +0200
commitd441d6f39bb846989d95bcf5caf387b42414718d (patch)
treee367e64a75991c554930278175d403c072de6bb8 /Source/WebCore/page/FrameView.cpp
parent0060b2994c07842f4c59de64b5e3e430525c4b90 (diff)
downloadqtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit. Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/WebCore/page/FrameView.cpp')
-rw-r--r--Source/WebCore/page/FrameView.cpp1252
1 files changed, 879 insertions, 373 deletions
diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp
index 083b83ad5..209030309 100644
--- a/Source/WebCore/page/FrameView.cpp
+++ b/Source/WebCore/page/FrameView.cpp
@@ -28,19 +28,24 @@
#include "FrameView.h"
#include "AXObjectCache.h"
+#include "AnimationController.h"
#include "BackForwardController.h"
+#include "CachedImage.h"
#include "CachedResourceLoader.h"
#include "Chrome.h"
#include "ChromeClient.h"
+#include "DOMWindow.h"
#include "DocumentMarkerController.h"
#include "EventHandler.h"
#include "FloatRect.h"
#include "FocusController.h"
#include "FontCache.h"
+#include "FontLoader.h"
#include "Frame.h"
#include "FrameActionScheduler.h"
#include "FrameLoader.h"
#include "FrameLoaderClient.h"
+#include "FrameSelection.h"
#include "FrameTree.h"
#include "GraphicsContext.h"
#include "HTMLDocument.h"
@@ -52,14 +57,17 @@
#include "InspectorController.h"
#include "InspectorInstrumentation.h"
#include "OverflowEvent.h"
+#include "ProgressTracker.h"
#include "RenderArena.h"
#include "RenderEmbeddedObject.h"
#include "RenderFullScreen.h"
#include "RenderIFrame.h"
#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
#include "RenderPart.h"
#include "RenderScrollbar.h"
#include "RenderScrollbarPart.h"
+#include "RenderStyle.h"
#include "RenderTheme.h"
#include "RenderView.h"
#include "ScrollAnimator.h"
@@ -71,7 +79,6 @@
#include <wtf/CurrentTime.h>
#include <wtf/TemporaryChange.h>
-#include <wtf/UnusedParam.h>
#if USE(ACCELERATED_COMPOSITING)
#include "RenderLayerCompositor.h"
@@ -123,16 +130,13 @@ double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
// The maximum number of updateWidgets iterations that should be done before returning.
static const unsigned maxUpdateWidgetsIterations = 2;
-static inline RenderView* rootRenderer(const FrameView* view)
-{
- return view->frame() ? view->frame()->contentRenderer() : 0;
-}
-
static RenderLayer::UpdateLayerPositionsFlags updateLayerPositionFlags(RenderLayer* layer, bool isRelayoutingSubtree, bool didFullRepaint)
{
RenderLayer::UpdateLayerPositionsFlags flags = RenderLayer::defaultFlags;
- if (didFullRepaint)
+ if (didFullRepaint) {
flags &= ~RenderLayer::CheckForRepaint;
+ flags |= RenderLayer::NeedsFullRepaintInBacking;
+ }
if (isRelayoutingSubtree && layer->isPaginated())
flags |= RenderLayer::UpdatePagination;
return flags;
@@ -168,7 +172,6 @@ Pagination::Mode paginationModeForRenderStyle(RenderStyle* style)
FrameView::FrameView(Frame* frame)
: m_frame(frame)
, m_canHaveScrollbars(true)
- , m_slowRepaintObjectCount(0)
, m_layoutTimer(this, &FrameView::layoutTimerFired)
, m_layoutRoot(0)
, m_inSynchronousPostLayout(false)
@@ -192,9 +195,14 @@ FrameView::FrameView(Frame* frame)
, m_shouldAutoSize(false)
, m_inAutoSize(false)
, m_didRunAutosize(false)
+ , m_headerHeight(0)
+ , m_footerHeight(0)
+ , m_milestonesPendingPaint(0)
#if ENABLE(CSS_FILTERS)
, m_hasSoftwareFilters(false)
#endif
+ , m_visualUpdatesAllowedByClient(true)
+ , m_scrollPinningBehavior(DoNotPin)
{
init();
@@ -234,9 +242,7 @@ FrameView::~FrameView()
m_actionScheduler->clear();
}
- if (AXObjectCache::accessibilityEnabled() && axObjectCache())
- axObjectCache()->remove(this);
-
+ removeFromAXObjectCache();
resetScrollbars();
// Custom scrollbars should already be destroyed at this point
@@ -299,9 +305,10 @@ void FrameView::reset()
m_disableRepaints = 0;
}
-bool FrameView::isFrameView() const
-{
- return true;
+void FrameView::removeFromAXObjectCache()
+{
+ if (AXObjectCache* cache = axObjectCache())
+ cache->remove(this);
}
void FrameView::clearFrame()
@@ -340,7 +347,7 @@ void FrameView::init()
// Propagate the marginwidth/height and scrolling modes to the view.
Element* ownerElement = m_frame ? m_frame->ownerElement() : 0;
if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
- HTMLFrameElementBase* frameElt = static_cast<HTMLFrameElementBase*>(ownerElement);
+ HTMLFrameElementBase* frameElt = toHTMLFrameElementBase(ownerElement);
if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
setCanHaveScrollbars(false);
LayoutUnit marginWidth = frameElt->marginWidth();
@@ -350,6 +357,23 @@ void FrameView::init()
if (marginHeight != -1)
setMarginHeight(marginHeight);
}
+
+ Page* page = frame() ? frame()->page() : 0;
+ if (page && page->chrome().client()->shouldPaintEntireContents())
+ setPaintsEntireContents(true);
+}
+
+void FrameView::prepareForDetach()
+{
+ detachCustomScrollbars();
+ // When the view is no longer associated with a frame, it needs to be removed from the ax object cache
+ // right now, otherwise it won't be able to reach the topDocument()'s axObject cache later.
+ removeFromAXObjectCache();
+
+ if (m_frame && m_frame->page()) {
+ if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator())
+ scrollingCoordinator->willDestroyScrollableArea(this);
+ }
}
void FrameView::detachCustomScrollbars()
@@ -374,20 +398,13 @@ void FrameView::recalculateScrollbarOverlayStyle()
ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault;
Color backgroundColor = documentBackgroundColor();
-#if USE(ACCELERATED_COMPOSITING)
- if (RenderView* root = rootRenderer(this)) {
- RenderLayerCompositor* compositor = root->compositor();
- compositor->documentBackgroundColorDidChange();
- }
-#endif
-
if (backgroundColor.isValid()) {
// Reduce the background color from RGB to a lightness value
// and determine which scrollbar style to use based on a lightness
// heuristic.
double hue, saturation, lightness;
backgroundColor.getHSL(hue, saturation, lightness);
- if (lightness <= .5)
+ if (lightness <= .5 && backgroundColor.alpha() > 0)
overlayStyle = ScrollbarOverlayStyleLight;
}
@@ -417,8 +434,8 @@ bool FrameView::didFirstLayout() const
void FrameView::invalidateRect(const IntRect& rect)
{
if (!parent()) {
- if (hostWindow())
- hostWindow()->invalidateContentsAndRootView(rect, false /*immediate*/);
+ if (HostWindow* window = hostWindow())
+ window->invalidateContentsAndRootView(rect, false /*immediate*/);
return;
}
@@ -441,23 +458,37 @@ void FrameView::setFrameRect(const IntRect& newRect)
if (newRect == oldRect)
return;
+#if ENABLE(TEXT_AUTOSIZING)
+ // Autosized font sizes depend on the width of the viewing area.
+ if (newRect.width() != oldRect.width()) {
+ Page* page = m_frame ? m_frame->page() : 0;
+ if (page && page->mainFrame() == m_frame && page->settings()->textAutosizingEnabled()) {
+ for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())
+ m_frame->document()->textAutosizer()->recalculateMultipliers();
+ }
+ }
+#endif
+
ScrollView::setFrameRect(newRect);
updateScrollableAreaSet();
#if USE(ACCELERATED_COMPOSITING)
- if (RenderView* root = rootRenderer(this)) {
- if (root->usesCompositing())
- root->compositor()->frameViewDidChangeSize();
+ if (RenderView* renderView = this->renderView()) {
+ if (renderView->usesCompositing())
+ renderView->compositor()->frameViewDidChangeSize();
}
#endif
+
+ if (!frameFlatteningEnabled())
+ sendResizeEventIfNeeded();
}
#if ENABLE(REQUEST_ANIMATION_FRAME)
bool FrameView::scheduleAnimation()
{
- if (hostWindow()) {
- hostWindow()->scheduleAnimation();
+ if (HostWindow* window = hostWindow()) {
+ window->scheduleAnimation();
return true;
}
return false;
@@ -476,21 +507,35 @@ void FrameView::setMarginHeight(LayoutUnit h)
m_margins.setHeight(h);
}
-bool FrameView::avoidScrollbarCreation() const
+bool FrameView::frameFlatteningEnabled() const
{
- ASSERT(m_frame);
+ Settings* settings = frame() ? frame()->settings() : 0;
+ if (!settings)
+ return false;
- // with frame flattening no subframe can have scrollbars
- // but we also cannot turn scrollbars off as we determine
- // our flattening policy using that.
+ return settings->frameFlatteningEnabled();
+}
- if (!m_frame->ownerElement())
+bool FrameView::isFrameFlatteningValidForThisFrame() const
+{
+ if (!frameFlatteningEnabled())
return false;
- if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
- return true;
+ HTMLFrameOwnerElement* owner = frame() ? frame()->ownerElement() : 0;
+ if (!owner)
+ return false;
- return false;
+ // Frame flattening is valid only for <frame> and <iframe>.
+ return owner->hasTagName(frameTag) || owner->hasTagName(iframeTag);
+}
+
+bool FrameView::avoidScrollbarCreation() const
+{
+ ASSERT(m_frame);
+ // with frame flattening no subframe can have scrollbars
+ // but we also cannot turn scrollbars off as we determine
+ // our flattening policy using that.
+ return isFrameFlatteningValidForThisFrame();
}
void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
@@ -555,7 +600,7 @@ void FrameView::setContentsSize(const IntSize& size)
updateScrollableAreaSet();
- page->chrome()->contentsSizeChanged(frame(), size); //notify only
+ page->chrome().contentsSizeChanged(frame(), size); // Notify only.
m_deferSetNeedsLayouts--;
@@ -565,13 +610,13 @@ void FrameView::setContentsSize(const IntSize& size)
void FrameView::adjustViewSize()
{
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return;
ASSERT(m_frame->view() == this);
- const IntRect rect = root->documentRect();
+ const IntRect rect = renderView->documentRect();
const IntSize& size = rect.size();
ScrollView::setScrollOrigin(IntPoint(-rect.x(), -rect.y()), !m_frame->document()->printing(), size == contentsSize());
@@ -586,9 +631,11 @@ void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, S
// use the root element.
// To combat the inability to scroll on a page with overflow:hidden on the root when scaled, disregard hidden when
- // there is a frameScaleFactor that is greater than one on the main frame.
+ // there is a frameScaleFactor that is greater than one on the main frame. Also disregard hidden if there is a
+ // header or footer.
- bool overrideHidden = m_frame->page() && m_frame->page()->mainFrame() == m_frame && m_frame->frameScaleFactor() > 1;
+ bool overrideHidden = (m_frame->page() && m_frame->page()->mainFrame() == m_frame && m_frame->frameScaleFactor() > 1)
+ || (m_frame->page() && m_frame->page()->mainFrame() == m_frame && (headerHeight() || footerHeight()));
EOverflow overflowX = o->style()->overflowX();
EOverflow overflowY = o->style()->overflowY();
@@ -683,7 +730,11 @@ void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, Scrollbar
if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) {
hMode = ScrollbarAuto;
- vMode = ScrollbarAuto;
+ // Seamless documents begin with heights of 0; we special case that here
+ // to correctly render documents that don't need scrollbars.
+ IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size();
+ bool isSeamlessDocument = frame() && frame()->document() && frame()->document()->shouldDisplaySeamlesslyWithParent();
+ vMode = (isSeamlessDocument && !fullVisibleSize.height()) ? ScrollbarAlwaysOff : ScrollbarAuto;
} else {
hMode = ScrollbarAlwaysOff;
vMode = ScrollbarAlwaysOff;
@@ -695,7 +746,7 @@ void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, Scrollbar
RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
Node* body = document->body();
if (body && body->renderer()) {
- if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
+ if (body->hasTagName(framesetTag) && !frameFlatteningEnabled()) {
vMode = ScrollbarAlwaysOff;
hMode = ScrollbarAlwaysOff;
} else if (body->hasTagName(bodyTag)) {
@@ -712,37 +763,37 @@ void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, Scrollbar
#if USE(ACCELERATED_COMPOSITING)
void FrameView::updateCompositingLayersAfterStyleChange()
{
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return;
// If we expect to update compositing after an incipient layout, don't do so here.
- if (m_doingPreLayoutStyleUpdate || layoutPending() || root->needsLayout())
+ if (m_doingPreLayoutStyleUpdate || layoutPending() || renderView->needsLayout())
return;
// This call will make sure the cached hasAcceleratedCompositing is updated from the pref
- root->compositor()->cacheAcceleratedCompositingFlags();
- root->compositor()->updateCompositingLayers(CompositingUpdateAfterStyleChange);
+ renderView->compositor()->cacheAcceleratedCompositingFlags();
+ renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterStyleChange);
}
void FrameView::updateCompositingLayersAfterLayout()
{
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return;
// This call will make sure the cached hasAcceleratedCompositing is updated from the pref
- root->compositor()->cacheAcceleratedCompositingFlags();
- root->compositor()->updateCompositingLayers(CompositingUpdateAfterLayout);
+ renderView->compositor()->cacheAcceleratedCompositingFlags();
+ renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterLayout);
}
void FrameView::clearBackingStores()
{
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return;
- RenderLayerCompositor* compositor = root->compositor();
+ RenderLayerCompositor* compositor = renderView->compositor();
ASSERT(compositor->inCompositingMode());
compositor->enableCompositingMode(false);
compositor->clearBackingForAllLayers();
@@ -750,46 +801,64 @@ void FrameView::clearBackingStores()
void FrameView::restoreBackingStores()
{
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return;
- RenderLayerCompositor* compositor = root->compositor();
+ RenderLayerCompositor* compositor = renderView->compositor();
compositor->enableCompositingMode(true);
compositor->updateCompositingLayers(CompositingUpdateAfterLayout);
}
+bool FrameView::usesCompositedScrolling() const
+{
+ RenderView* renderView = this->renderView();
+ if (!renderView)
+ return false;
+ if (m_frame->settings() && m_frame->settings()->compositedScrollingForFramesEnabled())
+ return renderView->compositor()->inForcedCompositingMode();
+ return false;
+}
+
+GraphicsLayer* FrameView::layerForScrolling() const
+{
+ RenderView* renderView = this->renderView();
+ if (!renderView)
+ return 0;
+ return renderView->compositor()->scrollLayer();
+}
+
GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
{
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return 0;
- return root->compositor()->layerForHorizontalScrollbar();
+ return renderView->compositor()->layerForHorizontalScrollbar();
}
GraphicsLayer* FrameView::layerForVerticalScrollbar() const
{
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return 0;
- return root->compositor()->layerForVerticalScrollbar();
+ return renderView->compositor()->layerForVerticalScrollbar();
}
GraphicsLayer* FrameView::layerForScrollCorner() const
{
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return 0;
- return root->compositor()->layerForScrollCorner();
+ return renderView->compositor()->layerForScrollCorner();
}
TiledBacking* FrameView::tiledBacking()
{
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return 0;
- RenderLayerBacking* backing = root->layer()->backing();
+ RenderLayerBacking* backing = renderView->layer()->backing();
if (!backing)
return 0;
@@ -798,11 +867,11 @@ TiledBacking* FrameView::tiledBacking()
uint64_t FrameView::scrollLayerID() const
{
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return 0;
- RenderLayerBacking* backing = root->layer()->backing();
+ RenderLayerBacking* backing = renderView->layer()->backing();
if (!backing)
return 0;
@@ -812,17 +881,44 @@ uint64_t FrameView::scrollLayerID() const
#if ENABLE(RUBBER_BANDING)
GraphicsLayer* FrameView::layerForOverhangAreas() const
{
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return 0;
- return root->compositor()->layerForOverhangAreas();
+ return renderView->compositor()->layerForOverhangAreas();
+}
+
+GraphicsLayer* FrameView::setWantsLayerForTopOverHangArea(bool wantsLayer) const
+{
+ RenderView* renderView = this->renderView();
+ if (!renderView)
+ return 0;
+
+ return renderView->compositor()->updateLayerForTopOverhangArea(wantsLayer);
+}
+
+GraphicsLayer* FrameView::setWantsLayerForBottomOverHangArea(bool wantsLayer) const
+{
+ RenderView* renderView = this->renderView();
+ if (!renderView)
+ return 0;
+
+ return renderView->compositor()->updateLayerForBottomOverhangArea(wantsLayer);
+}
+
+#endif // ENABLE(RUBBER_BANDING)
+
+bool FrameView::scrollbarAnimationsAreSuppressed() const
+{
+ Page* page = frame() ? frame()->page() : 0;
+ if (!page)
+ return true;
+ return page->shouldSuppressScrollbarAnimations();
}
-#endif
bool FrameView::flushCompositingStateForThisFrame(Frame* rootFrameForFlush)
{
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return true; // We don't want to keep trying to update layers if we have no renderer.
ASSERT(m_frame->view() == this);
@@ -836,7 +932,7 @@ bool FrameView::flushCompositingStateForThisFrame(Frame* rootFrameForFlush)
// visible flash to occur. Instead, stop the deferred repaint timer and repaint immediately.
flushDeferredRepaints();
- root->compositor()->flushPendingLayerChanges(rootFrameForFlush == m_frame);
+ renderView->compositor()->flushPendingLayerChanges(rootFrameForFlush == m_frame);
return true;
}
@@ -845,16 +941,36 @@ void FrameView::setNeedsOneShotDrawingSynchronization()
{
Page* page = frame() ? frame()->page() : 0;
if (page)
- page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
+ page->chrome().client()->setNeedsOneShotDrawingSynchronization();
}
#endif // USE(ACCELERATED_COMPOSITING)
+void FrameView::setHeaderHeight(int headerHeight)
+{
+ if (m_frame && m_frame->page())
+ ASSERT(m_frame == m_frame->page()->mainFrame());
+ m_headerHeight = headerHeight;
+
+ if (RenderView* renderView = this->renderView())
+ renderView->setNeedsLayout(true);
+}
+
+void FrameView::setFooterHeight(int footerHeight)
+{
+ if (m_frame && m_frame->page())
+ ASSERT(m_frame == m_frame->page()->mainFrame());
+ m_footerHeight = footerHeight;
+
+ if (RenderView* renderView = this->renderView())
+ renderView->setNeedsLayout(true);
+}
+
bool FrameView::hasCompositedContent() const
{
#if USE(ACCELERATED_COMPOSITING)
- if (RenderView* root = rootRenderer(this))
- return root->compositor()->inCompositingMode();
+ if (RenderView* renderView = this->renderView())
+ return renderView->compositor()->inCompositingMode();
#endif
return false;
}
@@ -894,10 +1010,10 @@ bool FrameView::hasCompositingAncestor() const
void FrameView::enterCompositingMode()
{
#if USE(ACCELERATED_COMPOSITING)
- if (RenderView* root = rootRenderer(this)) {
- root->compositor()->enableCompositingMode();
+ if (RenderView* renderView = this->renderView()) {
+ renderView->compositor()->enableCompositingMode();
if (!needsLayout())
- root->compositor()->scheduleCompositingLayerUpdate();
+ renderView->compositor()->scheduleCompositingLayerUpdate();
}
#endif
}
@@ -933,11 +1049,8 @@ bool FrameView::flushCompositingStateIncludingSubframes()
bool FrameView::isSoftwareRenderable() const
{
#if USE(ACCELERATED_COMPOSITING)
- RenderView* root = rootRenderer(this);
- if (!root)
- return true;
-
- return !root->compositor()->has3DContent();
+ RenderView* renderView = this->renderView();
+ return !renderView || !renderView->compositor()->has3DContent();
#else
return true;
#endif
@@ -945,18 +1058,31 @@ bool FrameView::isSoftwareRenderable() const
void FrameView::didMoveOnscreen()
{
- if (RenderView* root = rootRenderer(this))
- root->didMoveOnscreen();
contentAreaDidShow();
}
void FrameView::willMoveOffscreen()
{
- if (RenderView* root = rootRenderer(this))
- root->willMoveOffscreen();
contentAreaDidHide();
}
+void FrameView::setIsInWindow(bool isInWindow)
+{
+ if (RenderView* renderView = this->renderView())
+ renderView->setIsInWindow(isInWindow);
+
+ if (isInWindow)
+ resumeAnimatingImages();
+}
+
+void FrameView::resumeAnimatingImages()
+{
+ // Drawing models which cache painted content while out-of-window (WebKit2's composited drawing areas, etc.)
+ // require that we repaint animated images to kickstart the animation loop.
+
+ CachedImage::resumeAnimatingImagesForLoader(frame()->document()->cachedResourceLoader());
+}
+
RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
{
return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
@@ -971,7 +1097,7 @@ static inline void collectFrameViewChildren(FrameView* frameView, Vector<RefPtr<
for (HashSet<RefPtr<Widget> >::iterator current = viewChildren->begin(); current != end; ++current) {
Widget* widget = (*current).get();
if (widget->isFrameView())
- frameViews.append(static_cast<FrameView*>(widget));
+ frameViews.append(toFrameView(widget));
}
}
@@ -1016,6 +1142,9 @@ void FrameView::layout(bool allowSubtree)
// Protect the view from being deleted during layout (in recalcStyle)
RefPtr<FrameView> protector(this);
+ // Every scroll that happens during layout is programmatic.
+ TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
+
bool inChildFrameLayoutWithFrameFlattening = isInChildFrameWithFrameFlattening();
if (inChildFrameLayoutWithFrameFlattening) {
@@ -1065,9 +1194,10 @@ void FrameView::layout(bool allowSubtree)
}
// Viewport-dependent media queries may cause us to need completely different style information.
- // Check that here.
- if (document->styleResolver()->affectedByViewportChange()) {
- document->styleResolverChanged(RecalcStyleImmediately);
+ if (!document->styleResolverIfExists() || document->styleResolverIfExists()->affectedByViewportChange()) {
+ document->styleResolverChanged(DeferRecalcStyle);
+ // FIXME: This instrumentation event is not strictly accurate since cached media query results
+ // do not persist across StyleResolver rebuilds.
InspectorInstrumentation::mediaQueryResultChanged(document);
} else
document->evaluateMediaQueryList();
@@ -1108,7 +1238,7 @@ void FrameView::layout(bool allowSubtree)
Document* document = m_frame->document();
Node* body = document->body();
if (body && body->renderer()) {
- if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
+ if (body->hasTagName(framesetTag) && !frameFlatteningEnabled()) {
body->renderer()->setChildNeedsLayout(true);
} else if (body->hasTagName(bodyTag)) {
if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
@@ -1144,7 +1274,7 @@ void FrameView::layout(bool allowSubtree)
if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
m_lastViewportSize = fixedLayoutSize();
else
- m_lastViewportSize = visibleContentRect(true /*includeScrollbars*/).size();
+ m_lastViewportSize = visibleContentRect(IncludeScrollbars).size();
m_lastZoomFactor = root->style()->zoom();
// Set the initial vMode to AlwaysOn if we're auto.
@@ -1208,16 +1338,20 @@ void FrameView::layout(bool allowSubtree)
m_layoutRoot = 0;
} // Reset m_layoutSchedulingEnabled to its previous value.
+ bool neededFullRepaint = m_doFullRepaint;
+
if (!subtree && !toRenderView(root)->printing())
adjustViewSize();
+ m_doFullRepaint = neededFullRepaint;
+
// Now update the positions of all layers.
beginDeferredRepaints();
if (m_doFullRepaint)
root->view()->repaint(); // FIXME: This isn't really right, since the RenderView doesn't fully encompass the visibleContentRect(). It just happens
// to work out most of the time, since first layouts and printing don't have you scrolled anywhere.
- layer->updateLayerPositionsAfterLayout(rootRenderer(this)->layer(), updateLayerPositionFlags(layer, subtree, m_doFullRepaint));
+ layer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPositionFlags(layer, subtree, m_doFullRepaint));
endDeferredRepaints();
@@ -1227,9 +1361,9 @@ void FrameView::layout(bool allowSubtree)
m_layoutCount++;
-#if PLATFORM(MAC) || PLATFORM(CHROMIUM)
- if (AXObjectCache::accessibilityEnabled())
- root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true);
+#if PLATFORM(MAC) || PLATFORM(WIN)
+ if (AXObjectCache* cache = root->document()->existingAXObjectCache())
+ cache->postNotification(root, AXObjectCache::AXLayoutComplete, true);
#endif
#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
updateAnnotatedRegions();
@@ -1246,8 +1380,8 @@ void FrameView::layout(bool allowSubtree)
if (!m_postLayoutTasksTimer.isActive()) {
if (!m_inSynchronousPostLayout) {
if (inChildFrameLayoutWithFrameFlattening) {
- if (RenderView* root = rootRenderer(this))
- root->updateWidgetPositions();
+ if (RenderView* renderView = this->renderView())
+ renderView->updateWidgetPositions();
} else {
m_inSynchronousPostLayout = true;
// Calls resumeScheduledEvents()
@@ -1281,44 +1415,45 @@ void FrameView::layout(bool allowSubtree)
if (!page)
return;
- page->chrome()->client()->layoutUpdated(frame());
+ page->chrome().client()->layoutUpdated(frame());
}
RenderBox* FrameView::embeddedContentBox() const
{
#if ENABLE(SVG)
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return 0;
- RenderObject* rootChild = root->firstChild();
- if (!rootChild || !rootChild->isBox())
+ RenderObject* firstChild = renderView->firstChild();
+ if (!firstChild || !firstChild->isBox())
return 0;
// Curently only embedded SVG documents participate in the size-negotiation logic.
- if (rootChild->isSVGRoot())
- return toRenderBox(rootChild);
+ if (firstChild->isSVGRoot())
+ return toRenderBox(firstChild);
#endif
return 0;
}
-void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object)
+void FrameView::addWidgetToUpdate(RenderObject* object)
{
if (!m_widgetUpdateSet)
- m_widgetUpdateSet = adoptPtr(new RenderEmbeddedObjectSet);
+ m_widgetUpdateSet = adoptPtr(new RenderObjectSet);
// Tell the DOM element that it needs a widget update.
Node* node = object->node();
if (node->hasTagName(objectTag) || node->hasTagName(embedTag)) {
- HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(node);
- pluginElement->setNeedsWidgetUpdate(true);
+ HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(node);
+ if (!pluginElement->needsCheckForSizeChange())
+ pluginElement->setNeedsWidgetUpdate(true);
}
m_widgetUpdateSet->add(object);
}
-void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object)
+void FrameView::removeWidgetToUpdate(RenderObject* object)
{
if (!m_widgetUpdateSet)
return;
@@ -1335,6 +1470,7 @@ String FrameView::mediaType() const
{
// See if we have an override type.
String overrideType = m_frame->loader()->client()->overrideMediaType();
+ InspectorInstrumentation::applyEmulatedMedia(m_frame.get(), &overrideType);
if (!overrideType.isNull())
return overrideType;
return m_mediaType;
@@ -1355,7 +1491,7 @@ void FrameView::adjustMediaTypeForPrinting(bool printing)
bool FrameView::useSlowRepaints(bool considerOverlap) const
{
- bool mustBeSlow = m_slowRepaintObjectCount > 0 || (platformWidget() && hasViewportConstrainedObjects());
+ bool mustBeSlow = hasSlowRepaintObjects() || (platformWidget() && hasViewportConstrainedObjects());
// FIXME: WidgetMac.mm makes the assumption that useSlowRepaints ==
// m_contentIsOpaque, so don't take the fast path for composited layers
@@ -1364,13 +1500,6 @@ bool FrameView::useSlowRepaints(bool considerOverlap) const
if (contentsInCompositedLayer() && !platformWidget())
return mustBeSlow;
-#if PLATFORM(CHROMIUM)
- // The chromium compositor does not support scrolling a non-composited frame within a composited page through
- // the fast scrolling path, so force slow scrolling in that case.
- if (m_frame->ownerElement() && !hasCompositedContent() && m_frame->page() && m_frame->page()->mainFrame()->view()->hasCompositedContent())
- return true;
-#endif
-
bool isOverlapped = m_isOverlapped && considerOverlap;
if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque)
@@ -1398,9 +1527,9 @@ void FrameView::updateCanBlitOnScrollRecursively()
bool FrameView::contentsInCompositedLayer() const
{
#if USE(ACCELERATED_COMPOSITING)
- RenderView* root = rootRenderer(this);
- if (root && root->isComposited()) {
- GraphicsLayer* layer = root->layer()->backing()->graphicsLayer();
+ RenderView* renderView = this->renderView();
+ if (renderView && renderView->isComposited()) {
+ GraphicsLayer* layer = renderView->layer()->backing()->graphicsLayer();
if (layer && layer->drawsContent())
return true;
}
@@ -1414,9 +1543,16 @@ void FrameView::setCannotBlitToWindow()
updateCanBlitOnScrollRecursively();
}
-void FrameView::addSlowRepaintObject()
+void FrameView::addSlowRepaintObject(RenderObject* o)
{
- if (!m_slowRepaintObjectCount++) {
+ bool hadSlowRepaintObjects = hasSlowRepaintObjects();
+
+ if (!m_slowRepaintObjects)
+ m_slowRepaintObjects = adoptPtr(new RenderObjectSet);
+
+ m_slowRepaintObjects->add(o);
+
+ if (!hadSlowRepaintObjects) {
updateCanBlitOnScrollRecursively();
if (Page* page = m_frame->page()) {
@@ -1426,11 +1562,14 @@ void FrameView::addSlowRepaintObject()
}
}
-void FrameView::removeSlowRepaintObject()
+void FrameView::removeSlowRepaintObject(RenderObject* o)
{
- ASSERT(m_slowRepaintObjectCount > 0);
- m_slowRepaintObjectCount--;
- if (!m_slowRepaintObjectCount) {
+ if (!m_slowRepaintObjects)
+ return;
+
+ m_slowRepaintObjects->remove(o);
+ if (m_slowRepaintObjects->isEmpty()) {
+ m_slowRepaintObjects = nullptr;
updateCanBlitOnScrollRecursively();
if (Page* page = m_frame->page()) {
@@ -1472,14 +1611,61 @@ void FrameView::removeViewportConstrainedObject(RenderObject* object)
}
}
+LayoutRect FrameView::viewportConstrainedVisibleContentRect() const
+{
+ LayoutRect viewportRect = visibleContentRect();
+ viewportRect.setLocation(toPoint(scrollOffsetForFixedPosition()));
+ return viewportRect;
+}
+
+IntSize FrameView::scrollOffsetForFixedPosition(const IntRect& visibleContentRect, const IntSize& totalContentsSize, const IntPoint& scrollPosition, const IntPoint& scrollOrigin, float frameScaleFactor, bool fixedElementsLayoutRelativeToFrame, int headerHeight, int footerHeight)
+{
+ IntPoint constrainedPosition = ScrollableArea::constrainScrollPositionForOverhang(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, headerHeight, footerHeight);
+
+ IntSize maxSize = totalContentsSize - visibleContentRect.size();
+
+ float dragFactorX = (fixedElementsLayoutRelativeToFrame || !maxSize.width()) ? 1 : (totalContentsSize.width() - visibleContentRect.width() * frameScaleFactor) / maxSize.width();
+ float dragFactorY = (fixedElementsLayoutRelativeToFrame || !maxSize.height()) ? 1 : (totalContentsSize.height() - visibleContentRect.height() * frameScaleFactor) / maxSize.height();
+
+ return IntSize(constrainedPosition.x() * dragFactorX / frameScaleFactor, constrainedPosition.y() * dragFactorY / frameScaleFactor);
+}
+
IntSize FrameView::scrollOffsetForFixedPosition() const
{
IntRect visibleContentRect = this->visibleContentRect();
- IntSize contentsSize = this->contentsSize();
+ IntSize totalContentsSize = this->totalContentsSize();
IntPoint scrollPosition = this->scrollPosition();
IntPoint scrollOrigin = this->scrollOrigin();
float frameScaleFactor = m_frame ? m_frame->frameScaleFactor() : 1;
- return WebCore::scrollOffsetForFixedPosition(visibleContentRect, contentsSize, scrollPosition, scrollOrigin, frameScaleFactor, fixedElementsLayoutRelativeToFrame());
+ return scrollOffsetForFixedPosition(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, frameScaleFactor, fixedElementsLayoutRelativeToFrame(), headerHeight(), footerHeight());
+}
+
+IntPoint FrameView::minimumScrollPosition() const
+{
+ IntPoint minimumPosition(ScrollView::minimumScrollPosition());
+
+ if (!m_frame || !m_frame->page())
+ return minimumPosition;
+
+ if (m_frame == m_frame->page()->mainFrame() && m_scrollPinningBehavior == PinToBottom)
+ minimumPosition.setY(maximumScrollPosition().y());
+
+ return minimumPosition;
+}
+
+IntPoint FrameView::maximumScrollPosition() const
+{
+ IntPoint maximumOffset(contentsWidth() - visibleWidth() - scrollOrigin().x(), totalContentsSize().height() - visibleHeight() - scrollOrigin().y());
+
+ maximumOffset.clampNegativeToZero();
+
+ if (!m_frame || !m_frame->page())
+ return maximumOffset;
+
+ if (m_frame == m_frame->page()->mainFrame() && m_scrollPinningBehavior == PinToTop)
+ maximumOffset.setY(minimumScrollPosition().y());
+
+ return maximumOffset;
}
bool FrameView::fixedElementsLayoutRelativeToFrame() const
@@ -1491,9 +1677,20 @@ bool FrameView::fixedElementsLayoutRelativeToFrame() const
return m_frame->settings()->fixedElementsLayoutRelativeToFrame();
}
-IntPoint FrameView::currentMousePosition() const
+IntPoint FrameView::lastKnownMousePosition() const
{
- return m_frame ? m_frame->eventHandler()->currentMousePosition() : IntPoint();
+ return m_frame ? m_frame->eventHandler()->lastKnownMousePosition() : IntPoint();
+}
+
+bool FrameView::isHandlingWheelEvent() const
+{
+ return m_frame ? m_frame->eventHandler()->isHandlingWheelEvent() : false;
+}
+
+bool FrameView::shouldSetCursor() const
+{
+ Page* page = frame()->page();
+ return page && page->isOnscreen() && page->focusController()->isActive();
}
bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
@@ -1520,7 +1717,15 @@ bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect
// Fixed items should always have layers.
ASSERT(renderer->hasLayer());
RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
-
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForBoundsOutOfView
+ || layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForNoVisibleContent) {
+ // Don't invalidate for invisible fixed layers.
+ continue;
+ }
+#endif
+
#if ENABLE(CSS_FILTERS)
if (layer->hasAncestorWithFilterOutsets()) {
// If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot
@@ -1550,9 +1755,8 @@ bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect
#if USE(ACCELERATED_COMPOSITING)
if (isCompositedContentLayer) {
updateRect = rootViewToContents(updateRect);
- RenderView* root = rootRenderer(this);
- ASSERT(root);
- root->layer()->setBackingNeedsRepaintInRect(updateRect);
+ ASSERT(renderView());
+ renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
continue;
}
#endif
@@ -1568,17 +1772,18 @@ void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
{
#if USE(ACCELERATED_COMPOSITING)
if (contentsInCompositedLayer()) {
- RenderView* root = rootRenderer(this);
- ASSERT(root);
-
IntRect updateRect = visibleContentRect();
// Make sure to "apply" the scale factor here since we're converting from frame view
// coordinates to layer backing coordinates.
updateRect.scale(1 / m_frame->frameScaleFactor());
- root->layer()->setBackingNeedsRepaintInRect(updateRect);
+ ASSERT(renderView());
+ renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
}
+
+ repaintSlowRepaintObjects();
+
if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
if (isEnclosedInCompositingLayer()) {
LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
@@ -1593,6 +1798,20 @@ void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
ScrollView::scrollContentsSlowPath(updateRect);
}
+void FrameView::repaintSlowRepaintObjects()
+{
+ if (!m_slowRepaintObjects)
+ return;
+
+ // Renderers with fixed backgrounds may be in compositing layers, so we need to explicitly
+ // repaint them after scrolling.
+ RenderObjectSet::const_iterator end = m_slowRepaintObjects->end();
+ for (RenderObjectSet::const_iterator it = m_slowRepaintObjects->begin(); it != end; ++it) {
+ RenderObject* renderer = *it;
+ renderer->repaint();
+ }
+}
+
// Note that this gets called at painting time.
void FrameView::setIsOverlapped(bool isOverlapped)
{
@@ -1687,26 +1906,31 @@ bool FrameView::scrollToAnchor(const String& name)
m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
- Element* anchorNode = m_frame->document()->findAnchor(name);
+ Element* anchorElement = m_frame->document()->findAnchor(name);
// Setting to null will clear the current target.
- m_frame->document()->setCSSTarget(anchorNode);
+ m_frame->document()->setCSSTarget(anchorElement);
#if ENABLE(SVG)
if (m_frame->document()->isSVGDocument()) {
- if (SVGSVGElement* svg = static_cast<SVGDocument*>(m_frame->document())->rootElement()) {
- svg->setupInitialView(name, anchorNode);
- if (!anchorNode)
+ if (SVGSVGElement* svg = toSVGDocument(m_frame->document())->rootElement()) {
+ svg->setupInitialView(name, anchorElement);
+ if (!anchorElement)
return true;
}
}
#endif
// Implement the rule that "" and "top" both mean top of page as in other browsers.
- if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
+ if (!anchorElement && !(name.isEmpty() || equalIgnoringCase(name, "top")))
return false;
- maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
+ maintainScrollPositionAtAnchor(anchorElement ? static_cast<Node*>(anchorElement) : m_frame->document());
+
+ // If the anchor accepts keyboard focus, move focus there to aid users relying on keyboard navigation.
+ if (anchorElement && anchorElement->isFocusable())
+ m_frame->document()->setFocusedElement(anchorElement);
+
return true;
}
@@ -1720,8 +1944,8 @@ void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
// really mess things up if an anchor scroll comes at a bad moment.
m_frame->document()->updateStyleIfNeeded();
// Only do a layout if changes have occurred that make it necessary.
- RenderView* root = rootRenderer(this);
- if (root && root->needsLayout())
+ RenderView* renderView = this->renderView();
+ if (renderView && renderView->needsLayout())
layout();
else
scrollToAnchor();
@@ -1741,10 +1965,6 @@ void FrameView::setScrollPosition(const IntPoint& scrollPoint)
{
TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
m_maintainScrollPositionAnchor = 0;
-
- if (requestScrollPositionUpdate(scrollPoint))
- return;
-
ScrollView::setScrollPosition(scrollPoint);
}
@@ -1770,6 +1990,7 @@ void FrameView::setFixedVisibleContentRect(const IntRect& visibleContentRect)
IntSize offset = scrollOffset();
ScrollView::setFixedVisibleContentRect(visibleContentRect);
if (offset != scrollOffset()) {
+ repaintFixedElementsAfterScrolling();
if (m_frame->page()->settings()->acceleratedCompositingForFixedPositionEnabled())
updateFixedElementsAfterScrolling();
scrollAnimator()->setCurrentPosition(scrollPosition());
@@ -1794,11 +2015,11 @@ void FrameView::setViewportConstrainedObjectsNeedLayout()
}
}
-
void FrameView::scrollPositionChangedViaPlatformWidget()
{
repaintFixedElementsAfterScrolling();
updateFixedElementsAfterScrolling();
+ repaintSlowRepaintObjects();
scrollPositionChanged();
}
@@ -1808,21 +2029,22 @@ void FrameView::scrollPositionChanged()
frame()->eventHandler()->dispatchFakeMouseMoveEventSoon();
#if USE(ACCELERATED_COMPOSITING)
- if (RenderView* root = rootRenderer(this)) {
- if (root->usesCompositing())
- root->compositor()->frameViewDidScroll();
+ if (RenderView* renderView = this->renderView()) {
+ if (renderView->usesCompositing())
+ renderView->compositor()->frameViewDidScroll();
}
#endif
}
+// FIXME: this function is misnamed; its primary purpose is to update RenderLayer positions.
void FrameView::repaintFixedElementsAfterScrolling()
{
// For fixed position elements, update widget positions and compositing layers after scrolling,
// but only if we're not inside of layout.
- if (!m_nestedLayoutCount && hasViewportConstrainedObjects()) {
- if (RenderView* root = rootRenderer(this)) {
- root->updateWidgetPositions();
- root->layer()->updateLayerPositionsAfterDocumentScroll();
+ if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) {
+ if (RenderView* renderView = this->renderView()) {
+ renderView->updateWidgetPositions();
+ renderView->layer()->updateLayerPositionsAfterDocumentScroll();
}
}
}
@@ -1863,8 +2085,8 @@ void FrameView::updateFixedElementsAfterScrolling()
return;
if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) {
- if (RenderView* root = rootRenderer(this))
- root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
+ if (RenderView* renderView = this->renderView())
+ renderView->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
}
#endif
}
@@ -1874,12 +2096,40 @@ bool FrameView::shouldRubberBandInDirection(ScrollDirection direction) const
Page* page = frame() ? frame()->page() : 0;
if (!page)
return ScrollView::shouldRubberBandInDirection(direction);
- return page->chrome()->client()->shouldRubberBandInDirection(direction);
+ return page->chrome().client()->shouldRubberBandInDirection(direction);
+}
+
+bool FrameView::isRubberBandInProgress() const
+{
+ if (scrollbarsSuppressed())
+ return false;
+
+ // If the scrolling thread updates the scroll position for this FrameView, then we should return
+ // ScrollingCoordinator::isRubberBandInProgress().
+ if (Page* page = m_frame->page()) {
+ if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
+ if (!scrollingCoordinator->shouldUpdateScrollLayerPositionOnMainThread())
+ return scrollingCoordinator->isRubberBandInProgress();
+ }
+ }
+
+ // If the main thread updates the scroll position for this FrameView, we should return
+ // ScrollAnimator::isRubberBandInProgress().
+ if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
+ return scrollAnimator->isRubberBandInProgress();
+
+ return false;
}
bool FrameView::requestScrollPositionUpdate(const IntPoint& position)
{
#if ENABLE(THREADED_SCROLLING)
+ if (TiledBacking* tiledBacking = this->tiledBacking()) {
+ IntRect visibleRect = visibleContentRect();
+ visibleRect.setLocation(position);
+ tiledBacking->prepopulateRect(visibleRect);
+ }
+
if (Page* page = m_frame->page()) {
if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
return scrollingCoordinator->requestScrollPositionUpdate(this, position);
@@ -1896,7 +2146,7 @@ HostWindow* FrameView::hostWindow() const
Page* page = frame() ? frame()->page() : 0;
if (!page)
return 0;
- return page->chrome();
+ return &page->chrome();
}
const unsigned cRepaintRectUnionThreshold = 25;
@@ -1955,6 +2205,15 @@ void FrameView::contentsResized()
setNeedsLayout();
}
+void FrameView::fixedLayoutSizeChanged()
+{
+ // Can be triggered before the view is set, see comment in FrameView::visibleContentsResized().
+ // An ASSERT is triggered when a view schedules a layout before being attached to a frame.
+ if (!frame()->view())
+ return;
+ ScrollView::fixedLayoutSizeChanged();
+}
+
void FrameView::visibleContentsResized()
{
// We check to make sure the view is attached to a frame() as this method can
@@ -1964,13 +2223,13 @@ void FrameView::visibleContentsResized()
if (!frame()->view())
return;
- if (needsLayout())
+ if (!useFixedLayout() && needsLayout())
layout();
#if USE(ACCELERATED_COMPOSITING)
- if (RenderView* root = rootRenderer(this)) {
- if (root->usesCompositing())
- root->compositor()->frameViewDidChangeSize();
+ if (RenderView* renderView = this->renderView()) {
+ if (renderView->usesCompositing())
+ renderView->compositor()->frameViewDidChangeSize();
}
#endif
}
@@ -2100,6 +2359,10 @@ void FrameView::resetDeferredRepaintDelay()
if (!m_deferringRepaints)
doDeferredRepaints();
}
+#if USE(ACCELERATED_COMPOSITING)
+ if (RenderView* view = renderView())
+ view->compositor()->disableLayerFlushThrottlingTemporarilyForInteraction();
+#endif
}
double FrameView::adjustedDeferredRepaintDelay() const
@@ -2127,6 +2390,26 @@ void FrameView::endDisableRepaints()
m_disableRepaints--;
}
+void FrameView::updateLayerFlushThrottlingInAllFrames()
+{
+#if USE(ACCELERATED_COMPOSITING)
+ bool isMainLoadProgressing = m_frame->page()->progress()->isMainLoadProgressing();
+ for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
+ if (RenderView* renderView = frame->contentRenderer())
+ renderView->compositor()->setLayerFlushThrottlingEnabled(isMainLoadProgressing);
+ }
+#endif
+}
+
+void FrameView::adjustTiledBackingCoverage()
+{
+#if USE(ACCELERATED_COMPOSITING)
+ RenderView* renderView = this->renderView();
+ if (renderView && renderView->layer()->backing())
+ renderView->layer()->backing()->adjustTiledBackingCoverage();
+#endif
+}
+
void FrameView::layoutTimerFired(Timer<FrameView>*)
{
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
@@ -2187,8 +2470,8 @@ void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
{
ASSERT(m_frame->view() == this);
- RenderView* root = rootRenderer(this);
- if (root && root->needsLayout()) {
+ RenderView* renderView = this->renderView();
+ if (renderView && renderView->needsLayout()) {
if (relayoutRoot)
relayoutRoot->markContainingBlocksForLayout(false);
return;
@@ -2238,9 +2521,9 @@ bool FrameView::needsLayout() const
if (!m_frame)
return false;
- RenderView* root = rootRenderer(this);
+ RenderView* renderView = this->renderView();
return layoutPending()
- || (root && root->needsLayout())
+ || (renderView && renderView->needsLayout())
|| m_layoutRoot
|| (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
}
@@ -2252,8 +2535,8 @@ void FrameView::setNeedsLayout()
return;
}
- if (RenderView* root = rootRenderer(this))
- root->setNeedsLayout(true);
+ if (RenderView* renderView = this->renderView())
+ renderView->setNeedsLayout(true);
}
void FrameView::unscheduleRelayout()
@@ -2297,6 +2580,11 @@ void FrameView::setTransparent(bool isTransparent)
m_isTransparent = isTransparent;
}
+bool FrameView::hasOpaqueBackground() const
+{
+ return !m_isTransparent && !m_baseBackgroundColor.hasAlpha();
+}
+
Color FrameView::baseBackgroundColor() const
{
return m_baseBackgroundColor;
@@ -2371,45 +2659,60 @@ void FrameView::scrollToAnchor()
// Align to the top and to the closest side (this matches other browsers).
anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
- if (AXObjectCache::accessibilityEnabled())
- m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get());
+ if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache())
+ cache->handleScrolledToAnchor(anchorNode.get());
// scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
m_maintainScrollPositionAnchor = anchorNode;
}
-void FrameView::updateWidget(RenderEmbeddedObject* object)
+void FrameView::updateWidget(RenderObject* object)
{
ASSERT(!object->node() || object->node()->isElementNode());
- Element* ownerElement = static_cast<Element*>(object->node());
+ Element* ownerElement = toElement(object->node());
// The object may have already been destroyed (thus node cleared),
// but FrameView holds a manual ref, so it won't have been deleted.
ASSERT(m_widgetUpdateSet->contains(object));
if (!ownerElement)
return;
- // No need to update if it's already crashed or known to be missing.
- if (object->showsUnavailablePluginIndicator())
- return;
+ if (object->isEmbeddedObject()) {
+ RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
+ // No need to update if it's already crashed or known to be missing.
+ if (embeddedObject->isPluginUnavailable())
+ return;
- // FIXME: This could turn into a real virtual dispatch if we defined
- // updateWidget(PluginCreationOption) on HTMLElement.
- if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag) || ownerElement->hasTagName(appletTag)) {
- HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(ownerElement);
- if (pluginElement->needsWidgetUpdate())
- pluginElement->updateWidget(CreateAnyWidgetType);
- }
- // FIXME: It is not clear that Media elements need or want this updateWidget() call.
+ if (object->isSnapshottedPlugIn()) {
+ if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag)) {
+ HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement);
+ pluginElement->checkSnapshotStatus();
+ }
+ return;
+ }
+
+ // FIXME: This could turn into a real virtual dispatch if we defined
+ // updateWidget(PluginCreationOption) on HTMLElement.
+ if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag) || ownerElement->hasTagName(appletTag)) {
+ HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement);
+ if (pluginElement->needsCheckForSizeChange()) {
+ pluginElement->checkSnapshotStatus();
+ return;
+ }
+ if (pluginElement->needsWidgetUpdate())
+ pluginElement->updateWidget(CreateAnyWidgetType);
+ }
+ // FIXME: It is not clear that Media elements need or want this updateWidget() call.
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- else if (ownerElement->isMediaElement())
- static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
+ else if (ownerElement->isMediaElement())
+ toHTMLMediaElement(ownerElement)->updateWidget(CreateAnyWidgetType);
#endif
- else
- ASSERT_NOT_REACHED();
+ else
+ ASSERT_NOT_REACHED();
- // Caution: it's possible the object was destroyed again, since loading a
- // plugin may run any arbitrary javascript.
- object->updateWidgetPosition();
+ // Caution: it's possible the object was destroyed again, since loading a
+ // plugin may run any arbitrary JavaScript.
+ embeddedObject->updateWidgetPosition();
+ }
}
bool FrameView::updateWidgets()
@@ -2419,24 +2722,34 @@ bool FrameView::updateWidgets()
size_t size = m_widgetUpdateSet->size();
- Vector<RenderEmbeddedObject*> objects;
- objects.reserveCapacity(size);
-
- RenderEmbeddedObjectSet::const_iterator end = m_widgetUpdateSet->end();
- for (RenderEmbeddedObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
- objects.uncheckedAppend(*it);
- (*it)->ref();
+ Vector<RenderObject*> objects;
+ objects.reserveInitialCapacity(size);
+ // Protect RendereArena from getting wiped out, when Document is detached during updateWidget().
+ RefPtr<RenderArena> protectedArena = m_frame->document()->renderArena();
+
+ RenderObjectSet::const_iterator end = m_widgetUpdateSet->end();
+ for (RenderObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
+ RenderObject* object = *it;
+ objects.uncheckedAppend(object);
+ if (object->isEmbeddedObject()) {
+ RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
+ embeddedObject->ref();
+ }
}
for (size_t i = 0; i < size; ++i) {
- RenderEmbeddedObject* object = objects[i];
+ RenderObject* object = objects[i];
updateWidget(object);
m_widgetUpdateSet->remove(object);
}
- RenderArena* arena = m_frame->document()->renderArena();
- for (size_t i = 0; i < size; ++i)
- objects[i]->deref(arena);
+ for (size_t i = 0; i < size; ++i) {
+ RenderObject* object = objects[i];
+ if (object->isEmbeddedObject()) {
+ RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
+ embeddedObject->deref(protectedArena.get());
+ }
+ }
return m_widgetUpdateSet->isEmpty();
}
@@ -2456,46 +2769,50 @@ void FrameView::performPostLayoutTasks()
m_frame->selection()->setCaretRectNeedsUpdate();
m_frame->selection()->updateAppearance();
- LayoutMilestones milestonesOfInterest = 0;
+ LayoutMilestones requestedMilestones = 0;
LayoutMilestones milestonesAchieved = 0;
Page* page = m_frame->page();
if (page)
- milestonesOfInterest = page->layoutMilestones();
+ requestedMilestones = page->requestedLayoutMilestones();
- if (m_nestedLayoutCount <= 1) {
+ if (m_nestedLayoutCount <= 1 && m_frame->document()->documentElement()) {
if (m_firstLayoutCallbackPending) {
m_firstLayoutCallbackPending = false;
m_frame->loader()->didFirstLayout();
- if (milestonesOfInterest & DidFirstLayout)
+ if (requestedMilestones & DidFirstLayout)
milestonesAchieved |= DidFirstLayout;
if (page) {
if (page->mainFrame() == m_frame)
page->startCountingRelevantRepaintedObjects();
}
}
-
- // Ensure that we always send this eventually.
- if (!m_frame->document()->parsing() && m_frame->loader()->stateMachine()->committedFirstRealDocumentLoad())
- m_isVisuallyNonEmpty = true;
+ updateIsVisuallyNonEmpty();
// If the layout was done with pending sheets, we are not in fact visually non-empty yet.
if (m_isVisuallyNonEmpty && !m_frame->document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) {
m_firstVisuallyNonEmptyLayoutCallbackPending = false;
- if (milestonesOfInterest & DidFirstVisuallyNonEmptyLayout)
+ if (requestedMilestones & DidFirstVisuallyNonEmptyLayout)
milestonesAchieved |= DidFirstVisuallyNonEmptyLayout;
}
}
- m_frame->loader()->didLayout(milestonesAchieved);
+ if (milestonesAchieved)
+ m_frame->loader()->didLayout(milestonesAchieved);
+#if ENABLE(FONT_LOAD_EVENTS)
+ if (RuntimeEnabledFeatures::fontLoadEventsEnabled())
+ m_frame->document()->fontloader()->didLayout();
+#endif
// FIXME: We should consider adding DidLayout as a LayoutMilestone. That would let us merge this
// with didLayout(LayoutMilestones).
m_frame->loader()->client()->dispatchDidLayout();
- RenderView* root = rootRenderer(this);
- if (root)
- root->updateWidgetPositions();
+ if (RenderView* renderView = this->renderView())
+ renderView->updateWidgetPositions();
+ // layout() protects FrameView, but it still can get destroyed when updateWidgets()
+ // is called through the post layout timer.
+ RefPtr<FrameView> protector(this);
for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
if (updateWidgets())
break;
@@ -2507,9 +2824,9 @@ void FrameView::performPostLayoutTasks()
}
#if USE(ACCELERATED_COMPOSITING)
- if (RenderView* root = rootRenderer(this)) {
- if (root->usesCompositing())
- root->compositor()->frameViewDidLayout();
+ if (RenderView* renderView = this->renderView()) {
+ if (renderView->usesCompositing())
+ renderView->compositor()->frameViewDidLayout();
}
#endif
@@ -2517,31 +2834,61 @@ void FrameView::performPostLayoutTasks()
m_actionScheduler->resume();
- if (root && !root->printing()) {
- IntSize currentSize;
- if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
- currentSize = fixedLayoutSize();
- else
- currentSize = visibleContentRect(true /*includeScrollbars*/).size();
- float currentZoomFactor = root->style()->zoom();
- bool resized = !m_firstLayout && (currentSize != m_lastViewportSize || currentZoomFactor != m_lastZoomFactor);
- m_lastViewportSize = currentSize;
- m_lastZoomFactor = currentZoomFactor;
- if (resized) {
- m_frame->eventHandler()->sendResizeEvent();
+ sendResizeEventIfNeeded();
+}
+
+void FrameView::sendResizeEventIfNeeded()
+{
+ ASSERT(m_frame);
+
+ RenderView* renderView = this->renderView();
+ if (!renderView || renderView->printing())
+ return;
+
+ Page* page = m_frame->page();
+ IntSize currentSize;
+ if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
+ currentSize = fixedLayoutSize();
+ else
+ currentSize = visibleContentRect(IncludeScrollbars).size();
+
+ float currentZoomFactor = renderView->style()->zoom();
+ bool shouldSendResizeEvent = !m_firstLayout && (currentSize != m_lastViewportSize || currentZoomFactor != m_lastZoomFactor);
+
+ m_lastViewportSize = currentSize;
+ m_lastZoomFactor = currentZoomFactor;
+
+ if (!shouldSendResizeEvent)
+ return;
+
+ bool isMainFrame = page && page->mainFrame() == m_frame;
+ bool canSendResizeEventSynchronously = isMainFrame && !isInLayout();
+
+ // If we resized during layout, queue up a resize event for later, otherwise fire it right away.
+ RefPtr<Event> resizeEvent = Event::create(eventNames().resizeEvent, false, false);
+ if (canSendResizeEventSynchronously)
+ m_frame->document()->dispatchWindowEvent(resizeEvent.release(), m_frame->document()->domWindow());
+ else
+ m_frame->document()->enqueueWindowEvent(resizeEvent.release());
#if ENABLE(INSPECTOR)
- if (InspectorInstrumentation::hasFrontends()) {
- if (page) {
- if (page->mainFrame() == m_frame) {
- if (InspectorClient* inspectorClient = page->inspectorController()->inspectorClient())
- inspectorClient->didResizeMainFrame(m_frame.get());
- }
- }
- }
-#endif
- }
+ if (InspectorInstrumentation::hasFrontends() && isMainFrame) {
+ if (InspectorClient* inspectorClient = page ? page->inspectorController()->inspectorClient() : 0)
+ inspectorClient->didResizeMainFrame(m_frame.get());
}
+#endif
+}
+
+void FrameView::willStartLiveResize()
+{
+ ScrollView::willStartLiveResize();
+ adjustTiledBackingCoverage();
+}
+
+void FrameView::willEndLiveResize()
+{
+ ScrollView::willEndLiveResize();
+ adjustTiledBackingCoverage();
}
void FrameView::postLayoutTimerFired(Timer<FrameView>*)
@@ -2568,14 +2915,8 @@ void FrameView::autoSizeIfEnabled()
if (!documentView || !documentElement)
return;
- RenderBox* documentRenderBox = documentElement->renderBox();
- if (!documentRenderBox)
- return;
-
- // If this is the first time we run autosize, start from small height and
- // allow it to grow.
- if (!m_didRunAutosize)
- resize(frameRect().width(), m_minAutoSize.height());
+ // Start from the minimum size and allow it to grow.
+ resize(m_minAutoSize.width(), m_minAutoSize.height());
IntSize size = frameRect().size();
@@ -2585,7 +2926,7 @@ void FrameView::autoSizeIfEnabled()
// Update various sizes including contentsSize, scrollHeight, etc.
document->updateLayoutIgnorePendingStylesheets();
int width = documentView->minPreferredLogicalWidth();
- int height = documentRenderBox->scrollHeight();
+ int height = documentView->documentRect().height();
IntSize newSize(width, height);
// Check to see if a scrollbar is needed for a given dimension and
@@ -2701,10 +3042,10 @@ IntRect FrameView::windowClipRect(bool clipToContents) const
ASSERT(m_frame->view() == this);
if (paintsEntireContents())
- return IntRect(IntPoint(), contentsSize());
+ return IntRect(IntPoint(), totalContentsSize());
// Set our clip rect to be our contents.
- IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
+ IntRect clipRect = contentsToWindow(visibleContentRect(clipToContents ? ExcludeScrollbars : IncludeScrollbars));
if (!m_frame || !m_frame->ownerElement())
return clipRect;
@@ -2771,7 +3112,18 @@ IntRect FrameView::windowResizerRect() const
Page* page = frame() ? frame()->page() : 0;
if (!page)
return IntRect();
- return page->chrome()->windowResizerRect();
+ return page->chrome().windowResizerRect();
+}
+
+float FrameView::visibleContentScaleFactor() const
+{
+ if (!m_frame || !m_frame->page())
+ return 1;
+
+ if (!m_frame->settings()->applyPageScaleFactorInCompositor() || m_frame != m_frame->page()->mainFrame())
+ return 1;
+
+ return m_frame->page()->pageScaleFactor();
}
void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
@@ -2781,7 +3133,7 @@ void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
return;
if (page->mainFrame() != m_frame)
return;
- page->chrome()->client()->notifyScrollerThumbIsVisibleInRect(scrollerThumb);
+ page->chrome().client()->notifyScrollerThumbIsVisibleInRect(scrollerThumb);
}
bool FrameView::scrollbarsCanBeActive() const
@@ -2811,45 +3163,55 @@ ScrollableArea* FrameView::enclosingScrollableArea() const
IntRect FrameView::scrollableAreaBoundingBox() const
{
- // FIXME: This isn't correct for transformed frames. We probably need to ask the renderer instead.
- return frameRect();
+ RenderPart* ownerRenderer = frame()->ownerRenderer();
+ if (!ownerRenderer)
+ return frameRect();
+
+ return ownerRenderer->absoluteContentQuad().enclosingBoundingBox();
}
-void FrameView::updateScrollableAreaSet()
+bool FrameView::isScrollable()
{
- // That ensures that only inner frames are cached.
- if (!parentFrameView())
- return;
-
// Check for:
- // 1) display:none or visibility:hidden set to self or inherited.
- // 2) overflow{-x,-y}: hidden;
- // 3) scrolling: no;
-
- // Covers #1.
- HTMLFrameOwnerElement* owner = m_frame->ownerElement();
- if (!owner || !owner->renderer() || !owner->renderer()->visibleToHitTesting()) {
- parentFrameView()->removeScrollableArea(this);
- return;
- }
+ // 1) If there an actual overflow.
+ // 2) display:none or visibility:hidden set to self or inherited.
+ // 3) overflow{-x,-y}: hidden;
+ // 4) scrolling: no;
- IntSize contentSize = contentsSize();
+ // Covers #1
+ IntSize totalContentsSize = this->totalContentsSize();
IntSize visibleContentSize = visibleContentRect().size();
- if ((contentSize.height() <= visibleContentSize.height() && contentSize.width() <= visibleContentSize.width())) {
- parentFrameView()->removeScrollableArea(this);
- return;
- }
+ if ((totalContentsSize.height() <= visibleContentSize.height() && totalContentsSize.width() <= visibleContentSize.width()))
+ return false;
- // Cover #2 and #3.
+ // Covers #2.
+ HTMLFrameOwnerElement* owner = m_frame->ownerElement();
+ if (owner && (!owner->renderer() || !owner->renderer()->visibleToHitTesting()))
+ return false;
+
+ // Cover #3 and #4.
ScrollbarMode horizontalMode;
ScrollbarMode verticalMode;
calculateScrollbarModesForLayout(horizontalMode, verticalMode, RulesFromWebContentOnly);
- if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff) {
- parentFrameView()->removeScrollableArea(this);
+ if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff)
+ return false;
+
+ return true;
+}
+
+void FrameView::updateScrollableAreaSet()
+{
+ // That ensures that only inner frames are cached.
+ FrameView* parentFrameView = this->parentFrameView();
+ if (!parentFrameView)
+ return;
+
+ if (!isScrollable()) {
+ parentFrameView->removeScrollableArea(this);
return;
}
- parentFrameView()->addScrollableArea(this);
+ parentFrameView->addScrollableArea(this);
}
bool FrameView::shouldSuspendScrollAnimations() const
@@ -2864,7 +3226,7 @@ void FrameView::scrollbarStyleChanged(int newStyle, bool forceUpdate)
return;
if (page->mainFrame() != m_frame)
return;
- page->chrome()->client()->recommendedScrollbarStyleDidChange(newStyle);
+ page->chrome().client()->recommendedScrollbarStyleDidChange(newStyle);
if (forceUpdate)
ScrollView::scrollbarStyleChanged(newStyle, forceUpdate);
@@ -2935,7 +3297,7 @@ void FrameView::updateAnnotatedRegions()
Page* page = m_frame->page();
if (!page)
return;
- page->chrome()->client()->annotatedRegionsChanged();
+ page->chrome().client()->annotatedRegionsChanged();
}
#endif
@@ -2951,7 +3313,7 @@ void FrameView::updateScrollCorner()
Element* body = doc ? doc->body() : 0;
if (body && body->renderer()) {
renderer = body->renderer();
- cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
+ cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
}
if (!cornerStyle) {
@@ -2959,20 +3321,20 @@ void FrameView::updateScrollCorner()
Element* docElement = doc ? doc->documentElement() : 0;
if (docElement && docElement->renderer()) {
renderer = docElement->renderer();
- cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
+ cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
}
}
if (!cornerStyle) {
// If we have an owning iframe/frame element, then it can set the custom scrollbar also.
if (RenderPart* renderer = m_frame->ownerRenderer())
- cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
+ cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
}
}
if (cornerStyle) {
if (!m_scrollCorner)
- m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document());
+ m_scrollCorner = RenderScrollbarPart::createAnonymous(renderer->document());
m_scrollCorner->setStyle(cornerStyle.release());
invalidateScrollCorner(cornerRect);
} else if (m_scrollCorner) {
@@ -3060,7 +3422,7 @@ bool FrameView::hasCustomScrollbars() const
for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
Widget* widget = current->get();
if (widget->isFrameView()) {
- if (static_cast<FrameView*>(widget)->hasCustomScrollbars())
+ if (toFrameView(widget)->hasCustomScrollbars())
return true;
} else if (widget->isScrollbar()) {
Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
@@ -3096,7 +3458,7 @@ bool FrameView::isInChildFrameWithFrameFlattening() const
return true;
}
- if (!m_frame->settings() || !m_frame->settings()->frameFlatteningEnabled())
+ if (!frameFlatteningEnabled())
return false;
if (m_frame->ownerElement()->hasTagName(frameTag))
@@ -3143,8 +3505,8 @@ void FrameView::updateControlTints()
if (!m_frame || m_frame->document()->url().isEmpty())
return;
- RenderView* root = rootRenderer(this);
- if ((root && root->theme()->supportsControlTints()) || hasCustomScrollbars())
+ RenderView* renderView = this->renderView();
+ if ((renderView && renderView->theme()->supportsControlTints()) || hasCustomScrollbars())
paintControlTints();
}
@@ -3171,7 +3533,10 @@ void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
if (m_inProgrammaticScroll)
return;
m_maintainScrollPositionAnchor = 0;
+ if (m_wasScrolledByUser == wasScrolledByUser)
+ return;
m_wasScrolledByUser = wasScrolledByUser;
+ adjustTiledBackingCoverage();
}
void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
@@ -3179,8 +3544,6 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
if (!frame())
return;
- InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get());
-
Document* document = m_frame->document();
#ifndef NDEBUG
@@ -3202,8 +3565,8 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
#endif
- RenderView* root = rootRenderer(this);
- if (!root) {
+ RenderView* renderView = this->renderView();
+ if (!renderView) {
LOG_ERROR("called FrameView::paint with nil renderer");
return;
}
@@ -3212,6 +3575,9 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
if (needsLayout())
return;
+ if (!p->paintingDisabled())
+ InspectorInstrumentation::willPaint(renderView);
+
bool isTopLevelPainter = !sCurrentPaintTimeStamp;
if (isTopLevelPainter)
sCurrentPaintTimeStamp = currentTime();
@@ -3246,7 +3612,7 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
// m_nodeToDraw is used to draw only one element (and its descendants)
RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
- RenderLayer* rootLayer = root->layer();
+ RenderLayer* rootLayer = renderView->layer();
#ifndef NDEBUG
RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(rootLayer->renderer());
@@ -3274,7 +3640,11 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
if (isTopLevelPainter)
sCurrentPaintTimeStamp = 0;
- InspectorInstrumentation::didPaint(cookie, p, rect);
+ if (!p->paintingDisabled()) {
+ InspectorInstrumentation::didPaint(renderView, p, rect);
+ // FIXME: should probably not fire milestones for snapshot painting. https://bugs.webkit.org/show_bug.cgi?id=117623
+ firePaintRelatedMilestones();
+ }
}
void FrameView::setPaintBehavior(PaintBehavior behavior)
@@ -3292,6 +3662,7 @@ bool FrameView::isPainting() const
return m_isPainting;
}
+// FIXME: change this to use the subtreePaint terminology.
void FrameView::setNodeToDraw(Node* node)
{
m_nodeToDraw = node;
@@ -3343,7 +3714,7 @@ void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& hori
Page* page = m_frame->page();
if (page->mainFrame() == m_frame) {
- if (page->chrome()->client()->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
+ if (page->chrome().client()->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
return;
}
@@ -3386,6 +3757,41 @@ void FrameView::updateLayoutAndStyleIfNeededRecursive()
ASSERT(!needsLayout());
}
+bool FrameView::qualifiesAsVisuallyNonEmpty() const
+{
+ // No content yet.
+ Element* documentElement = m_frame->document()->documentElement();
+ if (!documentElement || !documentElement->renderer())
+ return false;
+
+ // Ensure that we always get marked visually non-empty eventually.
+ if (!m_frame->document()->parsing() && m_frame->loader()->stateMachine()->committedFirstRealDocumentLoad())
+ return true;
+
+ // Require the document to grow a bit.
+ static const int documentHeightThreshold = 200;
+ if (documentElement->renderBox()->layoutOverflowRect().pixelSnappedHeight() < documentHeightThreshold)
+ return false;
+
+ // The first few hundred characters rarely contain the interesting content of the page.
+ if (m_visuallyNonEmptyCharacterCount > visualCharacterThreshold)
+ return true;
+ // Use a threshold value to prevent very small amounts of visible content from triggering didFirstVisuallyNonEmptyLayout
+ if (m_visuallyNonEmptyPixelCount > visualPixelThreshold)
+ return true;
+ return false;
+}
+
+void FrameView::updateIsVisuallyNonEmpty()
+{
+ if (m_isVisuallyNonEmpty)
+ return;
+ if (!qualifiesAsVisuallyNonEmpty())
+ return;
+ m_isVisuallyNonEmpty = true;
+ adjustTiledBackingCoverage();
+}
+
void FrameView::enableAutoSizeMode(bool enable, const IntSize& minSize, const IntSize& maxSize)
{
ASSERT(!enable || !minSize.isEmpty());
@@ -3420,23 +3826,23 @@ void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatS
{
// Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
// the state of things before and after the layout
- if (RenderView* root = rootRenderer(this)) {
- float pageLogicalWidth = root->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
- float pageLogicalHeight = root->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
+ if (RenderView* renderView = this->renderView()) {
+ float pageLogicalWidth = renderView->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
+ float pageLogicalHeight = renderView->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
LayoutUnit flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
LayoutUnit flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
- root->setLogicalWidth(flooredPageLogicalWidth);
- root->setPageLogicalHeight(flooredPageLogicalHeight);
- root->setNeedsLayoutAndPrefWidthsRecalc();
+ renderView->setLogicalWidth(flooredPageLogicalWidth);
+ renderView->setPageLogicalHeight(flooredPageLogicalHeight);
+ renderView->setNeedsLayoutAndPrefWidthsRecalc();
forceLayout();
// If we don't fit in the given page width, we'll lay out again. If we don't fit in the
// page width when shrunk, we will lay out at maximum shrink and clip extra content.
// FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
// implementation should not do this!
- bool horizontalWritingMode = root->style()->isHorizontalWritingMode();
- const LayoutRect& documentRect = root->documentRect();
+ bool horizontalWritingMode = renderView->style()->isHorizontalWritingMode();
+ const LayoutRect& documentRect = renderView->documentRect();
LayoutUnit docLogicalWidth = horizontalWritingMode ? documentRect.width() : documentRect.height();
if (docLogicalWidth > pageLogicalWidth) {
int expectedPageWidth = std::min<float>(documentRect.width(), pageSize.width() * maximumShrinkFactor);
@@ -3447,24 +3853,24 @@ void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatS
flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
- root->setLogicalWidth(flooredPageLogicalWidth);
- root->setPageLogicalHeight(flooredPageLogicalHeight);
- root->setNeedsLayoutAndPrefWidthsRecalc();
+ renderView->setLogicalWidth(flooredPageLogicalWidth);
+ renderView->setPageLogicalHeight(flooredPageLogicalHeight);
+ renderView->setNeedsLayoutAndPrefWidthsRecalc();
forceLayout();
- const LayoutRect& updatedDocumentRect = root->documentRect();
+ const LayoutRect& updatedDocumentRect = renderView->documentRect();
LayoutUnit docLogicalHeight = horizontalWritingMode ? updatedDocumentRect.height() : updatedDocumentRect.width();
LayoutUnit docLogicalTop = horizontalWritingMode ? updatedDocumentRect.y() : updatedDocumentRect.x();
LayoutUnit docLogicalRight = horizontalWritingMode ? updatedDocumentRect.maxX() : updatedDocumentRect.maxY();
LayoutUnit clippedLogicalLeft = 0;
- if (!root->style()->isLeftToRightDirection())
+ if (!renderView->style()->isLeftToRightDirection())
clippedLogicalLeft = docLogicalRight - pageLogicalWidth;
LayoutRect overflow(clippedLogicalLeft, docLogicalTop, pageLogicalWidth, docLogicalHeight);
if (!horizontalWritingMode)
overflow = overflow.transposedRect();
- root->clearLayoutOverflow();
- root->addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
+ renderView->clearLayoutOverflow();
+ renderView->addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
}
}
@@ -3474,28 +3880,31 @@ void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatS
void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
{
- if (RenderView* root = rootRenderer(this)) {
- // Use a context with painting disabled.
- GraphicsContext context((PlatformGraphicsContext*)0);
- root->setTruncatedAt(static_cast<int>(floorf(oldBottom)));
- IntRect dirtyRect(0, static_cast<int>(floorf(oldTop)), root->layoutOverflowRect().maxX(), static_cast<int>(ceilf(oldBottom - oldTop)));
- root->setPrintRect(dirtyRect);
- root->layer()->paint(&context, dirtyRect);
- *newBottom = root->bestTruncatedAt();
- if (*newBottom == 0)
- *newBottom = oldBottom;
- root->setPrintRect(IntRect());
- } else
+ RenderView* renderView = this->renderView();
+ if (!renderView) {
+ *newBottom = oldBottom;
+ return;
+
+ }
+ // Use a context with painting disabled.
+ GraphicsContext context((PlatformGraphicsContext*)0);
+ renderView->setTruncatedAt(static_cast<int>(floorf(oldBottom)));
+ IntRect dirtyRect(0, static_cast<int>(floorf(oldTop)), renderView->layoutOverflowRect().maxX(), static_cast<int>(ceilf(oldBottom - oldTop)));
+ renderView->setPrintRect(dirtyRect);
+ renderView->layer()->paint(&context, dirtyRect);
+ *newBottom = renderView->bestTruncatedAt();
+ if (!*newBottom)
*newBottom = oldBottom;
+ renderView->setPrintRect(IntRect());
}
IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
{
- IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect), SnapOffsetForTransforms).enclosingBoundingBox();
+ IntRect rect = pixelSnappedIntRect(enclosingLayoutRect(renderer->localToAbsoluteQuad(FloatRect(rendererRect)).boundingBox()));
// Convert from page ("absolute") to FrameView coordinates.
if (!delegatesScrolling())
- rect.moveBy(-scrollPosition());
+ rect.moveBy(-scrollPosition() + IntPoint(0, headerHeight()));
return rect;
}
@@ -3506,21 +3915,21 @@ IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect
// Convert from FrameView coords into page ("absolute") coordinates.
if (!delegatesScrolling())
- rect.moveBy(scrollPosition());
+ rect.moveBy(scrollPositionRelativeToDocument());
// FIXME: we don't have a way to map an absolute rect down to a local quad, so just
// move the rect for now.
- rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), UseTransforms | SnapOffsetForTransforms)));
+ rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), UseTransforms)));
return rect;
}
IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
{
- IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, UseTransforms | SnapOffsetForTransforms));
+ IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, UseTransforms));
// Convert from page ("absolute") to FrameView coordinates.
if (!delegatesScrolling())
- point.moveBy(-scrollPosition());
+ point.moveBy(-scrollPosition() + IntPoint(0, headerHeight()));
return point;
}
@@ -3530,16 +3939,16 @@ IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoi
// Convert from FrameView coords into page ("absolute") coordinates.
if (!delegatesScrolling())
- point += IntSize(scrollX(), scrollY());
+ point = point + scrollPositionRelativeToDocument();
- return roundedIntPoint(renderer->absoluteToLocal(point, UseTransforms | SnapOffsetForTransforms));
+ return roundedIntPoint(renderer->absoluteToLocal(point, UseTransforms));
}
IntRect FrameView::convertToContainingView(const IntRect& localRect) const
{
if (const ScrollView* parentScrollView = parent()) {
if (parentScrollView->isFrameView()) {
- const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+ const FrameView* parentView = toFrameView(parentScrollView);
// Get our renderer in the parent view
RenderPart* renderer = m_frame->ownerRenderer();
if (!renderer)
@@ -3562,7 +3971,7 @@ IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
{
if (const ScrollView* parentScrollView = parent()) {
if (parentScrollView->isFrameView()) {
- const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+ const FrameView* parentView = toFrameView(parentScrollView);
// Get our renderer in the parent view
RenderPart* renderer = m_frame->ownerRenderer();
@@ -3586,7 +3995,7 @@ IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
{
if (const ScrollView* parentScrollView = parent()) {
if (parentScrollView->isFrameView()) {
- const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+ const FrameView* parentView = toFrameView(parentScrollView);
// Get our renderer in the parent view
RenderPart* renderer = m_frame->ownerRenderer();
@@ -3611,7 +4020,7 @@ IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
{
if (const ScrollView* parentScrollView = parent()) {
if (parentScrollView->isFrameView()) {
- const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+ const FrameView* parentView = toFrameView(parentScrollView);
// Get our renderer in the parent view
RenderPart* renderer = m_frame->ownerRenderer();
@@ -3660,6 +4069,12 @@ void FrameView::setTracksRepaints(bool trackRepaints)
if (trackRepaints == m_isTrackingRepaints)
return;
+ // Force layout to flush out any pending repaints.
+ if (trackRepaints) {
+ if (frame() && frame()->document())
+ frame()->document()->updateLayout();
+ }
+
#if USE(ACCELERATED_COMPOSITING)
for (Frame* frame = m_frame->tree()->top(); frame; frame = frame->tree()->traverseNext()) {
if (RenderView* renderView = frame->contentRenderer())
@@ -3675,15 +4090,16 @@ void FrameView::resetTrackedRepaints()
{
m_trackedRepaintRects.clear();
#if USE(ACCELERATED_COMPOSITING)
- if (RenderView* root = rootRenderer(this)) {
- RenderLayerCompositor* compositor = root->compositor();
- compositor->resetTrackedRepaintRects();
- }
+ if (RenderView* renderView = this->renderView())
+ renderView->compositor()->resetTrackedRepaintRects();
#endif
}
String FrameView::trackedRepaintRectsAsText() const
{
+ if (frame() && frame()->document())
+ frame()->document()->updateLayout();
+
TextStream ts;
if (!m_trackedRepaintRects.isEmpty()) {
ts << "(repaint rects\n";
@@ -3694,18 +4110,24 @@ String FrameView::trackedRepaintRectsAsText() const
return ts.release();
}
-void FrameView::addScrollableArea(ScrollableArea* scrollableArea)
+bool FrameView::addScrollableArea(ScrollableArea* scrollableArea)
{
if (!m_scrollableAreas)
m_scrollableAreas = adoptPtr(new ScrollableAreaSet);
- m_scrollableAreas->add(scrollableArea);
+ return m_scrollableAreas->add(scrollableArea).isNewEntry;
}
-void FrameView::removeScrollableArea(ScrollableArea* scrollableArea)
+bool FrameView::removeScrollableArea(ScrollableArea* scrollableArea)
{
if (!m_scrollableAreas)
- return;
- m_scrollableAreas->remove(scrollableArea);
+ return false;
+
+ ScrollableAreaSet::iterator it = m_scrollableAreas->find(scrollableArea);
+ if (it == m_scrollableAreas->end())
+ return false;
+
+ m_scrollableAreas->remove(it);
+ return true;
}
bool FrameView::containsScrollableArea(ScrollableArea* scrollableArea) const
@@ -3718,21 +4140,37 @@ bool FrameView::containsScrollableArea(ScrollableArea* scrollableArea) const
void FrameView::removeChild(Widget* widget)
{
if (widget->isFrameView())
- removeScrollableArea(static_cast<FrameView*>(widget));
+ removeScrollableArea(toFrameView(widget));
ScrollView::removeChild(widget);
}
bool FrameView::wheelEvent(const PlatformWheelEvent& wheelEvent)
{
+ // Note that to allow for rubber-band over-scroll behavior, even non-scrollable views
+ // should handle wheel events.
+#if !ENABLE(RUBBER_BANDING)
+ if (!isScrollable())
+ return false;
+#endif
+
+ if (delegatesScrolling()) {
+ IntSize offset = scrollOffset();
+ IntSize newOffset = IntSize(offset.width() - wheelEvent.deltaX(), offset.height() - wheelEvent.deltaY());
+ if (offset != newOffset) {
+ ScrollView::scrollTo(newOffset);
+ scrollPositionChanged();
+ frame()->loader()->client()->didChangeScrollOffset();
+ }
+ return true;
+ }
+
// We don't allow mouse wheeling to happen in a ScrollView that has had its scrollbars explicitly disabled.
if (!canHaveScrollbars())
return false;
-#if !PLATFORM(WX)
if (platformWidget())
return false;
-#endif
#if ENABLE(THREADED_SCROLLING)
if (Page* page = m_frame->page()) {
@@ -3749,20 +4187,20 @@ bool FrameView::wheelEvent(const PlatformWheelEvent& wheelEvent)
bool FrameView::isVerticalDocument() const
{
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return true;
- return root->style()->isHorizontalWritingMode();
+ return renderView->style()->isHorizontalWritingMode();
}
bool FrameView::isFlippedDocument() const
{
- RenderView* root = rootRenderer(this);
- if (!root)
+ RenderView* renderView = this->renderView();
+ if (!renderView)
return false;
- return root->style()->isFlippedBlocksWritingMode();
+ return renderView->style()->isFlippedBlocksWritingMode();
}
void FrameView::notifyWidgetsInAllFrames(WidgetNotification notification)
@@ -3775,8 +4213,8 @@ void FrameView::notifyWidgetsInAllFrames(WidgetNotification notification)
AXObjectCache* FrameView::axObjectCache() const
{
- if (frame() && frame()->document() && frame()->document()->axObjectCacheExists())
- return frame()->document()->axObjectCache();
+ if (frame() && frame()->document())
+ return frame()->document()->existingAXObjectCache();
return 0;
}
@@ -3790,4 +4228,72 @@ void FrameView::setScrollingPerformanceLoggingEnabled(bool flag)
#endif
}
+void FrameView::didAddScrollbar(Scrollbar* scrollbar, ScrollbarOrientation orientation)
+{
+ ScrollableArea::didAddScrollbar(scrollbar, orientation);
+ if (AXObjectCache* cache = axObjectCache())
+ cache->handleScrollbarUpdate(this);
+}
+
+void FrameView::willRemoveScrollbar(Scrollbar* scrollbar, ScrollbarOrientation orientation)
+{
+ ScrollableArea::willRemoveScrollbar(scrollbar, orientation);
+ if (AXObjectCache* cache = axObjectCache()) {
+ cache->remove(scrollbar);
+ cache->handleScrollbarUpdate(this);
+ }
+}
+
+void FrameView::addPaintPendingMilestones(LayoutMilestones milestones)
+{
+ m_milestonesPendingPaint |= milestones;
+}
+
+void FrameView::firePaintRelatedMilestones()
+{
+ Page* page = m_frame->page();
+ if (!page)
+ return;
+
+ LayoutMilestones milestonesAchieved = 0;
+
+ // Make sure the pending paint milestones have actually been requested before we send them.
+ if (m_milestonesPendingPaint & DidFirstFlushForHeaderLayer) {
+ if (page->requestedLayoutMilestones() & DidFirstFlushForHeaderLayer)
+ milestonesAchieved |= DidFirstFlushForHeaderLayer;
+ }
+
+ if (m_milestonesPendingPaint & DidFirstPaintAfterSuppressedIncrementalRendering) {
+ if (page->requestedLayoutMilestones() & DidFirstPaintAfterSuppressedIncrementalRendering)
+ milestonesAchieved |= DidFirstPaintAfterSuppressedIncrementalRendering;
+ }
+
+ m_milestonesPendingPaint = 0;
+
+ if (milestonesAchieved) {
+ if (Frame* frame = page->mainFrame())
+ frame->loader()->didLayout(milestonesAchieved);
+ }
+}
+
+void FrameView::setVisualUpdatesAllowedByClient(bool visualUpdatesAllowed)
+{
+ if (m_visualUpdatesAllowedByClient == visualUpdatesAllowed)
+ return;
+
+ m_visualUpdatesAllowedByClient = visualUpdatesAllowed;
+
+ m_frame->document()->setVisualUpdatesAllowedByClient(visualUpdatesAllowed);
+}
+
+void FrameView::setScrollPinningBehavior(ScrollPinningBehavior pinning)
+{
+ m_scrollPinningBehavior = pinning;
+
+ if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator())
+ scrollingCoordinator->setScrollPinningBehavior(pinning);
+
+ updateScrollbars(scrollOffset());
+}
+
} // namespace WebCore