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 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 "BackForwardController.h"
32 #include "CachedImage.h"
33 #include "CachedResourceLoader.h"
35 #include "ChromeClient.h"
36 #include "DocumentMarkerController.h"
37 #include "EventHandler.h"
38 #include "FloatRect.h"
39 #include "FocusController.h"
40 #include "FontCache.h"
41 #include "FontLoader.h"
43 #include "FrameActionScheduler.h"
44 #include "FrameLoader.h"
45 #include "FrameLoaderClient.h"
46 #include "FrameTree.h"
47 #include "GraphicsContext.h"
48 #include "HTMLDocument.h"
49 #include "HTMLFrameElement.h"
50 #include "HTMLFrameSetElement.h"
51 #include "HTMLNames.h"
52 #include "HTMLPlugInImageElement.h"
53 #include "InspectorClient.h"
54 #include "InspectorController.h"
55 #include "InspectorInstrumentation.h"
56 #include "OverflowEvent.h"
57 #include "RenderArena.h"
58 #include "RenderEmbeddedObject.h"
59 #include "RenderFullScreen.h"
60 #include "RenderIFrame.h"
61 #include "RenderLayer.h"
62 #include "RenderLayerBacking.h"
63 #include "RenderPart.h"
64 #include "RenderScrollbar.h"
65 #include "RenderScrollbarPart.h"
66 #include "RenderTheme.h"
67 #include "RenderView.h"
68 #include "ScrollAnimator.h"
69 #include "ScrollingCoordinator.h"
71 #include "StyleResolver.h"
72 #include "TextResourceDecoder.h"
73 #include "TextStream.h"
75 #include <wtf/CurrentTime.h>
76 #include <wtf/TemporaryChange.h>
77 #include <wtf/UnusedParam.h>
79 #if USE(ACCELERATED_COMPOSITING)
80 #include "RenderLayerCompositor.h"
81 #include "TiledBacking.h"
85 #include "RenderSVGRoot.h"
86 #include "SVGDocument.h"
87 #include "SVGSVGElement.h"
90 #if USE(TILED_BACKING_STORE)
91 #include "TiledBackingStore.h"
94 #if ENABLE(TEXT_AUTOSIZING)
95 #include "TextAutosizer.h"
100 using namespace HTMLNames;
102 double FrameView::sCurrentPaintTimeStamp = 0.0;
105 // REPAINT_THROTTLING now chooses default values for throttling parameters.
106 // Should be removed when applications start using runtime configuration.
107 #if ENABLE(REPAINT_THROTTLING)
109 double FrameView::s_normalDeferredRepaintDelay = 0.016;
110 // Negative value would mean that first few repaints happen without a delay
111 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
112 // The delay grows on each repaint to this maximum value
113 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
114 // On each repaint the delay increses by this amount
115 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
117 // FIXME: Repaint throttling could be good to have on all platform.
118 // The balance between CPU use and repaint frequency will need some tuning for desktop.
119 // More hooks may be needed to reset the delay on things like GIF and CSS animations.
120 double FrameView::s_normalDeferredRepaintDelay = 0;
121 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
122 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
123 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
126 // While the browser window is being resized, resize events will be dispatched at most this often.
127 static const double minimumIntervalBetweenResizeEventsDuringLiveResizeInSeconds = 0.2;
129 // The maximum number of updateWidgets iterations that should be done before returning.
130 static const unsigned maxUpdateWidgetsIterations = 2;
132 static RenderLayer::UpdateLayerPositionsFlags updateLayerPositionFlags(RenderLayer* layer, bool isRelayoutingSubtree, bool didFullRepaint)
134 RenderLayer::UpdateLayerPositionsFlags flags = RenderLayer::defaultFlags;
135 if (didFullRepaint) {
136 flags &= ~RenderLayer::CheckForRepaint;
137 flags |= RenderLayer::NeedsFullRepaintInBacking;
139 if (isRelayoutingSubtree && layer->isPaginated())
140 flags |= RenderLayer::UpdatePagination;
144 Pagination::Mode paginationModeForRenderStyle(RenderStyle* style)
146 EOverflow overflow = style->overflowY();
147 if (overflow != OPAGEDX && overflow != OPAGEDY)
148 return Pagination::Unpaginated;
150 bool isHorizontalWritingMode = style->isHorizontalWritingMode();
151 TextDirection textDirection = style->direction();
152 WritingMode writingMode = style->writingMode();
154 // paged-x always corresponds to LeftToRightPaginated or RightToLeftPaginated. If the WritingMode
155 // is horizontal, then we use TextDirection to choose between those options. If the WritingMode
156 // is vertical, then the direction of the verticality dictates the choice.
157 if (overflow == OPAGEDX) {
158 if ((isHorizontalWritingMode && textDirection == LTR) || writingMode == LeftToRightWritingMode)
159 return Pagination::LeftToRightPaginated;
160 return Pagination::RightToLeftPaginated;
163 // paged-y always corresponds to TopToBottomPaginated or BottomToTopPaginated. If the WritingMode
164 // is horizontal, then the direction of the horizontality dictates the choice. If the WritingMode
165 // is vertical, then we use TextDirection to choose between those options.
166 if (writingMode == TopToBottomWritingMode || (!isHorizontalWritingMode && textDirection == RTL))
167 return Pagination::TopToBottomPaginated;
168 return Pagination::BottomToTopPaginated;
171 FrameView::FrameView(Frame* frame)
173 , m_canHaveScrollbars(true)
174 , m_slowRepaintObjectCount(0)
175 , m_delayedResizeEventTimer(this, &FrameView::delayedResizeEventTimerFired)
176 , m_layoutTimer(this, &FrameView::layoutTimerFired)
178 , m_inSynchronousPostLayout(false)
179 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
180 , m_isTransparent(false)
181 , m_baseBackgroundColor(Color::white)
182 , m_mediaType("screen")
183 , m_actionScheduler(adoptPtr(new FrameActionScheduler))
184 , m_overflowStatusDirty(true)
185 , m_viewportRenderer(0)
186 , m_wasScrolledByUser(false)
187 , m_inProgrammaticScroll(false)
188 , m_safeToPropagateScrollToParent(true)
189 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
190 , m_disableRepaints(0)
191 , m_isTrackingRepaints(false)
192 , m_shouldUpdateWhileOffscreen(true)
193 , m_deferSetNeedsLayouts(0)
194 , m_setNeedsLayoutWasDeferred(false)
196 , m_shouldAutoSize(false)
197 , m_inAutoSize(false)
198 , m_didRunAutosize(false)
201 #if ENABLE(CSS_FILTERS)
202 , m_hasSoftwareFilters(false)
207 // FIXME: Can m_frame ever be null here?
211 Page* page = m_frame->page();
215 if (m_frame == page->mainFrame()) {
216 ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed);
217 ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed);
221 PassRefPtr<FrameView> FrameView::create(Frame* frame)
223 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
225 return view.release();
228 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize)
230 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
231 view->Widget::setFrameRect(IntRect(view->location(), initialSize));
233 return view.release();
236 FrameView::~FrameView()
238 if (m_postLayoutTasksTimer.isActive()) {
239 m_postLayoutTasksTimer.stop();
240 m_actionScheduler->clear();
243 removeFromAXObjectCache();
246 // Custom scrollbars should already be destroyed at this point
247 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
248 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
250 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
251 setHasVerticalScrollbar(false);
253 ASSERT(!m_scrollCorner);
254 ASSERT(m_actionScheduler->isEmpty());
257 ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
258 RenderPart* renderer = m_frame->ownerRenderer();
259 if (renderer && renderer->widget() == this)
260 renderer->setWidget(0);
264 void FrameView::reset()
266 m_cannotBlitToWindow = false;
267 m_isOverlapped = false;
268 m_contentIsOpaque = false;
271 m_layoutTimer.stop();
273 m_delayedLayout = false;
274 m_doFullRepaint = true;
275 m_layoutSchedulingEnabled = true;
277 m_doingPreLayoutStyleUpdate = false;
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;
303 m_disableRepaints = 0;
306 void FrameView::removeFromAXObjectCache()
308 if (AXObjectCache* cache = axObjectCache())
312 void FrameView::clearFrame()
317 void FrameView::resetScrollbars()
319 // Reset the document's scrollbars back to our defaults before we yield the floor.
320 m_firstLayout = true;
321 setScrollbarsSuppressed(true);
322 if (m_canHaveScrollbars)
323 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
325 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
326 setScrollbarsSuppressed(false);
329 void FrameView::resetScrollbarsAndClearContentsSize()
333 setScrollbarsSuppressed(true);
334 setContentsSize(IntSize());
335 setScrollbarsSuppressed(false);
338 void FrameView::init()
342 m_margins = LayoutSize(-1, -1); // undefined
343 m_size = LayoutSize();
345 // Propagate the marginwidth/height and scrolling modes to the view.
346 Element* ownerElement = m_frame ? m_frame->ownerElement() : 0;
347 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
348 HTMLFrameElementBase* frameElt = static_cast<HTMLFrameElementBase*>(ownerElement);
349 if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
350 setCanHaveScrollbars(false);
351 LayoutUnit marginWidth = frameElt->marginWidth();
352 LayoutUnit marginHeight = frameElt->marginHeight();
353 if (marginWidth != -1)
354 setMarginWidth(marginWidth);
355 if (marginHeight != -1)
356 setMarginHeight(marginHeight);
360 void FrameView::prepareForDetach()
362 detachCustomScrollbars();
363 // When the view is no longer associated with a frame, it needs to be removed from the ax object cache
364 // right now, otherwise it won't be able to reach the topDocument()'s axObject cache later.
365 removeFromAXObjectCache();
367 if (m_frame && m_frame->page()) {
368 if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator())
369 scrollingCoordinator->willDestroyScrollableArea(this);
373 void FrameView::detachCustomScrollbars()
375 Scrollbar* horizontalBar = horizontalScrollbar();
376 if (horizontalBar && horizontalBar->isCustomScrollbar())
377 setHasHorizontalScrollbar(false);
379 Scrollbar* verticalBar = verticalScrollbar();
380 if (verticalBar && verticalBar->isCustomScrollbar())
381 setHasVerticalScrollbar(false);
383 if (m_scrollCorner) {
384 m_scrollCorner->destroy();
389 void FrameView::recalculateScrollbarOverlayStyle()
391 ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle();
392 ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault;
394 Color backgroundColor = documentBackgroundColor();
395 if (backgroundColor.isValid()) {
396 // Reduce the background color from RGB to a lightness value
397 // and determine which scrollbar style to use based on a lightness
399 double hue, saturation, lightness;
400 backgroundColor.getHSL(hue, saturation, lightness);
402 overlayStyle = ScrollbarOverlayStyleLight;
405 if (oldOverlayStyle != overlayStyle)
406 setScrollbarOverlayStyle(overlayStyle);
409 void FrameView::clear()
411 setCanBlitOnScroll(true);
416 if (RenderPart* renderer = m_frame->ownerRenderer())
417 renderer->viewCleared();
420 setScrollbarsSuppressed(true);
423 bool FrameView::didFirstLayout() const
425 return !m_firstLayout;
428 void FrameView::invalidateRect(const IntRect& rect)
432 hostWindow()->invalidateContentsAndRootView(rect, false /*immediate*/);
439 RenderPart* renderer = m_frame->ownerRenderer();
443 IntRect repaintRect = rect;
444 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
445 renderer->borderTop() + renderer->paddingTop());
446 renderer->repaintRectangle(repaintRect);
449 void FrameView::setFrameRect(const IntRect& newRect)
451 IntRect oldRect = frameRect();
452 if (newRect == oldRect)
455 #if ENABLE(TEXT_AUTOSIZING)
456 // Autosized font sizes depend on the width of the viewing area.
457 if (newRect.width() != oldRect.width()) {
458 Page* page = m_frame ? m_frame->page() : 0;
459 if (page && page->mainFrame() == m_frame && page->settings()->textAutosizingEnabled()) {
460 for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())
461 m_frame->document()->textAutosizer()->recalculateMultipliers();
466 ScrollView::setFrameRect(newRect);
468 updateScrollableAreaSet();
470 #if USE(ACCELERATED_COMPOSITING)
471 if (RenderView* renderView = this->renderView()) {
472 if (renderView->usesCompositing())
473 renderView->compositor()->frameViewDidChangeSize();
478 #if ENABLE(REQUEST_ANIMATION_FRAME)
479 bool FrameView::scheduleAnimation()
482 hostWindow()->scheduleAnimation();
489 void FrameView::setMarginWidth(LayoutUnit w)
491 // make it update the rendering area when set
492 m_margins.setWidth(w);
495 void FrameView::setMarginHeight(LayoutUnit h)
497 // make it update the rendering area when set
498 m_margins.setHeight(h);
501 bool FrameView::avoidScrollbarCreation() const
505 // with frame flattening no subframe can have scrollbars
506 // but we also cannot turn scrollbars off as we determine
507 // our flattening policy using that.
509 if (!m_frame->ownerElement())
512 if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
518 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
520 m_canHaveScrollbars = canHaveScrollbars;
521 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
524 void FrameView::updateCanHaveScrollbars()
528 scrollbarModes(hMode, vMode);
529 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
530 setCanHaveScrollbars(false);
532 setCanHaveScrollbars(true);
535 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
537 if (Settings* settings = m_frame->settings()) {
538 if (!settings->allowCustomScrollbarInMainFrame() && m_frame->page() && m_frame->page()->mainFrame() == m_frame)
539 return ScrollView::createScrollbar(orientation);
542 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
543 Document* doc = m_frame->document();
545 // Try the <body> element first as a scrollbar source.
546 Element* body = doc ? doc->body() : 0;
547 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
548 return RenderScrollbar::createCustomScrollbar(this, orientation, body);
550 // If the <body> didn't have a custom style, then the root element might.
551 Element* docElement = doc ? doc->documentElement() : 0;
552 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
553 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement);
555 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
556 RenderPart* frameRenderer = m_frame->ownerRenderer();
557 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
558 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
560 // Nobody set a custom style, so we just use a native scrollbar.
561 return ScrollView::createScrollbar(orientation);
564 void FrameView::setContentsSize(const IntSize& size)
566 if (size == contentsSize())
569 m_deferSetNeedsLayouts++;
571 ScrollView::setContentsSize(size);
572 ScrollView::contentsResized();
574 Page* page = frame() ? frame()->page() : 0;
578 updateScrollableAreaSet();
580 page->chrome()->contentsSizeChanged(frame(), size); //notify only
582 m_deferSetNeedsLayouts--;
584 if (!m_deferSetNeedsLayouts)
585 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
588 void FrameView::adjustViewSize()
590 RenderView* renderView = this->renderView();
594 ASSERT(m_frame->view() == this);
596 const IntRect rect = renderView->documentRect();
597 const IntSize& size = rect.size();
598 ScrollView::setScrollOrigin(IntPoint(-rect.x(), -rect.y()), !m_frame->document()->printing(), size == contentsSize());
600 setContentsSize(size);
603 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
605 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
606 // overflow:hidden and overflow:scroll on <body> as applying to the document's
607 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
608 // use the root element.
610 // To combat the inability to scroll on a page with overflow:hidden on the root when scaled, disregard hidden when
611 // there is a frameScaleFactor that is greater than one on the main frame. Also disregard hidden if there is a
614 bool overrideHidden = (m_frame->page() && m_frame->page()->mainFrame() == m_frame && m_frame->frameScaleFactor() > 1)
615 || (m_frame->page() && m_frame->page()->mainFrame() == m_frame && (headerHeight() || footerHeight()));
617 EOverflow overflowX = o->style()->overflowX();
618 EOverflow overflowY = o->style()->overflowY();
621 if (o->isSVGRoot()) {
622 // overflow is ignored in stand-alone SVG documents.
623 if (!toRenderSVGRoot(o)->isEmbeddedThroughFrameContainingSVGDocument())
633 hMode = ScrollbarAuto;
635 hMode = ScrollbarAlwaysOff;
638 hMode = ScrollbarAlwaysOn;
641 hMode = ScrollbarAuto;
644 // Don't set it at all.
651 vMode = ScrollbarAuto;
653 vMode = ScrollbarAlwaysOff;
656 vMode = ScrollbarAlwaysOn;
659 vMode = ScrollbarAuto;
662 // Don't set it at all. Values of OPAGEDX and OPAGEDY are handled by applyPaginationToViewPort().
666 m_viewportRenderer = o;
669 void FrameView::applyPaginationToViewport()
671 Document* document = m_frame->document();
672 Node* documentElement = document->documentElement();
673 RenderObject* documentRenderer = documentElement ? documentElement->renderer() : 0;
674 RenderObject* documentOrBodyRenderer = documentRenderer;
675 Node* body = document->body();
676 if (body && body->renderer()) {
677 if (body->hasTagName(bodyTag))
678 documentOrBodyRenderer = documentRenderer->style()->overflowX() == OVISIBLE && documentElement->hasTagName(htmlTag) ? body->renderer() : documentRenderer;
681 Pagination pagination;
683 if (!documentOrBodyRenderer) {
684 setPagination(pagination);
688 EOverflow overflowY = documentOrBodyRenderer->style()->overflowY();
689 if (overflowY == OPAGEDX || overflowY == OPAGEDY) {
690 pagination.mode = WebCore::paginationModeForRenderStyle(documentOrBodyRenderer->style());
691 pagination.gap = static_cast<unsigned>(documentOrBodyRenderer->style()->columnGap());
694 setPagination(pagination);
697 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy)
699 m_viewportRenderer = 0;
701 const HTMLFrameOwnerElement* owner = m_frame->ownerElement();
702 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
703 hMode = ScrollbarAlwaysOff;
704 vMode = ScrollbarAlwaysOff;
708 if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) {
709 hMode = ScrollbarAuto;
710 // Seamless documents begin with heights of 0; we special case that here
711 // to correctly render documents that don't need scrollbars.
712 IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size();
713 bool isSeamlessDocument = frame() && frame()->document() && frame()->document()->shouldDisplaySeamlesslyWithParent();
714 vMode = (isSeamlessDocument && !fullVisibleSize.height()) ? ScrollbarAlwaysOff : ScrollbarAuto;
716 hMode = ScrollbarAlwaysOff;
717 vMode = ScrollbarAlwaysOff;
721 Document* document = m_frame->document();
722 Node* documentElement = document->documentElement();
723 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
724 Node* body = document->body();
725 if (body && body->renderer()) {
726 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
727 vMode = ScrollbarAlwaysOff;
728 hMode = ScrollbarAlwaysOff;
729 } else if (body->hasTagName(bodyTag)) {
730 // It's sufficient to just check the X overflow,
731 // since it's illegal to have visible in only one direction.
732 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
733 applyOverflowToViewport(o, hMode, vMode);
735 } else if (rootRenderer)
736 applyOverflowToViewport(rootRenderer, hMode, vMode);
740 #if USE(ACCELERATED_COMPOSITING)
741 void FrameView::updateCompositingLayersAfterStyleChange()
743 RenderView* renderView = this->renderView();
747 // If we expect to update compositing after an incipient layout, don't do so here.
748 if (m_doingPreLayoutStyleUpdate || layoutPending() || renderView->needsLayout())
751 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
752 renderView->compositor()->cacheAcceleratedCompositingFlags();
753 renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterStyleChange);
756 void FrameView::updateCompositingLayersAfterLayout()
758 RenderView* renderView = this->renderView();
762 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
763 renderView->compositor()->cacheAcceleratedCompositingFlags();
764 renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterLayout);
767 void FrameView::clearBackingStores()
769 RenderView* renderView = this->renderView();
773 RenderLayerCompositor* compositor = renderView->compositor();
774 ASSERT(compositor->inCompositingMode());
775 compositor->enableCompositingMode(false);
776 compositor->clearBackingForAllLayers();
779 void FrameView::restoreBackingStores()
781 RenderView* renderView = this->renderView();
785 RenderLayerCompositor* compositor = renderView->compositor();
786 compositor->enableCompositingMode(true);
787 compositor->updateCompositingLayers(CompositingUpdateAfterLayout);
790 bool FrameView::usesCompositedScrolling() const
792 RenderView* renderView = this->renderView();
795 if (m_frame->settings() && m_frame->settings()->compositedScrollingForFramesEnabled())
796 return renderView->compositor()->inForcedCompositingMode();
800 GraphicsLayer* FrameView::layerForScrolling() const
802 RenderView* renderView = this->renderView();
805 return renderView->compositor()->scrollLayer();
808 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
810 RenderView* renderView = this->renderView();
813 return renderView->compositor()->layerForHorizontalScrollbar();
816 GraphicsLayer* FrameView::layerForVerticalScrollbar() const
818 RenderView* renderView = this->renderView();
821 return renderView->compositor()->layerForVerticalScrollbar();
824 GraphicsLayer* FrameView::layerForScrollCorner() const
826 RenderView* renderView = this->renderView();
829 return renderView->compositor()->layerForScrollCorner();
832 TiledBacking* FrameView::tiledBacking()
834 RenderView* renderView = this->renderView();
838 RenderLayerBacking* backing = renderView->layer()->backing();
842 return backing->graphicsLayer()->tiledBacking();
845 uint64_t FrameView::scrollLayerID() const
847 RenderView* renderView = this->renderView();
851 RenderLayerBacking* backing = renderView->layer()->backing();
855 return backing->scrollLayerID();
858 #if ENABLE(RUBBER_BANDING)
859 GraphicsLayer* FrameView::layerForOverhangAreas() const
861 RenderView* renderView = this->renderView();
864 return renderView->compositor()->layerForOverhangAreas();
867 GraphicsLayer* FrameView::setWantsLayerForTopOverHangArea(bool wantsLayer) const
869 RenderView* renderView = this->renderView();
873 return renderView->compositor()->updateLayerForTopOverhangArea(wantsLayer);
876 GraphicsLayer* FrameView::setWantsLayerForBottomOverHangArea(bool wantsLayer) const
878 RenderView* renderView = this->renderView();
882 return renderView->compositor()->updateLayerForBottomOverhangArea(wantsLayer);
885 GraphicsLayer* FrameView::setWantsLayerForHeader(bool wantsLayer) const
887 RenderView* renderView = this->renderView();
891 ASSERT(m_frame == m_frame->page()->mainFrame());
893 return renderView->compositor()->updateLayerForHeader(wantsLayer);
896 GraphicsLayer* FrameView::setWantsLayerForFooter(bool wantsLayer) const
898 RenderView* renderView = this->renderView();
902 ASSERT(m_frame == m_frame->page()->mainFrame());
904 return renderView->compositor()->updateLayerForFooter(wantsLayer);
907 #endif // ENABLE(RUBBER_BANDING)
909 bool FrameView::flushCompositingStateForThisFrame(Frame* rootFrameForFlush)
911 RenderView* renderView = this->renderView();
913 return true; // We don't want to keep trying to update layers if we have no renderer.
915 ASSERT(m_frame->view() == this);
917 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
918 // layer content to occur before layout has happened, which will cause paintContents() to bail.
922 // If we sync compositing layers and allow the repaint to be deferred, there is time for a
923 // visible flash to occur. Instead, stop the deferred repaint timer and repaint immediately.
924 flushDeferredRepaints();
926 renderView->compositor()->flushPendingLayerChanges(rootFrameForFlush == m_frame);
931 void FrameView::setNeedsOneShotDrawingSynchronization()
933 Page* page = frame() ? frame()->page() : 0;
935 page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
938 #endif // USE(ACCELERATED_COMPOSITING)
940 void FrameView::setHeaderHeight(int headerHeight)
942 if (m_frame && m_frame->page())
943 ASSERT(m_frame == m_frame->page()->mainFrame());
944 m_headerHeight = headerHeight;
946 if (RenderView* renderView = this->renderView())
947 renderView->setNeedsLayout(true);
950 void FrameView::setFooterHeight(int footerHeight)
952 if (m_frame && m_frame->page())
953 ASSERT(m_frame == m_frame->page()->mainFrame());
954 m_footerHeight = footerHeight;
956 if (RenderView* renderView = this->renderView())
957 renderView->setNeedsLayout(true);
960 bool FrameView::hasCompositedContent() const
962 #if USE(ACCELERATED_COMPOSITING)
963 if (RenderView* renderView = this->renderView())
964 return renderView->compositor()->inCompositingMode();
969 bool FrameView::hasCompositedContentIncludingDescendants() const
971 #if USE(ACCELERATED_COMPOSITING)
972 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
973 RenderView* renderView = frame->contentRenderer();
974 RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0;
976 if (compositor->inCompositingMode())
979 if (!RenderLayerCompositor::allowsIndependentlyCompositedFrames(this))
987 bool FrameView::hasCompositingAncestor() const
989 #if USE(ACCELERATED_COMPOSITING)
990 for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) {
991 if (FrameView* view = frame->view()) {
992 if (view->hasCompositedContent())
1000 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
1001 void FrameView::enterCompositingMode()
1003 #if USE(ACCELERATED_COMPOSITING)
1004 if (RenderView* renderView = this->renderView()) {
1005 renderView->compositor()->enableCompositingMode();
1007 renderView->compositor()->scheduleCompositingLayerUpdate();
1012 bool FrameView::isEnclosedInCompositingLayer() const
1014 #if USE(ACCELERATED_COMPOSITING)
1015 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
1016 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
1019 if (FrameView* parentView = parentFrameView())
1020 return parentView->isEnclosedInCompositingLayer();
1025 bool FrameView::flushCompositingStateIncludingSubframes()
1027 #if USE(ACCELERATED_COMPOSITING)
1028 bool allFramesFlushed = flushCompositingStateForThisFrame(m_frame.get());
1030 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame.get())) {
1031 bool flushed = child->view()->flushCompositingStateForThisFrame(m_frame.get());
1032 allFramesFlushed &= flushed;
1034 return allFramesFlushed;
1035 #else // USE(ACCELERATED_COMPOSITING)
1040 bool FrameView::isSoftwareRenderable() const
1042 #if USE(ACCELERATED_COMPOSITING)
1043 RenderView* renderView = this->renderView();
1044 return !renderView || !renderView->compositor()->has3DContent();
1050 void FrameView::didMoveOnscreen()
1052 contentAreaDidShow();
1055 void FrameView::willMoveOffscreen()
1057 contentAreaDidHide();
1060 void FrameView::setIsInWindow(bool isInWindow)
1062 if (RenderView* renderView = this->renderView())
1063 renderView->setIsInWindow(isInWindow);
1066 // Drawing models which cache painted content while out-of-window (WebKit2's composited drawing areas, etc.)
1067 // require that we repaint animated images to kickstart the animation loop.
1069 CachedImage::resumeAnimatingImagesForLoader(frame()->document()->cachedResourceLoader());
1073 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
1075 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
1078 static inline void collectFrameViewChildren(FrameView* frameView, Vector<RefPtr<FrameView> >& frameViews)
1080 const HashSet<RefPtr<Widget> >* viewChildren = frameView->children();
1081 ASSERT(viewChildren);
1083 const HashSet<RefPtr<Widget> >::iterator end = viewChildren->end();
1084 for (HashSet<RefPtr<Widget> >::iterator current = viewChildren->begin(); current != end; ++current) {
1085 Widget* widget = (*current).get();
1086 if (widget->isFrameView())
1087 frameViews.append(toFrameView(widget));
1091 inline void FrameView::forceLayoutParentViewIfNeeded()
1094 RenderPart* ownerRenderer = m_frame->ownerRenderer();
1095 if (!ownerRenderer || !ownerRenderer->frame())
1098 RenderBox* contentBox = embeddedContentBox();
1102 RenderSVGRoot* svgRoot = toRenderSVGRoot(contentBox);
1103 if (svgRoot->everHadLayout() && !svgRoot->needsLayout())
1106 // If the embedded SVG document appears the first time, the ownerRenderer has already finished
1107 // layout without knowing about the existence of the embedded SVG document, because RenderReplaced
1108 // embeddedContentBox() returns 0, as long as the embedded document isn't loaded yet. Before
1109 // bothering to lay out the SVG document, mark the ownerRenderer needing layout and ask its
1110 // FrameView for a layout. After that the RenderEmbeddedObject (ownerRenderer) carries the
1111 // correct size, which RenderSVGRoot::computeReplacedLogicalWidth/Height rely on, when laying
1112 // out for the first time, or when the RenderSVGRoot size has changed dynamically (eg. via <script>).
1113 RefPtr<FrameView> frameView = ownerRenderer->frame()->view();
1115 // Mark the owner renderer as needing layout.
1116 ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc();
1118 // Synchronously enter layout, to layout the view containing the host object/embed/iframe.
1120 frameView->layout();
1124 void FrameView::layout(bool allowSubtree)
1129 // Protect the view from being deleted during layout (in recalcStyle)
1130 RefPtr<FrameView> protector(this);
1132 // Every scroll that happens during layout is programmatic.
1133 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1135 bool inChildFrameLayoutWithFrameFlattening = isInChildFrameWithFrameFlattening();
1137 if (inChildFrameLayoutWithFrameFlattening) {
1138 if (doLayoutWithFrameFlattening(allowSubtree))
1142 m_layoutTimer.stop();
1143 m_delayedLayout = false;
1144 m_setNeedsLayoutWasDeferred = false;
1147 // FIXME: Do we need to set m_size.width here?
1148 // FIXME: Should we set m_size.height here too?
1149 m_size.setWidth(layoutWidth());
1153 // we shouldn't enter layout() while painting
1154 ASSERT(!isPainting());
1158 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
1160 if (!allowSubtree && m_layoutRoot) {
1161 m_layoutRoot->markContainingBlocksForLayout(false);
1165 ASSERT(m_frame->view() == this);
1167 Document* document = m_frame->document();
1168 ASSERT(!document->inPageCache());
1173 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1175 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_postLayoutTasksTimer.isActive() && !inChildFrameLayoutWithFrameFlattening) {
1176 // This is a new top-level layout. If there are any remaining tasks from the previous
1177 // layout, finish them now.
1178 m_inSynchronousPostLayout = true;
1179 performPostLayoutTasks();
1180 m_inSynchronousPostLayout = false;
1183 // Viewport-dependent media queries may cause us to need completely different style information.
1185 if (document->styleResolver()->affectedByViewportChange()) {
1186 document->styleResolverChanged(RecalcStyleImmediately);
1187 InspectorInstrumentation::mediaQueryResultChanged(document);
1189 document->evaluateMediaQueryList();
1191 // If there is any pagination to apply, it will affect the RenderView's style, so we should
1192 // take care of that now.
1193 applyPaginationToViewport();
1195 // Always ensure our style info is up-to-date. This can happen in situations where
1196 // the layout beats any sort of style recalc update that needs to occur.
1197 TemporaryChange<bool> changeDoingPreLayoutStyleUpdate(m_doingPreLayoutStyleUpdate, true);
1198 document->updateStyleIfNeeded();
1200 subtree = m_layoutRoot;
1202 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
1203 // so there's no point to continuing to layout
1204 if (protector->hasOneRef())
1207 root = subtree ? m_layoutRoot : document->renderer();
1209 // FIXME: Do we need to set m_size here?
1212 } // Reset m_layoutSchedulingEnabled to its previous value.
1213 // The only reason the scoping was closed here is allow fontCachePurgePreventer
1214 // to outlive the change and reset of m_layoutSchedulingEnabled.
1216 FontCachePurgePreventer fontCachePurgePreventer;
1219 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1221 m_nestedLayoutCount++;
1223 if (!m_layoutRoot) {
1224 Document* document = m_frame->document();
1225 Node* body = document->body();
1226 if (body && body->renderer()) {
1227 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
1228 body->renderer()->setChildNeedsLayout(true);
1229 } else if (body->hasTagName(bodyTag)) {
1230 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
1231 body->renderer()->setChildNeedsLayout(true);
1235 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1236 if (m_firstLayout && !m_frame->ownerElement())
1237 printf("Elapsed time before first layout: %d\n", document->elapsedTime());
1241 autoSizeIfEnabled();
1243 ScrollbarMode hMode;
1244 ScrollbarMode vMode;
1245 calculateScrollbarModesForLayout(hMode, vMode);
1247 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
1250 // Now set our scrollbar state for the layout.
1251 ScrollbarMode currentHMode = horizontalScrollbarMode();
1252 ScrollbarMode currentVMode = verticalScrollbarMode();
1254 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
1255 if (m_firstLayout) {
1256 setScrollbarsSuppressed(true);
1258 m_firstLayout = false;
1259 m_firstLayoutCallbackPending = true;
1260 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
1261 m_lastViewportSize = fixedLayoutSize();
1263 m_lastViewportSize = visibleContentRect(IncludeScrollbars).size();
1264 m_lastZoomFactor = root->style()->zoom();
1266 // Set the initial vMode to AlwaysOn if we're auto.
1267 if (vMode == ScrollbarAuto)
1268 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
1269 // Set the initial hMode to AlwaysOff if we're auto.
1270 if (hMode == ScrollbarAuto)
1271 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
1273 setScrollbarModes(hMode, vMode);
1274 setScrollbarsSuppressed(false, true);
1276 setScrollbarModes(hMode, vMode);
1279 LayoutSize oldSize = m_size;
1281 m_size = LayoutSize(layoutWidth(), layoutHeight());
1283 if (oldSize != m_size) {
1284 m_doFullRepaint = true;
1285 if (!m_firstLayout) {
1286 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
1287 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
1288 if (bodyRenderer && bodyRenderer->stretchesToViewport())
1289 bodyRenderer->setChildNeedsLayout(true);
1290 else if (rootRenderer && rootRenderer->stretchesToViewport())
1291 rootRenderer->setChildNeedsLayout(true);
1296 layer = root->enclosingLayer();
1298 m_actionScheduler->pause();
1301 bool disableLayoutState = false;
1303 RenderView* view = root->view();
1304 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
1305 view->pushLayoutState(root);
1307 LayoutStateDisabler layoutStateDisabler(disableLayoutState ? root->view() : 0);
1310 beginDeferredRepaints();
1311 forceLayoutParentViewIfNeeded();
1313 #if ENABLE(TEXT_AUTOSIZING)
1314 bool autosized = document->textAutosizer()->processSubtree(root);
1315 if (autosized && root->needsLayout())
1318 endDeferredRepaints();
1322 root->view()->popLayoutState(root);
1325 } // Reset m_layoutSchedulingEnabled to its previous value.
1327 bool neededFullRepaint = m_doFullRepaint;
1329 if (!subtree && !toRenderView(root)->printing())
1332 m_doFullRepaint = neededFullRepaint;
1334 // Now update the positions of all layers.
1335 beginDeferredRepaints();
1336 if (m_doFullRepaint)
1337 root->view()->repaint(); // FIXME: This isn't really right, since the RenderView doesn't fully encompass the visibleContentRect(). It just happens
1338 // to work out most of the time, since first layouts and printing don't have you scrolled anywhere.
1340 layer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPositionFlags(layer, subtree, m_doFullRepaint));
1342 endDeferredRepaints();
1344 #if USE(ACCELERATED_COMPOSITING)
1345 updateCompositingLayersAfterLayout();
1351 if (AXObjectCache* cache = root->document()->existingAXObjectCache())
1352 cache->postNotification(root, AXObjectCache::AXLayoutComplete, true);
1354 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
1355 updateAnnotatedRegions();
1358 ASSERT(!root->needsLayout());
1360 updateCanBlitOnScrollRecursively();
1362 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1363 updateOverflowStatus(layoutWidth() < contentsWidth(),
1364 layoutHeight() < contentsHeight());
1366 if (!m_postLayoutTasksTimer.isActive()) {
1367 if (!m_inSynchronousPostLayout) {
1368 if (inChildFrameLayoutWithFrameFlattening) {
1369 if (RenderView* renderView = this->renderView())
1370 renderView->updateWidgetPositions();
1372 m_inSynchronousPostLayout = true;
1373 // Calls resumeScheduledEvents()
1374 performPostLayoutTasks();
1375 m_inSynchronousPostLayout = false;
1379 if (!m_postLayoutTasksTimer.isActive() && (needsLayout() || m_inSynchronousPostLayout || inChildFrameLayoutWithFrameFlattening)) {
1380 // If we need layout or are already in a synchronous call to postLayoutTasks(),
1381 // defer widget updates and event dispatch until after we return. postLayoutTasks()
1382 // can make us need to update again, and we can get stuck in a nasty cycle unless
1383 // we call it through the timer here.
1384 m_postLayoutTasksTimer.startOneShot(0);
1385 if (needsLayout()) {
1386 m_actionScheduler->pause();
1391 m_actionScheduler->resume();
1394 InspectorInstrumentation::didLayout(cookie, root);
1396 m_nestedLayoutCount--;
1397 if (m_nestedLayoutCount)
1400 Page* page = frame() ? frame()->page() : 0;
1404 page->chrome()->client()->layoutUpdated(frame());
1407 RenderBox* FrameView::embeddedContentBox() const
1410 RenderView* renderView = this->renderView();
1414 RenderObject* firstChild = renderView->firstChild();
1415 if (!firstChild || !firstChild->isBox())
1418 // Curently only embedded SVG documents participate in the size-negotiation logic.
1419 if (firstChild->isSVGRoot())
1420 return toRenderBox(firstChild);
1426 void FrameView::addWidgetToUpdate(RenderObject* object)
1428 if (!m_widgetUpdateSet)
1429 m_widgetUpdateSet = adoptPtr(new RenderObjectSet);
1431 // Tell the DOM element that it needs a widget update.
1432 Node* node = object->node();
1433 if (node->hasTagName(objectTag) || node->hasTagName(embedTag)) {
1434 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(node);
1435 if (!pluginElement->needsCheckForSizeChange())
1436 pluginElement->setNeedsWidgetUpdate(true);
1439 m_widgetUpdateSet->add(object);
1442 void FrameView::removeWidgetToUpdate(RenderObject* object)
1444 if (!m_widgetUpdateSet)
1447 m_widgetUpdateSet->remove(object);
1450 void FrameView::setMediaType(const String& mediaType)
1452 m_mediaType = mediaType;
1455 String FrameView::mediaType() const
1457 // See if we have an override type.
1458 String overrideType = m_frame->loader()->client()->overrideMediaType();
1459 InspectorInstrumentation::applyEmulatedMedia(m_frame.get(), &overrideType);
1460 if (!overrideType.isNull())
1461 return overrideType;
1465 void FrameView::adjustMediaTypeForPrinting(bool printing)
1468 if (m_mediaTypeWhenNotPrinting.isNull())
1469 m_mediaTypeWhenNotPrinting = mediaType();
1470 setMediaType("print");
1472 if (!m_mediaTypeWhenNotPrinting.isNull())
1473 setMediaType(m_mediaTypeWhenNotPrinting);
1474 m_mediaTypeWhenNotPrinting = String();
1478 bool FrameView::useSlowRepaints(bool considerOverlap) const
1480 bool mustBeSlow = m_slowRepaintObjectCount > 0 || (platformWidget() && hasViewportConstrainedObjects());
1482 // FIXME: WidgetMac.mm makes the assumption that useSlowRepaints ==
1483 // m_contentIsOpaque, so don't take the fast path for composited layers
1484 // if they are a platform widget in order to get painting correctness
1485 // for transparent layers. See the comment in WidgetMac::paint.
1486 if (contentsInCompositedLayer() && !platformWidget())
1489 bool isOverlapped = m_isOverlapped && considerOverlap;
1491 if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque)
1494 if (FrameView* parentView = parentFrameView())
1495 return parentView->useSlowRepaints(considerOverlap);
1500 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1502 return useSlowRepaints(false);
1505 void FrameView::updateCanBlitOnScrollRecursively()
1507 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1508 if (FrameView* view = frame->view())
1509 view->setCanBlitOnScroll(!view->useSlowRepaints());
1513 bool FrameView::contentsInCompositedLayer() const
1515 #if USE(ACCELERATED_COMPOSITING)
1516 RenderView* renderView = this->renderView();
1517 if (renderView && renderView->isComposited()) {
1518 GraphicsLayer* layer = renderView->layer()->backing()->graphicsLayer();
1519 if (layer && layer->drawsContent())
1526 void FrameView::setCannotBlitToWindow()
1528 m_cannotBlitToWindow = true;
1529 updateCanBlitOnScrollRecursively();
1532 void FrameView::addSlowRepaintObject()
1534 if (!m_slowRepaintObjectCount++) {
1535 updateCanBlitOnScrollRecursively();
1537 if (Page* page = m_frame->page()) {
1538 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1539 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1544 void FrameView::removeSlowRepaintObject()
1546 ASSERT(m_slowRepaintObjectCount > 0);
1547 m_slowRepaintObjectCount--;
1548 if (!m_slowRepaintObjectCount) {
1549 updateCanBlitOnScrollRecursively();
1551 if (Page* page = m_frame->page()) {
1552 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1553 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1558 void FrameView::addViewportConstrainedObject(RenderObject* object)
1560 if (!m_viewportConstrainedObjects)
1561 m_viewportConstrainedObjects = adoptPtr(new ViewportConstrainedObjectSet);
1563 if (!m_viewportConstrainedObjects->contains(object)) {
1564 m_viewportConstrainedObjects->add(object);
1565 if (platformWidget())
1566 updateCanBlitOnScrollRecursively();
1568 if (Page* page = m_frame->page()) {
1569 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1570 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1575 void FrameView::removeViewportConstrainedObject(RenderObject* object)
1577 if (m_viewportConstrainedObjects && m_viewportConstrainedObjects->contains(object)) {
1578 m_viewportConstrainedObjects->remove(object);
1579 if (Page* page = m_frame->page()) {
1580 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1581 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1584 // FIXME: In addFixedObject() we only call this if there's a platform widget,
1585 // why isn't the same check being made here?
1586 updateCanBlitOnScrollRecursively();
1590 LayoutRect FrameView::viewportConstrainedVisibleContentRect() const
1592 LayoutRect viewportRect = visibleContentRect();
1593 viewportRect.setLocation(toPoint(scrollOffsetForFixedPosition()));
1594 return viewportRect;
1597 IntSize FrameView::scrollOffsetForFixedPosition(const IntRect& visibleContentRect, const IntSize& totalContentsSize, const IntPoint& scrollPosition, const IntPoint& scrollOrigin, float frameScaleFactor, bool fixedElementsLayoutRelativeToFrame, int headerHeight, int footerHeight)
1599 IntPoint constrainedPosition = ScrollableArea::constrainScrollPositionForOverhang(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, headerHeight, footerHeight);
1601 IntSize maxSize = totalContentsSize - visibleContentRect.size();
1603 float dragFactorX = (fixedElementsLayoutRelativeToFrame || !maxSize.width()) ? 1 : (totalContentsSize.width() - visibleContentRect.width() * frameScaleFactor) / maxSize.width();
1604 float dragFactorY = (fixedElementsLayoutRelativeToFrame || !maxSize.height()) ? 1 : (totalContentsSize.height() - visibleContentRect.height() * frameScaleFactor) / maxSize.height();
1606 return IntSize(constrainedPosition.x() * dragFactorX / frameScaleFactor, constrainedPosition.y() * dragFactorY / frameScaleFactor);
1609 IntSize FrameView::scrollOffsetForFixedPosition() const
1611 IntRect visibleContentRect = this->visibleContentRect();
1612 IntSize totalContentsSize = this->totalContentsSize();
1613 IntPoint scrollPosition = this->scrollPosition();
1614 IntPoint scrollOrigin = this->scrollOrigin();
1615 float frameScaleFactor = m_frame ? m_frame->frameScaleFactor() : 1;
1616 return scrollOffsetForFixedPosition(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, frameScaleFactor, fixedElementsLayoutRelativeToFrame(), headerHeight(), footerHeight());
1619 bool FrameView::fixedElementsLayoutRelativeToFrame() const
1622 if (!m_frame->settings())
1625 return m_frame->settings()->fixedElementsLayoutRelativeToFrame();
1628 IntPoint FrameView::lastKnownMousePosition() const
1630 return m_frame ? m_frame->eventHandler()->lastKnownMousePosition() : IntPoint();
1633 bool FrameView::shouldSetCursor() const
1635 Page* page = frame()->page();
1636 return page && page->isOnscreen() && page->focusController()->isActive();
1639 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1641 if (!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty()) {
1642 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1646 const bool isCompositedContentLayer = contentsInCompositedLayer();
1648 // Get the rects of the fixed objects visible in the rectToScroll
1649 Region regionToUpdate;
1650 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end();
1651 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) {
1652 RenderObject* renderer = *it;
1653 if (!renderer->style()->hasViewportConstrainedPosition())
1655 #if USE(ACCELERATED_COMPOSITING)
1656 if (renderer->isComposited())
1660 // Fixed items should always have layers.
1661 ASSERT(renderer->hasLayer());
1662 RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
1664 #if USE(ACCELERATED_COMPOSITING)
1665 if (layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForBoundsOutOfView
1666 || layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForNoVisibleContent) {
1667 // Don't invalidate for invisible fixed layers.
1672 #if ENABLE(CSS_FILTERS)
1673 if (layer->hasAncestorWithFilterOutsets()) {
1674 // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot
1675 // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
1679 IntRect updateRect = pixelSnappedIntRect(layer->repaintRectIncludingNonCompositingDescendants());
1680 updateRect = contentsToRootView(updateRect);
1681 if (!isCompositedContentLayer && clipsRepaints())
1682 updateRect.intersect(rectToScroll);
1683 if (!updateRect.isEmpty())
1684 regionToUpdate.unite(updateRect);
1688 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1690 // 2) update the area of fixed objects that has been invalidated
1691 Vector<IntRect> subRectsToUpdate = regionToUpdate.rects();
1692 size_t viewportConstrainedObjectsCount = subRectsToUpdate.size();
1693 for (size_t i = 0; i < viewportConstrainedObjectsCount; ++i) {
1694 IntRect updateRect = subRectsToUpdate[i];
1695 IntRect scrolledRect = updateRect;
1696 scrolledRect.move(scrollDelta);
1697 updateRect.unite(scrolledRect);
1698 #if USE(ACCELERATED_COMPOSITING)
1699 if (isCompositedContentLayer) {
1700 updateRect = rootViewToContents(updateRect);
1701 ASSERT(renderView());
1702 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
1706 if (clipsRepaints())
1707 updateRect.intersect(rectToScroll);
1708 hostWindow()->invalidateContentsAndRootView(updateRect, false);
1714 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1716 #if USE(ACCELERATED_COMPOSITING)
1717 if (contentsInCompositedLayer()) {
1718 IntRect updateRect = visibleContentRect();
1720 // Make sure to "apply" the scale factor here since we're converting from frame view
1721 // coordinates to layer backing coordinates.
1722 updateRect.scale(1 / m_frame->frameScaleFactor());
1724 ASSERT(renderView());
1725 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
1727 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1728 if (isEnclosedInCompositingLayer()) {
1729 LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1730 frameRenderer->borderTop() + frameRenderer->paddingTop(),
1731 visibleWidth(), visibleHeight());
1732 frameRenderer->repaintRectangle(rect);
1738 ScrollView::scrollContentsSlowPath(updateRect);
1741 // Note that this gets called at painting time.
1742 void FrameView::setIsOverlapped(bool isOverlapped)
1744 if (isOverlapped == m_isOverlapped)
1747 m_isOverlapped = isOverlapped;
1748 updateCanBlitOnScrollRecursively();
1750 #if USE(ACCELERATED_COMPOSITING)
1751 if (hasCompositedContentIncludingDescendants()) {
1752 // Overlap can affect compositing tests, so if it changes, we need to trigger
1753 // a layer update in the parent document.
1754 if (Frame* parentFrame = m_frame->tree()->parent()) {
1755 if (RenderView* parentView = parentFrame->contentRenderer()) {
1756 RenderLayerCompositor* compositor = parentView->compositor();
1757 compositor->setCompositingLayersNeedRebuild();
1758 compositor->scheduleCompositingLayerUpdate();
1762 if (RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) {
1763 // We also need to trigger reevaluation for this and all descendant frames,
1764 // since a frame uses compositing if any ancestor is compositing.
1765 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1766 if (RenderView* view = frame->contentRenderer()) {
1767 RenderLayerCompositor* compositor = view->compositor();
1768 compositor->setCompositingLayersNeedRebuild();
1769 compositor->scheduleCompositingLayerUpdate();
1777 bool FrameView::isOverlappedIncludingAncestors() const
1782 if (FrameView* parentView = parentFrameView()) {
1783 if (parentView->isOverlapped())
1790 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1792 if (contentIsOpaque == m_contentIsOpaque)
1795 m_contentIsOpaque = contentIsOpaque;
1796 updateCanBlitOnScrollRecursively();
1799 void FrameView::restoreScrollbar()
1801 setScrollbarsSuppressed(false);
1804 bool FrameView::scrollToFragment(const KURL& url)
1806 // If our URL has no ref, then we have no place we need to jump to.
1807 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1808 // and possibly repaint because :target pseudo class may have been
1809 // set (see bug 11321).
1810 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1813 String fragmentIdentifier = url.fragmentIdentifier();
1814 if (scrollToAnchor(fragmentIdentifier))
1817 // Try again after decoding the ref, based on the document's encoding.
1818 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1819 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1824 bool FrameView::scrollToAnchor(const String& name)
1826 ASSERT(m_frame->document());
1828 if (!m_frame->document()->haveStylesheetsLoaded()) {
1829 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1833 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1835 Element* anchorNode = m_frame->document()->findAnchor(name);
1837 // Setting to null will clear the current target.
1838 m_frame->document()->setCSSTarget(anchorNode);
1841 if (m_frame->document()->isSVGDocument()) {
1842 if (SVGSVGElement* svg = toSVGDocument(m_frame->document())->rootElement()) {
1843 svg->setupInitialView(name, anchorNode);
1850 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1851 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1854 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1856 // If the anchor accepts keyboard focus, move focus there to aid users relying on keyboard navigation.
1857 if (anchorNode && anchorNode->isFocusable())
1858 m_frame->document()->setFocusedNode(anchorNode);
1863 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1865 m_maintainScrollPositionAnchor = anchorNode;
1866 if (!m_maintainScrollPositionAnchor)
1869 // We need to update the layout before scrolling, otherwise we could
1870 // really mess things up if an anchor scroll comes at a bad moment.
1871 m_frame->document()->updateStyleIfNeeded();
1872 // Only do a layout if changes have occurred that make it necessary.
1873 RenderView* renderView = this->renderView();
1874 if (renderView && renderView->needsLayout())
1880 void FrameView::scrollElementToRect(Element* element, const IntRect& rect)
1882 m_frame->document()->updateLayoutIgnorePendingStylesheets();
1884 LayoutRect bounds = element->boundingBox();
1885 int centeringOffsetX = (rect.width() - bounds.width()) / 2;
1886 int centeringOffsetY = (rect.height() - bounds.height()) / 2;
1887 setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y()));
1890 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1892 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1893 m_maintainScrollPositionAnchor = 0;
1895 IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint);
1897 if (newScrollPosition == scrollPosition())
1900 if (requestScrollPositionUpdate(newScrollPosition))
1903 ScrollView::setScrollPosition(newScrollPosition);
1906 void FrameView::delegatesScrollingDidChange()
1908 #if USE(ACCELERATED_COMPOSITING)
1909 // When we switch to delgatesScrolling mode, we should destroy the scrolling/clipping layers in RenderLayerCompositor.
1910 if (hasCompositedContent())
1911 clearBackingStores();
1915 void FrameView::setFixedVisibleContentRect(const IntRect& visibleContentRect)
1917 bool visibleContentSizeDidChange = false;
1918 if (visibleContentRect.size() != this->fixedVisibleContentRect().size()) {
1919 // When the viewport size changes or the content is scaled, we need to
1920 // reposition the fixed and sticky positioned elements.
1921 setViewportConstrainedObjectsNeedLayout();
1922 visibleContentSizeDidChange = true;
1925 IntSize offset = scrollOffset();
1926 ScrollView::setFixedVisibleContentRect(visibleContentRect);
1927 if (offset != scrollOffset()) {
1928 repaintFixedElementsAfterScrolling();
1929 if (m_frame->page()->settings()->acceleratedCompositingForFixedPositionEnabled())
1930 updateFixedElementsAfterScrolling();
1931 scrollAnimator()->setCurrentPosition(scrollPosition());
1932 scrollPositionChanged();
1934 if (visibleContentSizeDidChange) {
1935 // Update the scroll-bars to calculate new page-step size.
1936 updateScrollbars(scrollOffset());
1938 frame()->loader()->client()->didChangeScrollOffset();
1941 void FrameView::setViewportConstrainedObjectsNeedLayout()
1943 if (!hasViewportConstrainedObjects())
1946 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end();
1947 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) {
1948 RenderObject* renderer = *it;
1949 renderer->setNeedsLayout(true);
1954 void FrameView::scrollPositionChangedViaPlatformWidget()
1956 repaintFixedElementsAfterScrolling();
1957 updateFixedElementsAfterScrolling();
1958 scrollPositionChanged();
1961 void FrameView::scrollPositionChanged()
1963 frame()->eventHandler()->sendScrollEvent();
1964 frame()->eventHandler()->dispatchFakeMouseMoveEventSoon();
1966 #if USE(ACCELERATED_COMPOSITING)
1967 if (RenderView* renderView = this->renderView()) {
1968 if (renderView->usesCompositing())
1969 renderView->compositor()->frameViewDidScroll();
1974 void FrameView::repaintFixedElementsAfterScrolling()
1976 // For fixed position elements, update widget positions and compositing layers after scrolling,
1977 // but only if we're not inside of layout.
1978 if (!m_nestedLayoutCount && hasViewportConstrainedObjects()) {
1979 if (RenderView* renderView = this->renderView()) {
1980 renderView->updateWidgetPositions();
1981 renderView->layer()->updateLayerPositionsAfterDocumentScroll();
1986 bool FrameView::shouldUpdateFixedElementsAfterScrolling()
1988 #if ENABLE(THREADED_SCROLLING)
1989 Page* page = m_frame->page();
1993 // If the scrolling thread is updating the fixed elements, then the FrameView should not update them as well.
1994 if (page->mainFrame() != m_frame)
1997 ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
1998 if (!scrollingCoordinator)
2001 if (!scrollingCoordinator->supportsFixedPositionLayers())
2004 if (scrollingCoordinator->shouldUpdateScrollLayerPositionOnMainThread())
2007 if (inProgrammaticScroll())
2015 void FrameView::updateFixedElementsAfterScrolling()
2017 #if USE(ACCELERATED_COMPOSITING)
2018 if (!shouldUpdateFixedElementsAfterScrolling())
2021 if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) {
2022 if (RenderView* renderView = this->renderView())
2023 renderView->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
2028 bool FrameView::shouldRubberBandInDirection(ScrollDirection direction) const
2030 Page* page = frame() ? frame()->page() : 0;
2032 return ScrollView::shouldRubberBandInDirection(direction);
2033 return page->chrome()->client()->shouldRubberBandInDirection(direction);
2036 bool FrameView::isRubberBandInProgress() const
2038 if (scrollbarsSuppressed())
2041 // If the scrolling thread updates the scroll position for this FrameView, then we should return
2042 // ScrollingCoordinator::isRubberBandInProgress().
2043 if (Page* page = m_frame->page()) {
2044 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
2045 if (!scrollingCoordinator->shouldUpdateScrollLayerPositionOnMainThread())
2046 return scrollingCoordinator->isRubberBandInProgress();
2050 // If the main thread updates the scroll position for this FrameView, we should return
2051 // ScrollAnimator::isRubberBandInProgress().
2052 if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
2053 return scrollAnimator->isRubberBandInProgress();
2058 bool FrameView::requestScrollPositionUpdate(const IntPoint& position)
2060 #if ENABLE(THREADED_SCROLLING)
2061 if (TiledBacking* tiledBacking = this->tiledBacking()) {
2062 IntRect visibleRect = visibleContentRect();
2063 visibleRect.setLocation(position);
2064 tiledBacking->prepopulateRect(visibleRect);
2067 if (Page* page = m_frame->page()) {
2068 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2069 return scrollingCoordinator->requestScrollPositionUpdate(this, position);
2072 UNUSED_PARAM(position);
2078 HostWindow* FrameView::hostWindow() const
2080 Page* page = frame() ? frame()->page() : 0;
2083 return page->chrome();
2086 const unsigned cRepaintRectUnionThreshold = 25;
2088 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
2090 ASSERT(!m_frame->ownerElement());
2092 if (m_isTrackingRepaints) {
2093 IntRect repaintRect = r;
2094 repaintRect.move(-scrollOffset());
2095 m_trackedRepaintRects.append(repaintRect);
2098 double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay();
2099 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
2100 IntRect paintRect = r;
2101 if (clipsRepaints() && !paintsEntireContents())
2102 paintRect.intersect(visibleContentRect());
2103 if (paintRect.isEmpty())
2105 if (m_repaintCount == cRepaintRectUnionThreshold) {
2106 IntRect unionedRect;
2107 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
2108 unionedRect.unite(pixelSnappedIntRect(m_repaintRects[i]));
2109 m_repaintRects.clear();
2110 m_repaintRects.append(unionedRect);
2112 if (m_repaintCount < cRepaintRectUnionThreshold)
2113 m_repaintRects.append(paintRect);
2115 m_repaintRects[0].unite(paintRect);
2118 if (!m_deferringRepaints)
2119 startDeferredRepaintTimer(delay);
2124 if (!shouldUpdate(immediate))
2127 #if USE(TILED_BACKING_STORE)
2128 if (frame()->tiledBackingStore()) {
2129 frame()->tiledBackingStore()->invalidate(r);
2133 ScrollView::repaintContentRectangle(r, immediate);
2136 void FrameView::contentsResized()
2138 ScrollView::contentsResized();
2142 void FrameView::visibleContentsResized()
2144 // We check to make sure the view is attached to a frame() as this method can
2145 // be triggered before the view is attached by Frame::createView(...) setting
2146 // various values such as setScrollBarModes(...) for example. An ASSERT is
2147 // triggered when a view is layout before being attached to a frame().
2148 if (!frame()->view())
2151 if (!useFixedLayout() && needsLayout())
2154 #if USE(ACCELERATED_COMPOSITING)
2155 if (RenderView* renderView = this->renderView()) {
2156 if (renderView->usesCompositing())
2157 renderView->compositor()->frameViewDidChangeSize();
2162 void FrameView::beginDeferredRepaints()
2164 Page* page = m_frame->page();
2165 if (page->mainFrame() != m_frame) {
2166 page->mainFrame()->view()->beginDeferredRepaints();
2170 m_deferringRepaints++;
2173 void FrameView::endDeferredRepaints()
2175 Page* page = m_frame->page();
2176 if (page->mainFrame() != m_frame) {
2177 page->mainFrame()->view()->endDeferredRepaints();
2181 ASSERT(m_deferringRepaints > 0);
2183 if (--m_deferringRepaints)
2186 if (m_deferredRepaintTimer.isActive())
2189 if (double delay = adjustedDeferredRepaintDelay()) {
2190 startDeferredRepaintTimer(delay);
2194 doDeferredRepaints();
2197 void FrameView::startDeferredRepaintTimer(double delay)
2199 if (m_deferredRepaintTimer.isActive())
2202 if (m_disableRepaints)
2205 m_deferredRepaintTimer.startOneShot(delay);
2208 void FrameView::handleLoadCompleted()
2210 // Once loading has completed, allow autoSize one last opportunity to
2211 // reduce the size of the frame.
2212 autoSizeIfEnabled();
2213 if (shouldUseLoadTimeDeferredRepaintDelay())
2215 m_deferredRepaintDelay = s_normalDeferredRepaintDelay;
2216 flushDeferredRepaints();
2219 void FrameView::flushDeferredRepaints()
2221 if (!m_deferredRepaintTimer.isActive())
2223 m_deferredRepaintTimer.stop();
2224 doDeferredRepaints();
2227 void FrameView::doDeferredRepaints()
2229 if (m_disableRepaints)
2232 ASSERT(!m_deferringRepaints);
2233 if (!shouldUpdate()) {
2234 m_repaintRects.clear();
2238 unsigned size = m_repaintRects.size();
2239 for (unsigned i = 0; i < size; i++) {
2240 #if USE(TILED_BACKING_STORE)
2241 if (frame()->tiledBackingStore()) {
2242 frame()->tiledBackingStore()->invalidate(pixelSnappedIntRect(m_repaintRects[i]));
2246 ScrollView::repaintContentRectangle(pixelSnappedIntRect(m_repaintRects[i]), false);
2248 m_repaintRects.clear();
2251 updateDeferredRepaintDelayAfterRepaint();
2254 bool FrameView::shouldUseLoadTimeDeferredRepaintDelay() const
2256 // Don't defer after the initial load of the page has been completed.
2257 if (m_frame->tree()->top()->loader()->isComplete())
2259 Document* document = m_frame->document();
2262 if (document->parsing())
2264 if (document->cachedResourceLoader()->requestCount())
2269 void FrameView::updateDeferredRepaintDelayAfterRepaint()
2271 if (!shouldUseLoadTimeDeferredRepaintDelay()) {
2272 m_deferredRepaintDelay = s_normalDeferredRepaintDelay;
2275 double incrementedRepaintDelay = m_deferredRepaintDelay + s_deferredRepaintDelayIncrementDuringLoading;
2276 m_deferredRepaintDelay = std::min(incrementedRepaintDelay, s_maxDeferredRepaintDelayDuringLoading);
2279 void FrameView::resetDeferredRepaintDelay()
2281 m_deferredRepaintDelay = 0;
2282 if (m_deferredRepaintTimer.isActive()) {
2283 m_deferredRepaintTimer.stop();
2284 if (!m_deferringRepaints)
2285 doDeferredRepaints();
2287 #if USE(ACCELERATED_COMPOSITING)
2288 if (RenderView* view = renderView())
2289 view->compositor()->disableLayerFlushThrottlingTemporarilyForInteraction();
2293 double FrameView::adjustedDeferredRepaintDelay() const
2295 ASSERT(!m_deferringRepaints);
2296 if (!m_deferredRepaintDelay)
2298 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
2299 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
2302 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
2304 doDeferredRepaints();
2307 void FrameView::beginDisableRepaints()
2309 m_disableRepaints++;
2312 void FrameView::endDisableRepaints()
2314 ASSERT(m_disableRepaints > 0);
2315 m_disableRepaints--;
2318 void FrameView::updateLayerFlushThrottlingInAllFrames(bool isLoadProgressing)
2320 #if USE(ACCELERATED_COMPOSITING)
2321 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
2322 if (RenderView* renderView = frame->contentRenderer())
2323 renderView->compositor()->setLayerFlushThrottlingEnabled(isLoadProgressing);
2326 UNUSED_PARAM(isLoadProgressing);
2330 void FrameView::adjustTiledBackingCoverage()
2332 #if USE(ACCELERATED_COMPOSITING)
2333 RenderView* renderView = this->renderView();
2334 if (renderView && renderView->layer()->backing())
2335 renderView->layer()->backing()->adjustTiledBackingCoverage();
2339 void FrameView::layoutTimerFired(Timer<FrameView>*)
2341 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2342 if (!m_frame->document()->ownerElement())
2343 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
2348 void FrameView::scheduleRelayout()
2350 // FIXME: We should assert the page is not in the page cache, but that is causing
2351 // too many false assertions. See <rdar://problem/7218118>.
2352 ASSERT(m_frame->view() == this);
2355 m_layoutRoot->markContainingBlocksForLayout(false);
2358 if (!m_layoutSchedulingEnabled)
2362 if (!m_frame->document()->shouldScheduleLayout())
2364 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2365 // When frame flattening is enabled, the contents of the frame could affect the layout of the parent frames.
2366 // Also invalidate parent frame starting from the owner element of this frame.
2367 if (m_frame->ownerRenderer() && isInChildFrameWithFrameFlattening())
2368 m_frame->ownerRenderer()->setNeedsLayout(true, MarkContainingBlockChain);
2370 int delay = m_frame->document()->minimumLayoutDelay();
2371 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
2372 unscheduleRelayout();
2373 if (m_layoutTimer.isActive())
2376 m_delayedLayout = delay != 0;
2378 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2379 if (!m_frame->document()->ownerElement())
2380 printf("Scheduling layout for %d\n", delay);
2383 m_layoutTimer.startOneShot(delay * 0.001);
2386 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
2388 for (RenderObject* r = descendant; r; r = r->container()) {
2395 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
2397 ASSERT(m_frame->view() == this);
2399 RenderView* renderView = this->renderView();
2400 if (renderView && renderView->needsLayout()) {
2402 relayoutRoot->markContainingBlocksForLayout(false);
2406 if (layoutPending() || !m_layoutSchedulingEnabled) {
2407 if (m_layoutRoot != relayoutRoot) {
2408 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
2409 // Keep the current root
2410 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
2411 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2412 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
2413 // Re-root at relayoutRoot
2414 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
2415 m_layoutRoot = relayoutRoot;
2416 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2417 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2419 // Just do a full relayout
2421 m_layoutRoot->markContainingBlocksForLayout(false);
2423 relayoutRoot->markContainingBlocksForLayout(false);
2424 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2427 } else if (m_layoutSchedulingEnabled) {
2428 int delay = m_frame->document()->minimumLayoutDelay();
2429 m_layoutRoot = relayoutRoot;
2430 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2431 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2432 m_delayedLayout = delay != 0;
2433 m_layoutTimer.startOneShot(delay * 0.001);
2437 bool FrameView::layoutPending() const
2439 return m_layoutTimer.isActive();
2442 bool FrameView::needsLayout() const
2444 // This can return true in cases where the document does not have a body yet.
2445 // Document::shouldScheduleLayout takes care of preventing us from scheduling
2446 // layout in that case.
2450 RenderView* renderView = this->renderView();
2451 return layoutPending()
2452 || (renderView && renderView->needsLayout())
2454 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
2457 void FrameView::setNeedsLayout()
2459 if (m_deferSetNeedsLayouts) {
2460 m_setNeedsLayoutWasDeferred = true;
2464 if (RenderView* renderView = this->renderView())
2465 renderView->setNeedsLayout(true);
2468 void FrameView::unscheduleRelayout()
2470 if (!m_layoutTimer.isActive())
2473 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2474 if (!m_frame->document()->ownerElement())
2475 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
2478 m_layoutTimer.stop();
2479 m_delayedLayout = false;
2482 #if ENABLE(REQUEST_ANIMATION_FRAME)
2483 void FrameView::serviceScriptedAnimations(double monotonicAnimationStartTime)
2485 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext()) {
2486 frame->view()->serviceScrollAnimations();
2487 frame->animation()->serviceAnimations();
2490 Vector<RefPtr<Document> > documents;
2491 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext())
2492 documents.append(frame->document());
2494 for (size_t i = 0; i < documents.size(); ++i)
2495 documents[i]->serviceScriptedAnimations(monotonicAnimationStartTime);
2499 bool FrameView::isTransparent() const
2501 return m_isTransparent;
2504 void FrameView::setTransparent(bool isTransparent)
2506 m_isTransparent = isTransparent;
2509 bool FrameView::hasOpaqueBackground() const
2511 return !m_isTransparent && !m_baseBackgroundColor.hasAlpha();
2514 Color FrameView::baseBackgroundColor() const
2516 return m_baseBackgroundColor;
2519 void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
2521 if (!backgroundColor.isValid())
2522 m_baseBackgroundColor = Color::white;
2524 m_baseBackgroundColor = backgroundColor;
2526 recalculateScrollbarOverlayStyle();
2529 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
2531 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
2532 if (FrameView* view = frame->view()) {
2533 view->setTransparent(transparent);
2534 view->setBaseBackgroundColor(backgroundColor);
2539 bool FrameView::shouldUpdateWhileOffscreen() const
2541 return m_shouldUpdateWhileOffscreen;
2544 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
2546 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
2549 bool FrameView::shouldUpdate(bool immediateRequested) const
2551 if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen())
2556 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
2558 m_actionScheduler->scheduleEvent(event, eventTarget);
2561 void FrameView::pauseScheduledEvents()
2563 m_actionScheduler->pause();
2566 void FrameView::resumeScheduledEvents()
2568 m_actionScheduler->resume();
2571 void FrameView::scrollToAnchor()
2573 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
2577 if (!anchorNode->renderer())
2581 if (anchorNode != m_frame->document())
2582 rect = anchorNode->boundingBox();
2584 // Scroll nested layers and frames to reveal the anchor.
2585 // Align to the top and to the closest side (this matches other browsers).
2586 anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
2588 if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache())
2589 cache->handleScrolledToAnchor(anchorNode.get());
2591 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
2592 m_maintainScrollPositionAnchor = anchorNode;
2595 void FrameView::updateWidget(RenderObject* object)
2597 ASSERT(!object->node() || object->node()->isElementNode());
2598 Element* ownerElement = toElement(object->node());
2599 // The object may have already been destroyed (thus node cleared),
2600 // but FrameView holds a manual ref, so it won't have been deleted.
2601 ASSERT(m_widgetUpdateSet->contains(object));
2605 if (object->isEmbeddedObject()) {
2606 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
2607 // No need to update if it's already crashed or known to be missing.
2608 if (embeddedObject->showsUnavailablePluginIndicator())
2611 if (object->isSnapshottedPlugIn()) {
2612 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag)) {
2613 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement);
2614 pluginElement->checkSnapshotStatus();
2619 // FIXME: This could turn into a real virtual dispatch if we defined
2620 // updateWidget(PluginCreationOption) on HTMLElement.
2621 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag) || ownerElement->hasTagName(appletTag)) {
2622 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement);
2623 if (pluginElement->needsCheckForSizeChange()) {
2624 pluginElement->checkSnapshotStatus();
2627 if (pluginElement->needsWidgetUpdate())
2628 pluginElement->updateWidget(CreateAnyWidgetType);
2630 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
2631 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
2632 else if (ownerElement->isMediaElement())
2633 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
2636 ASSERT_NOT_REACHED();
2638 // Caution: it's possible the object was destroyed again, since loading a
2639 // plugin may run any arbitrary JavaScript.
2640 embeddedObject->updateWidgetPosition();
2644 bool FrameView::updateWidgets()
2646 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
2649 size_t size = m_widgetUpdateSet->size();
2651 Vector<RenderObject*> objects;
2652 objects.reserveInitialCapacity(size);
2654 RenderObjectSet::const_iterator end = m_widgetUpdateSet->end();
2655 for (RenderObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
2656 RenderObject* object = *it;
2657 objects.uncheckedAppend(object);
2658 if (object->isEmbeddedObject()) {
2659 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
2660 embeddedObject->ref();
2664 for (size_t i = 0; i < size; ++i) {
2665 RenderObject* object = objects[i];
2666 updateWidget(object);
2667 m_widgetUpdateSet->remove(object);
2670 RenderArena* arena = m_frame->document()->renderArena();
2671 for (size_t i = 0; i < size; ++i) {
2672 RenderObject* object = objects[i];
2673 if (object->isEmbeddedObject()) {
2674 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
2675 embeddedObject->deref(arena);
2679 return m_widgetUpdateSet->isEmpty();
2682 void FrameView::flushAnyPendingPostLayoutTasks()
2684 if (!m_postLayoutTasksTimer.isActive())
2687 performPostLayoutTasks();
2690 void FrameView::performPostLayoutTasks()
2692 m_postLayoutTasksTimer.stop();
2694 m_frame->selection()->setCaretRectNeedsUpdate();
2695 m_frame->selection()->updateAppearance();
2697 LayoutMilestones milestonesOfInterest = 0;
2698 LayoutMilestones milestonesAchieved = 0;
2699 Page* page = m_frame->page();
2701 milestonesOfInterest = page->layoutMilestones();
2703 if (m_nestedLayoutCount <= 1) {
2704 if (m_firstLayoutCallbackPending) {
2705 m_firstLayoutCallbackPending = false;
2706 m_frame->loader()->didFirstLayout();
2707 if (milestonesOfInterest & DidFirstLayout)
2708 milestonesAchieved |= DidFirstLayout;
2710 if (page->mainFrame() == m_frame)
2711 page->startCountingRelevantRepaintedObjects();
2715 // Ensure that we always send this eventually.
2716 if (!m_frame->document()->parsing() && m_frame->loader()->stateMachine()->committedFirstRealDocumentLoad())
2717 m_isVisuallyNonEmpty = true;
2719 // If the layout was done with pending sheets, we are not in fact visually non-empty yet.
2720 if (m_isVisuallyNonEmpty && !m_frame->document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) {
2721 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
2722 if (milestonesOfInterest & DidFirstVisuallyNonEmptyLayout)
2723 milestonesAchieved |= DidFirstVisuallyNonEmptyLayout;
2727 m_frame->loader()->didLayout(milestonesAchieved);
2728 #if ENABLE(FONT_LOAD_EVENTS)
2729 if (RuntimeEnabledFeatures::fontLoadEventsEnabled())
2730 m_frame->document()->fontloader()->didLayout();
2733 // FIXME: We should consider adding DidLayout as a LayoutMilestone. That would let us merge this
2734 // with didLayout(LayoutMilestones).
2735 m_frame->loader()->client()->dispatchDidLayout();
2737 RenderView* renderView = this->renderView();
2739 renderView->updateWidgetPositions();
2741 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
2742 if (updateWidgets())
2747 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2748 scrollingCoordinator->frameViewLayoutUpdated(this);
2751 #if USE(ACCELERATED_COMPOSITING)
2752 if (renderView && renderView->usesCompositing())
2753 renderView->compositor()->frameViewDidLayout();
2758 m_actionScheduler->resume();
2760 if (renderView && !renderView->printing()) {
2761 IntSize currentSize;
2762 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
2763 currentSize = fixedLayoutSize();
2765 currentSize = visibleContentRect(IncludeScrollbars).size();
2766 float currentZoomFactor = renderView->style()->zoom();
2767 bool resized = !m_firstLayout && (currentSize != m_lastViewportSize || currentZoomFactor != m_lastZoomFactor);
2768 m_lastViewportSize = currentSize;
2769 m_lastZoomFactor = currentZoomFactor;
2772 scheduleResizeEvent();
2779 void FrameView::sendResizeEvent()
2784 m_frame->eventHandler()->sendResizeEvent();
2786 #if ENABLE(INSPECTOR)
2787 if (InspectorInstrumentation::hasFrontends()) {
2788 if (Page* page = m_frame->page()) {
2789 if (page->mainFrame() == m_frame) {
2790 if (InspectorClient* inspectorClient = page->inspectorController()->inspectorClient())
2791 inspectorClient->didResizeMainFrame(m_frame.get());
2798 void FrameView::delayedResizeEventTimerFired(Timer<FrameView>*)
2803 void FrameView::willStartLiveResize()
2805 ScrollView::willStartLiveResize();
2806 adjustTiledBackingCoverage();
2809 void FrameView::willEndLiveResize()
2811 ScrollableArea::willEndLiveResize();
2812 if (m_delayedResizeEventTimer.isActive()) {
2813 m_delayedResizeEventTimer.stop();
2816 adjustTiledBackingCoverage();
2819 void FrameView::scheduleResizeEvent()
2821 if (!m_delayedResizeEventTimer.isActive())
2822 m_delayedResizeEventTimer.startOneShot(minimumIntervalBetweenResizeEventsDuringLiveResizeInSeconds);
2825 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
2827 performPostLayoutTasks();
2830 void FrameView::autoSizeIfEnabled()
2832 if (!m_shouldAutoSize)
2838 TemporaryChange<bool> changeInAutoSize(m_inAutoSize, true);
2840 Document* document = frame()->document();
2844 RenderView* documentView = document->renderView();
2845 Element* documentElement = document->documentElement();
2846 if (!documentView || !documentElement)
2849 // Start from the minimum size and allow it to grow.
2850 resize(m_minAutoSize.width(), m_minAutoSize.height());
2852 IntSize size = frameRect().size();
2854 // Do the resizing twice. The first time is basically a rough calculation using the preferred width
2855 // which may result in a height change during the second iteration.
2856 for (int i = 0; i < 2; i++) {
2857 // Update various sizes including contentsSize, scrollHeight, etc.
2858 document->updateLayoutIgnorePendingStylesheets();
2859 int width = documentView->minPreferredLogicalWidth();
2860 int height = documentView->documentRect().height();
2861 IntSize newSize(width, height);
2863 // Check to see if a scrollbar is needed for a given dimension and
2864 // if so, increase the other dimension to account for the scrollbar.
2865 // Since the dimensions are only for the view rectangle, once a
2866 // dimension exceeds the maximum, there is no need to increase it further.
2867 if (newSize.width() > m_maxAutoSize.width()) {
2868 RefPtr<Scrollbar> localHorizontalScrollbar = horizontalScrollbar();
2869 if (!localHorizontalScrollbar)
2870 localHorizontalScrollbar = createScrollbar(HorizontalScrollbar);
2871 if (!localHorizontalScrollbar->isOverlayScrollbar())
2872 newSize.setHeight(newSize.height() + localHorizontalScrollbar->height());
2874 // Don't bother checking for a vertical scrollbar because the width is at
2875 // already greater the maximum.
2876 } else if (newSize.height() > m_maxAutoSize.height()) {
2877 RefPtr<Scrollbar> localVerticalScrollbar = verticalScrollbar();
2878 if (!localVerticalScrollbar)
2879 localVerticalScrollbar = createScrollbar(VerticalScrollbar);
2880 if (!localVerticalScrollbar->isOverlayScrollbar())
2881 newSize.setWidth(newSize.width() + localVerticalScrollbar->width());
2883 // Don't bother checking for a horizontal scrollbar because the height is
2884 // already greater the maximum.
2887 // Ensure the size is at least the min bounds.
2888 newSize = newSize.expandedTo(m_minAutoSize);
2890 // Bound the dimensions by the max bounds and determine what scrollbars to show.
2891 ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff;
2892 if (newSize.width() > m_maxAutoSize.width()) {
2893 newSize.setWidth(m_maxAutoSize.width());
2894 horizonalScrollbarMode = ScrollbarAlwaysOn;
2896 ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff;
2897 if (newSize.height() > m_maxAutoSize.height()) {
2898 newSize.setHeight(m_maxAutoSize.height());
2899 verticalScrollbarMode = ScrollbarAlwaysOn;
2902 if (newSize == size)
2905 // While loading only allow the size to increase (to avoid twitching during intermediate smaller states)
2906 // unless autoresize has just been turned on or the maximum size is smaller than the current size.
2907 if (m_didRunAutosize && size.height() <= m_maxAutoSize.height() && size.width() <= m_maxAutoSize.width()
2908 && !frame()->loader()->isComplete() && (newSize.height() < size.height() || newSize.width() < size.width()))
2911 resize(newSize.width(), newSize.height());
2912 // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example,
2913 // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed).
2914 setVerticalScrollbarLock(false);
2915 setHorizontalScrollbarLock(false);
2916 setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true);
2918 m_didRunAutosize = true;
2921 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
2923 if (!m_viewportRenderer)
2926 if (m_overflowStatusDirty) {
2927 m_horizontalOverflow = horizontalOverflow;
2928 m_verticalOverflow = verticalOverflow;
2929 m_overflowStatusDirty = false;
2933 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
2934 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
2936 if (horizontalOverflowChanged || verticalOverflowChanged) {
2937 m_horizontalOverflow = horizontalOverflow;
2938 m_verticalOverflow = verticalOverflow;
2940 m_actionScheduler->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
2941 verticalOverflowChanged, verticalOverflow),
2942 m_viewportRenderer->node());
2947 const Pagination& FrameView::pagination() const
2949 if (m_pagination != Pagination())
2950 return m_pagination;
2952 if (Page* page = m_frame->page()) {
2953 if (page->mainFrame() == m_frame)
2954 return page->pagination();
2957 return m_pagination;
2960 void FrameView::setPagination(const Pagination& pagination)
2962 if (m_pagination == pagination)
2965 m_pagination = pagination;
2968 m_frame->document()->styleResolverChanged(DeferRecalcStyle);
2971 IntRect FrameView::windowClipRect(bool clipToContents) const
2973 ASSERT(m_frame->view() == this);
2975 if (paintsEntireContents())
2976 return IntRect(IntPoint(), totalContentsSize());
2978 // Set our clip rect to be our contents.
2979 IntRect clipRect = contentsToWindow(visibleContentRect(clipToContents ? ExcludeScrollbars : IncludeScrollbars));
2980 if (!m_frame || !m_frame->ownerElement())
2983 // Take our owner element and get its clip rect.
2984 HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement();
2985 FrameView* parentView = ownerElement->document()->view();
2987 clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement, true));
2991 IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement, bool clipToLayerContents) const
2993 // The renderer can sometimes be null when style="display:none" interacts
2994 // with external content and plugins.
2995 if (!ownerElement->renderer())
2996 return windowClipRect();
2998 // If we have no layer, just return our window clip rect.
2999 const RenderLayer* enclosingLayer = ownerElement->renderer()->enclosingLayer();
3000 if (!enclosingLayer)
3001 return windowClipRect();
3003 // Apply the clip from the layer.
3005 if (clipToLayerContents)
3006 clipRect = pixelSnappedIntRect(enclosingLayer->childrenClipRect());
3008 clipRect = pixelSnappedIntRect(enclosingLayer->selfClipRect());
3009 clipRect = contentsToWindow(clipRect);
3010 return intersection(clipRect, windowClipRect());
3013 bool FrameView::isActive() const
3015 Page* page = frame()->page();
3016 return page && page->focusController()->isActive();
3019 void FrameView::scrollTo(const IntSize& newOffset)
3021 LayoutSize offset = scrollOffset();
3022 ScrollView::scrollTo(newOffset);
3023 if (offset != scrollOffset())
3024 scrollPositionChanged();
3025 frame()->loader()->client()->didChangeScrollOffset();
3028 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
3030 // Add in our offset within the FrameView.
3031 IntRect dirtyRect = rect;
3032 dirtyRect.moveBy(scrollbar->location());
3033 invalidateRect(dirtyRect);
3036 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
3038 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
3041 IntRect FrameView::windowResizerRect() const
3043 Page* page = frame() ? frame()->page() : 0;
3046 return page->chrome()->windowResizerRect();
3049 float FrameView::visibleContentScaleFactor() const
3051 if (!m_frame || !m_frame->page())
3054 if (!m_frame->settings()->applyPageScaleFactorInCompositor() || m_frame != m_frame->page()->mainFrame())
3057 return m_frame->page()->pageScaleFactor();
3060 void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
3062 Page* page = m_frame->page();
3065 if (page->mainFrame() != m_frame)
3067 page->chrome()->client()->notifyScrollerThumbIsVisibleInRect(scrollerThumb);
3070 bool FrameView::scrollbarsCanBeActive() const
3075 if (m_frame->view() != this)
3078 if (Page* page = m_frame->page()) {
3079 if (page->shouldSuppressScrollbarAnimations())
3083 if (Document* document = m_frame->document())
3084 return !document->inPageCache();
3089 ScrollableArea* FrameView::enclosingScrollableArea() const
3091 // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer.
3095 IntRect FrameView::scrollableAreaBoundingBox() const
3097 RenderPart* ownerRenderer = frame()->ownerRenderer();
3101 return ownerRenderer->absoluteContentQuad().enclosingBoundingBox();
3104 bool FrameView::isScrollable()
3107 // 1) If there an actual overflow.
3108 // 2) display:none or visibility:hidden set to self or inherited.
3109 // 3) overflow{-x,-y}: hidden;
3110 // 4) scrolling: no;
3113 IntSize totalContentsSize = this->totalContentsSize();
3114 IntSize visibleContentSize = visibleContentRect().size();
3115 if ((totalContentsSize.height() <= visibleContentSize.height() && totalContentsSize.width() <= visibleContentSize.width()))
3119 HTMLFrameOwnerElement* owner = m_frame->ownerElement();
3120 if (owner && (!owner->renderer() || !owner->renderer()->visibleToHitTesting()))
3124 ScrollbarMode horizontalMode;
3125 ScrollbarMode verticalMode;
3126 calculateScrollbarModesForLayout(horizontalMode, verticalMode, RulesFromWebContentOnly);
3127 if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff)
3133 void FrameView::updateScrollableAreaSet()
3135 // That ensures that only inner frames are cached.
3136 FrameView* parentFrameView = this->parentFrameView();
3137 if (!parentFrameView)
3140 if (!isScrollable()) {
3141 parentFrameView->removeScrollableArea(this);
3145 parentFrameView->addScrollableArea(this);
3148 bool FrameView::shouldSuspendScrollAnimations() const
3150 return m_frame->loader()->state() != FrameStateComplete;
3153 void FrameView::scrollbarStyleChanged(int newStyle, bool forceUpdate)
3155 Page* page = m_frame->page();
3158 if (page->mainFrame() != m_frame)
3160 page->chrome()->client()->recommendedScrollbarStyleDidChange(newStyle);
3163 ScrollView::scrollbarStyleChanged(newStyle, forceUpdate);
3166 void FrameView::setAnimatorsAreActive()
3168 Page* page = m_frame->page();
3172 if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
3173 scrollAnimator->setIsActive();
3175 if (!m_scrollableAreas)
3178 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
3179 ScrollableArea* scrollableArea = *it;
3181 ASSERT(scrollableArea->scrollbarsCanBeActive());
3182 scrollableArea->scrollAnimator()->setIsActive();
3186 void FrameView::notifyPageThatContentAreaWillPaint() const
3188 Page* page = m_frame->page();
3192 contentAreaWillPaint();
3194 if (!m_scrollableAreas)
3197 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
3198 ScrollableArea* scrollableArea = *it;
3200 if (!scrollableArea->scrollbarsCanBeActive())
3203 scrollableArea->contentAreaWillPaint();
3207 bool FrameView::scrollAnimatorEnabled() const
3209 #if ENABLE(SMOOTH_SCROLLING)
3210 if (Page* page = m_frame->page())
3211 return page->settings()->scrollAnimatorEnabled();
3217 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
3218 void FrameView::updateAnnotatedRegions()
3220 Document* document = m_frame->document();
3221 if (!document->hasAnnotatedRegions())
3223 Vector<AnnotatedRegionValue> newRegions;
3224 document->renderBox()->collectAnnotatedRegions(newRegions);
3225 if (newRegions == document->annotatedRegions())
3227 document->setAnnotatedRegions(newRegions);
3228 Page* page = m_frame->page();
3231 page->chrome()->client()->annotatedRegionsChanged();
3235 void FrameView::updateScrollCorner()
3237 RenderObject* renderer = 0;
3238 RefPtr<RenderStyle> cornerStyle;
3239 IntRect cornerRect = scrollCornerRect();
3241 if (!cornerRect.isEmpty()) {
3242 // Try the <body> element first as a scroll corner source.
3243 Document* doc = m_frame->document();
3244 Element* body = doc ? doc->body() : 0;
3245 if (body && body->renderer()) {
3246 renderer = body->renderer();
3247 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
3251 // If the <body> didn't have a custom style, then the root element might.
3252 Element* docElement = doc ? doc->documentElement() : 0;
3253 if (docElement && docElement->renderer()) {
3254 renderer = docElement->renderer();
3255 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
3260 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
3261 if (RenderPart* renderer = m_frame->ownerRenderer())
3262 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
3267 if (!m_scrollCorner)
3268 m_scrollCorner = RenderScrollbarPart::createAnonymous(renderer->document());
3269 m_scrollCorner->setStyle(cornerStyle.release());
3270 invalidateScrollCorner(cornerRect);
3271 } else if (m_scrollCorner) {
3272 m_scrollCorner->destroy();
3276 ScrollView::updateScrollCorner();
3279 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
3281 if (context->updatingControlTints()) {
3282 updateScrollCorner();
3286 if (m_scrollCorner) {
3287 bool needsBackgorund = m_frame->page() && m_frame->page()->mainFrame() == m_frame;
3288 if (needsBackgorund)
3289 context->fillRect(cornerRect, baseBackgroundColor(), ColorSpaceDeviceRGB);
3290 m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect);
3294 ScrollView::paintScrollCorner(context, cornerRect);
3297 void FrameView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
3299 bool needsBackgorund = bar->isCustomScrollbar() && (m_frame->page() && m_frame->page()->mainFrame() == m_frame);
3300 if (needsBackgorund) {
3301 IntRect toFill = bar->frameRect();
3302 toFill.intersect(rect);
3303 context->fillRect(toFill, baseBackgroundColor(), ColorSpaceDeviceRGB);
3306 ScrollView::paintScrollbar(context, bar, rect);
3309 Color FrameView::documentBackgroundColor() const
3311 // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of
3312 // the document and the body against the base background color of the frame view.
3313 // Background images are unfortunately impractical to include.
3315 // Return invalid Color objects whenever there is insufficient information.
3316 if (!frame()->document())
3319 Element* htmlElement = frame()->document()->documentElement();
3320 Element* bodyElement = frame()->document()->body();
3322 // Start with invalid colors.
3323 Color htmlBackgroundColor;
3324 Color bodyBackgroundColor;
3325 if (htmlElement && htmlElement->renderer())
3326 htmlBackgroundColor = htmlElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
3327 if (bodyElement && bodyElement->renderer())
3328 bodyBackgroundColor = bodyElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
3330 if (!bodyBackgroundColor.isValid()) {
3331 if (!htmlBackgroundColor.isValid())
3333 return baseBackgroundColor().blend(htmlBackgroundColor);
3336 if (!htmlBackgroundColor.isValid())
3337 return baseBackgroundColor().blend(bodyBackgroundColor);
3339 // We take the aggregate of the base background color
3340 // the <html> background color, and the <body>
3341 // background color to find the document color. The
3342 // addition of the base background color is not
3343 // technically part of the document background, but it
3344 // otherwise poses problems when the aggregate is not
3346 return baseBackgroundColor().blend(htmlBackgroundColor).blend(bodyBackgroundColor);
3349 bool FrameView::hasCustomScrollbars() const
3351 const HashSet<RefPtr<Widget> >* viewChildren = children();
3352 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
3353 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
3354 Widget* widget = current->get();
3355 if (widget->isFrameView()) {
3356 if (toFrameView(widget)->hasCustomScrollbars())
3358 } else if (widget->isScrollbar()) {
3359 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
3360 if (scrollbar->isCustomScrollbar())
3368 FrameView* FrameView::parentFrameView() const
3373 if (Frame* parentFrame = m_frame->tree()->parent())
3374 return parentFrame->view();
3379 bool FrameView::isInChildFrameWithFrameFlattening() const
3381 if (!parent() || !m_frame->ownerElement())
3384 // Frame flattening applies when the owner element is either in a frameset or
3385 // an iframe with flattening parameters.
3386 if (m_frame->ownerElement()->hasTagName(iframeTag)) {
3387 RenderIFrame* iframeRenderer = toRenderIFrame(m_frame->ownerElement()->renderPart());
3388 if (iframeRenderer->flattenFrame() || iframeRenderer->isSeamless())
3392 if (!m_frame->settings() || !m_frame->settings()->frameFlatteningEnabled())
3395 if (m_frame->ownerElement()->hasTagName(frameTag))
3401 bool FrameView::doLayoutWithFrameFlattening(bool allowSubtree)
3403 // Try initiating layout from the topmost parent.
3404 FrameView* parentView = parentFrameView();
3409 // In the middle of parent layout, no need to restart from topmost.
3410 if (parentView->m_nestedLayoutCount)
3413 // Parent tree is clean. Starting layout from it would have no effect.
3414 if (!parentView->needsLayout())
3417 while (parentView->parentFrameView())
3418 parentView = parentView->parentFrameView();
3420 parentView->layout(allowSubtree);
3422 RenderObject* root = m_layoutRoot ? m_layoutRoot : m_frame->document()->renderer();
3423 ASSERT_UNUSED(root, !root->needsLayout());
3428 void FrameView::updateControlTints()
3430 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
3431 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
3432 // This is only done if the theme supports control tinting. It's up to the theme and platform
3433 // to define when controls get the tint and to call this function when that changes.
3435 // Optimize the common case where we bring a window to the front while it's still empty.
3436 if (!m_frame || m_frame->document()->url().isEmpty())
3439 RenderView* renderView = this->renderView();
3440 if ((renderView && renderView->theme()->supportsControlTints()) || hasCustomScrollbars())
3441 paintControlTints();
3444 void FrameView::paintControlTints()
3448 PlatformGraphicsContext* const noContext = 0;
3449 GraphicsContext context(noContext);
3450 context.setUpdatingControlTints(true);
3451 if (platformWidget())
3452 paintContents(&context, visibleContentRect());
3454 paint(&context, frameRect());
3457 bool FrameView::wasScrolledByUser() const
3459 return m_wasScrolledByUser;
3462 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
3464 if (m_inProgrammaticScroll)
3466 m_maintainScrollPositionAnchor = 0;
3467 if (m_wasScrolledByUser == wasScrolledByUser)
3469 m_wasScrolledByUser = wasScrolledByUser;
3470 adjustTiledBackingCoverage();
3473 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
3478 Document* document = m_frame->document();
3482 if (document->printing())
3483 fillWithRed = false; // Printing, don't fill with red (can't remember why).
3484 else if (m_frame->ownerElement())
3485 fillWithRed = false; // Subframe, don't fill with red.
3486 else if (isTransparent())
3487 fillWithRed = false; // Transparent, don't fill with red.
3488 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
3489 fillWithRed = false; // Selections are transparent, don't fill with red.
3490 else if (m_nodeToDraw)
3491 fillWithRed = false; // Element images are transparent, don't fill with red.
3496 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
3499 RenderView* renderView = this->renderView();
3501 LOG_ERROR("called FrameView::paint with nil renderer");
3505 ASSERT(!needsLayout());
3509 InspectorInstrumentation::willPaint(renderView);
3511 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
3512 if (isTopLevelPainter)
3513 sCurrentPaintTimeStamp = currentTime();
3515 FontCachePurgePreventer fontCachePurgePreventer;
3517 #if USE(ACCELERATED_COMPOSITING)
3518 if (!p->paintingDisabled() && !document->printing())
3519 flushCompositingStateForThisFrame(m_frame.get());
3522 PaintBehavior oldPaintBehavior = m_paintBehavior;
3524 if (FrameView* parentView = parentFrameView()) {
3525 if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
3526 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
3529 if (m_paintBehavior == PaintBehaviorNormal)
3530 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
3532 if (document->printing())
3533 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
3535 bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers;
3536 bool isRootFrame = !m_frame->ownerElement();
3537 if (flatteningPaint && isRootFrame)
3538 notifyWidgetsInAllFrames(WillPaintFlattened);
3540 ASSERT(!m_isPainting);
3541 m_isPainting = true;
3543 // m_nodeToDraw is used to draw only one element (and its descendants)
3544 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
3545 RenderLayer* rootLayer = renderView->layer();
3548 RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(rootLayer->renderer());
3551 rootLayer->paint(p, rect, m_paintBehavior, eltRenderer);
3553 if (rootLayer->containsDirtyOverlayScrollbars())
3554 rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer);
3556 m_isPainting = false;
3558 if (flatteningPaint && isRootFrame)
3559 notifyWidgetsInAllFrames(DidPaintFlattened);
3561 m_paintBehavior = oldPaintBehavior;
3562 m_lastPaintTime = currentTime();
3564 // Regions may have changed as a result of the visibility/z-index of element changing.
3565 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
3566 if (document->annotatedRegionsDirty())
3567 updateAnnotatedRegions();
3570 if (isTopLevelPainter)
3571 sCurrentPaintTimeStamp = 0;
3573 InspectorInstrumentation::didPaint(renderView, p, rect);
3576 void FrameView::setPaintBehavior(PaintBehavior behavior)
3578 m_paintBehavior = behavior;
3581 PaintBehavior FrameView::paintBehavior() const
3583 return m_paintBehavior;
3586 bool FrameView::isPainting() const
3588 return m_isPainting;
3591 void FrameView::setNodeToDraw(Node* node)
3593 m_nodeToDraw = node;
3596 void FrameView::paintContentsForSnapshot(GraphicsContext* context, const IntRect& imageRect, SelectionInSnaphot shouldPaintSelection, CoordinateSpaceForSnapshot coordinateSpace)
3598 updateLayoutAndStyleIfNeededRecursive();
3600 // Cache paint behavior and set a new behavior appropriate for snapshots.
3601 PaintBehavior oldBehavior = paintBehavior();
3602 setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
3604 // If the snapshot should exclude selection, then we'll clear the current selection
3605 // in the render tree only. This will allow us to restore the selection from the DOM
3606 // after we paint the snapshot.
3607 if (shouldPaintSelection == ExcludeSelection) {
3608 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {