2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 * 1999 Lars Knoll <knoll@kde.org>
4 * 1999 Antti Koivisto <koivisto@kde.org>
5 * 2000 Dirk Mueller <mueller@kde.org>
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserved.
7 * (C) 2006 Graham Dennis (graham.dennis@gmail.com)
8 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
9 * Copyright (C) 2009 Google Inc. All rights reserved.
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details.
21 * You should have received a copy of the GNU Library General Public License
22 * along with this library; see the file COPYING.LIB. If not, write to
23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 * Boston, MA 02110-1301, USA.
28 #include "FrameView.h"
30 #include "AXObjectCache.h"
31 #include "AnimationController.h"
32 #include "BackForwardController.h"
33 #include "CachedImage.h"
34 #include "CachedResourceLoader.h"
36 #include "ChromeClient.h"
37 #include "DOMWindow.h"
38 #include "DocumentMarkerController.h"
39 #include "EventHandler.h"
40 #include "FloatRect.h"
41 #include "FocusController.h"
42 #include "FontCache.h"
43 #include "FontLoader.h"
44 #include "FrameLoader.h"
45 #include "FrameLoaderClient.h"
46 #include "FrameSelection.h"
47 #include "FrameTree.h"
48 #include "GraphicsContext.h"
49 #include "HTMLDocument.h"
50 #include "HTMLFrameElement.h"
51 #include "HTMLFrameSetElement.h"
52 #include "HTMLNames.h"
53 #include "HTMLPlugInImageElement.h"
54 #include "InspectorClient.h"
55 #include "InspectorController.h"
56 #include "InspectorInstrumentation.h"
57 #include "MainFrame.h"
58 #include "OverflowEvent.h"
59 #include "ProgressTracker.h"
60 #include "RenderEmbeddedObject.h"
61 #include "RenderFullScreen.h"
62 #include "RenderIFrame.h"
63 #include "RenderLayer.h"
64 #include "RenderLayerBacking.h"
65 #include "RenderScrollbar.h"
66 #include "RenderScrollbarPart.h"
67 #include "RenderStyle.h"
68 #include "RenderText.h"
69 #include "RenderTheme.h"
70 #include "RenderView.h"
71 #include "RenderWidget.h"
72 #include "ScrollAnimator.h"
73 #include "ScrollingCoordinator.h"
75 #include "StyleResolver.h"
76 #include "TextResourceDecoder.h"
77 #include "TextStream.h"
79 #include <wtf/CurrentTime.h>
81 #include <wtf/TemporaryChange.h>
83 #if USE(ACCELERATED_COMPOSITING)
84 #include "RenderLayerCompositor.h"
85 #include "TiledBacking.h"
89 #include "RenderSVGRoot.h"
90 #include "SVGDocument.h"
91 #include "SVGSVGElement.h"
94 #if USE(TILED_BACKING_STORE)
95 #include "TiledBackingStore.h"
98 #if ENABLE(TEXT_AUTOSIZING)
99 #include "TextAutosizer.h"
103 #include "DocumentLoader.h"
105 #include "MemoryCache.h"
106 #include "MemoryPressureHandler.h"
107 #include "SystemMemory.h"
108 #include "TileCache.h"
111 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
112 #include "HTMLMediaElement.h"
117 using namespace HTMLNames;
119 double FrameView::sCurrentPaintTimeStamp = 0.0;
122 // REPAINT_THROTTLING now chooses default values for throttling parameters.
123 // Should be removed when applications start using runtime configuration.
124 #if ENABLE(REPAINT_THROTTLING)
126 double FrameView::s_normalDeferredRepaintDelay = 0.016;
127 // Negative value would mean that first few repaints happen without a delay
128 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
129 // The delay grows on each repaint to this maximum value
130 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
131 // On each repaint the delay increses by this amount
132 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
134 // FIXME: Repaint throttling could be good to have on all platform.
135 // The balance between CPU use and repaint frequency will need some tuning for desktop.
136 // More hooks may be needed to reset the delay on things like GIF and CSS animations.
137 double FrameView::s_normalDeferredRepaintDelay = 0;
138 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
139 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
140 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
143 // The maximum number of updateEmbeddedObjects iterations that should be done before returning.
144 static const unsigned maxUpdateEmbeddedObjectsIterations = 2;
146 static RenderLayer::UpdateLayerPositionsFlags updateLayerPositionFlags(RenderLayer* layer, bool isRelayoutingSubtree, bool didFullRepaint)
148 RenderLayer::UpdateLayerPositionsFlags flags = RenderLayer::defaultFlags;
149 if (didFullRepaint) {
150 flags &= ~RenderLayer::CheckForRepaint;
151 flags |= RenderLayer::NeedsFullRepaintInBacking;
153 if (isRelayoutingSubtree && layer->isPaginated())
154 flags |= RenderLayer::UpdatePagination;
158 Pagination::Mode paginationModeForRenderStyle(const RenderStyle& style)
160 EOverflow overflow = style.overflowY();
161 if (overflow != OPAGEDX && overflow != OPAGEDY)
162 return Pagination::Unpaginated;
164 bool isHorizontalWritingMode = style.isHorizontalWritingMode();
165 TextDirection textDirection = style.direction();
166 WritingMode writingMode = style.writingMode();
168 // paged-x always corresponds to LeftToRightPaginated or RightToLeftPaginated. If the WritingMode
169 // is horizontal, then we use TextDirection to choose between those options. If the WritingMode
170 // is vertical, then the direction of the verticality dictates the choice.
171 if (overflow == OPAGEDX) {
172 if ((isHorizontalWritingMode && textDirection == LTR) || writingMode == LeftToRightWritingMode)
173 return Pagination::LeftToRightPaginated;
174 return Pagination::RightToLeftPaginated;
177 // paged-y always corresponds to TopToBottomPaginated or BottomToTopPaginated. If the WritingMode
178 // is horizontal, then the direction of the horizontality dictates the choice. If the WritingMode
179 // is vertical, then we use TextDirection to choose between those options.
180 if (writingMode == TopToBottomWritingMode || (!isHorizontalWritingMode && textDirection == RTL))
181 return Pagination::TopToBottomPaginated;
182 return Pagination::BottomToTopPaginated;
185 FrameView::FrameView(Frame& frame)
187 , m_canHaveScrollbars(true)
188 , m_layoutTimer(this, &FrameView::layoutTimerFired)
190 , m_layoutPhase(OutsideLayout)
191 , m_inSynchronousPostLayout(false)
192 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
193 , m_isTransparent(false)
194 , m_baseBackgroundColor(Color::white)
195 , m_mediaType("screen")
196 , m_overflowStatusDirty(true)
197 , m_viewportRenderer(0)
198 , m_wasScrolledByUser(false)
199 , m_inProgrammaticScroll(false)
200 , m_safeToPropagateScrollToParent(true)
201 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
202 , m_isTrackingRepaints(false)
203 , m_shouldUpdateWhileOffscreen(true)
204 , m_exposedRect(FloatRect::infiniteRect())
205 , m_deferSetNeedsLayouts(0)
206 , m_setNeedsLayoutWasDeferred(false)
208 , m_useCustomFixedPositionLayoutRect(false)
210 , m_shouldAutoSize(false)
211 , m_inAutoSize(false)
212 , m_didRunAutosize(false)
213 , m_autoSizeFixedMinimumHeight(0)
216 , m_milestonesPendingPaint(0)
217 , m_visualUpdatesAllowedByClient(true)
218 , m_scrollPinningBehavior(DoNotPin)
222 if (frame.isMainFrame()) {
223 ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed);
224 ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAutomatic);
228 PassRefPtr<FrameView> FrameView::create(Frame& frame)
230 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
232 return view.release();
235 PassRefPtr<FrameView> FrameView::create(Frame& frame, const IntSize& initialSize)
237 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
238 view->Widget::setFrameRect(IntRect(view->location(), initialSize));
240 return view.release();
243 FrameView::~FrameView()
245 if (m_postLayoutTasksTimer.isActive())
246 m_postLayoutTasksTimer.stop();
248 removeFromAXObjectCache();
251 // Custom scrollbars should already be destroyed at this point
252 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
253 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
255 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
256 setHasVerticalScrollbar(false);
258 ASSERT(!m_scrollCorner);
260 ASSERT(frame().view() != this || !frame().contentRenderer());
263 void FrameView::reset()
265 m_cannotBlitToWindow = false;
266 m_isOverlapped = false;
267 m_contentIsOpaque = false;
270 m_layoutTimer.stop();
272 m_delayedLayout = false;
273 m_needsFullRepaint = true;
274 m_layoutSchedulingEnabled = true;
275 m_layoutPhase = OutsideLayout;
276 m_inSynchronousPostLayout = false;
278 m_nestedLayoutCount = 0;
279 m_postLayoutTasksTimer.stop();
280 m_firstLayout = true;
281 m_firstLayoutCallbackPending = false;
282 m_wasScrolledByUser = false;
283 m_safeToPropagateScrollToParent = true;
284 m_lastViewportSize = IntSize();
285 m_lastZoomFactor = 1.0f;
286 m_deferringRepaints = 0;
288 m_repaintRects.clear();
289 m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading;
290 m_deferredRepaintTimer.stop();
291 m_isTrackingRepaints = false;
292 m_trackedRepaintRects.clear();
294 m_paintBehavior = PaintBehaviorNormal;
295 m_isPainting = false;
296 m_visuallyNonEmptyCharacterCount = 0;
297 m_visuallyNonEmptyPixelCount = 0;
298 m_isVisuallyNonEmpty = false;
299 m_firstVisuallyNonEmptyLayoutCallbackPending = true;
300 m_maintainScrollPositionAnchor = 0;
303 void FrameView::removeFromAXObjectCache()
305 if (AXObjectCache* cache = axObjectCache())
309 void FrameView::resetScrollbars()
311 // Reset the document's scrollbars back to our defaults before we yield the floor.
312 m_firstLayout = true;
313 setScrollbarsSuppressed(true);
314 if (m_canHaveScrollbars)
315 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
317 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
318 setScrollbarsSuppressed(false);
321 void FrameView::resetScrollbarsAndClearContentsSize()
325 setScrollbarsSuppressed(true);
326 setContentsSize(IntSize());
327 setScrollbarsSuppressed(false);
330 void FrameView::init()
334 m_margins = LayoutSize(-1, -1); // undefined
335 m_size = LayoutSize();
337 // Propagate the marginwidth/height and scrolling modes to the view.
338 Element* ownerElement = frame().ownerElement();
339 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
340 HTMLFrameElementBase* frameElt = toHTMLFrameElementBase(ownerElement);
341 if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
342 setCanHaveScrollbars(false);
343 LayoutUnit marginWidth = frameElt->marginWidth();
344 LayoutUnit marginHeight = frameElt->marginHeight();
345 if (marginWidth != -1)
346 setMarginWidth(marginWidth);
347 if (marginHeight != -1)
348 setMarginHeight(marginHeight);
351 Page* page = frame().page();
352 if (page && page->chrome().client().shouldPaintEntireContents())
353 setPaintsEntireContents(true);
356 void FrameView::prepareForDetach()
358 detachCustomScrollbars();
359 // When the view is no longer associated with a frame, it needs to be removed from the ax object cache
360 // right now, otherwise it won't be able to reach the topDocument()'s axObject cache later.
361 removeFromAXObjectCache();
363 if (frame().page()) {
364 if (ScrollingCoordinator* scrollingCoordinator = frame().page()->scrollingCoordinator())
365 scrollingCoordinator->willDestroyScrollableArea(this);
369 void FrameView::detachCustomScrollbars()
371 Scrollbar* horizontalBar = horizontalScrollbar();
372 if (horizontalBar && horizontalBar->isCustomScrollbar())
373 setHasHorizontalScrollbar(false);
375 Scrollbar* verticalBar = verticalScrollbar();
376 if (verticalBar && verticalBar->isCustomScrollbar())
377 setHasVerticalScrollbar(false);
379 m_scrollCorner = nullptr;
382 void FrameView::recalculateScrollbarOverlayStyle()
384 ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle();
385 ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault;
387 Color backgroundColor = documentBackgroundColor();
388 if (backgroundColor.isValid()) {
389 // Reduce the background color from RGB to a lightness value
390 // and determine which scrollbar style to use based on a lightness
392 double hue, saturation, lightness;
393 backgroundColor.getHSL(hue, saturation, lightness);
394 if (lightness <= .5 && backgroundColor.alpha() > 0)
395 overlayStyle = ScrollbarOverlayStyleLight;
398 if (oldOverlayStyle != overlayStyle)
399 setScrollbarOverlayStyle(overlayStyle);
402 void FrameView::clear()
404 setCanBlitOnScroll(true);
408 setScrollbarsSuppressed(true);
411 // To avoid flashes of white, disable tile updates immediately when view is cleared at the beginning of a page load.
412 // Tiling will be re-enabled from UIKit via [WAKWindow setTilingMode:] when we have content to draw.
413 if (TileCache* tileCache = this->tileCache())
414 tileCache->setTilingMode(TileCache::Disabled);
418 bool FrameView::didFirstLayout() const
420 return !m_firstLayout;
423 void FrameView::invalidateRect(const IntRect& rect)
426 if (HostWindow* window = hostWindow())
427 window->invalidateContentsAndRootView(rect, false /*immediate*/);
431 RenderWidget* renderer = frame().ownerRenderer();
435 IntRect repaintRect = rect;
436 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
437 renderer->borderTop() + renderer->paddingTop());
438 renderer->repaintRectangle(repaintRect);
441 void FrameView::setFrameRect(const IntRect& newRect)
443 IntRect oldRect = frameRect();
444 if (newRect == oldRect)
447 #if ENABLE(TEXT_AUTOSIZING)
448 // Autosized font sizes depend on the width of the viewing area.
449 if (newRect.width() != oldRect.width()) {
450 Page* page = frame().page();
451 if (frame().isMainFrame() && page->settings().textAutosizingEnabled()) {
452 for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext())
453 frame().document()->textAutosizer()->recalculateMultipliers();
458 ScrollView::setFrameRect(newRect);
460 updateScrollableAreaSet();
462 #if USE(ACCELERATED_COMPOSITING)
463 if (RenderView* renderView = this->renderView()) {
464 if (renderView->usesCompositing())
465 renderView->compositor().frameViewDidChangeSize();
469 if (!frameFlatteningEnabled())
470 sendResizeEventIfNeeded();
473 #if ENABLE(REQUEST_ANIMATION_FRAME)
474 bool FrameView::scheduleAnimation()
476 if (HostWindow* window = hostWindow()) {
477 window->scheduleAnimation();
484 void FrameView::setMarginWidth(LayoutUnit w)
486 // make it update the rendering area when set
487 m_margins.setWidth(w);
490 void FrameView::setMarginHeight(LayoutUnit h)
492 // make it update the rendering area when set
493 m_margins.setHeight(h);
496 bool FrameView::frameFlatteningEnabled() const
498 return frame().settings().frameFlatteningEnabled();
501 bool FrameView::isFrameFlatteningValidForThisFrame() const
503 if (!frameFlatteningEnabled())
506 HTMLFrameOwnerElement* owner = frame().ownerElement();
510 // Frame flattening is valid only for <frame> and <iframe>.
511 return owner->hasTagName(frameTag) || owner->hasTagName(iframeTag);
514 bool FrameView::avoidScrollbarCreation() const
516 // with frame flattening no subframe can have scrollbars
517 // but we also cannot turn scrollbars off as we determine
518 // our flattening policy using that.
519 return isFrameFlatteningValidForThisFrame();
522 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
524 m_canHaveScrollbars = canHaveScrollbars;
525 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
528 void FrameView::updateCanHaveScrollbars()
532 scrollbarModes(hMode, vMode);
533 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
534 setCanHaveScrollbars(false);
536 setCanHaveScrollbars(true);
539 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
541 if (!frame().settings().allowCustomScrollbarInMainFrame() && frame().isMainFrame())
542 return ScrollView::createScrollbar(orientation);
544 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
545 Document* doc = frame().document();
547 // Try the <body> element first as a scrollbar source.
548 Element* body = doc ? doc->body() : 0;
549 if (body && body->renderer() && body->renderer()->style().hasPseudoStyle(SCROLLBAR))
550 return RenderScrollbar::createCustomScrollbar(this, orientation, body);
552 // If the <body> didn't have a custom style, then the root element might.
553 Element* docElement = doc ? doc->documentElement() : 0;
554 if (docElement && docElement->renderer() && docElement->renderer()->style().hasPseudoStyle(SCROLLBAR))
555 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement);
557 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
558 RenderWidget* frameRenderer = frame().ownerRenderer();
559 if (frameRenderer && frameRenderer->style().hasPseudoStyle(SCROLLBAR))
560 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, &frame());
562 // Nobody set a custom style, so we just use a native scrollbar.
563 return ScrollView::createScrollbar(orientation);
566 void FrameView::setContentsSize(const IntSize& size)
568 if (size == contentsSize())
571 m_deferSetNeedsLayouts++;
573 ScrollView::setContentsSize(size);
574 ScrollView::contentsResized();
576 Page* page = frame().page();
580 updateScrollableAreaSet();
582 page->chrome().contentsSizeChanged(&frame(), size); // Notify only.
584 ASSERT(m_deferSetNeedsLayouts);
585 m_deferSetNeedsLayouts--;
587 if (!m_deferSetNeedsLayouts)
588 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
591 void FrameView::adjustViewSize()
593 RenderView* renderView = this->renderView();
597 ASSERT(frame().view() == this);
599 const IntRect rect = renderView->documentRect();
600 const IntSize& size = rect.size();
601 ScrollView::setScrollOrigin(IntPoint(-rect.x(), -rect.y()), !frame().document()->printing(), size == contentsSize());
603 setContentsSize(size);
606 void FrameView::applyOverflowToViewport(RenderElement* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
608 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
609 // overflow:hidden and overflow:scroll on <body> as applying to the document's
610 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
611 // use the root element.
613 // To combat the inability to scroll on a page with overflow:hidden on the root when scaled, disregard hidden when
614 // there is a frameScaleFactor that is greater than one on the main frame. Also disregard hidden if there is a
617 bool overrideHidden = frame().isMainFrame() && ((frame().frameScaleFactor() > 1) || headerHeight() || footerHeight());
619 EOverflow overflowX = o->style().overflowX();
620 EOverflow overflowY = o->style().overflowY();
623 if (o->isSVGRoot()) {
624 // overflow is ignored in stand-alone SVG documents.
625 if (!toRenderSVGRoot(o)->isEmbeddedThroughFrameContainingSVGDocument())
635 hMode = ScrollbarAuto;
637 hMode = ScrollbarAlwaysOff;
640 hMode = ScrollbarAlwaysOn;
643 hMode = ScrollbarAuto;
646 // Don't set it at all.
653 vMode = ScrollbarAuto;
655 vMode = ScrollbarAlwaysOff;
658 vMode = ScrollbarAlwaysOn;
661 vMode = ScrollbarAuto;
664 // Don't set it at all. Values of OPAGEDX and OPAGEDY are handled by applyPaginationToViewPort().
668 m_viewportRenderer = o;
671 void FrameView::applyPaginationToViewport()
673 Document* document = frame().document();
674 auto documentElement = document->documentElement();
675 RenderElement* documentRenderer = documentElement ? documentElement->renderer() : nullptr;
676 RenderElement* documentOrBodyRenderer = documentRenderer;
677 auto body = document->body();
678 if (body && body->renderer()) {
679 if (body->hasTagName(bodyTag))
680 documentOrBodyRenderer = documentRenderer->style().overflowX() == OVISIBLE && documentElement->hasTagName(htmlTag) ? body->renderer() : documentRenderer;
683 Pagination pagination;
685 if (!documentOrBodyRenderer) {
686 setPagination(pagination);
690 EOverflow overflowY = documentOrBodyRenderer->style().overflowY();
691 if (overflowY == OPAGEDX || overflowY == OPAGEDY) {
692 pagination.mode = WebCore::paginationModeForRenderStyle(documentOrBodyRenderer->style());
693 pagination.gap = static_cast<unsigned>(documentOrBodyRenderer->style().columnGap());
696 setPagination(pagination);
699 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy)
701 m_viewportRenderer = 0;
703 const HTMLFrameOwnerElement* owner = frame().ownerElement();
704 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
705 hMode = ScrollbarAlwaysOff;
706 vMode = ScrollbarAlwaysOff;
710 if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) {
711 hMode = ScrollbarAuto;
712 // Seamless documents begin with heights of 0; we special case that here
713 // to correctly render documents that don't need scrollbars.
714 IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size();
715 bool isSeamlessDocument = frame().document() && frame().document()->shouldDisplaySeamlesslyWithParent();
716 vMode = (isSeamlessDocument && !fullVisibleSize.height()) ? ScrollbarAlwaysOff : ScrollbarAuto;
718 hMode = ScrollbarAlwaysOff;
719 vMode = ScrollbarAlwaysOff;
723 Document* document = frame().document();
724 auto documentElement = document->documentElement();
725 RenderElement* rootRenderer = documentElement ? documentElement->renderer() : nullptr;
726 auto body = document->body();
727 if (body && body->renderer()) {
728 if (body->hasTagName(framesetTag) && !frameFlatteningEnabled()) {
729 vMode = ScrollbarAlwaysOff;
730 hMode = ScrollbarAlwaysOff;
731 } else if (body->hasTagName(bodyTag)) {
732 // It's sufficient to just check the X overflow,
733 // since it's illegal to have visible in only one direction.
734 RenderElement* o = rootRenderer->style().overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
735 applyOverflowToViewport(o, hMode, vMode);
737 } else if (rootRenderer)
738 applyOverflowToViewport(rootRenderer, hMode, vMode);
742 #if USE(ACCELERATED_COMPOSITING)
743 void FrameView::updateCompositingLayersAfterStyleChange()
745 RenderView* renderView = this->renderView();
749 // If we expect to update compositing after an incipient layout, don't do so here.
750 if (inPreLayoutStyleUpdate() || layoutPending() || renderView->needsLayout())
753 RenderLayerCompositor& compositor = renderView->compositor();
754 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
755 compositor.cacheAcceleratedCompositingFlags();
756 compositor.updateCompositingLayers(CompositingUpdateAfterStyleChange);
759 void FrameView::updateCompositingLayersAfterLayout()
761 RenderView* renderView = this->renderView();
765 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
766 renderView->compositor().cacheAcceleratedCompositingFlags();
767 renderView->compositor().updateCompositingLayers(CompositingUpdateAfterLayout);
770 void FrameView::clearBackingStores()
772 RenderView* renderView = this->renderView();
776 RenderLayerCompositor& compositor = renderView->compositor();
777 ASSERT(compositor.inCompositingMode());
778 compositor.enableCompositingMode(false);
779 compositor.clearBackingForAllLayers();
782 void FrameView::restoreBackingStores()
784 RenderView* renderView = this->renderView();
788 RenderLayerCompositor& compositor = renderView->compositor();
789 compositor.enableCompositingMode(true);
790 compositor.updateCompositingLayers(CompositingUpdateAfterLayout);
793 bool FrameView::usesCompositedScrolling() const
795 RenderView* renderView = this->renderView();
798 if (frame().settings().compositedScrollingForFramesEnabled())
799 return renderView->compositor().inForcedCompositingMode();
803 GraphicsLayer* FrameView::layerForScrolling() const
805 RenderView* renderView = this->renderView();
808 return renderView->compositor().scrollLayer();
811 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
813 RenderView* renderView = this->renderView();
816 return renderView->compositor().layerForHorizontalScrollbar();
819 GraphicsLayer* FrameView::layerForVerticalScrollbar() const
821 RenderView* renderView = this->renderView();
824 return renderView->compositor().layerForVerticalScrollbar();
827 GraphicsLayer* FrameView::layerForScrollCorner() const
829 RenderView* renderView = this->renderView();
832 return renderView->compositor().layerForScrollCorner();
835 TiledBacking* FrameView::tiledBacking() const
837 RenderView* renderView = this->renderView();
841 RenderLayerBacking* backing = renderView->layer()->backing();
845 return backing->graphicsLayer()->tiledBacking();
848 uint64_t FrameView::scrollLayerID() const
850 RenderView* renderView = this->renderView();
854 RenderLayerBacking* backing = renderView->layer()->backing();
858 return backing->scrollLayerID();
861 #if ENABLE(RUBBER_BANDING)
862 GraphicsLayer* FrameView::layerForOverhangAreas() const
864 RenderView* renderView = this->renderView();
867 return renderView->compositor().layerForOverhangAreas();
870 GraphicsLayer* FrameView::setWantsLayerForTopOverHangArea(bool wantsLayer) const
872 RenderView* renderView = this->renderView();
876 return renderView->compositor().updateLayerForTopOverhangArea(wantsLayer);
879 GraphicsLayer* FrameView::setWantsLayerForBottomOverHangArea(bool wantsLayer) const
881 RenderView* renderView = this->renderView();
885 return renderView->compositor().updateLayerForBottomOverhangArea(wantsLayer);
888 #endif // ENABLE(RUBBER_BANDING)
890 bool FrameView::flushCompositingStateForThisFrame(Frame* rootFrameForFlush)
892 RenderView* renderView = this->renderView();
894 return true; // We don't want to keep trying to update layers if we have no renderer.
896 ASSERT(frame().view() == this);
898 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
899 // layer content to occur before layout has happened, which will cause paintContents() to bail.
903 // If we sync compositing layers and allow the repaint to be deferred, there is time for a
904 // visible flash to occur. Instead, stop the deferred repaint timer and repaint immediately.
905 flushDeferredRepaints();
908 if (TileCache* tileCache = this->tileCache())
909 tileCache->doPendingRepaints();
912 renderView->compositor().flushPendingLayerChanges(rootFrameForFlush == &frame());
917 void FrameView::setNeedsOneShotDrawingSynchronization()
919 if (Page* page = frame().page())
920 page->chrome().client().setNeedsOneShotDrawingSynchronization();
923 GraphicsLayer* FrameView::graphicsLayerForPlatformWidget(PlatformWidget platformWidget)
925 // To find the Widget that corresponds with platformWidget we have to do a linear
926 // search of our child widgets.
927 Widget* foundWidget = nullptr;
928 for (auto& widget : children()) {
929 if (widget->platformWidget() != platformWidget)
931 foundWidget = widget.get();
938 auto* renderWidget = RenderWidget::find(foundWidget);
942 RenderLayer* widgetLayer = renderWidget->layer();
943 if (!widgetLayer || !widgetLayer->isComposited())
946 return widgetLayer->backing()->parentForSublayers();
949 void FrameView::scheduleLayerFlushAllowingThrottling()
951 RenderView* view = this->renderView();
954 view->compositor().scheduleLayerFlush(true /* canThrottle */);
956 #endif // USE(ACCELERATED_COMPOSITING)
958 void FrameView::setHeaderHeight(int headerHeight)
961 ASSERT(frame().isMainFrame());
962 m_headerHeight = headerHeight;
964 if (RenderView* renderView = this->renderView())
965 renderView->setNeedsLayout();
968 void FrameView::setFooterHeight(int footerHeight)
971 ASSERT(frame().isMainFrame());
972 m_footerHeight = footerHeight;
974 if (RenderView* renderView = this->renderView())
975 renderView->setNeedsLayout();
978 bool FrameView::hasCompositedContent() const
980 #if USE(ACCELERATED_COMPOSITING)
981 if (RenderView* renderView = this->renderView())
982 return renderView->compositor().inCompositingMode();
987 bool FrameView::hasCompositedContentIncludingDescendants() const
989 #if USE(ACCELERATED_COMPOSITING)
990 for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) {
991 RenderView* renderView = frame->contentRenderer();
992 if (RenderLayerCompositor* compositor = renderView ? &renderView->compositor() : 0) {
993 if (compositor->inCompositingMode())
996 if (!RenderLayerCompositor::allowsIndependentlyCompositedFrames(this))
1004 bool FrameView::hasCompositingAncestor() const
1006 #if USE(ACCELERATED_COMPOSITING)
1007 for (Frame* frame = this->frame().tree().parent(); frame; frame = frame->tree().parent()) {
1008 if (FrameView* view = frame->view()) {
1009 if (view->hasCompositedContent())
1017 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
1018 void FrameView::enterCompositingMode()
1020 #if USE(ACCELERATED_COMPOSITING)
1021 if (RenderView* renderView = this->renderView()) {
1022 renderView->compositor().enableCompositingMode();
1024 renderView->compositor().scheduleCompositingLayerUpdate();
1029 bool FrameView::isEnclosedInCompositingLayer() const
1031 #if USE(ACCELERATED_COMPOSITING)
1032 auto frameOwnerRenderer = frame().ownerRenderer();
1033 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
1036 if (FrameView* parentView = parentFrameView())
1037 return parentView->isEnclosedInCompositingLayer();
1042 bool FrameView::flushCompositingStateIncludingSubframes()
1044 #if USE(ACCELERATED_COMPOSITING)
1045 bool allFramesFlushed = flushCompositingStateForThisFrame(&frame());
1047 for (Frame* child = frame().tree().firstChild(); child; child = child->tree().traverseNext(&frame())) {
1048 bool flushed = child->view()->flushCompositingStateForThisFrame(&frame());
1049 allFramesFlushed &= flushed;
1051 return allFramesFlushed;
1052 #else // USE(ACCELERATED_COMPOSITING)
1057 bool FrameView::isSoftwareRenderable() const
1059 #if USE(ACCELERATED_COMPOSITING)
1060 RenderView* renderView = this->renderView();
1061 return !renderView || !renderView->compositor().has3DContent();
1067 void FrameView::didMoveOnscreen()
1069 contentAreaDidShow();
1072 void FrameView::willMoveOffscreen()
1074 contentAreaDidHide();
1077 void FrameView::setIsInWindow(bool isInWindow)
1079 if (RenderView* renderView = this->renderView())
1080 renderView->setIsInWindow(isInWindow);
1083 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
1085 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
1088 inline void FrameView::forceLayoutParentViewIfNeeded()
1091 RenderWidget* ownerRenderer = frame().ownerRenderer();
1095 RenderBox* contentBox = embeddedContentBox();
1099 RenderSVGRoot* svgRoot = toRenderSVGRoot(contentBox);
1100 if (svgRoot->everHadLayout() && !svgRoot->needsLayout())
1103 // If the embedded SVG document appears the first time, the ownerRenderer has already finished
1104 // layout without knowing about the existence of the embedded SVG document, because RenderReplaced
1105 // embeddedContentBox() returns 0, as long as the embedded document isn't loaded yet. Before
1106 // bothering to lay out the SVG document, mark the ownerRenderer needing layout and ask its
1107 // FrameView for a layout. After that the RenderEmbeddedObject (ownerRenderer) carries the
1108 // correct size, which RenderSVGRoot::computeReplacedLogicalWidth/Height rely on, when laying
1109 // out for the first time, or when the RenderSVGRoot size has changed dynamically (eg. via <script>).
1110 Ref<FrameView> frameView(ownerRenderer->view().frameView());
1112 // Mark the owner renderer as needing layout.
1113 ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc();
1115 // Synchronously enter layout, to layout the view containing the host object/embed/iframe.
1116 frameView->layout();
1120 void FrameView::layout(bool allowSubtree)
1125 // Many of the tasks performed during layout can cause this function to be re-entered,
1126 // so save the layout phase now and restore it on exit.
1127 TemporaryChange<LayoutPhase> layoutPhaseRestorer(m_layoutPhase, InPreLayout);
1129 // Protect the view from being deleted during layout (in recalcStyle)
1130 Ref<FrameView> protect(*this);
1132 // Every scroll that happens during layout is programmatic.
1133 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1135 bool inChildFrameLayoutWithFrameFlattening = isInChildFrameWithFrameFlattening();
1137 if (inChildFrameLayoutWithFrameFlattening) {
1138 startLayoutAtMainFrameViewIfNeeded(allowSubtree);
1139 RenderElement* root = m_layoutRoot ? m_layoutRoot : frame().document()->renderView();
1140 if (!root->needsLayout())
1145 if (updateFixedPositionLayoutRect())
1146 allowSubtree = false;
1149 m_layoutTimer.stop();
1150 m_delayedLayout = false;
1151 m_setNeedsLayoutWasDeferred = false;
1153 // we shouldn't enter layout() while painting
1154 ASSERT(!isPainting());
1158 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(&frame());
1160 if (!allowSubtree && m_layoutRoot) {
1161 m_layoutRoot->markContainingBlocksForLayout(false);
1165 ASSERT(frame().view() == this);
1166 ASSERT(frame().document());
1168 Document& document = *frame().document();
1169 ASSERT(!document.inPageCache());
1172 RenderElement* root;
1175 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1177 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_postLayoutTasksTimer.isActive() && !inChildFrameLayoutWithFrameFlattening) {
1178 // This is a new top-level layout. If there are any remaining tasks from the previous
1179 // layout, finish them now.
1180 TemporaryChange<bool> inSynchronousPostLayoutChange(m_inSynchronousPostLayout, true);
1181 performPostLayoutTasks();
1184 m_layoutPhase = InPreLayoutStyleUpdate;
1186 // Viewport-dependent media queries may cause us to need completely different style information.
1187 StyleResolver* styleResolver = document.styleResolverIfExists();
1188 if (!styleResolver || styleResolver->affectedByViewportChange()) {
1189 document.styleResolverChanged(DeferRecalcStyle);
1190 // FIXME: This instrumentation event is not strictly accurate since cached media query results do not persist across StyleResolver rebuilds.
1191 InspectorInstrumentation::mediaQueryResultChanged(&document);
1193 document.evaluateMediaQueryList();
1195 // If there is any pagination to apply, it will affect the RenderView's style, so we should
1196 // take care of that now.
1197 applyPaginationToViewport();
1199 // Always ensure our style info is up-to-date. This can happen in situations where
1200 // the layout beats any sort of style recalc update that needs to occur.
1201 document.updateStyleIfNeeded();
1202 m_layoutPhase = InPreLayout;
1204 subtree = m_layoutRoot;
1206 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
1207 // so there's no point to continuing to layout
1211 root = subtree ? m_layoutRoot : document.renderView();
1213 // FIXME: Do we need to set m_size here?
1217 // Close block here so we can set up the font cache purge preventer, which we will still
1218 // want in scope even after we want m_layoutSchedulingEnabled to be restored again.
1219 // The next block sets m_layoutSchedulingEnabled back to false once again.
1222 FontCachePurgePreventer fontCachePurgePreventer;
1225 ++m_nestedLayoutCount;
1228 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1230 if (!m_layoutRoot) {
1231 HTMLElement* body = document.body();
1232 if (body && body->renderer()) {
1233 if (body->hasTagName(framesetTag) && !frameFlatteningEnabled()) {
1234 body->renderer()->setChildNeedsLayout();
1235 } else if (body->hasTagName(bodyTag)) {
1236 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
1237 body->renderer()->setChildNeedsLayout();
1241 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1242 if (m_firstLayout && !frame().ownerElement())
1243 printf("Elapsed time before first layout: %d\n", document.elapsedTime());
1247 autoSizeIfEnabled();
1249 m_needsFullRepaint = !subtree && (m_firstLayout || toRenderView(*root).printing());
1252 ScrollbarMode hMode;
1253 ScrollbarMode vMode;
1254 calculateScrollbarModesForLayout(hMode, vMode);
1256 if (m_firstLayout || (hMode != horizontalScrollbarMode() || vMode != verticalScrollbarMode())) {
1257 if (m_firstLayout) {
1258 setScrollbarsSuppressed(true);
1260 m_firstLayout = false;
1261 m_firstLayoutCallbackPending = true;
1262 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
1263 m_lastViewportSize = fixedLayoutSize();
1266 m_lastViewportSize = actualVisibleContentRect().size();
1268 m_lastViewportSize = visibleContentRect(IncludeScrollbars).size();
1271 m_lastZoomFactor = root->style().zoom();
1273 // Set the initial vMode to AlwaysOn if we're auto.
1274 if (vMode == ScrollbarAuto)
1275 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
1276 // Set the initial hMode to AlwaysOff if we're auto.
1277 if (hMode == ScrollbarAuto)
1278 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
1280 setScrollbarModes(hMode, vMode);
1281 setScrollbarsSuppressed(false, true);
1283 setScrollbarModes(hMode, vMode);
1286 LayoutSize oldSize = m_size;
1288 m_size = layoutSize();
1290 if (oldSize != m_size) {
1291 m_needsFullRepaint = true;
1292 if (!m_firstLayout) {
1293 RenderBox* rootRenderer = document.documentElement() ? document.documentElement()->renderBox() : 0;
1294 RenderBox* bodyRenderer = rootRenderer && document.body() ? document.body()->renderBox() : 0;
1295 if (bodyRenderer && bodyRenderer->stretchesToViewport())
1296 bodyRenderer->setChildNeedsLayout();
1297 else if (rootRenderer && rootRenderer->stretchesToViewport())
1298 rootRenderer->setChildNeedsLayout();
1302 m_layoutPhase = InPreLayout;
1305 layer = root->enclosingLayer();
1307 bool disableLayoutState = false;
1309 disableLayoutState = root->view().shouldDisableLayoutStateForSubtree(root);
1310 root->view().pushLayoutState(*root);
1312 LayoutStateDisabler layoutStateDisabler(disableLayoutState ? &root->view() : 0);
1314 ASSERT(m_layoutPhase == InPreLayout);
1315 m_layoutPhase = InLayout;
1317 beginDeferredRepaints();
1318 forceLayoutParentViewIfNeeded();
1320 ASSERT(m_layoutPhase == InLayout);
1323 #if ENABLE(IOS_TEXT_AUTOSIZING)
1324 float minZoomFontSize = frame().settings().minimumZoomFontSize();
1325 float visWidth = frame().page()->mainFrame().textAutosizingWidth();
1326 if (minZoomFontSize && visWidth && !root->view().printing()) {
1327 root->adjustComputedFontSizesOnBlocks(minZoomFontSize, visWidth);
1328 bool needsLayout = root->needsLayout();
1333 #if ENABLE(TEXT_AUTOSIZING)
1334 if (document.textAutosizer()->processSubtree(root) && root->needsLayout())
1337 endDeferredRepaints();
1339 ASSERT(m_layoutPhase == InLayout);
1342 root->view().popLayoutState(*root);
1346 // Close block here to end the scope of changeSchedulingEnabled and layoutStateDisabler.
1349 m_layoutPhase = InViewSizeAdjust;
1351 bool neededFullRepaint = m_needsFullRepaint;
1353 if (!subtree && !toRenderView(*root).printing())
1356 m_layoutPhase = InPostLayout;
1358 m_needsFullRepaint = neededFullRepaint;
1360 // Now update the positions of all layers.
1361 beginDeferredRepaints();
1362 if (m_needsFullRepaint)
1363 root->view().repaintRootContents();
1365 layer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPositionFlags(layer, subtree, m_needsFullRepaint));
1367 endDeferredRepaints();
1369 #if USE(ACCELERATED_COMPOSITING)
1370 updateCompositingLayersAfterLayout();
1375 #if PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(EFL)
1376 if (AXObjectCache* cache = root->document().existingAXObjectCache())
1377 cache->postNotification(root, AXObjectCache::AXLayoutComplete);
1380 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
1381 updateAnnotatedRegions();
1384 #if ENABLE(IOS_TOUCH_EVENTS)
1385 document.dirtyTouchEventRects();
1388 ASSERT(!root->needsLayout());
1390 updateCanBlitOnScrollRecursively();
1392 if (document.hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1393 updateOverflowStatus(layoutWidth() < contentsWidth(), layoutHeight() < contentsHeight());
1395 if (!m_postLayoutTasksTimer.isActive()) {
1396 if (!m_inSynchronousPostLayout) {
1397 if (inChildFrameLayoutWithFrameFlattening)
1398 updateWidgetPositions();
1400 TemporaryChange<bool> inSynchronousPostLayoutChange(m_inSynchronousPostLayout, true);
1401 performPostLayoutTasks(); // Calls resumeScheduledEvents().
1405 if (!m_postLayoutTasksTimer.isActive() && (needsLayout() || m_inSynchronousPostLayout || inChildFrameLayoutWithFrameFlattening)) {
1406 // If we need layout or are already in a synchronous call to postLayoutTasks(),
1407 // defer widget updates and event dispatch until after we return. postLayoutTasks()
1408 // can make us need to update again, and we can get stuck in a nasty cycle unless
1409 // we call it through the timer here.
1410 m_postLayoutTasksTimer.startOneShot(0);
1416 InspectorInstrumentation::didLayout(cookie, root);
1418 --m_nestedLayoutCount;
1420 if (m_nestedLayoutCount)
1423 if (Page* page = frame().page())
1424 page->chrome().client().layoutUpdated(&frame());
1427 RenderBox* FrameView::embeddedContentBox() const
1430 RenderView* renderView = this->renderView();
1434 RenderObject* firstChild = renderView->firstChild();
1435 if (!firstChild || !firstChild->isBox())
1438 // Curently only embedded SVG documents participate in the size-negotiation logic.
1439 if (toRenderBox(firstChild)->isSVGRoot())
1440 return toRenderBox(firstChild);
1446 void FrameView::addEmbeddedObjectToUpdate(RenderEmbeddedObject& embeddedObject)
1448 if (!m_embeddedObjectsToUpdate)
1449 m_embeddedObjectsToUpdate = adoptPtr(new ListHashSet<RenderEmbeddedObject*>);
1451 HTMLFrameOwnerElement& element = embeddedObject.frameOwnerElement();
1452 if (isHTMLObjectElement(element) || isHTMLEmbedElement(element)) {
1453 // Tell the DOM element that it needs a widget update.
1454 HTMLPlugInImageElement& pluginElement = toHTMLPlugInImageElement(element);
1455 if (!pluginElement.needsCheckForSizeChange())
1456 pluginElement.setNeedsWidgetUpdate(true);
1459 m_embeddedObjectsToUpdate->add(&embeddedObject);
1462 void FrameView::removeEmbeddedObjectToUpdate(RenderEmbeddedObject& embeddedObject)
1464 if (!m_embeddedObjectsToUpdate)
1467 m_embeddedObjectsToUpdate->remove(&embeddedObject);
1470 void FrameView::setMediaType(const String& mediaType)
1472 m_mediaType = mediaType;
1475 String FrameView::mediaType() const
1477 // See if we have an override type.
1478 String overrideType = frame().loader().client().overrideMediaType();
1479 InspectorInstrumentation::applyEmulatedMedia(&frame(), &overrideType);
1480 if (!overrideType.isNull())
1481 return overrideType;
1485 void FrameView::adjustMediaTypeForPrinting(bool printing)
1488 if (m_mediaTypeWhenNotPrinting.isNull())
1489 m_mediaTypeWhenNotPrinting = mediaType();
1490 setMediaType("print");
1492 if (!m_mediaTypeWhenNotPrinting.isNull())
1493 setMediaType(m_mediaTypeWhenNotPrinting);
1494 m_mediaTypeWhenNotPrinting = String();
1498 bool FrameView::useSlowRepaints(bool considerOverlap) const
1500 bool mustBeSlow = hasSlowRepaintObjects() || (platformWidget() && hasViewportConstrainedObjects());
1502 // FIXME: WidgetMac.mm makes the assumption that useSlowRepaints ==
1503 // m_contentIsOpaque, so don't take the fast path for composited layers
1504 // if they are a platform widget in order to get painting correctness
1505 // for transparent layers. See the comment in WidgetMac::paint.
1506 if (contentsInCompositedLayer() && !platformWidget())
1509 bool isOverlapped = m_isOverlapped && considerOverlap;
1511 if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque)
1514 if (FrameView* parentView = parentFrameView())
1515 return parentView->useSlowRepaints(considerOverlap);
1520 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1522 return useSlowRepaints(false);
1525 void FrameView::updateCanBlitOnScrollRecursively()
1527 for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) {
1528 if (FrameView* view = frame->view())
1529 view->setCanBlitOnScroll(!view->useSlowRepaints());
1533 bool FrameView::contentsInCompositedLayer() const
1535 #if USE(ACCELERATED_COMPOSITING)
1536 RenderView* renderView = this->renderView();
1537 if (renderView && renderView->isComposited()) {
1538 GraphicsLayer* layer = renderView->layer()->backing()->graphicsLayer();
1539 if (layer && layer->drawsContent())
1546 void FrameView::setCannotBlitToWindow()
1548 m_cannotBlitToWindow = true;
1549 updateCanBlitOnScrollRecursively();
1552 void FrameView::addSlowRepaintObject(RenderElement* o)
1554 bool hadSlowRepaintObjects = hasSlowRepaintObjects();
1556 if (!m_slowRepaintObjects)
1557 m_slowRepaintObjects = adoptPtr(new HashSet<RenderElement*>);
1559 m_slowRepaintObjects->add(o);
1561 if (!hadSlowRepaintObjects) {
1562 updateCanBlitOnScrollRecursively();
1564 if (Page* page = frame().page()) {
1565 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1566 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1571 void FrameView::removeSlowRepaintObject(RenderElement* o)
1573 if (!m_slowRepaintObjects)
1576 m_slowRepaintObjects->remove(o);
1577 if (m_slowRepaintObjects->isEmpty()) {
1578 m_slowRepaintObjects = nullptr;
1579 updateCanBlitOnScrollRecursively();
1581 if (Page* page = frame().page()) {
1582 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1583 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1588 void FrameView::addViewportConstrainedObject(RenderElement* object)
1590 if (!m_viewportConstrainedObjects)
1591 m_viewportConstrainedObjects = adoptPtr(new ViewportConstrainedObjectSet);
1593 if (!m_viewportConstrainedObjects->contains(object)) {
1594 m_viewportConstrainedObjects->add(object);
1595 if (platformWidget())
1596 updateCanBlitOnScrollRecursively();
1598 if (Page* page = frame().page()) {
1599 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1600 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1605 void FrameView::removeViewportConstrainedObject(RenderElement* object)
1607 if (m_viewportConstrainedObjects && m_viewportConstrainedObjects->remove(object)) {
1608 if (Page* page = frame().page()) {
1609 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1610 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1613 // FIXME: In addFixedObject() we only call this if there's a platform widget,
1614 // why isn't the same check being made here?
1615 updateCanBlitOnScrollRecursively();
1619 LayoutRect FrameView::viewportConstrainedVisibleContentRect() const
1621 LayoutRect viewportRect = visibleContentRect();
1622 viewportRect.setLocation(toPoint(scrollOffsetForFixedPosition()));
1623 return viewportRect;
1626 IntSize FrameView::scrollOffsetForFixedPosition(const IntRect& visibleContentRect, const IntSize& totalContentsSize, const IntPoint& scrollPosition, const IntPoint& scrollOrigin, float frameScaleFactor, bool fixedElementsLayoutRelativeToFrame, ScrollBehaviorForFixedElements behaviorForFixed, int headerHeight, int footerHeight)
1629 if (behaviorForFixed == StickToDocumentBounds)
1630 position = ScrollableArea::constrainScrollPositionForOverhang(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, headerHeight, footerHeight);
1632 position = scrollPosition;
1633 position.setY(position.y() - headerHeight);
1636 IntSize maxSize = totalContentsSize - visibleContentRect.size();
1638 float dragFactorX = (fixedElementsLayoutRelativeToFrame || !maxSize.width()) ? 1 : (totalContentsSize.width() - visibleContentRect.width() * frameScaleFactor) / maxSize.width();
1639 float dragFactorY = (fixedElementsLayoutRelativeToFrame || !maxSize.height()) ? 1 : (totalContentsSize.height() - visibleContentRect.height() * frameScaleFactor) / maxSize.height();
1641 return IntSize(position.x() * dragFactorX / frameScaleFactor, position.y() * dragFactorY / frameScaleFactor);
1644 IntSize FrameView::scrollOffsetForFixedPosition() const
1646 IntRect visibleContentRect = this->visibleContentRect();
1647 IntSize totalContentsSize = this->totalContentsSize();
1648 IntPoint scrollPosition = this->scrollPosition();
1649 IntPoint scrollOrigin = this->scrollOrigin();
1650 float frameScaleFactor = frame().frameScaleFactor();
1651 ScrollBehaviorForFixedElements behaviorForFixed = scrollBehaviorForFixedElements();
1652 return scrollOffsetForFixedPosition(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, frameScaleFactor, fixedElementsLayoutRelativeToFrame(), behaviorForFixed, headerHeight(), footerHeight());
1655 IntPoint FrameView::minimumScrollPosition() const
1657 IntPoint minimumPosition(ScrollView::minimumScrollPosition());
1659 if (frame().isMainFrame() && m_scrollPinningBehavior == PinToBottom)
1660 minimumPosition.setY(maximumScrollPosition().y());
1662 return minimumPosition;
1665 IntPoint FrameView::maximumScrollPosition() const
1667 IntPoint maximumOffset(contentsWidth() - visibleWidth() - scrollOrigin().x(), totalContentsSize().height() - visibleHeight() - scrollOrigin().y());
1669 maximumOffset.clampNegativeToZero();
1671 if (frame().isMainFrame() && m_scrollPinningBehavior == PinToTop)
1672 maximumOffset.setY(minimumScrollPosition().y());
1674 return maximumOffset;
1677 bool FrameView::fixedElementsLayoutRelativeToFrame() const
1679 return frame().settings().fixedElementsLayoutRelativeToFrame();
1682 IntPoint FrameView::lastKnownMousePosition() const
1684 return frame().eventHandler().lastKnownMousePosition();
1687 bool FrameView::isHandlingWheelEvent() const
1689 return frame().eventHandler().isHandlingWheelEvent();
1692 bool FrameView::shouldSetCursor() const
1694 Page* page = frame().page();
1695 return page && page->isVisible() && page->focusController().isActive();
1698 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1700 if (!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty()) {
1701 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1705 const bool isCompositedContentLayer = contentsInCompositedLayer();
1707 // Get the rects of the fixed objects visible in the rectToScroll
1708 Region regionToUpdate;
1709 for (auto& renderer : *m_viewportConstrainedObjects) {
1710 if (!renderer->style().hasViewportConstrainedPosition())
1712 #if USE(ACCELERATED_COMPOSITING)
1713 if (renderer->isComposited())
1717 // Fixed items should always have layers.
1718 ASSERT(renderer->hasLayer());
1719 RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
1721 #if USE(ACCELERATED_COMPOSITING)
1722 if (layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForBoundsOutOfView
1723 || layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForNoVisibleContent) {
1724 // Don't invalidate for invisible fixed layers.
1729 #if ENABLE(CSS_FILTERS)
1730 if (layer->hasAncestorWithFilterOutsets()) {
1731 // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot
1732 // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
1736 IntRect updateRect = pixelSnappedIntRect(layer->repaintRectIncludingNonCompositingDescendants());
1737 updateRect = contentsToRootView(updateRect);
1738 if (!isCompositedContentLayer && clipsRepaints())
1739 updateRect.intersect(rectToScroll);
1740 if (!updateRect.isEmpty())
1741 regionToUpdate.unite(updateRect);
1745 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1747 // 2) update the area of fixed objects that has been invalidated
1748 Vector<IntRect> subRectsToUpdate = regionToUpdate.rects();
1749 size_t viewportConstrainedObjectsCount = subRectsToUpdate.size();
1750 for (size_t i = 0; i < viewportConstrainedObjectsCount; ++i) {
1751 IntRect updateRect = subRectsToUpdate[i];
1752 IntRect scrolledRect = updateRect;
1753 scrolledRect.move(scrollDelta);
1754 updateRect.unite(scrolledRect);
1755 #if USE(ACCELERATED_COMPOSITING)
1756 if (isCompositedContentLayer) {
1757 updateRect = rootViewToContents(updateRect);
1758 ASSERT(renderView());
1759 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
1763 if (clipsRepaints())
1764 updateRect.intersect(rectToScroll);
1765 hostWindow()->invalidateContentsAndRootView(updateRect, false);
1771 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1773 #if USE(ACCELERATED_COMPOSITING)
1774 if (contentsInCompositedLayer()) {
1775 IntRect updateRect = visibleContentRect();
1777 // Make sure to "apply" the scale factor here since we're converting from frame view
1778 // coordinates to layer backing coordinates.
1779 updateRect.scale(1 / frame().frameScaleFactor());
1781 ASSERT(renderView());
1782 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
1785 repaintSlowRepaintObjects();
1787 if (RenderWidget* frameRenderer = frame().ownerRenderer()) {
1788 if (isEnclosedInCompositingLayer()) {
1789 LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1790 frameRenderer->borderTop() + frameRenderer->paddingTop(),
1791 visibleWidth(), visibleHeight());
1792 frameRenderer->repaintRectangle(rect);
1798 ScrollView::scrollContentsSlowPath(updateRect);
1801 void FrameView::repaintSlowRepaintObjects()
1803 if (!m_slowRepaintObjects)
1806 // Renderers with fixed backgrounds may be in compositing layers, so we need to explicitly
1807 // repaint them after scrolling.
1808 for (auto& renderer : *m_slowRepaintObjects)
1809 renderer->repaint();
1812 // Note that this gets called at painting time.
1813 void FrameView::setIsOverlapped(bool isOverlapped)
1815 if (isOverlapped == m_isOverlapped)
1818 m_isOverlapped = isOverlapped;
1819 updateCanBlitOnScrollRecursively();
1821 #if USE(ACCELERATED_COMPOSITING)
1822 if (hasCompositedContentIncludingDescendants()) {
1823 // Overlap can affect compositing tests, so if it changes, we need to trigger
1824 // a layer update in the parent document.
1825 if (Frame* parentFrame = frame().tree().parent()) {
1826 if (RenderView* parentView = parentFrame->contentRenderer()) {
1827 RenderLayerCompositor& compositor = parentView->compositor();
1828 compositor.setCompositingLayersNeedRebuild();
1829 compositor.scheduleCompositingLayerUpdate();
1833 if (RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) {
1834 // We also need to trigger reevaluation for this and all descendant frames,
1835 // since a frame uses compositing if any ancestor is compositing.
1836 for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) {
1837 if (RenderView* view = frame->contentRenderer()) {
1838 RenderLayerCompositor& compositor = view->compositor();
1839 compositor.setCompositingLayersNeedRebuild();
1840 compositor.scheduleCompositingLayerUpdate();
1848 bool FrameView::isOverlappedIncludingAncestors() const
1853 if (FrameView* parentView = parentFrameView()) {
1854 if (parentView->isOverlapped())
1861 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1863 if (contentIsOpaque == m_contentIsOpaque)
1866 m_contentIsOpaque = contentIsOpaque;
1867 updateCanBlitOnScrollRecursively();
1870 void FrameView::restoreScrollbar()
1872 setScrollbarsSuppressed(false);
1875 bool FrameView::scrollToFragment(const URL& url)
1877 // If our URL has no ref, then we have no place we need to jump to.
1878 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1879 // and possibly repaint because :target pseudo class may have been
1880 // set (see bug 11321).
1881 if (!url.hasFragmentIdentifier() && !frame().document()->cssTarget())
1884 String fragmentIdentifier = url.fragmentIdentifier();
1885 if (scrollToAnchor(fragmentIdentifier))
1888 // Try again after decoding the ref, based on the document's encoding.
1889 if (TextResourceDecoder* decoder = frame().document()->decoder())
1890 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1895 bool FrameView::scrollToAnchor(const String& name)
1897 ASSERT(frame().document());
1899 if (!frame().document()->haveStylesheetsLoaded()) {
1900 frame().document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1904 frame().document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1906 Element* anchorElement = frame().document()->findAnchor(name);
1908 // Setting to null will clear the current target.
1909 frame().document()->setCSSTarget(anchorElement);
1912 if (frame().document()->isSVGDocument()) {
1913 if (SVGSVGElement* svg = toSVGDocument(frame().document())->rootElement()) {
1914 svg->setupInitialView(name, anchorElement);
1921 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1922 if (!anchorElement && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1925 maintainScrollPositionAtAnchor(anchorElement ? static_cast<Node*>(anchorElement) : frame().document());
1927 // If the anchor accepts keyboard focus, move focus there to aid users relying on keyboard navigation.
1928 if (anchorElement && anchorElement->isFocusable())
1929 frame().document()->setFocusedElement(anchorElement);
1934 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1936 m_maintainScrollPositionAnchor = anchorNode;
1937 if (!m_maintainScrollPositionAnchor)
1940 // We need to update the layout before scrolling, otherwise we could
1941 // really mess things up if an anchor scroll comes at a bad moment.
1942 frame().document()->updateStyleIfNeeded();
1943 // Only do a layout if changes have occurred that make it necessary.
1944 RenderView* renderView = this->renderView();
1945 if (renderView && renderView->needsLayout())
1951 void FrameView::scrollElementToRect(Element* element, const IntRect& rect)
1953 frame().document()->updateLayoutIgnorePendingStylesheets();
1955 LayoutRect bounds = element->boundingBox();
1956 int centeringOffsetX = (rect.width() - bounds.width()) / 2;
1957 int centeringOffsetY = (rect.height() - bounds.height()) / 2;
1958 setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y()));
1961 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1963 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1964 m_maintainScrollPositionAnchor = 0;
1965 ScrollView::setScrollPosition(scrollPoint);
1968 void FrameView::delegatesScrollingDidChange()
1970 #if USE(ACCELERATED_COMPOSITING)
1971 // When we switch to delgatesScrolling mode, we should destroy the scrolling/clipping layers in RenderLayerCompositor.
1972 if (hasCompositedContent())
1973 clearBackingStores();
1978 void FrameView::setFixedVisibleContentRect(const IntRect& visibleContentRect)
1980 bool visibleContentSizeDidChange = false;
1981 if (visibleContentRect.size() != this->fixedVisibleContentRect().size()) {
1982 // When the viewport size changes or the content is scaled, we need to
1983 // reposition the fixed and sticky positioned elements.
1984 setViewportConstrainedObjectsNeedLayout();
1985 visibleContentSizeDidChange = true;
1988 IntSize offset = scrollOffset();
1989 ScrollView::setFixedVisibleContentRect(visibleContentRect);
1990 if (offset != scrollOffset()) {
1991 updateLayerPositionsAfterScrolling();
1992 if (frame().page()->settings().acceleratedCompositingForFixedPositionEnabled())
1993 updateCompositingLayersAfterScrolling();
1994 scrollAnimator()->setCurrentPosition(scrollPosition());
1995 scrollPositionChanged();
1997 if (visibleContentSizeDidChange) {
1998 // Update the scroll-bars to calculate new page-step size.
1999 updateScrollbars(scrollOffset());
2001 frame().loader().client().didChangeScrollOffset();
2005 void FrameView::setViewportConstrainedObjectsNeedLayout()
2007 if (!hasViewportConstrainedObjects())
2010 for (auto& renderer : *m_viewportConstrainedObjects)
2011 renderer->setNeedsLayout();
2014 void FrameView::scrollPositionChangedViaPlatformWidget()
2016 updateLayerPositionsAfterScrolling();
2017 updateCompositingLayersAfterScrolling();
2018 repaintSlowRepaintObjects();
2019 scrollPositionChanged();
2022 void FrameView::scrollPositionChanged()
2024 frame().eventHandler().sendScrollEvent();
2025 frame().eventHandler().dispatchFakeMouseMoveEventSoon();
2027 #if USE(ACCELERATED_COMPOSITING)
2028 if (RenderView* renderView = this->renderView()) {
2029 if (renderView->usesCompositing())
2030 renderView->compositor().frameViewDidScroll();
2035 void FrameView::updateLayerPositionsAfterScrolling()
2037 // If we're scrolling as a result of updating the view size after layout, we'll update widgets and layer positions soon anyway.
2038 if (m_layoutPhase == InViewSizeAdjust)
2041 if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) {
2042 if (RenderView* renderView = this->renderView()) {
2043 updateWidgetPositions();
2044 renderView->layer()->updateLayerPositionsAfterDocumentScroll();
2049 bool FrameView::shouldUpdateCompositingLayersAfterScrolling() const
2051 #if ENABLE(ASYNC_SCROLLING)
2052 // If the scrolling thread is updating the fixed elements, then the FrameView should not update them as well.
2054 Page* page = frame().page();
2058 if (&page->mainFrame() != &frame())
2061 ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
2062 if (!scrollingCoordinator)
2065 if (!scrollingCoordinator->supportsFixedPositionLayers())
2068 if (scrollingCoordinator->shouldUpdateScrollLayerPositionSynchronously())
2071 if (inProgrammaticScroll())
2079 void FrameView::updateCompositingLayersAfterScrolling()
2081 #if USE(ACCELERATED_COMPOSITING)
2082 if (!shouldUpdateCompositingLayersAfterScrolling())
2085 if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) {
2086 if (RenderView* renderView = this->renderView())
2087 renderView->compositor().updateCompositingLayers(CompositingUpdateOnScroll);
2092 bool FrameView::isRubberBandInProgress() const
2094 if (scrollbarsSuppressed())
2097 // If the scrolling thread updates the scroll position for this FrameView, then we should return
2098 // ScrollingCoordinator::isRubberBandInProgress().
2099 if (Page* page = frame().page()) {
2100 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
2101 if (!scrollingCoordinator->shouldUpdateScrollLayerPositionSynchronously())
2102 return scrollingCoordinator->isRubberBandInProgress();
2106 // If the main thread updates the scroll position for this FrameView, we should return
2107 // ScrollAnimator::isRubberBandInProgress().
2108 if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
2109 return scrollAnimator->isRubberBandInProgress();
2114 bool FrameView::requestScrollPositionUpdate(const IntPoint& position)
2116 #if ENABLE(ASYNC_SCROLLING)
2117 if (TiledBacking* tiledBacking = this->tiledBacking()) {
2118 IntRect visibleRect = visibleContentRect();
2119 visibleRect.setLocation(position);
2120 tiledBacking->prepopulateRect(visibleRect);
2123 if (Page* page = frame().page()) {
2124 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2125 return scrollingCoordinator->requestScrollPositionUpdate(this, position);
2128 UNUSED_PARAM(position);
2134 HostWindow* FrameView::hostWindow() const
2136 if (Page* page = frame().page())
2137 return &page->chrome();
2141 void FrameView::addTrackedRepaintRect(const IntRect& r)
2143 if (!m_isTrackingRepaints || r.isEmpty())
2146 IntRect repaintRect = r;
2147 repaintRect.move(-scrollOffset());
2148 m_trackedRepaintRects.append(repaintRect);
2151 const unsigned cRepaintRectUnionThreshold = 25;
2153 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
2155 ASSERT(!frame().ownerElement());
2157 addTrackedRepaintRect(r);
2159 double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay();
2160 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
2161 IntRect paintRect = r;
2162 if (clipsRepaints() && !paintsEntireContents())
2163 paintRect.intersect(visibleContentRect());
2164 if (paintRect.isEmpty())
2166 if (m_repaintCount == cRepaintRectUnionThreshold) {
2167 IntRect unionedRect;
2168 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
2169 unionedRect.unite(pixelSnappedIntRect(m_repaintRects[i]));
2170 m_repaintRects.clear();
2171 m_repaintRects.append(unionedRect);
2173 if (m_repaintCount < cRepaintRectUnionThreshold)
2174 m_repaintRects.append(paintRect);
2176 m_repaintRects[0].unite(paintRect);
2179 if (!m_deferringRepaints)
2180 startDeferredRepaintTimer(delay);
2185 if (!shouldUpdate(immediate))
2188 #if USE(TILED_BACKING_STORE)
2189 if (frame().tiledBackingStore()) {
2190 frame().tiledBackingStore()->invalidate(r);
2194 ScrollView::repaintContentRectangle(r, immediate);
2197 static unsigned countRenderedCharactersInRenderObjectWithThreshold(const RenderObject& renderer, unsigned countSoFar, unsigned threshold)
2199 // FIXME: Consider writing this using RenderObject::nextInPreOrder() instead of using recursion.
2200 if (renderer.isText())
2201 countSoFar += toRenderText(renderer).text()->length();
2203 for (RenderObject* child = renderer.firstChildSlow(); child; child = child->nextSibling()) {
2204 if (countSoFar >= threshold)
2206 countSoFar = countRenderedCharactersInRenderObjectWithThreshold(*child, countSoFar, threshold);
2211 bool FrameView::renderedCharactersExceed(unsigned threshold)
2213 if (!m_frame->contentRenderer())
2215 return countRenderedCharactersInRenderObjectWithThreshold(*m_frame->contentRenderer(), 0, threshold) >= threshold;
2218 void FrameView::contentsResized()
2220 ScrollView::contentsResized();
2224 void FrameView::fixedLayoutSizeChanged()
2226 // Can be triggered before the view is set, see comment in FrameView::visibleContentsResized().
2227 // An ASSERT is triggered when a view schedules a layout before being attached to a frame.
2228 if (!frame().view())
2230 ScrollView::fixedLayoutSizeChanged();
2233 void FrameView::visibleContentsResized()
2235 // We check to make sure the view is attached to a frame() as this method can
2236 // be triggered before the view is attached by Frame::createView(...) setting
2237 // various values such as setScrollBarModes(...) for example. An ASSERT is
2238 // triggered when a view is layout before being attached to a frame().
2239 if (!frame().view())
2243 if (RenderView* root = m_frame->contentRenderer()) {
2244 if (useCustomFixedPositionLayoutRect() && hasViewportConstrainedObjects()) {
2245 setViewportConstrainedObjectsNeedLayout();
2246 // We must eagerly enter compositing mode because fixed position elements
2247 // will not have been made compositing via a preceding style change before
2248 // m_useCustomFixedPositionLayoutRect was true.
2249 root->compositor().enableCompositingMode();
2254 if (!useFixedLayout() && needsLayout())
2257 #if USE(ACCELERATED_COMPOSITING)
2258 if (RenderView* renderView = this->renderView()) {
2259 if (renderView->usesCompositing())
2260 renderView->compositor().frameViewDidChangeSize();
2265 void FrameView::addedOrRemovedScrollbar()
2267 #if USE(ACCELERATED_COMPOSITING)
2268 if (RenderView* renderView = this->renderView()) {
2269 if (renderView->usesCompositing())
2270 renderView->compositor().frameViewDidAddOrRemoveScrollbars();
2275 void FrameView::beginDeferredRepaints()
2277 if (!frame().isMainFrame()) {
2278 frame().mainFrame().view()->beginDeferredRepaints();
2282 m_deferringRepaints++;
2285 void FrameView::endDeferredRepaints()
2287 if (!frame().isMainFrame()) {
2288 frame().mainFrame().view()->endDeferredRepaints();
2292 ASSERT(m_deferringRepaints > 0);
2294 if (--m_deferringRepaints)
2297 if (m_deferredRepaintTimer.isActive())
2300 if (double delay = adjustedDeferredRepaintDelay()) {
2301 startDeferredRepaintTimer(delay);
2305 doDeferredRepaints();
2308 void FrameView::startDeferredRepaintTimer(double delay)
2310 if (m_deferredRepaintTimer.isActive())
2313 m_deferredRepaintTimer.startOneShot(delay);
2316 void FrameView::handleLoadCompleted()
2318 // Once loading has completed, allow autoSize one last opportunity to
2319 // reduce the size of the frame.
2320 autoSizeIfEnabled();
2321 if (shouldUseLoadTimeDeferredRepaintDelay())
2323 m_deferredRepaintDelay = s_normalDeferredRepaintDelay;
2324 flushDeferredRepaints();
2327 void FrameView::flushDeferredRepaints()
2329 if (!m_deferredRepaintTimer.isActive())
2331 m_deferredRepaintTimer.stop();
2332 doDeferredRepaints();
2335 void FrameView::doDeferredRepaints()
2337 ASSERT(!m_deferringRepaints);
2338 if (!shouldUpdate()) {
2339 m_repaintRects.clear();
2343 unsigned size = m_repaintRects.size();
2344 for (unsigned i = 0; i < size; i++) {
2345 #if USE(TILED_BACKING_STORE)
2346 if (frame().tiledBackingStore()) {
2347 frame().tiledBackingStore()->invalidate(pixelSnappedIntRect(m_repaintRects[i]));
2351 ScrollView::repaintContentRectangle(pixelSnappedIntRect(m_repaintRects[i]), false);
2353 m_repaintRects.clear();
2356 updateDeferredRepaintDelayAfterRepaint();
2359 bool FrameView::shouldUseLoadTimeDeferredRepaintDelay() const
2361 // Don't defer after the initial load of the page has been completed.
2362 if (frame().tree().top().loader().isComplete())
2364 Document* document = frame().document();
2367 if (document->parsing())
2369 if (document->cachedResourceLoader()->requestCount())
2374 void FrameView::updateDeferredRepaintDelayAfterRepaint()
2376 if (!shouldUseLoadTimeDeferredRepaintDelay()) {
2377 m_deferredRepaintDelay = s_normalDeferredRepaintDelay;
2380 double incrementedRepaintDelay = m_deferredRepaintDelay + s_deferredRepaintDelayIncrementDuringLoading;
2381 m_deferredRepaintDelay = std::min(incrementedRepaintDelay, s_maxDeferredRepaintDelayDuringLoading);
2384 void FrameView::resetDeferredRepaintDelay()
2386 m_deferredRepaintDelay = 0;
2387 if (m_deferredRepaintTimer.isActive()) {
2388 m_deferredRepaintTimer.stop();
2389 if (!m_deferringRepaints)
2390 doDeferredRepaints();
2392 #if USE(ACCELERATED_COMPOSITING)
2393 if (RenderView* view = renderView())
2394 view->compositor().disableLayerFlushThrottlingTemporarilyForInteraction();
2398 double FrameView::adjustedDeferredRepaintDelay() const
2400 ASSERT(!m_deferringRepaints);
2401 if (!m_deferredRepaintDelay)
2403 double timeSinceLastPaint = monotonicallyIncreasingTime() - m_lastPaintTime;
2404 return std::max<double>(0, m_deferredRepaintDelay - timeSinceLastPaint);
2407 void FrameView::deferredRepaintTimerFired(Timer<FrameView>&)
2409 doDeferredRepaints();
2412 void FrameView::updateLayerFlushThrottlingInAllFrames()
2414 #if USE(ACCELERATED_COMPOSITING)
2415 bool isMainLoadProgressing = frame().page()->progress().isMainLoadProgressing();
2416 for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) {
2417 if (RenderView* renderView = frame->contentRenderer())
2418 renderView->compositor().setLayerFlushThrottlingEnabled(isMainLoadProgressing);
2423 void FrameView::adjustTiledBackingCoverage()
2425 #if USE(ACCELERATED_COMPOSITING)
2426 RenderView* renderView = this->renderView();
2427 if (renderView && renderView->layer()->backing())
2428 renderView->layer()->backing()->adjustTiledBackingCoverage();
2431 if (TileCache* tileCache = this->tileCache())
2432 tileCache->setSpeculativeTileCreationEnabled(!m_frame->page()->progress().isMainLoadProgressing());
2436 void FrameView::layoutTimerFired(Timer<FrameView>&)
2438 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2439 if (!frame().document()->ownerElement())
2440 printf("Layout timer fired at %d\n", frame().document()->elapsedTime());
2445 void FrameView::scheduleRelayout()
2447 // FIXME: We should assert the page is not in the page cache, but that is causing
2448 // too many false assertions. See <rdar://problem/7218118>.
2449 ASSERT(frame().view() == this);
2452 m_layoutRoot->markContainingBlocksForLayout(false);
2455 if (!m_layoutSchedulingEnabled)
2459 if (!frame().document()->shouldScheduleLayout())
2461 InspectorInstrumentation::didInvalidateLayout(&frame());
2462 // When frame flattening is enabled, the contents of the frame could affect the layout of the parent frames.
2463 // Also invalidate parent frame starting from the owner element of this frame.
2464 if (frame().ownerRenderer() && isInChildFrameWithFrameFlattening())
2465 frame().ownerRenderer()->setNeedsLayout(MarkContainingBlockChain);
2467 int delay = frame().document()->minimumLayoutDelay();
2468 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
2469 unscheduleRelayout();
2470 if (m_layoutTimer.isActive())
2473 m_delayedLayout = delay != 0;
2475 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2476 if (!frame().document()->ownerElement())
2477 printf("Scheduling layout for %d\n", delay);
2480 m_layoutTimer.startOneShot(delay * 0.001);
2483 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
2485 for (RenderObject* r = descendant; r; r = r->container()) {
2492 void FrameView::scheduleRelayoutOfSubtree(RenderElement& newRelayoutRoot)
2494 ASSERT(renderView());
2495 RenderView& renderView = *this->renderView();
2497 // Try to catch unnecessary work during render tree teardown.
2498 ASSERT(!renderView.documentBeingDestroyed());
2499 ASSERT(frame().view() == this);
2501 if (renderView.needsLayout()) {
2502 newRelayoutRoot.markContainingBlocksForLayout(false);
2506 if (!layoutPending() && m_layoutSchedulingEnabled) {
2507 int delay = renderView.document().minimumLayoutDelay();
2508 ASSERT(!newRelayoutRoot.container() || !newRelayoutRoot.container()->needsLayout());
2509 m_layoutRoot = &newRelayoutRoot;
2510 InspectorInstrumentation::didInvalidateLayout(&frame());
2511 m_delayedLayout = delay != 0;
2512 m_layoutTimer.startOneShot(delay * 0.001);
2516 if (m_layoutRoot == &newRelayoutRoot)
2519 if (!m_layoutRoot) {
2520 // Just relayout the subtree.
2521 newRelayoutRoot.markContainingBlocksForLayout(false);
2522 InspectorInstrumentation::didInvalidateLayout(&frame());
2526 if (isObjectAncestorContainerOf(m_layoutRoot, &newRelayoutRoot)) {
2527 // Keep the current root.
2528 newRelayoutRoot.markContainingBlocksForLayout(false, m_layoutRoot);
2529 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2533 if (isObjectAncestorContainerOf(&newRelayoutRoot, m_layoutRoot)) {
2534 // Re-root at newRelayoutRoot.
2535 m_layoutRoot->markContainingBlocksForLayout(false, &newRelayoutRoot);
2536 m_layoutRoot = &newRelayoutRoot;
2537 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2538 InspectorInstrumentation::didInvalidateLayout(&frame());
2542 // Just do a full relayout.
2543 m_layoutRoot->markContainingBlocksForLayout(false);
2545 newRelayoutRoot.markContainingBlocksForLayout(false);
2546 InspectorInstrumentation::didInvalidateLayout(&frame());
2549 bool FrameView::layoutPending() const
2551 return m_layoutTimer.isActive();
2554 bool FrameView::needsLayout() const
2556 // This can return true in cases where the document does not have a body yet.
2557 // Document::shouldScheduleLayout takes care of preventing us from scheduling
2558 // layout in that case.
2559 RenderView* renderView = this->renderView();
2560 return layoutPending()
2561 || (renderView && renderView->needsLayout())
2563 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
2566 void FrameView::setNeedsLayout()
2568 if (m_deferSetNeedsLayouts) {
2569 m_setNeedsLayoutWasDeferred = true;
2573 if (RenderView* renderView = this->renderView())
2574 renderView->setNeedsLayout();
2577 void FrameView::unscheduleRelayout()
2579 if (!m_layoutTimer.isActive())
2582 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2583 if (!frame().document()->ownerElement())
2584 printf("Layout timer unscheduled at %d\n", frame().document()->elapsedTime());
2587 m_layoutTimer.stop();
2588 m_delayedLayout = false;
2591 #if ENABLE(REQUEST_ANIMATION_FRAME)
2592 void FrameView::serviceScriptedAnimations(double monotonicAnimationStartTime)
2594 for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext()) {
2595 frame->view()->serviceScrollAnimations();
2596 frame->animation().serviceAnimations();
2599 Vector<RefPtr<Document>> documents;
2600 for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext())
2601 documents.append(frame->document());
2603 for (size_t i = 0; i < documents.size(); ++i)
2604 documents[i]->serviceScriptedAnimations(monotonicAnimationStartTime);
2608 bool FrameView::isTransparent() const
2610 return m_isTransparent;
2613 void FrameView::setTransparent(bool isTransparent)
2615 m_isTransparent = isTransparent;
2618 bool FrameView::hasOpaqueBackground() const
2620 return !m_isTransparent && !m_baseBackgroundColor.hasAlpha();
2623 Color FrameView::baseBackgroundColor() const
2625 return m_baseBackgroundColor;
2628 void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
2630 if (!backgroundColor.isValid())
2631 m_baseBackgroundColor = Color::white;
2633 m_baseBackgroundColor = backgroundColor;
2635 recalculateScrollbarOverlayStyle();
2638 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
2640 for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) {
2641 if (FrameView* view = frame->view()) {
2642 view->setTransparent(transparent);
2643 view->setBaseBackgroundColor(backgroundColor);
2648 bool FrameView::hasExtendedBackground() const
2650 #if USE(ACCELERATED_COMPOSITING)
2651 if (!frame().settings().backgroundShouldExtendBeyondPage())
2654 TiledBacking* tiledBacking = this->tiledBacking();
2658 return tiledBacking->hasMargins();
2664 IntRect FrameView::extendedBackgroundRect() const
2666 #if USE(ACCELERATED_COMPOSITING)
2667 TiledBacking* tiledBacking = this->tiledBacking();
2671 return tiledBacking->bounds();
2673 RenderView* renderView = this->renderView();
2677 return renderView->unscaledDocumentRect();
2681 #if USE(ACCELERATED_COMPOSITING)
2682 void FrameView::setBackgroundExtendsBeyondPage(bool extendBackground)
2684 RenderView* renderView = this->renderView();
2688 RenderLayerBacking* backing = renderView->layer()->backing();
2692 backing->setTiledBackingHasMargins(extendBackground);
2696 bool FrameView::shouldUpdateWhileOffscreen() const
2698 return m_shouldUpdateWhileOffscreen;
2701 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
2703 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
2706 bool FrameView::shouldUpdate(bool immediateRequested) const
2708 if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen())
2713 void FrameView::scrollToAnchor()
2715 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
2719 if (!anchorNode->renderer())
2723 if (anchorNode != frame().document())
2724 rect = anchorNode->boundingBox();
2726 // Scroll nested layers and frames to reveal the anchor.
2727 // Align to the top and to the closest side (this matches other browsers).
2728 anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
2730 if (AXObjectCache* cache = frame().document()->existingAXObjectCache())
2731 cache->handleScrolledToAnchor(anchorNode.get());
2733 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
2734 m_maintainScrollPositionAnchor = anchorNode;
2737 void FrameView::updateEmbeddedObject(RenderEmbeddedObject& embeddedObject)
2739 // No need to update if it's already crashed or known to be missing.
2740 if (embeddedObject.isPluginUnavailable())
2743 HTMLFrameOwnerElement& element = embeddedObject.frameOwnerElement();
2745 if (embeddedObject.isSnapshottedPlugIn()) {
2746 if (isHTMLObjectElement(element) || isHTMLEmbedElement(element)) {
2747 HTMLPlugInImageElement& pluginElement = toHTMLPlugInImageElement(element);
2748 pluginElement.checkSnapshotStatus();
2753 auto weakRenderer = embeddedObject.createWeakPtr();
2755 // FIXME: This could turn into a real virtual dispatch if we defined
2756 // updateWidget(PluginCreationOption) on HTMLElement.
2757 if (isHTMLObjectElement(element) || isHTMLEmbedElement(element) || isHTMLAppletElement(element)) {
2758 HTMLPlugInImageElement& pluginElement = toHTMLPlugInImageElement(element);
2759 if (pluginElement.needsCheckForSizeChange()) {
2760 pluginElement.checkSnapshotStatus();
2763 if (pluginElement.needsWidgetUpdate())
2764 pluginElement.updateWidget(CreateAnyWidgetType);
2767 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
2768 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
2769 else if (element.isMediaElement())
2770 toHTMLMediaElement(element).updateWidget(CreateAnyWidgetType);
2773 ASSERT_NOT_REACHED();
2775 // It's possible the renderer was destroyed below updateWidget() since loading a plugin may execute arbitrary JavaScript.
2779 embeddedObject.updateWidgetPosition();
2782 bool FrameView::updateEmbeddedObjects()
2784 if (m_nestedLayoutCount > 1 || !m_embeddedObjectsToUpdate || m_embeddedObjectsToUpdate->isEmpty())
2787 WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
2789 // Insert a marker for where we should stop.
2790 ASSERT(!m_embeddedObjectsToUpdate->contains(nullptr));
2791 m_embeddedObjectsToUpdate->add(nullptr);
2793 while (!m_embeddedObjectsToUpdate->isEmpty()) {
2794 RenderEmbeddedObject* embeddedObject = m_embeddedObjectsToUpdate->takeFirst();
2795 if (!embeddedObject)
2797 updateEmbeddedObject(*embeddedObject);
2800 return m_embeddedObjectsToUpdate->isEmpty();
2803 void FrameView::flushAnyPendingPostLayoutTasks()
2805 if (!m_postLayoutTasksTimer.isActive())
2808 performPostLayoutTasks();
2811 void FrameView::performPostLayoutTasks()
2813 m_postLayoutTasksTimer.stop();
2815 frame().selection().setCaretRectNeedsUpdate();
2816 frame().selection().updateAppearance();
2818 LayoutMilestones requestedMilestones = 0;
2819 LayoutMilestones milestonesAchieved = 0;
2820 Page* page = frame().page();
2822 requestedMilestones = page->requestedLayoutMilestones();
2824 if (m_nestedLayoutCount <= 1 && frame().document()->documentElement()) {
2825 if (m_firstLayoutCallbackPending) {
2826 m_firstLayoutCallbackPending = false;
2827 frame().loader().didFirstLayout();
2828 if (requestedMilestones & DidFirstLayout)
2829 milestonesAchieved |= DidFirstLayout;
2830 if (frame().isMainFrame())
2831 page->startCountingRelevantRepaintedObjects();
2833 updateIsVisuallyNonEmpty();
2835 // If the layout was done with pending sheets, we are not in fact visually non-empty yet.
2836 if (m_isVisuallyNonEmpty && !frame().document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) {
2837 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
2838 if (requestedMilestones & DidFirstVisuallyNonEmptyLayout)
2839 milestonesAchieved |= DidFirstVisuallyNonEmptyLayout;
2844 // Only send layout-related delegate callbacks synchronously for the main frame to
2845 // avoid re-entering layout for the main frame while delivering a layout-related delegate
2846 // callback for a subframe.
2847 if (frame().isMainFrame())
2848 page->chrome().client().didLayout();
2851 if (milestonesAchieved && frame().isMainFrame())
2852 frame().loader().didLayout(milestonesAchieved);
2854 #if ENABLE(FONT_LOAD_EVENTS)
2855 if (RuntimeEnabledFeatures::sharedFeatures().fontLoadEventsEnabled())
2856 frame().document()->fontloader()->didLayout();
2859 // FIXME: We should consider adding DidLayout as a LayoutMilestone. That would let us merge this
2860 // with didLayout(LayoutMilestones).
2861 frame().loader().client().dispatchDidLayout();
2863 updateWidgetPositions();
2865 // layout() protects FrameView, but it still can get destroyed when updateEmbeddedObjects()
2866 // is called through the post layout timer.
2867 Ref<FrameView> protect(*this);
2869 for (unsigned i = 0; i < maxUpdateEmbeddedObjectsIterations; i++) {
2870 if (updateEmbeddedObjects())
2875 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2876 scrollingCoordinator->frameViewLayoutUpdated(this);
2879 #if USE(ACCELERATED_COMPOSITING)
2880 if (RenderView* renderView = this->renderView()) {
2881 if (renderView->usesCompositing())
2882 renderView->compositor().frameViewDidLayout();
2888 sendResizeEventIfNeeded();
2891 void FrameView::sendResizeEventIfNeeded()
2893 RenderView* renderView = this->renderView();
2894 if (!renderView || renderView->printing())
2896 if (frame().page() && frame().page()->chrome().client().isSVGImageChromeClient())
2899 IntSize currentSize;
2900 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
2901 currentSize = fixedLayoutSize();
2904 currentSize = actualVisibleContentRect().size();
2906 currentSize = visibleContentRect(IncludeScrollbars).size();
2909 float currentZoomFactor = renderView->style().zoom();
2910 bool shouldSendResizeEvent = !m_firstLayout && (currentSize != m_lastViewportSize || currentZoomFactor != m_lastZoomFactor);
2912 m_lastViewportSize = currentSize;
2913 m_lastZoomFactor = currentZoomFactor;
2915 if (!shouldSendResizeEvent)
2919 // Don't send the resize event if the document is loading. Some pages automatically reload
2920 // when the window is resized; Safari on iOS often resizes the window while setting up its
2921 // viewport. This obviously can cause problems.
2922 if (DocumentLoader* documentLoader = frame().loader().documentLoader()) {
2923 if (documentLoader->isLoadingInAPISense())
2928 bool isMainFrame = frame().isMainFrame();
2929 bool canSendResizeEventSynchronously = isMainFrame && !isInLayout();
2931 // If we resized during layout, queue up a resize event for later, otherwise fire it right away.
2932 RefPtr<Event> resizeEvent = Event::create(eventNames().resizeEvent, false, false);
2933 if (canSendResizeEventSynchronously)
2934 frame().document()->dispatchWindowEvent(resizeEvent.release(), frame().document()->domWindow());
2936 frame().document()->enqueueWindowEvent(resizeEvent.release());
2938 #if ENABLE(INSPECTOR)
2939 Page* page = frame().page();
2940 if (InspectorInstrumentation::hasFrontends() && isMainFrame) {
2941 if (InspectorClient* inspectorClient = page ? page->inspectorController()->inspectorClient() : 0)
2942 inspectorClient->didResizeMainFrame(&frame());
2947 void FrameView::willStartLiveResize()
2949 ScrollView::willStartLiveResize();
2950 adjustTiledBackingCoverage();
2953 void FrameView::willEndLiveResize()
2955 ScrollView::willEndLiveResize();
2956 adjustTiledBackingCoverage();
2959 void FrameView::postLayoutTimerFired(Timer<FrameView>&)
2961 performPostLayoutTasks();
2964 void FrameView::autoSizeIfEnabled()
2966 if (!m_shouldAutoSize)
2972 TemporaryChange<bool> changeInAutoSize(m_inAutoSize, true);
2974 Document* document = frame().document();
2978 RenderView* documentView = document->renderView();
2979 Element* documentElement = document->documentElement();
2980 if (!documentView || !documentElement)
2983 // Start from the minimum size and allow it to grow.
2984 resize(m_minAutoSize.width(), m_minAutoSize.height());
2986 IntSize size = frameRect().size();
2988 // Do the resizing twice. The first time is basically a rough calculation using the preferred width
2989 // which may result in a height change during the second iteration.
2990 for (int i = 0; i < 2; i++) {
2991 // Update various sizes including contentsSize, scrollHeight, etc.
2992 document->updateLayoutIgnorePendingStylesheets();
2993 int width = documentView->minPreferredLogicalWidth();
2994 int height = documentView->documentRect().height();
2995 IntSize newSize(width, height);
2997 // Check to see if a scrollbar is needed for a given dimension and
2998 // if so, increase the other dimension to account for the scrollbar.
2999 // Since the dimensions are only for the view rectangle, once a
3000 // dimension exceeds the maximum, there is no need to increase it further.
3001 if (newSize.width() > m_maxAutoSize.width()) {
3002 RefPtr<Scrollbar> localHorizontalScrollbar = horizontalScrollbar();
3003 if (!localHorizontalScrollbar)
3004 localHorizontalScrollbar = createScrollbar(HorizontalScrollbar);
3005 if (!localHorizontalScrollbar->isOverlayScrollbar())
3006 newSize.setHeight(newSize.height() + localHorizontalScrollbar->height());
3008 // Don't bother checking for a vertical scrollbar because the width is at
3009 // already greater the maximum.
3010 } else if (newSize.height() > m_maxAutoSize.height()) {
3011 RefPtr<Scrollbar> localVerticalScrollbar = verticalScrollbar();
3012 if (!localVerticalScrollbar)
3013 localVerticalScrollbar = createScrollbar(VerticalScrollbar);
3014 if (!localVerticalScrollbar->isOverlayScrollbar())
3015 newSize.setWidth(newSize.width() + localVerticalScrollbar->width());
3017 // Don't bother checking for a horizontal scrollbar because the height is
3018 // already greater the maximum.
3021 // Ensure the size is at least the min bounds.
3022 newSize = newSize.expandedTo(m_minAutoSize);
3024 // Bound the dimensions by the max bounds and determine what scrollbars to show.
3025 ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff;
3026 if (newSize.width() > m_maxAutoSize.width()) {
3027 newSize.setWidth(m_maxAutoSize.width());
3028 horizonalScrollbarMode = ScrollbarAlwaysOn;
3030 ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff;
3031 if (newSize.height() > m_maxAutoSize.height()) {
3032 newSize.setHeight(m_maxAutoSize.height());
3033 verticalScrollbarMode = ScrollbarAlwaysOn;
3036 if (newSize == size)
3039 // While loading only allow the size to increase (to avoid twitching during intermediate smaller states)
3040 // unless autoresize has just been turned on or the maximum size is smaller than the current size.
3041 if (m_didRunAutosize && size.height() <= m_maxAutoSize.height() && size.width() <= m_maxAutoSize.width()
3042 && !frame().loader().isComplete() && (newSize.height() < size.height() || newSize.width() < size.width()))
3045 resize(newSize.width(), newSize.height());
3046 // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example,
3047 // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed).
3048 setVerticalScrollbarLock(false);
3049 setHorizontalScrollbarLock(false);
3050 setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true);
3053 m_autoSizeContentSize = contentsSize();
3055 if (m_autoSizeFixedMinimumHeight) {
3056 resize(m_autoSizeContentSize.width(), std::max(m_autoSizeFixedMinimumHeight, m_autoSizeContentSize.height()));
3057 document->updateLayoutIgnorePendingStylesheets();
3060 m_didRunAutosize = true;
3063 void FrameView::setAutoSizeFixedMinimumHeight(int fixedMinimumHeight)
3065 if (m_autoSizeFixedMinimumHeight == fixedMinimumHeight)
3068 m_autoSizeFixedMinimumHeight = fixedMinimumHeight;
3073 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
3075 if (!m_viewportRenderer)
3078 if (m_overflowStatusDirty) {
3079 m_horizontalOverflow = horizontalOverflow;
3080 m_verticalOverflow = verticalOverflow;
3081 m_overflowStatusDirty = false;
3085 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
3086 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
3088 if (horizontalOverflowChanged || verticalOverflowChanged) {
3089 m_horizontalOverflow = horizontalOverflow;
3090 m_verticalOverflow = verticalOverflow;
3092 RefPtr<OverflowEvent> overflowEvent = OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
3093 verticalOverflowChanged, verticalOverflow);
3094 overflowEvent->setTarget(m_viewportRenderer->element());
3096 frame().document()->enqueueOverflowEvent(overflowEvent.release());
3101 const Pagination& FrameView::pagination() const
3103 if (m_pagination != Pagination())
3104 return m_pagination;
3106 if (frame().isMainFrame())
3107 return frame().page()->pagination();
3109 return m_pagination;
3112 void FrameView::setPagination(const Pagination& pagination)
3114 if (m_pagination == pagination)
3117 m_pagination = pagination;
3119 frame().document()->styleResolverChanged(DeferRecalcStyle);
3122 IntRect FrameView::windowClipRect(bool clipToContents) const
3124 ASSERT(frame().view() == this);
3126 if (paintsEntireContents())
3127 return IntRect(IntPoint(), totalContentsSize());
3129 // Set our clip rect to be our contents.
3130 IntRect clipRect = contentsToWindow(visibleContentRect(clipToContents ? ExcludeScrollbars : IncludeScrollbars));
3131 if (!frame().ownerElement())
3134 // Take our owner element and get its clip rect.
3135 HTMLFrameOwnerElement* ownerElement = frame().ownerElement();
3136 if (FrameView* parentView = ownerElement->document().view())
3137 clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement, true));
3141 IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement, bool clipToLayerContents) const
3143 // The renderer can sometimes be null when style="display:none" interacts
3144 // with external content and plugins.
3145 if (!ownerElement->renderer())
3146 return windowClipRect();
3148 // If we have no layer, just return our window clip rect.
3149 const RenderLayer* enclosingLayer = ownerElement->renderer()->enclosingLayer();
3150 if (!enclosingLayer)
3151 return windowClipRect();
3153 // Apply the clip from the layer.
3155 if (clipToLayerContents)
3156 clipRect = pixelSnappedIntRect(enclosingLayer->childrenClipRect());
3158 clipRect = pixelSnappedIntRect(enclosingLayer->selfClipRect());
3159 clipRect = contentsToWindow(clipRect);
3160 return intersection(clipRect, windowClipRect());
3163 bool FrameView::isActive() const
3165 Page* page = frame().page();
3166 return page && page->focusController().isActive();
3169 bool FrameView::updatesScrollLayerPositionOnMainThread() const
3171 if (Page* page = frame().page()) {
3172 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
3173 return scrollingCoordinator->shouldUpdateScrollLayerPositionSynchronously();
3179 void FrameView::scrollTo(const IntSize& newOffset)
3181 LayoutSize offset = scrollOffset();
3182 ScrollView::scrollTo(newOffset);
3183 if (offset != scrollOffset())
3184 scrollPositionChanged();
3185 frame().loader().client().didChangeScrollOffset();
3188 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
3190 // Add in our offset within the FrameView.
3191 IntRect dirtyRect = rect;
3192 dirtyRect.moveBy(scrollbar->location());
3193 invalidateRect(dirtyRect);
3196 IntRect FrameView::windowResizerRect() const
3198 if (Page* page = frame().page())
3199 return page->chrome().windowResizerRect();
3203 float FrameView::visibleContentScaleFactor() const
3205 if (!frame().isMainFrame() || !frame().settings().delegatesPageScaling())
3208 return frame().page()->pageScaleFactor();
3211 void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
3213 if (!frame().isMainFrame())
3216 frame().page()->chrome().client().notifyScrollerThumbIsVisibleInRect(scrollerThumb);
3219 ScrollableArea* FrameView::enclosingScrollableArea() const
3221 // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer.
3225 IntRect FrameView::scrollableAreaBoundingBox() const
3227 RenderWidget* ownerRenderer = frame().ownerRenderer();
3231 return ownerRenderer->absoluteContentQuad().enclosingBoundingBox();
3234 bool FrameView::isScrollable()
3237 // 1) If there an actual overflow.
3238 // 2) display:none or visibility:hidden set to self or inherited.
3239 // 3) overflow{-x,-y}: hidden;
3240 // 4) scrolling: no;
3243 IntSize totalContentsSize = this->totalContentsSize();
3244 IntSize visibleContentSize = visibleContentRect().size();
3245 if ((totalContentsSize.height() <= visibleContentSize.height() && totalContentsSize.width() <= visibleContentSize.width()))
3249 HTMLFrameOwnerElement* owner = frame().ownerElement();
3250 if (owner && (!owner->renderer() || !owner->renderer()->visibleToHitTesting()))
3254 ScrollbarMode horizontalMode;
3255 ScrollbarMode verticalMode;
3256 calculateScrollbarModesForLayout(horizontalMode, verticalMode, RulesFromWebContentOnly);
3257 if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff)
3263 void FrameView::updateScrollableAreaSet()
3265 // That ensures that only inner frames are cached.
3266 FrameView* parentFrameView = this->parentFrameView();
3267 if (!parentFrameView)
3270 if (!isScrollable()) {
3271 parentFrameView->removeScrollableArea(this);
3275 parentFrameView->addScrollableArea(this);
3278 bool FrameView::shouldSuspendScrollAnimations() const
3280 return frame().loader().state() != FrameStateComplete;
3283 void FrameView::scrollbarStyleChanged(int newStyle, bool forceUpdate)
3285 if (!frame().isMainFrame())
3288 frame().page()->chrome().client().recommendedScrollbarStyleDidChange(newStyle);
3291 ScrollView::scrollbarStyleChanged(newStyle, forceUpdate);
3294 void FrameView::notifyPageThatContentAreaWillPaint() const
3296 Page* page = frame().page();
3300 contentAreaWillPaint();
3302 if (!m_scrollableAreas)
3305 for (auto& scrollableArea : *m_scrollableAreas)
3306 scrollableArea->contentAreaWillPaint();
3309 bool FrameView::scrollAnimatorEnabled() const
3311 #if ENABLE(SMOOTH_SCROLLING)
3312 if (Page* page = frame().page())
3313 return page->settings().scrollAnimatorEnabled();
3319 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
3320 void FrameView::updateAnnotatedRegions()
3322 Document* document = frame().document();
3323 if (!document->hasAnnotatedRegions())
3325 Vector<AnnotatedRegionValue> newRegions;
3326 document->renderBox()->collectAnnotatedRegions(newRegions);
3327 if (newRegions == document->annotatedRegions())
3329 document->setAnnotatedRegions(newRegions);
3330 Page* page = frame().page();
3333 page->chrome().client().annotatedRegionsChanged();
3337 void FrameView::updateScrollCorner()
3339 RenderElement* renderer = 0;
3340 RefPtr<RenderStyle> cornerStyle;
3341 IntRect cornerRect = scrollCornerRect();
3343 if (!cornerRect.isEmpty()) {
3344 // Try the <body> element first as a scroll corner source.
3345 Document* doc = frame().document();
3346 Element* body = doc ? doc->body() : 0;
3347 if (body && body->renderer()) {
3348 renderer = body->renderer();
3349 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), &renderer->style());
3353 // If the <body> didn't have a custom style, then the root element might.
3354 Element* docElement = doc ? doc->documentElement() : 0;
3355 if (docElement && docElement->renderer()) {
3356 renderer = docElement->renderer();
3357 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), &renderer->style());
3362 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
3363 if (RenderWidget* renderer = frame().ownerRenderer())
3364 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), &renderer->style());
3369 m_scrollCorner = nullptr;
3371 if (!m_scrollCorner) {
3372 m_scrollCorner = createRenderer<RenderScrollbarPart>(renderer->document(), cornerStyle.releaseNonNull());
3373 m_scrollCorner->initializeStyle();
3375 m_scrollCorner->setStyle(cornerStyle.releaseNonNull());
3376 invalidateScrollCorner(cornerRect);
3379 ScrollView::updateScrollCorner();
3382 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
3384 if (context->updatingControlTints()) {
3385 updateScrollCorner();
3389 if (m_scrollCorner) {
3390 if (frame().isMainFrame())
3391 context->fillRect(cornerRect, baseBackgroundColor(), ColorSpaceDeviceRGB);
3392 m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect);
3396 ScrollView::paintScrollCorner(context, cornerRect);
3399 void FrameView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
3401 if (bar->isCustomScrollbar() && frame().isMainFrame()) {
3402 IntRect toFill = bar->frameRect();
3403 toFill.intersect(rect);
3404 context->fillRect(toFill, baseBackgroundColor(), ColorSpaceDeviceRGB);
3407 ScrollView::paintScrollbar(context, bar, rect);
3410 Color FrameView::documentBackgroundColor() const
3412 // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of
3413 // the document and the body against the base background color of the frame view.
3414 // Background images are unfortunately impractical to include.
3416 // Return invalid Color objects whenever there is insufficient information.
3417 if (!frame().document())
3420 Element* htmlElement = frame().document()->documentElement();
3421 Element* bodyElement = frame().document()->body();
3423 // Start with invalid colors.
3424 Color htmlBackgroundColor;
3425 Color bodyBackgroundColor;
3426 if (htmlElement && htmlElement->renderer())
3427 htmlBackgroundColor = htmlElement->renderer()->style().visitedDependentColor(CSSPropertyBackgroundColor);
3428 if (bodyElement && bodyElement->renderer())
3429 bodyBackgroundColor = bodyElement->renderer()->style().visitedDependentColor(CSSPropertyBackgroundColor);
3431 if (!bodyBackgroundColor.isValid()) {
3432 if (!htmlBackgroundColor.isValid())
3434 return baseBackgroundColor().blend(htmlBackgroundColor);
3437 if (!htmlBackgroundColor.isValid())
3438 return baseBackgroundColor().blend(bodyBackgroundColor);
3440 // We take the aggregate of the base background color
3441 // the <html> background color, and the <body>
3442 // background color to find the document color. The
3443 // addition of the base background color is not
3444 // technically part of the document background, but it
3445 // otherwise poses problems when the aggregate is not
3447 return baseBackgroundColor().blend(htmlBackgroundColor).blend(bodyBackgroundColor);
3450 bool FrameView::hasCustomScrollbars() const
3452 for (auto& widget : children()) {
3453 if (widget->isFrameView()) {
3454 if (toFrameView(*widget).hasCustomScrollbars())
3456 } else if (widget->isScrollbar()) {
3457 if (toScrollbar(*widget).isCustomScrollbar())
3465 FrameView* FrameView::parentFrameView() const
3470 if (Frame* parentFrame = frame().tree().parent())
3471 return parentFrame->view();
3476 bool FrameView::isInChildFrameWithFrameFlattening() const
3478 if (!parent() || !frame().ownerElement())
3481 // Frame flattening applies when the owner element is either in a frameset or
3482 // an iframe with flattening parameters.
3483 if (frame().ownerElement()->hasTagName(iframeTag)) {
3484 RenderIFrame* iframeRenderer = toRenderIFrame(frame().ownerElement()->renderWidget());
3485 if (iframeRenderer->flattenFrame() || iframeRenderer->isSeamless())
3489 if (!frameFlatteningEnabled())
3492 if (frame().ownerElement()->hasTagName(frameTag))
3498 void FrameView::startLayoutAtMainFrameViewIfNeeded(bool allowSubtree)
3500 // When we start a layout at the child level as opposed to the topmost frame view and this child
3501 // frame requires flattening, we need to re-initiate the layout at the topmost view. Layout
3502 // will hit this view eventually.
3503 FrameView* parentView = parentFrameView();
3507 // In the middle of parent layout, no need to restart from topmost.
3508 if (parentView->m_nestedLayoutCount)
3511 // Parent tree is clean. Starting layout from it would have no effect.
3512 if (!parentView->needsLayout())
3515 while (parentView->parentFrameView())
3516 parentView = parentView->parentFrameView();
3518 parentView->layout(allowSubtree);
3520 RenderElement* root = m_layoutRoot ? m_layoutRoot : frame().document()->renderView();
3521 ASSERT_UNUSED(root, !root->needsLayout());
3524 void FrameView::updateControlTints()
3526 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
3527 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
3528 // This is only done if the theme supports control tinting. It's up to the theme and platform
3529 // to define when controls get the tint and to call this function when that changes.
3531 // Optimize the common case where we bring a window to the front while it's still empty.
3532 if (frame().document()->url().isEmpty())
3535 RenderView* renderView = this->renderView();
3536 if ((renderView && renderView->theme().supportsControlTints()) || hasCustomScrollbars())
3537 paintControlTints();
3540 void FrameView::paintControlTints()
3544 PlatformGraphicsContext* const noContext = 0;
3545 GraphicsContext context(noContext);
3546 context.setUpdatingControlTints(true);
3547 if (platformWidget())
3548 paintContents(&context, visibleContentRect());
3550 paint(&context, frameRect());
3553 bool FrameView::wasScrolledByUser() const
3555 return m_wasScrolledByUser;
3558 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
3560 if (m_inProgrammaticScroll)
3562 m_maintainScrollPositionAnchor = 0;
3563 if (m_wasScrolledByUser == wasScrolledByUser)
3565 m_wasScrolledByUser = wasScrolledByUser;
3566 adjustTiledBackingCoverage();
3569 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
3571 Document* document = frame().document();
3575 if (document->printing())
3576 fillWithRed = false; // Printing, don't fill with red (can't remember why).
3577 else if (frame().ownerElement())
3578 fillWithRed = false; // Subframe, don't fill with red.
3579 else if (isTransparent())
3580 fillWithRed = false; // Transparent, don't fill with red.
3581 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
3582 fillWithRed = false; // Selections are transparent, don't fill with red.
3583 else if (m_nodeToDraw)
3584 fillWithRed = false; // Element images are transparent, don't fill with red.
3589 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
3592 RenderView* renderView = this->renderView();
3594 LOG_ERROR("called FrameView::paint with nil renderer");
3598 ASSERT(!needsLayout());
3602 if (!p->paintingDisabled())
3603 InspectorInstrumentation::willPaint(renderView);
3605 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
3607 // FIXME: Remove PLATFORM(IOS)-guard once we upstream the iOS changes to MemoryPressureHandler.h.
3608 if (isTopLevelPainter && memoryPressureHandler().hasReceivedMemoryPressure()) {
3609 LOG(MemoryPressure, "Under memory pressure: %s", __PRETTY_FUNCTION__);
3611 // To avoid unnecessary image decoding, we don't prune recently-decoded live resources here since
3612 // we might need some live bitmaps on painting.
3613 memoryCache()->prune();
3616 if (isTopLevelPainter)
3617 sCurrentPaintTimeStamp = monotonicallyIncreasingTime();
3619 FontCachePurgePreventer fontCachePurgePreventer;
3621 #if USE(ACCELERATED_COMPOSITING)
3622 if (!p->paintingDisabled() && !document->printing())
3623 flushCompositingStateForThisFrame(&frame());
3626 PaintBehavior oldPaintBehavior = m_paintBehavior;
3628 if (FrameView* parentView = parentFrameView()) {
3629 if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)