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 "CachedResourceLoader.h"
34 #include "ChromeClient.h"
35 #include "DocumentMarkerController.h"
36 #include "EventHandler.h"
37 #include "FloatRect.h"
38 #include "FocusController.h"
39 #include "FontCache.h"
40 #include "FontLoader.h"
42 #include "FrameActionScheduler.h"
43 #include "FrameLoader.h"
44 #include "FrameLoaderClient.h"
45 #include "FrameTree.h"
46 #include "GraphicsContext.h"
47 #include "HTMLDocument.h"
48 #include "HTMLFrameElement.h"
49 #include "HTMLFrameSetElement.h"
50 #include "HTMLNames.h"
51 #include "HTMLPlugInImageElement.h"
52 #include "InspectorClient.h"
53 #include "InspectorController.h"
54 #include "InspectorInstrumentation.h"
55 #include "OverflowEvent.h"
56 #include "RenderArena.h"
57 #include "RenderEmbeddedObject.h"
58 #include "RenderFullScreen.h"
59 #include "RenderIFrame.h"
60 #include "RenderLayer.h"
61 #include "RenderLayerBacking.h"
62 #include "RenderPart.h"
63 #include "RenderScrollbar.h"
64 #include "RenderScrollbarPart.h"
65 #include "RenderTheme.h"
66 #include "RenderView.h"
67 #include "ScrollAnimator.h"
68 #include "ScrollingCoordinator.h"
70 #include "StyleResolver.h"
71 #include "TextResourceDecoder.h"
72 #include "TextStream.h"
74 #include <wtf/CurrentTime.h>
75 #include <wtf/TemporaryChange.h>
76 #include <wtf/UnusedParam.h>
78 #if USE(ACCELERATED_COMPOSITING)
79 #include "RenderLayerCompositor.h"
80 #include "TiledBacking.h"
84 #include "RenderSVGRoot.h"
85 #include "SVGDocument.h"
86 #include "SVGSVGElement.h"
89 #if USE(TILED_BACKING_STORE)
90 #include "TiledBackingStore.h"
93 #if ENABLE(TEXT_AUTOSIZING)
94 #include "TextAutosizer.h"
97 #if PLATFORM(CHROMIUM)
98 #include "TraceEvent.h"
103 using namespace HTMLNames;
105 double FrameView::sCurrentPaintTimeStamp = 0.0;
108 // REPAINT_THROTTLING now chooses default values for throttling parameters.
109 // Should be removed when applications start using runtime configuration.
110 #if ENABLE(REPAINT_THROTTLING)
112 double FrameView::s_normalDeferredRepaintDelay = 0.016;
113 // Negative value would mean that first few repaints happen without a delay
114 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
115 // The delay grows on each repaint to this maximum value
116 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
117 // On each repaint the delay increses by this amount
118 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
120 // FIXME: Repaint throttling could be good to have on all platform.
121 // The balance between CPU use and repaint frequency will need some tuning for desktop.
122 // More hooks may be needed to reset the delay on things like GIF and CSS animations.
123 double FrameView::s_normalDeferredRepaintDelay = 0;
124 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
125 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
126 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
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_layoutTimer(this, &FrameView::layoutTimerFired)
177 , m_inSynchronousPostLayout(false)
178 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
179 , m_isTransparent(false)
180 , m_baseBackgroundColor(Color::white)
181 , m_mediaType("screen")
182 , m_actionScheduler(adoptPtr(new FrameActionScheduler))
183 , m_overflowStatusDirty(true)
184 , m_viewportRenderer(0)
185 , m_wasScrolledByUser(false)
186 , m_inProgrammaticScroll(false)
187 , m_safeToPropagateScrollToParent(true)
188 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
189 , m_disableRepaints(0)
190 , m_isTrackingRepaints(false)
191 , m_shouldUpdateWhileOffscreen(true)
192 , m_deferSetNeedsLayouts(0)
193 , m_setNeedsLayoutWasDeferred(false)
195 , m_shouldAutoSize(false)
196 , m_inAutoSize(false)
197 , m_didRunAutosize(false)
200 #if ENABLE(CSS_FILTERS)
201 , m_hasSoftwareFilters(false)
206 // FIXME: Can m_frame ever be null here?
210 Page* page = m_frame->page();
214 if (m_frame == page->mainFrame()) {
215 ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed);
216 ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed);
220 PassRefPtr<FrameView> FrameView::create(Frame* frame)
222 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
224 return view.release();
227 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize)
229 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
230 view->Widget::setFrameRect(IntRect(view->location(), initialSize));
232 return view.release();
235 FrameView::~FrameView()
237 if (m_postLayoutTasksTimer.isActive()) {
238 m_postLayoutTasksTimer.stop();
239 m_actionScheduler->clear();
242 removeFromAXObjectCache();
245 // Custom scrollbars should already be destroyed at this point
246 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
247 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
249 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
250 setHasVerticalScrollbar(false);
252 ASSERT(!m_scrollCorner);
253 ASSERT(m_actionScheduler->isEmpty());
256 ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
257 RenderPart* renderer = m_frame->ownerRenderer();
258 if (renderer && renderer->widget() == this)
259 renderer->setWidget(0);
263 void FrameView::reset()
265 m_cannotBlitToWindow = false;
266 m_isOverlapped = false;
267 m_contentIsOpaque = false;
270 m_layoutTimer.stop();
272 m_delayedLayout = false;
273 m_doFullRepaint = true;
274 m_layoutSchedulingEnabled = true;
276 m_doingPreLayoutStyleUpdate = false;
277 m_inSynchronousPostLayout = false;
279 m_nestedLayoutCount = 0;
280 m_postLayoutTasksTimer.stop();
281 m_firstLayout = true;
282 m_firstLayoutCallbackPending = false;
283 m_wasScrolledByUser = false;
284 m_safeToPropagateScrollToParent = true;
285 m_lastViewportSize = IntSize();
286 m_lastZoomFactor = 1.0f;
287 m_deferringRepaints = 0;
289 m_repaintRects.clear();
290 m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading;
291 m_deferredRepaintTimer.stop();
292 m_isTrackingRepaints = false;
293 m_trackedRepaintRects.clear();
295 m_paintBehavior = PaintBehaviorNormal;
296 m_isPainting = false;
297 m_visuallyNonEmptyCharacterCount = 0;
298 m_visuallyNonEmptyPixelCount = 0;
299 m_isVisuallyNonEmpty = false;
300 m_firstVisuallyNonEmptyLayoutCallbackPending = true;
301 m_maintainScrollPositionAnchor = 0;
302 m_disableRepaints = 0;
305 void FrameView::removeFromAXObjectCache()
307 if (AXObjectCache* cache = axObjectCache())
311 void FrameView::clearFrame()
316 void FrameView::resetScrollbars()
318 // Reset the document's scrollbars back to our defaults before we yield the floor.
319 m_firstLayout = true;
320 setScrollbarsSuppressed(true);
321 if (m_canHaveScrollbars)
322 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
324 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
325 setScrollbarsSuppressed(false);
328 void FrameView::resetScrollbarsAndClearContentsSize()
332 setScrollbarsSuppressed(true);
333 setContentsSize(IntSize());
334 setScrollbarsSuppressed(false);
337 void FrameView::init()
341 m_margins = LayoutSize(-1, -1); // undefined
342 m_size = LayoutSize();
344 // Propagate the marginwidth/height and scrolling modes to the view.
345 Element* ownerElement = m_frame ? m_frame->ownerElement() : 0;
346 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
347 HTMLFrameElementBase* frameElt = static_cast<HTMLFrameElementBase*>(ownerElement);
348 if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
349 setCanHaveScrollbars(false);
350 LayoutUnit marginWidth = frameElt->marginWidth();
351 LayoutUnit marginHeight = frameElt->marginHeight();
352 if (marginWidth != -1)
353 setMarginWidth(marginWidth);
354 if (marginHeight != -1)
355 setMarginHeight(marginHeight);
359 void FrameView::prepareForDetach()
361 detachCustomScrollbars();
362 // When the view is no longer associated with a frame, it needs to be removed from the ax object cache
363 // right now, otherwise it won't be able to reach the topDocument()'s axObject cache later.
364 removeFromAXObjectCache();
366 if (m_frame && m_frame->page()) {
367 if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator())
368 scrollingCoordinator->willDestroyScrollableArea(this);
372 void FrameView::detachCustomScrollbars()
374 Scrollbar* horizontalBar = horizontalScrollbar();
375 if (horizontalBar && horizontalBar->isCustomScrollbar())
376 setHasHorizontalScrollbar(false);
378 Scrollbar* verticalBar = verticalScrollbar();
379 if (verticalBar && verticalBar->isCustomScrollbar())
380 setHasVerticalScrollbar(false);
382 if (m_scrollCorner) {
383 m_scrollCorner->destroy();
388 void FrameView::recalculateScrollbarOverlayStyle()
390 ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle();
391 ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault;
393 Color backgroundColor = documentBackgroundColor();
394 if (backgroundColor.isValid()) {
395 // Reduce the background color from RGB to a lightness value
396 // and determine which scrollbar style to use based on a lightness
398 double hue, saturation, lightness;
399 backgroundColor.getHSL(hue, saturation, lightness);
401 overlayStyle = ScrollbarOverlayStyleLight;
404 if (oldOverlayStyle != overlayStyle)
405 setScrollbarOverlayStyle(overlayStyle);
408 void FrameView::clear()
410 setCanBlitOnScroll(true);
415 if (RenderPart* renderer = m_frame->ownerRenderer())
416 renderer->viewCleared();
419 setScrollbarsSuppressed(true);
422 bool FrameView::didFirstLayout() const
424 return !m_firstLayout;
427 void FrameView::invalidateRect(const IntRect& rect)
431 hostWindow()->invalidateContentsAndRootView(rect, false /*immediate*/);
438 RenderPart* renderer = m_frame->ownerRenderer();
442 IntRect repaintRect = rect;
443 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
444 renderer->borderTop() + renderer->paddingTop());
445 renderer->repaintRectangle(repaintRect);
448 void FrameView::setFrameRect(const IntRect& newRect)
450 IntRect oldRect = frameRect();
451 if (newRect == oldRect)
454 #if ENABLE(TEXT_AUTOSIZING)
455 // Autosized font sizes depend on the width of the viewing area.
456 if (newRect.width() != oldRect.width()) {
457 Page* page = m_frame ? m_frame->page() : 0;
458 if (page && page->mainFrame() == m_frame && page->settings()->textAutosizingEnabled()) {
459 for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())
460 m_frame->document()->textAutosizer()->recalculateMultipliers();
465 ScrollView::setFrameRect(newRect);
467 updateScrollableAreaSet();
469 #if USE(ACCELERATED_COMPOSITING)
470 if (RenderView* renderView = this->renderView()) {
471 if (renderView->usesCompositing())
472 renderView->compositor()->frameViewDidChangeSize();
477 #if ENABLE(REQUEST_ANIMATION_FRAME)
478 bool FrameView::scheduleAnimation()
481 hostWindow()->scheduleAnimation();
488 void FrameView::setMarginWidth(LayoutUnit w)
490 // make it update the rendering area when set
491 m_margins.setWidth(w);
494 void FrameView::setMarginHeight(LayoutUnit h)
496 // make it update the rendering area when set
497 m_margins.setHeight(h);
500 bool FrameView::avoidScrollbarCreation() const
504 // with frame flattening no subframe can have scrollbars
505 // but we also cannot turn scrollbars off as we determine
506 // our flattening policy using that.
508 if (!m_frame->ownerElement())
511 if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
517 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
519 m_canHaveScrollbars = canHaveScrollbars;
520 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
523 void FrameView::updateCanHaveScrollbars()
527 scrollbarModes(hMode, vMode);
528 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
529 setCanHaveScrollbars(false);
531 setCanHaveScrollbars(true);
534 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
536 if (Settings* settings = m_frame->settings()) {
537 if (!settings->allowCustomScrollbarInMainFrame() && m_frame->page() && m_frame->page()->mainFrame() == m_frame)
538 return ScrollView::createScrollbar(orientation);
541 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
542 Document* doc = m_frame->document();
544 // Try the <body> element first as a scrollbar source.
545 Element* body = doc ? doc->body() : 0;
546 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
547 return RenderScrollbar::createCustomScrollbar(this, orientation, body);
549 // If the <body> didn't have a custom style, then the root element might.
550 Element* docElement = doc ? doc->documentElement() : 0;
551 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
552 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement);
554 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
555 RenderPart* frameRenderer = m_frame->ownerRenderer();
556 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
557 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
559 // Nobody set a custom style, so we just use a native scrollbar.
560 return ScrollView::createScrollbar(orientation);
563 void FrameView::setContentsSize(const IntSize& size)
565 if (size == contentsSize())
568 m_deferSetNeedsLayouts++;
570 ScrollView::setContentsSize(size);
571 ScrollView::contentsResized();
573 Page* page = frame() ? frame()->page() : 0;
577 updateScrollableAreaSet();
579 page->chrome()->contentsSizeChanged(frame(), size); //notify only
581 m_deferSetNeedsLayouts--;
583 if (!m_deferSetNeedsLayouts)
584 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
587 void FrameView::adjustViewSize()
589 RenderView* renderView = this->renderView();
593 ASSERT(m_frame->view() == this);
595 const IntRect rect = renderView->documentRect();
596 const IntSize& size = rect.size();
597 ScrollView::setScrollOrigin(IntPoint(-rect.x(), -rect.y()), !m_frame->document()->printing(), size == contentsSize());
599 setContentsSize(size);
602 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
604 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
605 // overflow:hidden and overflow:scroll on <body> as applying to the document's
606 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
607 // use the root element.
609 // To combat the inability to scroll on a page with overflow:hidden on the root when scaled, disregard hidden when
610 // there is a frameScaleFactor that is greater than one on the main frame.
612 bool overrideHidden = m_frame->page() && m_frame->page()->mainFrame() == m_frame && m_frame->frameScaleFactor() > 1;
614 EOverflow overflowX = o->style()->overflowX();
615 EOverflow overflowY = o->style()->overflowY();
618 if (o->isSVGRoot()) {
619 // overflow is ignored in stand-alone SVG documents.
620 if (!toRenderSVGRoot(o)->isEmbeddedThroughFrameContainingSVGDocument())
630 hMode = ScrollbarAuto;
632 hMode = ScrollbarAlwaysOff;
635 hMode = ScrollbarAlwaysOn;
638 hMode = ScrollbarAuto;
641 // Don't set it at all.
648 vMode = ScrollbarAuto;
650 vMode = ScrollbarAlwaysOff;
653 vMode = ScrollbarAlwaysOn;
656 vMode = ScrollbarAuto;
659 // Don't set it at all. Values of OPAGEDX and OPAGEDY are handled by applyPaginationToViewPort().
663 m_viewportRenderer = o;
666 void FrameView::applyPaginationToViewport()
668 Document* document = m_frame->document();
669 Node* documentElement = document->documentElement();
670 RenderObject* documentRenderer = documentElement ? documentElement->renderer() : 0;
671 RenderObject* documentOrBodyRenderer = documentRenderer;
672 Node* body = document->body();
673 if (body && body->renderer()) {
674 if (body->hasTagName(bodyTag))
675 documentOrBodyRenderer = documentRenderer->style()->overflowX() == OVISIBLE && documentElement->hasTagName(htmlTag) ? body->renderer() : documentRenderer;
678 Pagination pagination;
680 if (!documentOrBodyRenderer) {
681 setPagination(pagination);
685 EOverflow overflowY = documentOrBodyRenderer->style()->overflowY();
686 if (overflowY == OPAGEDX || overflowY == OPAGEDY) {
687 pagination.mode = WebCore::paginationModeForRenderStyle(documentOrBodyRenderer->style());
688 pagination.gap = static_cast<unsigned>(documentOrBodyRenderer->style()->columnGap());
691 setPagination(pagination);
694 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy)
696 m_viewportRenderer = 0;
698 const HTMLFrameOwnerElement* owner = m_frame->ownerElement();
699 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
700 hMode = ScrollbarAlwaysOff;
701 vMode = ScrollbarAlwaysOff;
705 if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) {
706 hMode = ScrollbarAuto;
707 // Seamless documents begin with heights of 0; we special case that here
708 // to correctly render documents that don't need scrollbars.
709 IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size();
710 bool isSeamlessDocument = frame() && frame()->document() && frame()->document()->shouldDisplaySeamlesslyWithParent();
711 vMode = (isSeamlessDocument && !fullVisibleSize.height()) ? ScrollbarAlwaysOff : ScrollbarAuto;
713 hMode = ScrollbarAlwaysOff;
714 vMode = ScrollbarAlwaysOff;
718 Document* document = m_frame->document();
719 Node* documentElement = document->documentElement();
720 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
721 Node* body = document->body();
722 if (body && body->renderer()) {
723 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
724 vMode = ScrollbarAlwaysOff;
725 hMode = ScrollbarAlwaysOff;
726 } else if (body->hasTagName(bodyTag)) {
727 // It's sufficient to just check the X overflow,
728 // since it's illegal to have visible in only one direction.
729 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
730 applyOverflowToViewport(o, hMode, vMode);
732 } else if (rootRenderer)
733 applyOverflowToViewport(rootRenderer, hMode, vMode);
737 #if USE(ACCELERATED_COMPOSITING)
738 void FrameView::updateCompositingLayersAfterStyleChange()
740 RenderView* renderView = this->renderView();
744 // If we expect to update compositing after an incipient layout, don't do so here.
745 if (m_doingPreLayoutStyleUpdate || layoutPending() || renderView->needsLayout())
748 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
749 renderView->compositor()->cacheAcceleratedCompositingFlags();
750 renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterStyleChange);
753 void FrameView::updateCompositingLayersAfterLayout()
755 RenderView* renderView = this->renderView();
759 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
760 renderView->compositor()->cacheAcceleratedCompositingFlags();
761 renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterLayout);
764 void FrameView::clearBackingStores()
766 RenderView* renderView = this->renderView();
770 RenderLayerCompositor* compositor = renderView->compositor();
771 ASSERT(compositor->inCompositingMode());
772 compositor->enableCompositingMode(false);
773 compositor->clearBackingForAllLayers();
776 void FrameView::restoreBackingStores()
778 RenderView* renderView = this->renderView();
782 RenderLayerCompositor* compositor = renderView->compositor();
783 compositor->enableCompositingMode(true);
784 compositor->updateCompositingLayers(CompositingUpdateAfterLayout);
787 bool FrameView::usesCompositedScrolling() const
789 RenderView* renderView = this->renderView();
792 if (m_frame->settings() && m_frame->settings()->compositedScrollingForFramesEnabled())
793 return renderView->compositor()->inForcedCompositingMode();
797 GraphicsLayer* FrameView::layerForScrolling() const
799 RenderView* renderView = this->renderView();
802 return renderView->compositor()->scrollLayer();
805 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
807 RenderView* renderView = this->renderView();
810 return renderView->compositor()->layerForHorizontalScrollbar();
813 GraphicsLayer* FrameView::layerForVerticalScrollbar() const
815 RenderView* renderView = this->renderView();
818 return renderView->compositor()->layerForVerticalScrollbar();
821 GraphicsLayer* FrameView::layerForScrollCorner() const
823 RenderView* renderView = this->renderView();
826 return renderView->compositor()->layerForScrollCorner();
829 TiledBacking* FrameView::tiledBacking()
831 RenderView* renderView = this->renderView();
835 RenderLayerBacking* backing = renderView->layer()->backing();
839 return backing->graphicsLayer()->tiledBacking();
842 uint64_t FrameView::scrollLayerID() const
844 RenderView* renderView = this->renderView();
848 RenderLayerBacking* backing = renderView->layer()->backing();
852 return backing->scrollLayerID();
855 #if ENABLE(RUBBER_BANDING)
856 GraphicsLayer* FrameView::layerForOverhangAreas() const
858 RenderView* renderView = this->renderView();
861 return renderView->compositor()->layerForOverhangAreas();
864 GraphicsLayer* FrameView::setWantsLayerForTopOverHangArea(bool wantsLayer) const
866 RenderView* renderView = this->renderView();
870 #if USE(ACCELERATED_COMPOSITING)
871 return renderView->compositor()->updateLayerForTopOverhangArea(wantsLayer);
877 GraphicsLayer* FrameView::setWantsLayerForBottomOverHangArea(bool wantsLayer) const
879 RenderView* renderView = this->renderView();
883 #if USE(ACCELERATED_COMPOSITING)
884 return renderView->compositor()->updateLayerForBottomOverhangArea(wantsLayer);
890 GraphicsLayer* FrameView::setWantsLayerForHeader(bool wantsLayer) const
892 RenderView* renderView = this->renderView();
896 ASSERT(m_frame == m_frame->page()->mainFrame());
898 #if USE(ACCELERATED_COMPOSITING)
899 return renderView->compositor()->updateLayerForHeader(wantsLayer);
905 GraphicsLayer* FrameView::setWantsLayerForFooter(bool wantsLayer) const
907 RenderView* renderView = this->renderView();
911 ASSERT(m_frame == m_frame->page()->mainFrame());
913 #if USE(ACCELERATED_COMPOSITING)
914 return renderView->compositor()->updateLayerForFooter(wantsLayer);
922 void FrameView::setHeaderHeight(int headerHeight)
924 if (m_frame && m_frame->page())
925 ASSERT(m_frame == m_frame->page()->mainFrame());
926 m_headerHeight = headerHeight;
929 void FrameView::setFooterHeight(int footerHeight)
931 if (m_frame && m_frame->page())
932 ASSERT(m_frame == m_frame->page()->mainFrame());
933 m_footerHeight = footerHeight;
936 bool FrameView::flushCompositingStateForThisFrame(Frame* rootFrameForFlush)
938 RenderView* renderView = this->renderView();
940 return true; // We don't want to keep trying to update layers if we have no renderer.
942 ASSERT(m_frame->view() == this);
944 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
945 // layer content to occur before layout has happened, which will cause paintContents() to bail.
949 // If we sync compositing layers and allow the repaint to be deferred, there is time for a
950 // visible flash to occur. Instead, stop the deferred repaint timer and repaint immediately.
951 flushDeferredRepaints();
953 renderView->compositor()->flushPendingLayerChanges(rootFrameForFlush == m_frame);
958 void FrameView::setNeedsOneShotDrawingSynchronization()
960 Page* page = frame() ? frame()->page() : 0;
962 page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
965 #endif // USE(ACCELERATED_COMPOSITING)
967 bool FrameView::hasCompositedContent() const
969 #if USE(ACCELERATED_COMPOSITING)
970 if (RenderView* renderView = this->renderView())
971 return renderView->compositor()->inCompositingMode();
976 bool FrameView::hasCompositedContentIncludingDescendants() const
978 #if USE(ACCELERATED_COMPOSITING)
979 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
980 RenderView* renderView = frame->contentRenderer();
981 RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0;
983 if (compositor->inCompositingMode())
986 if (!RenderLayerCompositor::allowsIndependentlyCompositedFrames(this))
994 bool FrameView::hasCompositingAncestor() const
996 #if USE(ACCELERATED_COMPOSITING)
997 for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) {
998 if (FrameView* view = frame->view()) {
999 if (view->hasCompositedContent())
1007 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
1008 void FrameView::enterCompositingMode()
1010 #if USE(ACCELERATED_COMPOSITING)
1011 if (RenderView* renderView = this->renderView()) {
1012 renderView->compositor()->enableCompositingMode();
1014 renderView->compositor()->scheduleCompositingLayerUpdate();
1019 bool FrameView::isEnclosedInCompositingLayer() const
1021 #if USE(ACCELERATED_COMPOSITING)
1022 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
1023 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
1026 if (FrameView* parentView = parentFrameView())
1027 return parentView->isEnclosedInCompositingLayer();
1032 bool FrameView::flushCompositingStateIncludingSubframes()
1034 #if USE(ACCELERATED_COMPOSITING)
1035 bool allFramesFlushed = flushCompositingStateForThisFrame(m_frame.get());
1037 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame.get())) {
1038 bool flushed = child->view()->flushCompositingStateForThisFrame(m_frame.get());
1039 allFramesFlushed &= flushed;
1041 return allFramesFlushed;
1042 #else // USE(ACCELERATED_COMPOSITING)
1047 bool FrameView::isSoftwareRenderable() const
1049 #if USE(ACCELERATED_COMPOSITING)
1050 RenderView* renderView = this->renderView();
1051 return !renderView || !renderView->compositor()->has3DContent();
1057 void FrameView::didMoveOnscreen()
1059 contentAreaDidShow();
1062 void FrameView::willMoveOffscreen()
1064 contentAreaDidHide();
1067 void FrameView::setIsInWindow(bool isInWindow)
1069 if (RenderView* renderView = this->renderView())
1070 renderView->setIsInWindow(isInWindow);
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 #if PLATFORM(CHROMIUM)
1130 TRACE_EVENT0("webkit", "FrameView::layout");
1133 // Protect the view from being deleted during layout (in recalcStyle)
1134 RefPtr<FrameView> protector(this);
1136 // Every scroll that happens during layout is programmatic.
1137 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1139 bool inChildFrameLayoutWithFrameFlattening = isInChildFrameWithFrameFlattening();
1141 if (inChildFrameLayoutWithFrameFlattening) {
1142 if (doLayoutWithFrameFlattening(allowSubtree))
1146 m_layoutTimer.stop();
1147 m_delayedLayout = false;
1148 m_setNeedsLayoutWasDeferred = false;
1151 // FIXME: Do we need to set m_size.width here?
1152 // FIXME: Should we set m_size.height here too?
1153 m_size.setWidth(layoutWidth());
1157 // we shouldn't enter layout() while painting
1158 ASSERT(!isPainting());
1162 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
1164 if (!allowSubtree && m_layoutRoot) {
1165 m_layoutRoot->markContainingBlocksForLayout(false);
1169 ASSERT(m_frame->view() == this);
1171 Document* document = m_frame->document();
1172 ASSERT(!document->inPageCache());
1177 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1179 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_postLayoutTasksTimer.isActive() && !inChildFrameLayoutWithFrameFlattening) {
1180 // This is a new top-level layout. If there are any remaining tasks from the previous
1181 // layout, finish them now.
1182 m_inSynchronousPostLayout = true;
1183 performPostLayoutTasks();
1184 m_inSynchronousPostLayout = false;
1187 // Viewport-dependent media queries may cause us to need completely different style information.
1189 if (document->styleResolver()->affectedByViewportChange()) {
1190 document->styleResolverChanged(RecalcStyleImmediately);
1191 InspectorInstrumentation::mediaQueryResultChanged(document);
1193 document->evaluateMediaQueryList();
1195 // If there is any pagination to apply, it will affect the RenderView's style, so we should
1196 // take care of that now.
1197 applyPaginationToViewport();
1199 // Always ensure our style info is up-to-date. This can happen in situations where
1200 // the layout beats any sort of style recalc update that needs to occur.
1201 TemporaryChange<bool> changeDoingPreLayoutStyleUpdate(m_doingPreLayoutStyleUpdate, true);
1202 document->updateStyleIfNeeded();
1204 subtree = m_layoutRoot;
1206 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
1207 // so there's no point to continuing to layout
1208 if (protector->hasOneRef())
1211 root = subtree ? m_layoutRoot : document->renderer();
1213 // FIXME: Do we need to set m_size here?
1216 } // Reset m_layoutSchedulingEnabled to its previous value.
1217 // The only reason the scoping was closed here is allow fontCachePurgePreventer
1218 // to outlive the change and reset of m_layoutSchedulingEnabled.
1220 FontCachePurgePreventer fontCachePurgePreventer;
1223 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1225 m_nestedLayoutCount++;
1227 if (!m_layoutRoot) {
1228 Document* document = m_frame->document();
1229 Node* body = document->body();
1230 if (body && body->renderer()) {
1231 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
1232 body->renderer()->setChildNeedsLayout(true);
1233 } else if (body->hasTagName(bodyTag)) {
1234 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
1235 body->renderer()->setChildNeedsLayout(true);
1239 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1240 if (m_firstLayout && !m_frame->ownerElement())
1241 printf("Elapsed time before first layout: %d\n", document->elapsedTime());
1245 autoSizeIfEnabled();
1247 ScrollbarMode hMode;
1248 ScrollbarMode vMode;
1249 calculateScrollbarModesForLayout(hMode, vMode);
1251 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
1254 // Now set our scrollbar state for the layout.
1255 ScrollbarMode currentHMode = horizontalScrollbarMode();
1256 ScrollbarMode currentVMode = verticalScrollbarMode();
1258 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
1259 if (m_firstLayout) {
1260 setScrollbarsSuppressed(true);
1262 m_firstLayout = false;
1263 m_firstLayoutCallbackPending = true;
1264 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
1265 m_lastViewportSize = fixedLayoutSize();
1267 m_lastViewportSize = visibleContentRect(IncludeScrollbars).size();
1268 m_lastZoomFactor = root->style()->zoom();
1270 // Set the initial vMode to AlwaysOn if we're auto.
1271 if (vMode == ScrollbarAuto)
1272 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
1273 // Set the initial hMode to AlwaysOff if we're auto.
1274 if (hMode == ScrollbarAuto)
1275 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
1277 setScrollbarModes(hMode, vMode);
1278 setScrollbarsSuppressed(false, true);
1280 setScrollbarModes(hMode, vMode);
1283 LayoutSize oldSize = m_size;
1285 m_size = LayoutSize(layoutWidth(), layoutHeight());
1287 if (oldSize != m_size) {
1288 m_doFullRepaint = true;
1289 if (!m_firstLayout) {
1290 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
1291 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
1292 if (bodyRenderer && bodyRenderer->stretchesToViewport())
1293 bodyRenderer->setChildNeedsLayout(true);
1294 else if (rootRenderer && rootRenderer->stretchesToViewport())
1295 rootRenderer->setChildNeedsLayout(true);
1300 layer = root->enclosingLayer();
1302 m_actionScheduler->pause();
1305 bool disableLayoutState = false;
1307 RenderView* view = root->view();
1308 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
1309 view->pushLayoutState(root);
1311 LayoutStateDisabler layoutStateDisabler(disableLayoutState ? root->view() : 0);
1314 beginDeferredRepaints();
1315 forceLayoutParentViewIfNeeded();
1317 #if ENABLE(TEXT_AUTOSIZING)
1318 bool autosized = document->textAutosizer()->processSubtree(root);
1319 if (autosized && root->needsLayout())
1322 endDeferredRepaints();
1326 root->view()->popLayoutState(root);
1329 } // Reset m_layoutSchedulingEnabled to its previous value.
1331 bool neededFullRepaint = m_doFullRepaint;
1333 if (!subtree && !toRenderView(root)->printing())
1336 m_doFullRepaint = neededFullRepaint;
1338 // Now update the positions of all layers.
1339 beginDeferredRepaints();
1340 if (m_doFullRepaint)
1341 root->view()->repaint(); // FIXME: This isn't really right, since the RenderView doesn't fully encompass the visibleContentRect(). It just happens
1342 // to work out most of the time, since first layouts and printing don't have you scrolled anywhere.
1344 layer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPositionFlags(layer, subtree, m_doFullRepaint));
1346 endDeferredRepaints();
1348 #if USE(ACCELERATED_COMPOSITING)
1349 updateCompositingLayersAfterLayout();
1354 #if PLATFORM(MAC) || PLATFORM(CHROMIUM)
1355 if (AXObjectCache* cache = root->document()->existingAXObjectCache())
1356 cache->postNotification(root, AXObjectCache::AXLayoutComplete, true);
1358 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
1359 updateAnnotatedRegions();
1362 ASSERT(!root->needsLayout());
1364 updateCanBlitOnScrollRecursively();
1366 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1367 updateOverflowStatus(layoutWidth() < contentsWidth(),
1368 layoutHeight() < contentsHeight());
1370 if (!m_postLayoutTasksTimer.isActive()) {
1371 if (!m_inSynchronousPostLayout) {
1372 if (inChildFrameLayoutWithFrameFlattening) {
1373 if (RenderView* renderView = this->renderView())
1374 renderView->updateWidgetPositions();
1376 m_inSynchronousPostLayout = true;
1377 // Calls resumeScheduledEvents()
1378 performPostLayoutTasks();
1379 m_inSynchronousPostLayout = false;
1383 if (!m_postLayoutTasksTimer.isActive() && (needsLayout() || m_inSynchronousPostLayout || inChildFrameLayoutWithFrameFlattening)) {
1384 // If we need layout or are already in a synchronous call to postLayoutTasks(),
1385 // defer widget updates and event dispatch until after we return. postLayoutTasks()
1386 // can make us need to update again, and we can get stuck in a nasty cycle unless
1387 // we call it through the timer here.
1388 m_postLayoutTasksTimer.startOneShot(0);
1389 if (needsLayout()) {
1390 m_actionScheduler->pause();
1395 m_actionScheduler->resume();
1398 InspectorInstrumentation::didLayout(cookie, root);
1400 m_nestedLayoutCount--;
1401 if (m_nestedLayoutCount)
1404 Page* page = frame() ? frame()->page() : 0;
1408 page->chrome()->client()->layoutUpdated(frame());
1411 RenderBox* FrameView::embeddedContentBox() const
1414 RenderView* renderView = this->renderView();
1418 RenderObject* firstChild = renderView->firstChild();
1419 if (!firstChild || !firstChild->isBox())
1422 // Curently only embedded SVG documents participate in the size-negotiation logic.
1423 if (firstChild->isSVGRoot())
1424 return toRenderBox(firstChild);
1430 void FrameView::addWidgetToUpdate(RenderObject* object)
1432 if (!m_widgetUpdateSet)
1433 m_widgetUpdateSet = adoptPtr(new RenderObjectSet);
1435 // Tell the DOM element that it needs a widget update.
1436 Node* node = object->node();
1437 if (node->hasTagName(objectTag) || node->hasTagName(embedTag)) {
1438 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(node);
1439 pluginElement->setNeedsWidgetUpdate(true);
1442 m_widgetUpdateSet->add(object);
1445 void FrameView::removeWidgetToUpdate(RenderObject* object)
1447 if (!m_widgetUpdateSet)
1450 m_widgetUpdateSet->remove(object);
1453 void FrameView::setMediaType(const String& mediaType)
1455 m_mediaType = mediaType;
1458 String FrameView::mediaType() const
1460 // See if we have an override type.
1461 String overrideType = m_frame->loader()->client()->overrideMediaType();
1462 InspectorInstrumentation::applyEmulatedMedia(m_frame.get(), &overrideType);
1463 if (!overrideType.isNull())
1464 return overrideType;
1468 void FrameView::adjustMediaTypeForPrinting(bool printing)
1471 if (m_mediaTypeWhenNotPrinting.isNull())
1472 m_mediaTypeWhenNotPrinting = mediaType();
1473 setMediaType("print");
1475 if (!m_mediaTypeWhenNotPrinting.isNull())
1476 setMediaType(m_mediaTypeWhenNotPrinting);
1477 m_mediaTypeWhenNotPrinting = String();
1481 bool FrameView::useSlowRepaints(bool considerOverlap) const
1483 bool mustBeSlow = m_slowRepaintObjectCount > 0 || (platformWidget() && hasViewportConstrainedObjects());
1485 // FIXME: WidgetMac.mm makes the assumption that useSlowRepaints ==
1486 // m_contentIsOpaque, so don't take the fast path for composited layers
1487 // if they are a platform widget in order to get painting correctness
1488 // for transparent layers. See the comment in WidgetMac::paint.
1489 if (contentsInCompositedLayer() && !platformWidget())
1492 #if PLATFORM(CHROMIUM)
1493 // The chromium compositor does not support scrolling a non-composited frame within a composited page through
1494 // the fast scrolling path, so force slow scrolling in that case.
1495 if (m_frame->ownerElement() && !hasCompositedContent() && m_frame->page() && m_frame->page()->mainFrame()->view()->hasCompositedContent())
1499 bool isOverlapped = m_isOverlapped && considerOverlap;
1501 if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque)
1504 if (FrameView* parentView = parentFrameView())
1505 return parentView->useSlowRepaints(considerOverlap);
1510 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1512 return useSlowRepaints(false);
1515 void FrameView::updateCanBlitOnScrollRecursively()
1517 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1518 if (FrameView* view = frame->view())
1519 view->setCanBlitOnScroll(!view->useSlowRepaints());
1523 bool FrameView::contentsInCompositedLayer() const
1525 #if USE(ACCELERATED_COMPOSITING)
1526 RenderView* renderView = this->renderView();
1527 if (renderView && renderView->isComposited()) {
1528 GraphicsLayer* layer = renderView->layer()->backing()->graphicsLayer();
1529 if (layer && layer->drawsContent())
1536 void FrameView::setCannotBlitToWindow()
1538 m_cannotBlitToWindow = true;
1539 updateCanBlitOnScrollRecursively();
1542 void FrameView::addSlowRepaintObject()
1544 if (!m_slowRepaintObjectCount++) {
1545 updateCanBlitOnScrollRecursively();
1547 if (Page* page = m_frame->page()) {
1548 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1549 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1554 void FrameView::removeSlowRepaintObject()
1556 ASSERT(m_slowRepaintObjectCount > 0);
1557 m_slowRepaintObjectCount--;
1558 if (!m_slowRepaintObjectCount) {
1559 updateCanBlitOnScrollRecursively();
1561 if (Page* page = m_frame->page()) {
1562 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1563 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1568 void FrameView::addViewportConstrainedObject(RenderObject* object)
1570 if (!m_viewportConstrainedObjects)
1571 m_viewportConstrainedObjects = adoptPtr(new ViewportConstrainedObjectSet);
1573 if (!m_viewportConstrainedObjects->contains(object)) {
1574 m_viewportConstrainedObjects->add(object);
1575 if (platformWidget())
1576 updateCanBlitOnScrollRecursively();
1578 if (Page* page = m_frame->page()) {
1579 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1580 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1585 void FrameView::removeViewportConstrainedObject(RenderObject* object)
1587 if (m_viewportConstrainedObjects && m_viewportConstrainedObjects->contains(object)) {
1588 m_viewportConstrainedObjects->remove(object);
1589 if (Page* page = m_frame->page()) {
1590 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1591 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1594 // FIXME: In addFixedObject() we only call this if there's a platform widget,
1595 // why isn't the same check being made here?
1596 updateCanBlitOnScrollRecursively();
1600 LayoutRect FrameView::viewportConstrainedVisibleContentRect() const
1602 LayoutRect viewportRect = visibleContentRect();
1603 viewportRect.setLocation(toPoint(scrollOffsetForFixedPosition()));
1604 return viewportRect;
1607 IntSize FrameView::scrollOffsetForFixedPosition(const IntRect& visibleContentRect, const IntSize& totalContentsSize, const IntPoint& scrollPosition, const IntPoint& scrollOrigin, float frameScaleFactor, bool fixedElementsLayoutRelativeToFrame, int headerHeight, int footerHeight)
1609 IntPoint constrainedPosition = ScrollableArea::constrainScrollPositionForOverhang(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, headerHeight, footerHeight);
1611 IntSize maxSize = totalContentsSize - visibleContentRect.size();
1613 float dragFactorX = (fixedElementsLayoutRelativeToFrame || !maxSize.width()) ? 1 : (totalContentsSize.width() - visibleContentRect.width() * frameScaleFactor) / maxSize.width();
1614 float dragFactorY = (fixedElementsLayoutRelativeToFrame || !maxSize.height()) ? 1 : (totalContentsSize.height() - visibleContentRect.height() * frameScaleFactor) / maxSize.height();
1616 return IntSize(constrainedPosition.x() * dragFactorX / frameScaleFactor, constrainedPosition.y() * dragFactorY / frameScaleFactor);
1619 IntSize FrameView::scrollOffsetForFixedPosition() const
1621 IntRect visibleContentRect = this->visibleContentRect();
1622 IntSize totalContentsSize = this->totalContentsSize();
1623 IntPoint scrollPosition = this->scrollPosition();
1624 IntPoint scrollOrigin = this->scrollOrigin();
1625 float frameScaleFactor = m_frame ? m_frame->frameScaleFactor() : 1;
1626 return scrollOffsetForFixedPosition(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, frameScaleFactor, fixedElementsLayoutRelativeToFrame(), headerHeight(), footerHeight());
1629 bool FrameView::fixedElementsLayoutRelativeToFrame() const
1632 if (!m_frame->settings())
1635 return m_frame->settings()->fixedElementsLayoutRelativeToFrame();
1638 IntPoint FrameView::lastKnownMousePosition() const
1640 return m_frame ? m_frame->eventHandler()->lastKnownMousePosition() : IntPoint();
1643 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1645 if (!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty()) {
1646 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1650 const bool isCompositedContentLayer = contentsInCompositedLayer();
1652 // Get the rects of the fixed objects visible in the rectToScroll
1653 Region regionToUpdate;
1654 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end();
1655 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) {
1656 RenderObject* renderer = *it;
1657 if (!renderer->style()->hasViewportConstrainedPosition())
1659 #if USE(ACCELERATED_COMPOSITING)
1660 if (renderer->isComposited())
1664 // Fixed items should always have layers.
1665 ASSERT(renderer->hasLayer());
1666 RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
1668 #if USE(ACCELERATED_COMPOSITING)
1669 if (layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForBoundsOutOfView
1670 || layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForNoVisibleContent) {
1671 // Don't invalidate for invisible fixed layers.
1676 #if ENABLE(CSS_FILTERS)
1677 if (layer->hasAncestorWithFilterOutsets()) {
1678 // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot
1679 // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
1683 IntRect updateRect = pixelSnappedIntRect(layer->repaintRectIncludingNonCompositingDescendants());
1684 updateRect = contentsToRootView(updateRect);
1685 if (!isCompositedContentLayer && clipsRepaints())
1686 updateRect.intersect(rectToScroll);
1687 if (!updateRect.isEmpty())
1688 regionToUpdate.unite(updateRect);
1692 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1694 // 2) update the area of fixed objects that has been invalidated
1695 Vector<IntRect> subRectsToUpdate = regionToUpdate.rects();
1696 size_t viewportConstrainedObjectsCount = subRectsToUpdate.size();
1697 for (size_t i = 0; i < viewportConstrainedObjectsCount; ++i) {
1698 IntRect updateRect = subRectsToUpdate[i];
1699 IntRect scrolledRect = updateRect;
1700 scrolledRect.move(scrollDelta);
1701 updateRect.unite(scrolledRect);
1702 #if USE(ACCELERATED_COMPOSITING)
1703 if (isCompositedContentLayer) {
1704 updateRect = rootViewToContents(updateRect);
1705 ASSERT(renderView());
1706 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
1710 if (clipsRepaints())
1711 updateRect.intersect(rectToScroll);
1712 hostWindow()->invalidateContentsAndRootView(updateRect, false);
1718 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1720 #if USE(ACCELERATED_COMPOSITING)
1721 if (contentsInCompositedLayer()) {
1722 IntRect updateRect = visibleContentRect();
1724 // Make sure to "apply" the scale factor here since we're converting from frame view
1725 // coordinates to layer backing coordinates.
1726 updateRect.scale(1 / m_frame->frameScaleFactor());
1728 ASSERT(renderView());
1729 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
1731 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1732 if (isEnclosedInCompositingLayer()) {
1733 LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1734 frameRenderer->borderTop() + frameRenderer->paddingTop(),
1735 visibleWidth(), visibleHeight());
1736 frameRenderer->repaintRectangle(rect);
1742 ScrollView::scrollContentsSlowPath(updateRect);
1745 // Note that this gets called at painting time.
1746 void FrameView::setIsOverlapped(bool isOverlapped)
1748 if (isOverlapped == m_isOverlapped)
1751 m_isOverlapped = isOverlapped;
1752 updateCanBlitOnScrollRecursively();
1754 #if USE(ACCELERATED_COMPOSITING)
1755 if (hasCompositedContentIncludingDescendants()) {
1756 // Overlap can affect compositing tests, so if it changes, we need to trigger
1757 // a layer update in the parent document.
1758 if (Frame* parentFrame = m_frame->tree()->parent()) {
1759 if (RenderView* parentView = parentFrame->contentRenderer()) {
1760 RenderLayerCompositor* compositor = parentView->compositor();
1761 compositor->setCompositingLayersNeedRebuild();
1762 compositor->scheduleCompositingLayerUpdate();
1766 if (RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) {
1767 // We also need to trigger reevaluation for this and all descendant frames,
1768 // since a frame uses compositing if any ancestor is compositing.
1769 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1770 if (RenderView* view = frame->contentRenderer()) {
1771 RenderLayerCompositor* compositor = view->compositor();
1772 compositor->setCompositingLayersNeedRebuild();
1773 compositor->scheduleCompositingLayerUpdate();
1781 bool FrameView::isOverlappedIncludingAncestors() const
1786 if (FrameView* parentView = parentFrameView()) {
1787 if (parentView->isOverlapped())
1794 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1796 if (contentIsOpaque == m_contentIsOpaque)
1799 m_contentIsOpaque = contentIsOpaque;
1800 updateCanBlitOnScrollRecursively();
1803 void FrameView::restoreScrollbar()
1805 setScrollbarsSuppressed(false);
1808 bool FrameView::scrollToFragment(const KURL& url)
1810 // If our URL has no ref, then we have no place we need to jump to.
1811 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1812 // and possibly repaint because :target pseudo class may have been
1813 // set (see bug 11321).
1814 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1817 String fragmentIdentifier = url.fragmentIdentifier();
1818 if (scrollToAnchor(fragmentIdentifier))
1821 // Try again after decoding the ref, based on the document's encoding.
1822 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1823 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1828 bool FrameView::scrollToAnchor(const String& name)
1830 ASSERT(m_frame->document());
1832 if (!m_frame->document()->haveStylesheetsLoaded()) {
1833 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1837 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1839 Element* anchorNode = m_frame->document()->findAnchor(name);
1841 // Setting to null will clear the current target.
1842 m_frame->document()->setCSSTarget(anchorNode);
1845 if (m_frame->document()->isSVGDocument()) {
1846 if (SVGSVGElement* svg = toSVGDocument(m_frame->document())->rootElement()) {
1847 svg->setupInitialView(name, anchorNode);
1854 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1855 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1858 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1862 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1864 m_maintainScrollPositionAnchor = anchorNode;
1865 if (!m_maintainScrollPositionAnchor)
1868 // We need to update the layout before scrolling, otherwise we could
1869 // really mess things up if an anchor scroll comes at a bad moment.
1870 m_frame->document()->updateStyleIfNeeded();
1871 // Only do a layout if changes have occurred that make it necessary.
1872 RenderView* renderView = this->renderView();
1873 if (renderView && renderView->needsLayout())
1879 void FrameView::scrollElementToRect(Element* element, const IntRect& rect)
1881 m_frame->document()->updateLayoutIgnorePendingStylesheets();
1883 LayoutRect bounds = element->boundingBox();
1884 int centeringOffsetX = (rect.width() - bounds.width()) / 2;
1885 int centeringOffsetY = (rect.height() - bounds.height()) / 2;
1886 setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y()));
1889 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1891 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1892 m_maintainScrollPositionAnchor = 0;
1894 IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint);
1896 if (newScrollPosition == scrollPosition())
1899 if (requestScrollPositionUpdate(newScrollPosition))
1902 ScrollView::setScrollPosition(newScrollPosition);
1905 void FrameView::delegatesScrollingDidChange()
1907 #if USE(ACCELERATED_COMPOSITING)
1908 // When we switch to delgatesScrolling mode, we should destroy the scrolling/clipping layers in RenderLayerCompositor.
1909 if (hasCompositedContent())
1910 clearBackingStores();
1914 void FrameView::setFixedVisibleContentRect(const IntRect& visibleContentRect)
1916 bool visibleContentSizeDidChange = false;
1917 if (visibleContentRect.size() != this->fixedVisibleContentRect().size()) {
1918 // When the viewport size changes or the content is scaled, we need to
1919 // reposition the fixed and sticky positioned elements.
1920 setViewportConstrainedObjectsNeedLayout();
1921 visibleContentSizeDidChange = true;
1924 IntSize offset = scrollOffset();
1925 ScrollView::setFixedVisibleContentRect(visibleContentRect);
1926 if (offset != scrollOffset()) {
1927 repaintFixedElementsAfterScrolling();
1928 if (m_frame->page()->settings()->acceleratedCompositingForFixedPositionEnabled())
1929 updateFixedElementsAfterScrolling();
1930 scrollAnimator()->setCurrentPosition(scrollPosition());
1931 scrollPositionChanged();
1933 if (visibleContentSizeDidChange) {
1934 // Update the scroll-bars to calculate new page-step size.
1935 updateScrollbars(scrollOffset());
1937 frame()->loader()->client()->didChangeScrollOffset();
1940 void FrameView::setViewportConstrainedObjectsNeedLayout()
1942 if (!hasViewportConstrainedObjects())
1945 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end();
1946 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) {
1947 RenderObject* renderer = *it;
1948 renderer->setNeedsLayout(true);
1953 void FrameView::scrollPositionChangedViaPlatformWidget()
1955 repaintFixedElementsAfterScrolling();
1956 updateFixedElementsAfterScrolling();
1957 scrollPositionChanged();
1960 void FrameView::scrollPositionChanged()
1962 frame()->eventHandler()->sendScrollEvent();
1963 frame()->eventHandler()->dispatchFakeMouseMoveEventSoon();
1965 #if USE(ACCELERATED_COMPOSITING)
1966 if (RenderView* renderView = this->renderView()) {
1967 if (renderView->usesCompositing())
1968 renderView->compositor()->frameViewDidScroll();
1973 void FrameView::repaintFixedElementsAfterScrolling()
1975 // For fixed position elements, update widget positions and compositing layers after scrolling,
1976 // but only if we're not inside of layout.
1977 if (!m_nestedLayoutCount && hasViewportConstrainedObjects()) {
1978 if (RenderView* renderView = this->renderView()) {
1979 renderView->updateWidgetPositions();
1980 renderView->layer()->updateLayerPositionsAfterDocumentScroll();
1985 bool FrameView::shouldUpdateFixedElementsAfterScrolling()
1987 #if ENABLE(THREADED_SCROLLING)
1988 Page* page = m_frame->page();
1992 // If the scrolling thread is updating the fixed elements, then the FrameView should not update them as well.
1993 if (page->mainFrame() != m_frame)
1996 ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
1997 if (!scrollingCoordinator)
2000 if (!scrollingCoordinator->supportsFixedPositionLayers())
2003 if (scrollingCoordinator->shouldUpdateScrollLayerPositionOnMainThread())
2006 if (inProgrammaticScroll())
2014 void FrameView::updateFixedElementsAfterScrolling()
2016 #if USE(ACCELERATED_COMPOSITING)
2017 if (!shouldUpdateFixedElementsAfterScrolling())
2020 if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) {
2021 if (RenderView* renderView = this->renderView())
2022 renderView->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
2027 bool FrameView::shouldRubberBandInDirection(ScrollDirection direction) const
2029 Page* page = frame() ? frame()->page() : 0;
2031 return ScrollView::shouldRubberBandInDirection(direction);
2032 return page->chrome()->client()->shouldRubberBandInDirection(direction);
2035 bool FrameView::isRubberBandInProgress() const
2037 if (scrollbarsSuppressed())
2040 // If the scrolling thread updates the scroll position for this FrameView, then we should return
2041 // ScrollingCoordinator::isRubberBandInProgress().
2042 if (Page* page = m_frame->page()) {
2043 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
2044 if (!scrollingCoordinator->shouldUpdateScrollLayerPositionOnMainThread())
2045 return scrollingCoordinator->isRubberBandInProgress();
2049 // If the main thread updates the scroll position for this FrameView, we should return
2050 // ScrollAnimator::isRubberBandInProgress().
2051 if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
2052 return scrollAnimator->isRubberBandInProgress();
2057 bool FrameView::requestScrollPositionUpdate(const IntPoint& position)
2059 #if ENABLE(THREADED_SCROLLING)
2060 if (TiledBacking* tiledBacking = this->tiledBacking()) {
2061 IntRect visibleRect = visibleContentRect();
2062 visibleRect.setLocation(position);
2063 tiledBacking->prepopulateRect(visibleRect);
2066 if (Page* page = m_frame->page()) {
2067 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2068 return scrollingCoordinator->requestScrollPositionUpdate(this, position);
2071 UNUSED_PARAM(position);
2077 HostWindow* FrameView::hostWindow() const
2079 Page* page = frame() ? frame()->page() : 0;
2082 return page->chrome();
2085 const unsigned cRepaintRectUnionThreshold = 25;
2087 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
2089 ASSERT(!m_frame->ownerElement());
2091 if (m_isTrackingRepaints) {
2092 IntRect repaintRect = r;
2093 repaintRect.move(-scrollOffset());
2094 m_trackedRepaintRects.append(repaintRect);
2097 double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay();
2098 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
2099 IntRect paintRect = r;
2100 if (clipsRepaints() && !paintsEntireContents())
2101 paintRect.intersect(visibleContentRect());
2102 if (paintRect.isEmpty())
2104 if (m_repaintCount == cRepaintRectUnionThreshold) {
2105 IntRect unionedRect;
2106 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
2107 unionedRect.unite(pixelSnappedIntRect(m_repaintRects[i]));
2108 m_repaintRects.clear();
2109 m_repaintRects.append(unionedRect);
2111 if (m_repaintCount < cRepaintRectUnionThreshold)
2112 m_repaintRects.append(paintRect);
2114 m_repaintRects[0].unite(paintRect);
2117 if (!m_deferringRepaints)
2118 startDeferredRepaintTimer(delay);
2123 if (!shouldUpdate(immediate))
2126 #if USE(TILED_BACKING_STORE)
2127 if (frame()->tiledBackingStore()) {
2128 frame()->tiledBackingStore()->invalidate(r);
2132 ScrollView::repaintContentRectangle(r, immediate);
2135 void FrameView::contentsResized()
2137 ScrollView::contentsResized();
2141 void FrameView::visibleContentsResized()
2143 // We check to make sure the view is attached to a frame() as this method can
2144 // be triggered before the view is attached by Frame::createView(...) setting
2145 // various values such as setScrollBarModes(...) for example. An ASSERT is
2146 // triggered when a view is layout before being attached to a frame().
2147 if (!frame()->view())
2150 if (!useFixedLayout() && needsLayout())
2153 #if USE(ACCELERATED_COMPOSITING)
2154 if (RenderView* renderView = this->renderView()) {
2155 if (renderView->usesCompositing())
2156 renderView->compositor()->frameViewDidChangeSize();
2161 void FrameView::beginDeferredRepaints()
2163 Page* page = m_frame->page();
2164 if (page->mainFrame() != m_frame) {
2165 page->mainFrame()->view()->beginDeferredRepaints();
2169 m_deferringRepaints++;
2172 void FrameView::endDeferredRepaints()
2174 Page* page = m_frame->page();
2175 if (page->mainFrame() != m_frame) {
2176 page->mainFrame()->view()->endDeferredRepaints();
2180 ASSERT(m_deferringRepaints > 0);
2182 if (--m_deferringRepaints)
2185 if (m_deferredRepaintTimer.isActive())
2188 if (double delay = adjustedDeferredRepaintDelay()) {
2189 startDeferredRepaintTimer(delay);
2193 doDeferredRepaints();
2196 void FrameView::startDeferredRepaintTimer(double delay)
2198 if (m_deferredRepaintTimer.isActive())
2201 if (m_disableRepaints)
2204 m_deferredRepaintTimer.startOneShot(delay);
2207 void FrameView::handleLoadCompleted()
2209 // Once loading has completed, allow autoSize one last opportunity to
2210 // reduce the size of the frame.
2211 autoSizeIfEnabled();
2212 if (shouldUseLoadTimeDeferredRepaintDelay())
2214 m_deferredRepaintDelay = s_normalDeferredRepaintDelay;
2215 flushDeferredRepaints();
2218 void FrameView::flushDeferredRepaints()
2220 if (!m_deferredRepaintTimer.isActive())
2222 m_deferredRepaintTimer.stop();
2223 doDeferredRepaints();
2226 void FrameView::doDeferredRepaints()
2228 if (m_disableRepaints)
2231 ASSERT(!m_deferringRepaints);
2232 if (!shouldUpdate()) {
2233 m_repaintRects.clear();
2237 unsigned size = m_repaintRects.size();
2238 for (unsigned i = 0; i < size; i++) {
2239 #if USE(TILED_BACKING_STORE)
2240 if (frame()->tiledBackingStore()) {
2241 frame()->tiledBackingStore()->invalidate(pixelSnappedIntRect(m_repaintRects[i]));
2245 ScrollView::repaintContentRectangle(pixelSnappedIntRect(m_repaintRects[i]), false);
2247 m_repaintRects.clear();
2250 updateDeferredRepaintDelayAfterRepaint();
2253 bool FrameView::shouldUseLoadTimeDeferredRepaintDelay() const
2255 // Don't defer after the initial load of the page has been completed.
2256 if (m_frame->tree()->top()->loader()->isComplete())
2258 Document* document = m_frame->document();
2261 if (document->parsing())
2263 if (document->cachedResourceLoader()->requestCount())
2268 void FrameView::updateDeferredRepaintDelayAfterRepaint()
2270 if (!shouldUseLoadTimeDeferredRepaintDelay()) {
2271 m_deferredRepaintDelay = s_normalDeferredRepaintDelay;
2274 double incrementedRepaintDelay = m_deferredRepaintDelay + s_deferredRepaintDelayIncrementDuringLoading;
2275 m_deferredRepaintDelay = std::min(incrementedRepaintDelay, s_maxDeferredRepaintDelayDuringLoading);
2278 void FrameView::resetDeferredRepaintDelay()
2280 m_deferredRepaintDelay = 0;
2281 if (m_deferredRepaintTimer.isActive()) {
2282 m_deferredRepaintTimer.stop();
2283 if (!m_deferringRepaints)
2284 doDeferredRepaints();
2288 double FrameView::adjustedDeferredRepaintDelay() const
2290 ASSERT(!m_deferringRepaints);
2291 if (!m_deferredRepaintDelay)
2293 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
2294 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
2297 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
2299 doDeferredRepaints();
2302 void FrameView::beginDisableRepaints()
2304 m_disableRepaints++;
2307 void FrameView::endDisableRepaints()
2309 ASSERT(m_disableRepaints > 0);
2310 m_disableRepaints--;
2313 void FrameView::layoutTimerFired(Timer<FrameView>*)
2315 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2316 if (!m_frame->document()->ownerElement())
2317 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
2322 void FrameView::scheduleRelayout()
2324 // FIXME: We should assert the page is not in the page cache, but that is causing
2325 // too many false assertions. See <rdar://problem/7218118>.
2326 ASSERT(m_frame->view() == this);
2329 m_layoutRoot->markContainingBlocksForLayout(false);
2332 if (!m_layoutSchedulingEnabled)
2336 if (!m_frame->document()->shouldScheduleLayout())
2338 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2339 // When frame flattening is enabled, the contents of the frame could affect the layout of the parent frames.
2340 // Also invalidate parent frame starting from the owner element of this frame.
2341 if (m_frame->ownerRenderer() && isInChildFrameWithFrameFlattening())
2342 m_frame->ownerRenderer()->setNeedsLayout(true, MarkContainingBlockChain);
2344 int delay = m_frame->document()->minimumLayoutDelay();
2345 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
2346 unscheduleRelayout();
2347 if (m_layoutTimer.isActive())
2350 m_delayedLayout = delay != 0;
2352 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2353 if (!m_frame->document()->ownerElement())
2354 printf("Scheduling layout for %d\n", delay);
2357 m_layoutTimer.startOneShot(delay * 0.001);
2360 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
2362 for (RenderObject* r = descendant; r; r = r->container()) {
2369 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
2371 ASSERT(m_frame->view() == this);
2373 RenderView* renderView = this->renderView();
2374 if (renderView && renderView->needsLayout()) {
2376 relayoutRoot->markContainingBlocksForLayout(false);
2380 if (layoutPending() || !m_layoutSchedulingEnabled) {
2381 if (m_layoutRoot != relayoutRoot) {
2382 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
2383 // Keep the current root
2384 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
2385 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2386 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
2387 // Re-root at relayoutRoot
2388 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
2389 m_layoutRoot = relayoutRoot;
2390 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2391 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2393 // Just do a full relayout
2395 m_layoutRoot->markContainingBlocksForLayout(false);
2397 relayoutRoot->markContainingBlocksForLayout(false);
2398 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2401 } else if (m_layoutSchedulingEnabled) {
2402 int delay = m_frame->document()->minimumLayoutDelay();
2403 m_layoutRoot = relayoutRoot;
2404 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2405 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2406 m_delayedLayout = delay != 0;
2407 m_layoutTimer.startOneShot(delay * 0.001);
2411 bool FrameView::layoutPending() const
2413 return m_layoutTimer.isActive();
2416 bool FrameView::needsLayout() const
2418 // This can return true in cases where the document does not have a body yet.
2419 // Document::shouldScheduleLayout takes care of preventing us from scheduling
2420 // layout in that case.
2424 RenderView* renderView = this->renderView();
2425 return layoutPending()
2426 || (renderView && renderView->needsLayout())
2428 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
2431 void FrameView::setNeedsLayout()
2433 if (m_deferSetNeedsLayouts) {
2434 m_setNeedsLayoutWasDeferred = true;
2438 if (RenderView* renderView = this->renderView())
2439 renderView->setNeedsLayout(true);
2442 void FrameView::unscheduleRelayout()
2444 if (!m_layoutTimer.isActive())
2447 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2448 if (!m_frame->document()->ownerElement())
2449 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
2452 m_layoutTimer.stop();
2453 m_delayedLayout = false;
2456 #if ENABLE(REQUEST_ANIMATION_FRAME)
2457 void FrameView::serviceScriptedAnimations(double monotonicAnimationStartTime)
2459 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext()) {
2460 frame->view()->serviceScrollAnimations();
2461 frame->animation()->serviceAnimations();
2464 Vector<RefPtr<Document> > documents;
2465 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext())
2466 documents.append(frame->document());
2468 for (size_t i = 0; i < documents.size(); ++i)
2469 documents[i]->serviceScriptedAnimations(monotonicAnimationStartTime);
2473 bool FrameView::isTransparent() const
2475 return m_isTransparent;
2478 void FrameView::setTransparent(bool isTransparent)
2480 m_isTransparent = isTransparent;
2483 bool FrameView::hasOpaqueBackground() const
2485 return !m_isTransparent && !m_baseBackgroundColor.hasAlpha();
2488 Color FrameView::baseBackgroundColor() const
2490 return m_baseBackgroundColor;
2493 void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
2495 if (!backgroundColor.isValid())
2496 m_baseBackgroundColor = Color::white;
2498 m_baseBackgroundColor = backgroundColor;
2500 recalculateScrollbarOverlayStyle();
2503 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
2505 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
2506 if (FrameView* view = frame->view()) {
2507 view->setTransparent(transparent);
2508 view->setBaseBackgroundColor(backgroundColor);
2513 bool FrameView::shouldUpdateWhileOffscreen() const
2515 return m_shouldUpdateWhileOffscreen;
2518 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
2520 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
2523 bool FrameView::shouldUpdate(bool immediateRequested) const
2525 if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen())
2530 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
2532 m_actionScheduler->scheduleEvent(event, eventTarget);
2535 void FrameView::pauseScheduledEvents()
2537 m_actionScheduler->pause();
2540 void FrameView::resumeScheduledEvents()
2542 m_actionScheduler->resume();
2545 void FrameView::scrollToAnchor()
2547 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
2551 if (!anchorNode->renderer())
2555 if (anchorNode != m_frame->document())
2556 rect = anchorNode->boundingBox();
2558 // Scroll nested layers and frames to reveal the anchor.
2559 // Align to the top and to the closest side (this matches other browsers).
2560 anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
2562 if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache())
2563 cache->handleScrolledToAnchor(anchorNode.get());
2565 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
2566 m_maintainScrollPositionAnchor = anchorNode;
2569 void FrameView::updateWidget(RenderObject* object)
2571 ASSERT(!object->node() || object->node()->isElementNode());
2572 Element* ownerElement = toElement(object->node());
2573 // The object may have already been destroyed (thus node cleared),
2574 // but FrameView holds a manual ref, so it won't have been deleted.
2575 ASSERT(m_widgetUpdateSet->contains(object));
2579 if (object->isEmbeddedObject()) {
2580 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
2581 // No need to update if it's already crashed or known to be missing.
2582 if (embeddedObject->showsUnavailablePluginIndicator())
2585 if (object->isSnapshottedPlugIn()) {
2586 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag)) {
2587 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement);
2588 pluginElement->updateSnapshotInfo();
2593 // FIXME: This could turn into a real virtual dispatch if we defined
2594 // updateWidget(PluginCreationOption) on HTMLElement.
2595 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag) || ownerElement->hasTagName(appletTag)) {
2596 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement);
2597 if (pluginElement->needsWidgetUpdate())
2598 pluginElement->updateWidget(CreateAnyWidgetType);
2600 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
2601 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
2602 else if (ownerElement->isMediaElement())
2603 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
2606 ASSERT_NOT_REACHED();
2608 // Caution: it's possible the object was destroyed again, since loading a
2609 // plugin may run any arbitrary JavaScript.
2610 embeddedObject->updateWidgetPosition();
2614 bool FrameView::updateWidgets()
2616 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
2619 size_t size = m_widgetUpdateSet->size();
2621 Vector<RenderObject*> objects;
2622 objects.reserveInitialCapacity(size);
2624 RenderObjectSet::const_iterator end = m_widgetUpdateSet->end();
2625 for (RenderObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
2626 RenderObject* object = *it;
2627 objects.uncheckedAppend(object);
2628 if (object->isEmbeddedObject()) {
2629 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
2630 embeddedObject->ref();
2634 for (size_t i = 0; i < size; ++i) {
2635 RenderObject* object = objects[i];
2636 updateWidget(object);
2637 m_widgetUpdateSet->remove(object);
2640 RenderArena* arena = m_frame->document()->renderArena();
2641 for (size_t i = 0; i < size; ++i) {
2642 RenderObject* object = objects[i];
2643 if (object->isEmbeddedObject()) {
2644 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
2645 embeddedObject->deref(arena);
2649 return m_widgetUpdateSet->isEmpty();
2652 void FrameView::flushAnyPendingPostLayoutTasks()
2654 if (!m_postLayoutTasksTimer.isActive())
2657 performPostLayoutTasks();
2660 void FrameView::performPostLayoutTasks()
2662 m_postLayoutTasksTimer.stop();
2664 m_frame->selection()->setCaretRectNeedsUpdate();
2665 m_frame->selection()->updateAppearance();
2667 LayoutMilestones milestonesOfInterest = 0;
2668 LayoutMilestones milestonesAchieved = 0;
2669 Page* page = m_frame->page();
2671 milestonesOfInterest = page->layoutMilestones();
2673 if (m_nestedLayoutCount <= 1) {
2674 if (m_firstLayoutCallbackPending) {
2675 m_firstLayoutCallbackPending = false;
2676 m_frame->loader()->didFirstLayout();
2677 if (milestonesOfInterest & DidFirstLayout)
2678 milestonesAchieved |= DidFirstLayout;
2680 if (page->mainFrame() == m_frame)
2681 page->startCountingRelevantRepaintedObjects();
2685 // Ensure that we always send this eventually.
2686 if (!m_frame->document()->parsing() && m_frame->loader()->stateMachine()->committedFirstRealDocumentLoad())
2687 m_isVisuallyNonEmpty = true;
2689 // If the layout was done with pending sheets, we are not in fact visually non-empty yet.
2690 if (m_isVisuallyNonEmpty && !m_frame->document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) {
2691 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
2692 if (milestonesOfInterest & DidFirstVisuallyNonEmptyLayout)
2693 milestonesAchieved |= DidFirstVisuallyNonEmptyLayout;
2697 m_frame->loader()->didLayout(milestonesAchieved);
2698 #if ENABLE(FONT_LOAD_EVENTS)
2699 if (RuntimeEnabledFeatures::fontLoadEventsEnabled())
2700 m_frame->document()->fontloader()->didLayout();
2703 // FIXME: We should consider adding DidLayout as a LayoutMilestone. That would let us merge this
2704 // with didLayout(LayoutMilestones).
2705 m_frame->loader()->client()->dispatchDidLayout();
2707 RenderView* renderView = this->renderView();
2709 renderView->updateWidgetPositions();
2711 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
2712 if (updateWidgets())
2717 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2718 scrollingCoordinator->frameViewLayoutUpdated(this);
2721 #if USE(ACCELERATED_COMPOSITING)
2722 if (renderView && renderView->usesCompositing())
2723 renderView->compositor()->frameViewDidLayout();
2728 m_actionScheduler->resume();
2730 if (renderView && !renderView->printing()) {
2731 IntSize currentSize;
2732 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
2733 currentSize = fixedLayoutSize();
2735 currentSize = visibleContentRect(IncludeScrollbars).size();
2736 float currentZoomFactor = renderView->style()->zoom();
2737 bool resized = !m_firstLayout && (currentSize != m_lastViewportSize || currentZoomFactor != m_lastZoomFactor);
2738 m_lastViewportSize = currentSize;
2739 m_lastZoomFactor = currentZoomFactor;
2741 m_frame->eventHandler()->sendResizeEvent();
2743 #if ENABLE(INSPECTOR)
2744 if (InspectorInstrumentation::hasFrontends()) {
2746 if (page->mainFrame() == m_frame) {
2747 if (InspectorClient* inspectorClient = page->inspectorController()->inspectorClient())
2748 inspectorClient->didResizeMainFrame(m_frame.get());
2757 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
2759 performPostLayoutTasks();
2762 void FrameView::autoSizeIfEnabled()
2764 if (!m_shouldAutoSize)
2770 TemporaryChange<bool> changeInAutoSize(m_inAutoSize, true);
2772 Document* document = frame()->document();
2776 RenderView* documentView = document->renderView();
2777 Element* documentElement = document->documentElement();
2778 if (!documentView || !documentElement)
2781 // Start from the minimum height and allow it to grow.
2782 resize(frameRect().width(), m_minAutoSize.height());
2784 IntSize size = frameRect().size();
2786 // Do the resizing twice. The first time is basically a rough calculation using the preferred width
2787 // which may result in a height change during the second iteration.
2788 for (int i = 0; i < 2; i++) {
2789 // Update various sizes including contentsSize, scrollHeight, etc.
2790 document->updateLayoutIgnorePendingStylesheets();
2791 int width = documentView->minPreferredLogicalWidth();
2792 int height = documentView->documentRect().height();
2793 IntSize newSize(width, height);
2795 // Check to see if a scrollbar is needed for a given dimension and
2796 // if so, increase the other dimension to account for the scrollbar.
2797 // Since the dimensions are only for the view rectangle, once a
2798 // dimension exceeds the maximum, there is no need to increase it further.
2799 if (newSize.width() > m_maxAutoSize.width()) {
2800 RefPtr<Scrollbar> localHorizontalScrollbar = horizontalScrollbar();
2801 if (!localHorizontalScrollbar)
2802 localHorizontalScrollbar = createScrollbar(HorizontalScrollbar);
2803 if (!localHorizontalScrollbar->isOverlayScrollbar())
2804 newSize.setHeight(newSize.height() + localHorizontalScrollbar->height());
2806 // Don't bother checking for a vertical scrollbar because the width is at
2807 // already greater the maximum.
2808 } else if (newSize.height() > m_maxAutoSize.height()) {
2809 RefPtr<Scrollbar> localVerticalScrollbar = verticalScrollbar();
2810 if (!localVerticalScrollbar)
2811 localVerticalScrollbar = createScrollbar(VerticalScrollbar);
2812 if (!localVerticalScrollbar->isOverlayScrollbar())
2813 newSize.setWidth(newSize.width() + localVerticalScrollbar->width());
2815 // Don't bother checking for a horizontal scrollbar because the height is
2816 // already greater the maximum.
2819 // Ensure the size is at least the min bounds.
2820 newSize = newSize.expandedTo(m_minAutoSize);
2822 // Bound the dimensions by the max bounds and determine what scrollbars to show.
2823 ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff;
2824 if (newSize.width() > m_maxAutoSize.width()) {
2825 newSize.setWidth(m_maxAutoSize.width());
2826 horizonalScrollbarMode = ScrollbarAlwaysOn;
2828 ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff;
2829 if (newSize.height() > m_maxAutoSize.height()) {
2830 newSize.setHeight(m_maxAutoSize.height());
2831 verticalScrollbarMode = ScrollbarAlwaysOn;
2834 if (newSize == size)
2837 // While loading only allow the size to increase (to avoid twitching during intermediate smaller states)
2838 // unless autoresize has just been turned on or the maximum size is smaller than the current size.
2839 if (m_didRunAutosize && size.height() <= m_maxAutoSize.height() && size.width() <= m_maxAutoSize.width()
2840 && !frame()->loader()->isComplete() && (newSize.height() < size.height() || newSize.width() < size.width()))
2843 resize(newSize.width(), newSize.height());
2844 // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example,
2845 // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed).
2846 setVerticalScrollbarLock(false);
2847 setHorizontalScrollbarLock(false);
2848 setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true);
2850 m_didRunAutosize = true;
2853 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
2855 if (!m_viewportRenderer)
2858 if (m_overflowStatusDirty) {
2859 m_horizontalOverflow = horizontalOverflow;
2860 m_verticalOverflow = verticalOverflow;
2861 m_overflowStatusDirty = false;
2865 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
2866 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
2868 if (horizontalOverflowChanged || verticalOverflowChanged) {
2869 m_horizontalOverflow = horizontalOverflow;
2870 m_verticalOverflow = verticalOverflow;
2872 m_actionScheduler->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
2873 verticalOverflowChanged, verticalOverflow),
2874 m_viewportRenderer->node());
2879 const Pagination& FrameView::pagination() const
2881 if (m_pagination != Pagination())
2882 return m_pagination;
2884 if (Page* page = m_frame->page()) {
2885 if (page->mainFrame() == m_frame)
2886 return page->pagination();
2889 return m_pagination;
2892 void FrameView::setPagination(const Pagination& pagination)
2894 if (m_pagination == pagination)
2897 m_pagination = pagination;
2900 m_frame->document()->styleResolverChanged(DeferRecalcStyle);
2903 IntRect FrameView::windowClipRect(bool clipToContents) const
2905 ASSERT(m_frame->view() == this);
2907 if (paintsEntireContents())
2908 return IntRect(IntPoint(), totalContentsSize());
2910 // Set our clip rect to be our contents.
2911 IntRect clipRect = contentsToWindow(visibleContentRect(clipToContents ? ExcludeScrollbars : IncludeScrollbars));
2912 if (!m_frame || !m_frame->ownerElement())
2915 // Take our owner element and get its clip rect.
2916 HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement();
2917 FrameView* parentView = ownerElement->document()->view();
2919 clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement, true));
2923 IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement, bool clipToLayerContents) const
2925 // The renderer can sometimes be null when style="display:none" interacts
2926 // with external content and plugins.
2927 if (!ownerElement->renderer())
2928 return windowClipRect();
2930 // If we have no layer, just return our window clip rect.
2931 const RenderLayer* enclosingLayer = ownerElement->renderer()->enclosingLayer();
2932 if (!enclosingLayer)
2933 return windowClipRect();
2935 // Apply the clip from the layer.
2937 if (clipToLayerContents)
2938 clipRect = pixelSnappedIntRect(enclosingLayer->childrenClipRect());
2940 clipRect = pixelSnappedIntRect(enclosingLayer->selfClipRect());
2941 clipRect = contentsToWindow(clipRect);
2942 return intersection(clipRect, windowClipRect());
2945 bool FrameView::isActive() const
2947 Page* page = frame()->page();
2948 return page && page->focusController()->isActive();
2951 void FrameView::scrollTo(const IntSize& newOffset)
2953 LayoutSize offset = scrollOffset();
2954 ScrollView::scrollTo(newOffset);
2955 if (offset != scrollOffset())
2956 scrollPositionChanged();
2957 frame()->loader()->client()->didChangeScrollOffset();
2960 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
2962 // Add in our offset within the FrameView.
2963 IntRect dirtyRect = rect;
2964 dirtyRect.moveBy(scrollbar->location());
2965 invalidateRect(dirtyRect);
2968 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
2970 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
2973 IntRect FrameView::windowResizerRect() const
2975 Page* page = frame() ? frame()->page() : 0;
2978 return page->chrome()->windowResizerRect();
2981 float FrameView::visibleContentScaleFactor() const
2983 if (!m_frame || !m_frame->page())
2986 if (!m_frame->settings()->applyPageScaleFactorInCompositor() || m_frame != m_frame->page()->mainFrame())
2989 return m_frame->page()->pageScaleFactor();
2992 void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
2994 Page* page = m_frame->page();
2997 if (page->mainFrame() != m_frame)
2999 page->chrome()->client()->notifyScrollerThumbIsVisibleInRect(scrollerThumb);
3002 bool FrameView::scrollbarsCanBeActive() const
3007 if (m_frame->view() != this)
3010 if (Page* page = m_frame->page()) {
3011 if (page->shouldSuppressScrollbarAnimations())
3015 if (Document* document = m_frame->document())
3016 return !document->inPageCache();
3021 ScrollableArea* FrameView::enclosingScrollableArea() const
3023 // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer.
3027 IntRect FrameView::scrollableAreaBoundingBox() const
3029 RenderPart* ownerRenderer = frame()->ownerRenderer();
3033 return ownerRenderer->absoluteContentQuad().enclosingBoundingBox();
3036 bool FrameView::isScrollable()
3039 // 1) If there an actual overflow.
3040 // 2) display:none or visibility:hidden set to self or inherited.
3041 // 3) overflow{-x,-y}: hidden;
3042 // 4) scrolling: no;
3045 IntSize totalContentsSize = this->totalContentsSize();
3046 IntSize visibleContentSize = visibleContentRect().size();
3047 if ((totalContentsSize.height() <= visibleContentSize.height() && totalContentsSize.width() <= visibleContentSize.width()))
3051 HTMLFrameOwnerElement* owner = m_frame->ownerElement();
3052 if (owner && (!owner->renderer() || !owner->renderer()->visibleToHitTesting()))
3056 ScrollbarMode horizontalMode;
3057 ScrollbarMode verticalMode;
3058 calculateScrollbarModesForLayout(horizontalMode, verticalMode, RulesFromWebContentOnly);
3059 if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff)
3065 void FrameView::updateScrollableAreaSet()
3067 // That ensures that only inner frames are cached.
3068 FrameView* parentFrameView = this->parentFrameView();
3069 if (!parentFrameView)
3072 if (!isScrollable()) {
3073 parentFrameView->removeScrollableArea(this);
3077 parentFrameView->addScrollableArea(this);
3080 bool FrameView::shouldSuspendScrollAnimations() const
3082 return m_frame->loader()->state() != FrameStateComplete;
3085 void FrameView::scrollbarStyleChanged(int newStyle, bool forceUpdate)
3087 Page* page = m_frame->page();
3090 if (page->mainFrame() != m_frame)
3092 page->chrome()->client()->recommendedScrollbarStyleDidChange(newStyle);
3095 ScrollView::scrollbarStyleChanged(newStyle, forceUpdate);
3098 void FrameView::setAnimatorsAreActive()
3100 Page* page = m_frame->page();
3104 if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
3105 scrollAnimator->setIsActive();
3107 if (!m_scrollableAreas)
3110 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
3111 ScrollableArea* scrollableArea = *it;
3113 ASSERT(scrollableArea->scrollbarsCanBeActive());
3114 scrollableArea->scrollAnimator()->setIsActive();
3118 void FrameView::notifyPageThatContentAreaWillPaint() const
3120 Page* page = m_frame->page();
3124 contentAreaWillPaint();
3126 if (!m_scrollableAreas)
3129 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
3130 ScrollableArea* scrollableArea = *it;
3132 if (!scrollableArea->scrollbarsCanBeActive())
3135 scrollableArea->contentAreaWillPaint();
3139 bool FrameView::scrollAnimatorEnabled() const
3141 #if ENABLE(SMOOTH_SCROLLING)
3142 if (Page* page = m_frame->page())
3143 return page->settings()->scrollAnimatorEnabled();
3149 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
3150 void FrameView::updateAnnotatedRegions()
3152 Document* document = m_frame->document();
3153 if (!document->hasAnnotatedRegions())
3155 Vector<AnnotatedRegionValue> newRegions;
3156 document->renderBox()->collectAnnotatedRegions(newRegions);
3157 if (newRegions == document->annotatedRegions())
3159 document->setAnnotatedRegions(newRegions);
3160 Page* page = m_frame->page();
3163 page->chrome()->client()->annotatedRegionsChanged();
3167 void FrameView::updateScrollCorner()
3169 RenderObject* renderer = 0;
3170 RefPtr<RenderStyle> cornerStyle;
3171 IntRect cornerRect = scrollCornerRect();
3173 if (!cornerRect.isEmpty()) {
3174 // Try the <body> element first as a scroll corner source.
3175 Document* doc = m_frame->document();
3176 Element* body = doc ? doc->body() : 0;
3177 if (body && body->renderer()) {
3178 renderer = body->renderer();
3179 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
3183 // If the <body> didn't have a custom style, then the root element might.
3184 Element* docElement = doc ? doc->documentElement() : 0;
3185 if (docElement && docElement->renderer()) {
3186 renderer = docElement->renderer();
3187 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
3192 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
3193 if (RenderPart* renderer = m_frame->ownerRenderer())
3194 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
3199 if (!m_scrollCorner)
3200 m_scrollCorner = RenderScrollbarPart::createAnonymous(renderer->document());
3201 m_scrollCorner->setStyle(cornerStyle.release());
3202 invalidateScrollCorner(cornerRect);
3203 } else if (m_scrollCorner) {
3204 m_scrollCorner->destroy();
3208 ScrollView::updateScrollCorner();
3211 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
3213 if (context->updatingControlTints()) {
3214 updateScrollCorner();
3218 if (m_scrollCorner) {
3219 bool needsBackgorund = m_frame->page() && m_frame->page()->mainFrame() == m_frame;
3220 if (needsBackgorund)
3221 context->fillRect(cornerRect, baseBackgroundColor(), ColorSpaceDeviceRGB);
3222 m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect);
3226 ScrollView::paintScrollCorner(context, cornerRect);
3229 void FrameView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
3231 bool needsBackgorund = bar->isCustomScrollbar() && (m_frame->page() && m_frame->page()->mainFrame() == m_frame);
3232 if (needsBackgorund) {
3233 IntRect toFill = bar->frameRect();
3234 toFill.intersect(rect);
3235 context->fillRect(toFill, baseBackgroundColor(), ColorSpaceDeviceRGB);
3238 ScrollView::paintScrollbar(context, bar, rect);
3241 Color FrameView::documentBackgroundColor() const
3243 // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of
3244 // the document and the body against the base background color of the frame view.
3245 // Background images are unfortunately impractical to include.
3247 // Return invalid Color objects whenever there is insufficient information.
3248 if (!frame()->document())
3251 Element* htmlElement = frame()->document()->documentElement();
3252 Element* bodyElement = frame()->document()->body();
3254 // Start with invalid colors.
3255 Color htmlBackgroundColor;
3256 Color bodyBackgroundColor;
3257 if (htmlElement && htmlElement->renderer())
3258 htmlBackgroundColor = htmlElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
3259 if (bodyElement && bodyElement->renderer())
3260 bodyBackgroundColor = bodyElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
3262 if (!bodyBackgroundColor.isValid()) {
3263 if (!htmlBackgroundColor.isValid())
3265 return baseBackgroundColor().blend(htmlBackgroundColor);
3268 if (!htmlBackgroundColor.isValid())
3269 return baseBackgroundColor().blend(bodyBackgroundColor);
3271 // We take the aggregate of the base background color
3272 // the <html> background color, and the <body>
3273 // background color to find the document color. The
3274 // addition of the base background color is not
3275 // technically part of the document background, but it
3276 // otherwise poses problems when the aggregate is not
3278 return baseBackgroundColor().blend(htmlBackgroundColor).blend(bodyBackgroundColor);
3281 bool FrameView::hasCustomScrollbars() const
3283 const HashSet<RefPtr<Widget> >* viewChildren = children();
3284 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
3285 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
3286 Widget* widget = current->get();
3287 if (widget->isFrameView()) {
3288 if (toFrameView(widget)->hasCustomScrollbars())
3290 } else if (widget->isScrollbar()) {
3291 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
3292 if (scrollbar->isCustomScrollbar())
3300 FrameView* FrameView::parentFrameView() const
3305 if (Frame* parentFrame = m_frame->tree()->parent())
3306 return parentFrame->view();
3311 bool FrameView::isInChildFrameWithFrameFlattening() const
3313 if (!parent() || !m_frame->ownerElement())
3316 // Frame flattening applies when the owner element is either in a frameset or
3317 // an iframe with flattening parameters.
3318 if (m_frame->ownerElement()->hasTagName(iframeTag)) {
3319 RenderIFrame* iframeRenderer = toRenderIFrame(m_frame->ownerElement()->renderPart());
3320 if (iframeRenderer->flattenFrame() || iframeRenderer->isSeamless())
3324 if (!m_frame->settings() || !m_frame->settings()->frameFlatteningEnabled())
3327 if (m_frame->ownerElement()->hasTagName(frameTag))
3333 bool FrameView::doLayoutWithFrameFlattening(bool allowSubtree)
3335 // Try initiating layout from the topmost parent.
3336 FrameView* parentView = parentFrameView();
3341 // In the middle of parent layout, no need to restart from topmost.
3342 if (parentView->m_nestedLayoutCount)
3345 // Parent tree is clean. Starting layout from it would have no effect.
3346 if (!parentView->needsLayout())
3349 while (parentView->parentFrameView())
3350 parentView = parentView->parentFrameView();
3352 parentView->layout(allowSubtree);
3354 RenderObject* root = m_layoutRoot ? m_layoutRoot : m_frame->document()->renderer();
3355 ASSERT_UNUSED(root, !root->needsLayout());
3360 void FrameView::updateControlTints()
3362 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
3363 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
3364 // This is only done if the theme supports control tinting. It's up to the theme and platform
3365 // to define when controls get the tint and to call this function when that changes.
3367 // Optimize the common case where we bring a window to the front while it's still empty.
3368 if (!m_frame || m_frame->document()->url().isEmpty())
3371 RenderView* renderView = this->renderView();
3372 if ((renderView && renderView->theme()->supportsControlTints()) || hasCustomScrollbars())
3373 paintControlTints();
3376 void FrameView::paintControlTints()
3380 PlatformGraphicsContext* const noContext = 0;
3381 GraphicsContext context(noContext);
3382 context.setUpdatingControlTints(true);
3383 if (platformWidget())
3384 paintContents(&context, visibleContentRect());
3386 paint(&context, frameRect());
3389 bool FrameView::wasScrolledByUser() const
3391 return m_wasScrolledByUser;
3394 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
3396 if (m_inProgrammaticScroll)
3398 m_maintainScrollPositionAnchor = 0;
3399 m_wasScrolledByUser = wasScrolledByUser;
3402 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
3407 Document* document = m_frame->document();
3411 if (document->printing())
3412 fillWithRed = false; // Printing, don't fill with red (can't remember why).
3413 else if (m_frame->ownerElement())
3414 fillWithRed = false; // Subframe, don't fill with red.
3415 else if (isTransparent())
3416 fillWithRed = false; // Transparent, don't fill with red.
3417 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
3418 fillWithRed = false; // Selections are transparent, don't fill with red.
3419 else if (m_nodeToDraw)
3420 fillWithRed = false; // Element images are transparent, don't fill with red.
3425 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
3428 RenderView* renderView = this->renderView();
3430 LOG_ERROR("called FrameView::paint with nil renderer");
3434 ASSERT(!needsLayout());
3438 InspectorInstrumentation::willPaint(renderView);
3440 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
3441 if (isTopLevelPainter)
3442 sCurrentPaintTimeStamp = currentTime();
3444 FontCachePurgePreventer fontCachePurgePreventer;
3446 #if USE(ACCELERATED_COMPOSITING)
3447 if (!p->paintingDisabled() && !document->printing())
3448 flushCompositingStateForThisFrame(m_frame.get());
3451 PaintBehavior oldPaintBehavior = m_paintBehavior;
3453 if (FrameView* parentView = parentFrameView()) {
3454 if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
3455 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
3458 if (m_paintBehavior == PaintBehaviorNormal)
3459 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
3461 if (document->printing())
3462 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
3464 bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers;
3465 bool isRootFrame = !m_frame->ownerElement();
3466 if (flatteningPaint && isRootFrame)
3467 notifyWidgetsInAllFrames(WillPaintFlattened);
3469 ASSERT(!m_isPainting);
3470 m_isPainting = true;
3472 // m_nodeToDraw is used to draw only one element (and its descendants)
3473 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
3474 RenderLayer* rootLayer = renderView->layer();
3477 RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(rootLayer->renderer());
3480 rootLayer->paint(p, rect, m_paintBehavior, eltRenderer);
3482 if (rootLayer->containsDirtyOverlayScrollbars())
3483 rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer);
3485 m_isPainting = false;
3487 if (flatteningPaint && isRootFrame)
3488 notifyWidgetsInAllFrames(DidPaintFlattened);
3490 m_paintBehavior = oldPaintBehavior;
3491 m_lastPaintTime = currentTime();
3493 // Regions may have changed as a result of the visibility/z-index of element changing.
3494 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
3495 if (document->annotatedRegionsDirty())
3496 updateAnnotatedRegions();
3499 if (isTopLevelPainter)
3500 sCurrentPaintTimeStamp = 0;
3502 InspectorInstrumentation::didPaint(renderView, p, rect);
3505 void FrameView::setPaintBehavior(PaintBehavior behavior)
3507 m_paintBehavior = behavior;
3510 PaintBehavior FrameView::paintBehavior() const
3512 return m_paintBehavior;
3515 bool FrameView::isPainting() const
3517 return m_isPainting;
3520 void FrameView::setNodeToDraw(Node* node)
3522 m_nodeToDraw = node;
3525 void FrameView::paintContentsForSnapshot(GraphicsContext* context, const IntRect& imageRect, SelectionInSnaphot shouldPaintSelection, CoordinateSpaceForSnapshot coordinateSpace)
3527 updateLayoutAndStyleIfNeededRecursive();
3529 // Cache paint behavior and set a new behavior appropriate for snapshots.
3530 PaintBehavior oldBehavior = paintBehavior();
3531 setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
3533 // If the snapshot should exclude selection, then we'll clear the current selection
3534 // in the render tree only. This will allow us to restore the selection from the DOM
3535 // after we paint the snapshot.
3536 if (shouldPaintSelection == ExcludeSelection) {
3537 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
3538 if (RenderView* root = frame->contentRenderer())
3539 root->clearSelection();
3543 if (coordinateSpace == DocumentCoordinates)
3544 paintContents(context, imageRect);
3546 // A snapshot in ViewCoordinates will include a scrollbar, and the snapshot will contain
3547 // whatever content the document is currently scrolled to.
3548 paint(context, imageRect);
3551 // Restore selection.
3552 if (shouldPaintSelection == ExcludeSelection) {
3553 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get()))
3554 frame->selection()->updateAppearance();
3557 // Restore cached paint behavior.
3558 setPaintBehavior(oldBehavior);
3561 void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
3563 if (context->paintingDisabled())
3566 if (m_frame->document()->printing())
3569 Page* page = m_frame->page();
3570 if (page->mainFrame() == m_frame) {
3571 if (page->chrome()->client()->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
3575 ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
3578 void FrameView::updateLayoutAndStyleIfNeededRecursive()
3580 // We have to crawl our entire tree looking for any FrameViews that need
3581 // layout and make sure they are up to date.
3582 // Mac actually tests for intersection with the dirty region and tries not to
3583 // update layout for frames that are outside the dirty region. Not only does this seem
3584 // pointless (since those frames will have set a zero timer to layout anyway), but
3585 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
3586 // region but then become included later by the second frame adding rects to the dirty region
3587 // when it lays out.
3589 m_frame->document()->updateStyleIfNeeded();
3594 // Grab a copy of the children() set, as it may be mutated by the following updateLayoutAndStyleIfNeededRecursive
3595 // calls, as they can potentially re-enter a layout of the parent frame view, which may add/remove scrollbars
3596 // and thus mutates the children() set.
3597 Vector<RefPtr<FrameView> > frameViews;
3598 collectFrameViewChildren(this, frameViews);
3600 const Vector<RefPtr<FrameView> >::iterator end = frameViews.end();
3601 for (Vector<RefPtr<FrameView> >::iterator it = frameViews.begin(); it != end; ++it)
3602 (*it)->updateLayoutAndStyleIfNeededRecursive();
3604 // updateLayoutAndStyleIfNeededRecursive is called when we need to&nbs