2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 * 1999 Lars Knoll <knoll@kde.org>
4 * 1999 Antti Koivisto <koivisto@kde.org>
5 * 2000 Dirk Mueller <mueller@kde.org>
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
7 * (C) 2006 Graham Dennis (graham.dennis@gmail.com)
8 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
9 * Copyright (C) 2009 Google Inc. All rights reserved.
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details.
21 * You should have received a copy of the GNU Library General Public License
22 * along with this library; see the file COPYING.LIB. If not, write to
23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 * Boston, MA 02110-1301, USA.
28 #include "FrameView.h"
30 #include "AXObjectCache.h"
31 #include "BackForwardController.h"
32 #include "CachedImage.h"
33 #include "CachedResourceLoader.h"
35 #include "ChromeClient.h"
36 #include "DocumentMarkerController.h"
37 #include "EventHandler.h"
38 #include "FloatRect.h"
39 #include "FocusController.h"
40 #include "FontCache.h"
41 #include "FontLoader.h"
43 #include "FrameActionScheduler.h"
44 #include "FrameLoader.h"
45 #include "FrameLoaderClient.h"
46 #include "FrameTree.h"
47 #include "GraphicsContext.h"
48 #include "HTMLDocument.h"
49 #include "HTMLFrameElement.h"
50 #include "HTMLFrameSetElement.h"
51 #include "HTMLNames.h"
52 #include "HTMLPlugInImageElement.h"
53 #include "InspectorClient.h"
54 #include "InspectorController.h"
55 #include "InspectorInstrumentation.h"
56 #include "OverflowEvent.h"
57 #include "RenderArena.h"
58 #include "RenderEmbeddedObject.h"
59 #include "RenderFullScreen.h"
60 #include "RenderIFrame.h"
61 #include "RenderLayer.h"
62 #include "RenderLayerBacking.h"
63 #include "RenderPart.h"
64 #include "RenderScrollbar.h"
65 #include "RenderScrollbarPart.h"
66 #include "RenderTheme.h"
67 #include "RenderView.h"
68 #include "ScrollAnimator.h"
69 #include "ScrollingCoordinator.h"
71 #include "StyleResolver.h"
72 #include "TextResourceDecoder.h"
73 #include "TextStream.h"
75 #include <wtf/CurrentTime.h>
76 #include <wtf/TemporaryChange.h>
77 #include <wtf/UnusedParam.h>
79 #if USE(ACCELERATED_COMPOSITING)
80 #include "RenderLayerCompositor.h"
81 #include "TiledBacking.h"
85 #include "RenderSVGRoot.h"
86 #include "SVGDocument.h"
87 #include "SVGSVGElement.h"
90 #if USE(TILED_BACKING_STORE)
91 #include "TiledBackingStore.h"
94 #if ENABLE(TEXT_AUTOSIZING)
95 #include "TextAutosizer.h"
100 using namespace HTMLNames;
102 double FrameView::sCurrentPaintTimeStamp = 0.0;
105 // REPAINT_THROTTLING now chooses default values for throttling parameters.
106 // Should be removed when applications start using runtime configuration.
107 #if ENABLE(REPAINT_THROTTLING)
109 double FrameView::s_normalDeferredRepaintDelay = 0.016;
110 // Negative value would mean that first few repaints happen without a delay
111 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
112 // The delay grows on each repaint to this maximum value
113 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
114 // On each repaint the delay increses by this amount
115 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
117 // FIXME: Repaint throttling could be good to have on all platform.
118 // The balance between CPU use and repaint frequency will need some tuning for desktop.
119 // More hooks may be needed to reset the delay on things like GIF and CSS animations.
120 double FrameView::s_normalDeferredRepaintDelay = 0;
121 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
122 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
123 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
126 // While the browser window is being resized, resize events will be dispatched at most this often.
127 static const double minimumIntervalBetweenResizeEventsDuringLiveResizeInSeconds = 0.2;
129 // The maximum number of updateWidgets iterations that should be done before returning.
130 static const unsigned maxUpdateWidgetsIterations = 2;
132 static RenderLayer::UpdateLayerPositionsFlags updateLayerPositionFlags(RenderLayer* layer, bool isRelayoutingSubtree, bool didFullRepaint)
134 RenderLayer::UpdateLayerPositionsFlags flags = RenderLayer::defaultFlags;
135 if (didFullRepaint) {
136 flags &= ~RenderLayer::CheckForRepaint;
137 flags |= RenderLayer::NeedsFullRepaintInBacking;
139 if (isRelayoutingSubtree && layer->isPaginated())
140 flags |= RenderLayer::UpdatePagination;
144 Pagination::Mode paginationModeForRenderStyle(RenderStyle* style)
146 EOverflow overflow = style->overflowY();
147 if (overflow != OPAGEDX && overflow != OPAGEDY)
148 return Pagination::Unpaginated;
150 bool isHorizontalWritingMode = style->isHorizontalWritingMode();
151 TextDirection textDirection = style->direction();
152 WritingMode writingMode = style->writingMode();
154 // paged-x always corresponds to LeftToRightPaginated or RightToLeftPaginated. If the WritingMode
155 // is horizontal, then we use TextDirection to choose between those options. If the WritingMode
156 // is vertical, then the direction of the verticality dictates the choice.
157 if (overflow == OPAGEDX) {
158 if ((isHorizontalWritingMode && textDirection == LTR) || writingMode == LeftToRightWritingMode)
159 return Pagination::LeftToRightPaginated;
160 return Pagination::RightToLeftPaginated;
163 // paged-y always corresponds to TopToBottomPaginated or BottomToTopPaginated. If the WritingMode
164 // is horizontal, then the direction of the horizontality dictates the choice. If the WritingMode
165 // is vertical, then we use TextDirection to choose between those options.
166 if (writingMode == TopToBottomWritingMode || (!isHorizontalWritingMode && textDirection == RTL))
167 return Pagination::TopToBottomPaginated;
168 return Pagination::BottomToTopPaginated;
171 FrameView::FrameView(Frame* frame)
173 , m_canHaveScrollbars(true)
174 , m_slowRepaintObjectCount(0)
175 , m_delayedResizeEventTimer(this, &FrameView::delayedResizeEventTimerFired)
176 , m_layoutTimer(this, &FrameView::layoutTimerFired)
178 , m_inSynchronousPostLayout(false)
179 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
180 , m_isTransparent(false)
181 , m_baseBackgroundColor(Color::white)
182 , m_mediaType("screen")
183 , m_actionScheduler(adoptPtr(new FrameActionScheduler))
184 , m_overflowStatusDirty(true)
185 , m_viewportRenderer(0)
186 , m_wasScrolledByUser(false)
187 , m_inProgrammaticScroll(false)
188 , m_safeToPropagateScrollToParent(true)
189 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
190 , m_disableRepaints(0)
191 , m_isTrackingRepaints(false)
192 , m_shouldUpdateWhileOffscreen(true)
193 , m_deferSetNeedsLayouts(0)
194 , m_setNeedsLayoutWasDeferred(false)
196 , m_shouldAutoSize(false)
197 , m_inAutoSize(false)
198 , m_didRunAutosize(false)
201 #if ENABLE(CSS_FILTERS)
202 , m_hasSoftwareFilters(false)
207 // FIXME: Can m_frame ever be null here?
211 Page* page = m_frame->page();
215 if (m_frame == page->mainFrame()) {
216 ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed);
217 ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed);
221 PassRefPtr<FrameView> FrameView::create(Frame* frame)
223 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
225 return view.release();
228 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize)
230 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
231 view->Widget::setFrameRect(IntRect(view->location(), initialSize));
233 return view.release();
236 FrameView::~FrameView()
238 if (m_postLayoutTasksTimer.isActive()) {
239 m_postLayoutTasksTimer.stop();
240 m_actionScheduler->clear();
243 removeFromAXObjectCache();
246 // Custom scrollbars should already be destroyed at this point
247 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
248 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
250 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
251 setHasVerticalScrollbar(false);
253 ASSERT(!m_scrollCorner);
254 ASSERT(m_actionScheduler->isEmpty());
257 ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
258 RenderPart* renderer = m_frame->ownerRenderer();
259 if (renderer && renderer->widget() == this)
260 renderer->setWidget(0);
264 void FrameView::reset()
266 m_cannotBlitToWindow = false;
267 m_isOverlapped = false;
268 m_contentIsOpaque = false;
271 m_layoutTimer.stop();
273 m_delayedLayout = false;
274 m_doFullRepaint = true;
275 m_layoutSchedulingEnabled = true;
277 m_doingPreLayoutStyleUpdate = false;
278 m_inSynchronousPostLayout = false;
280 m_nestedLayoutCount = 0;
281 m_postLayoutTasksTimer.stop();
282 m_firstLayout = true;
283 m_firstLayoutCallbackPending = false;
284 m_wasScrolledByUser = false;
285 m_safeToPropagateScrollToParent = true;
286 m_lastViewportSize = IntSize();
287 m_lastZoomFactor = 1.0f;
288 m_deferringRepaints = 0;
290 m_repaintRects.clear();
291 m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading;
292 m_deferredRepaintTimer.stop();
293 m_isTrackingRepaints = false;
294 m_trackedRepaintRects.clear();
296 m_paintBehavior = PaintBehaviorNormal;
297 m_isPainting = false;
298 m_visuallyNonEmptyCharacterCount = 0;
299 m_visuallyNonEmptyPixelCount = 0;
300 m_isVisuallyNonEmpty = false;
301 m_firstVisuallyNonEmptyLayoutCallbackPending = true;
302 m_maintainScrollPositionAnchor = 0;
303 m_disableRepaints = 0;
306 void FrameView::removeFromAXObjectCache()
308 if (AXObjectCache* cache = axObjectCache())
312 void FrameView::clearFrame()
317 void FrameView::resetScrollbars()
319 // Reset the document's scrollbars back to our defaults before we yield the floor.
320 m_firstLayout = true;
321 setScrollbarsSuppressed(true);
322 if (m_canHaveScrollbars)
323 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
325 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
326 setScrollbarsSuppressed(false);
329 void FrameView::resetScrollbarsAndClearContentsSize()
333 setScrollbarsSuppressed(true);
334 setContentsSize(IntSize());
335 setScrollbarsSuppressed(false);
338 void FrameView::init()
342 m_margins = LayoutSize(-1, -1); // undefined
343 m_size = LayoutSize();
345 // Propagate the marginwidth/height and scrolling modes to the view.
346 Element* ownerElement = m_frame ? m_frame->ownerElement() : 0;
347 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
348 HTMLFrameElementBase* frameElt = static_cast<HTMLFrameElementBase*>(ownerElement);
349 if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
350 setCanHaveScrollbars(false);
351 LayoutUnit marginWidth = frameElt->marginWidth();
352 LayoutUnit marginHeight = frameElt->marginHeight();
353 if (marginWidth != -1)
354 setMarginWidth(marginWidth);
355 if (marginHeight != -1)
356 setMarginHeight(marginHeight);
360 void FrameView::prepareForDetach()
362 detachCustomScrollbars();
363 // When the view is no longer associated with a frame, it needs to be removed from the ax object cache
364 // right now, otherwise it won't be able to reach the topDocument()'s axObject cache later.
365 removeFromAXObjectCache();
367 if (m_frame && m_frame->page()) {
368 if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator())
369 scrollingCoordinator->willDestroyScrollableArea(this);
373 void FrameView::detachCustomScrollbars()
375 Scrollbar* horizontalBar = horizontalScrollbar();
376 if (horizontalBar && horizontalBar->isCustomScrollbar())
377 setHasHorizontalScrollbar(false);
379 Scrollbar* verticalBar = verticalScrollbar();
380 if (verticalBar && verticalBar->isCustomScrollbar())
381 setHasVerticalScrollbar(false);
383 if (m_scrollCorner) {
384 m_scrollCorner->destroy();
389 void FrameView::recalculateScrollbarOverlayStyle()
391 ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle();
392 ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault;
394 Color backgroundColor = documentBackgroundColor();
395 if (backgroundColor.isValid()) {
396 // Reduce the background color from RGB to a lightness value
397 // and determine which scrollbar style to use based on a lightness
399 double hue, saturation, lightness;
400 backgroundColor.getHSL(hue, saturation, lightness);
402 overlayStyle = ScrollbarOverlayStyleLight;
405 if (oldOverlayStyle != overlayStyle)
406 setScrollbarOverlayStyle(overlayStyle);
409 void FrameView::clear()
411 setCanBlitOnScroll(true);
416 if (RenderPart* renderer = m_frame->ownerRenderer())
417 renderer->viewCleared();
420 setScrollbarsSuppressed(true);
423 bool FrameView::didFirstLayout() const
425 return !m_firstLayout;
428 void FrameView::invalidateRect(const IntRect& rect)
432 hostWindow()->invalidateContentsAndRootView(rect, false /*immediate*/);
439 RenderPart* renderer = m_frame->ownerRenderer();
443 IntRect repaintRect = rect;
444 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
445 renderer->borderTop() + renderer->paddingTop());
446 renderer->repaintRectangle(repaintRect);
449 void FrameView::setFrameRect(const IntRect& newRect)
451 IntRect oldRect = frameRect();
452 if (newRect == oldRect)
455 #if ENABLE(TEXT_AUTOSIZING)
456 // Autosized font sizes depend on the width of the viewing area.
457 if (newRect.width() != oldRect.width()) {
458 Page* page = m_frame ? m_frame->page() : 0;
459 if (page && page->mainFrame() == m_frame && page->settings()->textAutosizingEnabled()) {
460 for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())
461 m_frame->document()->textAutosizer()->recalculateMultipliers();
466 ScrollView::setFrameRect(newRect);
468 updateScrollableAreaSet();
470 #if USE(ACCELERATED_COMPOSITING)
471 if (RenderView* renderView = this->renderView()) {
472 if (renderView->usesCompositing())
473 renderView->compositor()->frameViewDidChangeSize();
478 #if ENABLE(REQUEST_ANIMATION_FRAME)
479 bool FrameView::scheduleAnimation()
482 hostWindow()->scheduleAnimation();
489 void FrameView::setMarginWidth(LayoutUnit w)
491 // make it update the rendering area when set
492 m_margins.setWidth(w);
495 void FrameView::setMarginHeight(LayoutUnit h)
497 // make it update the rendering area when set
498 m_margins.setHeight(h);
501 bool FrameView::avoidScrollbarCreation() const
505 // with frame flattening no subframe can have scrollbars
506 // but we also cannot turn scrollbars off as we determine
507 // our flattening policy using that.
509 if (!m_frame->ownerElement())
512 if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
518 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
520 m_canHaveScrollbars = canHaveScrollbars;
521 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
524 void FrameView::updateCanHaveScrollbars()
528 scrollbarModes(hMode, vMode);
529 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
530 setCanHaveScrollbars(false);
532 setCanHaveScrollbars(true);
535 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
537 if (Settings* settings = m_frame->settings()) {
538 if (!settings->allowCustomScrollbarInMainFrame() && m_frame->page() && m_frame->page()->mainFrame() == m_frame)
539 return ScrollView::createScrollbar(orientation);
542 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
543 Document* doc = m_frame->document();
545 // Try the <body> element first as a scrollbar source.
546 Element* body = doc ? doc->body() : 0;
547 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
548 return RenderScrollbar::createCustomScrollbar(this, orientation, body);
550 // If the <body> didn't have a custom style, then the root element might.
551 Element* docElement = doc ? doc->documentElement() : 0;
552 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
553 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement);
555 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
556 RenderPart* frameRenderer = m_frame->ownerRenderer();
557 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
558 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
560 // Nobody set a custom style, so we just use a native scrollbar.
561 return ScrollView::createScrollbar(orientation);
564 void FrameView::setContentsSize(const IntSize& size)
566 if (size == contentsSize())
569 m_deferSetNeedsLayouts++;
571 ScrollView::setContentsSize(size);
572 ScrollView::contentsResized();
574 Page* page = frame() ? frame()->page() : 0;
578 updateScrollableAreaSet();
580 page->chrome()->contentsSizeChanged(frame(), size); //notify only
582 m_deferSetNeedsLayouts--;
584 if (!m_deferSetNeedsLayouts)
585 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
588 void FrameView::adjustViewSize()
590 RenderView* renderView = this->renderView();
594 ASSERT(m_frame->view() == this);
596 const IntRect rect = renderView->documentRect();
597 const IntSize& size = rect.size();
598 ScrollView::setScrollOrigin(IntPoint(-rect.x(), -rect.y()), !m_frame->document()->printing(), size == contentsSize());
600 setContentsSize(size);
603 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
605 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
606 // overflow:hidden and overflow:scroll on <body> as applying to the document's
607 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
608 // use the root element.
610 // To combat the inability to scroll on a page with overflow:hidden on the root when scaled, disregard hidden when
611 // there is a frameScaleFactor that is greater than one on the main frame. Also disregard hidden if there is a
614 bool overrideHidden = (m_frame->page() && m_frame->page()->mainFrame() == m_frame && m_frame->frameScaleFactor() > 1)
615 || (m_frame->page() && m_frame->page()->mainFrame() == m_frame && (headerHeight() || footerHeight()));
617 EOverflow overflowX = o->style()->overflowX();
618 EOverflow overflowY = o->style()->overflowY();
621 if (o->isSVGRoot()) {
622 // overflow is ignored in stand-alone SVG documents.
623 if (!toRenderSVGRoot(o)->isEmbeddedThroughFrameContainingSVGDocument())
633 hMode = ScrollbarAuto;
635 hMode = ScrollbarAlwaysOff;
638 hMode = ScrollbarAlwaysOn;
641 hMode = ScrollbarAuto;
644 // Don't set it at all.
651 vMode = ScrollbarAuto;
653 vMode = ScrollbarAlwaysOff;
656 vMode = ScrollbarAlwaysOn;
659 vMode = ScrollbarAuto;
662 // Don't set it at all. Values of OPAGEDX and OPAGEDY are handled by applyPaginationToViewPort().
666 m_viewportRenderer = o;
669 void FrameView::applyPaginationToViewport()
671 Document* document = m_frame->document();
672 Node* documentElement = document->documentElement();
673 RenderObject* documentRenderer = documentElement ? documentElement->renderer() : 0;
674 RenderObject* documentOrBodyRenderer = documentRenderer;
675 Node* body = document->body();
676 if (body && body->renderer()) {
677 if (body->hasTagName(bodyTag))
678 documentOrBodyRenderer = documentRenderer->style()->overflowX() == OVISIBLE && documentElement->hasTagName(htmlTag) ? body->renderer() : documentRenderer;
681 Pagination pagination;
683 if (!documentOrBodyRenderer) {
684 setPagination(pagination);
688 EOverflow overflowY = documentOrBodyRenderer->style()->overflowY();
689 if (overflowY == OPAGEDX || overflowY == OPAGEDY) {
690 pagination.mode = WebCore::paginationModeForRenderStyle(documentOrBodyRenderer->style());
691 pagination.gap = static_cast<unsigned>(documentOrBodyRenderer->style()->columnGap());
694 setPagination(pagination);
697 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy)
699 m_viewportRenderer = 0;
701 const HTMLFrameOwnerElement* owner = m_frame->ownerElement();
702 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
703 hMode = ScrollbarAlwaysOff;
704 vMode = ScrollbarAlwaysOff;
708 if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) {
709 hMode = ScrollbarAuto;
710 // Seamless documents begin with heights of 0; we special case that here
711 // to correctly render documents that don't need scrollbars.
712 IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size();
713 bool isSeamlessDocument = frame() && frame()->document() && frame()->document()->shouldDisplaySeamlesslyWithParent();
714 vMode = (isSeamlessDocument && !fullVisibleSize.height()) ? ScrollbarAlwaysOff : ScrollbarAuto;
716 hMode = ScrollbarAlwaysOff;
717 vMode = ScrollbarAlwaysOff;
721 Document* document = m_frame->document();
722 Node* documentElement = document->documentElement();
723 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
724 Node* body = document->body();
725 if (body && body->renderer()) {
726 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
727 vMode = ScrollbarAlwaysOff;
728 hMode = ScrollbarAlwaysOff;
729 } else if (body->hasTagName(bodyTag)) {
730 // It's sufficient to just check the X overflow,
731 // since it's illegal to have visible in only one direction.
732 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
733 applyOverflowToViewport(o, hMode, vMode);
735 } else if (rootRenderer)
736 applyOverflowToViewport(rootRenderer, hMode, vMode);
740 #if USE(ACCELERATED_COMPOSITING)
741 void FrameView::updateCompositingLayersAfterStyleChange()
743 RenderView* renderView = this->renderView();
747 // If we expect to update compositing after an incipient layout, don't do so here.
748 if (m_doingPreLayoutStyleUpdate || layoutPending() || renderView->needsLayout())
751 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
752 renderView->compositor()->cacheAcceleratedCompositingFlags();
753 renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterStyleChange);
756 void FrameView::updateCompositingLayersAfterLayout()
758 RenderView* renderView = this->renderView();
762 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
763 renderView->compositor()->cacheAcceleratedCompositingFlags();
764 renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterLayout);
767 void FrameView::clearBackingStores()
769 RenderView* renderView = this->renderView();
773 RenderLayerCompositor* compositor = renderView->compositor();
774 ASSERT(compositor->inCompositingMode());
775 compositor->enableCompositingMode(false);
776 compositor->clearBackingForAllLayers();
779 void FrameView::restoreBackingStores()
781 RenderView* renderView = this->renderView();
785 RenderLayerCompositor* compositor = renderView->compositor();
786 compositor->enableCompositingMode(true);
787 compositor->updateCompositingLayers(CompositingUpdateAfterLayout);
790 bool FrameView::usesCompositedScrolling() const
792 RenderView* renderView = this->renderView();
795 if (m_frame->settings() && m_frame->settings()->compositedScrollingForFramesEnabled())
796 return renderView->compositor()->inForcedCompositingMode();
800 GraphicsLayer* FrameView::layerForScrolling() const
802 RenderView* renderView = this->renderView();
805 return renderView->compositor()->scrollLayer();
808 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
810 RenderView* renderView = this->renderView();
813 return renderView->compositor()->layerForHorizontalScrollbar();
816 GraphicsLayer* FrameView::layerForVerticalScrollbar() const
818 RenderView* renderView = this->renderView();
821 return renderView->compositor()->layerForVerticalScrollbar();
824 GraphicsLayer* FrameView::layerForScrollCorner() const
826 RenderView* renderView = this->renderView();
829 return renderView->compositor()->layerForScrollCorner();
832 TiledBacking* FrameView::tiledBacking()
834 RenderView* renderView = this->renderView();
838 RenderLayerBacking* backing = renderView->layer()->backing();
842 return backing->graphicsLayer()->tiledBacking();
845 uint64_t FrameView::scrollLayerID() const
847 RenderView* renderView = this->renderView();
851 RenderLayerBacking* backing = renderView->layer()->backing();
855 return backing->scrollLayerID();
858 #if ENABLE(RUBBER_BANDING)
859 GraphicsLayer* FrameView::layerForOverhangAreas() const
861 RenderView* renderView = this->renderView();
864 return renderView->compositor()->layerForOverhangAreas();
867 GraphicsLayer* FrameView::setWantsLayerForTopOverHangArea(bool wantsLayer) const
869 RenderView* renderView = this->renderView();
873 return renderView->compositor()->updateLayerForTopOverhangArea(wantsLayer);
876 GraphicsLayer* FrameView::setWantsLayerForBottomOverHangArea(bool wantsLayer) const
878 RenderView* renderView = this->renderView();
882 return renderView->compositor()->updateLayerForBottomOverhangArea(wantsLayer);
885 GraphicsLayer* FrameView::setWantsLayerForHeader(bool wantsLayer) const
887 RenderView* renderView = this->renderView();
891 ASSERT(m_frame == m_frame->page()->mainFrame());
893 return renderView->compositor()->updateLayerForHeader(wantsLayer);
896 GraphicsLayer* FrameView::setWantsLayerForFooter(bool wantsLayer) const
898 RenderView* renderView = this->renderView();
902 ASSERT(m_frame == m_frame->page()->mainFrame());
904 return renderView->compositor()->updateLayerForFooter(wantsLayer);
907 #endif // ENABLE(RUBBER_BANDING)
909 bool FrameView::flushCompositingStateForThisFrame(Frame* rootFrameForFlush)
911 RenderView* renderView = this->renderView();
913 return true; // We don't want to keep trying to update layers if we have no renderer.
915 ASSERT(m_frame->view() == this);
917 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
918 // layer content to occur before layout has happened, which will cause paintContents() to bail.
922 // If we sync compositing layers and allow the repaint to be deferred, there is time for a
923 // visible flash to occur. Instead, stop the deferred repaint timer and repaint immediately.
924 flushDeferredRepaints();
926 renderView->compositor()->flushPendingLayerChanges(rootFrameForFlush == m_frame);
931 void FrameView::setNeedsOneShotDrawingSynchronization()
933 Page* page = frame() ? frame()->page() : 0;
935 page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
938 #endif // USE(ACCELERATED_COMPOSITING)
940 void FrameView::setHeaderHeight(int headerHeight)
942 if (m_frame && m_frame->page())
943 ASSERT(m_frame == m_frame->page()->mainFrame());
944 m_headerHeight = headerHeight;
946 if (RenderView* renderView = this->renderView())
947 renderView->setNeedsLayout(true);
950 void FrameView::setFooterHeight(int footerHeight)
952 if (m_frame && m_frame->page())
953 ASSERT(m_frame == m_frame->page()->mainFrame());
954 m_footerHeight = footerHeight;
956 if (RenderView* renderView = this->renderView())
957 renderView->setNeedsLayout(true);
960 bool FrameView::hasCompositedContent() const
962 #if USE(ACCELERATED_COMPOSITING)
963 if (RenderView* renderView = this->renderView())
964 return renderView->compositor()->inCompositingMode();
969 bool FrameView::hasCompositedContentIncludingDescendants() const
971 #if USE(ACCELERATED_COMPOSITING)
972 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
973 RenderView* renderView = frame->contentRenderer();
974 RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0;
976 if (compositor->inCompositingMode())
979 if (!RenderLayerCompositor::allowsIndependentlyCompositedFrames(this))
987 bool FrameView::hasCompositingAncestor() const
989 #if USE(ACCELERATED_COMPOSITING)
990 for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) {
991 if (FrameView* view = frame->view()) {
992 if (view->hasCompositedContent())
1000 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
1001 void FrameView::enterCompositingMode()
1003 #if USE(ACCELERATED_COMPOSITING)
1004 if (RenderView* renderView = this->renderView()) {
1005 renderView->compositor()->enableCompositingMode();
1007 renderView->compositor()->scheduleCompositingLayerUpdate();
1012 bool FrameView::isEnclosedInCompositingLayer() const
1014 #if USE(ACCELERATED_COMPOSITING)
1015 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
1016 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
1019 if (FrameView* parentView = parentFrameView())
1020 return parentView->isEnclosedInCompositingLayer();
1025 bool FrameView::flushCompositingStateIncludingSubframes()
1027 #if USE(ACCELERATED_COMPOSITING)
1028 bool allFramesFlushed = flushCompositingStateForThisFrame(m_frame.get());
1030 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame.get())) {
1031 bool flushed = child->view()->flushCompositingStateForThisFrame(m_frame.get());
1032 allFramesFlushed &= flushed;
1034 return allFramesFlushed;
1035 #else // USE(ACCELERATED_COMPOSITING)
1040 bool FrameView::isSoftwareRenderable() const
1042 #if USE(ACCELERATED_COMPOSITING)
1043 RenderView* renderView = this->renderView();
1044 return !renderView || !renderView->compositor()->has3DContent();
1050 void FrameView::didMoveOnscreen()
1052 contentAreaDidShow();
1055 void FrameView::willMoveOffscreen()
1057 contentAreaDidHide();
1060 void FrameView::setIsInWindow(bool isInWindow)
1062 if (RenderView* renderView = this->renderView())
1063 renderView->setIsInWindow(isInWindow);
1066 // Drawing models which cache painted content while out-of-window (WebKit2's composited drawing areas, etc.)
1067 // require that we repaint animated images to kickstart the animation loop.
1069 CachedImage::resumeAnimatingImagesForLoader(frame()->document()->cachedResourceLoader());
1073 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
1075 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
1078 static inline void collectFrameViewChildren(FrameView* frameView, Vector<RefPtr<FrameView> >& frameViews)
1080 const HashSet<RefPtr<Widget> >* viewChildren = frameView->children();
1081 ASSERT(viewChildren);
1083 const HashSet<RefPtr<Widget> >::iterator end = viewChildren->end();
1084 for (HashSet<RefPtr<Widget> >::iterator current = viewChildren->begin(); current != end; ++current) {
1085 Widget* widget = (*current).get();
1086 if (widget->isFrameView())
1087 frameViews.append(toFrameView(widget));
1091 inline void FrameView::forceLayoutParentViewIfNeeded()
1094 RenderPart* ownerRenderer = m_frame->ownerRenderer();
1095 if (!ownerRenderer || !ownerRenderer->frame())
1098 RenderBox* contentBox = embeddedContentBox();
1102 RenderSVGRoot* svgRoot = toRenderSVGRoot(contentBox);
1103 if (svgRoot->everHadLayout() && !svgRoot->needsLayout())
1106 // If the embedded SVG document appears the first time, the ownerRenderer has already finished
1107 // layout without knowing about the existence of the embedded SVG document, because RenderReplaced
1108 // embeddedContentBox() returns 0, as long as the embedded document isn't loaded yet. Before
1109 // bothering to lay out the SVG document, mark the ownerRenderer needing layout and ask its
1110 // FrameView for a layout. After that the RenderEmbeddedObject (ownerRenderer) carries the
1111 // correct size, which RenderSVGRoot::computeReplacedLogicalWidth/Height rely on, when laying
1112 // out for the first time, or when the RenderSVGRoot size has changed dynamically (eg. via <script>).
1113 RefPtr<FrameView> frameView = ownerRenderer->frame()->view();
1115 // Mark the owner renderer as needing layout.
1116 ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc();
1118 // Synchronously enter layout, to layout the view containing the host object/embed/iframe.
1120 frameView->layout();
1124 void FrameView::layout(bool allowSubtree)
1129 // Protect the view from being deleted during layout (in recalcStyle)
1130 RefPtr<FrameView> protector(this);
1132 // Every scroll that happens during layout is programmatic.
1133 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1135 bool inChildFrameLayoutWithFrameFlattening = isInChildFrameWithFrameFlattening();
1137 if (inChildFrameLayoutWithFrameFlattening) {
1138 if (doLayoutWithFrameFlattening(allowSubtree))
1142 m_layoutTimer.stop();
1143 m_delayedLayout = false;
1144 m_setNeedsLayoutWasDeferred = false;
1147 // FIXME: Do we need to set m_size.width here?
1148 // FIXME: Should we set m_size.height here too?
1149 m_size.setWidth(layoutWidth());
1153 // we shouldn't enter layout() while painting
1154 ASSERT(!isPainting());
1158 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
1160 if (!allowSubtree && m_layoutRoot) {
1161 m_layoutRoot->markContainingBlocksForLayout(false);
1165 ASSERT(m_frame->view() == this);
1167 Document* document = m_frame->document();
1168 ASSERT(!document->inPageCache());
1173 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1175 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_postLayoutTasksTimer.isActive() && !inChildFrameLayoutWithFrameFlattening) {
1176 // This is a new top-level layout. If there are any remaining tasks from the previous
1177 // layout, finish them now.
1178 m_inSynchronousPostLayout = true;
1179 performPostLayoutTasks();
1180 m_inSynchronousPostLayout = false;
1183 // Viewport-dependent media queries may cause us to need completely different style information.
1185 if (document->styleResolver()->affectedByViewportChange()) {
1186 document->styleResolverChanged(RecalcStyleImmediately);
1187 InspectorInstrumentation::mediaQueryResultChanged(document);
1189 document->evaluateMediaQueryList();
1191 // If there is any pagination to apply, it will affect the RenderView's style, so we should
1192 // take care of that now.
1193 applyPaginationToViewport();
1195 // Always ensure our style info is up-to-date. This can happen in situations where
1196 // the layout beats any sort of style recalc update that needs to occur.
1197 TemporaryChange<bool> changeDoingPreLayoutStyleUpdate(m_doingPreLayoutStyleUpdate, true);
1198 document->updateStyleIfNeeded();
1200 subtree = m_layoutRoot;
1202 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
1203 // so there's no point to continuing to layout
1204 if (protector->hasOneRef())
1207 root = subtree ? m_layoutRoot : document->renderer();
1209 // FIXME: Do we need to set m_size here?
1212 } // Reset m_layoutSchedulingEnabled to its previous value.
1213 // The only reason the scoping was closed here is allow fontCachePurgePreventer
1214 // to outlive the change and reset of m_layoutSchedulingEnabled.
1216 FontCachePurgePreventer fontCachePurgePreventer;
1219 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1221 m_nestedLayoutCount++;
1223 if (!m_layoutRoot) {
1224 Document* document = m_frame->document();
1225 Node* body = document->body();
1226 if (body && body->renderer()) {
1227 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
1228 body->renderer()->setChildNeedsLayout(true);
1229 } else if (body->hasTagName(bodyTag)) {
1230 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
1231 body->renderer()->setChildNeedsLayout(true);
1235 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1236 if (m_firstLayout && !m_frame->ownerElement())
1237 printf("Elapsed time before first layout: %d\n", document->elapsedTime());
1241 autoSizeIfEnabled();
1243 ScrollbarMode hMode;
1244 ScrollbarMode vMode;
1245 calculateScrollbarModesForLayout(hMode, vMode);
1247 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
1250 // Now set our scrollbar state for the layout.
1251 ScrollbarMode currentHMode = horizontalScrollbarMode();
1252 ScrollbarMode currentVMode = verticalScrollbarMode();
1254 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
1255 if (m_firstLayout) {
1256 setScrollbarsSuppressed(true);
1258 m_firstLayout = false;
1259 m_firstLayoutCallbackPending = true;
1260 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
1261 m_lastViewportSize = fixedLayoutSize();
1263 m_lastViewportSize = visibleContentRect(IncludeScrollbars).size();
1264 m_lastZoomFactor = root->style()->zoom();
1266 // Set the initial vMode to AlwaysOn if we're auto.
1267 if (vMode == ScrollbarAuto)
1268 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
1269 // Set the initial hMode to AlwaysOff if we're auto.
1270 if (hMode == ScrollbarAuto)
1271 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
1273 setScrollbarModes(hMode, vMode);
1274 setScrollbarsSuppressed(false, true);
1276 setScrollbarModes(hMode, vMode);
1279 LayoutSize oldSize = m_size;
1281 m_size = LayoutSize(layoutWidth(), layoutHeight());
1283 if (oldSize != m_size) {
1284 m_doFullRepaint = true;
1285 if (!m_firstLayout) {
1286 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
1287 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
1288 if (bodyRenderer && bodyRenderer->stretchesToViewport())
1289 bodyRenderer->setChildNeedsLayout(true);
1290 else if (rootRenderer && rootRenderer->stretchesToViewport())
1291 rootRenderer->setChildNeedsLayout(true);
1296 layer = root->enclosingLayer();
1298 m_actionScheduler->pause();
1301 bool disableLayoutState = false;
1303 RenderView* view = root->view();
1304 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
1305 view->pushLayoutState(root);
1307 LayoutStateDisabler layoutStateDisabler(disableLayoutState ? root->view() : 0);
1310 beginDeferredRepaints();
1311 forceLayoutParentViewIfNeeded();
1313 #if ENABLE(TEXT_AUTOSIZING)
1314 bool autosized = document->textAutosizer()->processSubtree(root);
1315 if (autosized && root->needsLayout())
1318 endDeferredRepaints();
1322 root->view()->popLayoutState(root);
1325 } // Reset m_layoutSchedulingEnabled to its previous value.
1327 bool neededFullRepaint = m_doFullRepaint;
1329 if (!subtree && !toRenderView(root)->printing())
1332 m_doFullRepaint = neededFullRepaint;
1334 // Now update the positions of all layers.
1335 beginDeferredRepaints();
1336 if (m_doFullRepaint)
1337 root->view()->repaint(); // FIXME: This isn't really right, since the RenderView doesn't fully encompass the visibleContentRect(). It just happens
1338 // to work out most of the time, since first layouts and printing don't have you scrolled anywhere.
1340 layer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPositionFlags(layer, subtree, m_doFullRepaint));
1342 endDeferredRepaints();
1344 #if USE(ACCELERATED_COMPOSITING)
1345 updateCompositingLayersAfterLayout();
1351 if (AXObjectCache* cache = root->document()->existingAXObjectCache())
1352 cache->postNotification(root, AXObjectCache::AXLayoutComplete, true);
1354 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
1355 updateAnnotatedRegions();
1358 ASSERT(!root->needsLayout());
1360 updateCanBlitOnScrollRecursively();
1362 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1363 updateOverflowStatus(layoutWidth() < contentsWidth(),
1364 layoutHeight() < contentsHeight());
1366 if (!m_postLayoutTasksTimer.isActive()) {
1367 if (!m_inSynchronousPostLayout) {
1368 if (inChildFrameLayoutWithFrameFlattening) {
1369 if (RenderView* renderView = this->renderView())
1370 renderView->updateWidgetPositions();
1372 m_inSynchronousPostLayout = true;
1373 // Calls resumeScheduledEvents()
1374 performPostLayoutTasks();
1375 m_inSynchronousPostLayout = false;
1379 if (!m_postLayoutTasksTimer.isActive() && (needsLayout() || m_inSynchronousPostLayout || inChildFrameLayoutWithFrameFlattening)) {
1380 // If we need layout or are already in a synchronous call to postLayoutTasks(),
1381 // defer widget updates and event dispatch until after we return. postLayoutTasks()
1382 // can make us need to update again, and we can get stuck in a nasty cycle unless
1383 // we call it through the timer here.
1384 m_postLayoutTasksTimer.startOneShot(0);
1385 if (needsLayout()) {
1386 m_actionScheduler->pause();
1391 m_actionScheduler->resume();
1394 InspectorInstrumentation::didLayout(cookie, root);
1396 m_nestedLayoutCount--;
1397 if (m_nestedLayoutCount)
1400 Page* page = frame() ? frame()->page() : 0;
1404 page->chrome()->client()->layoutUpdated(frame());
1407 RenderBox* FrameView::embeddedContentBox() const
1410 RenderView* renderView = this->renderView();
1414 RenderObject* firstChild = renderView->firstChild();
1415 if (!firstChild || !firstChild->isBox())
1418 // Curently only embedded SVG documents participate in the size-negotiation logic.
1419 if (firstChild->isSVGRoot())
1420 return toRenderBox(firstChild);
1426 void FrameView::addWidgetToUpdate(RenderObject* object)
1428 if (!m_widgetUpdateSet)
1429 m_widgetUpdateSet = adoptPtr(new RenderObjectSet);
1431 // Tell the DOM element that it needs a widget update.
1432 Node* node = object->node();
1433 if (node->hasTagName(objectTag) || node->hasTagName(embedTag)) {
1434 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(node);
1435 pluginElement->setNeedsWidgetUpdate(true);
1438 m_widgetUpdateSet->add(object);
1441 void FrameView::removeWidgetToUpdate(RenderObject* object)
1443 if (!m_widgetUpdateSet)
1446 m_widgetUpdateSet->remove(object);
1449 void FrameView::setMediaType(const String& mediaType)
1451 m_mediaType = mediaType;
1454 String FrameView::mediaType() const
1456 // See if we have an override type.
1457 String overrideType = m_frame->loader()->client()->overrideMediaType();
1458 InspectorInstrumentation::applyEmulatedMedia(m_frame.get(), &overrideType);
1459 if (!overrideType.isNull())
1460 return overrideType;
1464 void FrameView::adjustMediaTypeForPrinting(bool printing)
1467 if (m_mediaTypeWhenNotPrinting.isNull())
1468 m_mediaTypeWhenNotPrinting = mediaType();
1469 setMediaType("print");
1471 if (!m_mediaTypeWhenNotPrinting.isNull())
1472 setMediaType(m_mediaTypeWhenNotPrinting);
1473 m_mediaTypeWhenNotPrinting = String();
1477 bool FrameView::useSlowRepaints(bool considerOverlap) const
1479 bool mustBeSlow = m_slowRepaintObjectCount > 0 || (platformWidget() && hasViewportConstrainedObjects());
1481 // FIXME: WidgetMac.mm makes the assumption that useSlowRepaints ==
1482 // m_contentIsOpaque, so don't take the fast path for composited layers
1483 // if they are a platform widget in order to get painting correctness
1484 // for transparent layers. See the comment in WidgetMac::paint.
1485 if (contentsInCompositedLayer() && !platformWidget())
1488 bool isOverlapped = m_isOverlapped && considerOverlap;
1490 if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque)
1493 if (FrameView* parentView = parentFrameView())
1494 return parentView->useSlowRepaints(considerOverlap);
1499 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1501 return useSlowRepaints(false);
1504 void FrameView::updateCanBlitOnScrollRecursively()
1506 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1507 if (FrameView* view = frame->view())
1508 view->setCanBlitOnScroll(!view->useSlowRepaints());
1512 bool FrameView::contentsInCompositedLayer() const
1514 #if USE(ACCELERATED_COMPOSITING)
1515 RenderView* renderView = this->renderView();
1516 if (renderView && renderView->isComposited()) {
1517 GraphicsLayer* layer = renderView->layer()->backing()->graphicsLayer();
1518 if (layer && layer->drawsContent())
1525 void FrameView::setCannotBlitToWindow()
1527 m_cannotBlitToWindow = true;
1528 updateCanBlitOnScrollRecursively();
1531 void FrameView::addSlowRepaintObject()
1533 if (!m_slowRepaintObjectCount++) {
1534 updateCanBlitOnScrollRecursively();
1536 if (Page* page = m_frame->page()) {
1537 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1538 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1543 void FrameView::removeSlowRepaintObject()
1545 ASSERT(m_slowRepaintObjectCount > 0);
1546 m_slowRepaintObjectCount--;
1547 if (!m_slowRepaintObjectCount) {
1548 updateCanBlitOnScrollRecursively();
1550 if (Page* page = m_frame->page()) {
1551 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1552 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1557 void FrameView::addViewportConstrainedObject(RenderObject* object)
1559 if (!m_viewportConstrainedObjects)
1560 m_viewportConstrainedObjects = adoptPtr(new ViewportConstrainedObjectSet);
1562 if (!m_viewportConstrainedObjects->contains(object)) {
1563 m_viewportConstrainedObjects->add(object);
1564 if (platformWidget())
1565 updateCanBlitOnScrollRecursively();
1567 if (Page* page = m_frame->page()) {
1568 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1569 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1574 void FrameView::removeViewportConstrainedObject(RenderObject* object)
1576 if (m_viewportConstrainedObjects && m_viewportConstrainedObjects->contains(object)) {
1577 m_viewportConstrainedObjects->remove(object);
1578 if (Page* page = m_frame->page()) {
1579 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1580 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1583 // FIXME: In addFixedObject() we only call this if there's a platform widget,
1584 // why isn't the same check being made here?
1585 updateCanBlitOnScrollRecursively();
1589 LayoutRect FrameView::viewportConstrainedVisibleContentRect() const
1591 LayoutRect viewportRect = visibleContentRect();
1592 viewportRect.setLocation(toPoint(scrollOffsetForFixedPosition()));
1593 return viewportRect;
1596 IntSize FrameView::scrollOffsetForFixedPosition(const IntRect& visibleContentRect, const IntSize& totalContentsSize, const IntPoint& scrollPosition, const IntPoint& scrollOrigin, float frameScaleFactor, bool fixedElementsLayoutRelativeToFrame, int headerHeight, int footerHeight)
1598 IntPoint constrainedPosition = ScrollableArea::constrainScrollPositionForOverhang(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, headerHeight, footerHeight);
1600 IntSize maxSize = totalContentsSize - visibleContentRect.size();
1602 float dragFactorX = (fixedElementsLayoutRelativeToFrame || !maxSize.width()) ? 1 : (totalContentsSize.width() - visibleContentRect.width() * frameScaleFactor) / maxSize.width();
1603 float dragFactorY = (fixedElementsLayoutRelativeToFrame || !maxSize.height()) ? 1 : (totalContentsSize.height() - visibleContentRect.height() * frameScaleFactor) / maxSize.height();
1605 return IntSize(constrainedPosition.x() * dragFactorX / frameScaleFactor, constrainedPosition.y() * dragFactorY / frameScaleFactor);
1608 IntSize FrameView::scrollOffsetForFixedPosition() const
1610 IntRect visibleContentRect = this->visibleContentRect();
1611 IntSize totalContentsSize = this->totalContentsSize();
1612 IntPoint scrollPosition = this->scrollPosition();
1613 IntPoint scrollOrigin = this->scrollOrigin();
1614 float frameScaleFactor = m_frame ? m_frame->frameScaleFactor() : 1;
1615 return scrollOffsetForFixedPosition(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, frameScaleFactor, fixedElementsLayoutRelativeToFrame(), headerHeight(), footerHeight());
1618 bool FrameView::fixedElementsLayoutRelativeToFrame() const
1621 if (!m_frame->settings())
1624 return m_frame->settings()->fixedElementsLayoutRelativeToFrame();
1627 IntPoint FrameView::lastKnownMousePosition() const
1629 return m_frame ? m_frame->eventHandler()->lastKnownMousePosition() : IntPoint();
1632 bool FrameView::shouldSetCursor() const
1634 Page* page = frame()->page();
1635 return page && page->isOnscreen() && page->focusController()->isActive();
1638 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1640 if (!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty()) {
1641 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1645 const bool isCompositedContentLayer = contentsInCompositedLayer();
1647 // Get the rects of the fixed objects visible in the rectToScroll
1648 Region regionToUpdate;
1649 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end();
1650 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) {
1651 RenderObject* renderer = *it;
1652 if (!renderer->style()->hasViewportConstrainedPosition())
1654 #if USE(ACCELERATED_COMPOSITING)
1655 if (renderer->isComposited())
1659 // Fixed items should always have layers.
1660 ASSERT(renderer->hasLayer());
1661 RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
1663 #if USE(ACCELERATED_COMPOSITING)
1664 if (layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForBoundsOutOfView
1665 || layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForNoVisibleContent) {
1666 // Don't invalidate for invisible fixed layers.
1671 #if ENABLE(CSS_FILTERS)
1672 if (layer->hasAncestorWithFilterOutsets()) {
1673 // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot
1674 // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
1678 IntRect updateRect = pixelSnappedIntRect(layer->repaintRectIncludingNonCompositingDescendants());
1679 updateRect = contentsToRootView(updateRect);
1680 if (!isCompositedContentLayer && clipsRepaints())
1681 updateRect.intersect(rectToScroll);
1682 if (!updateRect.isEmpty())
1683 regionToUpdate.unite(updateRect);
1687 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1689 // 2) update the area of fixed objects that has been invalidated
1690 Vector<IntRect> subRectsToUpdate = regionToUpdate.rects();
1691 size_t viewportConstrainedObjectsCount = subRectsToUpdate.size();
1692 for (size_t i = 0; i < viewportConstrainedObjectsCount; ++i) {
1693 IntRect updateRect = subRectsToUpdate[i];
1694 IntRect scrolledRect = updateRect;
1695 scrolledRect.move(scrollDelta);
1696 updateRect.unite(scrolledRect);
1697 #if USE(ACCELERATED_COMPOSITING)
1698 if (isCompositedContentLayer) {
1699 updateRect = rootViewToContents(updateRect);
1700 ASSERT(renderView());
1701 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
1705 if (clipsRepaints())
1706 updateRect.intersect(rectToScroll);
1707 hostWindow()->invalidateContentsAndRootView(updateRect, false);
1713 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1715 #if USE(ACCELERATED_COMPOSITING)
1716 if (contentsInCompositedLayer()) {
1717 IntRect updateRect = visibleContentRect();
1719 // Make sure to "apply" the scale factor here since we're converting from frame view
1720 // coordinates to layer backing coordinates.
1721 updateRect.scale(1 / m_frame->frameScaleFactor());
1723 ASSERT(renderView());
1724 renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
1726 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1727 if (isEnclosedInCompositingLayer()) {
1728 LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1729 frameRenderer->borderTop() + frameRenderer->paddingTop(),
1730 visibleWidth(), visibleHeight());
1731 frameRenderer->repaintRectangle(rect);
1737 ScrollView::scrollContentsSlowPath(updateRect);
1740 // Note that this gets called at painting time.
1741 void FrameView::setIsOverlapped(bool isOverlapped)
1743 if (isOverlapped == m_isOverlapped)
1746 m_isOverlapped = isOverlapped;
1747 updateCanBlitOnScrollRecursively();
1749 #if USE(ACCELERATED_COMPOSITING)
1750 if (hasCompositedContentIncludingDescendants()) {
1751 // Overlap can affect compositing tests, so if it changes, we need to trigger
1752 // a layer update in the parent document.
1753 if (Frame* parentFrame = m_frame->tree()->parent()) {
1754 if (RenderView* parentView = parentFrame->contentRenderer()) {
1755 RenderLayerCompositor* compositor = parentView->compositor();
1756 compositor->setCompositingLayersNeedRebuild();
1757 compositor->scheduleCompositingLayerUpdate();
1761 if (RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) {
1762 // We also need to trigger reevaluation for this and all descendant frames,
1763 // since a frame uses compositing if any ancestor is compositing.
1764 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1765 if (RenderView* view = frame->contentRenderer()) {
1766 RenderLayerCompositor* compositor = view->compositor();
1767 compositor->setCompositingLayersNeedRebuild();
1768 compositor->scheduleCompositingLayerUpdate();
1776 bool FrameView::isOverlappedIncludingAncestors() const
1781 if (FrameView* parentView = parentFrameView()) {
1782 if (parentView->isOverlapped())
1789 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1791 if (contentIsOpaque == m_contentIsOpaque)
1794 m_contentIsOpaque = contentIsOpaque;
1795 updateCanBlitOnScrollRecursively();
1798 void FrameView::restoreScrollbar()
1800 setScrollbarsSuppressed(false);
1803 bool FrameView::scrollToFragment(const KURL& url)
1805 // If our URL has no ref, then we have no place we need to jump to.
1806 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1807 // and possibly repaint because :target pseudo class may have been
1808 // set (see bug 11321).
1809 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1812 String fragmentIdentifier = url.fragmentIdentifier();
1813 if (scrollToAnchor(fragmentIdentifier))
1816 // Try again after decoding the ref, based on the document's encoding.
1817 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1818 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1823 bool FrameView::scrollToAnchor(const String& name)
1825 ASSERT(m_frame->document());
1827 if (!m_frame->document()->haveStylesheetsLoaded()) {
1828 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1832 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1834 Element* anchorNode = m_frame->document()->findAnchor(name);
1836 // Setting to null will clear the current target.
1837 m_frame->document()->setCSSTarget(anchorNode);
1840 if (m_frame->document()->isSVGDocument()) {
1841 if (SVGSVGElement* svg = toSVGDocument(m_frame->document())->rootElement()) {
1842 svg->setupInitialView(name, anchorNode);
1849 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1850 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1853 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1855 // If the anchor accepts keyboard focus, move focus there to aid users relying on keyboard navigation.
1856 if (anchorNode && anchorNode->isFocusable())
1857 m_frame->document()->setFocusedNode(anchorNode);
1862 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1864 m_maintainScrollPositionAnchor = anchorNode;
1865 if (!m_maintainScrollPositionAnchor)
1868 // We need to update the layout before scrolling, otherwise we could
1869 // really mess things up if an anchor scroll comes at a bad moment.
1870 m_frame->document()->updateStyleIfNeeded();
1871 // Only do a layout if changes have occurred that make it necessary.
1872 RenderView* renderView = this->renderView();
1873 if (renderView && renderView->needsLayout())
1879 void FrameView::scrollElementToRect(Element* element, const IntRect& rect)
1881 m_frame->document()->updateLayoutIgnorePendingStylesheets();
1883 LayoutRect bounds = element->boundingBox();
1884 int centeringOffsetX = (rect.width() - bounds.width()) / 2;
1885 int centeringOffsetY = (rect.height() - bounds.height()) / 2;
1886 setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y()));
1889 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1891 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1892 m_maintainScrollPositionAnchor = 0;
1894 IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint);
1896 if (newScrollPosition == scrollPosition())
1899 if (requestScrollPositionUpdate(newScrollPosition))
1902 ScrollView::setScrollPosition(newScrollPosition);
1905 void FrameView::delegatesScrollingDidChange()
1907 #if USE(ACCELERATED_COMPOSITING)
1908 // When we switch to delgatesScrolling mode, we should destroy the scrolling/clipping layers in RenderLayerCompositor.
1909 if (hasCompositedContent())
1910 clearBackingStores();
1914 void FrameView::setFixedVisibleContentRect(const IntRect& visibleContentRect)
1916 bool visibleContentSizeDidChange = false;
1917 if (visibleContentRect.size() != this->fixedVisibleContentRect().size()) {
1918 // When the viewport size changes or the content is scaled, we need to
1919 // reposition the fixed and sticky positioned elements.
1920 setViewportConstrainedObjectsNeedLayout();
1921 visibleContentSizeDidChange = true;
1924 IntSize offset = scrollOffset();
1925 ScrollView::setFixedVisibleContentRect(visibleContentRect);
1926 if (offset != scrollOffset()) {
1927 repaintFixedElementsAfterScrolling();
1928 if (m_frame->page()->settings()->acceleratedCompositingForFixedPositionEnabled())
1929 updateFixedElementsAfterScrolling();
1930 scrollAnimator()->setCurrentPosition(scrollPosition());
1931 scrollPositionChanged();
1933 if (visibleContentSizeDidChange) {
1934 // Update the scroll-bars to calculate new page-step size.
1935 updateScrollbars(scrollOffset());
1937 frame()->loader()->client()->didChangeScrollOffset();
1940 void FrameView::setViewportConstrainedObjectsNeedLayout()
1942 if (!hasViewportConstrainedObjects())
1945 ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end();
1946 for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) {
1947 RenderObject* renderer = *it;
1948 renderer->setNeedsLayout(true);
1953 void FrameView::scrollPositionChangedViaPlatformWidget()
1955 repaintFixedElementsAfterScrolling();
1956 updateFixedElementsAfterScrolling();
1957 scrollPositionChanged();
1960 void FrameView::scrollPositionChanged()
1962 frame()->eventHandler()->sendScrollEvent();
1963 frame()->eventHandler()->dispatchFakeMouseMoveEventSoon();
1965 #if USE(ACCELERATED_COMPOSITING)
1966 if (RenderView* renderView = this->renderView()) {
1967 if (renderView->usesCompositing())
1968 renderView->compositor()->frameViewDidScroll();
1973 void FrameView::repaintFixedElementsAfterScrolling()
1975 // For fixed position elements, update widget positions and compositing layers after scrolling,
1976 // but only if we're not inside of layout.
1977 if (!m_nestedLayoutCount && hasViewportConstrainedObjects()) {
1978 if (RenderView* renderView = this->renderView()) {
1979 renderView->updateWidgetPositions();
1980 renderView->layer()->updateLayerPositionsAfterDocumentScroll();
1985 bool FrameView::shouldUpdateFixedElementsAfterScrolling()
1987 #if ENABLE(THREADED_SCROLLING)
1988 Page* page = m_frame->page();
1992 // If the scrolling thread is updating the fixed elements, then the FrameView should not update them as well.
1993 if (page->mainFrame() != m_frame)
1996 ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
1997 if (!scrollingCoordinator)
2000 if (!scrollingCoordinator->supportsFixedPositionLayers())
2003 if (scrollingCoordinator->shouldUpdateScrollLayerPositionOnMainThread())
2006 if (inProgrammaticScroll())
2014 void FrameView::updateFixedElementsAfterScrolling()
2016 #if USE(ACCELERATED_COMPOSITING)
2017 if (!shouldUpdateFixedElementsAfterScrolling())
2020 if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) {
2021 if (RenderView* renderView = this->renderView())
2022 renderView->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
2027 bool FrameView::shouldRubberBandInDirection(ScrollDirection direction) const
2029 Page* page = frame() ? frame()->page() : 0;
2031 return ScrollView::shouldRubberBandInDirection(direction);
2032 return page->chrome()->client()->shouldRubberBandInDirection(direction);
2035 bool FrameView::isRubberBandInProgress() const
2037 if (scrollbarsSuppressed())
2040 // If the scrolling thread updates the scroll position for this FrameView, then we should return
2041 // ScrollingCoordinator::isRubberBandInProgress().
2042 if (Page* page = m_frame->page()) {
2043 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
2044 if (!scrollingCoordinator->shouldUpdateScrollLayerPositionOnMainThread())
2045 return scrollingCoordinator->isRubberBandInProgress();
2049 // If the main thread updates the scroll position for this FrameView, we should return
2050 // ScrollAnimator::isRubberBandInProgress().
2051 if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
2052 return scrollAnimator->isRubberBandInProgress();
2057 bool FrameView::requestScrollPositionUpdate(const IntPoint& position)
2059 #if ENABLE(THREADED_SCROLLING)
2060 if (TiledBacking* tiledBacking = this->tiledBacking()) {
2061 IntRect visibleRect = visibleContentRect();
2062 visibleRect.setLocation(position);
2063 tiledBacking->prepopulateRect(visibleRect);
2066 if (Page* page = m_frame->page()) {
2067 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2068 return scrollingCoordinator->requestScrollPositionUpdate(this, position);
2071 UNUSED_PARAM(position);
2077 HostWindow* FrameView::hostWindow() const
2079 Page* page = frame() ? frame()->page() : 0;
2082 return page->chrome();
2085 const unsigned cRepaintRectUnionThreshold = 25;
2087 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
2089 ASSERT(!m_frame->ownerElement());
2091 if (m_isTrackingRepaints) {
2092 IntRect repaintRect = r;
2093 repaintRect.move(-scrollOffset());
2094 m_trackedRepaintRects.append(repaintRect);
2097 double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay();
2098 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
2099 IntRect paintRect = r;
2100 if (clipsRepaints() && !paintsEntireContents())
2101 paintRect.intersect(visibleContentRect());
2102 if (paintRect.isEmpty())
2104 if (m_repaintCount == cRepaintRectUnionThreshold) {
2105 IntRect unionedRect;
2106 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
2107 unionedRect.unite(pixelSnappedIntRect(m_repaintRects[i]));
2108 m_repaintRects.clear();
2109 m_repaintRects.append(unionedRect);
2111 if (m_repaintCount < cRepaintRectUnionThreshold)
2112 m_repaintRects.append(paintRect);
2114 m_repaintRects[0].unite(paintRect);
2117 if (!m_deferringRepaints)
2118 startDeferredRepaintTimer(delay);
2123 if (!shouldUpdate(immediate))
2126 #if USE(TILED_BACKING_STORE)
2127 if (frame()->tiledBackingStore()) {
2128 frame()->tiledBackingStore()->invalidate(r);
2132 ScrollView::repaintContentRectangle(r, immediate);
2135 void FrameView::contentsResized()
2137 ScrollView::contentsResized();
2141 void FrameView::visibleContentsResized()
2143 // We check to make sure the view is attached to a frame() as this method can
2144 // be triggered before the view is attached by Frame::createView(...) setting
2145 // various values such as setScrollBarModes(...) for example. An ASSERT is
2146 // triggered when a view is layout before being attached to a frame().
2147 if (!frame()->view())
2150 if (!useFixedLayout() && needsLayout())
2153 #if USE(ACCELERATED_COMPOSITING)
2154 if (RenderView* renderView = this->renderView()) {
2155 if (renderView->usesCompositing())
2156 renderView->compositor()->frameViewDidChangeSize();
2161 void FrameView::beginDeferredRepaints()
2163 Page* page = m_frame->page();
2164 if (page->mainFrame() != m_frame) {
2165 page->mainFrame()->view()->beginDeferredRepaints();
2169 m_deferringRepaints++;
2172 void FrameView::endDeferredRepaints()
2174 Page* page = m_frame->page();
2175 if (page->mainFrame() != m_frame) {
2176 page->mainFrame()->view()->endDeferredRepaints();
2180 ASSERT(m_deferringRepaints > 0);
2182 if (--m_deferringRepaints)
2185 if (m_deferredRepaintTimer.isActive())
2188 if (double delay = adjustedDeferredRepaintDelay()) {
2189 startDeferredRepaintTimer(delay);
2193 doDeferredRepaints();
2196 void FrameView::startDeferredRepaintTimer(double delay)
2198 if (m_deferredRepaintTimer.isActive())
2201 if (m_disableRepaints)
2204 m_deferredRepaintTimer.startOneShot(delay);
2207 void FrameView::handleLoadCompleted()
2209 // Once loading has completed, allow autoSize one last opportunity to
2210 // reduce the size of the frame.
2211 autoSizeIfEnabled();
2212 if (shouldUseLoadTimeDeferredRepaintDelay())
2214 m_deferredRepaintDelay = s_normalDeferredRepaintDelay;
2215 flushDeferredRepaints();
2218 void FrameView::flushDeferredRepaints()
2220 if (!m_deferredRepaintTimer.isActive())
2222 m_deferredRepaintTimer.stop();
2223 doDeferredRepaints();
2226 void FrameView::doDeferredRepaints()
2228 if (m_disableRepaints)
2231 ASSERT(!m_deferringRepaints);
2232 if (!shouldUpdate()) {
2233 m_repaintRects.clear();
2237 unsigned size = m_repaintRects.size();
2238 for (unsigned i = 0; i < size; i++) {
2239 #if USE(TILED_BACKING_STORE)
2240 if (frame()->tiledBackingStore()) {
2241 frame()->tiledBackingStore()->invalidate(pixelSnappedIntRect(m_repaintRects[i]));
2245 ScrollView::repaintContentRectangle(pixelSnappedIntRect(m_repaintRects[i]), false);
2247 m_repaintRects.clear();
2250 updateDeferredRepaintDelayAfterRepaint();
2253 bool FrameView::shouldUseLoadTimeDeferredRepaintDelay() const
2255 // Don't defer after the initial load of the page has been completed.
2256 if (m_frame->tree()->top()->loader()->isComplete())
2258 Document* document = m_frame->document();
2261 if (document->parsing())
2263 if (document->cachedResourceLoader()->requestCount())
2268 void FrameView::updateDeferredRepaintDelayAfterRepaint()
2270 if (!shouldUseLoadTimeDeferredRepaintDelay()) {
2271 m_deferredRepaintDelay = s_normalDeferredRepaintDelay;
2274 double incrementedRepaintDelay = m_deferredRepaintDelay + s_deferredRepaintDelayIncrementDuringLoading;
2275 m_deferredRepaintDelay = std::min(incrementedRepaintDelay, s_maxDeferredRepaintDelayDuringLoading);
2278 void FrameView::resetDeferredRepaintDelay()
2280 m_deferredRepaintDelay = 0;
2281 if (m_deferredRepaintTimer.isActive()) {
2282 m_deferredRepaintTimer.stop();
2283 if (!m_deferringRepaints)
2284 doDeferredRepaints();
2286 #if USE(ACCELERATED_COMPOSITING)
2287 if (RenderView* view = renderView())
2288 view->compositor()->disableLayerFlushThrottlingTemporarilyForInteraction();
2292 double FrameView::adjustedDeferredRepaintDelay() const
2294 ASSERT(!m_deferringRepaints);
2295 if (!m_deferredRepaintDelay)
2297 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
2298 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
2301 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
2303 doDeferredRepaints();
2306 void FrameView::beginDisableRepaints()
2308 m_disableRepaints++;
2311 void FrameView::endDisableRepaints()
2313 ASSERT(m_disableRepaints > 0);
2314 m_disableRepaints--;
2317 void FrameView::updateLayerFlushThrottlingInAllFrames(bool isLoadProgressing)
2319 #if USE(ACCELERATED_COMPOSITING)
2320 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
2321 if (RenderView* renderView = frame->contentRenderer())
2322 renderView->compositor()->setLayerFlushThrottlingEnabled(isLoadProgressing);
2325 UNUSED_PARAM(isLoadProgressing);
2329 void FrameView::adjustTiledBackingCoverage()
2331 #if USE(ACCELERATED_COMPOSITING)
2332 RenderView* renderView = this->renderView();
2333 if (renderView && renderView->layer()->backing())
2334 renderView->layer()->backing()->adjustTiledBackingCoverage();
2338 void FrameView::layoutTimerFired(Timer<FrameView>*)
2340 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2341 if (!m_frame->document()->ownerElement())
2342 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
2347 void FrameView::scheduleRelayout()
2349 // FIXME: We should assert the page is not in the page cache, but that is causing
2350 // too many false assertions. See <rdar://problem/7218118>.
2351 ASSERT(m_frame->view() == this);
2354 m_layoutRoot->markContainingBlocksForLayout(false);
2357 if (!m_layoutSchedulingEnabled)
2361 if (!m_frame->document()->shouldScheduleLayout())
2363 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2364 // When frame flattening is enabled, the contents of the frame could affect the layout of the parent frames.
2365 // Also invalidate parent frame starting from the owner element of this frame.
2366 if (m_frame->ownerRenderer() && isInChildFrameWithFrameFlattening())
2367 m_frame->ownerRenderer()->setNeedsLayout(true, MarkContainingBlockChain);
2369 int delay = m_frame->document()->minimumLayoutDelay();
2370 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
2371 unscheduleRelayout();
2372 if (m_layoutTimer.isActive())
2375 m_delayedLayout = delay != 0;
2377 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2378 if (!m_frame->document()->ownerElement())
2379 printf("Scheduling layout for %d\n", delay);
2382 m_layoutTimer.startOneShot(delay * 0.001);
2385 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
2387 for (RenderObject* r = descendant; r; r = r->container()) {
2394 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
2396 ASSERT(m_frame->view() == this);
2398 RenderView* renderView = this->renderView();
2399 if (renderView && renderView->needsLayout()) {
2401 relayoutRoot->markContainingBlocksForLayout(false);
2405 if (layoutPending() || !m_layoutSchedulingEnabled) {
2406 if (m_layoutRoot != relayoutRoot) {
2407 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
2408 // Keep the current root
2409 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
2410 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2411 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
2412 // Re-root at relayoutRoot
2413 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
2414 m_layoutRoot = relayoutRoot;
2415 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2416 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2418 // Just do a full relayout
2420 m_layoutRoot->markContainingBlocksForLayout(false);
2422 relayoutRoot->markContainingBlocksForLayout(false);
2423 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2426 } else if (m_layoutSchedulingEnabled) {
2427 int delay = m_frame->document()->minimumLayoutDelay();
2428 m_layoutRoot = relayoutRoot;
2429 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2430 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2431 m_delayedLayout = delay != 0;
2432 m_layoutTimer.startOneShot(delay * 0.001);
2436 bool FrameView::layoutPending() const
2438 return m_layoutTimer.isActive();
2441 bool FrameView::needsLayout() const
2443 // This can return true in cases where the document does not have a body yet.
2444 // Document::shouldScheduleLayout takes care of preventing us from scheduling
2445 // layout in that case.
2449 RenderView* renderView = this->renderView();
2450 return layoutPending()
2451 || (renderView && renderView->needsLayout())
2453 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
2456 void FrameView::setNeedsLayout()
2458 if (m_deferSetNeedsLayouts) {
2459 m_setNeedsLayoutWasDeferred = true;
2463 if (RenderView* renderView = this->renderView())
2464 renderView->setNeedsLayout(true);
2467 void FrameView::unscheduleRelayout()
2469 if (!m_layoutTimer.isActive())
2472 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2473 if (!m_frame->document()->ownerElement())
2474 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
2477 m_layoutTimer.stop();
2478 m_delayedLayout = false;
2481 #if ENABLE(REQUEST_ANIMATION_FRAME)
2482 void FrameView::serviceScriptedAnimations(double monotonicAnimationStartTime)
2484 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext()) {
2485 frame->view()->serviceScrollAnimations();
2486 frame->animation()->serviceAnimations();
2489 Vector<RefPtr<Document> > documents;
2490 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext())
2491 documents.append(frame->document());
2493 for (size_t i = 0; i < documents.size(); ++i)
2494 documents[i]->serviceScriptedAnimations(monotonicAnimationStartTime);
2498 bool FrameView::isTransparent() const
2500 return m_isTransparent;
2503 void FrameView::setTransparent(bool isTransparent)
2505 m_isTransparent = isTransparent;
2508 bool FrameView::hasOpaqueBackground() const
2510 return !m_isTransparent && !m_baseBackgroundColor.hasAlpha();
2513 Color FrameView::baseBackgroundColor() const
2515 return m_baseBackgroundColor;
2518 void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
2520 if (!backgroundColor.isValid())
2521 m_baseBackgroundColor = Color::white;
2523 m_baseBackgroundColor = backgroundColor;
2525 recalculateScrollbarOverlayStyle();
2528 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
2530 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
2531 if (FrameView* view = frame->view()) {
2532 view->setTransparent(transparent);
2533 view->setBaseBackgroundColor(backgroundColor);
2538 bool FrameView::shouldUpdateWhileOffscreen() const
2540 return m_shouldUpdateWhileOffscreen;
2543 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
2545 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
2548 bool FrameView::shouldUpdate(bool immediateRequested) const
2550 if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen())
2555 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
2557 m_actionScheduler->scheduleEvent(event, eventTarget);
2560 void FrameView::pauseScheduledEvents()
2562 m_actionScheduler->pause();
2565 void FrameView::resumeScheduledEvents()
2567 m_actionScheduler->resume();
2570 void FrameView::scrollToAnchor()
2572 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
2576 if (!anchorNode->renderer())
2580 if (anchorNode != m_frame->document())
2581 rect = anchorNode->boundingBox();
2583 // Scroll nested layers and frames to reveal the anchor.
2584 // Align to the top and to the closest side (this matches other browsers).
2585 anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
2587 if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache())
2588 cache->handleScrolledToAnchor(anchorNode.get());
2590 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
2591 m_maintainScrollPositionAnchor = anchorNode;
2594 void FrameView::updateWidget(RenderObject* object)
2596 ASSERT(!object->node() || object->node()->isElementNode());
2597 Element* ownerElement = toElement(object->node());
2598 // The object may have already been destroyed (thus node cleared),
2599 // but FrameView holds a manual ref, so it won't have been deleted.
2600 ASSERT(m_widgetUpdateSet->contains(object));
2604 if (object->isEmbeddedObject()) {
2605 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
2606 // No need to update if it's already crashed or known to be missing.
2607 if (embeddedObject->showsUnavailablePluginIndicator())
2610 if (object->isSnapshottedPlugIn()) {
2611 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag)) {
2612 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement);
2613 pluginElement->updateSnapshotInfo();
2618 // FIXME: This could turn into a real virtual dispatch if we defined
2619 // updateWidget(PluginCreationOption) on HTMLElement.
2620 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag) || ownerElement->hasTagName(appletTag)) {
2621 HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement);
2622 if (pluginElement->needsWidgetUpdate())
2623 pluginElement->updateWidget(CreateAnyWidgetType);
2625 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
2626 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
2627 else if (ownerElement->isMediaElement())
2628 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
2631 ASSERT_NOT_REACHED();
2633 // Caution: it's possible the object was destroyed again, since loading a
2634 // plugin may run any arbitrary JavaScript.
2635 embeddedObject->updateWidgetPosition();
2639 bool FrameView::updateWidgets()
2641 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
2644 size_t size = m_widgetUpdateSet->size();
2646 Vector<RenderObject*> objects;
2647 objects.reserveInitialCapacity(size);
2649 RenderObjectSet::const_iterator end = m_widgetUpdateSet->end();
2650 for (RenderObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
2651 RenderObject* object = *it;
2652 objects.uncheckedAppend(object);
2653 if (object->isEmbeddedObject()) {
2654 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
2655 embeddedObject->ref();
2659 for (size_t i = 0; i < size; ++i) {
2660 RenderObject* object = objects[i];
2661 updateWidget(object);
2662 m_widgetUpdateSet->remove(object);
2665 RenderArena* arena = m_frame->document()->renderArena();
2666 for (size_t i = 0; i < size; ++i) {
2667 RenderObject* object = objects[i];
2668 if (object->isEmbeddedObject()) {
2669 RenderEmbeddedObject* embeddedObject = static_cast<RenderEmbeddedObject*>(object);
2670 embeddedObject->deref(arena);
2674 return m_widgetUpdateSet->isEmpty();
2677 void FrameView::flushAnyPendingPostLayoutTasks()
2679 if (!m_postLayoutTasksTimer.isActive())
2682 performPostLayoutTasks();
2685 void FrameView::performPostLayoutTasks()
2687 m_postLayoutTasksTimer.stop();
2689 m_frame->selection()->setCaretRectNeedsUpdate();
2690 m_frame->selection()->updateAppearance();
2692 LayoutMilestones milestonesOfInterest = 0;
2693 LayoutMilestones milestonesAchieved = 0;
2694 Page* page = m_frame->page();
2696 milestonesOfInterest = page->layoutMilestones();
2698 if (m_nestedLayoutCount <= 1) {
2699 if (m_firstLayoutCallbackPending) {
2700 m_firstLayoutCallbackPending = false;
2701 m_frame->loader()->didFirstLayout();
2702 if (milestonesOfInterest & DidFirstLayout)
2703 milestonesAchieved |= DidFirstLayout;
2705 if (page->mainFrame() == m_frame)
2706 page->startCountingRelevantRepaintedObjects();
2710 // Ensure that we always send this eventually.
2711 if (!m_frame->document()->parsing() && m_frame->loader()->stateMachine()->committedFirstRealDocumentLoad())
2712 m_isVisuallyNonEmpty = true;
2714 // If the layout was done with pending sheets, we are not in fact visually non-empty yet.
2715 if (m_isVisuallyNonEmpty && !m_frame->document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) {
2716 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
2717 if (milestonesOfInterest & DidFirstVisuallyNonEmptyLayout)
2718 milestonesAchieved |= DidFirstVisuallyNonEmptyLayout;
2722 m_frame->loader()->didLayout(milestonesAchieved);
2723 #if ENABLE(FONT_LOAD_EVENTS)
2724 if (RuntimeEnabledFeatures::fontLoadEventsEnabled())
2725 m_frame->document()->fontloader()->didLayout();
2728 // FIXME: We should consider adding DidLayout as a LayoutMilestone. That would let us merge this
2729 // with didLayout(LayoutMilestones).
2730 m_frame->loader()->client()->dispatchDidLayout();
2732 RenderView* renderView = this->renderView();
2734 renderView->updateWidgetPositions();
2736 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
2737 if (updateWidgets())
2742 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2743 scrollingCoordinator->frameViewLayoutUpdated(this);
2746 #if USE(ACCELERATED_COMPOSITING)
2747 if (renderView && renderView->usesCompositing())
2748 renderView->compositor()->frameViewDidLayout();
2753 m_actionScheduler->resume();
2755 if (renderView && !renderView->printing()) {
2756 IntSize currentSize;
2757 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
2758 currentSize = fixedLayoutSize();
2760 currentSize = visibleContentRect(IncludeScrollbars).size();
2761 float currentZoomFactor = renderView->style()->zoom();
2762 bool resized = !m_firstLayout && (currentSize != m_lastViewportSize || currentZoomFactor != m_lastZoomFactor);
2763 m_lastViewportSize = currentSize;
2764 m_lastZoomFactor = currentZoomFactor;
2767 scheduleResizeEvent();
2774 void FrameView::sendResizeEvent()
2779 m_frame->eventHandler()->sendResizeEvent();
2781 #if ENABLE(INSPECTOR)
2782 if (InspectorInstrumentation::hasFrontends()) {
2783 if (Page* page = m_frame->page()) {
2784 if (page->mainFrame() == m_frame) {
2785 if (InspectorClient* inspectorClient = page->inspectorController()->inspectorClient())
2786 inspectorClient->didResizeMainFrame(m_frame.get());
2793 void FrameView::delayedResizeEventTimerFired(Timer<FrameView>*)
2798 void FrameView::willStartLiveResize()
2800 ScrollView::willStartLiveResize();
2801 adjustTiledBackingCoverage();
2804 void FrameView::willEndLiveResize()
2806 ScrollableArea::willEndLiveResize();
2807 if (m_delayedResizeEventTimer.isActive()) {
2808 m_delayedResizeEventTimer.stop();
2811 adjustTiledBackingCoverage();
2814 void FrameView::scheduleResizeEvent()
2816 if (!m_delayedResizeEventTimer.isActive())
2817 m_delayedResizeEventTimer.startOneShot(minimumIntervalBetweenResizeEventsDuringLiveResizeInSeconds);
2820 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
2822 performPostLayoutTasks();
2825 void FrameView::autoSizeIfEnabled()
2827 if (!m_shouldAutoSize)
2833 TemporaryChange<bool> changeInAutoSize(m_inAutoSize, true);
2835 Document* document = frame()->document();
2839 RenderView* documentView = document->renderView();
2840 Element* documentElement = document->documentElement();
2841 if (!documentView || !documentElement)
2844 // Start from the minimum size and allow it to grow.
2845 resize(m_minAutoSize.width(), m_minAutoSize.height());
2847 IntSize size = frameRect().size();
2849 // Do the resizing twice. The first time is basically a rough calculation using the preferred width
2850 // which may result in a height change during the second iteration.
2851 for (int i = 0; i < 2; i++) {
2852 // Update various sizes including contentsSize, scrollHeight, etc.
2853 document->updateLayoutIgnorePendingStylesheets();
2854 int width = documentView->minPreferredLogicalWidth();
2855 int height = documentView->documentRect().height();
2856 IntSize newSize(width, height);
2858 // Check to see if a scrollbar is needed for a given dimension and
2859 // if so, increase the other dimension to account for the scrollbar.
2860 // Since the dimensions are only for the view rectangle, once a
2861 // dimension exceeds the maximum, there is no need to increase it further.
2862 if (newSize.width() > m_maxAutoSize.width()) {
2863 RefPtr<Scrollbar> localHorizontalScrollbar = horizontalScrollbar();
2864 if (!localHorizontalScrollbar)
2865 localHorizontalScrollbar = createScrollbar(HorizontalScrollbar);
2866 if (!localHorizontalScrollbar->isOverlayScrollbar())
2867 newSize.setHeight(newSize.height() + localHorizontalScrollbar->height());
2869 // Don't bother checking for a vertical scrollbar because the width is at
2870 // already greater the maximum.
2871 } else if (newSize.height() > m_maxAutoSize.height()) {
2872 RefPtr<Scrollbar> localVerticalScrollbar = verticalScrollbar();
2873 if (!localVerticalScrollbar)
2874 localVerticalScrollbar = createScrollbar(VerticalScrollbar);
2875 if (!localVerticalScrollbar->isOverlayScrollbar())
2876 newSize.setWidth(newSize.width() + localVerticalScrollbar->width());
2878 // Don't bother checking for a horizontal scrollbar because the height is
2879 // already greater the maximum.
2882 // Ensure the size is at least the min bounds.
2883 newSize = newSize.expandedTo(m_minAutoSize);
2885 // Bound the dimensions by the max bounds and determine what scrollbars to show.
2886 ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff;
2887 if (newSize.width() > m_maxAutoSize.width()) {
2888 newSize.setWidth(m_maxAutoSize.width());
2889 horizonalScrollbarMode = ScrollbarAlwaysOn;
2891 ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff;
2892 if (newSize.height() > m_maxAutoSize.height()) {
2893 newSize.setHeight(m_maxAutoSize.height());
2894 verticalScrollbarMode = ScrollbarAlwaysOn;
2897 if (newSize == size)
2900 // While loading only allow the size to increase (to avoid twitching during intermediate smaller states)
2901 // unless autoresize has just been turned on or the maximum size is smaller than the current size.
2902 if (m_didRunAutosize && size.height() <= m_maxAutoSize.height() && size.width() <= m_maxAutoSize.width()
2903 && !frame()->loader()->isComplete() && (newSize.height() < size.height() || newSize.width() < size.width()))
2906 resize(newSize.width(), newSize.height());
2907 // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example,
2908 // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed).
2909 setVerticalScrollbarLock(false);
2910 setHorizontalScrollbarLock(false);
2911 setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true);
2913 m_didRunAutosize = true;
2916 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
2918 if (!m_viewportRenderer)
2921 if (m_overflowStatusDirty) {
2922 m_horizontalOverflow = horizontalOverflow;
2923 m_verticalOverflow = verticalOverflow;
2924 m_overflowStatusDirty = false;
2928 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
2929 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
2931 if (horizontalOverflowChanged || verticalOverflowChanged) {
2932 m_horizontalOverflow = horizontalOverflow;
2933 m_verticalOverflow = verticalOverflow;
2935 m_actionScheduler->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
2936 verticalOverflowChanged, verticalOverflow),
2937 m_viewportRenderer->node());
2942 const Pagination& FrameView::pagination() const
2944 if (m_pagination != Pagination())
2945 return m_pagination;
2947 if (Page* page = m_frame->page()) {
2948 if (page->mainFrame() == m_frame)
2949 return page->pagination();
2952 return m_pagination;
2955 void FrameView::setPagination(const Pagination& pagination)
2957 if (m_pagination == pagination)
2960 m_pagination = pagination;
2963 m_frame->document()->styleResolverChanged(DeferRecalcStyle);
2966 IntRect FrameView::windowClipRect(bool clipToContents) const
2968 ASSERT(m_frame->view() == this);
2970 if (paintsEntireContents())
2971 return IntRect(IntPoint(), totalContentsSize());
2973 // Set our clip rect to be our contents.
2974 IntRect clipRect = contentsToWindow(visibleContentRect(clipToContents ? ExcludeScrollbars : IncludeScrollbars));
2975 if (!m_frame || !m_frame->ownerElement())
2978 // Take our owner element and get its clip rect.
2979 HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement();
2980 FrameView* parentView = ownerElement->document()->view();
2982 clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement, true));
2986 IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement, bool clipToLayerContents) const
2988 // The renderer can sometimes be null when style="display:none" interacts
2989 // with external content and plugins.
2990 if (!ownerElement->renderer())
2991 return windowClipRect();
2993 // If we have no layer, just return our window clip rect.
2994 const RenderLayer* enclosingLayer = ownerElement->renderer()->enclosingLayer();
2995 if (!enclosingLayer)
2996 return windowClipRect();
2998 // Apply the clip from the layer.
3000 if (clipToLayerContents)
3001 clipRect = pixelSnappedIntRect(enclosingLayer->childrenClipRect());
3003 clipRect = pixelSnappedIntRect(enclosingLayer->selfClipRect());
3004 clipRect = contentsToWindow(clipRect);
3005 return intersection(clipRect, windowClipRect());
3008 bool FrameView::isActive() const
3010 Page* page = frame()->page();
3011 return page && page->focusController()->isActive();
3014 void FrameView::scrollTo(const IntSize& newOffset)
3016 LayoutSize offset = scrollOffset();
3017 ScrollView::scrollTo(newOffset);
3018 if (offset != scrollOffset())
3019 scrollPositionChanged();
3020 frame()->loader()->client()->didChangeScrollOffset();
3023 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
3025 // Add in our offset within the FrameView.
3026 IntRect dirtyRect = rect;
3027 dirtyRect.moveBy(scrollbar->location());
3028 invalidateRect(dirtyRect);
3031 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
3033 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
3036 IntRect FrameView::windowResizerRect() const
3038 Page* page = frame() ? frame()->page() : 0;
3041 return page->chrome()->windowResizerRect();
3044 float FrameView::visibleContentScaleFactor() const
3046 if (!m_frame || !m_frame->page())
3049 if (!m_frame->settings()->applyPageScaleFactorInCompositor() || m_frame != m_frame->page()->mainFrame())
3052 return m_frame->page()->pageScaleFactor();
3055 void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
3057 Page* page = m_frame->page();
3060 if (page->mainFrame() != m_frame)
3062 page->chrome()->client()->notifyScrollerThumbIsVisibleInRect(scrollerThumb);
3065 bool FrameView::scrollbarsCanBeActive() const
3070 if (m_frame->view() != this)
3073 if (Page* page = m_frame->page()) {
3074 if (page->shouldSuppressScrollbarAnimations())
3078 if (Document* document = m_frame->document())
3079 return !document->inPageCache();
3084 ScrollableArea* FrameView::enclosingScrollableArea() const
3086 // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer.
3090 IntRect FrameView::scrollableAreaBoundingBox() const
3092 RenderPart* ownerRenderer = frame()->ownerRenderer();
3096 return ownerRenderer->absoluteContentQuad().enclosingBoundingBox();
3099 bool FrameView::isScrollable()
3102 // 1) If there an actual overflow.
3103 // 2) display:none or visibility:hidden set to self or inherited.
3104 // 3) overflow{-x,-y}: hidden;
3105 // 4) scrolling: no;
3108 IntSize totalContentsSize = this->totalContentsSize();
3109 IntSize visibleContentSize = visibleContentRect().size();
3110 if ((totalContentsSize.height() <= visibleContentSize.height() && totalContentsSize.width() <= visibleContentSize.width()))
3114 HTMLFrameOwnerElement* owner = m_frame->ownerElement();
3115 if (owner && (!owner->renderer() || !owner->renderer()->visibleToHitTesting()))
3119 ScrollbarMode horizontalMode;
3120 ScrollbarMode verticalMode;
3121 calculateScrollbarModesForLayout(horizontalMode, verticalMode, RulesFromWebContentOnly);
3122 if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff)
3128 void FrameView::updateScrollableAreaSet()
3130 // That ensures that only inner frames are cached.
3131 FrameView* parentFrameView = this->parentFrameView();
3132 if (!parentFrameView)
3135 if (!isScrollable()) {
3136 parentFrameView->removeScrollableArea(this);
3140 parentFrameView->addScrollableArea(this);
3143 bool FrameView::shouldSuspendScrollAnimations() const
3145 return m_frame->loader()->state() != FrameStateComplete;
3148 void FrameView::scrollbarStyleChanged(int newStyle, bool forceUpdate)
3150 Page* page = m_frame->page();
3153 if (page->mainFrame() != m_frame)
3155 page->chrome()->client()->recommendedScrollbarStyleDidChange(newStyle);
3158 ScrollView::scrollbarStyleChanged(newStyle, forceUpdate);
3161 void FrameView::setAnimatorsAreActive()
3163 Page* page = m_frame->page();
3167 if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
3168 scrollAnimator->setIsActive();
3170 if (!m_scrollableAreas)
3173 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
3174 ScrollableArea* scrollableArea = *it;
3176 ASSERT(scrollableArea->scrollbarsCanBeActive());
3177 scrollableArea->scrollAnimator()->setIsActive();
3181 void FrameView::notifyPageThatContentAreaWillPaint() const
3183 Page* page = m_frame->page();
3187 contentAreaWillPaint();
3189 if (!m_scrollableAreas)
3192 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
3193 ScrollableArea* scrollableArea = *it;
3195 if (!scrollableArea->scrollbarsCanBeActive())
3198 scrollableArea->contentAreaWillPaint();
3202 bool FrameView::scrollAnimatorEnabled() const
3204 #if ENABLE(SMOOTH_SCROLLING)
3205 if (Page* page = m_frame->page())
3206 return page->settings()->scrollAnimatorEnabled();
3212 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
3213 void FrameView::updateAnnotatedRegions()
3215 Document* document = m_frame->document();
3216 if (!document->hasAnnotatedRegions())
3218 Vector<AnnotatedRegionValue> newRegions;
3219 document->renderBox()->collectAnnotatedRegions(newRegions);
3220 if (newRegions == document->annotatedRegions())
3222 document->setAnnotatedRegions(newRegions);
3223 Page* page = m_frame->page();
3226 page->chrome()->client()->annotatedRegionsChanged();
3230 void FrameView::updateScrollCorner()
3232 RenderObject* renderer = 0;
3233 RefPtr<RenderStyle> cornerStyle;
3234 IntRect cornerRect = scrollCornerRect();
3236 if (!cornerRect.isEmpty()) {
3237 // Try the <body> element first as a scroll corner source.
3238 Document* doc = m_frame->document();
3239 Element* body = doc ? doc->body() : 0;
3240 if (body && body->renderer()) {
3241 renderer = body->renderer();
3242 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
3246 // If the <body> didn't have a custom style, then the root element might.
3247 Element* docElement = doc ? doc->documentElement() : 0;
3248 if (docElement && docElement->renderer()) {
3249 renderer = docElement->renderer();
3250 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
3255 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
3256 if (RenderPart* renderer = m_frame->ownerRenderer())
3257 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
3262 if (!m_scrollCorner)
3263 m_scrollCorner = RenderScrollbarPart::createAnonymous(renderer->document());
3264 m_scrollCorner->setStyle(cornerStyle.release());
3265 invalidateScrollCorner(cornerRect);
3266 } else if (m_scrollCorner) {
3267 m_scrollCorner->destroy();
3271 ScrollView::updateScrollCorner();
3274 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
3276 if (context->updatingControlTints()) {
3277 updateScrollCorner();
3281 if (m_scrollCorner) {
3282 bool needsBackgorund = m_frame->page() && m_frame->page()->mainFrame() == m_frame;
3283 if (needsBackgorund)
3284 context->fillRect(cornerRect, baseBackgroundColor(), ColorSpaceDeviceRGB);
3285 m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect);
3289 ScrollView::paintScrollCorner(context, cornerRect);
3292 void FrameView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
3294 bool needsBackgorund = bar->isCustomScrollbar() && (m_frame->page() && m_frame->page()->mainFrame() == m_frame);
3295 if (needsBackgorund) {
3296 IntRect toFill = bar->frameRect();
3297 toFill.intersect(rect);
3298 context->fillRect(toFill, baseBackgroundColor(), ColorSpaceDeviceRGB);
3301 ScrollView::paintScrollbar(context, bar, rect);
3304 Color FrameView::documentBackgroundColor() const
3306 // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of
3307 // the document and the body against the base background color of the frame view.
3308 // Background images are unfortunately impractical to include.
3310 // Return invalid Color objects whenever there is insufficient information.
3311 if (!frame()->document())
3314 Element* htmlElement = frame()->document()->documentElement();
3315 Element* bodyElement = frame()->document()->body();
3317 // Start with invalid colors.
3318 Color htmlBackgroundColor;
3319 Color bodyBackgroundColor;
3320 if (htmlElement && htmlElement->renderer())
3321 htmlBackgroundColor = htmlElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
3322 if (bodyElement && bodyElement->renderer())
3323 bodyBackgroundColor = bodyElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
3325 if (!bodyBackgroundColor.isValid()) {
3326 if (!htmlBackgroundColor.isValid())
3328 return baseBackgroundColor().blend(htmlBackgroundColor);
3331 if (!htmlBackgroundColor.isValid())
3332 return baseBackgroundColor().blend(bodyBackgroundColor);
3334 // We take the aggregate of the base background color
3335 // the <html> background color, and the <body>
3336 // background color to find the document color. The
3337 // addition of the base background color is not
3338 // technically part of the document background, but it
3339 // otherwise poses problems when the aggregate is not
3341 return baseBackgroundColor().blend(htmlBackgroundColor).blend(bodyBackgroundColor);
3344 bool FrameView::hasCustomScrollbars() const
3346 const HashSet<RefPtr<Widget> >* viewChildren = children();
3347 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
3348 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
3349 Widget* widget = current->get();
3350 if (widget->isFrameView()) {
3351 if (toFrameView(widget)->hasCustomScrollbars())
3353 } else if (widget->isScrollbar()) {
3354 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
3355 if (scrollbar->isCustomScrollbar())
3363 FrameView* FrameView::parentFrameView() const
3368 if (Frame* parentFrame = m_frame->tree()->parent())
3369 return parentFrame->view();
3374 bool FrameView::isInChildFrameWithFrameFlattening() const
3376 if (!parent() || !m_frame->ownerElement())
3379 // Frame flattening applies when the owner element is either in a frameset or
3380 // an iframe with flattening parameters.
3381 if (m_frame->ownerElement()->hasTagName(iframeTag)) {
3382 RenderIFrame* iframeRenderer = toRenderIFrame(m_frame->ownerElement()->renderPart());
3383 if (iframeRenderer->flattenFrame() || iframeRenderer->isSeamless())
3387 if (!m_frame->settings() || !m_frame->settings()->frameFlatteningEnabled())
3390 if (m_frame->ownerElement()->hasTagName(frameTag))
3396 bool FrameView::doLayoutWithFrameFlattening(bool allowSubtree)
3398 // Try initiating layout from the topmost parent.
3399 FrameView* parentView = parentFrameView();
3404 // In the middle of parent layout, no need to restart from topmost.
3405 if (parentView->m_nestedLayoutCount)
3408 // Parent tree is clean. Starting layout from it would have no effect.
3409 if (!parentView->needsLayout())
3412 while (parentView->parentFrameView())
3413 parentView = parentView->parentFrameView();
3415 parentView->layout(allowSubtree);
3417 RenderObject* root = m_layoutRoot ? m_layoutRoot : m_frame->document()->renderer();
3418 ASSERT_UNUSED(root, !root->needsLayout());
3423 void FrameView::updateControlTints()
3425 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
3426 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
3427 // This is only done if the theme supports control tinting. It's up to the theme and platform
3428 // to define when controls get the tint and to call this function when that changes.
3430 // Optimize the common case where we bring a window to the front while it's still empty.
3431 if (!m_frame || m_frame->document()->url().isEmpty())
3434 RenderView* renderView = this->renderView();
3435 if ((renderView && renderView->theme()->supportsControlTints()) || hasCustomScrollbars())
3436 paintControlTints();
3439 void FrameView::paintControlTints()
3443 PlatformGraphicsContext* const noContext = 0;
3444 GraphicsContext context(noContext);
3445 context.setUpdatingControlTints(true);
3446 if (platformWidget())
3447 paintContents(&context, visibleContentRect());
3449 paint(&context, frameRect());
3452 bool FrameView::wasScrolledByUser() const
3454 return m_wasScrolledByUser;
3457 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
3459 if (m_inProgrammaticScroll)
3461 m_maintainScrollPositionAnchor = 0;
3462 if (m_wasScrolledByUser == wasScrolledByUser)
3464 m_wasScrolledByUser = wasScrolledByUser;
3465 adjustTiledBackingCoverage();
3468 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
3473 Document* document = m_frame->document();
3477 if (document->printing())
3478 fillWithRed = false; // Printing, don't fill with red (can't remember why).
3479 else if (m_frame->ownerElement())
3480 fillWithRed = false; // Subframe, don't fill with red.
3481 else if (isTransparent())
3482 fillWithRed = false; // Transparent, don't fill with red.
3483 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
3484 fillWithRed = false; // Selections are transparent, don't fill with red.
3485 else if (m_nodeToDraw)
3486 fillWithRed = false; // Element images are transparent, don't fill with red.
3491 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
3494 RenderView* renderView = this->renderView();
3496 LOG_ERROR("called FrameView::paint with nil renderer");
3500 ASSERT(!needsLayout());
3504 InspectorInstrumentation::willPaint(renderView);
3506 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
3507 if (isTopLevelPainter)
3508 sCurrentPaintTimeStamp = currentTime();
3510 FontCachePurgePreventer fontCachePurgePreventer;
3512 #if USE(ACCELERATED_COMPOSITING)
3513 if (!p->paintingDisabled() && !document->printing())
3514 flushCompositingStateForThisFrame(m_frame.get());
3517 PaintBehavior oldPaintBehavior = m_paintBehavior;
3519 if (FrameView* parentView = parentFrameView()) {
3520 if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
3521 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
3524 if (m_paintBehavior == PaintBehaviorNormal)
3525 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
3527 if (document->printing())
3528 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
3530 bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers;
3531 bool isRootFrame = !m_frame->ownerElement();
3532 if (flatteningPaint && isRootFrame)
3533 notifyWidgetsInAllFrames(WillPaintFlattened);
3535 ASSERT(!m_isPainting);
3536 m_isPainting = true;
3538 // m_nodeToDraw is used to draw only one element (and its descendants)
3539 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
3540 RenderLayer* rootLayer = renderView->layer();
3543 RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(rootLayer->renderer());
3546 rootLayer->paint(p, rect, m_paintBehavior, eltRenderer);
3548 if (rootLayer->containsDirtyOverlayScrollbars())
3549 rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer);
3551 m_isPainting = false;
3553 if (flatteningPaint && isRootFrame)
3554 notifyWidgetsInAllFrames(DidPaintFlattened);
3556 m_paintBehavior = oldPaintBehavior;
3557 m_lastPaintTime = currentTime();
3559 // Regions may have changed as a result of the visibility/z-index of element changing.
3560 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
3561 if (document->annotatedRegionsDirty())
3562 updateAnnotatedRegions();
3565 if (isTopLevelPainter)
3566 sCurrentPaintTimeStamp = 0;
3568 InspectorInstrumentation::didPaint(renderView, p, rect);
3571 void FrameView::setPaintBehavior(PaintBehavior behavior)
3573 m_paintBehavior = behavior;
3576 PaintBehavior FrameView::paintBehavior() const
3578 return m_paintBehavior;
3581 bool FrameView::isPainting() const
3583 return m_isPainting;
3586 void FrameView::setNodeToDraw(Node* node)
3588 m_nodeToDraw = node;
3591 void FrameView::paintContentsForSnapshot(GraphicsContext* context, const IntRect& imageRect, SelectionInSnaphot shouldPaintSelection, CoordinateSpaceForSnapshot coordinateSpace)
3593 updateLayoutAndStyleIfNeededRecursive();
3595 // Cache paint behavior and set a new behavior appropriate for snapshots.
3596 PaintBehavior oldBehavior = paintBehavior();
3597 setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
3599 // If the snapshot should exclude selection, then we'll clear the current selection
3600 // in the render tree only. This will allow us to restore the selection from the DOM
3601 // after we paint the snapshot.
3602 if (shouldPaintSelection == ExcludeSelection) {
3603 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
3604 if (RenderView* root = frame->contentRenderer())
3605 root->clearSelection();
3609 if (coordinateSpace == DocumentCoordinates)
3610 paintContents(context, imageRect);
3612 // A snapshot in ViewCoordinates will include a scrollbar, and the snapshot will contain
3613 // whatever content the document is currently scrolled to.
3614 paint(context, imageRect);
3617 // Restore selection.
3618 if (shouldPaintSelection == ExcludeSelection) {
3619 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get()))
3620 frame->selection()->updateAppearance();
3623 // Restore cached paint behavior.
3624 setPaintBehavior(oldBehavior);
3627 void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
3629 if (context->paintingDisabled())
3632 if (m_frame->document()->printing())
3635 Page* page = m_frame->page();
3636 if (page->mainFrame() == m_frame) {
3637 if (page->chrome()->client()->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
3641 ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
3644 void FrameView::updateLayoutAndStyleIfNeededRecursive()
3646 // We have to crawl our entire tree looking for any FrameViews that need
3647 // layout and make sure they are up to date.
3648 // Mac actually tests for intersection with the dirty region and tries not to
3649 // update layout for frames that are outside the dirty region. Not only does this seem
3650 // pointless (since those frames will have set a zero timer to layout anyway), but
3651 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
3652 // region but then become included later by the second frame adding rects to the dirty region
3653 // when it lays out.
3655 m_frame->document()->updateStyleIfNeeded();
3660 // Grab a copy of the children() set, as it may be mutated by the following updateLayoutAndStyleIfNeededRecursive
3661 // calls, as they can potentially re-enter a layout of the parent frame view, which may add/remove scrollbars
3662 // and thus mutates the children() set.
3663 Vector<RefPtr<FrameView> > frameViews;
3664 collectFrameViewChildren(this, frameViews);
3666 const Vector<RefPtr<FrameView> >::iterator end = frameViews.end();
3667 for (Vector<RefPtr<FrameView> >::iterator it = frameViews.begin(); it != end; ++it)
3668 (*it)->updateLayoutAndStyleIfNeededRecursive();
3670 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
3671 // painting, so we need to flush out any deferred repaints too.
3672 flushDeferredRepaints();
3674 // When frame flattening is on, child frame can mark parent frame dirty. In such case, child frame
3675 // needs to call layout on parent frame recursively.
3676 // This assert ensures that parent frames are clean, when child frames finished updating layout and style.
3677 ASSERT(!needsLayout());
3680 void FrameView::setIsVisuallyNonEmpty()
3682 m_isVisuallyNonEmpty = true;
3683 adjustTiledBackingCoverage();
3686 void FrameView::enableAutoSizeMode(bool enable, const IntSize& minSize, const IntSize& maxSize)
3688 ASSERT(!enable || !minSize.isEmpty());
3689 ASSERT(minSize.width() <= maxSize.width());
3690 ASSERT(minSize.height() <= maxSize.height());
3692 if (m_shouldAutoSize == enable && m_minAutoSize == minSize && m_maxAutoSize == maxSize)
3695 m_shouldAutoSize = enable;
3696 m_minAutoSize = minSize;
3697 m_maxAutoSize = maxSize;
3698 m_didRunAutosize = false;
3702 if (m_shouldAutoSize)
3705 // Since autosize mode forces the scrollbar mode, change them to being auto.
3706 setVerticalScrollbarLock(false);
3707 setHorizontalScrollbarLock(false);
3708 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
3711 void FrameView::forceLayout(bool allowSubtree)
3713 layout(allowSubtree);
3716 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor, AdjustViewSizeOrNot shouldAdjustViewSize)
3718 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
3719 // the state of things before and after the layout
3720 if (RenderView* renderView = this->renderView()) {
3721 float pageLogicalWidth = renderView->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
3722 float pageLogicalHeight = renderView->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
3724 LayoutUnit flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
3725 LayoutUnit flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
3726 renderView->setLogicalWidth(flooredPageLogicalWidth);
3727 renderView->setPageLogicalHeight(flooredPageLogicalHeight);
3728 renderView->setNeedsLayoutAndPrefWidthsRecalc();
3731 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
3732 // page width when shrunk, we will lay out at maximum shrink and clip extra content.
3733 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
3734 // implementation should not do this!
3735 bool horizontalWritingMode = renderView->style()->isHorizontalWritingMode();
3736 const LayoutRect& documentRect = renderView->documentRect();
3737 LayoutUnit docLogicalWidth = horizontalWritingMode ? documentRect.width() : documentRect.height();
3738 if (docLogicalWidth > pageLogicalWidth) {
3739 int expectedPageWidth = std::min<float>(documentRect.width(), pageSize.width() * maximumShrinkFactor);
3740 int expectedPageHeight = std::min<float>(documentRect.height(), pageSize.height() * maximumShrinkFactor);
3741 FloatSize maxPageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(originalPageSize.width(), originalPageSize.height()), FloatSize(expectedPageWidth, expectedPageHeight));
3742 pageLogicalWidth = horizontalWritingMode ? maxPageSize.width() : maxPageSize.height();
3743 pageLogicalHeight = horizontalWritingMode ? maxPageSize.height() : maxPageSize.width();
3745 flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
3746 flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
3747 renderView->setLogicalWidth(flooredPageLogicalWidth);
3748 renderView->setPageLogicalHeight(flooredPageLogicalHeight);
3749 renderView->setNeedsLayoutAndPrefWidthsRecalc();
3752 const LayoutRect& updatedDocumentRect = renderView->documentRect();
3753 LayoutUnit docLogicalHeight = horizontalWritingMode ? updatedDocumentRect.height() : updatedDocumentRect.width();
3754 LayoutUnit docLogicalTop = horizontalWritingMode ? updatedDocumentRect.y() : updatedDocumentRect.x();
3755 LayoutUnit docLogicalRight = horizontalWritingMode ? updatedDocumentRect.maxX() : updatedDocumentRect.maxY();
3756 LayoutUnit clippedLogicalLeft = 0;
3757 if (!renderView->style()->isLeftToRightDirection())
3758 clippedLogicalLeft = docLogicalRight - pageLogicalWidth;
3759 LayoutRect overflow(clippedLogicalLeft, docLogicalTop, pageLogicalWidth, docLogicalHeight);
3761 if (!horizontalWritingMode)
3762 overflow = overflow.transposedRect();
3763 renderView->clearLayoutOverflow();
3764 renderView->addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
3768 if (shouldAdjustViewSize)
3772 void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
3774 RenderView* renderView = this->renderView();
3776 *newBottom = oldBottom;
3780 // Use a context with painting disabled.
3781 GraphicsContext context((PlatformGraphicsContext*)0);
3782 renderView->setTruncatedAt(static_cast<int>(floorf(oldBottom)));
3783 IntRect dirtyRect(0, static_cast<int>(floorf(oldTop)), renderView->layoutOverflowRect().maxX(), static_cast<int>(ceilf(oldBottom - oldTop)));
3784 renderView->setPrintRect(dirtyRect);
3785 renderView->layer()->paint(&context, dirtyRect);
3786 *newBottom = renderView->bestTruncatedAt();
3788 *newBottom = oldBottom;
3789 renderView->setPrintRect(IntRect());
3792 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
3794 IntRect rect = pixelSnappedIntRect(enclosingLayoutRect(renderer->localToAbsoluteQuad(FloatRect(rendererRect)).boundingBox()));
3796 // Convert from page ("absolute") to FrameView coordinates.
3797 if (!delegatesScrolling())
3798 rect.moveBy(-scrollPosition());
3803 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
3805 IntRect rect = viewRect;
3807 // Convert from FrameView coords into page ("absolute") coordinates.
3808 if (!delegatesScrolling())
3809 rect.moveBy(scrollPosition());
3811 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
3812 // move the rect for now.
3813 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), UseTransforms)));
3817 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
3819 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, UseTransforms));
3821 // Convert from page ("absolute") to FrameView coordinates.
3822 if (!delegatesScrolling())
3823 point.moveBy(-scrollPosition());
3827 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
3829 IntPoint point = viewPoint;
3831 // Convert from FrameView coords into page ("absolute") coordinates.
3832 if (!delegatesScrolling())
3833 point += IntSize(scrollX(), scrollY());
3835 return roundedIntPoint(renderer->absoluteToLocal(point, UseTransforms));
3838 IntRect FrameView::convertToContainingView(const IntRect& localRect) const
3840 if (const ScrollView* parentScrollView = parent()) {
3841 if (parentScrollView->isFrameView()) {
3842 const FrameView* parentView = toFrameView(parentScrollView);
3843 // Get our renderer in the parent view
3844 RenderPart* renderer = m_frame->ownerRenderer();
3848 IntRect rect(localRect);
3849 // Add borders and padding??
3850 rect.move(renderer->borderLeft() + renderer->paddingLeft(),
3851 renderer->borderTop() + renderer->paddingTop());
3852 return parentView->convertFromRenderer(renderer, rect);
3855 return Widget::convertToContainingView(localRect);
3861 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
3863 if (const ScrollView* parentScrollView = parent()) {
3864 if (parentScrollView->isFrameView()) {
3865 const FrameView* parentView = toFrameView(parentScrollView);
3867 // Get our renderer in the parent view
3868 RenderPart* renderer = m_frame->ownerRenderer();
3872 IntRect rect = parentView->convertToRenderer(renderer, parentRect);
3873 // Subtract borders and padding
3874 rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
3875 -renderer->borderTop() - renderer->paddingTop());
3879 return Widget::convertFromContainingView(parentRect);
3885 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
3887 if (const ScrollView* parentScrollView = parent()) {
3888 if (parentScrollView->isFrameView()) {
3889 const FrameView* parentView = toFrameView(parentScrollView);
3891 // Get our renderer in the parent view
3892 RenderPart* renderer = m_frame->ownerRenderer();
3896 IntPoint point(localPoint);
3898 // Add borders and padding
3899 point.move(renderer->borderLeft() + renderer->paddingLeft(),
3900 renderer->borderTop() + renderer->paddingTop());
3901 return parentView->convertFromRenderer(renderer, point);
3904 return Widget::convertToContainingView(localPoint);
3910 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
3912 if (const ScrollView* parentScrollView = parent()) {
3913 if (parentScrollView->isFrameView()) {
3914 const FrameView* parentView = toFrameView(parentScrollView);
3916 // Get our renderer in the parent view
3917 RenderPart* renderer = m_frame->ownerRenderer();
3921 IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
3922 // Subtract borders and padding
3923 point.move(-renderer->borderLeft() - renderer->paddingLeft(),
3924 -renderer->borderTop() - renderer->paddingTop());
3928 return Widget::convertFromContainingView(parentPoint);
3935 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
3937 s_normalDeferredRepaintDelay = p;
3940 // Negative value would mean that first few repaints happen without a delay
3941 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)
3943 s_initialDeferredRepaintDelayDuringLoading = p;
3946 // The delay grows on each repaint to this maximum value
3947 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)
3949 s_maxDeferredRepaintDelayDuringLoading = p;
3952 // On each repaint the delay increases by this amount
3953 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)
3955 s_deferredRepaintDelayIncrementDuringLoading = p;
3958 void FrameView::setTracksRepaints(bool trackRepaints)
3960 if (trackRepaints == m_isTrackingRepaints)
3963 // Force layout to flush out any pending repaints.
3964 if (trackRepaints) {
3965 if (frame() && frame()->document())
3966 frame()->document()->updateLayout();
3969 #if USE(ACCELERATED_COMPOSITING)
3970 for (Frame* frame = m_frame->tree()->top(); frame; frame = frame->tree()->traverseNext()) {
3971 if (RenderView* renderView = frame->contentRenderer())
3972 renderView->compositor()->setTracksRepaints(trackRepaints);
3976 resetTrackedRepaints();
3977 m_isTrackingRepaints = trackRepaints;
3980 void FrameView::resetTrackedRepaints()
3982 m_trackedRepaintRects.clear();
3983 #if USE(ACCELERATED_COMPOSITING)
3984 if (RenderView* renderView = this->renderView())
3985 renderView->compositor()->resetTrackedRepaintRects();
3989 String FrameView::trackedRepaintRectsAsText() const
3991 if (frame() && frame()->document())
3992 frame()->document()->updateLayout();
3995 if (!m_trackedRepaintRects.isEmpty()) {
3996 ts << "(repaint rects\n";
3997 for (size_t i = 0; i < m_trackedRepaintRects.size(); ++i)
3998 ts << " (rect " << m_trackedRepaintRects[i].x() << " " << m_trackedRepaintRects[i].y() << " " << m_trackedRepaintRects[i].width() << " " << m_trackedRepaintRects[i].height() << ")\n";
4001 return ts.release();
4004 bool FrameView::addScrollableArea(ScrollableArea* scrollableArea)
4006 if (!m_scrollableAreas)
4007 m_scrollableAreas = adoptPtr(new ScrollableAreaSet);
4008 return m_scrollableAreas->add(scrollableArea).isNewEntry;
4011 bool FrameView::removeScrollableArea(ScrollableArea* scrollableArea)
4013 if (!m_scrollableAreas)
4016 ScrollableAreaSet::iterator it = m_scrollableAreas->find(scrollableArea);
4017 if (it == m_scrollableAreas->end())
4020 m_scrollableAreas->remove(it);
4024 bool FrameView::containsScrollableArea(ScrollableArea* scrollableArea) const
4026 if (!m_scrollableAreas)
4028 return m_scrollableAreas->contains(scrollableArea);
4031 void FrameView::removeChild(Widget* widget)
4033 if (widget->isFrameView())
4034 removeScrollableArea(toFrameView(widget));
4036 ScrollView::removeChild(widget);
4039 bool FrameView::wheelEvent(const PlatformWheelEvent& wheelEvent)
4041 // Note that to allow for rubber-band over-scroll behavior, even non-scrollable views
4042 // should handle wheel events.
4043 #if !ENABLE(RUBBER_BANDING)
4044 if (!isScrollable())
4048 if (delegatesScrolling()) {
4049 IntSize offset = scrollOffset();
4050 IntSize newOffset = IntSize(offset.width() - wheelEvent.deltaX(), offset.height() - wheelEvent.deltaY());
4051 if (offset != newOffset) {
4052 ScrollView::scrollTo(newOffset);
4053 scrollPositionChanged();
4054 frame()->loader()->client()->didChangeScrollOffset();
4059 // We don't allow mouse wheeling to happen in a ScrollView that has had its scrollbars explicitly disabled.
4060 if (!canHaveScrollbars())
4064 if (platformWidget())
4068 #if ENABLE(THREADED_SCROLLING)
4069 if (Page* page = m_frame->page()) {
4070 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
4071 if (scrollingCoordinator->coordinatesScrollingForFrameView(this))
4072 return scrollingCoordinator->handleWheelEvent(this, wheelEvent);
4077 return ScrollableArea::handleWheelEvent(wheelEvent);
4081 bool FrameView::isVerticalDocument() const
4083 RenderView* renderView = this->renderView();
4087 return renderView->style()->isHorizontalWritingMode();
4090 bool FrameView::isFlippedDocument() const
4092 RenderView* renderView = this->renderView();
4096 return renderView->style()->isFlippedBlocksWritingMode();
4099 void FrameView::notifyWidgetsInAllFrames(WidgetNotification notification)
4101 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
4102 if (RenderView* root = frame->contentRenderer())
4103 root->notifyWidgets(notification);
4107 AXObjectCache* FrameView::axObjectCache() const
4109 if (frame() && frame()->document())
4110 return frame()->document()->existingAXObjectCache();
4114 void FrameView::setScrollingPerformanceLoggingEnabled(bool flag)
4116 #if USE(ACCELERATED_COMPOSITING)
4117 if (TiledBacking* tiledBacking = this->tiledBacking())
4118 tiledBacking->setScrollingPerformanceLoggingEnabled(flag);
4124 } // namespace WebCore