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)
207 , m_speculativeTilingEnabled(false)
208 , m_speculativeTilingEnableTimer(this, &FrameView::speculativeTilingEnableTimerFired)
210 , m_useCustomFixedPositionLayoutRect(false)
212 , m_shouldAutoSize(false)
213 , m_inAutoSize(false)
214 , m_didRunAutosize(false)
215 , m_autoSizeFixedMinimumHeight(0)
218 , m_milestonesPendingPaint(0)
219 , m_visualUpdatesAllowedByClient(true)
220 , m_scrollPinningBehavior(DoNotPin)
224 if (frame.isMainFrame()) {
225 ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed);
226 ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAutomatic);
230 PassRefPtr<FrameView> FrameView::create(Frame& frame)
232 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
234 return view.release();
237 PassRefPtr<FrameView> FrameView::create(Frame& frame, const IntSize& initialSize)
239 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
240 view->Widget::setFrameRect(IntRect(view->location(), initialSize));
242 return view.release();
245 FrameView::~FrameView()
247 if (m_postLayoutTasksTimer.isActive())
248 m_postLayoutTasksTimer.stop();
250 removeFromAXObjectCache();
253 // Custom scrollbars should already be destroyed at this point
254 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
255 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
257 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
258 setHasVerticalScrollbar(false);
260 ASSERT(!m_scrollCorner);
262 ASSERT(frame().view() != this || !frame().contentRenderer());
265 void FrameView::reset()
267 m_cannotBlitToWindow = false;
268 m_isOverlapped = false;
269 m_contentIsOpaque = false;
272 m_layoutTimer.stop();
274 m_delayedLayout = false;
275 m_needsFullRepaint = true;
276 m_layoutSchedulingEnabled = true;
277 m_layoutPhase = OutsideLayout;
278 m_inSynchronousPostLayout = false;
280 m_nestedLayoutCount = 0;
281 m_postLayoutTasksTimer.stop();
282 m_firstLayout = true;
283 m_firstLayoutCallbackPending = false;
284 m_wasScrolledByUser = false;
285 m_safeToPropagateScrollToParent = true;
286 m_lastViewportSize = IntSize();
287 m_lastZoomFactor = 1.0f;
288 m_deferringRepaints = 0;
290 m_repaintRects.clear();
291 m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading;
292 m_deferredRepaintTimer.stop();
293 m_isTrackingRepaints = false;
294 m_trackedRepaintRects.clear();
296 m_paintBehavior = PaintBehaviorNormal;
297 m_isPainting = false;
298 m_visuallyNonEmptyCharacterCount = 0;
299 m_visuallyNonEmptyPixelCount = 0;
300 m_isVisuallyNonEmpty = false;
301 m_firstVisuallyNonEmptyLayoutCallbackPending = true;
302 m_maintainScrollPositionAnchor = 0;
305 void FrameView::removeFromAXObjectCache()
307 if (AXObjectCache* cache = axObjectCache())
311 void FrameView::resetScrollbars()
313 // Reset the document's scrollbars back to our defaults before we yield the floor.
314 m_firstLayout = true;
315 setScrollbarsSuppressed(true);
316 if (m_canHaveScrollbars)
317 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
319 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
320 setScrollbarsSuppressed(false);
323 void FrameView::resetScrollbarsAndClearContentsSize()
327 setScrollbarsSuppressed(true);
328 setContentsSize(IntSize());
329 setScrollbarsSuppressed(false);
332 void FrameView::init()
336 m_margins = LayoutSize(-1, -1); // undefined
337 m_size = LayoutSize();
339 // Propagate the marginwidth/height and scrolling modes to the view.
340 Element* ownerElement = frame().ownerElement();
341 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
342 HTMLFrameElementBase* frameElt = toHTMLFrameElementBase(ownerElement);
343 if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
344 setCanHaveScrollbars(false);
345 LayoutUnit marginWidth = frameElt->marginWidth();
346 LayoutUnit marginHeight = frameElt->marginHeight();
347 if (marginWidth != -1)
348 setMarginWidth(marginWidth);
349 if (marginHeight != -1)
350 setMarginHeight(marginHeight);
353 Page* page = frame().page();
354 if (page && page->chrome().client().shouldPaintEntireContents())
355 setPaintsEntireContents(true);
358 void FrameView::prepareForDetach()
360 detachCustomScrollbars();
361 // When the view is no longer associated with a frame, it needs to be removed from the ax object cache
362 // right now, otherwise it won't be able to reach the topDocument()'s axObject cache later.
363 removeFromAXObjectCache();
365 if (frame().page()) {
366 if (ScrollingCoordinator* scrollingCoordinator = frame().page()->scrollingCoordinator())
367 scrollingCoordinator->willDestroyScrollableArea(this);
371 void FrameView::detachCustomScrollbars()
373 Scrollbar* horizontalBar = horizontalScrollbar();
374 if (horizontalBar && horizontalBar->isCustomScrollbar())
375 setHasHorizontalScrollbar(false);
377 Scrollbar* verticalBar = verticalScrollbar();
378 if (verticalBar && verticalBar->isCustomScrollbar())
379 setHasVerticalScrollbar(false);
381 m_scrollCorner = nullptr;
384 void FrameView::recalculateScrollbarOverlayStyle()
386 ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle();
387 ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault;
389 Color backgroundColor = documentBackgroundColor();
390 if (backgroundColor.isValid()) {
391 // Reduce the background color from RGB to a lightness value
392 // and determine which scrollbar style to use based on a lightness
394 double hue, saturation, lightness;
395 backgroundColor.getHSL(hue, saturation, lightness);
396 if (lightness <= .5 && backgroundColor.alpha() > 0)
397 overlayStyle = ScrollbarOverlayStyleLight;
400 if (oldOverlayStyle != overlayStyle)
401 setScrollbarOverlayStyle(overlayStyle);
404 void FrameView::clear()
406 setCanBlitOnScroll(true);
410 setScrollbarsSuppressed(true);
413 // To avoid flashes of white, disable tile updates immediately when view is cleared at the beginning of a page load.
414 // Tiling will be re-enabled from UIKit via [WAKWindow setTilingMode:] when we have content to draw.
415 if (TileCache* tileCache = this->tileCache())
416 tileCache->setTilingMode(TileCache::Disabled);
420 bool FrameView::didFirstLayout() const
422 return !m_firstLayout;
425 void FrameView::invalidateRect(const IntRect& rect)
428 if (HostWindow* window = hostWindow())
429 window->invalidateContentsAndRootView(rect, false /*immediate*/);
433 RenderWidget* renderer = frame().ownerRenderer();
437 IntRect repaintRect = rect;
438 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
439 renderer->borderTop() + renderer->paddingTop());
440 renderer->repaintRectangle(repaintRect);
443 void FrameView::setFrameRect(const IntRect& newRect)
445 IntRect oldRect = frameRect();
446 if (newRect == oldRect)
449 #if ENABLE(TEXT_AUTOSIZING)
450 // Autosized font sizes depend on the width of the viewing area.
451 if (newRect.width() != oldRect.width()) {
452 Page* page = frame().page();
453 if (frame().isMainFrame() && page->settings().textAutosizingEnabled()) {
454 for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext())
455 frame().document()->textAutosizer()->recalculateMultipliers();
460 ScrollView::setFrameRect(newRect);
462 updateScrollableAreaSet();
464 #if USE(ACCELERATED_COMPOSITING)
465 if (RenderView* renderView = this->renderView()) {
466 if (renderView->usesCompositing())
467 renderView->compositor().frameViewDidChangeSize();
471 if (!frameFlatteningEnabled())
472 sendResizeEventIfNeeded();
475 #if ENABLE(REQUEST_ANIMATION_FRAME)
476 bool FrameView::scheduleAnimation()
478 if (HostWindow* window = hostWindow()) {
479 window->scheduleAnimation();
486 void FrameView::setMarginWidth(LayoutUnit w)
488 // make it update the rendering area when set
489 m_margins.setWidth(w);
492 void FrameView::setMarginHeight(LayoutUnit h)
494 // make it update the rendering area when set
495 m_margins.setHeight(h);
498 bool FrameView::frameFlatteningEnabled() const
500 return frame().settings().frameFlatteningEnabled();
503 bool FrameView::isFrameFlatteningValidForThisFrame() const
505 if (!frameFlatteningEnabled())
508 HTMLFrameOwnerElement* owner = frame().ownerElement();
512 // Frame flattening is valid only for <frame> and <iframe>.
513 return owner->hasTagName(frameTag) || owner->hasTagName(iframeTag);
516 bool FrameView::avoidScrollbarCreation() const
518 // with frame flattening no subframe can have scrollbars
519 // but we also cannot turn scrollbars off as we determine
520 // our flattening policy using that.
521 return isFrameFlatteningValidForThisFrame();
524 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
526 m_canHaveScrollbars = canHaveScrollbars;
527 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
530 void FrameView::updateCanHaveScrollbars()
534 scrollbarModes(hMode, vMode);
535 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
536 setCanHaveScrollbars(false);
538 setCanHaveScrollbars(true);
541 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
543 if (!frame().settings().allowCustomScrollbarInMainFrame() && frame().isMainFrame())
544 return ScrollView::createScrollbar(orientation);
546 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
547 Document* doc = frame().document();
549 // Try the <body> element first as a scrollbar source.
550 Element* body = doc ? doc->body() : 0;
551 if (body && body->renderer() && body->renderer()->style().hasPseudoStyle(SCROLLBAR))
552 return RenderScrollbar::createCustomScrollbar(this, orientation, body);
554 // If the <body> didn't have a custom style, then the root element might.
555 Element* docElement = doc ? doc->documentElement() : 0;
556 if (docElement && docElement->renderer() && docElement->renderer()->style().hasPseudoStyle(SCROLLBAR))
557 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement);
559 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
560 RenderWidget* frameRenderer = frame().ownerRenderer();
561 if (frameRenderer && frameRenderer->style().hasPseudoStyle(SCROLLBAR))
562 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, &frame());
564 // Nobody set a custom style, so we just use a native scrollbar.
565 return ScrollView::createScrollbar(orientation);
568 void FrameView::setContentsSize(const IntSize& size)
570 if (size == contentsSize())
573 m_deferSetNeedsLayouts++;
575 ScrollView::setContentsSize(size);
576 ScrollView::contentsResized();
578 Page* page = frame().page();
582 updateScrollableAreaSet();
584 page->chrome().contentsSizeChanged(&frame(), size); // Notify only.
586 ASSERT(m_deferSetNeedsLayouts);
587 m_deferSetNeedsLayouts--;
589 if (!m_deferSetNeedsLayouts)
590 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
593 void FrameView::adjustViewSize()
595 RenderView* renderView = this->renderView();
599 ASSERT(frame().view() == this);
601 const IntRect rect = renderView->documentRect();
602 const IntSize& size = rect.size();
603 ScrollView::setScrollOrigin(IntPoint(-rect.x(), -rect.y()), !frame().document()->printing(), size == contentsSize());
605 setContentsSize(size);
608 void FrameView::applyOverflowToViewport(RenderElement* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
610 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
611 // overflow:hidden and overflow:scroll on <body> as applying to the document's
612 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
613 // use the root element.
615 // To combat the inability to scroll on a page with overflow:hidden on the root when scaled, disregard hidden when
616 // there is a frameScaleFactor that is greater than one on the main frame. Also disregard hidden if there is a
619 bool overrideHidden = frame().isMainFrame() && ((frame().frameScaleFactor() > 1) || headerHeight() || footerHeight());
621 EOverflow overflowX = o->style().overflowX();
622 EOverflow overflowY = o->style().overflowY();
625 if (o->isSVGRoot()) {
626 // overflow is ignored in stand-alone SVG documents.
627 if (!toRenderSVGRoot(o)->isEmbeddedThroughFrameContainingSVGDocument())
637 hMode = ScrollbarAuto;
639 hMode = ScrollbarAlwaysOff;
642 hMode = ScrollbarAlwaysOn;
645 hMode = ScrollbarAuto;
648 // Don't set it at all.
655 vMode = ScrollbarAuto;
657 vMode = ScrollbarAlwaysOff;
660 vMode = ScrollbarAlwaysOn;
663 vMode = ScrollbarAuto;
666 // Don't set it at all. Values of OPAGEDX and OPAGEDY are handled by applyPaginationToViewPort().
670 m_viewportRenderer = o;
673 void FrameView::applyPaginationToViewport()
675 Document* document = frame().document();
676 auto documentElement = document->documentElement();
677 RenderElement* documentRenderer = documentElement ? documentElement->renderer() : nullptr;
678 RenderElement* documentOrBodyRenderer = documentRenderer;
679 auto body = document->body();
680 if (body && body->renderer()) {
681 if (body->hasTagName(bodyTag))
682 documentOrBodyRenderer = documentRenderer->style().overflowX() == OVISIBLE && documentElement->hasTagName(htmlTag) ? body->renderer() : documentRenderer;
685 Pagination pagination;
687 if (!documentOrBodyRenderer) {
688 setPagination(pagination);
692 EOverflow overflowY = documentOrBodyRenderer->style().overflowY();
693 if (overflowY == OPAGEDX || overflowY == OPAGEDY) {
694 pagination.mode = WebCore::paginationModeForRenderStyle(documentOrBodyRenderer->style());
695 pagination.gap = static_cast<unsigned>(documentOrBodyRenderer->style().columnGap());
698 setPagination(pagination);
701 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy)
703 m_viewportRenderer = 0;
705 const HTMLFrameOwnerElement* owner = frame().ownerElement();
706 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
707 hMode = ScrollbarAlwaysOff;
708 vMode = ScrollbarAlwaysOff;
712 if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) {
713 hMode = ScrollbarAuto;
714 // Seamless documents begin with heights of 0; we special case that here
715 // to correctly render documents that don't need scrollbars.
716 IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size();
717 bool isSeamlessDocument = frame().document() && frame().document()->shouldDisplaySeamlesslyWithParent();
718 vMode = (isSeamlessDocument && !fullVisibleSize.height()) ? ScrollbarAlwaysOff : ScrollbarAuto;
720 hMode = ScrollbarAlwaysOff;
721 vMode = ScrollbarAlwaysOff;
725 Document* document = frame().document();
726 auto documentElement = document->documentElement();
727 RenderElement* rootRenderer = documentElement ? documentElement->renderer() : nullptr;
728 auto body = document->body();
729 if (body && body->renderer()) {
730 if (body->hasTagName(framesetTag) && !frameFlatteningEnabled()) {
731 vMode = ScrollbarAlwaysOff;
732 hMode = ScrollbarAlwaysOff;
733 } else if (body->hasTagName(bodyTag)) {
734 // It's sufficient to just check the X overflow,
735 // since it's illegal to have visible in only one direction.
736 RenderElement* o = rootRenderer->style().overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
737 applyOverflowToViewport(o, hMode, vMode);
739 } else if (rootRenderer)
740 applyOverflowToViewport(rootRenderer, hMode, vMode);
744 #if USE(ACCELERATED_COMPOSITING)
745 void FrameView::updateCompositingLayersAfterStyleChange()
747 RenderView* renderView = this->renderView();
751 // If we expect to update compositing after an incipient layout, don't do so here.
752 if (inPreLayoutStyleUpdate() || layoutPending() || renderView->needsLayout())
755 RenderLayerCompositor& compositor = renderView->compositor();
756 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
757 compositor.cacheAcceleratedCompositingFlags();
758 compositor.updateCompositingLayers(CompositingUpdateAfterStyleChange);
761 void FrameView::updateCompositingLayersAfterLayout()
763 RenderView* renderView = this->renderView();
767 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
768 renderView->compositor().cacheAcceleratedCompositingFlags();
769 renderView->compositor().updateCompositingLayers(CompositingUpdateAfterLayout);
772 void FrameView::clearBackingStores()
774 RenderView* renderView = this->renderView();
778 RenderLayerCompositor& compositor = renderView->compositor();
779 ASSERT(compositor.inCompositingMode());
780 compositor.enableCompositingMode(false);
781 compositor.clearBackingForAllLayers();
784 void FrameView::restoreBackingStores()
786 RenderView* renderView = this->renderView();
790 RenderLayerCompositor& compositor = renderView->compositor();
791 compositor.enableCompositingMode(true);
792 compositor.updateCompositingLayers(CompositingUpdateAfterLayout);
795 bool FrameView::usesCompositedScrolling() const
797 RenderView* renderView = this->renderView();
800 if (frame().settings().compositedScrollingForFramesEnabled())
801 return renderView->compositor().inForcedCompositingMode();
805 GraphicsLayer* FrameView::layerForScrolling() const
807 RenderView* renderView = this->renderView();
810 return renderView->compositor().scrollLayer();
813 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
815 RenderView* renderView = this->renderView();
818 return renderView->compositor().layerForHorizontalScrollbar();
821 GraphicsLayer* FrameView::layerForVerticalScrollbar() const
823 RenderView* renderView = this->renderView();
826 return renderView->compositor().layerForVerticalScrollbar();
829 GraphicsLayer* FrameView::layerForScrollCorner() const
831 RenderView* renderView = this->renderView();
834 return renderView->compositor().layerForScrollCorner();
837 TiledBacking* FrameView::tiledBacking() const
839 RenderView* renderView = this->renderView();
843 RenderLayerBacking* backing = renderView->layer()->backing();
847 return backing->graphicsLayer()->tiledBacking();
850 uint64_t FrameView::scrollLayerID() const
852 RenderView* renderView = this->renderView();
856 RenderLayerBacking* backing = renderView->layer()->backing();
860 return backing->scrollLayerID();
863 #if ENABLE(RUBBER_BANDING)
864 GraphicsLayer* FrameView::layerForOverhangAreas() const
866 RenderView* renderView = this->renderView();
869 return renderView->compositor().layerForOverhangAreas();
872 GraphicsLayer* FrameView::setWantsLayerForTopOverHangArea(bool wantsLayer) const
874 RenderView* renderView = this->renderView();
878 return renderView->compositor().updateLayerForTopOverhangArea(wantsLayer);
881 GraphicsLayer* FrameView::setWantsLayerForBottomOverHangArea(bool wantsLayer) const
883 RenderView* renderView = this->renderView();
887 return renderView->compositor().updateLayerForBottomOverhangArea(wantsLayer);
890 #endif // ENABLE(RUBBER_BANDING)
892 bool FrameView::flushCompositingStateForThisFrame(Frame* rootFrameForFlush)
894 RenderView* renderView = this->renderView();
896 return true; // We don't want to keep trying to update layers if we have no renderer.
898 ASSERT(frame().view() == this);
900 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
901 // layer content to occur before layout has happened, which will cause paintContents() to bail.
905 // If we sync compositing layers and allow the repaint to be deferred, there is time for a
906 // visible flash to occur. Instead, stop the deferred repaint timer and repaint immediately.
907 flushDeferredRepaints();
910 if (TileCache* tileCache = this->tileCache())
911 tileCache->doPendingRepaints();
914 renderView->compositor().flushPendingLayerChanges(rootFrameForFlush == &frame());
919 void FrameView::setNeedsOneShotDrawingSynchronization()
921 if (Page* page = frame().page())
922 page->chrome().client().setNeedsOneShotDrawingSynchronization();
925 GraphicsLayer* FrameView::graphicsLayerForPlatformWidget(PlatformWidget platformWidget)
927 // To find the Widget that corresponds with platformWidget we have to do a linear
928 // search of our child widgets.
929 Widget* foundWidget = nullptr;
930 for (auto& widget : children()) {
931 if (widget->platformWidget() != platformWidget)
933 foundWidget = widget.get();
940 auto* renderWidget = RenderWidget::find(foundWidget);
944 RenderLayer* widgetLayer = renderWidget->layer();
945 if (!widgetLayer || !widgetLayer->isComposited())
948 return widgetLayer->backing()->parentForSublayers();
951 void FrameView::scheduleLayerFlushAllowingThrottling()
953 RenderView* view = this->renderView();
956 view->compositor().scheduleLayerFlush(true /* canThrottle */);
958 #endif // USE(ACCELERATED_COMPOSITING)
960 void FrameView::setHeaderHeight(int headerHeight)
963 ASSERT(frame().isMainFrame());
964 m_headerHeight = headerHeight;
966 if (RenderView* renderView = this->renderView())
967 renderView->setNeedsLayout();
970 void FrameView::setFooterHeight(int footerHeight)
973 ASSERT(frame().isMainFrame());
974 m_footerHeight = footerHeight;
976 if (RenderView* renderView = this->renderView())
977 renderView->setNeedsLayout();
980 bool FrameView::hasCompositedContent() const
982 #if USE(ACCELERATED_COMPOSITING)
983 if (RenderView* renderView = this->renderView())
984 return renderView->compositor().inCompositingMode();
989 bool FrameView::hasCompositedContentIncludingDescendants() const
991 #if USE(ACCELERATED_COMPOSITING)
992 for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) {
993 RenderView* renderView = frame->contentRenderer();
994 if (RenderLayerCompositor* compositor = renderView ? &renderView->compositor() : 0) {
995 if (compositor->inCompositingMode())
998 if (!RenderLayerCompositor::allowsIndependentlyCompositedFrames(this))
1006 bool FrameView::hasCompositingAncestor() const
1008 #if USE(ACCELERATED_COMPOSITING)
1009 for (Frame* frame = this->frame().tree().parent(); frame; frame = frame->tree().parent()) {
1010 if (FrameView* view = frame->view()) {
1011 if (view->hasCompositedContent())
1019 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
1020 void FrameView::enterCompositingMode()
1022 #if USE(ACCELERATED_COMPOSITING)
1023 if (RenderView* renderView = this->renderView()) {
1024 renderView->compositor().enableCompositingMode();
1026 renderView->compositor().scheduleCompositingLayerUpdate();
1031 bool FrameView::isEnclosedInCompositingLayer() const
1033 #if USE(ACCELERATED_COMPOSITING)
1034 auto frameOwnerRenderer = frame().ownerRenderer();
1035 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
1038 if (FrameView* parentView = parentFrameView())
1039 return parentView->isEnclosedInCompositingLayer();
1044 bool FrameView::flushCompositingStateIncludingSubframes()
1046 #if USE(ACCELERATED_COMPOSITING)
1047 bool allFramesFlushed = flushCompositingStateForThisFrame(&frame());
1049 for (Frame* child = frame().tree().firstChild(); child; child = child->tree().traverseNext(&frame())) {
1050 bool flushed = child->view()->flushCompositingStateForThisFrame(&frame());
1051 allFramesFlushed &= flushed;
1053 return allFramesFlushed;
1054 #else // USE(ACCELERATED_COMPOSITING)
1059 bool FrameView::isSoftwareRenderable() const
1061 #if USE(ACCELERATED_COMPOSITING)
1062 RenderView* renderView = this->renderView();
1063 return !renderView || !renderView->compositor().has3DContent();
1069 void FrameView::didMoveOnscreen()
1071 contentAreaDidShow();
1074 void FrameView::willMoveOffscreen()
1076 contentAreaDidHide();
1079 void FrameView::setIsInWindow(bool isInWindow)
1081 if (RenderView* renderView = this->renderView())
1082 renderView->setIsInWindow(isInWindow);
1085 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
1087 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
1090 inline void FrameView::forceLayoutParentViewIfNeeded()
1093 RenderWidget* ownerRenderer = frame().ownerRenderer();
1097 RenderBox* contentBox = embeddedContentBox();
1101 RenderSVGRoot* svgRoot = toRenderSVGRoot(contentBox);
1102 if (svgRoot->everHadLayout() && !svgRoot->needsLayout())
1105 // If the embedded SVG document appears the first time, the ownerRenderer has already finished
1106 // layout without knowing about the existence of the embedded SVG document, because RenderReplaced
1107 // embeddedContentBox() returns 0, as long as the embedded document isn't loaded yet. Before
1108 // bothering to lay out the SVG document, mark the ownerRenderer needing layout and ask its
1109 // FrameView for a layout. After that the RenderEmbeddedObject (ownerRenderer) carries the
1110 // correct size, which RenderSVGRoot::computeReplacedLogicalWidth/Height rely on, when laying
1111 // out for the first time, or when the RenderSVGRoot size has changed dynamically (eg. via <script>).
1112 Ref<FrameView> frameView(ownerRenderer->view().frameView());
1114 // Mark the owner renderer as needing layout.
1115 ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc();
1117 // Synchronously enter layout, to layout the view containing the host object/embed/iframe.
1118 frameView->layout();
1122 void FrameView::layout(bool allowSubtree)
1127 // Many of the tasks performed during layout can cause this function to be re-entered,
1128 // so save the layout phase now and restore it on exit.
1129 TemporaryChange<LayoutPhase> layoutPhaseRestorer(m_layoutPhase, InPreLayout);
1131 // Protect the view from being deleted during layout (in recalcStyle)
1132 Ref<FrameView> protect(*this);
1134 // Every scroll that happens during layout is programmatic.
1135 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1137 bool inChildFrameLayoutWithFrameFlattening = isInChildFrameWithFrameFlattening();
1139 if (inChildFrameLayoutWithFrameFlattening) {
1140 startLayoutAtMainFrameViewIfNeeded(allowSubtree);
1141 RenderElement* root = m_layoutRoot ? m_layoutRoot : frame().document()->renderView();
1142 if (!root->needsLayout())
1147 if (updateFixedPositionLayoutRect())
1148 allowSubtree = false;
1151 m_layoutTimer.stop();
1152 m_delayedLayout = false;
1153 m_setNeedsLayoutWasDeferred = false;
1155 // we shouldn't enter layout() while painting
1156 ASSERT(!isPainting());
1160 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(&frame());
1162 if (!allowSubtree && m_layoutRoot) {
1163 m_layoutRoot->markContainingBlocksForLayout(false);
1167 ASSERT(frame().view() == this);
1168 ASSERT(frame().document());
1170 Document& document = *frame().document();
1171 ASSERT(!document.inPageCache());
1174 RenderElement* root;
1177 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1179 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_postLayoutTasksTimer.isActive() && !inChildFrameLayoutWithFrameFlattening) {
1180 // This is a new top-level layout. If there are any remaining tasks from the previous
1181 // layout, finish them now.
1182 TemporaryChange<bool> inSynchronousPostLayoutChange(m_inSynchronousPostLayout, true);
1183 performPostLayoutTasks();
1186 m_layoutPhase = InPreLayoutStyleUpdate;
1188 // Viewport-dependent media queries may cause us to need completely different style information.
1189 StyleResolver* styleResolver = document.styleResolverIfExists();
1190 if (!styleResolver || styleResolver->affectedByViewportChange()) {
1191 document.styleResolverChanged(DeferRecalcStyle);
1192 // FIXME: This instrumentation event is not strictly accurate since cached media query results do not persist across StyleResolver rebuilds.
1193 InspectorInstrumentation::mediaQueryResultChanged(&document);
1195 document.evaluateMediaQueryList();
1197 // If there is any pagination to apply, it will affect the RenderView's style, so we should
1198 // take care of that now.
1199 applyPaginationToViewport();
1201 // Always ensure our style info is up-to-date. This can happen in situations where
1202 // the layout beats any sort of style recalc update that needs to occur.
1203 document.updateStyleIfNeeded();
1204 m_layoutPhase = InPreLayout;
1206 subtree = m_layoutRoot;
1208 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
1209 // so there's no point to continuing to layout
1213 root = subtree ? m_layoutRoot : document.renderView();
1215 // FIXME: Do we need to set m_size here?
1219 // Close block here so we can set up the font cache purge preventer, which we will still
1220 // want in scope even after we want m_layoutSchedulingEnabled to be restored again.
1221 // The next block sets m_layoutSchedulingEnabled back to false once again.
1224 FontCachePurgePreventer fontCachePurgePreventer;
1227 ++m_nestedLayoutCount;
1230 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1232 if (!m_layoutRoot) {
1233 HTMLElement* body = document.body();
1234 if (body && body->renderer()) {
1235 if (body->hasTagName(framesetTag) && !frameFlatteningEnabled()) {
1236 body->renderer()->setChildNeedsLayout();
1237 } else if (body->hasTagName(bodyTag)) {
1238 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
1239 body->renderer()->setChildNeedsLayout();
1243 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1244 if (m_firstLayout && !frame().ownerElement())
1245 printf("Elapsed time before first layout: %d\n", document.elapsedTime());
1249 autoSizeIfEnabled();
1251 m_needsFullRepaint = !subtree && (m_firstLayout || toRenderView(*root).printing());
1254 ScrollbarMode hMode;
1255 ScrollbarMode vMode;
1256 calculateScrollbarModesForLayout(hMode, vMode);
1258 if (m_firstLayout || (hMode != horizontalScrollbarMode() || vMode != verticalScrollbarMode())) {
1259 if (m_firstLayout) {
1260 setScrollbarsSuppressed(true);
1262 m_firstLayout = false;
1263 m_firstLayoutCallbackPending = true;
1264 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
1265 m_lastViewportSize = fixedLayoutSize();
1268 m_lastViewportSize = actualVisibleContentRect().size();
1270 m_lastViewportSize = visibleContentRect(IncludeScrollbars).size();
1273 m_lastZoomFactor = root->style().zoom();
1275 // Set the initial vMode to AlwaysOn if we're auto.
1276 if (vMode == ScrollbarAuto)
1277 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
1278 // Set the initial hMode to AlwaysOff if we're auto.
1279 if (hMode == ScrollbarAuto)
1280 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
1282 setScrollbarModes(hMode, vMode);
1283 setScrollbarsSuppressed(false, true);
1285 setScrollbarModes(hMode, vMode);
1288 LayoutSize oldSize = m_size;
1290 m_size = layoutSize();
1292 if (oldSize != m_size) {
1293 m_needsFullRepaint = true;
1294 if (!m_firstLayout) {
1295 RenderBox* rootRenderer = document.documentElement() ? document.documentElement()->renderBox() : 0;
1296 RenderBox* bodyRenderer = rootRenderer && document.body() ? document.body()->renderBox() : 0;
1297 if (bodyRenderer && bodyRenderer->stretchesToViewport())
1298 bodyRenderer->setChildNeedsLayout();
1299 else if (rootRenderer && rootRenderer->stretchesToViewport())
1300 rootRenderer->setChildNeedsLayout();
1304 m_layoutPhase = InPreLayout;
1307 layer = root->enclosingLayer();
1309 bool disableLayoutState = false;
1311 disableLayoutState = root->view().shouldDisableLayoutStateForSubtree(root);
1312 root->view().pushLayoutState(*root);
1314 LayoutStateDisabler layoutStateDisabler(disableLayoutState ? &root->view() : 0);
1316 ASSERT(m_layoutPhase == InPreLayout);
1317 m_layoutPhase = InLayout;
1319 beginDeferredRepaints();
1320 forceLayoutParentViewIfNeeded();
1322 ASSERT(m_layoutPhase == InLayout);
1325 #if ENABLE(IOS_TEXT_AUTOSIZING)
1326 float minZoomFontSize = frame().settings().minimumZoomFontSize();
1327 float visWidth = frame().page()->mainFrame().textAutosizingWidth();
1328 if (minZoomFontSize && visWidth && !root->view().printing()) {
1329 root->adjustComputedFontSizesOnBlocks(minZoomFontSize, visWidth);
1330 bool needsLayout = root->needsLayout();
1335 #if ENABLE(TEXT_AUTOSIZING)
1336 if (document.textAutosizer()->processSubtree(root) && root->needsLayout())
1339 endDeferredRepaints();
1341 ASSERT(m_layoutPhase == InLayout);
1344 root->view().popLayoutState(*root);
1348 // Close block here to end the scope of changeSchedulingEnabled and layoutStateDisabler.
1351 m_layoutPhase = InViewSizeAdjust;
1353 bool neededFullRepaint = m_needsFullRepaint;
1355 if (!subtree && !toRenderView(*root).printing())
1358 m_layoutPhase = InPostLayout;
1360 m_needsFullRepaint = neededFullRepaint;
1362 // Now update the positions of all layers.
1363 beginDeferredRepaints();
1364 if (m_needsFullRepaint)
1365 root->view().repaintRootContents();
1367 layer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPositionFlags(layer, subtree, m_needsFullRepaint));
1369 endDeferredRepaints();
1371 #if USE(ACCELERATED_COMPOSITING)
1372 updateCompositingLayersAfterLayout();
1377 #if PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(EFL)
1378 if (AXObjectCache* cache = root->document().existingAXObjectCache())
1379 cache->postNotification(root, AXObjectCache::AXLayoutComplete);
1382 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
1383 updateAnnotatedRegions();
1386 #if ENABLE(IOS_TOUCH_EVENTS)
1387 document.dirtyTouchEventRects();
1390 ASSERT(!root->needsLayout());
1392 updateCanBlitOnScrollRecursively();
1394 if (document.hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1395 updateOverflowStatus(layoutWidth() < contentsWidth(), layoutHeight() < contentsHeight());
1397 if (!m_postLayoutTasksTimer.isActive()) {
1398 if (!m_inSynchronousPostLayout) {
1399 if (inChildFrameLayoutWithFrameFlattening)
1400 updateWidgetPositions();
1402 TemporaryChange<bool> inSynchronousPostLayoutChange(m_inSynchronousPostLayout, true);
1403 performPostLayoutTasks(); // Calls resumeScheduledEvents().
1407 if (!m_postLayoutTasksTimer.isActive() && (needsLayout() || m_inSynchronousPostLayout || inChildFrameLayoutWithFrameFlattening)) {
1408 // If we need layout or are already in a synchronous call to postLayoutTasks(),
1409 // defer widget updates and event dispatch until after we return. postLayoutTasks()
1410 // can make us need to update again, and we can get stuck in a nasty cycle unless
1411 // we call it through the timer here.
1412 m_postLayoutTasksTimer.startOneShot(0);
1418 InspectorInstrumentation::didLayout(cookie, root);
1420 --m_nestedLayoutCount;
1422 if (m_nestedLayoutCount)
1425 if (Page* page = frame().page())
1426 page->chrome().client().layoutUpdated(&frame());
1429 RenderBox* FrameView::embeddedContentBox() const
1432 RenderView* renderView = this->renderView();
1436 RenderObject* firstChild = renderView->firstChild();
1437 if (!firstChild || !firstChild->isBox())
1440 // Curently only embedded SVG documents participate in the size-negotiation logic.
1441 if (toRenderBox(firstChild)->isSVGRoot())
1442 return toRenderBox(firstChild);
1448 void FrameView::addEmbeddedObjectToUpdate(RenderEmbeddedObject& embeddedObject)
1450 if (!m_embeddedObjectsToUpdate)
1451 m_embeddedObjectsToUpdate = adoptPtr(new ListHashSet<RenderEmbeddedObject*>);
1453 HTMLFrameOwnerElement& element = embeddedObject.frameOwnerElement();
1454 if (isHTMLObjectElement(element) || isHTMLEmbedElement(element)) {
1455 // Tell the DOM element that it needs a widget update.
1456 HTMLPlugInImageElement& pluginElement = toHTMLPlugInImageElement(element);
1457 if (!pluginElement.needsCheckForSizeChange())
1458 pluginElement.setNeedsWidgetUpdate(true);
1461 m_embeddedObjectsToUpdate->add(&embeddedObject);
1464 void FrameView::removeEmbeddedObjectToUpdate(RenderEmbeddedObject& embeddedObject)
1466 if (!m_embeddedObjectsToUpdate)
1469 m_embeddedObjectsToUpdate->remove(&embeddedObject);
1472 void FrameView::setMediaType(const String& mediaType)
1474 m_mediaType = mediaType;
1477 String FrameView::mediaType() const
1479 // See if we have an override type.
1480 String overrideType = frame().loader().client().overrideMediaType();
1481 InspectorInstrumentation::applyEmulatedMedia(&frame(), &overrideType);
1482 if (!overrideType.isNull())
1483 return overrideType;
1487 void FrameView::adjustMediaTypeForPrinting(bool printing)
1490 if (m_mediaTypeWhenNotPrinting.isNull())
1491 m_mediaTypeWhenNotPrinting = mediaType();
1492 setMediaType("print");
1494 if (!m_mediaTypeWhenNotPrinting.isNull())
1495 setMediaType(m_mediaTypeWhenNotPrinting);
1496 m_mediaTypeWhenNotPrinting = String();
1500 bool FrameView::useSlowRepaints(bool considerOverlap) const
1502 bool mustBeSlow = hasSlowRepaintObjects() || (platformWidget() && hasViewportConstrainedObjects());
1504 // FIXME: WidgetMac.mm makes the assumption that useSlowRepaints ==
1505 // m_contentIsOpaque, so don't take the fast path for composited layers
1506 // if they are a platform widget in order to get painting correctness
1507 // for transparent layers. See the comment in WidgetMac::paint.
1508 if (contentsInCompositedLayer() && !platformWidget())
1511 bool isOverlapped = m_isOverlapped && considerOverlap;
1513 if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque)
1516 if (FrameView* parentView = parentFrameView())
1517 return parentView->useSlowRepaints(considerOverlap);
1522 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1524 return useSlowRepaints(false);
1527 void FrameView::updateCanBlitOnScrollRecursively()
1529 for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) {
1530 if (FrameView* view = frame->view())
1531 view->setCanBlitOnScroll(!view->useSlowRepaints());
1535 bool FrameView::contentsInCompositedLayer() const
1537 #if USE(ACCELERATED_COMPOSITING)
1538 RenderView* renderView = this->renderView();
1539 if (renderView && renderView->isComposited()) {
1540 GraphicsLayer* layer = renderView->layer()->backing()->graphicsLayer();
1541 if (layer && layer->drawsContent())
1548 void FrameView::setCannotBlitToWindow()
1550 m_cannotBlitToWindow = true;
1551 updateCanBlitOnScrollRecursively();
1554 void FrameView::addSlowRepaintObject(RenderElement* o)
1556 bool hadSlowRepaintObjects = hasSlowRepaintObjects();
1558 if (!m_slowRepaintObjects)
1559 m_slowRepaintObjects = adoptPtr(new HashSet<RenderElement*>);
1561 m_slowRepaintObjects->add(o);
1563 if (!hadSlowRepaintObjects) {
1564 updateCanBlitOnScrollRecursively();
1566 if (Page* page = frame().page()) {
1567 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1568 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1573 void FrameView::removeSlowRepaintObject(RenderElement* o)
1575 if (!m_slowRepaintObjects)
1578 m_slowRepaintObjects->remove(o);
1579 if (m_slowRepaintObjects->isEmpty()) {
1580 m_slowRepaintObjects = nullptr;
1581 updateCanBlitOnScrollRecursively();
1583 if (Page* page = frame().page()) {
1584 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1585 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1590 void FrameView::addViewportConstrainedObject(RenderElement* object)
1592 if (!m_viewportConstrainedObjects)
1593 m_viewportConstrainedObjects = adoptPtr(new ViewportConstrainedObjectSet);
1595 if (!m_viewportConstrainedObjects->contains(object)) {
1596 m_viewportConstrainedObjects->add(object);
1597 if (platformWidget())
1598 updateCanBlitOnScrollRecursively();
1600 if (Page* page = frame().page()) {
1601 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1602 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1607 void FrameView::removeViewportConstrainedObject(RenderElement* object)
1609 if (m_viewportConstrainedObjects && m_viewportConstrainedObjects->remove(object)) {
1610 if (Page* page = frame().page()) {
1611 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1612 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1615 // FIXME: In addFixedObject() we only call this if there's a platform widget,
1616 // why isn't the same check being made here?
1617 updateCanBlitOnScrollRecursively();
1621 LayoutRect FrameView::viewportConstrainedVisibleContentRect() const
1624 if (useCustomFixedPositionLayoutRect())
1625 return customFixedPositionLayoutRect();
1627 LayoutRect viewportRect = visibleContentRect();
1628 viewportRect.setLocation(toPoint(scrollOffsetForFixedPosition()));
1629 return viewportRect;
1632 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)
1635 if (behaviorForFixed == StickToDocumentBounds)
1636 position = ScrollableArea::constrainScrollPositionForOverhang(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, headerHeight, footerHeight);
1638 position = scrollPosition;
1639 position.setY(position.y() - headerHeight);
1642 IntSize maxSize = totalContentsSize - visibleContentRect.size();
1644 float dragFactorX = (fixedElementsLayoutRelativeToFrame || !maxSize.width()) ? 1 : (totalContentsSize.width() - visibleContentRect.width() * frameScaleFactor) / maxSize.width();
1645 float dragFactorY = (fixedElementsLayoutRelativeToFrame || !maxSize.height()) ? 1 : (totalContentsSize.height() - visibleContentRect.height() * frameScaleFactor) / maxSize.height();
1647 return IntSize(position.x() * dragFactorX / frameScaleFactor, position.y() * dragFactorY / frameScaleFactor);
1650 IntSize FrameView::scrollOffsetForFixedPosition() const
1652 IntRect visibleContentRect = this->visibleContentRect();
1653 IntSize totalContentsSize = this->totalContentsSize();
1654 IntPoint scrollPosition = this->scrollPosition();
1655 IntPoint scrollOrigin = this->scrollOrigin();
1656 float frameScaleFactor = frame().frameScaleFactor();
1657 ScrollBehaviorForFixedElements behaviorForFixed = scrollBehaviorForFixedElements();
1658 return scrollOffsetForFixedPosition(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, frameScaleFactor, fixedElementsLayoutRelativeToFrame(), behaviorForFixed, headerHeight(), footerHeight());
1661 IntPoint FrameView::minimumScrollPosition() const
1663 IntPoint minimumPosition(ScrollView::minimumScrollPosition());
1665 if (frame().isMainFrame() && m_scrollPinningBehavior == PinToBottom)
1666 minimumPosition.setY(maximumScrollPosition().y());
1668 return minimumPosition;
1671 IntPoint FrameView::maximumScrollPosition() const
1673 IntPoint maximumOffset(contentsWidth() - visibleWidth() - scrollOrigin().x(), totalContentsSize().height() - visibleHeight() - scrollOrigin().y());
1675 maximumOffset.clampNegativeToZero();
1677 if (frame().isMainFrame() && m_scrollPinningBehavior == PinToTop)
1678 maximumOffset.setY(minimumScrollPosition().y());
1680 return maximumOffset;
1683 bool FrameView::fixedElementsLayoutRelativeToFrame() const
1685 return frame().settings().fixedElementsLayoutRelativeToFrame();
1688 IntPoint FrameView::lastKnownMousePosition() const
1690 return frame().eventHandler().lastKnownMousePosition();
1693 bool FrameView::isHandlingWheelEvent() const
1695 return frame().eventHandler().isHandlingWheelEvent();
1698 bool FrameView::shouldSetCursor() const
1700 Page* page = frame().page();
1701 return page && page->isVisible() && page->focusController().isActive();
1704 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1706 if (!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty()) {
1707 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1711 const bool isCompositedContentLayer = contentsInCompositedLayer();
1713 // Get the rects of the fixed objects visible in the rectToScroll
1714 Region regionToUpdate;
1715 for (auto& renderer : *m_viewportConstrainedObjects) {
1716 if (!renderer->style().hasViewportConstrainedPosition())
1718 #if USE(ACCELERATED_COMPOSITING)
1719 if (renderer->isComposited())
1723 // Fixed items should always have layers.
1724 ASSERT(renderer->hasLayer());
1725 RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
1727 #if USE(ACCELERATED_COMPOSITING)
1728 if (layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForBoundsOutOfView
1729 || layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForNoVisibleContent) {
1730 // Don't invalidate for invisible fixed layers.
1735 #if ENABLE(CSS_FILTERS)
1736 if (layer->hasAncestorWithFilterOutsets()) {
1737 // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot
1738 // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
1742 IntRect updateRect = pixelSnappedIntRect(layer->repaintRectIncludingNonCompositingDescendants());
1743 updateRect = contentsToRootView(updateRect);
1744 if (!isCompositedContentLayer && clipsRepaints())
1745 updateRect.intersect(rectToScroll);
1746 if (!updateRect.isEmpty())
1747 regionToUpdate.unite(updateRect);
1751 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1753 // 2) update the area of fixed objects that has been invalidated
1754 Vector<IntRect> subRectsToUpdate = regionToUpdate.rects();
1755 size_t viewportConstrainedObjectsCount = subRectsToUpdate.size();
1756 for (size_t i = 0; i < viewportConstrainedObjectsCount; ++i) {
1757 IntRect updateRect = subRectsToUpdate[i];
1758 IntRect scrolledRect = updateRect;
1759 scrolledRect.move(scrollDelta);
1760 updateRect.unite(scrolledRect);
1761 #if USE(ACCELERATED_COMPOSITING)
1762 if (isCompositedContentLayer) {
1763 updateRect = rootViewToContents(updateRect);
1764 ASSERT(renderView());
1765 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
1769 if (clipsRepaints())
1770 updateRect.intersect(rectToScroll);
1771 hostWindow()->invalidateContentsAndRootView(updateRect, false);
1777 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1779 #if USE(ACCELERATED_COMPOSITING)
1780 if (contentsInCompositedLayer()) {
1781 IntRect updateRect = visibleContentRect();
1783 // Make sure to "apply" the scale factor here since we're converting from frame view
1784 // coordinates to layer backing coordinates.
1785 updateRect.scale(1 / frame().frameScaleFactor());
1787 ASSERT(renderView());
1788 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
1791 repaintSlowRepaintObjects();
1793 if (RenderWidget* frameRenderer = frame().ownerRenderer()) {
1794 if (isEnclosedInCompositingLayer()) {
1795 LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1796 frameRenderer->borderTop() + frameRenderer->paddingTop(),
1797 visibleWidth(), visibleHeight());
1798 frameRenderer->repaintRectangle(rect);
1804 ScrollView::scrollContentsSlowPath(updateRect);
1807 void FrameView::repaintSlowRepaintObjects()
1809 if (!m_slowRepaintObjects)
1812 // Renderers with fixed backgrounds may be in compositing layers, so we need to explicitly
1813 // repaint them after scrolling.
1814 for (auto& renderer : *m_slowRepaintObjects)
1815 renderer->repaint();
1818 // Note that this gets called at painting time.
1819 void FrameView::setIsOverlapped(bool isOverlapped)
1821 if (isOverlapped == m_isOverlapped)
1824 m_isOverlapped = isOverlapped;
1825 updateCanBlitOnScrollRecursively();
1827 #if USE(ACCELERATED_COMPOSITING)
1828 if (hasCompositedContentIncludingDescendants()) {
1829 // Overlap can affect compositing tests, so if it changes, we need to trigger
1830 // a layer update in the parent document.
1831 if (Frame* parentFrame = frame().tree().parent()) {
1832 if (RenderView* parentView = parentFrame->contentRenderer()) {
1833 RenderLayerCompositor& compositor = parentView->compositor();
1834 compositor.setCompositingLayersNeedRebuild();
1835 compositor.scheduleCompositingLayerUpdate();
1839 if (RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) {
1840 // We also need to trigger reevaluation for this and all descendant frames,
1841 // since a frame uses compositing if any ancestor is compositing.
1842 for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) {
1843 if (RenderView* view = frame->contentRenderer()) {
1844 RenderLayerCompositor& compositor = view->compositor();
1845 compositor.setCompositingLayersNeedRebuild();
1846 compositor.scheduleCompositingLayerUpdate();
1854 bool FrameView::isOverlappedIncludingAncestors() const
1859 if (FrameView* parentView = parentFrameView()) {
1860 if (parentView->isOverlapped())
1867 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1869 if (contentIsOpaque == m_contentIsOpaque)
1872 m_contentIsOpaque = contentIsOpaque;
1873 updateCanBlitOnScrollRecursively();
1876 void FrameView::restoreScrollbar()
1878 setScrollbarsSuppressed(false);
1881 bool FrameView::scrollToFragment(const URL& url)
1883 // If our URL has no ref, then we have no place we need to jump to.
1884 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1885 // and possibly repaint because :target pseudo class may have been
1886 // set (see bug 11321).
1887 if (!url.hasFragmentIdentifier() && !frame().document()->cssTarget())
1890 String fragmentIdentifier = url.fragmentIdentifier();
1891 if (scrollToAnchor(fragmentIdentifier))
1894 // Try again after decoding the ref, based on the document's encoding.
1895 if (TextResourceDecoder* decoder = frame().document()->decoder())
1896 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1901 bool FrameView::scrollToAnchor(const String& name)
1903 ASSERT(frame().document());
1905 if (!frame().document()->haveStylesheetsLoaded()) {
1906 frame().document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1910 frame().document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1912 Element* anchorElement = frame().document()->findAnchor(name);
1914 // Setting to null will clear the current target.
1915 frame().document()->setCSSTarget(anchorElement);
1918 if (frame().document()->isSVGDocument()) {
1919 if (SVGSVGElement* svg = toSVGDocument(frame().document())->rootElement()) {
1920 svg->setupInitialView(name, anchorElement);
1927 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1928 if (!anchorElement && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1931 maintainScrollPositionAtAnchor(anchorElement ? static_cast<Node*>(anchorElement) : frame().document());
1933 // If the anchor accepts keyboard focus, move focus there to aid users relying on keyboard navigation.
1934 if (anchorElement && anchorElement->isFocusable())
1935 frame().document()->setFocusedElement(anchorElement);
1940 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1942 m_maintainScrollPositionAnchor = anchorNode;
1943 if (!m_maintainScrollPositionAnchor)
1946 // We need to update the layout before scrolling, otherwise we could
1947 // really mess things up if an anchor scroll comes at a bad moment.
1948 frame().document()->updateStyleIfNeeded();
1949 // Only do a layout if changes have occurred that make it necessary.
1950 RenderView* renderView = this->renderView();
1951 if (renderView && renderView->needsLayout())
1957 void FrameView::scrollElementToRect(Element* element, const IntRect& rect)
1959 frame().document()->updateLayoutIgnorePendingStylesheets();
1961 LayoutRect bounds = element->boundingBox();
1962 int centeringOffsetX = (rect.width() - bounds.width()) / 2;
1963 int centeringOffsetY = (rect.height() - bounds.height()) / 2;
1964 setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y()));
1967 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1969 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1970 m_maintainScrollPositionAnchor = 0;
1971 ScrollView::setScrollPosition(scrollPoint);
1974 void FrameView::delegatesScrollingDidChange()
1976 #if USE(ACCELERATED_COMPOSITING)
1977 // When we switch to delgatesScrolling mode, we should destroy the scrolling/clipping layers in RenderLayerCompositor.
1978 if (hasCompositedContent())
1979 clearBackingStores();
1983 #if USE(TILED_BACKING_STORE)
1984 void FrameView::setFixedVisibleContentRect(const IntRect& visibleContentRect)
1986 bool visibleContentSizeDidChange = false;
1987 if (visibleContentRect.size() != this->fixedVisibleContentRect().size()) {
1988 // When the viewport size changes or the content is scaled, we need to
1989 // reposition the fixed and sticky positioned elements.
1990 setViewportConstrainedObjectsNeedLayout();
1991 visibleContentSizeDidChange = true;
1994 IntSize offset = scrollOffset();
1995 ScrollView::setFixedVisibleContentRect(visibleContentRect);
1996 if (offset != scrollOffset()) {
1997 updateLayerPositionsAfterScrolling();
1998 if (frame().page()->settings().acceleratedCompositingForFixedPositionEnabled())
1999 updateCompositingLayersAfterScrolling();
2000 scrollAnimator()->setCurrentPosition(scrollPosition());
2001 scrollPositionChanged();
2003 if (visibleContentSizeDidChange) {
2004 // Update the scroll-bars to calculate new page-step size.
2005 updateScrollbars(scrollOffset());
2007 frame().loader().client().didChangeScrollOffset();
2011 void FrameView::setViewportConstrainedObjectsNeedLayout()
2013 if (!hasViewportConstrainedObjects())
2016 for (auto& renderer : *m_viewportConstrainedObjects)
2017 renderer->setNeedsLayout();
2020 void FrameView::scrollPositionChangedViaPlatformWidget()
2022 updateLayerPositionsAfterScrolling();
2023 updateCompositingLayersAfterScrolling();
2024 repaintSlowRepaintObjects();
2025 scrollPositionChanged();
2028 void FrameView::scrollPositionChanged()
2030 frame().eventHandler().sendScrollEvent();
2031 frame().eventHandler().dispatchFakeMouseMoveEventSoon();
2033 #if USE(ACCELERATED_COMPOSITING)
2034 if (RenderView* renderView = this->renderView()) {
2035 if (renderView->usesCompositing())
2036 renderView->compositor().frameViewDidScroll();
2041 void FrameView::updateLayerPositionsAfterScrolling()
2043 // If we're scrolling as a result of updating the view size after layout, we'll update widgets and layer positions soon anyway.
2044 if (m_layoutPhase == InViewSizeAdjust)
2047 if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) {
2048 if (RenderView* renderView = this->renderView()) {
2049 updateWidgetPositions();
2050 renderView->layer()->updateLayerPositionsAfterDocumentScroll();
2055 bool FrameView::shouldUpdateCompositingLayersAfterScrolling() const
2057 #if ENABLE(ASYNC_SCROLLING)
2058 // If the scrolling thread is updating the fixed elements, then the FrameView should not update them as well.
2060 Page* page = frame().page();
2064 if (&page->mainFrame() != &frame())
2067 ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
2068 if (!scrollingCoordinator)
2071 if (!scrollingCoordinator->supportsFixedPositionLayers())
2074 if (scrollingCoordinator->shouldUpdateScrollLayerPositionSynchronously())
2077 if (inProgrammaticScroll())
2085 void FrameView::updateCompositingLayersAfterScrolling()
2087 #if USE(ACCELERATED_COMPOSITING)
2088 if (!shouldUpdateCompositingLayersAfterScrolling())
2091 if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) {
2092 if (RenderView* renderView = this->renderView())
2093 renderView->compositor().updateCompositingLayers(CompositingUpdateOnScroll);
2098 bool FrameView::isRubberBandInProgress() const
2100 if (scrollbarsSuppressed())
2103 // If the scrolling thread updates the scroll position for this FrameView, then we should return
2104 // ScrollingCoordinator::isRubberBandInProgress().
2105 if (Page* page = frame().page()) {
2106 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
2107 if (!scrollingCoordinator->shouldUpdateScrollLayerPositionSynchronously())
2108 return scrollingCoordinator->isRubberBandInProgress();
2112 // If the main thread updates the scroll position for this FrameView, we should return
2113 // ScrollAnimator::isRubberBandInProgress().
2114 if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
2115 return scrollAnimator->isRubberBandInProgress();
2120 bool FrameView::requestScrollPositionUpdate(const IntPoint& position)
2122 #if ENABLE(ASYNC_SCROLLING)
2123 if (TiledBacking* tiledBacking = this->tiledBacking()) {
2124 IntRect visibleRect = visibleContentRect();
2125 visibleRect.setLocation(position);
2126 tiledBacking->prepopulateRect(visibleRect);
2129 if (Page* page = frame().page()) {
2130 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2131 return scrollingCoordinator->requestScrollPositionUpdate(this, position);
2134 UNUSED_PARAM(position);
2140 HostWindow* FrameView::hostWindow() const
2142 if (Page* page = frame().page())
2143 return &page->chrome();
2147 void FrameView::addTrackedRepaintRect(const IntRect& r)
2149 if (!m_isTrackingRepaints || r.isEmpty())
2152 IntRect repaintRect = r;
2153 repaintRect.move(-scrollOffset());
2154 m_trackedRepaintRects.append(repaintRect);
2157 const unsigned cRepaintRectUnionThreshold = 25;
2159 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
2161 ASSERT(!frame().ownerElement());
2163 addTrackedRepaintRect(r);
2165 double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay();
2166 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
2167 IntRect paintRect = r;
2168 if (clipsRepaints() && !paintsEntireContents())
2169 paintRect.intersect(visibleContentRect());
2170 if (paintRect.isEmpty())
2172 if (m_repaintCount == cRepaintRectUnionThreshold) {
2173 IntRect unionedRect;
2174 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
2175 unionedRect.unite(pixelSnappedIntRect(m_repaintRects[i]));
2176 m_repaintRects.clear();
2177 m_repaintRects.append(unionedRect);
2179 if (m_repaintCount < cRepaintRectUnionThreshold)
2180 m_repaintRects.append(paintRect);
2182 m_repaintRects[0].unite(paintRect);
2185 if (!m_deferringRepaints)
2186 startDeferredRepaintTimer(delay);
2191 if (!shouldUpdate(immediate))
2194 #if USE(TILED_BACKING_STORE)
2195 if (frame().tiledBackingStore()) {
2196 frame().tiledBackingStore()->invalidate(r);
2200 ScrollView::repaintContentRectangle(r, immediate);
2203 static unsigned countRenderedCharactersInRenderObjectWithThreshold(const RenderObject& renderer, unsigned countSoFar, unsigned threshold)
2205 // FIXME: Consider writing this using RenderObject::nextInPreOrder() instead of using recursion.
2206 if (renderer.isText())
2207 countSoFar += toRenderText(renderer).text()->length();
2209 for (RenderObject* child = renderer.firstChildSlow(); child; child = child->nextSibling()) {
2210 if (countSoFar >= threshold)
2212 countSoFar = countRenderedCharactersInRenderObjectWithThreshold(*child, countSoFar, threshold);
2217 bool FrameView::renderedCharactersExceed(unsigned threshold)
2219 if (!m_frame->contentRenderer())
2221 return countRenderedCharactersInRenderObjectWithThreshold(*m_frame->contentRenderer(), 0, threshold) >= threshold;
2224 void FrameView::contentsResized()
2226 ScrollView::contentsResized();
2230 void FrameView::fixedLayoutSizeChanged()
2232 // Can be triggered before the view is set, see comment in FrameView::visibleContentsResized().
2233 // An ASSERT is triggered when a view schedules a layout before being attached to a frame.
2234 if (!frame().view())
2236 ScrollView::fixedLayoutSizeChanged();
2239 void FrameView::visibleContentsResized()
2241 // We check to make sure the view is attached to a frame() as this method can
2242 // be triggered before the view is attached by Frame::createView(...) setting
2243 // various values such as setScrollBarModes(...) for example. An ASSERT is
2244 // triggered when a view is layout before being attached to a frame().
2245 if (!frame().view())
2249 if (RenderView* root = m_frame->contentRenderer()) {
2250 if (useCustomFixedPositionLayoutRect() && hasViewportConstrainedObjects()) {
2251 setViewportConstrainedObjectsNeedLayout();
2252 // We must eagerly enter compositing mode because fixed position elements
2253 // will not have been made compositing via a preceding style change before
2254 // m_useCustomFixedPositionLayoutRect was true.
2255 root->compositor().enableCompositingMode();
2260 if (!useFixedLayout() && needsLayout())
2263 #if USE(ACCELERATED_COMPOSITING)
2264 if (RenderView* renderView = this->renderView()) {
2265 if (renderView->usesCompositing())
2266 renderView->compositor().frameViewDidChangeSize();
2271 void FrameView::addedOrRemovedScrollbar()
2273 #if USE(ACCELERATED_COMPOSITING)
2274 if (RenderView* renderView = this->renderView()) {
2275 if (renderView->usesCompositing())
2276 renderView->compositor().frameViewDidAddOrRemoveScrollbars();
2281 void FrameView::beginDeferredRepaints()
2283 if (!frame().isMainFrame()) {
2284 frame().mainFrame().view()->beginDeferredRepaints();
2288 m_deferringRepaints++;
2291 void FrameView::endDeferredRepaints()
2293 if (!frame().isMainFrame()) {
2294 frame().mainFrame().view()->endDeferredRepaints();
2298 ASSERT(m_deferringRepaints > 0);
2300 if (--m_deferringRepaints)
2303 if (m_deferredRepaintTimer.isActive())
2306 if (double delay = adjustedDeferredRepaintDelay()) {
2307 startDeferredRepaintTimer(delay);
2311 doDeferredRepaints();
2314 void FrameView::startDeferredRepaintTimer(double delay)
2316 if (m_deferredRepaintTimer.isActive())
2319 m_deferredRepaintTimer.startOneShot(delay);
2322 void FrameView::handleLoadCompleted()
2324 // Once loading has completed, allow autoSize one last opportunity to
2325 // reduce the size of the frame.
2326 autoSizeIfEnabled();
2327 if (shouldUseLoadTimeDeferredRepaintDelay())
2329 m_deferredRepaintDelay = s_normalDeferredRepaintDelay;
2330 flushDeferredRepaints();
2333 void FrameView::flushDeferredRepaints()
2335 if (!m_deferredRepaintTimer.isActive())
2337 m_deferredRepaintTimer.stop();
2338 doDeferredRepaints();
2341 void FrameView::doDeferredRepaints()
2343 ASSERT(!m_deferringRepaints);
2344 if (!shouldUpdate()) {
2345 m_repaintRects.clear();
2349 unsigned size = m_repaintRects.size();
2350 for (unsigned i = 0; i < size; i++) {
2351 #if USE(TILED_BACKING_STORE)
2352 if (frame().tiledBackingStore()) {
2353 frame().tiledBackingStore()->invalidate(pixelSnappedIntRect(m_repaintRects[i]));
2357 ScrollView::repaintContentRectangle(pixelSnappedIntRect(m_repaintRects[i]), false);
2359 m_repaintRects.clear();
2362 updateDeferredRepaintDelayAfterRepaint();
2365 bool FrameView::shouldUseLoadTimeDeferredRepaintDelay() const
2367 // Don't defer after the initial load of the page has been completed.
2368 if (frame().tree().top().loader().isComplete())
2370 Document* document = frame().document();
2373 if (document->parsing())
2375 if (document->cachedResourceLoader()->requestCount())
2380 void FrameView::updateDeferredRepaintDelayAfterRepaint()
2382 if (!shouldUseLoadTimeDeferredRepaintDelay()) {
2383 m_deferredRepaintDelay = s_normalDeferredRepaintDelay;
2386 double incrementedRepaintDelay = m_deferredRepaintDelay + s_deferredRepaintDelayIncrementDuringLoading;
2387 m_deferredRepaintDelay = std::min(incrementedRepaintDelay, s_maxDeferredRepaintDelayDuringLoading);
2390 void FrameView::resetDeferredRepaintDelay()
2392 m_deferredRepaintDelay = 0;
2393 if (m_deferredRepaintTimer.isActive()) {
2394 m_deferredRepaintTimer.stop();
2395 if (!m_deferringRepaints)
2396 doDeferredRepaints();
2398 #if USE(ACCELERATED_COMPOSITING)
2399 if (RenderView* view = renderView())
2400 view->compositor().disableLayerFlushThrottlingTemporarilyForInteraction();
2404 double FrameView::adjustedDeferredRepaintDelay() const
2406 ASSERT(!m_deferringRepaints);
2407 if (!m_deferredRepaintDelay)
2409 double timeSinceLastPaint = monotonicallyIncreasingTime() - m_lastPaintTime;
2410 return std::max<double>(0, m_deferredRepaintDelay - timeSinceLastPaint);
2413 void FrameView::deferredRepaintTimerFired(Timer<FrameView>&)
2415 doDeferredRepaints();
2418 void FrameView::updateLayerFlushThrottlingInAllFrames()
2420 #if USE(ACCELERATED_COMPOSITING)
2421 bool isMainLoadProgressing = frame().page()->progress().isMainLoadProgressing();
2422 for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) {
2423 if (RenderView* renderView = frame->contentRenderer())
2424 renderView->compositor().setLayerFlushThrottlingEnabled(isMainLoadProgressing);
2429 void FrameView::adjustTiledBackingCoverage()
2431 if (!m_speculativeTilingEnabled)
2432 enableSpeculativeTilingIfNeeded();
2434 #if USE(ACCELERATED_COMPOSITING)
2435 RenderView* renderView = this->renderView();
2436 if (renderView && renderView->layer()->backing())
2437 renderView->layer()->backing()->adjustTiledBackingCoverage();
2440 if (TileCache* tileCache = this->tileCache())
2441 tileCache->setSpeculativeTileCreationEnabled(m_speculativeTilingEnabled);
2445 static bool shouldEnableSpeculativeTilingDuringLoading(const FrameView& view)
2447 return view.isVisuallyNonEmpty() && !view.frame().page()->progress().isMainLoadProgressing();
2450 void FrameView::enableSpeculativeTilingIfNeeded()
2452 ASSERT(!m_speculativeTilingEnabled);
2453 if (m_wasScrolledByUser) {
2454 m_speculativeTilingEnabled = true;
2457 if (!shouldEnableSpeculativeTilingDuringLoading(*this))
2459 if (m_speculativeTilingEnableTimer.isActive())
2461 // Delay enabling a bit as load completion may trigger further loading from scripts.
2462 static const double speculativeTilingEnableDelay = 0.5;
2463 m_speculativeTilingEnableTimer.startOneShot(speculativeTilingEnableDelay);
2466 void FrameView::speculativeTilingEnableTimerFired(Timer<FrameView>&)
2468 if (m_speculativeTilingEnabled)
2470 m_speculativeTilingEnabled = shouldEnableSpeculativeTilingDuringLoading(*this);
2471 adjustTiledBackingCoverage();
2474 void FrameView::layoutTimerFired(Timer<FrameView>&)
2476 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2477 if (!frame().document()->ownerElement())
2478 printf("Layout timer fired at %d\n", frame().document()->elapsedTime());
2483 void FrameView::scheduleRelayout()
2485 // FIXME: We should assert the page is not in the page cache, but that is causing
2486 // too many false assertions. See <rdar://problem/7218118>.
2487 ASSERT(frame().view() == this);
2490 m_layoutRoot->markContainingBlocksForLayout(false);
2493 if (!m_layoutSchedulingEnabled)
2497 if (!frame().document()->shouldScheduleLayout())
2499 InspectorInstrumentation::didInvalidateLayout(&frame());
2500 // When frame flattening is enabled, the contents of the frame could affect the layout of the parent frames.
2501 // Also invalidate parent frame starting from the owner element of this frame.
2502 if (frame().ownerRenderer() && isInChildFrameWithFrameFlattening())
2503 frame().ownerRenderer()->setNeedsLayout(MarkContainingBlockChain);
2505 int delay = frame().document()->minimumLayoutDelay();
2506 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
2507 unscheduleRelayout();
2508 if (m_layoutTimer.isActive())
2511 m_delayedLayout = delay != 0;
2513 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2514 if (!frame().document()->ownerElement())
2515 printf("Scheduling layout for %d\n", delay);
2518 m_layoutTimer.startOneShot(delay * 0.001);
2521 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
2523 for (RenderObject* r = descendant; r; r = r->container()) {
2530 void FrameView::scheduleRelayoutOfSubtree(RenderElement& newRelayoutRoot)
2532 ASSERT(renderView());
2533 RenderView& renderView = *this->renderView();
2535 // Try to catch unnecessary work during render tree teardown.
2536 ASSERT(!renderView.documentBeingDestroyed());
2537 ASSERT(frame().view() == this);
2539 if (renderView.needsLayout()) {
2540 newRelayoutRoot.markContainingBlocksForLayout(false);
2544 if (!layoutPending() && m_layoutSchedulingEnabled) {
2545 int delay = renderView.document().minimumLayoutDelay();
2546 ASSERT(!newRelayoutRoot.container() || !newRelayoutRoot.container()->needsLayout());
2547 m_layoutRoot = &newRelayoutRoot;
2548 InspectorInstrumentation::didInvalidateLayout(&frame());
2549 m_delayedLayout = delay != 0;
2550 m_layoutTimer.startOneShot(delay * 0.001);
2554 if (m_layoutRoot == &newRelayoutRoot)
2557 if (!m_layoutRoot) {
2558 // Just relayout the subtree.
2559 newRelayoutRoot.markContainingBlocksForLayout(false);
2560 InspectorInstrumentation::didInvalidateLayout(&frame());
2564 if (isObjectAncestorContainerOf(m_layoutRoot, &newRelayoutRoot)) {
2565 // Keep the current root.
2566 newRelayoutRoot.markContainingBlocksForLayout(false, m_layoutRoot);
2567 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2571 if (isObjectAncestorContainerOf(&newRelayoutRoot, m_layoutRoot)) {
2572 // Re-root at newRelayoutRoot.
2573 m_layoutRoot->markContainingBlocksForLayout(false, &newRelayoutRoot);
2574 m_layoutRoot = &newRelayoutRoot;
2575 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2576 InspectorInstrumentation::didInvalidateLayout(&frame());
2580 // Just do a full relayout.
2581 m_layoutRoot->markContainingBlocksForLayout(false);
2583 newRelayoutRoot.markContainingBlocksForLayout(false);
2584 InspectorInstrumentation::didInvalidateLayout(&frame());
2587 bool FrameView::layoutPending() const
2589 return m_layoutTimer.isActive();
2592 bool FrameView::needsLayout() const
2594 // This can return true in cases where the document does not have a body yet.
2595 // Document::shouldScheduleLayout takes care of preventing us from scheduling
2596 // layout in that case.
2597 RenderView* renderView = this->renderView();
2598 return layoutPending()
2599 || (renderView && renderView->needsLayout())
2601 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
2604 void FrameView::setNeedsLayout()
2606 if (m_deferSetNeedsLayouts) {
2607 m_setNeedsLayoutWasDeferred = true;
2611 if (RenderView* renderView = this->renderView())
2612 renderView->setNeedsLayout();
2615 void FrameView::unscheduleRelayout()
2617 if (!m_layoutTimer.isActive())
2620 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2621 if (!frame().document()->ownerElement())
2622 printf("Layout timer unscheduled at %d\n", frame().document()->elapsedTime());
2625 m_layoutTimer.stop();
2626 m_delayedLayout = false;
2629 #if ENABLE(REQUEST_ANIMATION_FRAME)
2630 void FrameView::serviceScriptedAnimations(double monotonicAnimationStartTime)
2632 for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext()) {
2633 frame->view()->serviceScrollAnimations();
2634 frame->animation().serviceAnimations();
2637 Vector<RefPtr<Document>> documents;
2638 for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext())
2639 documents.append(frame->document());
2641 for (size_t i = 0; i < documents.size(); ++i)
2642 documents[i]->serviceScriptedAnimations(monotonicAnimationStartTime);
2646 bool FrameView::isTransparent() const
2648 return m_isTransparent;
2651 void FrameView::setTransparent(bool isTransparent)
2653 m_isTransparent = isTransparent;
2656 bool FrameView::hasOpaqueBackground() const
2658 return !m_isTransparent && !m_baseBackgroundColor.hasAlpha();
2661 Color FrameView::baseBackgroundColor() const
2663 return m_baseBackgroundColor;
2666 void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
2668 if (!backgroundColor.isValid())
2669 m_baseBackgroundColor = Color::white;
2671 m_baseBackgroundColor = backgroundColor;
2673 recalculateScrollbarOverlayStyle();
2676 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
2678 for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) {
2679 if (FrameView* view = frame->view()) {
2680 view->setTransparent(transparent);
2681 view->setBaseBackgroundColor(backgroundColor);
2686 bool FrameView::hasExtendedBackground() const
2688 #if USE(ACCELERATED_COMPOSITING)
2689 if (!frame().settings().backgroundShouldExtendBeyondPage())
2692 TiledBacking* tiledBacking = this->tiledBacking();
2696 return tiledBacking->hasMargins();
2702 IntRect FrameView::extendedBackgroundRect() const
2704 #if USE(ACCELERATED_COMPOSITING)
2705 TiledBacking* tiledBacking = this->tiledBacking();
2709 return tiledBacking->bounds();
2711 RenderView* renderView = this->renderView();
2715 return renderView->unscaledDocumentRect();
2719 #if USE(ACCELERATED_COMPOSITING)
2720 void FrameView::setBackgroundExtendsBeyondPage(bool extendBackground)
2722 RenderView* renderView = this->renderView();
2726 RenderLayerBacking* backing = renderView->layer()->backing();
2730 backing->setTiledBackingHasMargins(extendBackground);
2734 bool FrameView::shouldUpdateWhileOffscreen() const
2736 return m_shouldUpdateWhileOffscreen;
2739 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
2741 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
2744 bool FrameView::shouldUpdate(bool immediateRequested) const
2746 if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen())
2751 void FrameView::scrollToAnchor()
2753 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
2757 if (!anchorNode->renderer())
2761 if (anchorNode != frame().document())
2762 rect = anchorNode->boundingBox();
2764 // Scroll nested layers and frames to reveal the anchor.
2765 // Align to the top and to the closest side (this matches other browsers).
2766 anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
2768 if (AXObjectCache* cache = frame().document()->existingAXObjectCache())
2769 cache->handleScrolledToAnchor(anchorNode.get());
2771 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
2772 m_maintainScrollPositionAnchor = anchorNode;
2775 void FrameView::updateEmbeddedObject(RenderEmbeddedObject& embeddedObject)
2777 // No need to update if it's already crashed or known to be missing.
2778 if (embeddedObject.isPluginUnavailable())
2781 HTMLFrameOwnerElement& element = embeddedObject.frameOwnerElement();
2783 if (embeddedObject.isSnapshottedPlugIn()) {
2784 if (isHTMLObjectElement(element) || isHTMLEmbedElement(element)) {
2785 HTMLPlugInImageElement& pluginElement = toHTMLPlugInImageElement(element);
2786 pluginElement.checkSnapshotStatus();
2791 auto weakRenderer = embeddedObject.createWeakPtr();
2793 // FIXME: This could turn into a real virtual dispatch if we defined
2794 // updateWidget(PluginCreationOption) on HTMLElement.
2795 if (isHTMLObjectElement(element) || isHTMLEmbedElement(element) || isHTMLAppletElement(element)) {
2796 HTMLPlugInImageElement& pluginElement = toHTMLPlugInImageElement(element);
2797 if (pluginElement.needsCheckForSizeChange()) {
2798 pluginElement.checkSnapshotStatus();
2801 if (pluginElement.needsWidgetUpdate())
2802 pluginElement.updateWidget(CreateAnyWidgetType);
2805 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
2806 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
2807 else if (element.isMediaElement())
2808 toHTMLMediaElement(element).updateWidget(CreateAnyWidgetType);
2811 ASSERT_NOT_REACHED();
2813 // It's possible the renderer was destroyed below updateWidget() since loading a plugin may execute arbitrary JavaScript.
2817 embeddedObject.updateWidgetPosition();
2820 bool FrameView::updateEmbeddedObjects()
2822 if (m_nestedLayoutCount > 1 || !m_embeddedObjectsToUpdate || m_embeddedObjectsToUpdate->isEmpty())
2825 WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
2827 // Insert a marker for where we should stop.
2828 ASSERT(!m_embeddedObjectsToUpdate->contains(nullptr));
2829 m_embeddedObjectsToUpdate->add(nullptr);
2831 while (!m_embeddedObjectsToUpdate->isEmpty()) {
2832 RenderEmbeddedObject* embeddedObject = m_embeddedObjectsToUpdate->takeFirst();
2833 if (!embeddedObject)
2835 updateEmbeddedObject(*embeddedObject);
2838 return m_embeddedObjectsToUpdate->isEmpty();
2841 void FrameView::flushAnyPendingPostLayoutTasks()
2843 if (!m_postLayoutTasksTimer.isActive())
2846 performPostLayoutTasks();
2849 void FrameView::performPostLayoutTasks()
2851 m_postLayoutTasksTimer.stop();
2853 frame().selection().setCaretRectNeedsUpdate();
2854 frame().selection().updateAppearance();
2856 LayoutMilestones requestedMilestones = 0;
2857 LayoutMilestones milestonesAchieved = 0;
2858 Page* page = frame().page();
2860 requestedMilestones = page->requestedLayoutMilestones();
2862 if (m_nestedLayoutCount <= 1 && frame().document()->documentElement()) {
2863 if (m_firstLayoutCallbackPending) {
2864 m_firstLayoutCallbackPending = false;
2865 frame().loader().didFirstLayout();
2866 if (requestedMilestones & DidFirstLayout)
2867 milestonesAchieved |= DidFirstLayout;
2868 if (frame().isMainFrame())
2869 page->startCountingRelevantRepaintedObjects();
2871 updateIsVisuallyNonEmpty();
2873 // If the layout was done with pending sheets, we are not in fact visually non-empty yet.
2874 if (m_isVisuallyNonEmpty && !frame().document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) {
2875 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
2876 if (requestedMilestones & DidFirstVisuallyNonEmptyLayout)
2877 milestonesAchieved |= DidFirstVisuallyNonEmptyLayout;
2882 // Only send layout-related delegate callbacks synchronously for the main frame to
2883 // avoid re-entering layout for the main frame while delivering a layout-related delegate
2884 // callback for a subframe.
2885 if (frame().isMainFrame())
2886 page->chrome().client().didLayout();
2889 if (milestonesAchieved && frame().isMainFrame())
2890 frame().loader().didLayout(milestonesAchieved);
2892 #if ENABLE(FONT_LOAD_EVENTS)
2893 if (RuntimeEnabledFeatures::sharedFeatures().fontLoadEventsEnabled())
2894 frame().document()->fontloader()->didLayout();
2897 // FIXME: We should consider adding DidLayout as a LayoutMilestone. That would let us merge this
2898 // with didLayout(LayoutMilestones).
2899 frame().loader().client().dispatchDidLayout();
2901 updateWidgetPositions();
2903 // layout() protects FrameView, but it still can get destroyed when updateEmbeddedObjects()
2904 // is called through the post layout timer.
2905 Ref<FrameView> protect(*this);
2907 for (unsigned i = 0; i < maxUpdateEmbeddedObjectsIterations; i++) {
2908 if (updateEmbeddedObjects())
2913 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2914 scrollingCoordinator->frameViewLayoutUpdated(this);
2917 #if USE(ACCELERATED_COMPOSITING)
2918 if (RenderView* renderView = this->renderView()) {
2919 if (renderView->usesCompositing())
2920 renderView->compositor().frameViewDidLayout();
2926 sendResizeEventIfNeeded();
2929 void FrameView::sendResizeEventIfNeeded()
2931 RenderView* renderView = this->renderView();
2932 if (!renderView || renderView->printing())
2934 if (frame().page() && frame().page()->chrome().client().isSVGImageChromeClient())
2937 IntSize currentSize;
2938 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
2939 currentSize = fixedLayoutSize();
2942 currentSize = actualVisibleContentRect().size();
2944 currentSize = visibleContentRect(IncludeScrollbars).size();
2947 float currentZoomFactor = renderView->style().zoom();
2948 bool shouldSendResizeEvent = !m_firstLayout && (currentSize != m_lastViewportSize || currentZoomFactor != m_lastZoomFactor);
2950 m_lastViewportSize = currentSize;
2951 m_lastZoomFactor = currentZoomFactor;
2953 if (!shouldSendResizeEvent)
2957 // Don't send the resize event if the document is loading. Some pages automatically reload
2958 // when the window is resized; Safari on iOS often resizes the window while setting up its
2959 // viewport. This obviously can cause problems.
2960 if (DocumentLoader* documentLoader = frame().loader().documentLoader()) {
2961 if (documentLoader->isLoadingInAPISense())
2966 bool isMainFrame = frame().isMainFrame();
2967 bool canSendResizeEventSynchronously = isMainFrame && !isInLayout();
2969 // If we resized during layout, queue up a resize event for later, otherwise fire it right away.
2970 RefPtr<Event> resizeEvent = Event::create(eventNames().resizeEvent, false, false);
2971 if (canSendResizeEventSynchronously)
2972 frame().document()->dispatchWindowEvent(resizeEvent.release(), frame().document()->domWindow());
2974 frame().document()->enqueueWindowEvent(resizeEvent.release());
2976 #if ENABLE(INSPECTOR)
2977 Page* page = frame().page();
2978 if (InspectorInstrumentation::hasFrontends() && isMainFrame) {
2979 if (InspectorClient* inspectorClient = page ? page->inspectorController().inspectorClient() : nullptr)
2980 inspectorClient->didResizeMainFrame(&frame());
2985 void FrameView::willStartLiveResize()
2987 ScrollView::willStartLiveResize();
2988 adjustTiledBackingCoverage();
2991 void FrameView::willEndLiveResize()
2993 ScrollView::willEndLiveResize();
2994 adjustTiledBackingCoverage();
2997 void FrameView::postLayoutTimerFired(Timer<FrameView>&)
2999 performPostLayoutTasks();
3002 void FrameView::autoSizeIfEnabled()
3004 if (!m_shouldAutoSize)
3010 TemporaryChange<bool> changeInAutoSize(m_inAutoSize, true);
3012 Document* document = frame().document();
3016 RenderView* documentView = document->renderView();
3017 Element* documentElement = document->documentElement();
3018 if (!documentView || !documentElement)
3021 // Start from the minimum size and allow it to grow.
3022 resize(m_minAutoSize.width(), m_minAutoSize.height());
3024 IntSize size = frameRect().size();
3026 // Do the resizing twice. The first time is basically a rough calculation using the preferred width
3027 // which may result in a height change during the second iteration.
3028 for (int i = 0; i < 2; i++) {
3029 // Update various sizes including contentsSize, scrollHeight, etc.
3030 document->updateLayoutIgnorePendingStylesheets();
3031 int width = documentView->minPreferredLogicalWidth();
3032 int height = documentView->documentRect().height();
3033 IntSize newSize(width, height);
3035 // Check to see if a scrollbar is needed for a given dimension and
3036 // if so, increase the other dimension to account for the scrollbar.
3037 // Since the dimensions are only for the view rectangle, once a
3038 // dimension exceeds the maximum, there is no need to increase it further.
3039 if (newSize.width() > m_maxAutoSize.width()) {
3040 RefPtr<Scrollbar> localHorizontalScrollbar = horizontalScrollbar();
3041 if (!localHorizontalScrollbar)
3042 localHorizontalScrollbar = createScrollbar(HorizontalScrollbar);
3043 if (!localHorizontalScrollbar->isOverlayScrollbar())
3044 newSize.setHeight(newSize.height() + localHorizontalScrollbar->height());
3046 // Don't bother checking for a vertical scrollbar because the width is at
3047 // already greater the maximum.
3048 } else if (newSize.height() > m_maxAutoSize.height()) {
3049 RefPtr<Scrollbar> localVerticalScrollbar = verticalScrollbar();
3050 if (!localVerticalScrollbar)
3051 localVerticalScrollbar = createScrollbar(VerticalScrollbar);
3052 if (!localVerticalScrollbar->isOverlayScrollbar())
3053 newSize.setWidth(newSize.width() + localVerticalScrollbar->width());
3055 // Don't bother checking for a horizontal scrollbar because the height is
3056 // already greater the maximum.
3059 // Ensure the size is at least the min bounds.
3060 newSize = newSize.expandedTo(m_minAutoSize);
3062 // Bound the dimensions by the max bounds and determine what scrollbars to show.
3063 ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff;
3064 if (newSize.width() > m_maxAutoSize.width()) {
3065 newSize.setWidth(m_maxAutoSize.width());
3066 horizonalScrollbarMode = ScrollbarAlwaysOn;
3068 ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff;
3069 if (newSize.height() > m_maxAutoSize.height()) {
3070 newSize.setHeight(m_maxAutoSize.height());
3071 verticalScrollbarMode = ScrollbarAlwaysOn;
3074 if (newSize == size)
3077 // While loading only allow the size to increase (to avoid twitching during intermediate smaller states)
3078 // unless autoresize has just been turned on or the maximum size is smaller than the current size.
3079 if (m_didRunAutosize && size.height() <= m_maxAutoSize.height() && size.width() <= m_maxAutoSize.width()
3080 && !frame().loader().isComplete() && (newSize.height() < size.height() || newSize.width() < size.width()))
3083 resize(newSize.width(), newSize.height());
3084 // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example,
3085 // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed).
3086 setVerticalScrollbarLock(false);
3087 setHorizontalScrollbarLock(false);
3088 setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true);
3091 m_autoSizeContentSize = contentsSize();
3093 if (m_autoSizeFixedMinimumHeight) {
3094 resize(m_autoSizeContentSize.width(), std::max(m_autoSizeFixedMinimumHeight, m_autoSizeContentSize.height()));
3095 document->updateLayoutIgnorePendingStylesheets();
3098 m_didRunAutosize = true;
3101 void FrameView::setAutoSizeFixedMinimumHeight(int fixedMinimumHeight)
3103 if (m_autoSizeFixedMinimumHeight == fixedMinimumHeight)
3106 m_autoSizeFixedMinimumHeight = fixedMinimumHeight;
3111 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
3113 if (!m_viewportRenderer)
3116 if (m_overflowStatusDirty) {
3117 m_horizontalOverflow = horizontalOverflow;
3118 m_verticalOverflow = verticalOverflow;
3119 m_overflowStatusDirty = false;
3123 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
3124 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
3126 if (horizontalOverflowChanged || verticalOverflowChanged) {
3127 m_horizontalOverflow = horizontalOverflow;
3128 m_verticalOverflow = verticalOverflow;
3130 RefPtr<OverflowEvent> overflowEvent = OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
3131 verticalOverflowChanged, verticalOverflow);
3132 overflowEvent->setTarget(m_viewportRenderer->element());
3134 frame().document()->enqueueOverflowEvent(overflowEvent.release());
3139 const Pagination& FrameView::pagination() const
3141 if (m_pagination != Pagination())
3142 return m_pagination;
3144 if (frame().isMainFrame())
3145 return frame().page()->pagination();
3147 return m_pagination;
3150 void FrameView::setPagination(const Pagination& pagination)
3152 if (m_pagination == pagination)
3155 m_pagination = pagination;
3157 frame().document()->styleResolverChanged(DeferRecalcStyle);
3160 IntRect FrameView::windowClipRect(bool clipToContents) const
3162 ASSERT(frame().view() == this);
3164 if (paintsEntireContents())
3165 return IntRect(IntPoint(), totalContentsSize());
3167 // Set our clip rect to be our contents.
3168 IntRect clipRect = contentsToWindow(visibleContentRect(clipToContents ? ExcludeScrollbars : IncludeScrollbars));
3169 if (!frame().ownerElement())
3172 // Take our owner element and get its clip rect.
3173 HTMLFrameOwnerElement* ownerElement = frame().ownerElement();
3174 if (FrameView* parentView = ownerElement->document().view())
3175 clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement, true));
3179 IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement, bool clipToLayerContents) const
3181 // The renderer can sometimes be null when style="display:none" interacts
3182 // with external content and plugins.
3183 if (!ownerElement->renderer())
3184 return windowClipRect();
3186 // If we have no layer, just return our window clip rect.
3187 const RenderLayer* enclosingLayer = ownerElement->renderer()->enclosingLayer();
3188 if (!enclosingLayer)
3189 return windowClipRect();
3191 // Apply the clip from the layer.
3193 if (clipToLayerContents)
3194 clipRect = pixelSnappedIntRect(enclosingLayer->childrenClipRect());
3196 clipRect = pixelSnappedIntRect(enclosingLayer->selfClipRect());
3197 clipRect = contentsToWindow(clipRect);
3198 return intersection(clipRect, windowClipRect());
3201 bool FrameView::isActive() const
3203 Page* page = frame().page();
3204 return page && page->focusController().isActive();
3207 bool FrameView::updatesScrollLayerPositionOnMainThread() const
3209 if (Page* page = frame().page()) {
3210 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
3211 return scrollingCoordinator->shouldUpdateScrollLayerPositionSynchronously();
3217 void FrameView::scrollTo(const IntSize& newOffset)
3219 LayoutSize offset = scrollOffset();
3220 ScrollView::scrollTo(newOffset);
3221 if (offset != scrollOffset())
3222 scrollPositionChanged();
3223 frame().loader().client().didChangeScrollOffset();
3226 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
3228 // Add in our offset within the FrameView.
3229 IntRect dirtyRect = rect;
3230 dirtyRect.moveBy(scrollbar->location());
3231 invalidateRect(dirtyRect);
3234 IntRect FrameView::windowResizerRect() const
3236 if (Page* page = frame().page())
3237 return page->chrome().windowResizerRect();
3241 float FrameView::visibleContentScaleFactor() const
3243 if (!frame().isMainFrame() || !frame().settings().delegatesPageScaling())
3246 return frame().page()->pageScaleFactor();
3249 void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
3251 if (!frame().isMainFrame())
3254 frame().page()->chrome().client().notifyScrollerThumbIsVisibleInRect(scrollerThumb);
3257 ScrollableArea* FrameView::enclosingScrollableArea() const
3259 // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer.
3263 IntRect FrameView::scrollableAreaBoundingBox() const
3265 RenderWidget* ownerRenderer = frame().ownerRenderer();
3269 return ownerRenderer->absoluteContentQuad().enclosingBoundingBox();
3272 bool FrameView::isScrollable()
3275 // 1) If there an actual overflow.
3276 // 2) display:none or visibility:hidden set to self or inherited.
3277 // 3) overflow{-x,-y}: hidden;
3278 // 4) scrolling: no;
3281 IntSize totalContentsSize = this->totalContentsSize();
3282 IntSize visibleContentSize = visibleContentRect().size();
3283 if ((totalContentsSize.height() <= visibleContentSize.height() && totalContentsSize.width() <= visibleContentSize.width()))
3287 HTMLFrameOwnerElement* owner = frame().ownerElement();
3288 if (owner && (!owner->renderer() || !owner->renderer()->visibleToHitTesting()))
3292 ScrollbarMode horizontalMode;
3293 ScrollbarMode verticalMode;
3294 calculateScrollbarModesForLayout(horizontalMode, verticalMode, RulesFromWebContentOnly);
3295 if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff)
3301 void FrameView::updateScrollableAreaSet()
3303 // That ensures that only inner frames are cached.
3304 FrameView* parentFrameView = this->parentFrameView();
3305 if (!parentFrameView)
3308 if (!isScrollable()) {
3309 parentFrameView->removeScrollableArea(this);
3313 parentFrameView->addScrollableArea(this);
3316 bool FrameView::shouldSuspendScrollAnimations() const
3318 return frame().loader().state() != FrameStateComplete;
3321 void FrameView::scrollbarStyleChanged(int newStyle, bool forceUpdate)
3323 if (!frame().isMainFrame())
3326 frame().page()->chrome().client().recommendedScrollbarStyleDidChange(newStyle);
3329 ScrollView::scrollbarStyleChanged(newStyle, forceUpdate);
3332 void FrameView::notifyPageThatContentAreaWillPaint() const
3334 Page* page = frame().page();
3338 contentAreaWillPaint();
3340 if (!m_scrollableAreas)
3343 for (auto& scrollableArea : *m_scrollableAreas)
3344 scrollableArea->contentAreaWillPaint();
3347 bool FrameView::scrollAnimatorEnabled() const
3349 #if ENABLE(SMOOTH_SCROLLING)
3350 if (Page* page = frame().page())
3351 return page->settings().scrollAnimatorEnabled();
3357 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
3358 void FrameView::updateAnnotatedRegions()
3360 Document* document = frame().document();
3361 if (!document->hasAnnotatedRegions())
3363 Vector<AnnotatedRegionValue> newRegions;
3364 document->renderBox()->collectAnnotatedRegions(newRegions);
3365 if (newRegions == document->annotatedRegions())
3367 document->setAnnotatedRegions(newRegions);
3368 Page* page = frame().page();
3371 page->chrome().client().annotatedRegionsChanged();
3375 void FrameView::updateScrollCorner()
3377 RenderElement* renderer = 0;
3378 RefPtr<RenderStyle> cornerStyle;
3379 IntRect cornerRect = scrollCornerRect();
3381 if (!cornerRect.isEmpty()) {
3382 // Try the <body> element first as a scroll corner source.
3383 Document* doc = frame().document();
3384 Element* body = doc ? doc->body() : 0;
3385 if (body && body->renderer()) {
3386 renderer = body->renderer();
3387 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), &renderer->style());
3391 // If the <body> didn't have a custom style, then the root element might.
3392 Element* docElement = doc ? doc->documentElement() : 0;
3393 if (docElement && docElement->renderer()) {
3394 renderer = docElement->renderer();
3395 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), &renderer->style());
3400 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
3401 if (RenderWidget* renderer = frame().ownerRenderer())
3402 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), &renderer->style());
3407 m_scrollCorner = nullptr;
3409 if (!m_scrollCorner) {
3410 m_scrollCorner = createRenderer<RenderScrollbarPart>(renderer->document(), cornerStyle.releaseNonNull());
3411 m_scrollCorner->initializeStyle();
3413 m_scrollCorner->setStyle(cornerStyle.releaseNonNull());
3414 invalidateScrollCorner(cornerRect);
3417 ScrollView::updateScrollCorner();
3420 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
3422 if (context->updatingControlTints()) {
3423 updateScrollCorner();
3427 if (m_scrollCorner) {
3428 if (frame().isMainFrame())
3429 context->fillRect(cornerRect, baseBackgroundColor(), ColorSpaceDeviceRGB);
3430 m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect);
3434 ScrollView::paintScrollCorner(context, cornerRect);
3437 void FrameView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
3439 if (bar->isCustomScrollbar() && frame().isMainFrame()) {
3440 IntRect toFill = bar->frameRect();
3441 toFill.intersect(rect);
3442 context->fillRect(toFill, baseBackgroundColor(), ColorSpaceDeviceRGB);
3445 ScrollView::paintScrollbar(context, bar, rect);
3448 Color FrameView::documentBackgroundColor() const
3450 // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of
3451 // the document and the body against the base background color of the frame view.
3452 // Background images are unfortunately impractical to include.
3454 // Return invalid Color objects whenever there is insufficient information.
3455 if (!frame().document())
3458 Element* htmlElement = frame().document()->documentElement();
3459 Element* bodyElement = frame().document()->body();
3461 // Start with invalid colors.
3462 Color htmlBackgroundColor;
3463 Color bodyBackgroundColor;
3464 if (htmlElement && htmlElement->renderer())
3465 htmlBackgroundColor = htmlElement->renderer()->style().visitedDependentColor(CSSPropertyBackgroundColor);
3466 if (bodyElement && bodyElement->renderer())
3467 bodyBackgroundColor = bodyElement->renderer()->style().visitedDependentColor(CSSPropertyBackgroundColor);
3469 if (!bodyBackgroundColor.isValid()) {
3470 if (!htmlBackgroundColor.isValid())
3472 return baseBackgroundColor().blend(htmlBackgroundColor);
3475 if (!htmlBackgroundColor.isValid())
3476 return baseBackgroundColor().blend(bodyBackgroundColor);
3478 // We take the aggregate of the base background color
3479 // the <html> background color, and the <body>
3480 // background color to find the document color. The
3481 // addition of the base background color is not
3482 // technically part of the document background, but it
3483 // otherwise poses problems when the aggregate is not
3485 return baseBackgroundColor().blend(htmlBackgroundColor).blend(bodyBackgroundColor);
3488 bool FrameView::hasCustomScrollbars() const
3490 for (auto& widget : children()) {
3491 if (widget->isFrameView()) {
3492 if (toFrameView(*widget).hasCustomScrollbars())
3494 } else if (widget->isScrollbar()) {
3495 if (toScrollbar(*widget).isCustomScrollbar())
3503 FrameView* FrameView::parentFrameView() const
3508 if (Frame* parentFrame = frame().tree().parent())
3509 return parentFrame->view();
3514 bool FrameView::isInChildFrameWithFrameFlattening() const
3516 if (!parent() || !frame().ownerElement())
3519 // Frame flattening applies when the owner element is either in a frameset or
3520 // an iframe with flattening parameters.
3521 if (frame().ownerElement()->hasTagName(iframeTag)) {
3522 RenderIFrame* iframeRenderer = toRenderIFrame(frame().ownerElement()->renderWidget());
3523 if (iframeRenderer->flattenFrame() || iframeRenderer->isSeamless())
3527 if (!frameFlatteningEnabled())
3530 if (frame().ownerElement()->hasTagName(frameTag))
3536 void FrameView::startLayoutAtMainFrameViewIfNeeded(bool allowSubtree)
3538 // When we start a layout at the child level as opposed to the topmost frame view and this child
3539 // frame requires flattening, we need to re-initiate the layout at the topmost view. Layout
3540 // will hit this view eventually.
3541 FrameView* parentView = parentFrameView();
3545 // In the middle of parent layout, no need to restart from topmost.
3546 if (parentView->m_nestedLayoutCount)
3549 // Parent tree is clean. Starting layout from it would have no effect.
3550 if (!parentView->needsLayout())
3553 while (parentView->parentFrameView())
3554 parentView = parentView->parentFrameView();
3556 parentView->layout(allowSubtree);
3558 RenderElement* root = m_layoutRoot ? m_layoutRoot : frame().document()->renderView();
3559 ASSERT_UNUSED(root, !root->needsLayout());
3562 void FrameView::updateControlTints()
3564 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
3565 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
3566 // This is only done if the theme supports control tinting. It's up to the theme and platform
3567 // to define when controls get the tint and to call this function when that changes.
3569 // Optimize the common case where we bring a window to the front while it's still empty.
3570 if (frame().document()->url().isEmpty())
3573 RenderView* renderView = this->renderView();
3574 if ((renderView && renderView->theme().supportsControlTints()) || hasCustomScrollbars())
3575 paintControlTints();
3578 void FrameView::paintControlTints()
3582 PlatformGraphicsContext* const noContext = 0;
3583 GraphicsContext context(noContext);
3584 context.setUpdatingControlTints(true);
3585 if (platformWidget())
3586 paintContents(&context, visibleContentRect());
3588 paint(&context, frameRect());
3591 bool FrameView::wasScrolledByUser() const
3593 return m_wasScrolledByUser;
3596 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
3598 if (m_inProgrammaticScroll)
3600 m_maintainScrollPositionAnchor = 0;
3601 if (m_wasScrolledByUser == wasScrolledByUser)
3603 m_wasScrolledByUser = wasScrolledByUser;
3604 adjustTiledBackingCoverage();
3607 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
3609 Document* document = frame().document();
3613 if (document->printing())
3614 fillWithRed = false; // Printing, don't fill with red (can't remember why).
3615 else if (frame().ownerElement())
3616 fillWithRed = false; // Subframe, don't fill with red.
3617 else if (isTransparent())
3618 fillWithRed = false; // Transparent, don't fill with red.
3619 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
3620 fillWithRed = false; // Selections are transparent, don't fill with red.
3621 else if (m_nodeToDraw)
3622 fillWithRed = false; // Element images are transparent, don't fill with red.
3627 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
3630 RenderView* renderView = this->renderView();