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"
41 #include "FrameActionScheduler.h"
42 #include "FrameLoader.h"
43 #include "FrameLoaderClient.h"
44 #include "FrameTree.h"
45 #include "GraphicsContext.h"
46 #include "HTMLDocument.h"
47 #include "HTMLFrameElement.h"
48 #include "HTMLFrameSetElement.h"
49 #include "HTMLNames.h"
50 #include "HTMLPlugInImageElement.h"
51 #include "InspectorClient.h"
52 #include "InspectorController.h"
53 #include "InspectorInstrumentation.h"
54 #include "OverflowEvent.h"
55 #include "RenderArena.h"
56 #include "RenderEmbeddedObject.h"
57 #include "RenderFullScreen.h"
58 #include "RenderIFrame.h"
59 #include "RenderLayer.h"
60 #include "RenderLayerBacking.h"
61 #include "RenderPart.h"
62 #include "RenderScrollbar.h"
63 #include "RenderScrollbarPart.h"
64 #include "RenderTheme.h"
65 #include "RenderView.h"
66 #include "ScrollAnimator.h"
67 #include "ScrollingCoordinator.h"
69 #include "StyleResolver.h"
70 #include "TextResourceDecoder.h"
71 #include "TextStream.h"
73 #include <wtf/CurrentTime.h>
74 #include <wtf/TemporaryChange.h>
75 #include <wtf/UnusedParam.h>
77 #if USE(ACCELERATED_COMPOSITING)
78 #include "RenderLayerCompositor.h"
79 #include "TiledBacking.h"
83 #include "RenderSVGRoot.h"
84 #include "SVGDocument.h"
85 #include "SVGSVGElement.h"
88 #if USE(TILED_BACKING_STORE)
89 #include "TiledBackingStore.h"
92 #if ENABLE(TEXT_AUTOSIZING)
93 #include "TextAutosizer.h"
98 using namespace HTMLNames;
100 double FrameView::sCurrentPaintTimeStamp = 0.0;
103 // REPAINT_THROTTLING now chooses default values for throttling parameters.
104 // Should be removed when applications start using runtime configuration.
105 #if ENABLE(REPAINT_THROTTLING)
107 double FrameView::s_normalDeferredRepaintDelay = 0.016;
108 // Negative value would mean that first few repaints happen without a delay
109 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
110 // The delay grows on each repaint to this maximum value
111 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
112 // On each repaint the delay increses by this amount
113 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
115 // FIXME: Repaint throttling could be good to have on all platform.
116 // The balance between CPU use and repaint frequency will need some tuning for desktop.
117 // More hooks may be needed to reset the delay on things like GIF and CSS animations.
118 double FrameView::s_normalDeferredRepaintDelay = 0;
119 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
120 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
121 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
124 // The maximum number of updateWidgets iterations that should be done before returning.
125 static const unsigned maxUpdateWidgetsIterations = 2;
127 static RenderLayer::UpdateLayerPositionsFlags updateLayerPositionFlags(RenderLayer* layer, bool isRelayoutingSubtree, bool didFullRepaint)
129 RenderLayer::UpdateLayerPositionsFlags flags = RenderLayer::defaultFlags;
130 if (didFullRepaint) {
131 flags &= ~RenderLayer::CheckForRepaint;
132 flags |= RenderLayer::NeedsFullRepaintInBacking;
134 if (isRelayoutingSubtree && layer->isPaginated())
135 flags |= RenderLayer::UpdatePagination;
139 Pagination::Mode paginationModeForRenderStyle(RenderStyle* style)
141 EOverflow overflow = style->overflowY();
142 if (overflow != OPAGEDX && overflow != OPAGEDY)
143 return Pagination::Unpaginated;
145 bool isHorizontalWritingMode = style->isHorizontalWritingMode();
146 TextDirection textDirection = style->direction();
147 WritingMode writingMode = style->writingMode();
149 // paged-x always corresponds to LeftToRightPaginated or RightToLeftPaginated. If the WritingMode
150 // is horizontal, then we use TextDirection to choose between those options. If the WritingMode
151 // is vertical, then the direction of the verticality dictates the choice.
152 if (overflow == OPAGEDX) {
153 if ((isHorizontalWritingMode && textDirection == LTR) || writingMode == LeftToRightWritingMode)
154 return Pagination::LeftToRightPaginated;
155 return Pagination::RightToLeftPaginated;
158 // paged-y always corresponds to TopToBottomPaginated or BottomToTopPaginated. If the WritingMode
159 // is horizontal, then the direction of the horizontality dictates the choice. If the WritingMode
160 // is vertical, then we use TextDirection to choose between those options.
161 if (writingMode == TopToBottomWritingMode || (!isHorizontalWritingMode && textDirection == RTL))
162 return Pagination::TopToBottomPaginated;
163 return Pagination::BottomToTopPaginated;
166 FrameView::FrameView(Frame* frame)
168 , m_canHaveScrollbars(true)
169 , m_slowRepaintObjectCount(0)
170 , m_layoutTimer(this, &FrameView::layoutTimerFired)
172 , m_inSynchronousPostLayout(false)
173 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
174 , m_isTransparent(false)
175 , m_baseBackgroundColor(Color::white)
176 , m_mediaType("screen")
177 , m_actionScheduler(adoptPtr(new FrameActionScheduler))
178 , m_overflowStatusDirty(true)
179 , m_viewportRenderer(0)
180 , m_wasScrolledByUser(false)
181 , m_inProgrammaticScroll(false)
182 , m_safeToPropagateScrollToParent(true)
183 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
184 , m_disableRepaints(0)
185 , m_isTrackingRepaints(false)
186 , m_shouldUpdateWhileOffscreen(true)
187 , m_deferSetNeedsLayouts(0)
188 , m_setNeedsLayoutWasDeferred(false)
190 , m_shouldAutoSize(false)
191 , m_inAutoSize(false)
192 , m_didRunAutosize(false)
193 #if ENABLE(CSS_FILTERS)
194 , m_hasSoftwareFilters(false)
199 // FIXME: Can m_frame ever be null here?
203 Page* page = m_frame->page();
207 if (m_frame == page->mainFrame()) {
208 ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed);
209 ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed);
213 PassRefPtr<FrameView> FrameView::create(Frame* frame)
215 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
217 return view.release();
220 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize)
222 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
223 view->Widget::setFrameRect(IntRect(view->location(), initialSize));
225 return view.release();
228 FrameView::~FrameView()
230 if (m_postLayoutTasksTimer.isActive()) {
231 m_postLayoutTasksTimer.stop();
232 m_actionScheduler->clear();
235 removeFromAXObjectCache();
238 // Custom scrollbars should already be destroyed at this point
239 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
240 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
242 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
243 setHasVerticalScrollbar(false);
245 ASSERT(!m_scrollCorner);
246 ASSERT(m_actionScheduler->isEmpty());
249 ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
250 RenderPart* renderer = m_frame->ownerRenderer();
251 if (renderer && renderer->widget() == this)
252 renderer->setWidget(0);
256 void FrameView::reset()
258 m_cannotBlitToWindow = false;
259 m_isOverlapped = false;
260 m_contentIsOpaque = false;
263 m_layoutTimer.stop();
265 m_delayedLayout = false;
266 m_doFullRepaint = true;
267 m_layoutSchedulingEnabled = true;
269 m_doingPreLayoutStyleUpdate = false;
270 m_inSynchronousPostLayout = false;
272 m_nestedLayoutCount = 0;
273 m_postLayoutTasksTimer.stop();
274 m_firstLayout = true;
275 m_firstLayoutCallbackPending = false;
276 m_wasScrolledByUser = false;
277 m_safeToPropagateScrollToParent = true;
278 m_lastViewportSize = IntSize();
279 m_lastZoomFactor = 1.0f;
280 m_deferringRepaints = 0;
282 m_repaintRects.clear();
283 m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading;
284 m_deferredRepaintTimer.stop();
285 m_isTrackingRepaints = false;
286 m_trackedRepaintRects.clear();
288 m_paintBehavior = PaintBehaviorNormal;
289 m_isPainting = false;
290 m_visuallyNonEmptyCharacterCount = 0;
291 m_visuallyNonEmptyPixelCount = 0;
292 m_isVisuallyNonEmpty = false;
293 m_firstVisuallyNonEmptyLayoutCallbackPending = true;
294 m_maintainScrollPositionAnchor = 0;
295 m_disableRepaints = 0;
298 void FrameView::removeFromAXObjectCache()
300 if (AXObjectCache::accessibilityEnabled() && axObjectCache())
301 axObjectCache()->remove(this);
304 bool FrameView::isFrameView() const
309 void FrameView::clearFrame()
314 void FrameView::resetScrollbars()
316 // Reset the document's scrollbars back to our defaults before we yield the floor.
317 m_firstLayout = true;
318 setScrollbarsSuppressed(true);
319 if (m_canHaveScrollbars)
320 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
322 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
323 setScrollbarsSuppressed(false);
326 void FrameView::resetScrollbarsAndClearContentsSize()
330 setScrollbarsSuppressed(true);
331 setContentsSize(IntSize());
332 setScrollbarsSuppressed(false);
335 void FrameView::init()
339 m_margins = LayoutSize(-1, -1); // undefined
340 m_size = LayoutSize();
342 // Propagate the marginwidth/height and scrolling modes to the view.
343 Element* ownerElement = m_frame ? m_frame->ownerElement() : 0;
344 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
345 HTMLFrameElementBase* frameElt = static_cast<HTMLFrameElementBase*>(ownerElement);
346 if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
347 setCanHaveScrollbars(false);
348 LayoutUnit marginWidth = frameElt->marginWidth();
349 LayoutUnit marginHeight = frameElt->marginHeight();
350 if (marginWidth != -1)
351 setMarginWidth(marginWidth);
352 if (marginHeight != -1)
353 setMarginHeight(marginHeight);
357 void FrameView::prepareForDetach()
359 detachCustomScrollbars();
360 // When the view is no longer associated with a frame, it needs to be removed from the ax object cache
361 // right now, otherwise it won't be able to reach the topDocument()'s axObject cache later.
362 removeFromAXObjectCache();
365 void FrameView::detachCustomScrollbars()
367 Scrollbar* horizontalBar = horizontalScrollbar();
368 if (horizontalBar && horizontalBar->isCustomScrollbar())
369 setHasHorizontalScrollbar(false);
371 Scrollbar* verticalBar = verticalScrollbar();
372 if (verticalBar && verticalBar->isCustomScrollbar())
373 setHasVerticalScrollbar(false);
375 if (m_scrollCorner) {
376 m_scrollCorner->destroy();
381 void FrameView::recalculateScrollbarOverlayStyle()
383 ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle();
384 ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault;
386 Color backgroundColor = documentBackgroundColor();
387 if (backgroundColor.isValid()) {
388 // Reduce the background color from RGB to a lightness value
389 // and determine which scrollbar style to use based on a lightness
391 double hue, saturation, lightness;
392 backgroundColor.getHSL(hue, saturation, lightness);
394 overlayStyle = ScrollbarOverlayStyleLight;
397 if (oldOverlayStyle != overlayStyle)
398 setScrollbarOverlayStyle(overlayStyle);
401 void FrameView::clear()
403 setCanBlitOnScroll(true);
408 if (RenderPart* renderer = m_frame->ownerRenderer())
409 renderer->viewCleared();
412 setScrollbarsSuppressed(true);
415 bool FrameView::didFirstLayout() const
417 return !m_firstLayout;
420 void FrameView::invalidateRect(const IntRect& rect)
424 hostWindow()->invalidateContentsAndRootView(rect, false /*immediate*/);
431 RenderPart* renderer = m_frame->ownerRenderer();
435 IntRect repaintRect = rect;
436 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
437 renderer->borderTop() + renderer->paddingTop());
438 renderer->repaintRectangle(repaintRect);
441 void FrameView::setFrameRect(const IntRect& newRect)
443 IntRect oldRect = frameRect();
444 if (newRect == oldRect)
447 #if ENABLE(TEXT_AUTOSIZING)
448 // Autosized font sizes depend on the width of the viewing area.
449 if (newRect.width() != oldRect.width()) {
450 Page* page = m_frame ? m_frame->page() : 0;
451 if (page && page->mainFrame() == m_frame && page->settings()->textAutosizingEnabled()) {
452 for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())
453 m_frame->document()->textAutosizer()->recalculateMultipliers();
458 ScrollView::setFrameRect(newRect);
460 updateScrollableAreaSet();
462 #if USE(ACCELERATED_COMPOSITING)
463 if (RenderView* renderView = this->renderView()) {
464 if (renderView->usesCompositing())
465 renderView->compositor()->frameViewDidChangeSize();
470 #if ENABLE(REQUEST_ANIMATION_FRAME)
471 bool FrameView::scheduleAnimation()
474 hostWindow()->scheduleAnimation();
481 void FrameView::setMarginWidth(LayoutUnit w)
483 // make it update the rendering area when set
484 m_margins.setWidth(w);
487 void FrameView::setMarginHeight(LayoutUnit h)
489 // make it update the rendering area when set
490 m_margins.setHeight(h);
493 bool FrameView::avoidScrollbarCreation() const
497 // with frame flattening no subframe can have scrollbars
498 // but we also cannot turn scrollbars off as we determine
499 // our flattening policy using that.
501 if (!m_frame->ownerElement())
504 if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
510 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
512 m_canHaveScrollbars = canHaveScrollbars;
513 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
516 void FrameView::updateCanHaveScrollbars()
520 scrollbarModes(hMode, vMode);
521 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
522 setCanHaveScrollbars(false);
524 setCanHaveScrollbars(true);
527 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
529 if (Settings* settings = m_frame->settings()) {
530 if (!settings->allowCustomScrollbarInMainFrame() && m_frame->page() && m_frame->page()->mainFrame() == m_frame)
531 return ScrollView::createScrollbar(orientation);
534 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
535 Document* doc = m_frame->document();
537 // Try the <body> element first as a scrollbar source.
538 Element* body = doc ? doc->body() : 0;
539 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
540 return RenderScrollbar::createCustomScrollbar(this, orientation, body);
542 // If the <body> didn't have a custom style, then the root element might.
543 Element* docElement = doc ? doc->documentElement() : 0;
544 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
545 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement);
547 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
548 RenderPart* frameRenderer = m_frame->ownerRenderer();
549 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
550 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
552 // Nobody set a custom style, so we just use a native scrollbar.
553 return ScrollView::createScrollbar(orientation);
556 void FrameView::setContentsSize(const IntSize& size)
558 if (size == contentsSize())
561 m_deferSetNeedsLayouts++;
563 ScrollView::setContentsSize(size);
564 ScrollView::contentsResized();
566 Page* page = frame() ? frame()->page() : 0;
570 updateScrollableAreaSet();
572 page->chrome()->contentsSizeChanged(frame(), size); //notify only
574 m_deferSetNeedsLayouts--;
576 if (!m_deferSetNeedsLayouts)
577 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
580 void FrameView::adjustViewSize()
582 RenderView* renderView = this->renderView();
586 ASSERT(m_frame->view() == this);
588 const IntRect rect = renderView->documentRect();
589 const IntSize& size = rect.size();
590 ScrollView::setScrollOrigin(IntPoint(-rect.x(), -rect.y()), !m_frame->document()->printing(), size == contentsSize());
592 setContentsSize(size);
595 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
597 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
598 // overflow:hidden and overflow:scroll on <body> as applying to the document's
599 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
600 // use the root element.
602 // To combat the inability to scroll on a page with overflow:hidden on the root when scaled, disregard hidden when
603 // there is a frameScaleFactor that is greater than one on the main frame.
605 bool overrideHidden = m_frame->page() && m_frame->page()->mainFrame() == m_frame && m_frame->frameScaleFactor() > 1;
607 EOverflow overflowX = o->style()->overflowX();
608 EOverflow overflowY = o->style()->overflowY();
611 if (o->isSVGRoot()) {
612 // overflow is ignored in stand-alone SVG documents.
613 if (!toRenderSVGRoot(o)->isEmbeddedThroughFrameContainingSVGDocument())
623 hMode = ScrollbarAuto;
625 hMode = ScrollbarAlwaysOff;
628 hMode = ScrollbarAlwaysOn;
631 hMode = ScrollbarAuto;
634 // Don't set it at all.
641 vMode = ScrollbarAuto;
643 vMode = ScrollbarAlwaysOff;
646 vMode = ScrollbarAlwaysOn;
649 vMode = ScrollbarAuto;
652 // Don't set it at all. Values of OPAGEDX and OPAGEDY are handled by applyPaginationToViewPort().
656 m_viewportRenderer = o;
659 void FrameView::applyPaginationToViewport()
661 Document* document = m_frame->document();
662 Node* documentElement = document->documentElement();
663 RenderObject* documentRenderer = documentElement ? documentElement->renderer() : 0;
664 RenderObject* documentOrBodyRenderer = documentRenderer;
665 Node* body = document->body();
666 if (body && body->renderer()) {
667 if (body->hasTagName(bodyTag))
668 documentOrBodyRenderer = documentRenderer->style()->overflowX() == OVISIBLE && documentElement->hasTagName(htmlTag) ? body->renderer() : documentRenderer;
671 Pagination pagination;
673 if (!documentOrBodyRenderer) {
674 setPagination(pagination);
678 EOverflow overflowY = documentOrBodyRenderer->style()->overflowY();
679 if (overflowY == OPAGEDX || overflowY == OPAGEDY) {
680 pagination.mode = WebCore::paginationModeForRenderStyle(documentOrBodyRenderer->style());
681 pagination.gap = static_cast<unsigned>(documentOrBodyRenderer->style()->columnGap());
684 setPagination(pagination);
687 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy)
689 m_viewportRenderer = 0;
691 const HTMLFrameOwnerElement* owner = m_frame->ownerElement();
692 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
693 hMode = ScrollbarAlwaysOff;
694 vMode = ScrollbarAlwaysOff;
698 if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) {
699 hMode = ScrollbarAuto;
700 // Seamless documents begin with heights of 0; we special case that here
701 // to correctly render documents that don't need scrollbars.
702 IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size();
703 bool isSeamlessDocument = frame() && frame()->document() && frame()->document()->shouldDisplaySeamlesslyWithParent();
704 vMode = (isSeamlessDocument && !fullVisibleSize.height()) ? ScrollbarAlwaysOff : ScrollbarAuto;
706 hMode = ScrollbarAlwaysOff;
707 vMode = ScrollbarAlwaysOff;
711 Document* document = m_frame->document();
712 Node* documentElement = document->documentElement();
713 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
714 Node* body = document->body();
715 if (body && body->renderer()) {
716 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
717 vMode = ScrollbarAlwaysOff;
718 hMode = ScrollbarAlwaysOff;
719 } else if (body->hasTagName(bodyTag)) {
720 // It's sufficient to just check the X overflow,
721 // since it's illegal to have visible in only one direction.
722 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
723 applyOverflowToViewport(o, hMode, vMode);
725 } else if (rootRenderer)
726 applyOverflowToViewport(rootRenderer, hMode, vMode);
730 #if USE(ACCELERATED_COMPOSITING)
731 void FrameView::updateCompositingLayersAfterStyleChange()
733 RenderView* renderView = this->renderView();
737 // If we expect to update compositing after an incipient layout, don't do so here.
738 if (m_doingPreLayoutStyleUpdate || layoutPending() || renderView->needsLayout())
741 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
742 renderView->compositor()->cacheAcceleratedCompositingFlags();
743 renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterStyleChange);
746 void FrameView::updateCompositingLayersAfterLayout()
748 RenderView* renderView = this->renderView();
752 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
753 renderView->compositor()->cacheAcceleratedCompositingFlags();
754 renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterLayout);
757 void FrameView::clearBackingStores()
759 RenderView* renderView = this->renderView();
763 RenderLayerCompositor* compositor = renderView->compositor();
764 ASSERT(compositor->inCompositingMode());
765 compositor->enableCompositingMode(false);
766 compositor->clearBackingForAllLayers();
769 void FrameView::restoreBackingStores()
771 RenderView* renderView = this->renderView();
775 RenderLayerCompositor* compositor = renderView->compositor();
776 compositor->enableCompositingMode(true);
777 compositor->updateCompositingLayers(CompositingUpdateAfterLayout);
780 bool FrameView::usesCompositedScrolling() const
782 RenderView* renderView = this->renderView();
785 if (m_frame->settings() && m_frame->settings()->compositedScrollingForFramesEnabled())
786 return renderView->compositor()->inForcedCompositingMode();
790 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
792 RenderView* renderView = this->renderView();
795 return renderView->compositor()->layerForHorizontalScrollbar();
798 GraphicsLayer* FrameView::layerForVerticalScrollbar() const
800 RenderView* renderView = this->renderView();
803 return renderView->compositor()->layerForVerticalScrollbar();
806 GraphicsLayer* FrameView::layerForScrollCorner() const
808 RenderView* renderView = this->renderView();
811 return renderView->compositor()->layerForScrollCorner();
814 TiledBacking* FrameView::tiledBacking()
816 RenderView* renderView = this->renderView();
820 RenderLayerBacking* backing = renderView->layer()->backing();
824 return backing->graphicsLayer()->tiledBacking();
827 uint64_t FrameView::scrollLayerID() const
829 RenderView* renderView = this->renderView();
833 RenderLayerBacking* backing = renderView->layer()->backing();
837 return backing->scrollLayerID();
840 #if ENABLE(RUBBER_BANDING)
841 GraphicsLayer* FrameView::layerForOverhangAreas() const
843 RenderView* renderView = this->renderView();
846 return renderView->compositor()->layerForOverhangAreas();
850 bool FrameView::flushCompositingStateForThisFrame(Frame* rootFrameForFlush)
852 RenderView* renderView = this->renderView();
854 return true; // We don't want to keep trying to update layers if we have no renderer.
856 ASSERT(m_frame->view() == this);
858 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
859 // layer content to occur before layout has happened, which will cause paintContents() to bail.
863 // If we sync compositing layers and allow the repaint to be deferred, there is time for a
864 // visible flash to occur. Instead, stop the deferred repaint timer and repaint immediately.
865 flushDeferredRepaints();
867 renderView->compositor()->flushPendingLayerChanges(rootFrameForFlush == m_frame);
872 void FrameView::setNeedsOneShotDrawingSynchronization()
874 Page* page = frame() ? frame()->page() : 0;
876 page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
879 #endif // USE(ACCELERATED_COMPOSITING)
881 bool FrameView::hasCompositedContent() const
883 #if USE(ACCELERATED_COMPOSITING)
884 if (RenderView* renderView = this->renderView())
885 return renderView->compositor()->inCompositingMode();
890 bool FrameView::hasCompositedContentIncludingDescendants() const
892 #if USE(ACCELERATED_COMPOSITING)
893 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
894 RenderView* renderView = frame->contentRenderer();
895 RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0;
897 if (compositor->inCompositingMode())
900 if (!RenderLayerCompositor::allowsIndependentlyCompositedFrames(this))
908 bool FrameView::hasCompositingAncestor() const
910 #if USE(ACCELERATED_COMPOSITING)
911 for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) {
912 if (FrameView* view = frame->view()) {
913 if (view->hasCompositedContent())
921 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
922 void FrameView::enterCompositingMode()
924 #if USE(ACCELERATED_COMPOSITING)
925 if (RenderView* renderView = this->renderView()) {
926 renderView->compositor()->enableCompositingMode();
928 renderView->compositor()->scheduleCompositingLayerUpdate();
933 bool FrameView::isEnclosedInCompositingLayer() const
935 #if USE(ACCELERATED_COMPOSITING)
936 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
937 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
940 if (FrameView* parentView = parentFrameView())
941 return parentView->isEnclosedInCompositingLayer();
946 bool FrameView::flushCompositingStateIncludingSubframes()
948 #if USE(ACCELERATED_COMPOSITING)
949 bool allFramesFlushed = flushCompositingStateForThisFrame(m_frame.get());
951 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame.get())) {
952 bool flushed = child->view()->flushCompositingStateForThisFrame(m_frame.get());
953 allFramesFlushed &= flushed;
955 return allFramesFlushed;
956 #else // USE(ACCELERATED_COMPOSITING)
961 bool FrameView::isSoftwareRenderable() const
963 #if USE(ACCELERATED_COMPOSITING)
964 RenderView* renderView = this->renderView();
965 return !renderView || !renderView->compositor()->has3DContent();
971 void FrameView::didMoveOnscreen()
973 if (RenderView* renderView = this->renderView())
974 renderView->didMoveOnscreen();
975 contentAreaDidShow();
978 void FrameView::willMoveOffscreen()
980 if (RenderView* renderView = this->renderView())
981 renderView->willMoveOffscreen();
982 contentAreaDidHide();
985 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
987 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
990 static inline void collectFrameViewChildren(FrameView* frameView, Vector<RefPtr<FrameView> >& frameViews)
992 const HashSet<RefPtr<Widget> >* viewChildren = frameView->children();
993 ASSERT(viewChildren);
995 const HashSet<RefPtr<Widget> >::iterator end = viewChildren->end();
996 for (HashSet<RefPtr<Widget> >::iterator current = viewChildren->begin(); current != end; ++current) {
997 Widget* widget = (*current).get();
998 if (widget->isFrameView())
999 frameViews.append(static_cast<FrameView*>(widget));
1003 inline void FrameView::forceLayoutParentViewIfNeeded()
1006 RenderPart* ownerRenderer = m_frame->ownerRenderer();
1007 if (!ownerRenderer || !ownerRenderer->frame())
1010 RenderBox* contentBox = embeddedContentBox();
1014 RenderSVGRoot* svgRoot = toRenderSVGRoot(contentBox);
1015 if (svgRoot->everHadLayout() && !svgRoot->needsLayout())
1018 // If the embedded SVG document appears the first time, the ownerRenderer has already finished
1019 // layout without knowing about the existence of the embedded SVG document, because RenderReplaced
1020 // embeddedContentBox() returns 0, as long as the embedded document isn't loaded yet. Before
1021 // bothering to lay out the SVG document, mark the ownerRenderer needing layout and ask its
1022 // FrameView for a layout. After that the RenderEmbeddedObject (ownerRenderer) carries the
1023 // correct size, which RenderSVGRoot::computeReplacedLogicalWidth/Height rely on, when laying
1024 // out for the first time, or when the RenderSVGRoot size has changed dynamically (eg. via <script>).
1025 RefPtr<FrameView> frameView = ownerRenderer->frame()->view();
1027 // Mark the owner renderer as needing layout.
1028 ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc();
1030 // Synchronously enter layout, to layout the view containing the host object/embed/iframe.
1032 frameView->layout();
1036 void FrameView::layout(bool allowSubtree)
1041 // Protect the view from being deleted during layout (in recalcStyle)
1042 RefPtr<FrameView> protector(this);
1044 // Every scroll that happens during layout is programmatic.
1045 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1047 bool inChildFrameLayoutWithFrameFlattening = isInChildFrameWithFrameFlattening();
1049 if (inChildFrameLayoutWithFrameFlattening) {
1050 if (doLayoutWithFrameFlattening(allowSubtree))
1054 m_layoutTimer.stop();
1055 m_delayedLayout = false;
1056 m_setNeedsLayoutWasDeferred = false;
1059 // FIXME: Do we need to set m_size.width here?
1060 // FIXME: Should we set m_size.height here too?
1061 m_size.setWidth(layoutWidth());
1065 // we shouldn't enter layout() while painting
1066 ASSERT(!isPainting());
1070 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
1072 if (!allowSubtree && m_layoutRoot) {
1073 m_layoutRoot->markContainingBlocksForLayout(false);
1077 ASSERT(m_frame->view() == this);
1079 Document* document = m_frame->document();
1080 ASSERT(!document->inPageCache());
1085 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1087 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_postLayoutTasksTimer.isActive() && !inChildFrameLayoutWithFrameFlattening) {
1088 // This is a new top-level layout. If there are any remaining tasks from the previous
1089 // layout, finish them now.
1090 m_inSynchronousPostLayout = true;
1091 performPostLayoutTasks();
1092 m_inSynchronousPostLayout = false;
1095 // Viewport-dependent media queries may cause us to need completely different style information.
1097 if (document->styleResolver()->affectedByViewportChange()) {
1098 document->styleResolverChanged(RecalcStyleImmediately);
1099 InspectorInstrumentation::mediaQueryResultChanged(document);
1101 document->evaluateMediaQueryList();
1103 // If there is any pagination to apply, it will affect the RenderView's style, so we should
1104 // take care of that now.
1105 applyPaginationToViewport();
1107 // Always ensure our style info is up-to-date. This can happen in situations where
1108 // the layout beats any sort of style recalc update that needs to occur.
1109 TemporaryChange<bool> changeDoingPreLayoutStyleUpdate(m_doingPreLayoutStyleUpdate, true);
1110 document->updateStyleIfNeeded();
1112 subtree = m_layoutRoot;
1114 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
1115 // so there's no point to continuing to layout
1116 if (protector->hasOneRef())
1119 root = subtree ? m_layoutRoot : document->renderer();
1121 // FIXME: Do we need to set m_size here?
1124 } // Reset m_layoutSchedulingEnabled to its previous value.
1125 // The only reason the scoping was closed here is allow fontCachePurgePreventer
1126 // to outlive the change and reset of m_layoutSchedulingEnabled.
1128 FontCachePurgePreventer fontCachePurgePreventer;
1131 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1133 m_nestedLayoutCount++;
1135 if (!m_layoutRoot) {
1136 Document* document = m_frame->document();
1137 Node* body = document->body();
1138 if (body && body->renderer()) {
1139 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
1140 body->renderer()->setChildNeedsLayout(true);
1141 } else if (body->hasTagName(bodyTag)) {
1142 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
1143 body->renderer()->setChildNeedsLayout(true);
1147 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1148 if (m_firstLayout && !m_frame->ownerElement())
1149 printf("Elapsed time before first layout: %d\n", document->elapsedTime());
1153 autoSizeIfEnabled();
1155 ScrollbarMode hMode;
1156 ScrollbarMode vMode;
1157 calculateScrollbarModesForLayout(hMode, vMode);
1159 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
1162 // Now set our scrollbar state for the layout.
1163 ScrollbarMode currentHMode = horizontalScrollbarMode();
1164 ScrollbarMode currentVMode = verticalScrollbarMode();
1166 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
1167 if (m_firstLayout) {
1168 setScrollbarsSuppressed(true);
1170 m_firstLayout = false;
1171 m_firstLayoutCallbackPending = true;
1172 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
1173 m_lastViewportSize = fixedLayoutSize();
1175 m_lastViewportSize = visibleContentRect(IncludeScrollbars).size();
1176 m_lastZoomFactor = root->style()->zoom();
1178 // Set the initial vMode to AlwaysOn if we're auto.
1179 if (vMode == ScrollbarAuto)
1180 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
1181 // Set the initial hMode to AlwaysOff if we're auto.
1182 if (hMode == ScrollbarAuto)
1183 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
1185 setScrollbarModes(hMode, vMode);
1186 setScrollbarsSuppressed(false, true);
1188 setScrollbarModes(hMode, vMode);
1191 LayoutSize oldSize = m_size;
1193 m_size = LayoutSize(layoutWidth(), layoutHeight());
1195 if (oldSize != m_size) {
1196 m_doFullRepaint = true;
1197 if (!m_firstLayout) {
1198 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
1199 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
1200 if (bodyRenderer && bodyRenderer->stretchesToViewport())
1201 bodyRenderer->setChildNeedsLayout(true);
1202 else if (rootRenderer && rootRenderer->stretchesToViewport())
1203 rootRenderer->setChildNeedsLayout(true);
1208 layer = root->enclosingLayer();
1210 m_actionScheduler->pause();
1213 bool disableLayoutState = false;
1215 RenderView* view = root->view();
1216 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
1217 view->pushLayoutState(root);
1219 LayoutStateDisabler layoutStateDisabler(disableLayoutState ? root->view() : 0);
1222 beginDeferredRepaints();
1223 forceLayoutParentViewIfNeeded();
1225 #if ENABLE(TEXT_AUTOSIZING)
1226 bool autosized = document->textAutosizer()->processSubtree(root);
1227 if (autosized && root->needsLayout())
1230 endDeferredRepaints();
1234 root->view()->popLayoutState(root);
1237 } // Reset m_layoutSchedulingEnabled to its previous value.
1239 bool neededFullRepaint = m_doFullRepaint;
1241 if (!subtree && !toRenderView(root)->printing())
1244 m_doFullRepaint = neededFullRepaint;
1246 // Now update the positions of all layers.
1247 beginDeferredRepaints();
1248 if (m_doFullRepaint)
1249 root->view()->repaint(); // FIXME: This isn't really right, since the RenderView doesn't fully encompass the visibleContentRect(). It just happens
1250 // to work out most of the time, since first layouts and printing don't have you scrolled anywhere.
1252 layer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPositionFlags(layer, subtree, m_doFullRepaint));
1254 endDeferredRepaints();
1256 #if USE(ACCELERATED_COMPOSITING)
1257 updateCompositingLayersAfterLayout();
1262 #if PLATFORM(MAC) || PLATFORM(CHROMIUM)
1263 if (AXObjectCache::accessibilityEnabled())
1264 root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true);
1266 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
1267 updateAnnotatedRegions();
1270 ASSERT(!root->needsLayout());
1272 updateCanBlitOnScrollRecursively();
1274 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1275 updateOverflowStatus(layoutWidth() < contentsWidth(),
1276 layoutHeight() < contentsHeight());
1278 if (!m_postLayoutTasksTimer.isActive()) {
1279 if (!m_inSynchronousPostLayout) {
1280 if (inChildFrameLayoutWithFrameFlattening) {
1281 if (RenderView* renderView = this->renderView())
1282 renderView->updateWidgetPositions();
1284 m_inSynchronousPostLayout = true;
1285 // Calls resumeScheduledEvents()
1286 performPostLayoutTasks();
1287 m_inSynchronousPostLayout = false;
1291 if (!m_postLayoutTasksTimer.isActive() && (needsLayout() || m_inSynchronousPostLayout || inChildFrameLayoutWithFrameFlattening)) {
1292 // If we need layout or are already in a synchronous call to postLayoutTasks(),
1293 // defer widget updates and event dispatch until after we return. postLayoutTasks()
1294 // can make us need to update again, and we can get stuck in a nasty cycle unless
1295 // we call it through the timer here.
1296 m_postLayoutTasksTimer.startOneShot(0);
1297 if (needsLayout()) {
1298 m_actionScheduler->pause();
1303 m_actionScheduler->resume();
1306 InspectorInstrumentation::didLayout(cookie, root);
1308 m_nestedLayoutCount--;
1309 if (m_nestedLayoutCount)
1312 Page* page = frame() ? frame()->page() : 0;
1316 page->chrome()->client()->layoutUpdated(frame());
1319 RenderBox* FrameView::embeddedContentBox() const
1322 RenderView* renderView = this->renderView();
1326 RenderObject* firstChild = renderView->firstChild();
1327 if (!firstChild || !firstChild->isBox())
1330 // Curently only embedded SVG documents participate in the size-negotiation logic.
1331 if (firstChild->isSVGRoot())
1332 return toRenderBox(firstChild);
1338 void FrameView::addWidgetToUpdate(RenderObject* object)
1340 if (!m_widgetUpdateSet)
1341 m_widgetUpdateSet = adoptPtr(new RenderObjectSet);
1343 // Tell the DOM element that it needs a widget update.
1344 Node* node = object->node();
1345 if (node->hasTagName(objectTag) || node->hasTagName(embedTag)) {
1346 HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(node);
1347 pluginElement->setNeedsWidgetUpdate(true);
1350 m_widgetUpdateSet->add(object);
1353 void FrameView::removeWidgetToUpdate(RenderObject* object)
1355 if (!m_widgetUpdateSet)
1358 m_widgetUpdateSet->remove(object);
1361 void FrameView::setMediaType(const String& mediaType)
1363 m_mediaType = mediaType;
1366 String FrameView::mediaType() const
1368 // See if we have an override type.
1369 String overrideType = m_frame->loader()->client()->overrideMediaType();
1370 InspectorInstrumentation::applyEmulatedMedia(m_frame.get(), &overrideType);
1371 if (!overrideType.isNull())
1372 return overrideType;
1376 void FrameView::adjustMediaTypeForPrinting(bool printing)
1379 if (m_mediaTypeWhenNotPrinting.isNull())
1380 m_mediaTypeWhenNotPrinting = mediaType();
1381 setMediaType("print");
1383 if (!m_mediaTypeWhenNotPrinting.isNull())
1384 setMediaType(m_mediaTypeWhenNotPrinting);
1385 m_mediaTypeWhenNotPrinting = String();
1389 bool FrameView::useSlowRepaints(bool considerOverlap) const
1391 bool mustBeSlow = m_slowRepaintObjectCount > 0 || (platformWidget() && hasViewportConstrainedObjects());
1393 // FIXME: WidgetMac.mm makes the assumption that useSlowRepaints ==
1394 // m_contentIsOpaque, so don't take the fast path for composited layers
1395 // if they are a platform widget in order to get painting correctness
1396 // for transparent layers. See the comment in WidgetMac::paint.
1397 if (contentsInCompositedLayer() && !platformWidget())
1400 #if PLATFORM(CHROMIUM)
1401 // The chromium compositor does not support scrolling a non-composited frame within a composited page through
1402 // the fast scrolling path, so force slow scrolling in that case.
1403 if (m_frame->ownerElement() && !hasCompositedContent() && m_frame->page() && m_frame->page()->mainFrame()->view()->hasCompositedContent())
1407 bool isOverlapped = m_isOverlapped && considerOverlap;
1409 if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque)
1412 if (FrameView* parentView = parentFrameView())
1413 return parentView->useSlowRepaints(considerOverlap);
1418 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1420 return useSlowRepaints(false);
1423 void FrameView::updateCanBlitOnScrollRecursively()
1425 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1426 if (FrameView* view = frame->view())
1427 view->setCanBlitOnScroll(!view->useSlowRepaints());
1431 bool FrameView::contentsInCompositedLayer() const
1433 #if USE(ACCELERATED_COMPOSITING)
1434 RenderView* renderView = this->renderView();
1435 if (renderView && renderView->isComposited()) {
1436 GraphicsLayer* layer = renderView->layer()->backing()->graphicsLayer();
1437 if (layer && layer->drawsContent())
1444 void FrameView::setCannotBlitToWindow()
1446 m_cannotBlitToWindow = true;
1447 updateCanBlitOnScrollRecursively();
1450 void FrameView::addSlowRepaintObject()
1452 if (!m_slowRepaintObjectCount++) {
1453 updateCanBlitOnScrollRecursively();
1455 if (Page* page = m_frame->page()) {
1456 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1457 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1462 void FrameView::removeSlowRepaintObject()
1464 ASSERT(m_slowRepaintObjectCount > 0);
1465 m_slowRepaintObjectCount--;
1466 if (!m_slowRepaintObjectCount) {
1467 updateCanBlitOnScrollRecursively();
1469 if (Page* page = m_frame->page()) {
1470 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1471 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1476 void FrameView::addViewportConstrainedObject(RenderObject* object)
1478 if (!m_viewportConstrainedObjects)
1479 m_viewportConstrainedObjects = adoptPtr(new ViewportConstrainedObjectSet);
1481 if (!m_viewportConstrainedObjects->contains(object)) {
1482 m_viewportConstrainedObjects->add(object);
1483 if (platformWidget())
1484 updateCanBlitOnScrollRecursively();
1486 if (Page* page = m_frame->page()) {
1487 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1488 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1493 void FrameView::removeViewportConstrainedObject(RenderObject* object)
1495 if (m_viewportConstrainedObjects && m_viewportConstrainedObjects->contains(object)) {
1496 m_viewportConstrainedObjects->remove(object);
1497 if (Page* page = m_frame->page()) {
1498 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1499 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1502 // FIXME: In addFixedObject() we only call this if there's a platform widget,
1503 // why isn't the same check being made here?
1504 updateCanBlitOnScrollRecursively();
1508 LayoutRect FrameView::viewportConstrainedVisibleContentRect() const
1510 LayoutRect viewportRect = visibleContentRect();
1511 viewportRect.setLocation(toPoint(scrollOffsetForFixedPosition()));
1512 return viewportRect;
1515 IntSize FrameView::scrollOffsetForFixedPosition(const IntRect& visibleContentRect, const IntSize& contentsSize, const IntPoint& scrollPosition, const IntPoint& scrollOrigin, float frameScaleFactor, bool fixedElementsLayoutRelativeToFrame)
1517 IntPoint constrainedPosition = ScrollableArea::constrainScrollPositionForOverhang(visibleContentRect, contentsSize, scrollPosition, scrollOrigin);
1519 IntSize maxSize = contentsSize - visibleContentRect.size();
1521 float dragFactorX = (fixedElementsLayoutRelativeToFrame || !maxSize.width()) ? 1 : (contentsSize.width() - visibleContentRect.width() * frameScaleFactor) / maxSize.width();
1522 float dragFactorY = (fixedElementsLayoutRelativeToFrame || !maxSize.height()) ? 1 : (contentsSize.height() - visibleContentRect.height() * frameScaleFactor) / maxSize.height();
1524 return IntSize(constrainedPosition.x() * dragFactorX / frameScaleFactor, constrainedPosition.y() * dragFactorY / frameScaleFactor);
1527 IntSize FrameView::scrollOffsetForFixedPosition() const
1529 IntRect visibleContentRect = this->visibleContentRect();
1530 IntSize contentsSize = this->contentsSize();
1531 IntPoint scrollPosition = this->scrollPosition();
1532 IntPoint scrollOrigin = this->scrollOrigin();
1533 float frameScaleFactor = m_frame ? m_frame->frameScaleFactor() : 1;
1534 return scrollOffsetForFixedPosition(visibleContentRect, contentsSize, scrollPosition, scrollOrigin, frameScaleFactor, fixedElementsLayoutRelativeToFrame());
1537 bool FrameView::fixedElementsLayoutRelativeToFrame() const
1540 if (!m_frame->settings())
1543 return m_frame->settings()->fixedElementsLayoutRelativeToFrame();
1546 IntPoint FrameView::lastKnownMousePosition() const
1548 return m_frame ? m_frame->eventHandler()->lastKnownMousePosition() : IntPoint();
1551 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1553 if (!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty()) {
1554 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1558 const bool isCompositedContentLayer = contentsInCompositedLayer();
1560 // Get the rects of the fixed objects visible in the rectToScroll
1561 Region regionToUpdate;
1562 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end();
1563 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) {
1564 RenderObject* renderer = *it;
1565 if (!renderer->style()->hasViewportConstrainedPosition())
1567 #if USE(ACCELERATED_COMPOSITING)
1568 if (renderer->isComposited())
1572 // Fixed items should always have layers.
1573 ASSERT(renderer->hasLayer());
1574 RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
1576 #if ENABLE(CSS_FILTERS)
1577 if (layer->hasAncestorWithFilterOutsets()) {
1578 // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot
1579 // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
1583 IntRect updateRect = pixelSnappedIntRect(layer->repaintRectIncludingNonCompositingDescendants());
1584 updateRect = contentsToRootView(updateRect);
1585 if (!isCompositedContentLayer && clipsRepaints())
1586 updateRect.intersect(rectToScroll);
1587 if (!updateRect.isEmpty())
1588 regionToUpdate.unite(updateRect);
1592 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1594 // 2) update the area of fixed objects that has been invalidated
1595 Vector<IntRect> subRectsToUpdate = regionToUpdate.rects();
1596 size_t viewportConstrainedObjectsCount = subRectsToUpdate.size();
1597 for (size_t i = 0; i < viewportConstrainedObjectsCount; ++i) {
1598 IntRect updateRect = subRectsToUpdate[i];
1599 IntRect scrolledRect = updateRect;
1600 scrolledRect.move(scrollDelta);
1601 updateRect.unite(scrolledRect);
1602 #if USE(ACCELERATED_COMPOSITING)
1603 if (isCompositedContentLayer) {
1604 updateRect = rootViewToContents(updateRect);
1605 ASSERT(renderView());
1606 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
1610 if (clipsRepaints())
1611 updateRect.intersect(rectToScroll);
1612 hostWindow()->invalidateContentsAndRootView(updateRect, false);
1618 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1620 #if USE(ACCELERATED_COMPOSITING)
1621 if (contentsInCompositedLayer()) {
1622 IntRect updateRect = visibleContentRect();
1624 // Make sure to "apply" the scale factor here since we're converting from frame view
1625 // coordinates to layer backing coordinates.
1626 updateRect.scale(1 / m_frame->frameScaleFactor());
1628 ASSERT(renderView());
1629 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
1631 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1632 if (isEnclosedInCompositingLayer()) {
1633 LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1634 frameRenderer->borderTop() + frameRenderer->paddingTop(),
1635 visibleWidth(), visibleHeight());
1636 frameRenderer->repaintRectangle(rect);
1642 ScrollView::scrollContentsSlowPath(updateRect);
1645 // Note that this gets called at painting time.
1646 void FrameView::setIsOverlapped(bool isOverlapped)
1648 if (isOverlapped == m_isOverlapped)
1651 m_isOverlapped = isOverlapped;
1652 updateCanBlitOnScrollRecursively();
1654 #if USE(ACCELERATED_COMPOSITING)
1655 if (hasCompositedContentIncludingDescendants()) {
1656 // Overlap can affect compositing tests, so if it changes, we need to trigger
1657 // a layer update in the parent document.
1658 if (Frame* parentFrame = m_frame->tree()->parent()) {
1659 if (RenderView* parentView = parentFrame->contentRenderer()) {
1660 RenderLayerCompositor* compositor = parentView->compositor();
1661 compositor->setCompositingLayersNeedRebuild();
1662 compositor->scheduleCompositingLayerUpdate();
1666 if (RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) {
1667 // We also need to trigger reevaluation for this and all descendant frames,
1668 // since a frame uses compositing if any ancestor is compositing.
1669 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1670 if (RenderView* view = frame->contentRenderer()) {
1671 RenderLayerCompositor* compositor = view->compositor();
1672 compositor->setCompositingLayersNeedRebuild();
1673 compositor->scheduleCompositingLayerUpdate();
1681 bool FrameView::isOverlappedIncludingAncestors() const
1686 if (FrameView* parentView = parentFrameView()) {
1687 if (parentView->isOverlapped())
1694 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1696 if (contentIsOpaque == m_contentIsOpaque)
1699 m_contentIsOpaque = contentIsOpaque;
1700 updateCanBlitOnScrollRecursively();
1703 void FrameView::restoreScrollbar()
1705 setScrollbarsSuppressed(false);
1708 bool FrameView::scrollToFragment(const KURL& url)
1710 // If our URL has no ref, then we have no place we need to jump to.
1711 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1712 // and possibly repaint because :target pseudo class may have been
1713 // set (see bug 11321).
1714 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1717 String fragmentIdentifier = url.fragmentIdentifier();
1718 if (scrollToAnchor(fragmentIdentifier))
1721 // Try again after decoding the ref, based on the document's encoding.
1722 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1723 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1728 bool FrameView::scrollToAnchor(const String& name)
1730 ASSERT(m_frame->document());
1732 if (!m_frame->document()->haveStylesheetsLoaded()) {
1733 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1737 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1739 Element* anchorNode = m_frame->document()->findAnchor(name);
1741 // Setting to null will clear the current target.
1742 m_frame->document()->setCSSTarget(anchorNode);
1745 if (m_frame->document()->isSVGDocument()) {
1746 if (SVGSVGElement* svg = static_cast<SVGDocument*>(m_frame->document())->rootElement()) {
1747 svg->setupInitialView(name, anchorNode);
1754 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1755 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1758 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1762 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1764 m_maintainScrollPositionAnchor = anchorNode;
1765 if (!m_maintainScrollPositionAnchor)
1768 // We need to update the layout before scrolling, otherwise we could
1769 // really mess things up if an anchor scroll comes at a bad moment.
1770 m_frame->document()->updateStyleIfNeeded();
1771 // Only do a layout if changes have occurred that make it necessary.
1772 RenderView* renderView = this->renderView();
1773 if (renderView && renderView->needsLayout())
1779 void FrameView::scrollElementToRect(Element* element, const IntRect& rect)
1781 m_frame->document()->updateLayoutIgnorePendingStylesheets();
1783 LayoutRect bounds = element->boundingBox();
1784 int centeringOffsetX = (rect.width() - bounds.width()) / 2;
1785 int centeringOffsetY = (rect.height() - bounds.height()) / 2;
1786 setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y()));
1789 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1791 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1792 m_maintainScrollPositionAnchor = 0;
1794 IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint);
1796 if (newScrollPosition == scrollPosition())
1799 if (requestScrollPositionUpdate(newScrollPosition))
1802 ScrollView::setScrollPosition(newScrollPosition);
1805 void FrameView::delegatesScrollingDidChange()
1807 #if USE(ACCELERATED_COMPOSITING)
1808 // When we switch to delgatesScrolling mode, we should destroy the scrolling/clipping layers in RenderLayerCompositor.
1809 if (hasCompositedContent())
1810 clearBackingStores();
1814 void FrameView::setFixedVisibleContentRect(const IntRect& visibleContentRect)
1816 bool visibleContentSizeDidChange = false;
1817 if (visibleContentRect.size() != this->fixedVisibleContentRect().size()) {
1818 // When the viewport size changes or the content is scaled, we need to
1819 // reposition the fixed and sticky positioned elements.
1820 setViewportConstrainedObjectsNeedLayout();
1821 visibleContentSizeDidChange = true;
1824 IntSize offset = scrollOffset();
1825 ScrollView::setFixedVisibleContentRect(visibleContentRect);
1826 if (offset != scrollOffset()) {
1827 repaintFixedElementsAfterScrolling();
1828 if (m_frame->page()->settings()->acceleratedCompositingForFixedPositionEnabled())
1829 updateFixedElementsAfterScrolling();
1830 scrollAnimator()->setCurrentPosition(scrollPosition());
1831 scrollPositionChanged();
1833 if (visibleContentSizeDidChange) {
1834 // Update the scroll-bars to calculate new page-step size.
1835 updateScrollbars(scrollOffset());
1837 frame()->loader()->client()->didChangeScrollOffset();
1840 void FrameView::setViewportConstrainedObjectsNeedLayout()
1842 if (!hasViewportConstrainedObjects())
1845 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end();
1846 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) {
1847 RenderObject* renderer = *it;
1848 renderer->setNeedsLayout(true);
1853 void FrameView::scrollPositionChangedViaPlatformWidget()
1855 repaintFixedElementsAfterScrolling();
1856 updateFixedElementsAfterScrolling();
1857 scrollPositionChanged();
1860 void FrameView::scrollPositionChanged()
1862 frame()->eventHandler()->sendScrollEvent();
1863 frame()->eventHandler()->dispatchFakeMouseMoveEventSoon();
1865 #if USE(ACCELERATED_COMPOSITING)
1866 if (RenderView* renderView = this->renderView()) {
1867 if (renderView->usesCompositing())
1868 renderView->compositor()->frameViewDidScroll();
1873 void FrameView::repaintFixedElementsAfterScrolling()
1875 // For fixed position elements, update widget positions and compositing layers after scrolling,
1876 // but only if we're not inside of layout.
1877 if (!m_nestedLayoutCount && hasViewportConstrainedObjects()) {
1878 if (RenderView* renderView = this->renderView()) {
1879 renderView->updateWidgetPositions();
1880 renderView->layer()->updateLayerPositionsAfterDocumentScroll();
1885 bool FrameView::shouldUpdateFixedElementsAfterScrolling()
1887 #if ENABLE(THREADED_SCROLLING)
1888 Page* page = m_frame->page();
1892 // If the scrolling thread is updating the fixed elements, then the FrameView should not update them as well.
1893 if (page->mainFrame() != m_frame)
1896 ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
1897 if (!scrollingCoordinator)
1900 if (!scrollingCoordinator->supportsFixedPositionLayers())
1903 if (scrollingCoordinator->shouldUpdateScrollLayerPositionOnMainThread())
1906 if (inProgrammaticScroll())
1914 void FrameView::updateFixedElementsAfterScrolling()
1916 #if USE(ACCELERATED_COMPOSITING)
1917 if (!shouldUpdateFixedElementsAfterScrolling())
1920 if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) {
1921 if (RenderView* renderView = this->renderView())
1922 renderView->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
1927 bool FrameView::shouldRubberBandInDirection(ScrollDirection direction) const
1929 Page* page = frame() ? frame()->page() : 0;
1931 return ScrollView::shouldRubberBandInDirection(direction);
1932 return page->chrome()->client()->shouldRubberBandInDirection(direction);
1935 bool FrameView::isRubberBandInProgress() const
1937 if (scrollbarsSuppressed())
1940 // If the scrolling thread updates the scroll position for this FrameView, then we should return
1941 // ScrollingCoordinator::isRubberBandInProgress().
1942 if (Page* page = m_frame->page()) {
1943 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
1944 if (!scrollingCoordinator->shouldUpdateScrollLayerPositionOnMainThread())
1945 return scrollingCoordinator->isRubberBandInProgress();
1949 // If the main thread updates the scroll position for this FrameView, we should return
1950 // ScrollAnimator::isRubberBandInProgress().
1951 if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
1952 return scrollAnimator->isRubberBandInProgress();
1957 bool FrameView::requestScrollPositionUpdate(const IntPoint& position)
1959 #if ENABLE(THREADED_SCROLLING)
1960 if (TiledBacking* tiledBacking = this->tiledBacking()) {
1961 IntRect visibleRect = visibleContentRect();
1962 visibleRect.setLocation(position);
1963 tiledBacking->prepopulateRect(visibleRect);
1966 if (Page* page = m_frame->page()) {
1967 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1968 return scrollingCoordinator->requestScrollPositionUpdate(this, position);
1971 UNUSED_PARAM(position);
1977 HostWindow* FrameView::hostWindow() const
1979 Page* page = frame() ? frame()->page() : 0;
1982 return page->chrome();
1985 const unsigned cRepaintRectUnionThreshold = 25;
1987 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
1989 ASSERT(!m_frame->ownerElement());
1991 if (m_isTrackingRepaints) {
1992 IntRect repaintRect = r;
1993 repaintRect.move(-scrollOffset());
1994 m_trackedRepaintRects.append(repaintRect);
1997 double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay();
1998 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
1999 IntRect paintRect = r;
2000 if (clipsRepaints() && !paintsEntireContents())
2001 paintRect.intersect(visibleContentRect());
2002 if (paintRect.isEmpty())
2004 if (m_repaintCount == cRepaintRectUnionThreshold) {
2005 IntRect unionedRect;
2006 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
2007 unionedRect.unite(pixelSnappedIntRect(m_repaintRects[i]));
2008 m_repaintRects.clear();
2009 m_repaintRects.append(unionedRect);
2011 if (m_repaintCount < cRepaintRectUnionThreshold)
2012 m_repaintRects.append(paintRect);
2014 m_repaintRects[0].unite(paintRect);
2017 if (!m_deferringRepaints)
2018 startDeferredRepaintTimer(delay);
2023 if (!shouldUpdate(immediate))
2026 #if USE(TILED_BACKING_STORE)
2027 if (frame()->tiledBackingStore()) {
2028 frame()->tiledBackingStore()->invalidate(r);
2032 ScrollView::repaintContentRectangle(r, immediate);
2035 void FrameView::contentsResized()
2037 ScrollView::contentsResized();
2041 void FrameView::visibleContentsResized()
2043 // We check to make sure the view is attached to a frame() as this method can
2044 // be triggered before the view is attached by Frame::createView(...) setting
2045 // various values such as setScrollBarModes(...) for example. An ASSERT is
2046 // triggered when a view is layout before being attached to a frame().
2047 if (!frame()->view())
2050 if (!useFixedLayout() && needsLayout())
2053 #if USE(ACCELERATED_COMPOSITING)
2054 if (RenderView* renderView = this->renderView()) {
2055 if (renderView->usesCompositing())
2056 renderView->compositor()->frameViewDidChangeSize();
2061 void FrameView::beginDeferredRepaints()
2063 Page* page = m_frame->page();
2064 if (page->mainFrame() != m_frame) {
2065 page->mainFrame()->view()->beginDeferredRepaints();
2069 m_deferringRepaints++;
2072 void FrameView::endDeferredRepaints()
2074 Page* page = m_frame->page();
2075 if (page->mainFrame() != m_frame) {
2076 page->mainFrame()->view()->endDeferredRepaints();
2080 ASSERT(m_deferringRepaints > 0);
2082 if (--m_deferringRepaints)
2085 if (m_deferredRepaintTimer.isActive())
2088 if (double delay = adjustedDeferredRepaintDelay()) {
2089 startDeferredRepaintTimer(delay);
2093 doDeferredRepaints();
2096 void FrameView::startDeferredRepaintTimer(double delay)
2098 if (m_deferredRepaintTimer.isActive())
2101 if (m_disableRepaints)
2104 m_deferredRepaintTimer.startOneShot(delay);
2107 void FrameView::handleLoadCompleted()
2109 // Once loading has completed, allow autoSize one last opportunity to
2110 // reduce the size of the frame.
2111 autoSizeIfEnabled();
2112 if (shouldUseLoadTimeDeferredRepaintDelay())
2114 m_deferredRepaintDelay = s_normalDeferredRepaintDelay;
2115 flushDeferredRepaints();
2118 void FrameView::flushDeferredRepaints()
2120 if (!m_deferredRepaintTimer.isActive())
2122 m_deferredRepaintTimer.stop();
2123 doDeferredRepaints();
2126 void FrameView::doDeferredRepaints()
2128 if (m_disableRepaints)
2131 ASSERT(!m_deferringRepaints);
2132 if (!shouldUpdate()) {
2133 m_repaintRects.clear();
2137 unsigned size = m_repaintRects.size();
2138 for (unsigned i = 0; i < size; i++) {
2139 #if USE(TILED_BACKING_STORE)
2140 if (frame()->tiledBackingStore()) {
2141 frame()->tiledBackingStore()->invalidate(pixelSnappedIntRect(m_repaintRects[i]));
2145 ScrollView::repaintContentRectangle(pixelSnappedIntRect(m_repaintRects[i]), false);
2147 m_repaintRects.clear();
2150 updateDeferredRepaintDelayAfterRepaint();
2153 bool FrameView::shouldUseLoadTimeDeferredRepaintDelay() const
2155 // Don't defer after the initial load of the page has been completed.
2156 if (m_frame->tree()->top()->loader()->isComplete())
2158 Document* document = m_frame->document();
2161 if (document->parsing())
2163 if (document->cachedResourceLoader()->requestCount())
2168 void FrameView::updateDeferredRepaintDelayAfterRepaint()
2170 if (!shouldUseLoadTimeDeferredRepaintDelay()) {
2171 m_deferredRepaintDelay = s_normalDeferredRepaintDelay;
2174 double incrementedRepaintDelay = m_deferredRepaintDelay + s_deferredRepaintDelayIncrementDuringLoading;
2175 m_deferredRepaintDelay = std::min(incrementedRepaintDelay, s_maxDeferredRepaintDelayDuringLoading);
2178 void FrameView::resetDeferredRepaintDelay()
2180 m_deferredRepaintDelay = 0;
2181 if (m_deferredRepaintTimer.isActive()) {
2182 m_deferredRepaintTimer.stop();
2183 if (!m_deferringRepaints)
2184 doDeferredRepaints();
2188 double FrameView::adjustedDeferredRepaintDelay() const
2190 ASSERT(!m_deferringRepaints);
2191 if (!m_deferredRepaintDelay)
2193 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
2194 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
2197 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
2199 doDeferredRepaints();
2202 void FrameView::beginDisableRepaints()
2204 m_disableRepaints++;
2207 void FrameView::endDisableRepaints()
2209 ASSERT(m_disableRepaints > 0);
2210 m_disableRepaints--;
2213 void FrameView::layoutTimerFired(Timer<FrameView>*)
2215 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2216 if (!m_frame->document()->ownerElement())
2217 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
2222 void FrameView::scheduleRelayout()
2224 // FIXME: We should assert the page is not in the page cache, but that is causing
2225 // too many false assertions. See <rdar://problem/7218118>.
2226 ASSERT(m_frame->view() == this);
2229 m_layoutRoot->markContainingBlocksForLayout(false);
2232 if (!m_layoutSchedulingEnabled)
2236 if (!m_frame->document()->shouldScheduleLayout())
2238 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2239 // When frame flattening is enabled, the contents of the frame could affect the layout of the parent frames.
2240 // Also invalidate parent frame starting from the owner element of this frame.
2241 if (m_frame->ownerRenderer() && isInChildFrameWithFrameFlattening())
2242 m_frame->ownerRenderer()->setNeedsLayout(true, MarkContainingBlockChain);
2244 int delay = m_frame->document()->minimumLayoutDelay();
2245 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
2246 unscheduleRelayout();
2247 if (m_layoutTimer.isActive())
2250 m_delayedLayout = delay != 0;
2252 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2253 if (!m_frame->document()->ownerElement())
2254 printf("Scheduling layout for %d\n", delay);
2257 m_layoutTimer.startOneShot(delay * 0.001);
2260 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
2262 for (RenderObject* r = descendant; r; r = r->container()) {
2269 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
2271 ASSERT(m_frame->view() == this);
2273 RenderView* renderView = this->renderView();
2274 if (renderView && renderView->needsLayout()) {
2276 relayoutRoot->markContainingBlocksForLayout(false);
2280 if (layoutPending() || !m_layoutSchedulingEnabled) {
2281 if (m_layoutRoot != relayoutRoot) {
2282 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
2283 // Keep the current root
2284 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
2285 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2286 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
2287 // Re-root at relayoutRoot
2288 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
2289 m_layoutRoot = relayoutRoot;
2290 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2291 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2293 // Just do a full relayout
2295 m_layoutRoot->markContainingBlocksForLayout(false);
2297 relayoutRoot->markContainingBlocksForLayout(false);
2298 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2301 } else if (m_layoutSchedulingEnabled) {
2302 int delay = m_frame->document()->minimumLayoutDelay();
2303 m_layoutRoot = relayoutRoot;
2304 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2305 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2306 m_delayedLayout = delay != 0;
2307 m_layoutTimer.startOneShot(delay * 0.001);
2311 bool FrameView::layoutPending() const
2313 return m_layoutTimer.isActive();
2316 bool FrameView::needsLayout() const
2318 // This can return true in cases where the document does not have a body yet.
2319 // Document::shouldScheduleLayout takes care of preventing us from scheduling
2320 // layout in that case.
2324 RenderView* renderView = this->renderView();
2325 return layoutPending()
2326 || (renderView && renderView->needsLayout())
2328 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
2331 void FrameView::setNeedsLayout()
2333 if (m_deferSetNeedsLayouts) {
2334 m_setNeedsLayoutWasDeferred = true;
2338 if (RenderView* renderView = this->renderView())
2339 renderView->setNeedsLayout(true);
2342 void FrameView::unscheduleRelayout()
2344 if (!m_layoutTimer.isActive())
2347 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2348 if (!m_frame->document()->ownerElement())
2349 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
2352 m_layoutTimer.stop();
2353 m_delayedLayout = false;
2356 #if ENABLE(REQUEST_ANIMATION_FRAME)
2357 void FrameView::serviceScriptedAnimations(double monotonicAnimationStartTime)
2359 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext()) {
2360 frame->view()->serviceScrollAnimations();
2361 frame->animation()->serviceAnimations();
2364 Vector<RefPtr<Document> > documents;
2365 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext())
2366 documents.append(frame->document());
2368 for (size_t i = 0; i < documents.size(); ++i)
2369 documents[i]->serviceScriptedAnimations(monotonicAnimationStartTime);
2373 bool FrameView::isTransparent() const
2375 return m_isTransparent;
2378 void FrameView::setTransparent(bool isTransparent)
2380 m_isTransparent = isTransparent;
2383 bool FrameView::hasOpaqueBackground() const
2385 return !m_isTransparent && !m_baseBackgroundColor.hasAlpha();
2388 Color FrameView::baseBackgroundColor() const
2390 return m_baseBackgroundColor;
2393 void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
2395 if (!backgroundColor.isValid())
2396 m_baseBackgroundColor = Color::white;
2398 m_baseBackgroundColor = backgroundColor;
2400 recalculateScrollbarOverlayStyle();
2403 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
2405 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
2406 if (FrameView* view = frame->view()) {
2407 view->setTransparent(transparent);
2408 view->setBaseBackgroundColor(backgroundColor);
2413 bool FrameView::shouldUpdateWhileOffscreen() const
2415 return m_shouldUpdateWhileOffscreen;
2418 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
2420 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
2423 bool FrameView::shouldUpdate(bool immediateRequested) const
2425 if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen())
2430 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
2432 m_actionScheduler->scheduleEvent(event, eventTarget);
2435 void FrameView::pauseScheduledEvents()
2437 m_actionScheduler->pause();
2440 void FrameView::resumeScheduledEvents()
2442 m_actionScheduler->resume();
2445 void FrameView::scrollToAnchor()
2447 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
2451 if (!anchorNode->renderer())
2455 if (anchorNode != m_frame->document())
2456 rect = anchorNode->boundingBox();
2458 // Scroll nested layers and frames to reveal the anchor.
2459 // Align to the top and to the closest side (this matches other browsers).
2460 anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
2462 if (AXObjectCache::accessibilityEnabled())
2463 m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get());
2465 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
2466 m_maintainScrollPositionAnchor = anchorNode;
2469 void FrameView::updateWidget(RenderObject* object)
2471 ASSERT(!object->node() || object->node()->isElementNode());
2472 Element* ownerElement = static_cast<Element*>(object->node());
2473 // The object may have already been destroyed (thus node cleared),
2474 // but FrameView holds a manual ref, so it won't have been deleted.
2475 ASSERT(m_widgetUpdateSet->contains(object));
2479 if (object->isEmbeddedObject()) {
2480 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
2481 // No need to update if it's already crashed or known to be missing.
2482 if (embeddedObject->showsUnavailablePluginIndicator())
2485 // FIXME: This could turn into a real virtual dispatch if we defined
2486 // updateWidget(PluginCreationOption) on HTMLElement.
2487 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag) || ownerElement->hasTagName(appletTag)) {
2488 HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(ownerElement);
2489 if (pluginElement->needsWidgetUpdate())
2490 pluginElement->updateWidget(CreateAnyWidgetType);
2492 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
2493 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
2494 else if (ownerElement->isMediaElement())
2495 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
2498 ASSERT_NOT_REACHED();
2500 // Caution: it's possible the object was destroyed again, since loading a
2501 // plugin may run any arbitrary JavaScript.
2502 embeddedObject->updateWidgetPosition();
2503 } else if (object->isSnapshottedPlugIn()) {
2504 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag)) {
2505 HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(ownerElement);
2506 pluginElement->updateSnapshotInfo();
2511 bool FrameView::updateWidgets()
2513 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
2516 size_t size = m_widgetUpdateSet->size();
2518 Vector<RenderObject*> objects;
2519 objects.reserveInitialCapacity(size);
2521 RenderObjectSet::const_iterator end = m_widgetUpdateSet->end();
2522 for (RenderObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
2523 RenderObject* object = *it;
2524 objects.uncheckedAppend(object);
2525 if (object->isEmbeddedObject()) {
2526 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
2527 embeddedObject->ref();
2531 for (size_t i = 0; i < size; ++i) {
2532 RenderObject* object = objects[i];
2533 updateWidget(object);
2534 m_widgetUpdateSet->remove(object);
2537 RenderArena* arena = m_frame->document()->renderArena();
2538 for (size_t i = 0; i < size; ++i) {
2539 RenderObject* object = objects[i];
2540 if (object->isEmbeddedObject()) {
2541 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
2542 embeddedObject->deref(arena);
2546 return m_widgetUpdateSet->isEmpty();
2549 void FrameView::flushAnyPendingPostLayoutTasks()
2551 if (!m_postLayoutTasksTimer.isActive())
2554 performPostLayoutTasks();
2557 void FrameView::performPostLayoutTasks()
2559 m_postLayoutTasksTimer.stop();
2561 m_frame->selection()->setCaretRectNeedsUpdate();
2562 m_frame->selection()->updateAppearance();
2564 LayoutMilestones milestonesOfInterest = 0;
2565 LayoutMilestones milestonesAchieved = 0;
2566 Page* page = m_frame->page();
2568 milestonesOfInterest = page->layoutMilestones();
2570 if (m_nestedLayoutCount <= 1) {
2571 if (m_firstLayoutCallbackPending) {
2572 m_firstLayoutCallbackPending = false;
2573 m_frame->loader()->didFirstLayout();
2574 if (milestonesOfInterest & DidFirstLayout)
2575 milestonesAchieved |= DidFirstLayout;
2577 if (page->mainFrame() == m_frame)
2578 page->startCountingRelevantRepaintedObjects();
2582 // Ensure that we always send this eventually.
2583 if (!m_frame->document()->parsing() && m_frame->loader()->stateMachine()->committedFirstRealDocumentLoad())
2584 m_isVisuallyNonEmpty = true;
2586 // If the layout was done with pending sheets, we are not in fact visually non-empty yet.
2587 if (m_isVisuallyNonEmpty && !m_frame->document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) {
2588 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
2589 if (milestonesOfInterest & DidFirstVisuallyNonEmptyLayout)
2590 milestonesAchieved |= DidFirstVisuallyNonEmptyLayout;
2594 m_frame->loader()->didLayout(milestonesAchieved);
2596 // FIXME: We should consider adding DidLayout as a LayoutMilestone. That would let us merge this
2597 // with didLayout(LayoutMilestones).
2598 m_frame->loader()->client()->dispatchDidLayout();
2600 RenderView* renderView = this->renderView();
2602 renderView->updateWidgetPositions();
2604 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
2605 if (updateWidgets())
2610 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2611 scrollingCoordinator->frameViewLayoutUpdated(this);
2614 #if USE(ACCELERATED_COMPOSITING)
2615 if (renderView && renderView->usesCompositing())
2616 renderView->compositor()->frameViewDidLayout();
2621 m_actionScheduler->resume();
2623 if (renderView && !renderView->printing()) {
2624 IntSize currentSize;
2625 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
2626 currentSize = fixedLayoutSize();
2628 currentSize = visibleContentRect(IncludeScrollbars).size();
2629 float currentZoomFactor = renderView->style()->zoom();
2630 bool resized = !m_firstLayout && (currentSize != m_lastViewportSize || currentZoomFactor != m_lastZoomFactor);
2631 m_lastViewportSize = currentSize;
2632 m_lastZoomFactor = currentZoomFactor;
2634 m_frame->eventHandler()->sendResizeEvent();
2636 #if ENABLE(INSPECTOR)
2637 if (InspectorInstrumentation::hasFrontends()) {
2639 if (page->mainFrame() == m_frame) {
2640 if (InspectorClient* inspectorClient = page->inspectorController()->inspectorClient())
2641 inspectorClient->didResizeMainFrame(m_frame.get());
2650 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
2652 performPostLayoutTasks();
2655 void FrameView::autoSizeIfEnabled()
2657 if (!m_shouldAutoSize)
2663 TemporaryChange<bool> changeInAutoSize(m_inAutoSize, true);
2665 Document* document = frame()->document();
2669 RenderView* documentView = document->renderView();
2670 Element* documentElement = document->documentElement();
2671 if (!documentView || !documentElement)
2674 RenderBox* documentRenderBox = documentElement->renderBox();
2675 if (!documentRenderBox)
2678 // If this is the first time we run autosize, start from small height and
2679 // allow it to grow.
2680 if (!m_didRunAutosize)
2681 resize(frameRect().width(), m_minAutoSize.height());
2683 IntSize size = frameRect().size();
2685 // Do the resizing twice. The first time is basically a rough calculation using the preferred width
2686 // which may result in a height change during the second iteration.
2687 for (int i = 0; i < 2; i++) {
2688 // Update various sizes including contentsSize, scrollHeight, etc.
2689 document->updateLayoutIgnorePendingStylesheets();
2690 int width = documentView->minPreferredLogicalWidth();
2691 int height = documentRenderBox->scrollHeight();
2692 IntSize newSize(width, height);
2694 // Check to see if a scrollbar is needed for a given dimension and
2695 // if so, increase the other dimension to account for the scrollbar.
2696 // Since the dimensions are only for the view rectangle, once a
2697 // dimension exceeds the maximum, there is no need to increase it further.
2698 if (newSize.width() > m_maxAutoSize.width()) {
2699 RefPtr<Scrollbar> localHorizontalScrollbar = horizontalScrollbar();
2700 if (!localHorizontalScrollbar)
2701 localHorizontalScrollbar = createScrollbar(HorizontalScrollbar);
2702 if (!localHorizontalScrollbar->isOverlayScrollbar())
2703 newSize.setHeight(newSize.height() + localHorizontalScrollbar->height());
2705 // Don't bother checking for a vertical scrollbar because the width is at
2706 // already greater the maximum.
2707 } else if (newSize.height() > m_maxAutoSize.height()) {
2708 RefPtr<Scrollbar> localVerticalScrollbar = verticalScrollbar();
2709 if (!localVerticalScrollbar)
2710 localVerticalScrollbar = createScrollbar(VerticalScrollbar);
2711 if (!localVerticalScrollbar->isOverlayScrollbar())
2712 newSize.setWidth(newSize.width() + localVerticalScrollbar->width());
2714 // Don't bother checking for a horizontal scrollbar because the height is
2715 // already greater the maximum.
2718 // Ensure the size is at least the min bounds.
2719 newSize = newSize.expandedTo(m_minAutoSize);
2721 // Bound the dimensions by the max bounds and determine what scrollbars to show.
2722 ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff;
2723 if (newSize.width() > m_maxAutoSize.width()) {
2724 newSize.setWidth(m_maxAutoSize.width());
2725 horizonalScrollbarMode = ScrollbarAlwaysOn;
2727 ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff;
2728 if (newSize.height() > m_maxAutoSize.height()) {
2729 newSize.setHeight(m_maxAutoSize.height());
2730 verticalScrollbarMode = ScrollbarAlwaysOn;
2733 if (newSize == size)
2736 // While loading only allow the size to increase (to avoid twitching during intermediate smaller states)
2737 // unless autoresize has just been turned on or the maximum size is smaller than the current size.
2738 if (m_didRunAutosize && size.height() <= m_maxAutoSize.height() && size.width() <= m_maxAutoSize.width()
2739 && !frame()->loader()->isComplete() && (newSize.height() < size.height() || newSize.width() < size.width()))
2742 resize(newSize.width(), newSize.height());
2743 // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example,
2744 // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed).
2745 setVerticalScrollbarLock(false);
2746 setHorizontalScrollbarLock(false);
2747 setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true);
2749 m_didRunAutosize = true;
2752 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
2754 if (!m_viewportRenderer)
2757 if (m_overflowStatusDirty) {
2758 m_horizontalOverflow = horizontalOverflow;
2759 m_verticalOverflow = verticalOverflow;
2760 m_overflowStatusDirty = false;
2764 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
2765 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
2767 if (horizontalOverflowChanged || verticalOverflowChanged) {
2768 m_horizontalOverflow = horizontalOverflow;
2769 m_verticalOverflow = verticalOverflow;
2771 m_actionScheduler->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
2772 verticalOverflowChanged, verticalOverflow),
2773 m_viewportRenderer->node());
2778 const Pagination& FrameView::pagination() const
2780 if (m_pagination != Pagination())
2781 return m_pagination;
2783 if (Page* page = m_frame->page()) {
2784 if (page->mainFrame() == m_frame)
2785 return page->pagination();
2788 return m_pagination;
2791 void FrameView::setPagination(const Pagination& pagination)
2793 if (m_pagination == pagination)
2796 m_pagination = pagination;
2799 m_frame->document()->styleResolverChanged(DeferRecalcStyle);
2802 IntRect FrameView::windowClipRect(bool clipToContents) const
2804 ASSERT(m_frame->view() == this);
2806 if (paintsEntireContents())
2807 return IntRect(IntPoint(), contentsSize());
2809 // Set our clip rect to be our contents.
2810 IntRect clipRect = contentsToWindow(visibleContentRect(clipToContents ? ExcludeScrollbars : IncludeScrollbars));
2811 if (!m_frame || !m_frame->ownerElement())
2814 // Take our owner element and get its clip rect.
2815 HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement();
2816 FrameView* parentView = ownerElement->document()->view();
2818 clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement, true));
2822 IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement, bool clipToLayerContents) const
2824 // The renderer can sometimes be null when style="display:none" interacts
2825 // with external content and plugins.
2826 if (!ownerElement->renderer())
2827 return windowClipRect();
2829 // If we have no layer, just return our window clip rect.
2830 const RenderLayer* enclosingLayer = ownerElement->renderer()->enclosingLayer();
2831 if (!enclosingLayer)
2832 return windowClipRect();
2834 // Apply the clip from the layer.
2836 if (clipToLayerContents)
2837 clipRect = pixelSnappedIntRect(enclosingLayer->childrenClipRect());
2839 clipRect = pixelSnappedIntRect(enclosingLayer->selfClipRect());
2840 clipRect = contentsToWindow(clipRect);
2841 return intersection(clipRect, windowClipRect());
2844 bool FrameView::isActive() const
2846 Page* page = frame()->page();
2847 return page && page->focusController()->isActive();
2850 void FrameView::scrollTo(const IntSize& newOffset)
2852 LayoutSize offset = scrollOffset();
2853 ScrollView::scrollTo(newOffset);
2854 if (offset != scrollOffset())
2855 scrollPositionChanged();
2856 frame()->loader()->client()->didChangeScrollOffset();
2859 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
2861 // Add in our offset within the FrameView.
2862 IntRect dirtyRect = rect;
2863 dirtyRect.moveBy(scrollbar->location());
2864 invalidateRect(dirtyRect);
2867 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
2869 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
2872 IntRect FrameView::windowResizerRect() const
2874 Page* page = frame() ? frame()->page() : 0;
2877 return page->chrome()->windowResizerRect();
2880 float FrameView::visibleContentScaleFactor() const
2882 if (!m_frame || !m_frame->page())
2885 if (!m_frame->settings()->applyPageScaleFactorInCompositor() || m_frame != m_frame->page()->mainFrame())
2888 return m_frame->page()->pageScaleFactor();
2891 void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
2893 Page* page = m_frame->page();
2896 if (page->mainFrame() != m_frame)
2898 page->chrome()->client()->notifyScrollerThumbIsVisibleInRect(scrollerThumb);
2901 bool FrameView::scrollbarsCanBeActive() const
2906 if (m_frame->view() != this)
2909 if (Page* page = m_frame->page()) {
2910 if (page->shouldSuppressScrollbarAnimations())
2914 if (Document* document = m_frame->document())
2915 return !document->inPageCache();
2920 ScrollableArea* FrameView::enclosingScrollableArea() const
2922 // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer.
2926 IntRect FrameView::scrollableAreaBoundingBox() const
2928 RenderPart* ownerRenderer = frame()->ownerRenderer();
2932 return ownerRenderer->absoluteContentQuad().enclosingBoundingBox();
2935 bool FrameView::isScrollable()
2938 // 1) If there an actual overflow.
2939 // 2) display:none or visibility:hidden set to self or inherited.
2940 // 3) overflow{-x,-y}: hidden;
2941 // 4) scrolling: no;
2944 IntSize contentSize = contentsSize();
2945 IntSize visibleContentSize = visibleContentRect().size();
2946 if ((contentSize.height() <= visibleContentSize.height() && contentSize.width() <= visibleContentSize.width()))
2950 HTMLFrameOwnerElement* owner = m_frame->ownerElement();
2951 if (owner && (!owner->renderer() || !owner->renderer()->visibleToHitTesting()))
2955 ScrollbarMode horizontalMode;
2956 ScrollbarMode verticalMode;
2957 calculateScrollbarModesForLayout(horizontalMode, verticalMode, RulesFromWebContentOnly);
2958 if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff)
2964 void FrameView::updateScrollableAreaSet()
2966 // That ensures that only inner frames are cached.
2967 FrameView* parentFrameView = this->parentFrameView();
2968 if (!parentFrameView)
2971 if (!isScrollable()) {
2972 parentFrameView->removeScrollableArea(this);
2976 parentFrameView->addScrollableArea(this);
2979 bool FrameView::shouldSuspendScrollAnimations() const
2981 return m_frame->loader()->state() != FrameStateComplete;
2984 void FrameView::scrollbarStyleChanged(int newStyle, bool forceUpdate)
2986 Page* page = m_frame->page();
2989 if (page->mainFrame() != m_frame)
2991 page->chrome()->client()->recommendedScrollbarStyleDidChange(newStyle);
2994 ScrollView::scrollbarStyleChanged(newStyle, forceUpdate);
2997 void FrameView::setAnimatorsAreActive()
2999 Page* page = m_frame->page();
3003 if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
3004 scrollAnimator->setIsActive();
3006 if (!m_scrollableAreas)
3009 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
3010 ScrollableArea* scrollableArea = *it;
3012 ASSERT(scrollableArea->scrollbarsCanBeActive());
3013 scrollableArea->scrollAnimator()->setIsActive();
3017 void FrameView::notifyPageThatContentAreaWillPaint() const
3019 Page* page = m_frame->page();
3023 contentAreaWillPaint();
3025 if (!m_scrollableAreas)
3028 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
3029 ScrollableArea* scrollableArea = *it;
3031 if (!scrollableArea->scrollbarsCanBeActive())
3034 scrollableArea->contentAreaWillPaint();
3038 bool FrameView::scrollAnimatorEnabled() const
3040 #if ENABLE(SMOOTH_SCROLLING)
3041 if (Page* page = m_frame->page())
3042 return page->settings()->scrollAnimatorEnabled();
3048 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
3049 void FrameView::updateAnnotatedRegions()
3051 Document* document = m_frame->document();
3052 if (!document->hasAnnotatedRegions())
3054 Vector<AnnotatedRegionValue> newRegions;
3055 document->renderBox()->collectAnnotatedRegions(newRegions);
3056 if (newRegions == document->annotatedRegions())
3058 document->setAnnotatedRegions(newRegions);
3059 Page* page = m_frame->page();
3062 page->chrome()->client()->annotatedRegionsChanged();
3066 void FrameView::updateScrollCorner()
3068 RenderObject* renderer = 0;
3069 RefPtr<RenderStyle> cornerStyle;
3070 IntRect cornerRect = scrollCornerRect();
3072 if (!cornerRect.isEmpty()) {
3073 // Try the <body> element first as a scroll corner source.
3074 Document* doc = m_frame->document();
3075 Element* body = doc ? doc->body() : 0;
3076 if (body && body->renderer()) {
3077 renderer = body->renderer();
3078 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
3082 // If the <body> didn't have a custom style, then the root element might.
3083 Element* docElement = doc ? doc->documentElement() : 0;
3084 if (docElement && docElement->renderer()) {
3085 renderer = docElement->renderer();
3086 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
3091 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
3092 if (RenderPart* renderer = m_frame->ownerRenderer())
3093 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
3098 if (!m_scrollCorner)
3099 m_scrollCorner = RenderScrollbarPart::createAnonymous(renderer->document());
3100 m_scrollCorner->setStyle(cornerStyle.release());
3101 invalidateScrollCorner(cornerRect);
3102 } else if (m_scrollCorner) {
3103 m_scrollCorner->destroy();
3107 ScrollView::updateScrollCorner();
3110 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
3112 if (context->updatingControlTints()) {
3113 updateScrollCorner();
3117 if (m_scrollCorner) {
3118 bool needsBackgorund = m_frame->page() && m_frame->page()->mainFrame() == m_frame;
3119 if (needsBackgorund)
3120 context->fillRect(cornerRect, baseBackgroundColor(), ColorSpaceDeviceRGB);
3121 m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect);
3125 ScrollView::paintScrollCorner(context, cornerRect);
3128 void FrameView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
3130 bool needsBackgorund = bar->isCustomScrollbar() && (m_frame->page() && m_frame->page()->mainFrame() == m_frame);
3131 if (needsBackgorund) {
3132 IntRect toFill = bar->frameRect();
3133 toFill.intersect(rect);
3134 context->fillRect(toFill, baseBackgroundColor(), ColorSpaceDeviceRGB);
3137 ScrollView::paintScrollbar(context, bar, rect);
3140 Color FrameView::documentBackgroundColor() const
3142 // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of
3143 // the document and the body against the base background color of the frame view.
3144 // Background images are unfortunately impractical to include.
3146 // Return invalid Color objects whenever there is insufficient information.
3147 if (!frame()->document())
3150 Element* htmlElement = frame()->document()->documentElement();
3151 Element* bodyElement = frame()->document()->body();
3153 // Start with invalid colors.
3154 Color htmlBackgroundColor;
3155 Color bodyBackgroundColor;
3156 if (htmlElement && htmlElement->renderer())
3157 htmlBackgroundColor = htmlElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
3158 if (bodyElement && bodyElement->renderer())
3159 bodyBackgroundColor = bodyElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
3161 if (!bodyBackgroundColor.isValid()) {
3162 if (!htmlBackgroundColor.isValid())
3164 return baseBackgroundColor().blend(htmlBackgroundColor);
3167 if (!htmlBackgroundColor.isValid())
3168 return baseBackgroundColor().blend(bodyBackgroundColor);
3170 // We take the aggregate of the base background color
3171 // the <html> background color, and the <body>
3172 // background color to find the document color. The
3173 // addition of the base background color is not
3174 // technically part of the document background, but it
3175 // otherwise poses problems when the aggregate is not
3177 return baseBackgroundColor().blend(htmlBackgroundColor).blend(bodyBackgroundColor);
3180 bool FrameView::hasCustomScrollbars() const
3182 const HashSet<RefPtr<Widget> >* viewChildren = children();
3183 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
3184 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
3185 Widget* widget = current->get();
3186 if (widget->isFrameView()) {
3187 if (static_cast<FrameView*>(widget)->hasCustomScrollbars())
3189 } else if (widget->isScrollbar()) {
3190 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
3191 if (scrollbar->isCustomScrollbar())
3199 FrameView* FrameView::parentFrameView() const
3204 if (Frame* parentFrame = m_frame->tree()->parent())
3205 return parentFrame->view();
3210 bool FrameView::isInChildFrameWithFrameFlattening() const
3212 if (!parent() || !m_frame->ownerElement())
3215 // Frame flattening applies when the owner element is either in a frameset or
3216 // an iframe with flattening parameters.
3217 if (m_frame->ownerElement()->hasTagName(iframeTag)) {
3218 RenderIFrame* iframeRenderer = toRenderIFrame(m_frame->ownerElement()->renderPart());
3219 if (iframeRenderer->flattenFrame() || iframeRenderer->isSeamless())
3223 if (!m_frame->settings() || !m_frame->settings()->frameFlatteningEnabled())
3226 if (m_frame->ownerElement()->hasTagName(frameTag))
3232 bool FrameView::doLayoutWithFrameFlattening(bool allowSubtree)
3234 // Try initiating layout from the topmost parent.
3235 FrameView* parentView = parentFrameView();
3240 // In the middle of parent layout, no need to restart from topmost.
3241 if (parentView->m_nestedLayoutCount)
3244 // Parent tree is clean. Starting layout from it would have no effect.
3245 if (!parentView->needsLayout())
3248 while (parentView->parentFrameView())
3249 parentView = parentView->parentFrameView();
3251 parentView->layout(allowSubtree);
3253 RenderObject* root = m_layoutRoot ? m_layoutRoot : m_frame->document()->renderer();
3254 ASSERT_UNUSED(root, !root->needsLayout());
3259 void FrameView::updateControlTints()
3261 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
3262 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
3263 // This is only done if the theme supports control tinting. It's up to the theme and platform
3264 // to define when controls get the tint and to call this function when that changes.
3266 // Optimize the common case where we bring a window to the front while it's still empty.
3267 if (!m_frame || m_frame->document()->url().isEmpty())
3270 RenderView* renderView = this->renderView();
3271 if ((renderView && renderView->theme()->supportsControlTints()) || hasCustomScrollbars())
3272 paintControlTints();
3275 void FrameView::paintControlTints()
3279 PlatformGraphicsContext* const noContext = 0;
3280 GraphicsContext context(noContext);
3281 context.setUpdatingControlTints(true);
3282 if (platformWidget())
3283 paintContents(&context, visibleContentRect());
3285 paint(&context, frameRect());
3288 bool FrameView::wasScrolledByUser() const
3290 return m_wasScrolledByUser;
3293 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
3295 if (m_inProgrammaticScroll)
3297 m_maintainScrollPositionAnchor = 0;
3298 m_wasScrolledByUser = wasScrolledByUser;
3301 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
3306 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get());
3308 Document* document = m_frame->document();
3312 if (document->printing())
3313 fillWithRed = false; // Printing, don't fill with red (can't remember why).
3314 else if (m_frame->ownerElement())
3315 fillWithRed = false; // Subframe, don't fill with red.
3316 else if (isTransparent())
3317 fillWithRed = false; // Transparent, don't fill with red.
3318 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
3319 fillWithRed = false; // Selections are transparent, don't fill with red.
3320 else if (m_nodeToDraw)
3321 fillWithRed = false; // Element images are transparent, don't fill with red.
3326 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
3329 RenderView* renderView = this->renderView();
3331 LOG_ERROR("called FrameView::paint with nil renderer");
3335 ASSERT(!needsLayout());
3339 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
3340 if (isTopLevelPainter)
3341 sCurrentPaintTimeStamp = currentTime();
3343 FontCachePurgePreventer fontCachePurgePreventer;
3345 #if USE(ACCELERATED_COMPOSITING)
3346 if (!p->paintingDisabled() && !document->printing())
3347 flushCompositingStateForThisFrame(m_frame.get());
3350 PaintBehavior oldPaintBehavior = m_paintBehavior;
3352 if (FrameView* parentView = parentFrameView()) {
3353 if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
3354 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
3357 if (m_paintBehavior == PaintBehaviorNormal)
3358 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
3360 if (document->printing())
3361 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
3363 bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers;
3364 bool isRootFrame = !m_frame->ownerElement();
3365 if (flatteningPaint && isRootFrame)
3366 notifyWidgetsInAllFrames(WillPaintFlattened);
3368 ASSERT(!m_isPainting);
3369 m_isPainting = true;
3371 // m_nodeToDraw is used to draw only one element (and its descendants)
3372 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
3373 RenderLayer* rootLayer = renderView->layer();
3376 RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(rootLayer->renderer());
3379 rootLayer->paint(p, rect, m_paintBehavior, eltRenderer);
3381 if (rootLayer->containsDirtyOverlayScrollbars())
3382 rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer);
3384 m_isPainting = false;
3386 if (flatteningPaint && isRootFrame)
3387 notifyWidgetsInAllFrames(DidPaintFlattened);
3389 m_paintBehavior = oldPaintBehavior;
3390 m_lastPaintTime = currentTime();
3392 // Regions may have changed as a result of the visibility/z-index of element changing.
3393 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
3394 if (document->annotatedRegionsDirty())
3395 updateAnnotatedRegions();
3398 if (isTopLevelPainter)
3399 sCurrentPaintTimeStamp = 0;
3401 InspectorInstrumentation::didPaint(cookie, p, rect);
3404 void FrameView::setPaintBehavior(PaintBehavior behavior)
3406 m_paintBehavior = behavior;
3409 PaintBehavior FrameView::paintBehavior() const
3411 return m_paintBehavior;
3414 bool FrameView::isPainting() const
3416 return m_isPainting;
3419 void FrameView::setNodeToDraw(Node* node)
3421 m_nodeToDraw = node;
3424 void FrameView::paintContentsForSnapshot(GraphicsContext* context, const IntRect& imageRect, SelectionInSnaphot shouldPaintSelection, CoordinateSpaceForSnapshot coordinateSpace)
3426 updateLayoutAndStyleIfNeededRecursive();
3428 // Cache paint behavior and set a new behavior appropriate for snapshots.
3429 PaintBehavior oldBehavior = paintBehavior();
3430 setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
3432 // If the snapshot should exclude selection, then we'll clear the current selection
3433 // in the render tree only. This will allow us to restore the selection from the DOM
3434 // after we paint the snapshot.
3435 if (shouldPaintSelection == ExcludeSelection) {
3436 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
3437 if (RenderView* root = frame->contentRenderer())
3438 root->clearSelection();
3442 if (coordinateSpace == DocumentCoordinates)
3443 paintContents(context, imageRect);
3445 // A snapshot in ViewCoordinates will include a scrollbar, and the snapshot will contain
3446 // whatever content the document is currently scrolled to.
3447 paint(context, imageRect);
3450 // Restore selection.
3451 if (shouldPaintSelection == ExcludeSelection) {
3452 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get()))
3453 frame->selection()->updateAppearance();
3456 // Restore cached paint behavior.
3457 setPaintBehavior(oldBehavior);
3460 void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
3462 if (context->paintingDisabled())
3465 if (m_frame->document()->printing())
3468 Page* page = m_frame->page();
3469 if (page->mainFrame() == m_frame) {
3470 if (page->chrome()->client()->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
3474 ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
3477 void FrameView::updateLayoutAndStyleIfNeededRecursive()
3479 // We have to crawl our entire tree looking for any FrameViews that need
3480 // layout and make sure they are up to date.
3481 // Mac actually tests for intersection with the dirty region and tries not to
3482 // update layout for frames that are outside the dirty region. Not only does this seem
3483 // pointless (since those frames will have set a zero timer to layout anyway), but
3484 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
3485 // region but then become included later by the second frame adding rects to the dirty region
3486 // when it lays out.
3488 m_frame->document()->updateStyleIfNeeded();
3493 // Grab a copy of the children() set, as it may be mutated by the following updateLayoutAndStyleIfNeededRecursive
3494 // calls, as they can potentially re-enter a layout of the parent frame view, which may add/remove scrollbars
3495 // and thus mutates the children() set.
3496 Vector<RefPtr<FrameView> > frameViews;
3497 collectFrameViewChildren(this, frameViews);
3499 const Vector<RefPtr<FrameView> >::iterator end = frameViews.end();
3500 for (Vector<RefPtr<FrameView> >::iterator it = frameViews.begin(); it != end; ++it)
3501 (*it)->updateLayoutAndStyleIfNeededRecursive();
3503 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
3504 // painting, so we need to flush out any deferred repaints too.
3505 flushDeferredRepaints();
3507 // When frame flattening is on, child frame can mark parent frame dirty. In such case, child frame
3508 // needs to call layout on parent frame recursively.
3509 // This assert ensures that parent frames are clean, when child frames finished updating layout and style.
3510 ASSERT(!needsLayout());
3513 void FrameView::enableAutoSizeMode(bool enable, const IntSize& minSize, const IntSize& maxSize)
3515 ASSERT(!enable || !minSize.isEmpty());
3516 ASSERT(minSize.width() <= maxSize.width());
3517 ASSERT(minSize.height() <= maxSize.height());
3519 if (m_shouldAutoSize == enable && m_minAutoSize == minSize && m_maxAutoSize == maxSize)
3522 m_shouldAutoSize = enable;
3523 m_minAutoSize = minSize;
3524 m_maxAutoSize = maxSize;
3525 m_didRunAutosize = false;
3529 if (m_shouldAutoSize)
3532 // Since autosize mode forces the scrollbar mode, change them to being auto.
3533 setVerticalScrollbarLock(false);
3534 setHorizontalScrollbarLock(false);
3535 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
3538 void FrameView::forceLayout(bool allowSubtree)
3540 layout(allowSubtree);
3543 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor, AdjustViewSizeOrNot shouldAdjustViewSize)
3545 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
3546 // the state of things before and after the layout
3547 if (RenderView* renderView = this->renderView()) {
3548 float pageLogicalWidth = renderView->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
3549 float pageLogicalHeight = renderView->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
3551 LayoutUnit flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
3552 LayoutUnit flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
3553 renderView->setLogicalWidth(flooredPageLogicalWidth);
3554 renderView->setPageLogicalHeight(flooredPageLogicalHeight);
3555 renderView->setNeedsLayoutAndPrefWidthsRecalc();
3558 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
3559 // page width when shrunk, we will lay out at maximum shrink and clip extra content.
3560 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
3561 // implementation should not do this!
3562 bool horizontalWritingMode = renderView->style()->isHorizontalWritingMode();
3563 const LayoutRect& documentRect = renderView->documentRect();
3564 LayoutUnit docLogicalWidth = horizontalWritingMode ? documentRect.width() : documentRect.height();
3565 if (docLogicalWidth > pageLogicalWidth) {
3566 int expectedPageWidth = std::min<float>(documentRect.width(), pageSize.width() * maximumShrinkFactor);
3567 int expectedPageHeight = std::min<float>(documentRect.height(), pageSize.height() * maximumShrinkFactor);
3568 FloatSize maxPageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(originalPageSize.width(), originalPageSize.height()), FloatSize(expectedPageWidth, expectedPageHeight));
3569 pageLogicalWidth = horizontalWritingMode ? maxPageSize.width() : maxPageSize.height();
3570 pageLogicalHeight = horizontalWritingMode ? maxPageSize.height() : maxPageSize.width();
3572 flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
3573 flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
3574 renderView->setLogicalWidth(flooredPageLogicalWidth);
3575 renderView->setPageLogicalHeight(flooredPageLogicalHeight);
3576 renderView->setNeedsLayoutAndPrefWidthsRecalc();
3579 const LayoutRect& updatedDocumentRect = renderView->documentRect();
3580 LayoutUnit docLogicalHeight = horizontalWritingMode ? updatedDocumentRect.height() : updatedDocumentRect.width();
3581 LayoutUnit docLogicalTop = horizontalWritingMode ? updatedDocumentRect.y() : updatedDocumentRect.x();
3582 LayoutUnit docLogicalRight = horizontalWritingMode ? updatedDocumentRect.maxX() : updatedDocumentRect.maxY();
3583 LayoutUnit clippedLogicalLeft = 0;
3584 if (!renderView->style()->isLeftToRightDirection())
3585 clippedLogicalLeft = docLogicalRight - pageLogicalWidth;