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 "CSSStyleSelector.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"
42 #include "FrameActionScheduler.h"
43 #include "FrameLoader.h"
44 #include "FrameLoaderClient.h"
45 #include "FrameTree.h"
46 #include "GraphicsContext.h"
47 #include "HTMLDocument.h"
48 #include "HTMLFrameElement.h"
49 #include "HTMLFrameSetElement.h"
50 #include "HTMLNames.h"
51 #include "HTMLPlugInImageElement.h"
52 #include "InspectorInstrumentation.h"
53 #include "OverflowEvent.h"
54 #include "RenderArena.h"
55 #include "RenderEmbeddedObject.h"
56 #include "RenderFullScreen.h"
57 #include "RenderLayer.h"
58 #include "RenderPart.h"
59 #include "RenderScrollbar.h"
60 #include "RenderScrollbarPart.h"
61 #include "RenderTheme.h"
62 #include "RenderView.h"
63 #include "ScrollAnimator.h"
65 #include "TextResourceDecoder.h"
66 #include <wtf/CurrentTime.h>
68 #if USE(ACCELERATED_COMPOSITING)
69 #include "RenderLayerCompositor.h"
70 #if PLATFORM(CHROMIUM)
71 #include "TraceEvent.h"
76 #include "RenderSVGRoot.h"
77 #include "SVGDocument.h"
78 #include "SVGSVGElement.h"
81 #if USE(TILED_BACKING_STORE)
82 #include "TiledBackingStore.h"
87 using namespace HTMLNames;
89 double FrameView::sCurrentPaintTimeStamp = 0.0;
91 // REPAINT_THROTTLING now chooses default values for throttling parameters.
92 // Should be removed when applications start using runtime configuration.
93 #if ENABLE(REPAINT_THROTTLING)
95 double FrameView::s_deferredRepaintDelay = 0.025;
96 // Negative value would mean that first few repaints happen without a delay
97 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
98 // The delay grows on each repaint to this maximum value
99 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
100 // On each repaint the delay increses by this amount
101 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
103 // FIXME: Repaint throttling could be good to have on all platform.
104 // The balance between CPU use and repaint frequency will need some tuning for desktop.
105 // More hooks may be needed to reset the delay on things like GIF and CSS animations.
106 double FrameView::s_deferredRepaintDelay = 0;
107 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
108 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
109 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
112 // The maximum number of updateWidgets iterations that should be done before returning.
113 static const unsigned maxUpdateWidgetsIterations = 2;
115 static inline RenderView* rootRenderer(const FrameView* view)
117 return view->frame() ? view->frame()->contentRenderer() : 0;
120 FrameView::FrameView(Frame* frame)
122 , m_canHaveScrollbars(true)
123 , m_slowRepaintObjectCount(0)
124 , m_fixedObjectCount(0)
125 , m_layoutTimer(this, &FrameView::layoutTimerFired)
128 , m_inLayoutParentView(false)
130 , m_hasPendingPostLayoutTasks(false)
131 , m_inSynchronousPostLayout(false)
132 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
133 , m_isTransparent(false)
134 , m_baseBackgroundColor(Color::white)
135 , m_mediaType("screen")
136 , m_actionScheduler(adoptPtr(new FrameActionScheduler))
137 , m_overflowStatusDirty(true)
138 , m_viewportRenderer(0)
139 , m_wasScrolledByUser(false)
140 , m_inProgrammaticScroll(false)
141 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
142 , m_isTrackingRepaints(false)
143 , m_shouldUpdateWhileOffscreen(true)
144 , m_deferSetNeedsLayouts(0)
145 , m_setNeedsLayoutWasDeferred(false)
151 if (Page* page = m_frame->page()) {
153 m_page->addScrollableArea(this);
155 if (m_frame == m_page->mainFrame()) {
156 ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed);
157 ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed);
163 PassRefPtr<FrameView> FrameView::create(Frame* frame)
165 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
167 return view.release();
170 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize)
172 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
173 view->Widget::setFrameRect(LayoutRect(view->location(), initialSize));
175 return view.release();
178 FrameView::~FrameView()
180 if (m_hasPendingPostLayoutTasks) {
181 m_postLayoutTasksTimer.stop();
182 m_actionScheduler->clear();
185 if (AXObjectCache::accessibilityEnabled() && axObjectCache())
186 axObjectCache()->remove(this);
190 // Custom scrollbars should already be destroyed at this point
191 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
192 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
194 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
195 setHasVerticalScrollbar(false);
197 ASSERT(!m_scrollCorner);
198 ASSERT(m_actionScheduler->isEmpty());
201 m_page->removeScrollableArea(this);
204 ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
205 RenderPart* renderer = m_frame->ownerRenderer();
206 if (renderer && renderer->widget() == this)
207 renderer->setWidget(0);
211 void FrameView::reset()
213 m_cannotBlitToWindow = false;
214 m_isOverlapped = false;
215 m_contentIsOpaque = false;
218 m_layoutTimer.stop();
220 m_delayedLayout = false;
221 m_doFullRepaint = true;
222 m_layoutSchedulingEnabled = true;
224 m_inSynchronousPostLayout = false;
225 m_hasPendingPostLayoutTasks = false;
227 m_nestedLayoutCount = 0;
228 m_postLayoutTasksTimer.stop();
229 m_firstLayout = true;
230 m_firstLayoutCallbackPending = false;
231 m_wasScrolledByUser = false;
232 m_lastLayoutSize = LayoutSize();
233 m_lastZoomFactor = 1.0f;
234 m_deferringRepaints = 0;
236 m_repaintRects.clear();
237 m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading;
238 m_deferredRepaintTimer.stop();
239 m_isTrackingRepaints = false;
240 m_trackedRepaintRects.clear();
242 m_paintBehavior = PaintBehaviorNormal;
243 m_isPainting = false;
244 m_visuallyNonEmptyCharacterCount = 0;
245 m_visuallyNonEmptyPixelCount = 0;
246 m_isVisuallyNonEmpty = false;
247 m_firstVisuallyNonEmptyLayoutCallbackPending = true;
248 m_maintainScrollPositionAnchor = 0;
251 bool FrameView::isFrameView() const
256 void FrameView::clearFrame()
261 void FrameView::resetScrollbars()
263 // Reset the document's scrollbars back to our defaults before we yield the floor.
264 m_firstLayout = true;
265 setScrollbarsSuppressed(true);
266 if (m_canHaveScrollbars)
267 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
269 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
270 setScrollbarsSuppressed(false);
273 void FrameView::resetScrollbarsAndClearContentsSize()
277 setScrollbarsSuppressed(true);
278 setContentsSize(IntSize());
279 setScrollbarsSuppressed(false);
282 void FrameView::init()
286 m_margins = LayoutSize(-1, -1); // undefined
287 m_size = LayoutSize();
289 // Propagate the marginwidth/height and scrolling modes to the view.
290 Element* ownerElement = m_frame ? m_frame->ownerElement() : 0;
291 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
292 HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement);
293 if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
294 setCanHaveScrollbars(false);
295 LayoutUnit marginWidth = frameElt->marginWidth();
296 LayoutUnit marginHeight = frameElt->marginHeight();
297 // FIXME: Change to roughlyEquals or >= 0 when we move to floats.
298 // See https://bugs.webkit.org/show_bug.cgi?id=66148
299 if (marginWidth != -1)
300 setMarginWidth(marginWidth);
301 if (marginHeight != -1)
302 setMarginHeight(marginHeight);
306 void FrameView::detachCustomScrollbars()
311 Scrollbar* horizontalBar = horizontalScrollbar();
312 if (horizontalBar && horizontalBar->isCustomScrollbar())
313 setHasHorizontalScrollbar(false);
315 Scrollbar* verticalBar = verticalScrollbar();
316 if (verticalBar && verticalBar->isCustomScrollbar())
317 setHasVerticalScrollbar(false);
319 if (m_scrollCorner) {
320 m_scrollCorner->destroy();
325 void FrameView::didAddHorizontalScrollbar(Scrollbar* scrollbar)
327 if (m_frame && m_frame->document())
328 m_frame->document()->didAddWheelEventHandler();
329 ScrollView::didAddHorizontalScrollbar(scrollbar);
332 void FrameView::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
334 ScrollView::willRemoveHorizontalScrollbar(scrollbar);
335 // FIXME: maybe need a separate ScrollableArea::didRemoveHorizontalScrollbar callback?
336 if (m_frame && m_frame->document())
337 m_frame->document()->didRemoveWheelEventHandler();
340 void FrameView::recalculateScrollbarOverlayStyle()
342 ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle();
343 ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault;
345 Color backgroundColor = documentBackgroundColor();
346 if (backgroundColor.isValid()) {
347 // Reduce the background color from RGB to a lightness value
348 // and determine which scrollbar style to use based on a lightness
350 double hue, saturation, lightness;
351 backgroundColor.getHSL(hue, saturation, lightness);
353 overlayStyle = ScrollbarOverlayStyleLight;
356 if (oldOverlayStyle != overlayStyle)
357 setScrollbarOverlayStyle(overlayStyle);
360 void FrameView::clear()
362 setCanBlitOnScroll(true);
367 if (RenderPart* renderer = m_frame->ownerRenderer())
368 renderer->viewCleared();
371 setScrollbarsSuppressed(true);
374 bool FrameView::didFirstLayout() const
376 return !m_firstLayout;
379 void FrameView::invalidateRect(const LayoutRect& rect)
383 hostWindow()->invalidateContentsAndWindow(rect, false /*immediate*/);
390 RenderPart* renderer = m_frame->ownerRenderer();
394 LayoutRect repaintRect = rect;
395 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
396 renderer->borderTop() + renderer->paddingTop());
397 renderer->repaintRectangle(repaintRect);
400 void FrameView::setFrameRect(const LayoutRect& newRect)
402 LayoutRect oldRect = frameRect();
403 if (newRect == oldRect)
406 ScrollView::setFrameRect(newRect);
408 #if USE(ACCELERATED_COMPOSITING)
409 if (RenderView* root = rootRenderer(this)) {
410 if (root->usesCompositing())
411 root->compositor()->frameViewDidChangeSize();
416 #if ENABLE(REQUEST_ANIMATION_FRAME)
417 void FrameView::scheduleAnimation()
420 hostWindow()->scheduleAnimation();
424 void FrameView::setMarginWidth(LayoutUnit w)
426 // make it update the rendering area when set
427 m_margins.setWidth(w);
430 void FrameView::setMarginHeight(LayoutUnit h)
432 // make it update the rendering area when set
433 m_margins.setHeight(h);
436 bool FrameView::avoidScrollbarCreation() const
440 // with frame flattening no subframe can have scrollbars
441 // but we also cannot turn scrollbars of as we determine
442 // our flattening policy using that.
444 if (!m_frame->ownerElement())
447 if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
453 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
455 m_canHaveScrollbars = canHaveScrollbars;
456 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
459 void FrameView::updateCanHaveScrollbars()
463 scrollbarModes(hMode, vMode);
464 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
465 setCanHaveScrollbars(false);
467 setCanHaveScrollbars(true);
470 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
472 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
473 Document* doc = m_frame->document();
475 // Try the <body> element first as a scrollbar source.
476 Element* body = doc ? doc->body() : 0;
477 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
478 return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderer()->enclosingBox());
480 // If the <body> didn't have a custom style, then the root element might.
481 Element* docElement = doc ? doc->documentElement() : 0;
482 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
483 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox());
485 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
486 RenderPart* frameRenderer = m_frame->ownerRenderer();
487 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
488 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
490 // Nobody set a custom style, so we just use a native scrollbar.
491 return ScrollView::createScrollbar(orientation);
494 void FrameView::setContentsSize(const LayoutSize& size)
496 if (size == contentsSize())
499 m_deferSetNeedsLayouts++;
501 ScrollView::setContentsSize(size);
502 scrollAnimator()->contentsResized();
504 Page* page = frame() ? frame()->page() : 0;
508 page->chrome()->contentsSizeChanged(frame(), size); //notify only
510 m_deferSetNeedsLayouts--;
512 if (!m_deferSetNeedsLayouts)
513 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
516 void FrameView::adjustViewSize()
518 RenderView* root = rootRenderer(this);
522 ASSERT(m_frame->view() == this);
524 const LayoutRect& rect = root->documentRect();
525 const LayoutSize& size = rect.size();
526 ScrollView::setScrollOrigin(LayoutPoint(-rect.x(), -rect.y()), !m_frame->document()->printing(), size == contentsSize());
528 setContentsSize(size);
531 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
533 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
534 // overflow:hidden and overflow:scroll on <body> as applying to the document's
535 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
536 // use the root element.
538 // To combat the inability to scroll on a page with overflow:hidden on the root when scaled, disregard hidden when
539 // there is a frameScaleFactor that is greater than one on the main frame.
541 bool overrideHidden = m_frame->page() && m_frame->page()->mainFrame() == m_frame && m_frame->frameScaleFactor() > 1;
543 switch (o->style()->overflowX()) {
546 hMode = ScrollbarAuto;
548 hMode = ScrollbarAlwaysOff;
551 hMode = ScrollbarAlwaysOn;
554 hMode = ScrollbarAuto;
557 // Don't set it at all.
561 switch (o->style()->overflowY()) {
564 vMode = ScrollbarAuto;
566 vMode = ScrollbarAlwaysOff;
569 vMode = ScrollbarAlwaysOn;
572 vMode = ScrollbarAuto;
575 // Don't set it at all.
579 m_viewportRenderer = o;
582 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode)
584 m_viewportRenderer = 0;
586 const HTMLFrameOwnerElement* owner = m_frame->ownerElement();
587 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
588 hMode = ScrollbarAlwaysOff;
589 vMode = ScrollbarAlwaysOff;
593 if (m_canHaveScrollbars) {
594 hMode = ScrollbarAuto;
595 vMode = ScrollbarAuto;
597 hMode = ScrollbarAlwaysOff;
598 vMode = ScrollbarAlwaysOff;
602 Document* document = m_frame->document();
603 Node* documentElement = document->documentElement();
604 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
605 Node* body = document->body();
606 if (body && body->renderer()) {
607 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
608 vMode = ScrollbarAlwaysOff;
609 hMode = ScrollbarAlwaysOff;
610 } else if (body->hasTagName(bodyTag)) {
611 // It's sufficient to just check the X overflow,
612 // since it's illegal to have visible in only one direction.
613 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
614 applyOverflowToViewport(o, hMode, vMode);
616 } else if (rootRenderer) {
618 if (!documentElement->isSVGElement())
619 applyOverflowToViewport(rootRenderer, hMode, vMode);
621 applyOverflowToViewport(rootRenderer, hMode, vMode);
627 #if ENABLE(FULLSCREEN_API) && USE(ACCELERATED_COMPOSITING)
628 static bool isDocumentRunningFullScreenAnimation(Document* document)
630 return document->webkitIsFullScreen() && document->fullScreenRenderer() && document->isAnimatingFullScreen();
634 #if USE(ACCELERATED_COMPOSITING)
635 void FrameView::updateCompositingLayers()
637 RenderView* root = rootRenderer(this);
641 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
642 root->compositor()->cacheAcceleratedCompositingFlags();
643 root->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange);
645 #if ENABLE(FULLSCREEN_API)
646 Document* document = m_frame->document();
647 if (isDocumentRunningFullScreenAnimation(document))
648 root->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange, document->fullScreenRenderer()->layer());
652 void FrameView::clearBackingStores()
654 RenderView* root = rootRenderer(this);
658 RenderLayerCompositor* compositor = root->compositor();
659 ASSERT(compositor->inCompositingMode());
660 compositor->enableCompositingMode(false);
661 compositor->clearBackingForAllLayers();
664 void FrameView::restoreBackingStores()
666 RenderView* root = rootRenderer(this);
670 RenderLayerCompositor* compositor = root->compositor();
671 compositor->enableCompositingMode(true);
672 compositor->updateCompositingLayers();
675 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
677 RenderView* root = rootRenderer(this);
680 return root->compositor()->layerForHorizontalScrollbar();
683 GraphicsLayer* FrameView::layerForVerticalScrollbar() const
685 RenderView* root = rootRenderer(this);
688 return root->compositor()->layerForVerticalScrollbar();
691 GraphicsLayer* FrameView::layerForScrollCorner() const
693 RenderView* root = rootRenderer(this);
696 return root->compositor()->layerForScrollCorner();
699 #if PLATFORM(CHROMIUM) && ENABLE(RUBBER_BANDING)
700 GraphicsLayer* FrameView::layerForOverhangAreas() const
702 RenderView* root = rootRenderer(this);
705 return root->compositor()->layerForOverhangAreas();
709 bool FrameView::syncCompositingStateForThisFrame(Frame* rootFrameForSync)
711 RenderView* root = rootRenderer(this);
713 return true; // We don't want to keep trying to update layers if we have no renderer.
715 ASSERT(m_frame->view() == this);
717 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
718 // layer content to occur before layout has happened, which will cause paintContents() to bail.
722 root->compositor()->flushPendingLayerChanges(rootFrameForSync == m_frame);
724 #if ENABLE(FULLSCREEN_API)
725 // The fullScreenRenderer's graphicsLayer has been re-parented, and the above recursive syncCompositingState
726 // call will not cause the subtree under it to repaint. Explicitly call the syncCompositingState on
727 // the fullScreenRenderer's graphicsLayer here:
728 Document* document = m_frame->document();
729 if (isDocumentRunningFullScreenAnimation(document)) {
730 RenderLayerBacking* backing = document->fullScreenRenderer()->layer()->backing();
731 if (GraphicsLayer* fullScreenLayer = backing->graphicsLayer()) {
732 // FIXME: Passing frameRect() is correct only when RenderLayerCompositor uses a ScrollLayer (as in WebKit2)
733 // otherwise, the passed clip rect needs to take scrolling into account
734 fullScreenLayer->syncCompositingState(frameRect());
741 void FrameView::setNeedsOneShotDrawingSynchronization()
743 Page* page = frame() ? frame()->page() : 0;
745 page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
748 #endif // USE(ACCELERATED_COMPOSITING)
750 bool FrameView::hasCompositedContent() const
752 #if USE(ACCELERATED_COMPOSITING)
753 if (RenderView* root = rootRenderer(this))
754 return root->compositor()->inCompositingMode();
759 bool FrameView::hasCompositedContentIncludingDescendants() const
761 #if USE(ACCELERATED_COMPOSITING)
762 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
763 RenderView* renderView = frame->contentRenderer();
764 RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0;
766 if (compositor->inCompositingMode())
769 if (!RenderLayerCompositor::allowsIndependentlyCompositedFrames(this))
777 bool FrameView::hasCompositingAncestor() const
779 #if USE(ACCELERATED_COMPOSITING)
780 for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) {
781 if (FrameView* view = frame->view()) {
782 if (view->hasCompositedContent())
790 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
791 void FrameView::enterCompositingMode()
793 #if USE(ACCELERATED_COMPOSITING)
794 if (RenderView* root = rootRenderer(this)) {
795 root->compositor()->enableCompositingMode();
797 root->compositor()->scheduleCompositingLayerUpdate();
802 bool FrameView::isEnclosedInCompositingLayer() const
804 #if USE(ACCELERATED_COMPOSITING)
805 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
806 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
809 if (FrameView* parentView = parentFrameView())
810 return parentView->isEnclosedInCompositingLayer();
815 bool FrameView::syncCompositingStateIncludingSubframes()
817 #if USE(ACCELERATED_COMPOSITING)
818 bool allFramesSynced = syncCompositingStateForThisFrame(m_frame.get());
820 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame.get())) {
821 bool synced = child->view()->syncCompositingStateForThisFrame(m_frame.get());
822 allFramesSynced &= synced;
824 return allFramesSynced;
825 #else // USE(ACCELERATED_COMPOSITING)
830 bool FrameView::isSoftwareRenderable() const
832 #if USE(ACCELERATED_COMPOSITING)
833 RenderView* root = rootRenderer(this);
837 return !root->compositor()->has3DContent();
843 void FrameView::didMoveOnscreen()
845 RenderView* root = rootRenderer(this);
847 root->didMoveOnscreen();
848 scrollAnimator()->contentAreaDidShow();
851 void FrameView::willMoveOffscreen()
853 RenderView* root = rootRenderer(this);
855 root->willMoveOffscreen();
856 scrollAnimator()->contentAreaDidHide();
859 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
861 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
864 static inline void collectFrameViewChildren(FrameView* frameView, Vector<RefPtr<FrameView> >& frameViews)
866 const HashSet<RefPtr<Widget> >* viewChildren = frameView->children();
867 ASSERT(viewChildren);
869 const HashSet<RefPtr<Widget> >::iterator end = viewChildren->end();
870 for (HashSet<RefPtr<Widget> >::iterator current = viewChildren->begin(); current != end; ++current) {
871 Widget* widget = (*current).get();
872 if (widget->isFrameView())
873 frameViews.append(static_cast<FrameView*>(widget));
877 inline void FrameView::forceLayoutParentViewIfNeeded()
880 if (m_inLayoutParentView)
883 RenderPart* ownerRenderer = m_frame->ownerRenderer();
884 if (!ownerRenderer || !ownerRenderer->frame())
887 RenderBox* contentBox = embeddedContentBox();
891 RenderSVGRoot* svgRoot = toRenderSVGRoot(contentBox);
892 if (!svgRoot->needsSizeNegotiationWithHostDocument())
895 m_inLayoutParentView = true;
897 // Clear needs-size-negotiation flag in RenderSVGRoot, so the next call to our
898 // layout() method won't fire the size negotiation logic again.
899 svgRoot->scheduledSizeNegotiationWithHostDocument();
900 ASSERT(!svgRoot->needsSizeNegotiationWithHostDocument());
902 // Mark the owner renderer as needing layout.
903 ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc();
905 // Immediately relayout the child widgets, which can now calculate the SVG documents
906 // intrinsic size, negotiating with the parent object/embed/iframe.
907 RenderView* rootView = ownerRenderer->frame()->contentRenderer();
909 rootView->updateWidgetPositions();
911 // Synchronously enter layout, to layout the view containing the host object/embed/iframe.
912 FrameView* frameView = ownerRenderer->frame()->view();
916 m_inLayoutParentView = false;
920 void FrameView::layout(bool allowSubtree)
925 bool inSubframeLayoutWithFrameFlattening = parent() && m_frame->settings() && m_frame->settings()->frameFlatteningEnabled();
927 if (inSubframeLayoutWithFrameFlattening) {
928 if (parent()->isFrameView()) {
929 FrameView* parentView = static_cast<FrameView*>(parent());
930 if (!parentView->m_nestedLayoutCount) {
931 while (parentView->parent() && parentView->parent()->isFrameView())
932 parentView = static_cast<FrameView*>(parentView->parent());
933 parentView->layout(allowSubtree);
939 m_layoutTimer.stop();
940 m_delayedLayout = false;
941 m_setNeedsLayoutWasDeferred = false;
943 // Protect the view from being deleted during layout (in recalcStyle)
944 RefPtr<FrameView> protector(this);
947 // FIXME: Do we need to set m_size.width here?
948 // FIXME: Should we set m_size.height here too?
949 m_size.setWidth(layoutWidth());
953 // we shouldn't enter layout() while painting
954 ASSERT(!isPainting());
958 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
960 if (!allowSubtree && m_layoutRoot) {
961 m_layoutRoot->markContainingBlocksForLayout(false);
965 ASSERT(m_frame->view() == this);
967 Document* document = m_frame->document();
969 m_layoutSchedulingEnabled = false;
971 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_hasPendingPostLayoutTasks && !inSubframeLayoutWithFrameFlattening) {
972 // This is a new top-level layout. If there are any remaining tasks from the previous
973 // layout, finish them now.
974 m_inSynchronousPostLayout = true;
975 m_postLayoutTasksTimer.stop();
976 performPostLayoutTasks();
977 m_inSynchronousPostLayout = false;
980 // Viewport-dependent media queries may cause us to need completely different style information.
982 if (document->styleSelector()->affectedByViewportChange())
983 document->styleSelectorChanged(RecalcStyleImmediately);
985 // Always ensure our style info is up-to-date. This can happen in situations where
986 // the layout beats any sort of style recalc update that needs to occur.
987 document->updateStyleIfNeeded();
989 bool subtree = m_layoutRoot;
991 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
992 // so there's no point to continuing to layout
993 if (protector->hasOneRef())
996 RenderObject* root = subtree ? m_layoutRoot : document->renderer();
998 // FIXME: Do we need to set m_size here?
999 m_layoutSchedulingEnabled = true;
1003 FontCachePurgePreventer fontCachePurgePreventer;
1005 m_nestedLayoutCount++;
1007 if (!m_layoutRoot) {
1008 Document* document = m_frame->document();
1009 Node* documentElement = document->documentElement();
1010 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
1011 Node* body = document->body();
1012 if (body && body->renderer()) {
1013 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
1014 body->renderer()->setChildNeedsLayout(true);
1015 } else if (body->hasTagName(bodyTag)) {
1016 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
1017 body->renderer()->setChildNeedsLayout(true);
1019 } else if (rootRenderer) {
1021 if (documentElement->isSVGElement()) {
1022 if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight()))
1023 rootRenderer->setChildNeedsLayout(true);
1028 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1029 if (m_firstLayout && !m_frame->ownerElement())
1030 printf("Elapsed time before first layout: %d\n", document->elapsedTime());
1034 ScrollbarMode hMode;
1035 ScrollbarMode vMode;
1036 calculateScrollbarModesForLayout(hMode, vMode);
1038 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
1041 // Now set our scrollbar state for the layout.
1042 ScrollbarMode currentHMode = horizontalScrollbarMode();
1043 ScrollbarMode currentVMode = verticalScrollbarMode();
1045 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
1046 if (m_firstLayout) {
1047 setScrollbarsSuppressed(true);
1049 m_firstLayout = false;
1050 m_firstLayoutCallbackPending = true;
1051 m_lastLayoutSize = LayoutSize(width(), height());
1052 m_lastZoomFactor = root->style()->zoom();
1054 // Set the initial vMode to AlwaysOn if we're auto.
1055 if (vMode == ScrollbarAuto)
1056 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
1057 // Set the initial hMode to AlwaysOff if we're auto.
1058 if (hMode == ScrollbarAuto)
1059 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
1061 setScrollbarModes(hMode, vMode);
1062 setScrollbarsSuppressed(false, true);
1064 setScrollbarModes(hMode, vMode);
1067 LayoutSize oldSize = m_size;
1069 m_size = LayoutSize(layoutWidth(), layoutHeight());
1071 if (oldSize != m_size) {
1072 m_doFullRepaint = true;
1073 if (!m_firstLayout) {
1074 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
1075 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
1076 if (bodyRenderer && bodyRenderer->stretchesToViewport())
1077 bodyRenderer->setChildNeedsLayout(true);
1078 else if (rootRenderer && rootRenderer->stretchesToViewport())
1079 rootRenderer->setChildNeedsLayout(true);
1084 RenderLayer* layer = root->enclosingLayer();
1086 m_actionScheduler->pause();
1089 bool disableLayoutState = false;
1091 RenderView* view = root->view();
1092 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
1093 view->pushLayoutState(root);
1095 LayoutStateDisabler layoutStateDisabler(disableLayoutState ? root->view() : 0);
1098 beginDeferredRepaints();
1100 endDeferredRepaints();
1104 root->view()->popLayoutState(root);
1108 m_layoutSchedulingEnabled = true;
1110 if (!subtree && !toRenderView(root)->printing())
1113 // Now update the positions of all layers.
1114 beginDeferredRepaints();
1115 bool hasLayerOffset;
1116 LayoutPoint offsetFromRoot = layer->computeOffsetFromRoot(hasLayerOffset);
1117 if (m_doFullRepaint)
1118 root->view()->repaint(); // FIXME: This isn't really right, since the RenderView doesn't fully encompass the visibleContentRect(). It just happens
1119 // to work out most of the time, since first layouts and printing don't have you scrolled anywhere.
1120 layer->updateLayerPositions(hasLayerOffset ? &offsetFromRoot : 0,
1121 (m_doFullRepaint ? 0 : RenderLayer::CheckForRepaint)
1122 | RenderLayer::IsCompositingUpdateRoot
1123 | RenderLayer::UpdateCompositingLayers);
1124 endDeferredRepaints();
1126 #if USE(ACCELERATED_COMPOSITING)
1127 updateCompositingLayers();
1132 #if PLATFORM(MAC) || PLATFORM(CHROMIUM)
1133 if (AXObjectCache::accessibilityEnabled())
1134 root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true);
1136 #if ENABLE(DASHBOARD_SUPPORT)
1137 updateDashboardRegions();
1140 ASSERT(!root->needsLayout());
1142 updateCanBlitOnScrollRecursively();
1144 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1145 updateOverflowStatus(layoutWidth() < contentsWidth(),
1146 layoutHeight() < contentsHeight());
1148 if (!m_hasPendingPostLayoutTasks) {
1149 if (!m_inSynchronousPostLayout) {
1150 if (inSubframeLayoutWithFrameFlattening) {
1151 if (RenderView* root = rootRenderer(this))
1152 root->updateWidgetPositions();
1154 m_inSynchronousPostLayout = true;
1155 // Calls resumeScheduledEvents()
1156 performPostLayoutTasks();
1157 m_inSynchronousPostLayout = false;
1161 if (!m_hasPendingPostLayoutTasks && (needsLayout() || m_inSynchronousPostLayout || inSubframeLayoutWithFrameFlattening)) {
1162 // If we need layout or are already in a synchronous call to postLayoutTasks(),
1163 // defer widget updates and event dispatch until after we return. postLayoutTasks()
1164 // can make us need to update again, and we can get stuck in a nasty cycle unless
1165 // we call it through the timer here.
1166 m_hasPendingPostLayoutTasks = true;
1167 m_postLayoutTasksTimer.startOneShot(0);
1168 if (needsLayout()) {
1169 m_actionScheduler->pause();
1174 m_actionScheduler->resume();
1177 InspectorInstrumentation::didLayout(cookie);
1179 m_nestedLayoutCount--;
1180 if (m_nestedLayoutCount)
1183 Page* page = frame() ? frame()->page() : 0;
1187 page->chrome()->client()->layoutUpdated(frame());
1188 forceLayoutParentViewIfNeeded();
1191 RenderBox* FrameView::embeddedContentBox() const
1194 RenderView* root = rootRenderer(this);
1198 RenderObject* rootChild = root->firstChild();
1199 if (!rootChild || !rootChild->isBox())
1202 // Curently only embedded SVG documents participate in the size-negotiation logic.
1203 if (rootChild->isSVGRoot())
1204 return toRenderBox(rootChild);
1210 void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object)
1212 if (!m_widgetUpdateSet)
1213 m_widgetUpdateSet = adoptPtr(new RenderEmbeddedObjectSet);
1215 m_widgetUpdateSet->add(object);
1218 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object)
1220 if (!m_widgetUpdateSet)
1223 m_widgetUpdateSet->remove(object);
1226 void FrameView::zoomAnimatorTransformChanged(float scale, float x, float y, ZoomAnimationState state)
1228 if (state == ZoomAnimationFinishing) {
1229 m_page->setPageScaleFactor(m_page->pageScaleFactor() * scale,
1230 IntPoint(scale * scrollX() - x, scale * scrollY() - y));
1231 scrollAnimator()->resetZoom();
1234 #if USE(ACCELERATED_COMPOSITING)
1235 if (RenderView* root = rootRenderer(this)) {
1236 if (root->usesCompositing()) {
1237 root->compositor()->scheduleLayerFlush();
1238 #if PLATFORM(CHROMIUM)
1239 TRACE_EVENT("FrameView::zoomAnimatorTransformChanged", this, 0);
1246 void FrameView::setMediaType(const String& mediaType)
1248 m_mediaType = mediaType;
1251 String FrameView::mediaType() const
1253 // See if we have an override type.
1254 String overrideType = m_frame->loader()->client()->overrideMediaType();
1255 if (!overrideType.isNull())
1256 return overrideType;
1260 void FrameView::adjustMediaTypeForPrinting(bool printing)
1263 if (m_mediaTypeWhenNotPrinting.isNull())
1264 m_mediaTypeWhenNotPrinting = mediaType();
1265 setMediaType("print");
1267 if (!m_mediaTypeWhenNotPrinting.isNull())
1268 setMediaType(m_mediaTypeWhenNotPrinting);
1269 m_mediaTypeWhenNotPrinting = String();
1273 bool FrameView::useSlowRepaints(bool considerOverlap) const
1275 bool mustBeSlow = m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0);
1277 if (contentsInCompositedLayer())
1280 #if PLATFORM(CHROMIUM)
1281 // The chromium compositor does not support scrolling a non-composited frame within a composited page through
1282 // the fast scrolling path, so force slow scrolling in that case.
1283 if (m_frame->ownerElement() && !hasCompositedContent() && m_frame->page() && m_frame->page()->mainFrame()->view()->hasCompositedContent())
1287 bool isOverlapped = m_isOverlapped && considerOverlap;
1289 if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque)
1292 if (FrameView* parentView = parentFrameView())
1293 return parentView->useSlowRepaints(considerOverlap);
1298 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1300 return useSlowRepaints(false);
1303 void FrameView::updateCanBlitOnScrollRecursively()
1305 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1306 if (FrameView* view = frame->view())
1307 view->setCanBlitOnScroll(!view->useSlowRepaints());
1311 bool FrameView::contentsInCompositedLayer() const
1313 #if USE(ACCELERATED_COMPOSITING)
1314 RenderView* root = rootRenderer(this);
1315 if (root && root->layer()->isComposited()) {
1316 GraphicsLayer* layer = root->layer()->backing()->graphicsLayer();
1317 if (layer && layer->drawsContent())
1324 void FrameView::setCannotBlitToWindow()
1326 m_cannotBlitToWindow = true;
1327 updateCanBlitOnScrollRecursively();
1330 void FrameView::addSlowRepaintObject()
1332 if (!m_slowRepaintObjectCount)
1333 updateCanBlitOnScrollRecursively();
1334 m_slowRepaintObjectCount++;
1337 void FrameView::removeSlowRepaintObject()
1339 ASSERT(m_slowRepaintObjectCount > 0);
1340 m_slowRepaintObjectCount--;
1341 if (!m_slowRepaintObjectCount)
1342 updateCanBlitOnScrollRecursively();
1345 void FrameView::addFixedObject()
1347 if (!m_fixedObjectCount && platformWidget())
1348 updateCanBlitOnScrollRecursively();
1349 ++m_fixedObjectCount;
1352 void FrameView::removeFixedObject()
1354 ASSERT(m_fixedObjectCount > 0);
1355 --m_fixedObjectCount;
1356 if (!m_fixedObjectCount)
1357 updateCanBlitOnScrollRecursively();
1360 LayoutUnit FrameView::scrollXForFixedPosition() const
1362 LayoutUnit visibleContentWidth = visibleContentRect().width();
1363 LayoutUnit maxX = contentsWidth() - visibleContentWidth;
1368 LayoutUnit x = scrollX();
1370 if (!scrollOrigin().x()) {
1385 float frameScaleFactor = m_frame->frameScaleFactor();
1387 // When the page is scaled, the scaled "viewport" with respect to which fixed object are positioned
1388 // doesn't move as fast as the content view, so that when the content is scrolled all the way to the
1389 // end, the bottom of the scaled "viewport" touches the bottom of the real viewport.
1390 float dragFactor = (contentsWidth() - visibleContentWidth * frameScaleFactor) / maxX;
1392 return x * dragFactor / frameScaleFactor;
1395 LayoutUnit FrameView::scrollYForFixedPosition() const
1397 LayoutUnit visibleContentHeight = visibleContentRect().height();
1399 LayoutUnit maxY = contentsHeight() - visibleContentHeight;
1403 LayoutUnit y = scrollY();
1405 if (!scrollOrigin().y()) {
1420 float frameScaleFactor = m_frame->frameScaleFactor();
1421 float dragFactor = (contentsHeight() - visibleContentHeight * frameScaleFactor) / maxY;
1423 return y * dragFactor / frameScaleFactor;
1426 LayoutSize FrameView::scrollOffsetForFixedPosition() const
1428 return LayoutSize(scrollXForFixedPosition(), scrollYForFixedPosition());
1431 LayoutPoint FrameView::currentMousePosition() const
1433 return m_frame ? m_frame->eventHandler()->currentMousePosition() : IntPoint();
1436 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1438 const size_t fixedObjectThreshold = 5;
1440 RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0;
1441 if (RenderView* root = rootRenderer(this))
1442 positionedObjects = root->positionedObjects();
1444 if (!positionedObjects || positionedObjects->isEmpty()) {
1445 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1449 const bool isCompositedContentLayer = contentsInCompositedLayer();
1451 // Get the rects of the fixed objects visible in the rectToScroll
1452 Vector<IntRect, fixedObjectThreshold> subRectToUpdate;
1453 bool updateInvalidatedSubRect = true;
1454 RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
1455 for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
1456 RenderBox* renderBox = *it;
1457 if (renderBox->style()->position() != FixedPosition)
1459 IntRect updateRect = renderBox->layer()->repaintRectIncludingDescendants();
1460 updateRect = contentsToWindow(updateRect);
1461 if (!isCompositedContentLayer && clipsRepaints())
1462 updateRect.intersect(rectToScroll);
1463 if (!updateRect.isEmpty()) {
1464 if (subRectToUpdate.size() >= fixedObjectThreshold) {
1465 updateInvalidatedSubRect = false;
1468 subRectToUpdate.append(updateRect);
1473 if (updateInvalidatedSubRect) {
1475 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1477 // 2) update the area of fixed objects that has been invalidated
1478 size_t fixObjectsCount = subRectToUpdate.size();
1479 for (size_t i = 0; i < fixObjectsCount; ++i) {
1480 IntRect updateRect = subRectToUpdate[i];
1481 IntRect scrolledRect = updateRect;
1482 scrolledRect.move(scrollDelta);
1483 updateRect.unite(scrolledRect);
1484 #if USE(ACCELERATED_COMPOSITING)
1485 if (isCompositedContentLayer) {
1486 updateRect = windowToContents(updateRect);
1487 RenderView* root = rootRenderer(this);
1489 root->layer()->setBackingNeedsRepaintInRect(updateRect);
1493 if (clipsRepaints())
1494 updateRect.intersect(rectToScroll);
1495 hostWindow()->invalidateContentsAndWindow(updateRect, false);
1500 // the number of fixed objects exceed the threshold, we cannot use the fast path
1504 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1506 #if USE(ACCELERATED_COMPOSITING)
1507 if (contentsInCompositedLayer()) {
1508 RenderView* root = rootRenderer(this);
1510 root->layer()->setBackingNeedsRepaintInRect(visibleContentRect());
1512 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1513 if (frameRenderer->containerForRepaint()) {
1514 LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1515 frameRenderer->borderTop() + frameRenderer->paddingTop(),
1516 visibleWidth(), visibleHeight());
1517 frameRenderer->repaintRectangle(rect);
1523 ScrollView::scrollContentsSlowPath(updateRect);
1526 // Note that this gets called at painting time.
1527 void FrameView::setIsOverlapped(bool isOverlapped)
1529 if (isOverlapped == m_isOverlapped)
1532 m_isOverlapped = isOverlapped;
1533 updateCanBlitOnScrollRecursively();
1535 #if USE(ACCELERATED_COMPOSITING)
1536 if (hasCompositedContentIncludingDescendants()) {
1537 // Overlap can affect compositing tests, so if it changes, we need to trigger
1538 // a layer update in the parent document.
1539 if (Frame* parentFrame = m_frame->tree()->parent()) {
1540 if (RenderView* parentView = parentFrame->contentRenderer()) {
1541 RenderLayerCompositor* compositor = parentView->compositor();
1542 compositor->setCompositingLayersNeedRebuild();
1543 compositor->scheduleCompositingLayerUpdate();
1547 if (RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) {
1548 // We also need to trigger reevaluation for this and all descendant frames,
1549 // since a frame uses compositing if any ancestor is compositing.
1550 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1551 if (RenderView* view = frame->contentRenderer()) {
1552 RenderLayerCompositor* compositor = view->compositor();
1553 compositor->setCompositingLayersNeedRebuild();
1554 compositor->scheduleCompositingLayerUpdate();
1562 bool FrameView::isOverlappedIncludingAncestors() const
1567 if (FrameView* parentView = parentFrameView()) {
1568 if (parentView->isOverlapped())
1575 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1577 if (contentIsOpaque == m_contentIsOpaque)
1580 m_contentIsOpaque = contentIsOpaque;
1581 updateCanBlitOnScrollRecursively();
1584 void FrameView::restoreScrollbar()
1586 setScrollbarsSuppressed(false);
1589 bool FrameView::scrollToFragment(const KURL& url)
1591 // If our URL has no ref, then we have no place we need to jump to.
1592 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1593 // and possibly repaint because :target pseudo class may have been
1594 // set (see bug 11321).
1595 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1598 String fragmentIdentifier = url.fragmentIdentifier();
1599 if (scrollToAnchor(fragmentIdentifier))
1602 // Try again after decoding the ref, based on the document's encoding.
1603 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1604 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1609 bool FrameView::scrollToAnchor(const String& name)
1611 ASSERT(m_frame->document());
1613 if (!m_frame->document()->haveStylesheetsLoaded()) {
1614 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1618 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1620 Element* anchorNode = m_frame->document()->findAnchor(name);
1622 // Setting to null will clear the current target.
1623 m_frame->document()->setCSSTarget(anchorNode);
1626 if (m_frame->document()->isSVGDocument()) {
1627 if (SVGSVGElement* svg = static_cast<SVGDocument*>(m_frame->document())->rootElement()) {
1628 svg->setupInitialView(name, anchorNode);
1635 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1636 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1639 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1643 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1645 m_maintainScrollPositionAnchor = anchorNode;
1646 if (!m_maintainScrollPositionAnchor)
1649 // We need to update the layout before scrolling, otherwise we could
1650 // really mess things up if an anchor scroll comes at a bad moment.
1651 m_frame->document()->updateStyleIfNeeded();
1652 // Only do a layout if changes have occurred that make it necessary.
1653 RenderView* root = rootRenderer(this);
1654 if (root && root->needsLayout())
1660 void FrameView::scrollElementToRect(Element* element, const IntRect& rect)
1662 m_frame->document()->updateLayoutIgnorePendingStylesheets();
1664 LayoutRect bounds = element->getRect();
1665 int centeringOffsetX = (rect.width() - bounds.width()) / 2;
1666 int centeringOffsetY = (rect.height() - bounds.height()) / 2;
1667 setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y()));
1670 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1672 bool wasInProgrammaticScroll = m_inProgrammaticScroll;
1673 m_inProgrammaticScroll = true;
1674 m_maintainScrollPositionAnchor = 0;
1675 ScrollView::setScrollPosition(scrollPoint);
1676 m_inProgrammaticScroll = wasInProgrammaticScroll;
1679 void FrameView::setFixedVisibleContentRect(const IntRect& visibleContentRect)
1681 IntSize offset = scrollOffset();
1682 ScrollView::setFixedVisibleContentRect(visibleContentRect);
1683 if (offset != scrollOffset())
1684 scrollPositionChanged();
1685 frame()->loader()->client()->didChangeScrollOffset();
1688 void FrameView::scrollPositionChangedViaPlatformWidget()
1690 repaintFixedElementsAfterScrolling();
1691 scrollPositionChanged();
1694 void FrameView::scrollPositionChanged()
1696 frame()->eventHandler()->sendScrollEvent();
1698 #if USE(ACCELERATED_COMPOSITING)
1699 if (RenderView* root = rootRenderer(this)) {
1700 if (root->usesCompositing())
1701 root->compositor()->frameViewDidScroll(scrollPosition());
1706 void FrameView::repaintFixedElementsAfterScrolling()
1708 // For fixed position elements, update widget positions and compositing layers after scrolling,
1709 // but only if we're not inside of layout.
1710 if (!m_nestedLayoutCount && hasFixedObjects()) {
1711 if (RenderView* root = rootRenderer(this)) {
1712 root->updateWidgetPositions();
1713 root->layer()->updateLayerPositionsAfterScroll();
1714 #if USE(ACCELERATED_COMPOSITING)
1715 root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
1721 bool FrameView::shouldRubberBandInDirection(ScrollDirection direction) const
1723 Page* page = frame() ? frame()->page() : 0;
1725 return ScrollView::shouldRubberBandInDirection(direction);
1726 return page->chrome()->client()->shouldRubberBandInDirection(direction);
1729 HostWindow* FrameView::hostWindow() const
1731 Page* page = frame() ? frame()->page() : 0;
1734 return page->chrome();
1737 const unsigned cRepaintRectUnionThreshold = 25;
1739 void FrameView::repaintContentRectangle(const LayoutRect& r, bool immediate)
1741 ASSERT(!m_frame->ownerElement());
1743 if (m_isTrackingRepaints) {
1744 LayoutRect repaintRect = r;
1745 repaintRect.move(-scrollOffset());
1746 m_trackedRepaintRects.append(repaintRect);
1749 double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay();
1750 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
1751 LayoutRect paintRect = r;
1752 if (clipsRepaints() && !paintsEntireContents())
1753 paintRect.intersect(visibleContentRect());
1754 if (paintRect.isEmpty())
1756 if (m_repaintCount == cRepaintRectUnionThreshold) {
1757 LayoutRect unionedRect;
1758 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
1759 unionedRect.unite(m_repaintRects[i]);
1760 m_repaintRects.clear();
1761 m_repaintRects.append(unionedRect);
1763 if (m_repaintCount < cRepaintRectUnionThreshold)
1764 m_repaintRects.append(paintRect);
1766 m_repaintRects[0].unite(paintRect);
1769 if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive())
1770 m_deferredRepaintTimer.startOneShot(delay);
1774 if (!shouldUpdate(immediate))
1777 #if USE(TILED_BACKING_STORE)
1778 if (frame()->tiledBackingStore()) {
1779 frame()->tiledBackingStore()->invalidate(r);
1783 ScrollView::repaintContentRectangle(r, immediate);
1786 void FrameView::contentsResized()
1788 scrollAnimator()->contentsResized();
1792 void FrameView::visibleContentsResized()
1794 // We check to make sure the view is attached to a frame() as this method can
1795 // be triggered before the view is attached by Frame::createView(...) setting
1796 // various values such as setScrollBarModes(...) for example. An ASSERT is
1797 // triggered when a view is layout before being attached to a frame().
1798 if (!frame()->view())
1804 #if USE(ACCELERATED_COMPOSITING)
1805 if (RenderView* root = rootRenderer(this)) {
1806 if (root->usesCompositing())
1807 root->compositor()->frameViewDidChangeSize();
1812 void FrameView::beginDeferredRepaints()
1814 Page* page = m_frame->page();
1815 if (page->mainFrame() != m_frame)
1816 return page->mainFrame()->view()->beginDeferredRepaints();
1818 m_deferringRepaints++;
1822 void FrameView::endDeferredRepaints()
1824 Page* page = m_frame->page();
1825 if (page->mainFrame() != m_frame)
1826 return page->mainFrame()->view()->endDeferredRepaints();
1828 ASSERT(m_deferringRepaints > 0);
1830 if (--m_deferringRepaints)
1833 if (m_deferredRepaintTimer.isActive())
1836 if (double delay = adjustedDeferredRepaintDelay()) {
1837 m_deferredRepaintTimer.startOneShot(delay);
1841 doDeferredRepaints();
1844 void FrameView::checkStopDelayingDeferredRepaints()
1846 if (!m_deferredRepaintTimer.isActive())
1849 Document* document = m_frame->document();
1850 if (document && (document->parsing() || document->cachedResourceLoader()->requestCount()))
1853 m_deferredRepaintTimer.stop();
1855 doDeferredRepaints();
1858 void FrameView::doDeferredRepaints()
1860 ASSERT(!m_deferringRepaints);
1861 if (!shouldUpdate()) {
1862 m_repaintRects.clear();
1866 unsigned size = m_repaintRects.size();
1867 for (unsigned i = 0; i < size; i++) {
1868 #if USE(TILED_BACKING_STORE)
1869 if (frame()->tiledBackingStore()) {
1870 frame()->tiledBackingStore()->invalidate(m_repaintRects[i]);
1874 ScrollView::repaintContentRectangle(m_repaintRects[i], false);
1876 m_repaintRects.clear();
1879 updateDeferredRepaintDelay();
1882 void FrameView::updateDeferredRepaintDelay()
1884 Document* document = m_frame->document();
1885 if (!document || (!document->parsing() && !document->cachedResourceLoader()->requestCount())) {
1886 m_deferredRepaintDelay = s_deferredRepaintDelay;
1889 if (m_deferredRepaintDelay < s_maxDeferredRepaintDelayDuringLoading) {
1890 m_deferredRepaintDelay += s_deferredRepaintDelayIncrementDuringLoading;
1891 if (m_deferredRepaintDelay > s_maxDeferredRepaintDelayDuringLoading)
1892 m_deferredRepaintDelay = s_maxDeferredRepaintDelayDuringLoading;
1896 void FrameView::resetDeferredRepaintDelay()
1898 m_deferredRepaintDelay = 0;
1899 if (m_deferredRepaintTimer.isActive()) {
1900 m_deferredRepaintTimer.stop();
1901 if (!m_deferringRepaints)
1902 doDeferredRepaints();
1906 double FrameView::adjustedDeferredRepaintDelay() const
1908 ASSERT(!m_deferringRepaints);
1909 if (!m_deferredRepaintDelay)
1911 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
1912 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
1915 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
1917 doDeferredRepaints();
1920 void FrameView::layoutTimerFired(Timer<FrameView>*)
1922 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1923 if (!m_frame->document()->ownerElement())
1924 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
1929 void FrameView::scheduleRelayout()
1931 // FIXME: We should assert the page is not in the page cache, but that is causing
1932 // too many false assertions. See <rdar://problem/7218118>.
1933 ASSERT(m_frame->view() == this);
1936 m_layoutRoot->markContainingBlocksForLayout(false);
1939 if (!m_layoutSchedulingEnabled)
1943 if (!m_frame->document()->shouldScheduleLayout())
1946 // When frame flattening is enabled, the contents of the frame affects layout of the parent frames.
1947 // Also invalidate parent frame starting from the owner element of this frame.
1948 if (m_frame->settings() && m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) {
1949 if (m_frame->ownerElement()->hasTagName(iframeTag) || m_frame->ownerElement()->hasTagName(frameTag))
1950 m_frame->ownerRenderer()->setNeedsLayout(true, true);
1953 int delay = m_frame->document()->minimumLayoutDelay();
1954 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
1955 unscheduleRelayout();
1956 if (m_layoutTimer.isActive())
1959 m_delayedLayout = delay != 0;
1961 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1962 if (!m_frame->document()->ownerElement())
1963 printf("Scheduling layout for %d\n", delay);
1966 m_layoutTimer.startOneShot(delay * 0.001);
1969 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
1971 for (RenderObject* r = descendant; r; r = r->container()) {
1978 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
1980 ASSERT(m_frame->view() == this);
1982 RenderView* root = rootRenderer(this);
1983 if (root && root->needsLayout()) {
1985 relayoutRoot->markContainingBlocksForLayout(false);
1989 if (layoutPending() || !m_layoutSchedulingEnabled) {
1990 if (m_layoutRoot != relayoutRoot) {
1991 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
1992 // Keep the current root
1993 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
1994 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
1995 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
1996 // Re-root at relayoutRoot
1997 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
1998 m_layoutRoot = relayoutRoot;
1999 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2001 // Just do a full relayout
2003 m_layoutRoot->markContainingBlocksForLayout(false);
2005 relayoutRoot->markContainingBlocksForLayout(false);
2008 } else if (m_layoutSchedulingEnabled) {
2009 int delay = m_frame->document()->minimumLayoutDelay();
2010 m_layoutRoot = relayoutRoot;
2011 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2012 m_delayedLayout = delay != 0;
2013 m_layoutTimer.startOneShot(delay * 0.001);
2017 bool FrameView::layoutPending() const
2019 return m_layoutTimer.isActive();
2022 bool FrameView::needsLayout() const
2024 // This can return true in cases where the document does not have a body yet.
2025 // Document::shouldScheduleLayout takes care of preventing us from scheduling
2026 // layout in that case.
2030 RenderView* root = rootRenderer(this);
2031 return layoutPending()
2032 || (root && root->needsLayout())
2034 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
2037 void FrameView::setNeedsLayout()
2039 if (m_deferSetNeedsLayouts) {
2040 m_setNeedsLayoutWasDeferred = true;
2044 if (RenderView* root = rootRenderer(this))
2045 root->setNeedsLayout(true);
2048 void FrameView::unscheduleRelayout()
2050 m_postLayoutTasksTimer.stop();
2052 if (!m_layoutTimer.isActive())
2055 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2056 if (!m_frame->document()->ownerElement())
2057 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
2060 m_layoutTimer.stop();
2061 m_delayedLayout = false;
2064 #if ENABLE(REQUEST_ANIMATION_FRAME)
2065 void FrameView::serviceScriptedAnimations(DOMTimeStamp time)
2067 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext())
2068 frame->document()->serviceScriptedAnimations(time);
2072 bool FrameView::isTransparent() const
2074 return m_isTransparent;
2077 void FrameView::setTransparent(bool isTransparent)
2079 m_isTransparent = isTransparent;
2082 Color FrameView::baseBackgroundColor() const
2084 return m_baseBackgroundColor;
2087 void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
2089 if (!backgroundColor.isValid())
2090 m_baseBackgroundColor = Color::white;
2092 m_baseBackgroundColor = backgroundColor;
2094 recalculateScrollbarOverlayStyle();
2097 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
2099 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
2100 if (FrameView* view = frame->view()) {
2101 view->setTransparent(transparent);
2102 view->setBaseBackgroundColor(backgroundColor);
2107 bool FrameView::shouldUpdateWhileOffscreen() const
2109 return m_shouldUpdateWhileOffscreen;
2112 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
2114 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
2117 bool FrameView::shouldUpdate(bool immediateRequested) const
2119 if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen())
2124 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
2126 m_actionScheduler->scheduleEvent(event, eventTarget);
2129 void FrameView::pauseScheduledEvents()
2131 m_actionScheduler->pause();
2134 void FrameView::resumeScheduledEvents()
2136 m_actionScheduler->resume();
2139 void FrameView::scrollToAnchor()
2141 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
2145 if (!anchorNode->renderer())
2149 if (anchorNode != m_frame->document())
2150 rect = anchorNode->getRect();
2152 // Scroll nested layers and frames to reveal the anchor.
2153 // Align to the top and to the closest side (this matches other browsers).
2154 anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
2156 if (AXObjectCache::accessibilityEnabled())
2157 m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get());
2159 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
2160 m_maintainScrollPositionAnchor = anchorNode;
2163 void FrameView::updateWidget(RenderEmbeddedObject* object)
2165 ASSERT(!object->node() || object->node()->isElementNode());
2166 Element* ownerElement = static_cast<Element*>(object->node());
2167 // The object may have already been destroyed (thus node cleared),
2168 // but FrameView holds a manual ref, so it won't have been deleted.
2169 ASSERT(m_widgetUpdateSet->contains(object));
2173 // No need to update if it's already crashed or known to be missing.
2174 if (object->pluginCrashedOrWasMissing())
2177 // FIXME: This could turn into a real virtual dispatch if we defined
2178 // updateWidget(bool) on HTMLElement.
2179 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag))
2180 static_cast<HTMLPlugInImageElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
2181 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
2182 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
2183 else if (ownerElement->isMediaElement())
2184 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
2187 ASSERT_NOT_REACHED();
2189 // Caution: it's possible the object was destroyed again, since loading a
2190 // plugin may run any arbitrary javascript.
2191 object->updateWidgetPosition();
2194 bool FrameView::updateWidgets()
2196 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
2199 size_t size = m_widgetUpdateSet->size();
2201 Vector<RenderEmbeddedObject*> objects;
2202 objects.reserveCapacity(size);
2204 RenderEmbeddedObjectSet::const_iterator end = m_widgetUpdateSet->end();
2205 for (RenderEmbeddedObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
2206 objects.uncheckedAppend(*it);
2210 for (size_t i = 0; i < size; ++i) {
2211 RenderEmbeddedObject* object = objects[i];
2212 updateWidget(object);
2213 m_widgetUpdateSet->remove(object);
2216 RenderArena* arena = m_frame->document()->renderArena();
2217 for (size_t i = 0; i < size; ++i)
2218 objects[i]->deref(arena);
2220 return m_widgetUpdateSet->isEmpty();
2223 void FrameView::flushAnyPendingPostLayoutTasks()
2225 if (!m_hasPendingPostLayoutTasks)
2228 m_postLayoutTasksTimer.stop();
2229 performPostLayoutTasks();
2232 void FrameView::performPostLayoutTasks()
2234 m_hasPendingPostLayoutTasks = false;
2236 m_frame->selection()->setCaretRectNeedsUpdate();
2237 m_frame->selection()->updateAppearance();
2239 if (m_nestedLayoutCount <= 1) {
2240 if (m_firstLayoutCallbackPending) {
2241 m_firstLayoutCallbackPending = false;
2242 m_frame->loader()->didFirstLayout();
2245 // Ensure that we always send this eventually.
2246 if (!m_frame->document()->parsing() && m_frame->loader()->stateMachine()->committedFirstRealDocumentLoad())
2247 m_isVisuallyNonEmpty = true;
2249 // If the layout was done with pending sheets, we are not in fact visually non-empty yet.
2250 if (m_isVisuallyNonEmpty && !m_frame->document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) {
2251 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
2252 m_frame->loader()->didFirstVisuallyNonEmptyLayout();
2256 m_frame->loader()->client()->dispatchDidLayout();
2258 RenderView* root = rootRenderer(this);
2259 root->updateWidgetPositions();
2261 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
2262 if (updateWidgets())
2268 m_actionScheduler->resume();
2270 if (!root->printing()) {
2271 LayoutSize currentSize = LayoutSize(width(), height());
2272 float currentZoomFactor = root->style()->zoom();
2273 bool resized = !m_firstLayout && (currentSize != m_lastLayoutSize || currentZoomFactor != m_lastZoomFactor);
2274 m_lastLayoutSize = currentSize;
2275 m_lastZoomFactor = currentZoomFactor;
2277 m_frame->eventHandler()->sendResizeEvent();
2281 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
2283 performPostLayoutTasks();
2286 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
2288 if (!m_viewportRenderer)
2291 if (m_overflowStatusDirty) {
2292 m_horizontalOverflow = horizontalOverflow;
2293 m_verticalOverflow = verticalOverflow;
2294 m_overflowStatusDirty = false;
2298 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
2299 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
2301 if (horizontalOverflowChanged || verticalOverflowChanged) {
2302 m_horizontalOverflow = horizontalOverflow;
2303 m_verticalOverflow = verticalOverflow;
2305 m_actionScheduler->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
2306 verticalOverflowChanged, verticalOverflow),
2307 m_viewportRenderer->node());
2312 IntRect FrameView::windowClipRect(bool clipToContents) const
2314 ASSERT(m_frame->view() == this);
2316 if (paintsEntireContents())
2317 return IntRect(IntPoint(), contentsSize());
2319 // Set our clip rect to be our contents.
2320 IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
2321 if (!m_frame || !m_frame->ownerElement())
2324 // Take our owner element and get the clip rect from the enclosing layer.
2325 Element* elt = m_frame->ownerElement();
2326 // The renderer can sometimes be null when style="display:none" interacts
2327 // with external content and plugins.
2328 RenderLayer* layer = elt->renderer() ? elt->renderer()->enclosingLayer() : 0;
2331 FrameView* parentView = elt->document()->view();
2332 clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
2336 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const
2338 // If we have no layer, just return our window clip rect.
2340 return windowClipRect();
2342 // Apply the clip from the layer.
2344 if (clipToLayerContents)
2345 clipRect = layer->childrenClipRect();
2347 clipRect = layer->selfClipRect();
2348 clipRect = contentsToWindow(clipRect);
2349 return intersection(clipRect, windowClipRect());
2352 bool FrameView::isActive() const
2354 Page* page = frame()->page();
2355 return page && page->focusController()->isActive();
2358 void FrameView::scrollTo(const IntSize& newOffset)
2360 LayoutSize offset = scrollOffset();
2361 ScrollView::scrollTo(newOffset);
2362 if (offset != scrollOffset())
2363 scrollPositionChanged();
2364 frame()->loader()->client()->didChangeScrollOffset();
2367 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const LayoutRect& rect)
2369 // Add in our offset within the FrameView.
2370 LayoutRect dirtyRect = rect;
2371 dirtyRect.moveBy(scrollbar->location());
2372 invalidateRect(dirtyRect);
2375 void FrameView::getTickmarks(Vector<LayoutRect>& tickmarks) const
2377 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
2380 IntRect FrameView::windowResizerRect() const
2382 Page* page = frame() ? frame()->page() : 0;
2384 return LayoutRect();
2385 return page->chrome()->windowResizerRect();
2388 void FrameView::didStartRubberBand(const IntSize& initialOverhang) const
2390 Page* page = m_frame->page();
2393 return page->chrome()->client()->didCompleteRubberBandForFrame(m_frame.get(), initialOverhang);
2396 void FrameView::didCompleteRubberBand(const IntSize& initialOverhang) const
2398 Page* page = m_frame->page();
2401 return page->chrome()->client()->didCompleteRubberBandForFrame(m_frame.get(), initialOverhang);
2404 void FrameView::didStartAnimatedScroll() const
2406 Page* page = m_frame->page();
2409 return page->chrome()->client()->didStartAnimatedScroll();
2412 void FrameView::didCompleteAnimatedScroll() const
2414 Page* page = m_frame->page();
2417 return page->chrome()->client()->didCompleteAnimatedScroll();
2420 void FrameView::setVisibleScrollerThumbRect(const LayoutRect& scrollerThumb)
2422 Page* page = m_frame->page();
2425 if (page->mainFrame() != m_frame)
2427 return page->chrome()->client()->notifyScrollerThumbIsVisibleInRect(scrollerThumb);
2430 bool FrameView::isOnActivePage() const
2434 if (m_frame->view() != this)
2436 if (Document* document = m_frame->document())
2437 return !document->inPageCache();
2441 ScrollableArea* FrameView::enclosingScrollableArea() const
2443 // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer.
2447 bool FrameView::shouldSuspendScrollAnimations() const
2449 return m_frame->loader()->state() != FrameStateComplete;
2452 void FrameView::setAnimatorsAreActive()
2454 Page* page = m_frame->page();
2458 const HashSet<ScrollableArea*>* scrollableAreas = page->scrollableAreaSet();
2459 if (!scrollableAreas)
2462 HashSet<ScrollableArea*>::const_iterator end = scrollableAreas->end();
2463 for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(); it != end; ++it) {
2464 // FIXME: This extra check to make sure the ScrollableArea is on an active page needs
2465 // to be here as long as the ScrollableArea HashSet lives on Page. But it should really be
2466 // moved to the top-level Document or a similar class that really represents a single
2467 // web page. https://bugs.webkit.org/show_bug.cgi?id=62762
2468 if ((*it)->isOnActivePage())
2469 (*it)->scrollAnimator()->setIsActive();
2473 void FrameView::notifyPageThatContentAreaWillPaint() const
2475 Page* page = m_frame->page();
2476 const HashSet<ScrollableArea*>* scrollableAreas = page->scrollableAreaSet();
2477 if (!scrollableAreas)
2480 HashSet<ScrollableArea*>::const_iterator end = scrollableAreas->end();
2481 for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(); it != end; ++it)
2482 (*it)->scrollAnimator()->contentAreaWillPaint();
2485 bool FrameView::scrollAnimatorEnabled() const
2487 #if ENABLE(SMOOTH_SCROLLING)
2488 if (m_page && m_page->settings())
2489 return m_page->settings()->scrollAnimatorEnabled();
2494 #if ENABLE(DASHBOARD_SUPPORT)
2495 void FrameView::updateDashboardRegions()
2497 Document* document = m_frame->document();
2498 if (!document->hasDashboardRegions())
2500 Vector<DashboardRegionValue> newRegions;
2501 document->renderBox()->collectDashboardRegions(newRegions);
2502 if (newRegions == document->dashboardRegions())
2504 document->setDashboardRegions(newRegions);
2505 Page* page = m_frame->page();
2508 page->chrome()->client()->dashboardRegionsChanged();
2512 void FrameView::updateScrollCorner()
2514 RenderObject* renderer = 0;
2515 RefPtr<RenderStyle> cornerStyle;
2516 LayoutRect cornerRect = scrollCornerRect();
2518 if (!cornerRect.isEmpty()) {
2519 // Try the <body> element first as a scroll corner source.
2520 Document* doc = m_frame->document();
2521 Element* body = doc ? doc->body() : 0;
2522 if (body && body->renderer()) {
2523 renderer = body->renderer();
2524 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2528 // If the <body> didn't have a custom style, then the root element might.
2529 Element* docElement = doc ? doc->documentElement() : 0;
2530 if (docElement && docElement->renderer()) {
2531 renderer = docElement->renderer();
2532 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2537 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
2538 if (RenderPart* renderer = m_frame->ownerRenderer())
2539 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2544 if (!m_scrollCorner)
2545 m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document());
2546 m_scrollCorner->setStyle(cornerStyle.release());
2547 invalidateScrollCorner(cornerRect);
2548 } else if (m_scrollCorner) {
2549 m_scrollCorner->destroy();
2553 ScrollView::updateScrollCorner();
2556 void FrameView::paintScrollCorner(GraphicsContext* context, const LayoutRect& cornerRect)
2558 if (context->updatingControlTints()) {
2559 updateScrollCorner();
2563 if (m_scrollCorner) {
2564 m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect);
2568 ScrollView::paintScrollCorner(context, cornerRect);
2571 Color FrameView::documentBackgroundColor() const
2573 // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of
2574 // the document and the body against the base background color of the frame view.
2575 // Background images are unfortunately impractical to include.
2577 // Return invalid Color objects whenever there is insufficient information.
2578 if (!frame()->document())
2581 Element* htmlElement = frame()->document()->documentElement();
2582 Element* bodyElement = frame()->document()->body();
2584 // Start with invalid colors.
2585 Color htmlBackgroundColor;
2586 Color bodyBackgroundColor;
2587 if (htmlElement && htmlElement->renderer())
2588 htmlBackgroundColor = htmlElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
2589 if (bodyElement && bodyElement->renderer())
2590 bodyBackgroundColor = bodyElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
2592 if (!bodyBackgroundColor.isValid()) {
2593 if (!htmlBackgroundColor.isValid())
2595 return baseBackgroundColor().blend(htmlBackgroundColor);
2598 if (!htmlBackgroundColor.isValid())
2599 return baseBackgroundColor().blend(bodyBackgroundColor);
2601 // We take the aggregate of the base background color
2602 // the <html> background color, and the <body>
2603 // background color to find the document color. The
2604 // addition of the base background color is not
2605 // technically part of the document background, but it
2606 // otherwise poses problems when the aggregate is not
2608 return baseBackgroundColor().blend(htmlBackgroundColor).blend(bodyBackgroundColor);
2611 bool FrameView::hasCustomScrollbars() const
2613 const HashSet<RefPtr<Widget> >* viewChildren = children();
2614 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2615 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2616 Widget* widget = current->get();
2617 if (widget->isFrameView()) {
2618 if (static_cast<FrameView*>(widget)->hasCustomScrollbars())
2620 } else if (widget->isScrollbar()) {
2621 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
2622 if (scrollbar->isCustomScrollbar())
2630 void FrameView::clearOwningRendererForCustomScrollbars(RenderBox* box)
2632 const HashSet<RefPtr<Widget> >* viewChildren = children();
2633 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2634 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2635 Widget* widget = current->get();
2636 if (widget->isScrollbar()) {
2637 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
2638 if (scrollbar->isCustomScrollbar()) {
2639 RenderScrollbar* customScrollbar = toRenderScrollbar(scrollbar);
2640 if (customScrollbar->owningRenderer() == box)
2641 customScrollbar->clearOwningRenderer();
2647 FrameView* FrameView::parentFrameView() const
2649 if (Widget* parentView = parent()) {
2650 if (parentView->isFrameView())
2651 return static_cast<FrameView*>(parentView);
2656 void FrameView::updateControlTints()
2658 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
2659 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
2660 // This is only done if the theme supports control tinting. It's up to the theme and platform
2661 // to define when controls get the tint and to call this function when that changes.
2663 // Optimize the common case where we bring a window to the front while it's still empty.
2664 if (!m_frame || m_frame->document()->url().isEmpty())
2667 RenderView* root = rootRenderer(this);
2668 if ((root && root->theme()->supportsControlTints()) || hasCustomScrollbars())
2669 paintControlTints();
2672 void FrameView::paintControlTints()
2676 PlatformGraphicsContext* const noContext = 0;
2677 GraphicsContext context(noContext);
2678 context.setUpdatingControlTints(true);
2679 if (platformWidget())
2680 paintContents(&context, visibleContentRect());
2682 paint(&context, frameRect());
2685 bool FrameView::wasScrolledByUser() const
2687 return m_wasScrolledByUser;
2690 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
2692 if (m_inProgrammaticScroll)
2694 m_maintainScrollPositionAnchor = 0;
2695 m_wasScrolledByUser = wasScrolledByUser;
2698 void FrameView::paintContents(GraphicsContext* p, const LayoutRect& rect)
2703 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get(), rect);
2705 Document* document = m_frame->document();
2709 if (document->printing())
2710 fillWithRed = false; // Printing, don't fill with red (can't remember why).
2711 else if (m_frame->ownerElement())
2712 fillWithRed = false; // Subframe, don't fill with red.
2713 else if (isTransparent())
2714 fillWithRed = false; // Transparent, don't fill with red.
2715 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
2716 fillWithRed = false; // Selections are transparent, don't fill with red.
2717 else if (m_nodeToDraw)
2718 fillWithRed = false; // Element images are transparent, don't fill with red.
2723 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
2726 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
2727 if (isTopLevelPainter)
2728 sCurrentPaintTimeStamp = currentTime();
2730 RenderView* root = rootRenderer(this);
2732 LOG_ERROR("called FrameView::paint with nil renderer");
2736 ASSERT(!needsLayout());
2740 FontCachePurgePreventer fontCachePurgePreventer;
2742 #if USE(ACCELERATED_COMPOSITING)
2743 if (!p->paintingDisabled())
2744 syncCompositingStateForThisFrame(m_frame.get());
2747 PaintBehavior oldPaintBehavior = m_paintBehavior;
2749 if (FrameView* parentView = parentFrameView()) {
2750 if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
2751 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2754 if (m_paintBehavior == PaintBehaviorNormal)
2755 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
2757 if (document->printing())
2758 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2760 bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers;
2761 bool isRootFrame = !m_frame->ownerElement();
2762 if (flatteningPaint && isRootFrame)
2763 notifyWidgetsInAllFrames(WillPaintFlattened);
2765 ASSERT(!m_isPainting);
2766 m_isPainting = true;
2768 // m_nodeToDraw is used to draw only one element (and its descendants)
2769 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
2770 RenderLayer* rootLayer = root->layer();
2772 rootLayer->paint(p, rect, m_paintBehavior, eltRenderer);
2774 if (rootLayer->containsDirtyOverlayScrollbars())
2775 rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer);
2777 m_isPainting = false;
2779 if (flatteningPaint && isRootFrame)
2780 notifyWidgetsInAllFrames(DidPaintFlattened);
2782 m_paintBehavior = oldPaintBehavior;
2783 m_lastPaintTime = currentTime();
2785 #if ENABLE(DASHBOARD_SUPPORT)
2786 // Regions may have changed as a result of the visibility/z-index of element changing.
2787 if (document->dashboardRegionsDirty())
2788 updateDashboardRegions();
2791 if (isTopLevelPainter)
2792 sCurrentPaintTimeStamp = 0;
2794 InspectorInstrumentation::didPaint(cookie);
2797 void FrameView::setPaintBehavior(PaintBehavior behavior)
2799 m_paintBehavior = behavior;
2802 PaintBehavior FrameView::paintBehavior() const
2804 return m_paintBehavior;
2807 bool FrameView::isPainting() const
2809 return m_isPainting;
2812 void FrameView::setNodeToDraw(Node* node)
2814 m_nodeToDraw = node;
2817 void FrameView::paintOverhangAreas(GraphicsContext* context, const LayoutRect& horizontalOverhangArea, const LayoutRect& verticalOverhangArea, const LayoutRect& dirtyRect)
2819 if (context->paintingDisabled())
2822 if (m_frame->document()->printing())
2825 Page* page = m_frame->page();
2826 if (page->mainFrame() == m_frame) {
2827 if (page->chrome()->client()->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
2831 return ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
2834 void FrameView::updateLayoutAndStyleIfNeededRecursive()
2836 // We have to crawl our entire tree looking for any FrameViews that need
2837 // layout and make sure they are up to date.
2838 // Mac actually tests for intersection with the dirty region and tries not to
2839 // update layout for frames that are outside the dirty region. Not only does this seem
2840 // pointless (since those frames will have set a zero timer to layout anyway), but
2841 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
2842 // region but then become included later by the second frame adding rects to the dirty region
2843 // when it lays out.
2845 m_frame->document()->updateStyleIfNeeded();
2850 // Grab a copy of the children() set, as it may be mutated by the following updateLayoutAndStyleIfNeededRecursive
2851 // calls, as they can potentially re-enter a layout of the parent frame view, which may add/remove scrollbars
2852 // and thus mutates the children() set.
2853 Vector<RefPtr<FrameView> > frameViews;
2854 collectFrameViewChildren(this, frameViews);
2856 const Vector<RefPtr<FrameView> >::iterator end = frameViews.end();
2857 for (Vector<RefPtr<FrameView> >::iterator it = frameViews.begin(); it != end; ++it)
2858 (*it)->updateLayoutAndStyleIfNeededRecursive();
2860 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
2861 // painting, so we need to flush out any deferred repaints too.
2862 flushDeferredRepaints();
2865 void FrameView::flushDeferredRepaints()
2867 if (!m_deferredRepaintTimer.isActive())
2869 m_deferredRepaintTimer.stop();
2870 doDeferredRepaints();
2873 void FrameView::forceLayout(bool allowSubtree)
2875 layout(allowSubtree);
2878 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor, AdjustViewSizeOrNot shouldAdjustViewSize)
2880 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
2881 // the state of things before and after the layout
2882 if (RenderView* root = rootRenderer(this)) {
2883 float pageLogicalWidth = root->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
2884 float pageLogicalHeight = root->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
2886 LayoutUnit flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
2887 LayoutUnit flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
2888 root->setLogicalWidth(flooredPageLogicalWidth);
2889 root->setPageLogicalHeight(flooredPageLogicalHeight);
2890 root->setNeedsLayoutAndPrefWidthsRecalc();
2893 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
2894 // page width when shrunk, we will lay out at maximum shrink and clip extra content.
2895 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
2896 // implementation should not do this!
2897 bool horizontalWritingMode = root->style()->isHorizontalWritingMode();
2898 const LayoutRect& documentRect = root->documentRect();
2899 LayoutUnit docLogicalWidth = horizontalWritingMode ? documentRect.width() : documentRect.height();
2900 if (docLogicalWidth > pageLogicalWidth) {
2901 int expectedPageWidth = std::min<float>(documentRect.width(), originalPageSize.width() * maximumShrinkFactor);
2902 int expectedPageHeight = std::min<float>(documentRect.height(), originalPageSize.height() * maximumShrinkFactor);
2903 FloatSize maxPageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(originalPageSize.width(), originalPageSize.height()), FloatSize(expectedPageWidth, expectedPageHeight));
2904 pageLogicalWidth = horizontalWritingMode ? maxPageSize.width() : maxPageSize.height();
2905 pageLogicalHeight = horizontalWritingMode ? maxPageSize.height() : maxPageSize.width();
2907 flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
2908 flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
2909 root->setLogicalWidth(flooredPageLogicalWidth);
2910 root->setPageLogicalHeight(flooredPageLogicalHeight);
2911 root->setNeedsLayoutAndPrefWidthsRecalc();
2914 const LayoutRect& updatedDocumentRect = root->documentRect();
2915 LayoutUnit docLogicalHeight = horizontalWritingMode ? updatedDocumentRect.height() : updatedDocumentRect.width();
2916 LayoutUnit docLogicalTop = horizontalWritingMode ? updatedDocumentRect.y() : updatedDocumentRect.x();
2917 LayoutUnit docLogicalRight = horizontalWritingMode ? updatedDocumentRect.maxX() : updatedDocumentRect.maxY();
2918 LayoutUnit clippedLogicalLeft = 0;
2919 if (!root->style()->isLeftToRightDirection())
2920 clippedLogicalLeft = docLogicalRight - pageLogicalWidth;
2921 LayoutRect overflow(clippedLogicalLeft, docLogicalTop, pageLogicalWidth, docLogicalHeight);
2923 if (!horizontalWritingMode)
2924 overflow = overflow.transposedRect();
2925 root->clearLayoutOverflow();
2926 root->addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
2930 if (shouldAdjustViewSize)
2934 void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
2936 if (RenderView* root = rootRenderer(this)) {
2937 // Use a context with painting disabled.
2938 GraphicsContext context((PlatformGraphicsContext*)0);
2939 root->setTruncatedAt((int)floorf(oldBottom));
2940 IntRect dirtyRect(0, (int)floorf(oldTop), root->maxXLayoutOverflow(), (int)ceilf(oldBottom - oldTop));
2941 root->setPrintRect(dirtyRect);
2942 root->layer()->paint(&context, dirtyRect);
2943 *newBottom = root->bestTruncatedAt();
2944 if (*newBottom == 0)
2945 *newBottom = oldBottom;
2946 root->setPrintRect(IntRect());
2948 *newBottom = oldBottom;
2951 LayoutRect FrameView::convertFromRenderer(const RenderObject* renderer, const LayoutRect& rendererRect) const
2953 LayoutRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
2955 // Convert from page ("absolute") to FrameView coordinates.
2956 rect.moveBy(-scrollPosition());
2961 LayoutRect FrameView::convertToRenderer(const RenderObject* renderer, const LayoutRect& viewRect) const
2963 LayoutRect rect = viewRect;
2965 // Convert from FrameView coords into page ("absolute") coordinates.
2966 rect.moveBy(scrollPosition());
2968 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
2969 // move the rect for now.
2970 rect.setLocation(roundedLayoutPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
2974 LayoutPoint FrameView::convertFromRenderer(const RenderObject* renderer, const LayoutPoint& rendererPoint) const
2976 LayoutPoint point = roundedLayoutPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
2978 // Convert from page ("absolute") to FrameView coordinates.
2979 point.moveBy(-scrollPosition());
2983 LayoutPoint FrameView::convertToRenderer(const RenderObject* renderer, const LayoutPoint& viewPoint) const
2985 LayoutPoint point = viewPoint;
2987 // Convert from FrameView coords into page ("absolute") coordinates.
2988 point += IntSize(scrollX(), scrollY());
2990 return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
2993 LayoutRect FrameView::convertToContainingView(const LayoutRect& localRect) const
2995 if (const ScrollView* parentScrollView = parent()) {
2996 if (parentScrollView->isFrameView()) {
2997 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2998 // Get our renderer in the parent view
2999 RenderPart* renderer = m_frame->ownerRenderer();
3003 LayoutRect rect(localRect);
3004 // Add borders and padding??
3005 rect.move(renderer->borderLeft() + renderer->paddingLeft(),
3006 renderer->borderTop() + renderer->paddingTop());
3007 return parentView->convertFromRenderer(renderer, rect);
3010 return Widget::convertToContainingView(localRect);
3016 LayoutRect FrameView::convertFromContainingView(const LayoutRect& parentRect) const
3018 if (const ScrollView* parentScrollView = parent()) {
3019 if (parentScrollView->isFrameView()) {
3020 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
3022 // Get our renderer in the parent view
3023 RenderPart* renderer = m_frame->ownerRenderer();
3027 LayoutRect rect = parentView->convertToRenderer(renderer, parentRect);
3028 // Subtract borders and padding
3029 rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
3030 -renderer->borderTop() - renderer->paddingTop());
3034 return Widget::convertFromContainingView(parentRect);
3040 LayoutPoint FrameView::convertToContainingView(const LayoutPoint& localPoint) const
3042 if (const ScrollView* parentScrollView = parent()) {
3043 if (parentScrollView->isFrameView()) {
3044 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
3046 // Get our renderer in the parent view
3047 RenderPart* renderer = m_frame->ownerRenderer();
3051 LayoutPoint point(localPoint);
3053 // Add borders and padding
3054 point.move(renderer->borderLeft() + renderer->paddingLeft(),
3055 renderer->borderTop() + renderer->paddingTop());
3056 return parentView->convertFromRenderer(renderer, point);
3059 return Widget::convertToContainingView(localPoint);
3065 LayoutPoint FrameView::convertFromContainingView(const LayoutPoint& parentPoint) const
3067 if (const ScrollView* parentScrollView = parent()) {
3068 if (parentScrollView->isFrameView()) {
3069 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
3071 // Get our renderer in the parent view
3072 RenderPart* renderer = m_frame->ownerRenderer();
3076 LayoutPoint point = parentView->convertToRenderer(renderer, parentPoint);
3077 // Subtract borders and padding
3078 point.move(-renderer->borderLeft() - renderer->paddingLeft(),
3079 -renderer->borderTop() - renderer->paddingTop());
3083 return Widget::convertFromContainingView(parentPoint);
3090 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
3092 s_deferredRepaintDelay = p;
3095 // Negative value would mean that first few repaints happen without a delay
3096 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)
3098 s_initialDeferredRepaintDelayDuringLoading = p;
3101 // The delay grows on each repaint to this maximum value
3102 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)
3104 s_maxDeferredRepaintDelayDuringLoading = p;
3107 // On each repaint the delay increases by this amount
3108 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)
3110 s_deferredRepaintDelayIncrementDuringLoading = p;
3113 void FrameView::setTracksRepaints(bool trackRepaints)
3115 if (trackRepaints == m_isTrackingRepaints)
3118 m_trackedRepaintRects.clear();
3119 m_isTrackingRepaints = trackRepaints;
3122 bool FrameView::isVerticalDocument() const
3124 RenderView* root = rootRenderer(this);
3128 return root->style()->isHorizontalWritingMode();
3131 bool FrameView::isFlippedDocument() const
3133 RenderView* root = rootRenderer(this);
3137 return root->style()->isFlippedBlocksWritingMode();
3140 void FrameView::notifyWidgetsInAllFrames(WidgetNotification notification)
3142 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
3143 if (RenderView* root = frame->contentRenderer())
3144 root->notifyWidgets(notification);
3148 AXObjectCache* FrameView::axObjectCache() const
3150 if (frame() && frame()->document() && frame()->document()->axObjectCacheExists())
3151 return frame()->document()->axObjectCache();
3155 } // namespace WebCore