2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 * 1999 Lars Knoll <knoll@kde.org>
4 * 1999 Antti Koivisto <koivisto@kde.org>
5 * 2000 Dirk Mueller <mueller@kde.org>
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
7 * (C) 2006 Graham Dennis (graham.dennis@gmail.com)
8 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
9 * Copyright (C) 2009 Google Inc. All rights reserved.
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details.
21 * You should have received a copy of the GNU Library General Public License
22 * along with this library; see the file COPYING.LIB. If not, write to
23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 * Boston, MA 02110-1301, USA.
28 #include "FrameView.h"
30 #include "AXObjectCache.h"
31 #include "BackForwardController.h"
32 #include "CachedResourceLoader.h"
34 #include "ChromeClient.h"
35 #include "DocumentMarkerController.h"
36 #include "EventHandler.h"
37 #include "FloatRect.h"
38 #include "FocusController.h"
39 #include "FontCache.h"
41 #include "FrameActionScheduler.h"
42 #include "FrameLoader.h"
43 #include "FrameLoaderClient.h"
44 #include "FrameTree.h"
45 #include "GraphicsContext.h"
46 #include "HTMLDocument.h"
47 #include "HTMLFrameElement.h"
48 #include "HTMLFrameSetElement.h"
49 #include "HTMLNames.h"
50 #include "HTMLPlugInImageElement.h"
51 #include "InspectorClient.h"
52 #include "InspectorController.h"
53 #include "InspectorInstrumentation.h"
54 #include "OverflowEvent.h"
55 #include "RenderArena.h"
56 #include "RenderEmbeddedObject.h"
57 #include "RenderFullScreen.h"
58 #include "RenderIFrame.h"
59 #include "RenderLayer.h"
60 #include "RenderPart.h"
61 #include "RenderScrollbar.h"
62 #include "RenderScrollbarPart.h"
63 #include "RenderTheme.h"
64 #include "RenderView.h"
65 #include "ScrollAnimator.h"
66 #include "ScrollingCoordinator.h"
68 #include "StyleResolver.h"
69 #include "TextResourceDecoder.h"
71 #include <wtf/CurrentTime.h>
72 #include <wtf/TemporaryChange.h>
73 #include <wtf/UnusedParam.h>
75 #if USE(ACCELERATED_COMPOSITING)
76 #include "RenderLayerCompositor.h"
77 #include "TiledBacking.h"
81 #include "RenderSVGRoot.h"
82 #include "SVGDocument.h"
83 #include "SVGSVGElement.h"
86 #if USE(TILED_BACKING_STORE)
87 #include "TiledBackingStore.h"
90 #if ENABLE(TEXT_AUTOSIZING)
91 #include "TextAutosizer.h"
94 #if ENABLE(TIZEN_BLOCK_SENDING_RESIZE_EVENT_WHILE_LOADING)
95 #include "DocumentLoader.h"
100 using namespace HTMLNames;
102 double FrameView::sCurrentPaintTimeStamp = 0.0;
104 // REPAINT_THROTTLING now chooses default values for throttling parameters.
105 // Should be removed when applications start using runtime configuration.
106 #if ENABLE(REPAINT_THROTTLING)
108 double FrameView::s_deferredRepaintDelay = 0.025;
109 // Negative value would mean that first few repaints happen without a delay
110 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
111 // The delay grows on each repaint to this maximum value
112 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
113 // On each repaint the delay increses by this amount
114 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
116 // FIXME: Repaint throttling could be good to have on all platform.
117 // The balance between CPU use and repaint frequency will need some tuning for desktop.
118 // More hooks may be needed to reset the delay on things like GIF and CSS animations.
119 double FrameView::s_deferredRepaintDelay = 0;
120 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
121 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
122 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
125 // The maximum number of updateWidgets iterations that should be done before returning.
126 static const unsigned maxUpdateWidgetsIterations = 2;
128 static inline RenderView* rootRenderer(const FrameView* view)
130 return view->frame() ? view->frame()->contentRenderer() : 0;
133 static RenderLayer::UpdateLayerPositionsFlags updateLayerPositionFlags(RenderLayer* layer, bool isRelayoutingSubtree, bool didFullRepaint)
135 RenderLayer::UpdateLayerPositionsFlags flags = RenderLayer::defaultFlags;
137 flags &= ~RenderLayer::CheckForRepaint;
138 if (isRelayoutingSubtree && layer->isPaginated())
139 flags |= RenderLayer::UpdatePagination;
143 FrameView::FrameView(Frame* frame)
145 , m_canHaveScrollbars(true)
146 , m_slowRepaintObjectCount(0)
147 , m_layoutTimer(this, &FrameView::layoutTimerFired)
149 , m_inSynchronousPostLayout(false)
150 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
151 , m_isTransparent(false)
152 , m_baseBackgroundColor(Color::white)
153 , m_mediaType("screen")
154 , m_actionScheduler(adoptPtr(new FrameActionScheduler))
155 , m_overflowStatusDirty(true)
156 , m_viewportRenderer(0)
157 , m_wasScrolledByUser(false)
158 , m_inProgrammaticScroll(false)
159 , m_safeToPropagateScrollToParent(true)
160 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
161 , m_disableRepaints(0)
162 , m_isTrackingRepaints(false)
163 , m_shouldUpdateWhileOffscreen(true)
164 , m_deferSetNeedsLayouts(0)
165 , m_setNeedsLayoutWasDeferred(false)
167 , m_shouldAutoSize(false)
168 , m_inAutoSize(false)
169 , m_didRunAutosize(false)
173 // FIXME: Can m_frame ever be null here?
177 Page* page = m_frame->page();
181 if (m_frame == page->mainFrame()) {
182 ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed);
183 ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed);
187 PassRefPtr<FrameView> FrameView::create(Frame* frame)
189 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
191 return view.release();
194 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize)
196 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
197 view->Widget::setFrameRect(IntRect(view->location(), initialSize));
199 return view.release();
202 FrameView::~FrameView()
204 if (m_postLayoutTasksTimer.isActive()) {
205 m_postLayoutTasksTimer.stop();
206 m_actionScheduler->clear();
209 if (AXObjectCache::accessibilityEnabled() && axObjectCache())
210 axObjectCache()->remove(this);
214 // Custom scrollbars should already be destroyed at this point
215 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
216 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
218 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
219 setHasVerticalScrollbar(false);
221 ASSERT(!m_scrollCorner);
222 ASSERT(m_actionScheduler->isEmpty());
225 ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
226 RenderPart* renderer = m_frame->ownerRenderer();
227 if (renderer && renderer->widget() == this)
228 renderer->setWidget(0);
232 void FrameView::reset()
234 m_cannotBlitToWindow = false;
235 m_isOverlapped = false;
236 m_contentIsOpaque = false;
239 m_layoutTimer.stop();
241 m_delayedLayout = false;
242 m_doFullRepaint = true;
243 m_layoutSchedulingEnabled = true;
245 m_inSynchronousPostLayout = false;
247 m_nestedLayoutCount = 0;
248 m_postLayoutTasksTimer.stop();
249 m_firstLayout = true;
250 m_firstLayoutCallbackPending = false;
251 m_wasScrolledByUser = false;
252 m_safeToPropagateScrollToParent = true;
253 m_lastViewportSize = IntSize();
254 m_lastZoomFactor = 1.0f;
255 m_deferringRepaints = 0;
257 m_repaintRects.clear();
258 m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading;
259 m_deferredRepaintTimer.stop();
260 m_isTrackingRepaints = false;
261 m_trackedRepaintRects.clear();
263 m_paintBehavior = PaintBehaviorNormal;
264 m_isPainting = false;
265 m_visuallyNonEmptyCharacterCount = 0;
266 m_visuallyNonEmptyPixelCount = 0;
267 m_isVisuallyNonEmpty = false;
268 m_firstVisuallyNonEmptyLayoutCallbackPending = true;
269 m_maintainScrollPositionAnchor = 0;
270 m_disableRepaints = 0;
273 bool FrameView::isFrameView() const
278 void FrameView::clearFrame()
283 #if ENABLE(TIZEN_ELEMENTS_NESTED_IN_FLATTENED_FRAME_FIX)
284 bool FrameView::inFlattenFrame()
286 return (m_frame && m_frame->ownerElement() && (m_frame->ownerElement()->hasTagName(iframeTag) || m_frame->ownerElement()->hasTagName(frameTag) ) && m_frame->settings() && m_frame->settings()->frameFlatteningEnabled());
290 void FrameView::resetScrollbars()
292 // Reset the document's scrollbars back to our defaults before we yield the floor.
293 m_firstLayout = true;
294 setScrollbarsSuppressed(true);
295 if (m_canHaveScrollbars)
296 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
298 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
299 setScrollbarsSuppressed(false);
302 void FrameView::resetScrollbarsAndClearContentsSize()
306 setScrollbarsSuppressed(true);
307 setContentsSize(IntSize());
308 setScrollbarsSuppressed(false);
311 void FrameView::init()
315 m_margins = LayoutSize(-1, -1); // undefined
316 m_size = LayoutSize();
318 // Propagate the marginwidth/height and scrolling modes to the view.
319 Element* ownerElement = m_frame ? m_frame->ownerElement() : 0;
320 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
321 HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement);
322 if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
323 setCanHaveScrollbars(false);
324 LayoutUnit marginWidth = frameElt->marginWidth();
325 LayoutUnit marginHeight = frameElt->marginHeight();
326 if (marginWidth != -1)
327 setMarginWidth(marginWidth);
328 if (marginHeight != -1)
329 setMarginHeight(marginHeight);
333 void FrameView::detachCustomScrollbars()
335 Scrollbar* horizontalBar = horizontalScrollbar();
336 if (horizontalBar && horizontalBar->isCustomScrollbar())
337 setHasHorizontalScrollbar(false);
339 Scrollbar* verticalBar = verticalScrollbar();
340 if (verticalBar && verticalBar->isCustomScrollbar())
341 setHasVerticalScrollbar(false);
343 if (m_scrollCorner) {
344 m_scrollCorner->destroy();
349 void FrameView::recalculateScrollbarOverlayStyle()
351 ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle();
352 ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault;
354 Color backgroundColor = documentBackgroundColor();
355 #if USE(ACCELERATED_COMPOSITING)
356 if (RenderView* root = rootRenderer(this)) {
357 RenderLayerCompositor* compositor = root->compositor();
358 compositor->documentBackgroundColorDidChange();
362 if (backgroundColor.isValid()) {
363 // Reduce the background color from RGB to a lightness value
364 // and determine which scrollbar style to use based on a lightness
366 double hue, saturation, lightness;
367 backgroundColor.getHSL(hue, saturation, lightness);
369 overlayStyle = ScrollbarOverlayStyleLight;
372 if (oldOverlayStyle != overlayStyle)
373 setScrollbarOverlayStyle(overlayStyle);
376 void FrameView::clear()
378 setCanBlitOnScroll(true);
383 if (RenderPart* renderer = m_frame->ownerRenderer())
384 renderer->viewCleared();
387 setScrollbarsSuppressed(true);
390 bool FrameView::didFirstLayout() const
392 return !m_firstLayout;
395 void FrameView::invalidateRect(const IntRect& rect)
399 hostWindow()->invalidateContentsAndRootView(rect, false /*immediate*/);
406 RenderPart* renderer = m_frame->ownerRenderer();
410 IntRect repaintRect = rect;
411 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
412 renderer->borderTop() + renderer->paddingTop());
413 renderer->repaintRectangle(repaintRect);
416 void FrameView::setFrameRect(const IntRect& newRect)
418 IntRect oldRect = frameRect();
419 if (newRect == oldRect)
422 ScrollView::setFrameRect(newRect);
424 updateScrollableAreaSet();
426 #if USE(ACCELERATED_COMPOSITING)
427 if (RenderView* root = rootRenderer(this)) {
428 if (root->usesCompositing())
429 root->compositor()->frameViewDidChangeSize();
434 #if ENABLE(REQUEST_ANIMATION_FRAME)
435 bool FrameView::scheduleAnimation()
438 hostWindow()->scheduleAnimation();
445 void FrameView::setMarginWidth(LayoutUnit w)
447 // make it update the rendering area when set
448 m_margins.setWidth(w);
451 void FrameView::setMarginHeight(LayoutUnit h)
453 // make it update the rendering area when set
454 m_margins.setHeight(h);
457 bool FrameView::avoidScrollbarCreation() const
461 // with frame flattening no subframe can have scrollbars
462 // but we also cannot turn scrollbars off as we determine
463 // our flattening policy using that.
465 if (!m_frame->ownerElement())
468 if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
474 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
476 m_canHaveScrollbars = canHaveScrollbars;
477 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
480 void FrameView::updateCanHaveScrollbars()
484 scrollbarModes(hMode, vMode);
485 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
486 setCanHaveScrollbars(false);
488 setCanHaveScrollbars(true);
491 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
493 #if ENABLE(TIZEN_DISABLE_CUSTOM_SCROLLBAR)
494 if (m_frame->page() && m_frame->page()->mainFrame() == m_frame)
495 return ScrollView::createScrollbar(orientation);
498 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
499 Document* doc = m_frame->document();
501 // Try the <body> element first as a scrollbar source.
502 Element* body = doc ? doc->body() : 0;
503 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
504 return RenderScrollbar::createCustomScrollbar(this, orientation, body);
506 // If the <body> didn't have a custom style, then the root element might.
507 Element* docElement = doc ? doc->documentElement() : 0;
508 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
509 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement);
511 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
512 RenderPart* frameRenderer = m_frame->ownerRenderer();
513 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
514 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
516 // Nobody set a custom style, so we just use a native scrollbar.
517 return ScrollView::createScrollbar(orientation);
520 void FrameView::setContentsSize(const IntSize& size)
522 if (size == contentsSize())
525 m_deferSetNeedsLayouts++;
526 ScrollView::setContentsSize(size);
528 ScrollView::contentsResized();
530 Page* page = frame() ? frame()->page() : 0;
534 updateScrollableAreaSet();
536 page->chrome()->contentsSizeChanged(frame(), size); //notify only
538 m_deferSetNeedsLayouts--;
540 if (!m_deferSetNeedsLayouts)
541 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
544 void FrameView::adjustViewSize()
546 RenderView* root = rootRenderer(this);
550 ASSERT(m_frame->view() == this);
552 const IntRect rect = root->documentRect();
553 const IntSize& size = rect.size();
554 ScrollView::setScrollOrigin(IntPoint(-rect.x(), -rect.y()), !m_frame->document()->printing(), size == contentsSize());
555 #if ENABLE(TIZEN_ADJUST_CONTENTS_SIZE_FOR_MINUS_X_WORKAROUND)
556 // FIXME: In the case <html> starts at non-zero position (for example, the contents overflow to left of the <html> by dir=RTL (right-to-left)),
557 // the contents size should not include the left area of <html> because the leftmost paint position is (0,0) of the <html>.
558 // So, in here, I adjusted the contents size not to include the left area of <html>.
559 // It's not reasonable patch for Desktop browsers because it works wrong when the viewport size is changed.
560 // But now the TIZEN is only for Mobile, it works for now. (But need to be fixed ASAP)
562 setContentsSize(IntSize(size.width() + rect.x(), size.height()));
565 setContentsSize(size);
568 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
570 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
571 // overflow:hidden and overflow:scroll on <body> as applying to the document's
572 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
573 // use the root element.
575 // To combat the inability to scroll on a page with overflow:hidden on the root when scaled, disregard hidden when
576 // there is a frameScaleFactor that is greater than one on the main frame.
578 bool overrideHidden = m_frame->page() && m_frame->page()->mainFrame() == m_frame && m_frame->frameScaleFactor() > 1;
580 EOverflow overflowX = o->style()->overflowX();
581 EOverflow overflowY = o->style()->overflowY();
584 if (o->isSVGRoot()) {
585 // overflow is ignored in stand-alone SVG documents.
586 if (!toRenderSVGRoot(o)->isEmbeddedThroughFrameContainingSVGDocument())
596 hMode = ScrollbarAuto;
598 hMode = ScrollbarAlwaysOff;
601 hMode = ScrollbarAlwaysOn;
604 hMode = ScrollbarAuto;
607 // Don't set it at all.
614 vMode = ScrollbarAuto;
616 vMode = ScrollbarAlwaysOff;
619 vMode = ScrollbarAlwaysOn;
622 vMode = ScrollbarAuto;
625 // Don't set it at all.
629 m_viewportRenderer = o;
632 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy)
634 m_viewportRenderer = 0;
636 const HTMLFrameOwnerElement* owner = m_frame->ownerElement();
637 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
638 hMode = ScrollbarAlwaysOff;
639 vMode = ScrollbarAlwaysOff;
643 if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) {
644 hMode = ScrollbarAuto;
645 vMode = ScrollbarAuto;
647 hMode = ScrollbarAlwaysOff;
648 vMode = ScrollbarAlwaysOff;
652 Document* document = m_frame->document();
653 Node* documentElement = document->documentElement();
654 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
655 Node* body = document->body();
656 if (body && body->renderer()) {
657 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
658 vMode = ScrollbarAlwaysOff;
659 hMode = ScrollbarAlwaysOff;
660 } else if (body->hasTagName(bodyTag)) {
661 // It's sufficient to just check the X overflow,
662 // since it's illegal to have visible in only one direction.
663 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
664 applyOverflowToViewport(o, hMode, vMode);
666 } else if (rootRenderer)
667 applyOverflowToViewport(rootRenderer, hMode, vMode);
671 #if USE(ACCELERATED_COMPOSITING)
672 void FrameView::updateCompositingLayersAfterStyleChange()
674 RenderView* root = rootRenderer(this);
678 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
679 root->compositor()->cacheAcceleratedCompositingFlags();
680 root->compositor()->updateCompositingLayers(CompositingUpdateAfterStyleChange);
683 void FrameView::updateCompositingLayersAfterLayout()
685 RenderView* root = rootRenderer(this);
689 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
690 root->compositor()->cacheAcceleratedCompositingFlags();
691 root->compositor()->updateCompositingLayers(CompositingUpdateAfterLayout);
694 void FrameView::clearBackingStores()
696 RenderView* root = rootRenderer(this);
700 RenderLayerCompositor* compositor = root->compositor();
701 ASSERT(compositor->inCompositingMode());
702 compositor->enableCompositingMode(false);
703 compositor->clearBackingForAllLayers();
706 void FrameView::restoreBackingStores()
708 RenderView* root = rootRenderer(this);
712 RenderLayerCompositor* compositor = root->compositor();
713 compositor->enableCompositingMode(true);
714 compositor->updateCompositingLayers(CompositingUpdateAfterLayout);
717 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
719 RenderView* root = rootRenderer(this);
722 return root->compositor()->layerForHorizontalScrollbar();
725 GraphicsLayer* FrameView::layerForVerticalScrollbar() const
727 RenderView* root = rootRenderer(this);
730 return root->compositor()->layerForVerticalScrollbar();
733 GraphicsLayer* FrameView::layerForScrollCorner() const
735 RenderView* root = rootRenderer(this);
738 return root->compositor()->layerForScrollCorner();
741 TiledBacking* FrameView::tiledBacking()
743 RenderView* root = rootRenderer(this);
747 RenderLayerBacking* backing = root->layer()->backing();
751 return backing->graphicsLayer()->tiledBacking();
754 #if ENABLE(RUBBER_BANDING)
755 GraphicsLayer* FrameView::layerForOverhangAreas() const
757 RenderView* root = rootRenderer(this);
760 return root->compositor()->layerForOverhangAreas();
764 bool FrameView::syncCompositingStateForThisFrame(Frame* rootFrameForSync)
766 RenderView* root = rootRenderer(this);
768 return true; // We don't want to keep trying to update layers if we have no renderer.
770 ASSERT(m_frame->view() == this);
772 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
773 // layer content to occur before layout has happened, which will cause paintContents() to bail.
777 // If we sync compositing layers and allow the repaint to be deferred, there is time for a
778 // visible flash to occur. Instead, stop the deferred repaint timer and repaint immediately.
779 stopDelayingDeferredRepaints();
781 root->compositor()->flushPendingLayerChanges(rootFrameForSync == m_frame);
786 void FrameView::setNeedsOneShotDrawingSynchronization()
788 Page* page = frame() ? frame()->page() : 0;
790 page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
793 #endif // USE(ACCELERATED_COMPOSITING)
795 bool FrameView::hasCompositedContent() const
797 #if USE(ACCELERATED_COMPOSITING)
798 if (RenderView* root = rootRenderer(this))
799 return root->compositor()->inCompositingMode();
804 bool FrameView::hasCompositedContentIncludingDescendants() const
806 #if USE(ACCELERATED_COMPOSITING)
807 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
808 RenderView* renderView = frame->contentRenderer();
809 RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0;
811 if (compositor->inCompositingMode())
814 if (!RenderLayerCompositor::allowsIndependentlyCompositedFrames(this))
822 bool FrameView::hasCompositingAncestor() const
824 #if USE(ACCELERATED_COMPOSITING)
825 for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) {
826 if (FrameView* view = frame->view()) {
827 if (view->hasCompositedContent())
835 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
836 void FrameView::enterCompositingMode()
838 #if USE(ACCELERATED_COMPOSITING)
839 if (RenderView* root = rootRenderer(this)) {
840 root->compositor()->enableCompositingMode();
842 root->compositor()->scheduleCompositingLayerUpdate();
847 bool FrameView::isEnclosedInCompositingLayer() const
849 #if USE(ACCELERATED_COMPOSITING)
850 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
851 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
854 if (FrameView* parentView = parentFrameView())
855 return parentView->isEnclosedInCompositingLayer();
860 bool FrameView::syncCompositingStateIncludingSubframes()
862 #if USE(ACCELERATED_COMPOSITING)
863 bool allFramesSynced = syncCompositingStateForThisFrame(m_frame.get());
865 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame.get())) {
866 bool synced = child->view()->syncCompositingStateForThisFrame(m_frame.get());
867 allFramesSynced &= synced;
869 return allFramesSynced;
870 #else // USE(ACCELERATED_COMPOSITING)
875 bool FrameView::isSoftwareRenderable() const
877 #if USE(ACCELERATED_COMPOSITING)
878 RenderView* root = rootRenderer(this);
882 return !root->compositor()->has3DContent();
888 void FrameView::didMoveOnscreen()
890 #if USE(ACCELERATED_COMPOSITING)
891 if (TiledBacking* tiledBacking = this->tiledBacking())
892 tiledBacking->setIsInWindow(true);
895 if (RenderView* root = rootRenderer(this))
896 root->didMoveOnscreen();
897 contentAreaDidShow();
900 void FrameView::willMoveOffscreen()
902 #if USE(ACCELERATED_COMPOSITING)
903 if (TiledBacking* tiledBacking = this->tiledBacking())
904 tiledBacking->setIsInWindow(false);
907 if (RenderView* root = rootRenderer(this))
908 root->willMoveOffscreen();
909 contentAreaDidHide();
912 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
914 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
917 static inline void collectFrameViewChildren(FrameView* frameView, Vector<RefPtr<FrameView> >& frameViews)
919 const HashSet<RefPtr<Widget> >* viewChildren = frameView->children();
920 ASSERT(viewChildren);
922 const HashSet<RefPtr<Widget> >::iterator end = viewChildren->end();
923 for (HashSet<RefPtr<Widget> >::iterator current = viewChildren->begin(); current != end; ++current) {
924 Widget* widget = (*current).get();
925 if (widget->isFrameView())
926 frameViews.append(static_cast<FrameView*>(widget));
930 inline void FrameView::forceLayoutParentViewIfNeeded()
933 RenderPart* ownerRenderer = m_frame->ownerRenderer();
934 if (!ownerRenderer || !ownerRenderer->frame())
937 RenderBox* contentBox = embeddedContentBox();
941 RenderSVGRoot* svgRoot = toRenderSVGRoot(contentBox);
942 if (svgRoot->everHadLayout() && !svgRoot->needsLayout())
945 // If the embedded SVG document appears the first time, the ownerRenderer has already finished
946 // layout without knowing about the existence of the embedded SVG document, because RenderReplaced
947 // embeddedContentBox() returns 0, as long as the embedded document isn't loaded yet. Before
948 // bothering to lay out the SVG document, mark the ownerRenderer needing layout and ask its
949 // FrameView for a layout. After that the RenderEmbeddedObject (ownerRenderer) carries the
950 // correct size, which RenderSVGRoot::computeReplacedLogicalWidth/Height rely on, when laying
951 // out for the first time, or when the RenderSVGRoot size has changed dynamically (eg. via <script>).
952 RefPtr<FrameView> frameView = ownerRenderer->frame()->view();
954 // Mark the owner renderer as needing layout.
955 ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc();
957 // Synchronously enter layout, to layout the view containing the host object/embed/iframe.
963 void FrameView::layout(bool allowSubtree)
968 // Protect the view from being deleted during layout (in recalcStyle)
969 RefPtr<FrameView> protector(this);
971 bool inChildFrameLayoutWithFrameFlattening = isInChildFrameWithFrameFlattening();
973 if (inChildFrameLayoutWithFrameFlattening) {
974 if (doLayoutWithFrameFlattening(allowSubtree))
978 m_layoutTimer.stop();
979 m_delayedLayout = false;
980 m_setNeedsLayoutWasDeferred = false;
983 // FIXME: Do we need to set m_size.width here?
984 // FIXME: Should we set m_size.height here too?
985 m_size.setWidth(layoutWidth());
989 // we shouldn't enter layout() while painting
990 ASSERT(!isPainting());
994 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
996 if (!allowSubtree && m_layoutRoot) {
997 m_layoutRoot->markContainingBlocksForLayout(false);
1001 ASSERT(m_frame->view() == this);
1003 Document* document = m_frame->document();
1004 ASSERT(!document->inPageCache());
1009 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1011 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_postLayoutTasksTimer.isActive() && !inChildFrameLayoutWithFrameFlattening) {
1012 // This is a new top-level layout. If there are any remaining tasks from the previous
1013 // layout, finish them now.
1014 m_inSynchronousPostLayout = true;
1015 performPostLayoutTasks();
1016 m_inSynchronousPostLayout = false;
1019 // Viewport-dependent media queries may cause us to need completely different style information.
1021 if (document->styleResolver()->affectedByViewportChange()) {
1022 document->styleResolverChanged(RecalcStyleImmediately);
1023 InspectorInstrumentation::mediaQueryResultChanged(document);
1025 document->evaluateMediaQueryList();
1027 // Always ensure our style info is up-to-date. This can happen in situations where
1028 // the layout beats any sort of style recalc update that needs to occur.
1029 document->updateStyleIfNeeded();
1031 subtree = m_layoutRoot;
1033 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
1034 // so there's no point to continuing to layout
1035 if (protector->hasOneRef())
1038 root = subtree ? m_layoutRoot : document->renderer();
1040 // FIXME: Do we need to set m_size here?
1043 } // Reset m_layoutSchedulingEnabled to its previous value.
1044 // The only reason the scoping was closed here is allow fontCachePurgePreventer
1045 // to outlive the change and reset of m_layoutSchedulingEnabled.
1047 FontCachePurgePreventer fontCachePurgePreventer;
1050 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1052 m_nestedLayoutCount++;
1054 if (!m_layoutRoot) {
1055 Document* document = m_frame->document();
1056 Node* body = document->body();
1057 if (body && body->renderer()) {
1058 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
1059 body->renderer()->setChildNeedsLayout(true);
1060 } else if (body->hasTagName(bodyTag)) {
1061 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
1062 body->renderer()->setChildNeedsLayout(true);
1066 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1067 if (m_firstLayout && !m_frame->ownerElement())
1068 printf("Elapsed time before first layout: %d\n", document->elapsedTime());
1072 autoSizeIfEnabled();
1074 ScrollbarMode hMode;
1075 ScrollbarMode vMode;
1076 calculateScrollbarModesForLayout(hMode, vMode);
1078 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
1081 // Now set our scrollbar state for the layout.
1082 ScrollbarMode currentHMode = horizontalScrollbarMode();
1083 ScrollbarMode currentVMode = verticalScrollbarMode();
1085 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
1086 if (m_firstLayout) {
1087 setScrollbarsSuppressed(true);
1089 m_firstLayout = false;
1090 m_firstLayoutCallbackPending = true;
1091 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
1092 m_lastViewportSize = fixedLayoutSize();
1094 m_lastViewportSize = visibleContentRect(true /*includeScrollbars*/).size();
1095 m_lastZoomFactor = root->style()->zoom();
1097 // Set the initial vMode to AlwaysOn if we're auto.
1098 if (vMode == ScrollbarAuto)
1099 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
1100 // Set the initial hMode to AlwaysOff if we're auto.
1101 if (hMode == ScrollbarAuto)
1102 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
1104 setScrollbarModes(hMode, vMode);
1105 setScrollbarsSuppressed(false, true);
1107 setScrollbarModes(hMode, vMode);
1110 LayoutSize oldSize = m_size;
1112 m_size = LayoutSize(layoutWidth(), layoutHeight());
1114 if (oldSize != m_size) {
1115 m_doFullRepaint = true;
1116 if (!m_firstLayout) {
1117 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
1118 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
1119 if (bodyRenderer && bodyRenderer->stretchesToViewport())
1120 bodyRenderer->setChildNeedsLayout(true);
1121 else if (rootRenderer && rootRenderer->stretchesToViewport())
1122 rootRenderer->setChildNeedsLayout(true);
1127 layer = root->enclosingLayer();
1129 m_actionScheduler->pause();
1132 bool disableLayoutState = false;
1134 RenderView* view = root->view();
1135 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
1136 view->pushLayoutState(root);
1138 LayoutStateDisabler layoutStateDisabler(disableLayoutState ? root->view() : 0);
1141 beginDeferredRepaints();
1142 forceLayoutParentViewIfNeeded();
1144 #if ENABLE(TEXT_AUTOSIZING)
1145 bool autosized = document->textAutosizer()->processSubtree(root);
1146 if (autosized && root->needsLayout())
1149 endDeferredRepaints();
1153 root->view()->popLayoutState(root);
1156 } // Reset m_layoutSchedulingEnabled to its previous value.
1158 if (!subtree && !toRenderView(root)->printing())
1161 // Now update the positions of all layers.
1162 beginDeferredRepaints();
1163 bool hasLayerOffset;
1164 LayoutPoint offsetFromRoot = layer->computeOffsetFromRoot(hasLayerOffset);
1165 if (m_doFullRepaint)
1166 root->view()->repaint(); // FIXME: This isn't really right, since the RenderView doesn't fully encompass the visibleContentRect(). It just happens
1167 // to work out most of the time, since first layouts and printing don't have you scrolled anywhere.
1169 layer->updateLayerPositions(hasLayerOffset ? &offsetFromRoot : 0, updateLayerPositionFlags(layer, subtree, m_doFullRepaint));
1170 endDeferredRepaints();
1172 #if USE(ACCELERATED_COMPOSITING)
1173 updateCompositingLayersAfterLayout();
1178 #if PLATFORM(MAC) || PLATFORM(CHROMIUM)
1179 if (AXObjectCache::accessibilityEnabled())
1180 root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true);
1182 #if ENABLE(DASHBOARD_SUPPORT)
1183 updateDashboardRegions();
1186 ASSERT(!root->needsLayout());
1188 updateCanBlitOnScrollRecursively();
1190 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1191 updateOverflowStatus(layoutWidth() < contentsWidth(),
1192 layoutHeight() < contentsHeight());
1194 if (!m_postLayoutTasksTimer.isActive()) {
1195 if (!m_inSynchronousPostLayout) {
1196 if (inChildFrameLayoutWithFrameFlattening) {
1197 if (RenderView* root = rootRenderer(this))
1198 root->updateWidgetPositions();
1200 m_inSynchronousPostLayout = true;
1201 // Calls resumeScheduledEvents()
1202 performPostLayoutTasks();
1203 m_inSynchronousPostLayout = false;
1207 if (!m_postLayoutTasksTimer.isActive() && (needsLayout() || m_inSynchronousPostLayout || inChildFrameLayoutWithFrameFlattening)) {
1208 // If we need layout or are already in a synchronous call to postLayoutTasks(),
1209 // defer widget updates and event dispatch until after we return. postLayoutTasks()
1210 // can make us need to update again, and we can get stuck in a nasty cycle unless
1211 // we call it through the timer here.
1212 m_postLayoutTasksTimer.startOneShot(0);
1213 if (needsLayout()) {
1214 m_actionScheduler->pause();
1219 m_actionScheduler->resume();
1222 InspectorInstrumentation::didLayout(cookie);
1224 m_nestedLayoutCount--;
1225 if (m_nestedLayoutCount)
1228 Page* page = frame() ? frame()->page() : 0;
1232 page->chrome()->client()->layoutUpdated(frame());
1235 RenderBox* FrameView::embeddedContentBox() const
1238 RenderView* root = rootRenderer(this);
1242 RenderObject* rootChild = root->firstChild();
1243 if (!rootChild || !rootChild->isBox())
1246 // Curently only embedded SVG documents participate in the size-negotiation logic.
1247 if (rootChild->isSVGRoot())
1248 return toRenderBox(rootChild);
1254 void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object)
1256 if (!m_widgetUpdateSet)
1257 m_widgetUpdateSet = adoptPtr(new RenderEmbeddedObjectSet);
1259 // Tell the DOM element that it needs a widget update.
1260 Node* node = object->node();
1261 if (node->hasTagName(objectTag) || node->hasTagName(embedTag)) {
1262 HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(node);
1263 pluginElement->setNeedsWidgetUpdate(true);
1266 m_widgetUpdateSet->add(object);
1269 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object)
1271 if (!m_widgetUpdateSet)
1274 m_widgetUpdateSet->remove(object);
1277 void FrameView::setMediaType(const String& mediaType)
1279 m_mediaType = mediaType;
1282 String FrameView::mediaType() const
1284 // See if we have an override type.
1285 String overrideType = m_frame->loader()->client()->overrideMediaType();
1286 if (!overrideType.isNull())
1287 return overrideType;
1291 void FrameView::adjustMediaTypeForPrinting(bool printing)
1294 if (m_mediaTypeWhenNotPrinting.isNull())
1295 m_mediaTypeWhenNotPrinting = mediaType();
1296 setMediaType("print");
1298 if (!m_mediaTypeWhenNotPrinting.isNull())
1299 setMediaType(m_mediaTypeWhenNotPrinting);
1300 m_mediaTypeWhenNotPrinting = String();
1304 bool FrameView::useSlowRepaints(bool considerOverlap) const
1306 bool mustBeSlow = m_slowRepaintObjectCount > 0 || (platformWidget() && hasFixedObjects());
1308 // FIXME: WidgetMac.mm makes the assumption that useSlowRepaints ==
1309 // m_contentIsOpaque, so don't take the fast path for composited layers
1310 // if they are a platform widget in order to get painting correctness
1311 // for transparent layers. See the comment in WidgetMac::paint.
1312 if (contentsInCompositedLayer() && !platformWidget())
1315 #if PLATFORM(CHROMIUM)
1316 // The chromium compositor does not support scrolling a non-composited frame within a composited page through
1317 // the fast scrolling path, so force slow scrolling in that case.
1318 if (m_frame->ownerElement() && !hasCompositedContent() && m_frame->page() && m_frame->page()->mainFrame()->view()->hasCompositedContent())
1322 bool isOverlapped = m_isOverlapped && considerOverlap;
1324 if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque)
1327 if (FrameView* parentView = parentFrameView())
1328 return parentView->useSlowRepaints(considerOverlap);
1333 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1335 return useSlowRepaints(false);
1338 void FrameView::updateCanBlitOnScrollRecursively()
1340 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1341 if (FrameView* view = frame->view())
1342 view->setCanBlitOnScroll(!view->useSlowRepaints());
1346 bool FrameView::contentsInCompositedLayer() const
1348 #if USE(ACCELERATED_COMPOSITING)
1349 RenderView* root = rootRenderer(this);
1350 if (root && root->isComposited()) {
1351 GraphicsLayer* layer = root->layer()->backing()->graphicsLayer();
1352 if (layer && layer->drawsContent())
1359 void FrameView::setCannotBlitToWindow()
1361 m_cannotBlitToWindow = true;
1362 updateCanBlitOnScrollRecursively();
1365 void FrameView::addSlowRepaintObject()
1367 if (!m_slowRepaintObjectCount++) {
1368 updateCanBlitOnScrollRecursively();
1370 if (Page* page = m_frame->page()) {
1371 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1372 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1377 void FrameView::removeSlowRepaintObject()
1379 ASSERT(m_slowRepaintObjectCount > 0);
1380 m_slowRepaintObjectCount--;
1381 if (!m_slowRepaintObjectCount) {
1382 updateCanBlitOnScrollRecursively();
1384 if (Page* page = m_frame->page()) {
1385 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1386 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1391 void FrameView::addFixedObject(RenderObject* object)
1393 if (!m_fixedObjects)
1394 m_fixedObjects = adoptPtr(new FixedObjectSet);
1396 if (!m_fixedObjects->contains(object)) {
1397 m_fixedObjects->add(object);
1398 if (platformWidget())
1399 updateCanBlitOnScrollRecursively();
1401 if (Page* page = m_frame->page()) {
1402 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1403 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1408 void FrameView::removeFixedObject(RenderObject* object)
1410 ASSERT(hasFixedObjects());
1412 if (m_fixedObjects->contains(object)) {
1413 m_fixedObjects->remove(object);
1414 if (Page* page = m_frame->page()) {
1415 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1416 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1419 // FIXME: In addFixedObject() we only call this if there's a platform widget,
1420 // why isn't the same check being made here?
1421 updateCanBlitOnScrollRecursively();
1425 static int fixedPositionScrollOffset(int scrollPosition, int maxValue, int scrollOrigin, float dragFactor)
1430 if (!scrollOrigin) {
1431 if (scrollPosition < 0)
1433 else if (scrollPosition > maxValue)
1434 scrollPosition = maxValue;
1436 if (scrollPosition > 0)
1438 else if (scrollPosition < -maxValue)
1439 scrollPosition = -maxValue;
1442 return scrollPosition * dragFactor;
1445 IntSize FrameView::scrollOffsetForFixedPosition() const
1447 IntRect visibleContentRect = this->visibleContentRect();
1448 IntSize contentsSize = this->contentsSize();
1449 IntPoint scrollPosition = this->scrollPosition();
1450 IntPoint scrollOrigin = this->scrollOrigin();
1452 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
1453 // When showing IME, the fixed position element can be scrolled over maxOffset.
1454 IntSize maxOffset(contentsSize.width(), contentsSize.height());
1456 IntSize maxOffset(contentsSize.width() - visibleContentRect.width(), contentsSize.height() - visibleContentRect.height());
1459 float frameScaleFactor = m_frame ? m_frame->frameScaleFactor() : 1;
1461 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
1462 FloatSize dragFactor = fixedElementsLayoutRelativeToFrame() ? FloatSize(1, 1) : FloatSize(
1463 (contentsSize.width() * frameScaleFactor) / maxOffset.width(),
1464 (contentsSize.height() * frameScaleFactor) / maxOffset.height());
1466 FloatSize dragFactor = fixedElementsLayoutRelativeToFrame() ? FloatSize(1, 1) : FloatSize(
1467 (contentsSize.width() - visibleContentRect.width() * frameScaleFactor) / maxOffset.width(),
1468 (contentsSize.height() - visibleContentRect.height() * frameScaleFactor) / maxOffset.height());
1471 int x = fixedPositionScrollOffset(scrollPosition.x(), maxOffset.width(), scrollOrigin.x(), dragFactor.width() / frameScaleFactor);
1472 int y = fixedPositionScrollOffset(scrollPosition.y(), maxOffset.height(), scrollOrigin.y(), dragFactor.height() / frameScaleFactor);
1474 return IntSize(x, y);
1477 bool FrameView::fixedElementsLayoutRelativeToFrame() const
1480 if (!m_frame->settings())
1483 return m_frame->settings()->fixedElementsLayoutRelativeToFrame();
1486 IntPoint FrameView::currentMousePosition() const
1488 return m_frame ? m_frame->eventHandler()->currentMousePosition() : IntPoint();
1491 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1493 if (!m_fixedObjects || m_fixedObjects->isEmpty()) {
1494 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1498 const bool isCompositedContentLayer = contentsInCompositedLayer();
1500 // Get the rects of the fixed objects visible in the rectToScroll
1501 Region regionToUpdate;
1502 FixedObjectSet::const_iterator end = m_fixedObjects->end();
1503 for (FixedObjectSet::const_iterator it = m_fixedObjects->begin(); it != end; ++it) {
1504 RenderObject* renderer = *it;
1505 if (renderer->style()->position() != FixedPosition)
1507 #if USE(ACCELERATED_COMPOSITING)
1508 if (renderer->isComposited())
1512 // Fixed items should always have layers.
1513 ASSERT(renderer->hasLayer());
1514 RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
1516 #if ENABLE(CSS_FILTERS)
1517 if (layer->hasAncestorWithFilterOutsets()) {
1518 // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot
1519 // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
1523 IntRect updateRect = pixelSnappedIntRect(layer->repaintRectIncludingNonCompositingDescendants());
1524 updateRect = contentsToRootView(updateRect);
1525 if (!isCompositedContentLayer && clipsRepaints())
1526 updateRect.intersect(rectToScroll);
1527 if (!updateRect.isEmpty())
1528 regionToUpdate.unite(updateRect);
1531 // The area to be painted by fixed objects exceeds 50% of the area of the view, we cannot use the fast path.
1532 if (regionToUpdate.totalArea() > (clipRect.width() * clipRect.height() * 0.5))
1536 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1538 // 2) update the area of fixed objects that has been invalidated
1539 Vector<IntRect> subRectsToUpdate = regionToUpdate.rects();
1540 size_t fixObjectsCount = subRectsToUpdate.size();
1541 for (size_t i = 0; i < fixObjectsCount; ++i) {
1542 IntRect updateRect = subRectsToUpdate[i];
1543 IntRect scrolledRect = updateRect;
1544 scrolledRect.move(scrollDelta);
1545 updateRect.unite(scrolledRect);
1546 #if USE(ACCELERATED_COMPOSITING)
1547 if (isCompositedContentLayer) {
1548 updateRect = rootViewToContents(updateRect);
1549 RenderView* root = rootRenderer(this);
1551 root->layer()->setBackingNeedsRepaintInRect(updateRect);
1555 if (clipsRepaints())
1556 updateRect.intersect(rectToScroll);
1557 hostWindow()->invalidateContentsAndRootView(updateRect, false);
1563 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1565 #if USE(ACCELERATED_COMPOSITING)
1566 if (contentsInCompositedLayer()) {
1567 RenderView* root = rootRenderer(this);
1570 IntRect updateRect = visibleContentRect();
1572 // Make sure to "apply" the scale factor here since we're converting from frame view
1573 // coordinates to layer backing coordinates.
1574 updateRect.scale(1 / m_frame->frameScaleFactor());
1576 root->layer()->setBackingNeedsRepaintInRect(updateRect);
1578 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1579 if (isEnclosedInCompositingLayer()) {
1580 LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1581 frameRenderer->borderTop() + frameRenderer->paddingTop(),
1582 visibleWidth(), visibleHeight());
1583 frameRenderer->repaintRectangle(rect);
1589 ScrollView::scrollContentsSlowPath(updateRect);
1592 // Note that this gets called at painting time.
1593 void FrameView::setIsOverlapped(bool isOverlapped)
1595 if (isOverlapped == m_isOverlapped)
1598 m_isOverlapped = isOverlapped;
1599 updateCanBlitOnScrollRecursively();
1601 #if USE(ACCELERATED_COMPOSITING)
1602 if (hasCompositedContentIncludingDescendants()) {
1603 // Overlap can affect compositing tests, so if it changes, we need to trigger
1604 // a layer update in the parent document.
1605 if (Frame* parentFrame = m_frame->tree()->parent()) {
1606 if (RenderView* parentView = parentFrame->contentRenderer()) {
1607 RenderLayerCompositor* compositor = parentView->compositor();
1608 compositor->setCompositingLayersNeedRebuild();
1609 compositor->scheduleCompositingLayerUpdate();
1613 if (RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) {
1614 // We also need to trigger reevaluation for this and all descendant frames,
1615 // since a frame uses compositing if any ancestor is compositing.
1616 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1617 if (RenderView* view = frame->contentRenderer()) {
1618 RenderLayerCompositor* compositor = view->compositor();
1619 compositor->setCompositingLayersNeedRebuild();
1620 compositor->scheduleCompositingLayerUpdate();
1628 bool FrameView::isOverlappedIncludingAncestors() const
1633 if (FrameView* parentView = parentFrameView()) {
1634 if (parentView->isOverlapped())
1641 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1643 if (contentIsOpaque == m_contentIsOpaque)
1646 m_contentIsOpaque = contentIsOpaque;
1647 updateCanBlitOnScrollRecursively();
1650 void FrameView::restoreScrollbar()
1652 setScrollbarsSuppressed(false);
1655 bool FrameView::scrollToFragment(const KURL& url)
1657 // If our URL has no ref, then we have no place we need to jump to.
1658 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1659 // and possibly repaint because :target pseudo class may have been
1660 // set (see bug 11321).
1661 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1664 String fragmentIdentifier = url.fragmentIdentifier();
1665 if (scrollToAnchor(fragmentIdentifier))
1668 // Try again after decoding the ref, based on the document's encoding.
1669 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1670 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1675 bool FrameView::scrollToAnchor(const String& name)
1677 ASSERT(m_frame->document());
1679 if (!m_frame->document()->haveStylesheetsLoaded()) {
1680 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1684 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1686 Element* anchorNode = m_frame->document()->findAnchor(name);
1688 // Setting to null will clear the current target.
1689 m_frame->document()->setCSSTarget(anchorNode);
1692 if (m_frame->document()->isSVGDocument()) {
1693 if (SVGSVGElement* svg = static_cast<SVGDocument*>(m_frame->document())->rootElement()) {
1694 svg->setupInitialView(name, anchorNode);
1701 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1702 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1705 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1709 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1711 m_maintainScrollPositionAnchor = anchorNode;
1712 if (!m_maintainScrollPositionAnchor)
1715 // We need to update the layout before scrolling, otherwise we could
1716 // really mess things up if an anchor scroll comes at a bad moment.
1717 m_frame->document()->updateStyleIfNeeded();
1718 // Only do a layout if changes have occurred that make it necessary.
1719 RenderView* root = rootRenderer(this);
1720 if (root && root->needsLayout())
1726 void FrameView::scrollElementToRect(Element* element, const IntRect& rect)
1728 m_frame->document()->updateLayoutIgnorePendingStylesheets();
1730 LayoutRect bounds = element->getRect();
1731 int centeringOffsetX = (rect.width() - bounds.width()) / 2;
1732 int centeringOffsetY = (rect.height() - bounds.height()) / 2;
1733 setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y()));
1736 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1738 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1739 m_maintainScrollPositionAnchor = 0;
1741 if (requestScrollPositionUpdate(scrollPoint))
1744 ScrollView::setScrollPosition(scrollPoint);
1747 void FrameView::delegatesScrollingDidChange()
1749 #if USE(ACCELERATED_COMPOSITING)
1750 // When we switch to delgatesScrolling mode, we should destroy the scrolling/clipping layers in RenderLayerCompositor.
1751 if (hasCompositedContent())
1752 clearBackingStores();
1756 void FrameView::setFixedVisibleContentRect(const IntRect& visibleContentRect)
1758 bool visibleContentSizeDidChange = false;
1759 if (visibleContentRect.size() != this->fixedVisibleContentRect().size()) {
1760 // When the viewport size changes or the content is scaled, we need to
1761 // reposition the fixed positioned elements.
1762 if (RenderView* root = rootRenderer(this))
1763 root->setFixedPositionedObjectsNeedLayout();
1764 visibleContentSizeDidChange = true;
1767 IntSize offset = scrollOffset();
1768 ScrollView::setFixedVisibleContentRect(visibleContentRect);
1769 if (offset != scrollOffset()) {
1770 if (m_frame->page()->settings()->acceleratedCompositingForFixedPositionEnabled())
1771 updateFixedElementsAfterScrolling();
1772 scrollAnimator()->setCurrentPosition(scrollPosition());
1773 scrollPositionChanged();
1775 if (visibleContentSizeDidChange) {
1776 // Update the scroll-bars to calculate new page-step size.
1777 updateScrollbars(scrollOffset());
1779 frame()->loader()->client()->didChangeScrollOffset();
1782 void FrameView::scrollPositionChangedViaPlatformWidget()
1784 repaintFixedElementsAfterScrolling();
1785 updateFixedElementsAfterScrolling();
1786 scrollPositionChanged();
1789 void FrameView::scrollPositionChanged()
1791 frame()->eventHandler()->sendScrollEvent();
1792 frame()->eventHandler()->dispatchFakeMouseMoveEventSoon();
1794 #if USE(ACCELERATED_COMPOSITING)
1795 if (RenderView* root = rootRenderer(this)) {
1796 if (root->usesCompositing())
1797 root->compositor()->frameViewDidScroll();
1802 void FrameView::repaintFixedElementsAfterScrolling()
1804 // For fixed position elements, update widget positions and compositing layers after scrolling,
1805 // but only if we're not inside of layout.
1806 if (!m_nestedLayoutCount && hasFixedObjects()) {
1807 if (RenderView* root = rootRenderer(this)) {
1808 root->updateWidgetPositions();
1809 root->layer()->updateLayerPositionsAfterScroll();
1814 void FrameView::updateFixedElementsAfterScrolling()
1816 #if USE(ACCELERATED_COMPOSITING)
1817 if (m_nestedLayoutCount <= 1 && hasFixedObjects()) {
1818 if (RenderView* root = rootRenderer(this)) {
1819 root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
1825 bool FrameView::shouldRubberBandInDirection(ScrollDirection direction) const
1827 Page* page = frame() ? frame()->page() : 0;
1829 return ScrollView::shouldRubberBandInDirection(direction);
1830 return page->chrome()->client()->shouldRubberBandInDirection(direction);
1833 bool FrameView::requestScrollPositionUpdate(const IntPoint& position)
1835 #if ENABLE(THREADED_SCROLLING)
1836 if (Page* page = m_frame->page()) {
1837 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1838 return scrollingCoordinator->requestScrollPositionUpdate(this, position);
1841 UNUSED_PARAM(position);
1847 #if ENABLE(TIZEN_WEBKIT2_HISTORICAL_RESTORE_VISIBLE_CONTENT_RECT)
1848 void FrameView::requestVisibleContentRectRestore(const IntPoint& position, float scale)
1850 Page* page = m_frame->page();
1853 if (page->mainFrame() != m_frame)
1855 page->chrome()->client()->requestVisibleContentRectRestore(position, scale);
1859 HostWindow* FrameView::hostWindow() const
1861 Page* page = frame() ? frame()->page() : 0;
1864 return page->chrome();
1867 const unsigned cRepaintRectUnionThreshold = 25;
1869 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
1871 ASSERT(!m_frame->ownerElement());
1873 if (m_isTrackingRepaints) {
1874 IntRect repaintRect = r;
1875 repaintRect.move(-scrollOffset());
1876 m_trackedRepaintRects.append(repaintRect);
1879 double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay();
1880 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
1881 IntRect paintRect = r;
1882 if (clipsRepaints() && !paintsEntireContents())
1883 paintRect.intersect(visibleContentRect());
1884 if (paintRect.isEmpty())
1886 if (m_repaintCount == cRepaintRectUnionThreshold) {
1887 IntRect unionedRect;
1888 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
1889 unionedRect.unite(pixelSnappedIntRect(m_repaintRects[i]));
1890 m_repaintRects.clear();
1891 m_repaintRects.append(unionedRect);
1893 if (m_repaintCount < cRepaintRectUnionThreshold)
1894 m_repaintRects.append(paintRect);
1896 m_repaintRects[0].unite(paintRect);
1899 if (!m_deferringRepaints)
1900 startDeferredRepaintTimer(delay);
1905 if (!shouldUpdate(immediate))
1908 #if USE(TILED_BACKING_STORE)
1909 if (frame()->tiledBackingStore()) {
1910 frame()->tiledBackingStore()->invalidate(r);
1914 ScrollView::repaintContentRectangle(r, immediate);
1917 void FrameView::contentsResized()
1919 ScrollView::contentsResized();
1923 void FrameView::visibleContentsResized()
1925 // We check to make sure the view is attached to a frame() as this method can
1926 // be triggered before the view is attached by Frame::createView(...) setting
1927 // various values such as setScrollBarModes(...) for example. An ASSERT is
1928 // triggered when a view is layout before being attached to a frame().
1929 if (!frame()->view())
1935 #if USE(ACCELERATED_COMPOSITING)
1936 if (RenderView* root = rootRenderer(this)) {
1937 if (root->usesCompositing())
1938 root->compositor()->frameViewDidChangeSize();
1943 void FrameView::beginDeferredRepaints()
1945 Page* page = m_frame->page();
1946 if (page->mainFrame() != m_frame) {
1947 page->mainFrame()->view()->beginDeferredRepaints();
1951 m_deferringRepaints++;
1954 void FrameView::endDeferredRepaints()
1956 Page* page = m_frame->page();
1957 if (page->mainFrame() != m_frame) {
1958 page->mainFrame()->view()->endDeferredRepaints();
1962 ASSERT(m_deferringRepaints > 0);
1964 if (--m_deferringRepaints)
1967 if (m_deferredRepaintTimer.isActive())
1970 if (double delay = adjustedDeferredRepaintDelay()) {
1971 startDeferredRepaintTimer(delay);
1975 doDeferredRepaints();
1978 void FrameView::startDeferredRepaintTimer(double delay)
1980 if (m_deferredRepaintTimer.isActive())
1983 if (m_disableRepaints)
1986 m_deferredRepaintTimer.startOneShot(delay);
1989 void FrameView::checkStopDelayingDeferredRepaints()
1991 Document* document = m_frame->document();
1992 if (document && (document->parsing() || document->cachedResourceLoader()->requestCount()))
1995 stopDelayingDeferredRepaints();
1998 void FrameView::stopDelayingDeferredRepaints()
2000 if (!m_deferredRepaintTimer.isActive())
2003 m_deferredRepaintTimer.stop();
2005 doDeferredRepaints();
2008 void FrameView::doDeferredRepaints()
2010 if (m_disableRepaints)
2013 ASSERT(!m_deferringRepaints);
2014 if (!shouldUpdate()) {
2015 m_repaintRects.clear();
2019 unsigned size = m_repaintRects.size();
2020 for (unsigned i = 0; i < size; i++) {
2021 #if USE(TILED_BACKING_STORE)
2022 if (frame()->tiledBackingStore()) {
2023 frame()->tiledBackingStore()->invalidate(pixelSnappedIntRect(m_repaintRects[i]));
2027 ScrollView::repaintContentRectangle(pixelSnappedIntRect(m_repaintRects[i]), false);
2029 m_repaintRects.clear();
2032 updateDeferredRepaintDelay();
2035 void FrameView::updateDeferredRepaintDelay()
2037 Document* document = m_frame->document();
2038 if (!document || (!document->parsing() && !document->cachedResourceLoader()->requestCount())) {
2039 m_deferredRepaintDelay = s_deferredRepaintDelay;
2042 if (m_deferredRepaintDelay < s_maxDeferredRepaintDelayDuringLoading) {
2043 m_deferredRepaintDelay += s_deferredRepaintDelayIncrementDuringLoading;
2044 if (m_deferredRepaintDelay > s_maxDeferredRepaintDelayDuringLoading)
2045 m_deferredRepaintDelay = s_maxDeferredRepaintDelayDuringLoading;
2049 void FrameView::resetDeferredRepaintDelay()
2051 m_deferredRepaintDelay = 0;
2052 if (m_deferredRepaintTimer.isActive()) {
2053 m_deferredRepaintTimer.stop();
2054 if (!m_deferringRepaints)
2055 doDeferredRepaints();
2059 double FrameView::adjustedDeferredRepaintDelay() const
2061 ASSERT(!m_deferringRepaints);
2062 if (!m_deferredRepaintDelay)
2064 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
2065 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
2068 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
2070 doDeferredRepaints();
2073 void FrameView::beginDisableRepaints()
2075 m_disableRepaints++;
2078 void FrameView::endDisableRepaints()
2080 ASSERT(m_disableRepaints > 0);
2081 m_disableRepaints--;
2084 void FrameView::layoutTimerFired(Timer<FrameView>*)
2086 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2087 if (!m_frame->document()->ownerElement())
2088 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
2093 void FrameView::scheduleRelayout()
2095 // FIXME: We should assert the page is not in the page cache, but that is causing
2096 // too many false assertions. See <rdar://problem/7218118>.
2097 ASSERT(m_frame->view() == this);
2100 m_layoutRoot->markContainingBlocksForLayout(false);
2103 if (!m_layoutSchedulingEnabled)
2107 if (!m_frame->document()->shouldScheduleLayout())
2110 // When frame flattening is enabled, the contents of the frame could affect the layout of the parent frames.
2111 // Also invalidate parent frame starting from the owner element of this frame.
2112 if (m_frame->ownerRenderer() && isInChildFrameWithFrameFlattening())
2113 m_frame->ownerRenderer()->setNeedsLayout(true, MarkContainingBlockChain);
2115 int delay = m_frame->document()->minimumLayoutDelay();
2116 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
2117 unscheduleRelayout();
2118 if (m_layoutTimer.isActive())
2121 m_delayedLayout = delay != 0;
2123 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2124 if (!m_frame->document()->ownerElement())
2125 printf("Scheduling layout for %d\n", delay);
2128 m_layoutTimer.startOneShot(delay * 0.001);
2131 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
2133 for (RenderObject* r = descendant; r; r = r->container()) {
2140 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
2142 ASSERT(m_frame->view() == this);
2144 RenderView* root = rootRenderer(this);
2145 if (root && root->needsLayout()) {
2147 relayoutRoot->markContainingBlocksForLayout(false);
2151 if (layoutPending() || !m_layoutSchedulingEnabled) {
2152 if (m_layoutRoot != relayoutRoot) {
2153 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
2154 // Keep the current root
2155 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
2156 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2157 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
2158 // Re-root at relayoutRoot
2159 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
2160 m_layoutRoot = relayoutRoot;
2161 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2163 // Just do a full relayout
2165 m_layoutRoot->markContainingBlocksForLayout(false);
2167 relayoutRoot->markContainingBlocksForLayout(false);
2170 } else if (m_layoutSchedulingEnabled) {
2171 int delay = m_frame->document()->minimumLayoutDelay();
2172 m_layoutRoot = relayoutRoot;
2173 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2174 m_delayedLayout = delay != 0;
2175 m_layoutTimer.startOneShot(delay * 0.001);
2179 bool FrameView::layoutPending() const
2181 return m_layoutTimer.isActive();
2184 bool FrameView::needsLayout() const
2186 // This can return true in cases where the document does not have a body yet.
2187 // Document::shouldScheduleLayout takes care of preventing us from scheduling
2188 // layout in that case.
2192 RenderView* root = rootRenderer(this);
2193 return layoutPending()
2194 || (root && root->needsLayout())
2196 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
2199 void FrameView::setNeedsLayout()
2201 if (m_deferSetNeedsLayouts) {
2202 m_setNeedsLayoutWasDeferred = true;
2206 if (RenderView* root = rootRenderer(this))
2207 root->setNeedsLayout(true);
2210 void FrameView::unscheduleRelayout()
2212 if (!m_layoutTimer.isActive())
2215 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2216 if (!m_frame->document()->ownerElement())
2217 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
2220 m_layoutTimer.stop();
2221 m_delayedLayout = false;
2224 #if ENABLE(REQUEST_ANIMATION_FRAME)
2225 void FrameView::serviceScriptedAnimations(DOMTimeStamp time)
2227 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext()) {
2228 frame->view()->serviceScrollAnimations();
2229 frame->animation()->serviceAnimations();
2232 Vector<RefPtr<Document> > documents;
2233 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext())
2234 documents.append(frame->document());
2236 for (size_t i = 0; i < documents.size(); ++i)
2237 documents[i]->serviceScriptedAnimations(time);
2241 bool FrameView::isTransparent() const
2243 return m_isTransparent;
2246 void FrameView::setTransparent(bool isTransparent)
2248 m_isTransparent = isTransparent;
2251 Color FrameView::baseBackgroundColor() const
2253 return m_baseBackgroundColor;
2256 void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
2258 if (!backgroundColor.isValid())
2259 m_baseBackgroundColor = Color::white;
2261 m_baseBackgroundColor = backgroundColor;
2263 recalculateScrollbarOverlayStyle();
2266 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
2268 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
2269 if (FrameView* view = frame->view()) {
2270 view->setTransparent(transparent);
2271 view->setBaseBackgroundColor(backgroundColor);
2276 bool FrameView::shouldUpdateWhileOffscreen() const
2278 return m_shouldUpdateWhileOffscreen;
2281 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
2283 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
2286 bool FrameView::shouldUpdate(bool immediateRequested) const
2288 if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen())
2293 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
2295 m_actionScheduler->scheduleEvent(event, eventTarget);
2298 void FrameView::pauseScheduledEvents()
2300 m_actionScheduler->pause();
2303 void FrameView::resumeScheduledEvents()
2305 m_actionScheduler->resume();
2308 void FrameView::scrollToAnchor()
2310 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
2314 if (!anchorNode->renderer())
2318 if (anchorNode != m_frame->document())
2319 rect = anchorNode->getRect();
2321 // Scroll nested layers and frames to reveal the anchor.
2322 // Align to the top and to the closest side (this matches other browsers).
2323 anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
2325 if (AXObjectCache::accessibilityEnabled())
2326 m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get());
2328 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
2329 m_maintainScrollPositionAnchor = anchorNode;
2332 void FrameView::updateWidget(RenderEmbeddedObject* object)
2334 ASSERT(!object->node() || object->node()->isElementNode());
2335 Element* ownerElement = static_cast<Element*>(object->node());
2336 // The object may have already been destroyed (thus node cleared),
2337 // but FrameView holds a manual ref, so it won't have been deleted.
2338 ASSERT(m_widgetUpdateSet->contains(object));
2342 // No need to update if it's already crashed or known to be missing.
2343 if (object->showsUnavailablePluginIndicator())
2346 // FIXME: This could turn into a real virtual dispatch if we defined
2347 // updateWidget(PluginCreationOption) on HTMLElement.
2348 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag) || ownerElement->hasTagName(appletTag)) {
2349 HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(ownerElement);
2350 if (pluginElement->needsWidgetUpdate())
2351 pluginElement->updateWidget(CreateAnyWidgetType);
2353 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
2354 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
2355 else if (ownerElement->isMediaElement())
2356 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
2359 ASSERT_NOT_REACHED();
2361 // Caution: it's possible the object was destroyed again, since loading a
2362 // plugin may run any arbitrary javascript.
2363 object->updateWidgetPosition();
2366 bool FrameView::updateWidgets()
2368 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
2371 size_t size = m_widgetUpdateSet->size();
2373 Vector<RenderEmbeddedObject*> objects;
2374 objects.reserveCapacity(size);
2376 RenderEmbeddedObjectSet::const_iterator end = m_widgetUpdateSet->end();
2377 for (RenderEmbeddedObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
2378 objects.uncheckedAppend(*it);
2382 for (size_t i = 0; i < size; ++i) {
2383 RenderEmbeddedObject* object = objects[i];
2384 updateWidget(object);
2385 m_widgetUpdateSet->remove(object);
2388 RenderArena* arena = m_frame->document()->renderArena();
2389 for (size_t i = 0; i < size; ++i)
2390 objects[i]->deref(arena);
2392 return m_widgetUpdateSet->isEmpty();
2395 void FrameView::flushAnyPendingPostLayoutTasks()
2397 if (!m_postLayoutTasksTimer.isActive())
2400 performPostLayoutTasks();
2403 void FrameView::performPostLayoutTasks()
2405 m_postLayoutTasksTimer.stop();
2407 m_frame->selection()->setCaretRectNeedsUpdate();
2408 m_frame->selection()->updateAppearance();
2410 if (m_nestedLayoutCount <= 1) {
2411 if (m_firstLayoutCallbackPending) {
2412 m_firstLayoutCallbackPending = false;
2413 m_frame->loader()->didFirstLayout();
2414 if (Page* page = m_frame->page()) {
2415 if (page->mainFrame() == m_frame)
2416 page->startCountingRelevantRepaintedObjects();
2420 // Ensure that we always send this eventually.
2421 if (!m_frame->document()->parsing() && m_frame->loader()->stateMachine()->committedFirstRealDocumentLoad())
2422 m_isVisuallyNonEmpty = true;
2424 // If the layout was done with pending sheets, we are not in fact visually non-empty yet.
2425 if (m_isVisuallyNonEmpty && !m_frame->document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) {
2426 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
2427 m_frame->loader()->didFirstVisuallyNonEmptyLayout();
2431 m_frame->loader()->client()->dispatchDidLayout();
2433 RenderView* root = rootRenderer(this);
2435 root->updateWidgetPositions();
2437 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
2438 if (updateWidgets())
2442 if (Page* page = m_frame->page()) {
2443 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2444 scrollingCoordinator->frameViewLayoutUpdated(this);
2447 #if USE(ACCELERATED_COMPOSITING)
2448 if (TiledBacking* tiledBacking = this->tiledBacking())
2449 tiledBacking->setCanHaveScrollbars(canHaveScrollbars());
2454 m_actionScheduler->resume();
2456 if (root && !root->printing()) {
2457 IntSize currentSize;
2458 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
2459 currentSize = fixedLayoutSize();
2461 currentSize = visibleContentRect(true /*includeScrollbars*/).size();
2462 float currentZoomFactor = root->style()->zoom();
2463 bool resized = !m_firstLayout && (currentSize != m_lastViewportSize || currentZoomFactor != m_lastZoomFactor);
2464 m_lastViewportSize = currentSize;
2465 m_lastZoomFactor = currentZoomFactor;
2466 #if ENABLE(TIZEN_BLOCK_SENDING_RESIZE_EVENT_WHILE_LOADING)
2467 DocumentLoader* documentLoader = m_frame->loader()->documentLoader();
2468 if (resized && (!documentLoader || !documentLoader->isLoadingInAPISense())) {
2472 m_frame->eventHandler()->sendResizeEvent();
2474 #if ENABLE(INSPECTOR)
2475 if (InspectorInstrumentation::hasFrontends()) {
2476 if (Page* page = m_frame->page()) {
2477 if (page->mainFrame() == m_frame) {
2478 if (InspectorClient* inspectorClient = page->inspectorController()->inspectorClient())
2479 inspectorClient->didResizeMainFrame(m_frame.get());
2488 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
2490 performPostLayoutTasks();
2493 void FrameView::autoSizeIfEnabled()
2495 if (!m_shouldAutoSize)
2501 TemporaryChange<bool> changeInAutoSize(m_inAutoSize, true);
2503 Document* document = frame()->document();
2507 RenderView* documentView = document->renderView();
2508 Element* documentElement = document->documentElement();
2509 if (!documentView || !documentElement)
2512 RenderBox* documentRenderBox = documentElement->renderBox();
2513 if (!documentRenderBox)
2516 // If this is the first time we run autosize, start from small height and
2517 // allow it to grow.
2518 if (!m_didRunAutosize)
2519 resize(frameRect().width(), m_minAutoSize.height());
2521 IntSize size = frameRect().size();
2523 // Do the resizing twice. The first time is basically a rough calculation using the preferred width
2524 // which may result in a height change during the second iteration.
2525 for (int i = 0; i < 2; i++) {
2526 // Update various sizes including contentsSize, scrollHeight, etc.
2527 document->updateLayoutIgnorePendingStylesheets();
2528 int width = documentView->minPreferredLogicalWidth();
2529 int height = documentRenderBox->scrollHeight();
2530 IntSize newSize(width, height);
2532 // Check to see if a scrollbar is needed for a given dimension and
2533 // if so, increase the other dimension to account for the scrollbar.
2534 // Since the dimensions are only for the view rectangle, once a
2535 // dimension exceeds the maximum, there is no need to increase it further.
2536 if (newSize.width() > m_maxAutoSize.width()) {
2537 RefPtr<Scrollbar> localHorizontalScrollbar = horizontalScrollbar();
2538 if (!localHorizontalScrollbar)
2539 localHorizontalScrollbar = createScrollbar(HorizontalScrollbar);
2540 if (!localHorizontalScrollbar->isOverlayScrollbar())
2541 newSize.setHeight(newSize.height() + localHorizontalScrollbar->height());
2543 // Don't bother checking for a vertical scrollbar because the width is at
2544 // already greater the maximum.
2545 } else if (newSize.height() > m_maxAutoSize.height()) {
2546 RefPtr<Scrollbar> localVerticalScrollbar = verticalScrollbar();
2547 if (!localVerticalScrollbar)
2548 localVerticalScrollbar = createScrollbar(VerticalScrollbar);
2549 if (!localVerticalScrollbar->isOverlayScrollbar())
2550 newSize.setWidth(newSize.width() + localVerticalScrollbar->width());
2552 // Don't bother checking for a horizontal scrollbar because the height is
2553 // already greater the maximum.
2556 // Ensure the size is at least the min bounds.
2557 newSize = newSize.expandedTo(m_minAutoSize);
2559 // Bound the dimensions by the max bounds and determine what scrollbars to show.
2560 ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff;
2561 if (newSize.width() > m_maxAutoSize.width()) {
2562 newSize.setWidth(m_maxAutoSize.width());
2563 horizonalScrollbarMode = ScrollbarAlwaysOn;
2565 ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff;
2566 if (newSize.height() > m_maxAutoSize.height()) {
2567 newSize.setHeight(m_maxAutoSize.height());
2568 verticalScrollbarMode = ScrollbarAlwaysOn;
2571 if (newSize == size)
2574 // Avoid doing resizing to a smaller size while the frame is loading to avoid switching to a small size
2575 // during an intermediate state (and then changing back to a bigger size as the load progresses).
2576 if (!frame()->loader()->isComplete() && (newSize.height() < size.height() || newSize.width() < size.width()))
2578 else if (document->processingLoadEvent())
2579 newSize = newSize.expandedTo(size);
2580 resize(newSize.width(), newSize.height());
2581 // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example,
2582 // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed).
2583 setVerticalScrollbarLock(false);
2584 setHorizontalScrollbarLock(false);
2585 setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true);
2587 m_didRunAutosize = true;
2590 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
2592 if (!m_viewportRenderer)
2595 if (m_overflowStatusDirty) {
2596 m_horizontalOverflow = horizontalOverflow;
2597 m_verticalOverflow = verticalOverflow;
2598 m_overflowStatusDirty = false;
2602 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
2603 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
2605 if (horizontalOverflowChanged || verticalOverflowChanged) {
2606 m_horizontalOverflow = horizontalOverflow;
2607 m_verticalOverflow = verticalOverflow;
2609 m_actionScheduler->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
2610 verticalOverflowChanged, verticalOverflow),
2611 m_viewportRenderer->node());
2616 IntRect FrameView::windowClipRect(bool clipToContents) const
2618 ASSERT(m_frame->view() == this);
2620 if (paintsEntireContents())
2621 return IntRect(IntPoint(), contentsSize());
2623 // Set our clip rect to be our contents.
2624 IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
2625 if (!m_frame || !m_frame->ownerElement())
2628 // Take our owner element and get its clip rect.
2629 HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement();
2630 FrameView* parentView = ownerElement->document()->view();
2632 clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement, true));
2636 IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement, bool clipToLayerContents) const
2638 // The renderer can sometimes be null when style="display:none" interacts
2639 // with external content and plugins.
2640 if (!ownerElement->renderer())
2641 return windowClipRect();
2643 // If we have no layer, just return our window clip rect.
2644 const RenderLayer* enclosingLayer = ownerElement->renderer()->enclosingLayer();
2645 if (!enclosingLayer)
2646 return windowClipRect();
2648 // Apply the clip from the layer.
2650 if (clipToLayerContents)
2651 clipRect = pixelSnappedIntRect(enclosingLayer->childrenClipRect());
2653 clipRect = pixelSnappedIntRect(enclosingLayer->selfClipRect());
2654 clipRect = contentsToWindow(clipRect);
2655 return intersection(clipRect, windowClipRect());
2658 bool FrameView::isActive() const
2660 Page* page = frame()->page();
2661 return page && page->focusController()->isActive();
2664 void FrameView::scrollTo(const IntSize& newOffset)
2666 LayoutSize offset = scrollOffset();
2667 ScrollView::scrollTo(newOffset);
2668 if (offset != scrollOffset())
2669 scrollPositionChanged();
2670 frame()->loader()->client()->didChangeScrollOffset();
2673 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
2675 // Add in our offset within the FrameView.
2676 IntRect dirtyRect = rect;
2677 dirtyRect.moveBy(scrollbar->location());
2678 invalidateRect(dirtyRect);
2681 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
2683 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
2686 IntRect FrameView::windowResizerRect() const
2688 Page* page = frame() ? frame()->page() : 0;
2691 return page->chrome()->windowResizerRect();
2694 void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
2696 Page* page = m_frame->page();
2699 if (page->mainFrame() != m_frame)
2701 page->chrome()->client()->notifyScrollerThumbIsVisibleInRect(scrollerThumb);
2704 bool FrameView::isOnActivePage() const
2708 if (m_frame->view() != this)
2710 if (Document* document = m_frame->document())
2711 return !document->inPageCache();
2715 ScrollableArea* FrameView::enclosingScrollableArea() const
2717 // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer.
2721 IntRect FrameView::scrollableAreaBoundingBox() const
2723 // FIXME: This isn't correct for transformed frames. We probably need to ask the renderer instead.
2727 void FrameView::updateScrollableAreaSet()
2729 // That ensures that only inner frames are cached.
2730 if (!parentFrameView())
2734 // 1) display:none or visibility:hidden set to self or inherited.
2735 // 2) overflow{-x,-y}: hidden;
2736 // 3) scrolling: no;
2739 HTMLFrameOwnerElement* owner = m_frame->ownerElement();
2740 if (!owner || !owner->renderer() || !owner->renderer()->visibleToHitTesting()) {
2741 parentFrameView()->removeScrollableArea(this);
2745 IntSize contentSize = contentsSize();
2746 IntSize visibleContentSize = visibleContentRect().size();
2747 if ((contentSize.height() <= visibleContentSize.height() && contentSize.width() <= visibleContentSize.width())) {
2748 parentFrameView()->removeScrollableArea(this);
2753 ScrollbarMode horizontalMode;
2754 ScrollbarMode verticalMode;
2755 calculateScrollbarModesForLayout(horizontalMode, verticalMode, RulesFromWebContentOnly);
2756 if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff) {
2757 parentFrameView()->removeScrollableArea(this);
2761 parentFrameView()->addScrollableArea(this);
2764 bool FrameView::shouldSuspendScrollAnimations() const
2766 return m_frame->loader()->state() != FrameStateComplete;
2769 void FrameView::scrollbarStyleChanged(int newStyle, bool forceUpdate)
2771 Page* page = m_frame->page();
2774 if (page->mainFrame() != m_frame)
2776 page->chrome()->client()->recommendedScrollbarStyleDidChange(newStyle);
2779 ScrollView::scrollbarStyleChanged(newStyle, forceUpdate);
2782 void FrameView::setAnimatorsAreActive()
2784 Page* page = m_frame->page();
2788 if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
2789 scrollAnimator->setIsActive();
2791 if (!m_scrollableAreas)
2794 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
2795 ScrollableArea* scrollableArea = *it;
2797 ASSERT(scrollableArea->isOnActivePage());
2798 scrollableArea->scrollAnimator()->setIsActive();
2802 void FrameView::notifyPageThatContentAreaWillPaint() const
2804 Page* page = m_frame->page();
2808 contentAreaWillPaint();
2810 if (!m_scrollableAreas)
2813 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
2814 ScrollableArea* scrollableArea = *it;
2816 if (!scrollableArea->isOnActivePage())
2819 scrollableArea->contentAreaWillPaint();
2823 bool FrameView::scrollAnimatorEnabled() const
2825 #if ENABLE(SMOOTH_SCROLLING)
2826 if (Page* page = m_frame->page())
2827 return page->settings()->scrollAnimatorEnabled();
2833 #if ENABLE(DASHBOARD_SUPPORT)
2834 void FrameView::updateDashboardRegions()
2836 Document* document = m_frame->document();
2837 if (!document->hasDashboardRegions())
2839 Vector<DashboardRegionValue> newRegions;
2840 document->renderBox()->collectDashboardRegions(newRegions);
2841 if (newRegions == document->dashboardRegions())
2843 document->setDashboardRegions(newRegions);
2844 Page* page = m_frame->page();
2847 page->chrome()->client()->dashboardRegionsChanged();
2851 void FrameView::updateScrollCorner()
2853 RenderObject* renderer = 0;
2854 RefPtr<RenderStyle> cornerStyle;
2855 IntRect cornerRect = scrollCornerRect();
2857 if (!cornerRect.isEmpty()) {
2858 // Try the <body> element first as a scroll corner source.
2859 Document* doc = m_frame->document();
2860 Element* body = doc ? doc->body() : 0;
2861 if (body && body->renderer()) {
2862 renderer = body->renderer();
2863 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2867 // If the <body> didn't have a custom style, then the root element might.
2868 Element* docElement = doc ? doc->documentElement() : 0;
2869 if (docElement && docElement->renderer()) {
2870 renderer = docElement->renderer();
2871 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2876 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
2877 if (RenderPart* renderer = m_frame->ownerRenderer())
2878 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2883 if (!m_scrollCorner)
2884 m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document());
2885 m_scrollCorner->setStyle(cornerStyle.release());
2886 invalidateScrollCorner(cornerRect);
2887 } else if (m_scrollCorner) {
2888 m_scrollCorner->destroy();
2892 ScrollView::updateScrollCorner();
2895 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
2897 if (context->updatingControlTints()) {
2898 updateScrollCorner();
2902 if (m_scrollCorner) {
2903 bool needsBackgorund = m_frame->page() && m_frame->page()->mainFrame() == m_frame;
2904 if (needsBackgorund)
2905 context->fillRect(cornerRect, baseBackgroundColor(), ColorSpaceDeviceRGB);
2906 m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect);
2910 ScrollView::paintScrollCorner(context, cornerRect);
2913 void FrameView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
2915 bool needsBackgorund = bar->isCustomScrollbar() && (m_frame->page() && m_frame->page()->mainFrame() == m_frame);
2916 if (needsBackgorund) {
2917 IntRect toFill = bar->frameRect();
2918 toFill.intersect(rect);
2919 context->fillRect(toFill, baseBackgroundColor(), ColorSpaceDeviceRGB);
2922 ScrollView::paintScrollbar(context, bar, rect);
2925 Color FrameView::documentBackgroundColor() const
2927 // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of
2928 // the document and the body against the base background color of the frame view.
2929 // Background images are unfortunately impractical to include.
2931 // Return invalid Color objects whenever there is insufficient information.
2932 if (!frame()->document())
2935 Element* htmlElement = frame()->document()->documentElement();
2936 Element* bodyElement = frame()->document()->body();
2938 // Start with invalid colors.
2939 Color htmlBackgroundColor;
2940 Color bodyBackgroundColor;
2941 if (htmlElement && htmlElement->renderer())
2942 htmlBackgroundColor = htmlElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
2943 if (bodyElement && bodyElement->renderer())
2944 bodyBackgroundColor = bodyElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
2946 if (!bodyBackgroundColor.isValid()) {
2947 if (!htmlBackgroundColor.isValid())
2949 return baseBackgroundColor().blend(htmlBackgroundColor);
2952 if (!htmlBackgroundColor.isValid())
2953 return baseBackgroundColor().blend(bodyBackgroundColor);
2955 // We take the aggregate of the base background color
2956 // the <html> background color, and the <body>
2957 // background color to find the document color. The
2958 // addition of the base background color is not
2959 // technically part of the document background, but it
2960 // otherwise poses problems when the aggregate is not
2962 return baseBackgroundColor().blend(htmlBackgroundColor).blend(bodyBackgroundColor);
2965 bool FrameView::hasCustomScrollbars() const
2967 const HashSet<RefPtr<Widget> >* viewChildren = children();
2968 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2969 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2970 Widget* widget = current->get();
2971 if (widget->isFrameView()) {
2972 if (static_cast<FrameView*>(widget)->hasCustomScrollbars())
2974 } else if (widget->isScrollbar()) {
2975 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
2976 if (scrollbar->isCustomScrollbar())
2984 FrameView* FrameView::parentFrameView() const
2986 if (Frame* parentFrame = m_frame->tree()->parent())
2987 return parentFrame->view();
2992 bool FrameView::isInChildFrameWithFrameFlattening() const
2994 if (!parent() || !m_frame->ownerElement())
2997 // Frame flattening applies when the owner element is either in a frameset or
2998 // an iframe with flattening parameters.
2999 if (m_frame->ownerElement()->hasTagName(iframeTag)) {
3000 RenderIFrame* iframeRenderer = toRenderIFrame(m_frame->ownerElement()->renderPart());
3001 if (iframeRenderer->flattenFrame() || iframeRenderer->isSeamless())
3005 if (!m_frame->settings() || !m_frame->settings()->frameFlatteningEnabled())
3008 if (m_frame->ownerElement()->hasTagName(frameTag))
3014 bool FrameView::doLayoutWithFrameFlattening(bool allowSubtree)
3016 // Try initiating layout from the topmost parent.
3017 FrameView* parentView = parentFrameView();
3022 // In the middle of parent layout, no need to restart from topmost.
3023 if (parentView->m_nestedLayoutCount)
3026 // Parent tree is clean. Starting layout from it would have no effect.
3027 if (!parentView->needsLayout())
3030 while (parentView->parentFrameView())
3031 parentView = parentView->parentFrameView();
3033 parentView->layout(allowSubtree);
3035 RenderObject* root = m_layoutRoot ? m_layoutRoot : m_frame->document()->renderer();
3036 ASSERT_UNUSED(root, !root->needsLayout());
3041 void FrameView::updateControlTints()
3043 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
3044 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
3045 // This is only done if the theme supports control tinting. It's up to the theme and platform
3046 // to define when controls get the tint and to call this function when that changes.
3048 // Optimize the common case where we bring a window to the front while it's still empty.
3049 if (!m_frame || m_frame->document()->url().isEmpty())
3052 RenderView* root = rootRenderer(this);
3053 if ((root && root->theme()->supportsControlTints()) || hasCustomScrollbars())
3054 paintControlTints();
3057 void FrameView::paintControlTints()
3061 PlatformGraphicsContext* const noContext = 0;
3062 GraphicsContext context(noContext);
3063 context.setUpdatingControlTints(true);
3064 if (platformWidget())
3065 paintContents(&context, visibleContentRect());
3067 paint(&context, frameRect());
3070 bool FrameView::wasScrolledByUser() const
3072 return m_wasScrolledByUser;
3075 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
3077 if (m_inProgrammaticScroll)
3079 m_maintainScrollPositionAnchor = 0;
3080 m_wasScrolledByUser = wasScrolledByUser;
3083 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
3088 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get(), p, rect);
3090 Document* document = m_frame->document();
3094 if (document->printing())
3095 fillWithRed = false; // Printing, don't fill with red (can't remember why).
3096 else if (m_frame->ownerElement())
3097 fillWithRed = false; // Subframe, don't fill with red.
3098 else if (isTransparent())
3099 fillWithRed = false; // Transparent, don't fill with red.
3100 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
3101 fillWithRed = false; // Selections are transparent, don't fill with red.
3102 else if (m_nodeToDraw)
3103 fillWithRed = false; // Element images are transparent, don't fill with red.
3108 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
3111 Page* page = m_frame->page();
3112 if (page->mainFrame() == m_frame && page->pagination().mode != Page::Pagination::Unpaginated)
3113 p->fillRect(rect, baseBackgroundColor(), ColorSpaceDeviceRGB);
3115 RenderView* root = rootRenderer(this);
3117 LOG_ERROR("called FrameView::paint with nil renderer");
3121 ASSERT(!needsLayout());
3125 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
3126 if (isTopLevelPainter)
3127 sCurrentPaintTimeStamp = currentTime();
3129 FontCachePurgePreventer fontCachePurgePreventer;
3131 #if USE(ACCELERATED_COMPOSITING)
3132 if (!p->paintingDisabled() && !document->printing())
3133 syncCompositingStateForThisFrame(m_frame.get());
3136 PaintBehavior oldPaintBehavior = m_paintBehavior;
3138 if (FrameView* parentView = parentFrameView()) {
3139 if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
3140 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
3143 if (m_paintBehavior == PaintBehaviorNormal)
3144 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
3146 if (document->printing())
3147 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
3149 bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers;
3150 bool isRootFrame = !m_frame->ownerElement();
3151 if (flatteningPaint && isRootFrame)
3152 notifyWidgetsInAllFrames(WillPaintFlattened);
3154 ASSERT(!m_isPainting);
3155 m_isPainting = true;
3157 // m_nodeToDraw is used to draw only one element (and its descendants)
3158 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
3159 RenderLayer* rootLayer = root->layer();
3161 rootLayer->paint(p, rect, m_paintBehavior, eltRenderer);
3163 if (rootLayer->containsDirtyOverlayScrollbars())
3164 rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer);
3166 m_isPainting = false;
3168 if (flatteningPaint && isRootFrame)
3169 notifyWidgetsInAllFrames(DidPaintFlattened);
3171 m_paintBehavior = oldPaintBehavior;
3172 m_lastPaintTime = currentTime();
3174 #if ENABLE(DASHBOARD_SUPPORT)
3175 // Regions may have changed as a result of the visibility/z-index of element changing.
3176 if (document->dashboardRegionsDirty())
3177 updateDashboardRegions();
3180 if (isTopLevelPainter)
3181 sCurrentPaintTimeStamp = 0;
3183 InspectorInstrumentation::didPaint(cookie);
3186 void FrameView::setPaintBehavior(PaintBehavior behavior)
3188 m_paintBehavior = behavior;
3191 PaintBehavior FrameView::paintBehavior() const
3193 return m_paintBehavior;
3196 bool FrameView::isPainting() const
3198 return m_isPainting;
3201 void FrameView::setNodeToDraw(Node* node)
3203 m_nodeToDraw = node;
3206 void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
3208 if (context->paintingDisabled())
3211 if (m_frame->document()->printing())
3214 Page* page = m_frame->page();
3215 if (page->mainFrame() == m_frame) {
3216 if (page->chrome()->client()->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
3220 ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
3223 void FrameView::updateLayoutAndStyleIfNeededRecursive()
3225 // We have to crawl our entire tree looking for any FrameViews that need
3226 // layout and make sure they are up to date.
3227 // Mac actually tests for intersection with the dirty region and tries not to
3228 // update layout for frames that are outside the dirty region. Not only does this seem
3229 // pointless (since those frames will have set a zero timer to layout anyway), but
3230 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
3231 // region but then become included later by the second frame adding rects to the dirty region
3232 // when it lays out.
3234 m_frame->document()->updateStyleIfNeeded();
3239 // Grab a copy of the children() set, as it may be mutated by the following updateLayoutAndStyleIfNeededRecursive
3240 // calls, as they can potentially re-enter a layout of the parent frame view, which may add/remove scrollbars
3241 // and thus mutates the children() set.
3242 Vector<RefPtr<FrameView> > frameViews;
3243 collectFrameViewChildren(this, frameViews);
3245 const Vector<RefPtr<FrameView> >::iterator end = frameViews.end();
3246 for (Vector<RefPtr<FrameView> >::iterator it = frameViews.begin(); it != end; ++it)
3247 (*it)->updateLayoutAndStyleIfNeededRecursive();
3249 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
3250 // painting, so we need to flush out any deferred repaints too.
3251 flushDeferredRepaints();
3253 // When frame flattening is on, child frame can mark parent frame dirty. In such case, child frame
3254 // needs to call layout on parent frame recursively.
3255 // This assert ensures that parent frames are clean, when child frames finished updating layout and style.
3256 ASSERT(!needsLayout());
3259 void FrameView::flushDeferredRepaints()
3261 if (!m_deferredRepaintTimer.isActive())
3263 m_deferredRepaintTimer.stop();
3264 doDeferredRepaints();
3267 void FrameView::enableAutoSizeMode(bool enable, const IntSize& minSize, const IntSize& maxSize)
3269 ASSERT(!enable || !minSize.isEmpty());
3270 ASSERT(minSize.width() <= maxSize.width());
3271 ASSERT(minSize.height() <= maxSize.height());
3273 if (m_shouldAutoSize == enable && m_minAutoSize == minSize && m_maxAutoSize == maxSize)
3276 m_shouldAutoSize = enable;
3277 m_minAutoSize = minSize;
3278 m_maxAutoSize = maxSize;
3279 m_didRunAutosize = false;
3283 if (m_shouldAutoSize)
3286 // Since autosize mode forces the scrollbar mode, change them to being auto.
3287 setVerticalScrollbarLock(false);
3288 setHorizontalScrollbarLock(false);
3289 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
3292 void FrameView::forceLayout(bool allowSubtree)
3294 layout(allowSubtree);
3297 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor, AdjustViewSizeOrNot shouldAdjustViewSize)
3299 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
3300 // the state of things before and after the layout
3301 if (RenderView* root = rootRenderer(this)) {
3302 float pageLogicalWidth = root->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
3303 float pageLogicalHeight = root->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
3305 LayoutUnit flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
3306 LayoutUnit flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
3307 root->setLogicalWidth(flooredPageLogicalWidth);
3308 root->setPageLogicalHeight(flooredPageLogicalHeight);
3309 root->setNeedsLayoutAndPrefWidthsRecalc();
3312 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
3313 // page width when shrunk, we will lay out at maximum shrink and clip extra content.
3314 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
3315 // implementation should not do this!
3316 bool horizontalWritingMode = root->style()->isHorizontalWritingMode();
3317 const LayoutRect& documentRect = root->documentRect();
3318 LayoutUnit docLogicalWidth = horizontalWritingMode ? documentRect.width() : documentRect.height();
3319 if (docLogicalWidth > pageLogicalWidth) {
3320 int expectedPageWidth = std::min<float>(documentRect.width(), pageSize.width() * maximumShrinkFactor);
3321 int expectedPageHeight = std::min<float>(documentRect.height(), pageSize.height() * maximumShrinkFactor);
3322 FloatSize maxPageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(originalPageSize.width(), originalPageSize.height()), FloatSize(expectedPageWidth, expectedPageHeight));
3323 pageLogicalWidth = horizontalWritingMode ? maxPageSize.width() : maxPageSize.height();
3324 pageLogicalHeight = horizontalWritingMode ? maxPageSize.height() : maxPageSize.width();
3326 flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
3327 flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
3328 root->setLogicalWidth(flooredPageLogicalWidth);
3329 root->setPageLogicalHeight(flooredPageLogicalHeight);
3330 root->setNeedsLayoutAndPrefWidthsRecalc();
3333 const LayoutRect& updatedDocumentRect = root->documentRect();
3334 LayoutUnit docLogicalHeight = horizontalWritingMode ? updatedDocumentRect.height() : updatedDocumentRect.width();
3335 LayoutUnit docLogicalTop = horizontalWritingMode ? updatedDocumentRect.y() : updatedDocumentRect.x();
3336 LayoutUnit docLogicalRight = horizontalWritingMode ? updatedDocumentRect.maxX() : updatedDocumentRect.maxY();
3337 LayoutUnit clippedLogicalLeft = 0;
3338 if (!root->style()->isLeftToRightDirection())
3339 clippedLogicalLeft = docLogicalRight - pageLogicalWidth;
3340 LayoutRect overflow(clippedLogicalLeft, docLogicalTop, pageLogicalWidth, docLogicalHeight);
3342 if (!horizontalWritingMode)
3343 overflow = overflow.transposedRect();
3344 root->clearLayoutOverflow();
3345 root->addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
3349 if (shouldAdjustViewSize)
3353 void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
3355 if (RenderView* root = rootRenderer(this)) {
3356 // Use a context with painting disabled.
3357 GraphicsContext context((PlatformGraphicsContext*)0);
3358 root->setTruncatedAt(static_cast<int>(floorf(oldBottom)));
3359 IntRect dirtyRect(0, static_cast<int>(floorf(oldTop)), root->layoutOverflowRect().maxX(), static_cast<int>(ceilf(oldBottom - oldTop)));
3360 root->setPrintRect(dirtyRect);
3361 root->layer()->paint(&context, dirtyRect);
3362 *newBottom = root->bestTruncatedAt();
3363 if (*newBottom == 0)
3364 *newBottom = oldBottom;
3365 root->setPrintRect(IntRect());
3367 *newBottom = oldBottom;
3370 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
3372 IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
3374 // Convert from page ("absolute") to FrameView coordinates.
3375 if (!delegatesScrolling())
3376 rect.moveBy(-scrollPosition());
3381 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
3383 IntRect rect = viewRect;
3385 // Convert from FrameView coords into page ("absolute") coordinates.
3386 if (!delegatesScrolling())
3387 rect.moveBy(scrollPosition());
3389 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
3390 // move the rect for now.
3391 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
3395 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
3397 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
3399 // Convert from page ("absolute") to FrameView coordinates.
3400 if (!delegatesScrolling())
3401 point.moveBy(-scrollPosition());
3405 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
3407 IntPoint point = viewPoint;
3409 // Convert from FrameView coords into page ("absolute") coordinates.
3410 if (!delegatesScrolling())
3411 point += IntSize(scrollX(), scrollY());
3413 return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
3416 IntRect FrameView::convertToContainingView(const IntRect& localRect) const
3418 if (const ScrollView* parentScrollView = parent()) {
3419 if (parentScrollView->isFrameView()) {
3420 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
3421 // Get our renderer in the parent view
3422 RenderPart* renderer = m_frame->ownerRenderer();
3426 IntRect rect(localRect);
3427 // Add borders and padding??
3428 rect.move(renderer->borderLeft() + renderer->paddingLeft(),
3429 renderer->borderTop() + renderer->paddingTop());
3430 return parentView->convertFromRenderer(renderer, rect);
3433 return Widget::convertToContainingView(localRect);
3439 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
3441 if (const ScrollView* parentScrollView = parent()) {
3442 if (parentScrollView->isFrameView()) {
3443 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
3445 // Get our renderer in the parent view
3446 RenderPart* renderer = m_frame->ownerRenderer();
3450 IntRect rect = parentView->convertToRenderer(renderer, parentRect);
3451 // Subtract borders and padding
3452 rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
3453 -renderer->borderTop() - renderer->paddingTop());
3457 return Widget::convertFromContainingView(parentRect);
3463 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
3465 if (const ScrollView* parentScrollView = parent()) {
3466 if (parentScrollView->isFrameView()) {
3467 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
3469 // Get our renderer in the parent view
3470 RenderPart* renderer = m_frame->ownerRenderer();
3474 IntPoint point(localPoint);
3476 // Add borders and padding
3477 point.move(renderer->borderLeft() + renderer->paddingLeft(),
3478 renderer->borderTop() + renderer->paddingTop());
3479 return parentView->convertFromRenderer(renderer, point);
3482 return Widget::convertToContainingView(localPoint);
3488 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
3490 if (const ScrollView* parentScrollView = parent()) {
3491 if (parentScrollView->isFrameView()) {
3492 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
3494 // Get our renderer in the parent view
3495 RenderPart* renderer = m_frame->ownerRenderer();
3499 IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
3500 // Subtract borders and padding
3501 point.move(-renderer->borderLeft() - renderer->paddingLeft(),
3502 -renderer->borderTop() - renderer->paddingTop());
3506 return Widget::convertFromContainingView(parentPoint);
3513 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
3515 s_deferredRepaintDelay = p;
3518 // Negative value would mean that first few repaints happen without a delay
3519 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)
3521 s_initialDeferredRepaintDelayDuringLoading = p;
3524 // The delay grows on each repaint to this maximum value
3525 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)
3527 s_maxDeferredRepaintDelayDuringLoading = p;
3530 // On each repaint the delay increases by this amount
3531 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)
3533 s_deferredRepaintDelayIncrementDuringLoading = p;
3536 void FrameView::setTracksRepaints(bool trackRepaints)
3538 if (trackRepaints == m_isTrackingRepaints)
3541 m_trackedRepaintRects.clear();
3542 m_isTrackingRepaints = trackRepaints;
3545 void FrameView::addScrollableArea(ScrollableArea* scrollableArea)
3547 if (!m_scrollableAreas)
3548 m_scrollableAreas = adoptPtr(new ScrollableAreaSet);
3549 m_scrollableAreas->add(scrollableArea);
3552 void FrameView::removeScrollableArea(ScrollableArea* scrollableArea)
3554 if (!m_scrollableAreas)
3556 m_scrollableAreas->remove(scrollableArea);
3559 bool FrameView::containsScrollableArea(ScrollableArea* scrollableArea) const
3561 if (!m_scrollableAreas)
3563 return m_scrollableAreas->contains(scrollableArea);
3566 void FrameView::removeChild(Widget* widget)
3568 if (widget->isFrameView())
3569 removeScrollableArea(static_cast<FrameView*>(widget));
3571 ScrollView::removeChild(widget);
3574 bool FrameView::wheelEvent(const PlatformWheelEvent& wheelEvent)
3576 // We don't allow mouse wheeling to happen in a ScrollView that has had its scrollbars explicitly disabled.
3577 if (!canHaveScrollbars())
3581 if (platformWidget())
3585 #if ENABLE(THREADED_SCROLLING)
3586 if (Page* page = m_frame->page()) {
3587 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
3588 if (scrollingCoordinator->coordinatesScrollingForFrameView(this))
3589 return scrollingCoordinator->handleWheelEvent(this, wheelEvent);
3594 return ScrollableArea::handleWheelEvent(wheelEvent);
3598 bool FrameView::isVerticalDocument() const
3600 RenderView* root = rootRenderer(this);
3604 return root->style()->isHorizontalWritingMode();
3607 bool FrameView::isFlippedDocument() const
3609 RenderView* root = rootRenderer(this);
3613 return root->style()->isFlippedBlocksWritingMode();
3616 void FrameView::notifyWidgetsInAllFrames(WidgetNotification notification)
3618 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
3619 if (RenderView* root = frame->contentRenderer())
3620 root->notifyWidgets(notification);
3624 AXObjectCache* FrameView::axObjectCache() const
3626 if (frame() && frame()->document() && frame()->document()->axObjectCacheExists())
3627 return frame()->document()->axObjectCache();
3631 } // namespace WebCore