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 #if ENABLE(TEXT_AUTOSIZING)
423 // Autosized font sizes depend on the width of the viewing area.
424 if (newRect.width() != oldRect.width()) {
425 Page* page = m_frame ? m_frame->page() : 0;
426 if (page && page->mainFrame() == m_frame && page->settings()->textAutosizingEnabled()) {
427 for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())
428 m_frame->document()->textAutosizer()->recalculateMultipliers();
433 ScrollView::setFrameRect(newRect);
435 updateScrollableAreaSet();
437 #if USE(ACCELERATED_COMPOSITING)
438 if (RenderView* root = rootRenderer(this)) {
439 if (root->usesCompositing())
440 root->compositor()->frameViewDidChangeSize();
445 #if ENABLE(REQUEST_ANIMATION_FRAME)
446 bool FrameView::scheduleAnimation()
449 hostWindow()->scheduleAnimation();
456 void FrameView::setMarginWidth(LayoutUnit w)
458 // make it update the rendering area when set
459 m_margins.setWidth(w);
462 void FrameView::setMarginHeight(LayoutUnit h)
464 // make it update the rendering area when set
465 m_margins.setHeight(h);
468 bool FrameView::avoidScrollbarCreation() const
472 // with frame flattening no subframe can have scrollbars
473 // but we also cannot turn scrollbars off as we determine
474 // our flattening policy using that.
476 if (!m_frame->ownerElement())
479 if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
485 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
487 m_canHaveScrollbars = canHaveScrollbars;
488 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
491 void FrameView::updateCanHaveScrollbars()
495 scrollbarModes(hMode, vMode);
496 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
497 setCanHaveScrollbars(false);
499 setCanHaveScrollbars(true);
502 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
504 #if ENABLE(TIZEN_DISABLE_CUSTOM_SCROLLBAR)
505 if (m_frame->page() && m_frame->page()->mainFrame() == m_frame)
506 return ScrollView::createScrollbar(orientation);
509 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
510 Document* doc = m_frame->document();
512 // Try the <body> element first as a scrollbar source.
513 Element* body = doc ? doc->body() : 0;
514 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
515 return RenderScrollbar::createCustomScrollbar(this, orientation, body);
517 // If the <body> didn't have a custom style, then the root element might.
518 Element* docElement = doc ? doc->documentElement() : 0;
519 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
520 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement);
522 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
523 RenderPart* frameRenderer = m_frame->ownerRenderer();
524 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
525 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
527 // Nobody set a custom style, so we just use a native scrollbar.
528 return ScrollView::createScrollbar(orientation);
531 void FrameView::setContentsSize(const IntSize& size)
533 if (size == contentsSize())
536 m_deferSetNeedsLayouts++;
537 ScrollView::setContentsSize(size);
539 ScrollView::contentsResized();
541 Page* page = frame() ? frame()->page() : 0;
545 updateScrollableAreaSet();
547 page->chrome()->contentsSizeChanged(frame(), size); //notify only
549 m_deferSetNeedsLayouts--;
551 if (!m_deferSetNeedsLayouts)
552 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
555 void FrameView::adjustViewSize()
557 RenderView* root = rootRenderer(this);
561 ASSERT(m_frame->view() == this);
563 const IntRect rect = root->documentRect();
564 const IntSize& size = rect.size();
565 ScrollView::setScrollOrigin(IntPoint(-rect.x(), -rect.y()), !m_frame->document()->printing(), size == contentsSize());
566 #if ENABLE(TIZEN_ADJUST_CONTENTS_SIZE_FOR_MINUS_X_WORKAROUND)
567 // 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)),
568 // the contents size should not include the left area of <html> because the leftmost paint position is (0,0) of the <html>.
569 // So, in here, I adjusted the contents size not to include the left area of <html>.
570 // It's not reasonable patch for Desktop browsers because it works wrong when the viewport size is changed.
571 // But now the TIZEN is only for Mobile, it works for now. (But need to be fixed ASAP)
573 setContentsSize(IntSize(size.width() + rect.x(), size.height()));
576 setContentsSize(size);
579 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
581 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
582 // overflow:hidden and overflow:scroll on <body> as applying to the document's
583 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
584 // use the root element.
586 // To combat the inability to scroll on a page with overflow:hidden on the root when scaled, disregard hidden when
587 // there is a frameScaleFactor that is greater than one on the main frame.
589 bool overrideHidden = m_frame->page() && m_frame->page()->mainFrame() == m_frame && m_frame->frameScaleFactor() > 1;
591 EOverflow overflowX = o->style()->overflowX();
592 EOverflow overflowY = o->style()->overflowY();
595 if (o->isSVGRoot()) {
596 // overflow is ignored in stand-alone SVG documents.
597 if (!toRenderSVGRoot(o)->isEmbeddedThroughFrameContainingSVGDocument())
607 hMode = ScrollbarAuto;
609 hMode = ScrollbarAlwaysOff;
612 hMode = ScrollbarAlwaysOn;
615 hMode = ScrollbarAuto;
618 // Don't set it at all.
625 vMode = ScrollbarAuto;
627 vMode = ScrollbarAlwaysOff;
630 vMode = ScrollbarAlwaysOn;
633 vMode = ScrollbarAuto;
636 // Don't set it at all.
640 m_viewportRenderer = o;
643 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy)
645 m_viewportRenderer = 0;
647 const HTMLFrameOwnerElement* owner = m_frame->ownerElement();
648 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
649 hMode = ScrollbarAlwaysOff;
650 vMode = ScrollbarAlwaysOff;
654 if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) {
655 hMode = ScrollbarAuto;
656 vMode = ScrollbarAuto;
658 hMode = ScrollbarAlwaysOff;
659 vMode = ScrollbarAlwaysOff;
663 Document* document = m_frame->document();
664 Node* documentElement = document->documentElement();
665 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
666 Node* body = document->body();
667 if (body && body->renderer()) {
668 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
669 vMode = ScrollbarAlwaysOff;
670 hMode = ScrollbarAlwaysOff;
671 } else if (body->hasTagName(bodyTag)) {
672 // It's sufficient to just check the X overflow,
673 // since it's illegal to have visible in only one direction.
674 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
675 applyOverflowToViewport(o, hMode, vMode);
677 } else if (rootRenderer)
678 applyOverflowToViewport(rootRenderer, hMode, vMode);
682 #if USE(ACCELERATED_COMPOSITING)
683 void FrameView::updateCompositingLayersAfterStyleChange()
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(CompositingUpdateAfterStyleChange);
694 void FrameView::updateCompositingLayersAfterLayout()
696 RenderView* root = rootRenderer(this);
700 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
701 root->compositor()->cacheAcceleratedCompositingFlags();
702 root->compositor()->updateCompositingLayers(CompositingUpdateAfterLayout);
705 void FrameView::clearBackingStores()
707 RenderView* root = rootRenderer(this);
711 RenderLayerCompositor* compositor = root->compositor();
712 ASSERT(compositor->inCompositingMode());
713 compositor->enableCompositingMode(false);
714 compositor->clearBackingForAllLayers();
717 void FrameView::restoreBackingStores()
719 RenderView* root = rootRenderer(this);
723 RenderLayerCompositor* compositor = root->compositor();
724 compositor->enableCompositingMode(true);
725 compositor->updateCompositingLayers(CompositingUpdateAfterLayout);
728 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
730 RenderView* root = rootRenderer(this);
733 return root->compositor()->layerForHorizontalScrollbar();
736 GraphicsLayer* FrameView::layerForVerticalScrollbar() const
738 RenderView* root = rootRenderer(this);
741 return root->compositor()->layerForVerticalScrollbar();
744 GraphicsLayer* FrameView::layerForScrollCorner() const
746 RenderView* root = rootRenderer(this);
749 return root->compositor()->layerForScrollCorner();
752 TiledBacking* FrameView::tiledBacking()
754 RenderView* root = rootRenderer(this);
758 RenderLayerBacking* backing = root->layer()->backing();
762 return backing->graphicsLayer()->tiledBacking();
765 #if ENABLE(RUBBER_BANDING)
766 GraphicsLayer* FrameView::layerForOverhangAreas() const
768 RenderView* root = rootRenderer(this);
771 return root->compositor()->layerForOverhangAreas();
775 bool FrameView::syncCompositingStateForThisFrame(Frame* rootFrameForSync)
777 RenderView* root = rootRenderer(this);
779 return true; // We don't want to keep trying to update layers if we have no renderer.
781 ASSERT(m_frame->view() == this);
783 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
784 // layer content to occur before layout has happened, which will cause paintContents() to bail.
788 // If we sync compositing layers and allow the repaint to be deferred, there is time for a
789 // visible flash to occur. Instead, stop the deferred repaint timer and repaint immediately.
790 stopDelayingDeferredRepaints();
792 root->compositor()->flushPendingLayerChanges(rootFrameForSync == m_frame);
797 void FrameView::setNeedsOneShotDrawingSynchronization()
799 Page* page = frame() ? frame()->page() : 0;
801 page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
804 #endif // USE(ACCELERATED_COMPOSITING)
806 bool FrameView::hasCompositedContent() const
808 #if USE(ACCELERATED_COMPOSITING)
809 if (RenderView* root = rootRenderer(this))
810 return root->compositor()->inCompositingMode();
815 bool FrameView::hasCompositedContentIncludingDescendants() const
817 #if USE(ACCELERATED_COMPOSITING)
818 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
819 RenderView* renderView = frame->contentRenderer();
820 RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0;
822 if (compositor->inCompositingMode())
825 if (!RenderLayerCompositor::allowsIndependentlyCompositedFrames(this))
833 bool FrameView::hasCompositingAncestor() const
835 #if USE(ACCELERATED_COMPOSITING)
836 for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) {
837 if (FrameView* view = frame->view()) {
838 if (view->hasCompositedContent())
846 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
847 void FrameView::enterCompositingMode()
849 #if USE(ACCELERATED_COMPOSITING)
850 if (RenderView* root = rootRenderer(this)) {
851 root->compositor()->enableCompositingMode();
853 root->compositor()->scheduleCompositingLayerUpdate();
858 bool FrameView::isEnclosedInCompositingLayer() const
860 #if USE(ACCELERATED_COMPOSITING)
861 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
862 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
865 if (FrameView* parentView = parentFrameView())
866 return parentView->isEnclosedInCompositingLayer();
871 bool FrameView::syncCompositingStateIncludingSubframes()
873 #if USE(ACCELERATED_COMPOSITING)
874 bool allFramesSynced = syncCompositingStateForThisFrame(m_frame.get());
876 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame.get())) {
877 bool synced = child->view()->syncCompositingStateForThisFrame(m_frame.get());
878 allFramesSynced &= synced;
880 return allFramesSynced;
881 #else // USE(ACCELERATED_COMPOSITING)
886 bool FrameView::isSoftwareRenderable() const
888 #if USE(ACCELERATED_COMPOSITING)
889 RenderView* root = rootRenderer(this);
893 return !root->compositor()->has3DContent();
899 void FrameView::didMoveOnscreen()
901 #if USE(ACCELERATED_COMPOSITING)
902 if (TiledBacking* tiledBacking = this->tiledBacking())
903 tiledBacking->setIsInWindow(true);
906 if (RenderView* root = rootRenderer(this))
907 root->didMoveOnscreen();
908 contentAreaDidShow();
911 void FrameView::willMoveOffscreen()
913 #if USE(ACCELERATED_COMPOSITING)
914 if (TiledBacking* tiledBacking = this->tiledBacking())
915 tiledBacking->setIsInWindow(false);
918 if (RenderView* root = rootRenderer(this))
919 root->willMoveOffscreen();
920 contentAreaDidHide();
923 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
925 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
928 static inline void collectFrameViewChildren(FrameView* frameView, Vector<RefPtr<FrameView> >& frameViews)
930 const HashSet<RefPtr<Widget> >* viewChildren = frameView->children();
931 ASSERT(viewChildren);
933 const HashSet<RefPtr<Widget> >::iterator end = viewChildren->end();
934 for (HashSet<RefPtr<Widget> >::iterator current = viewChildren->begin(); current != end; ++current) {
935 Widget* widget = (*current).get();
936 if (widget->isFrameView())
937 frameViews.append(static_cast<FrameView*>(widget));
941 inline void FrameView::forceLayoutParentViewIfNeeded()
944 RenderPart* ownerRenderer = m_frame->ownerRenderer();
945 if (!ownerRenderer || !ownerRenderer->frame())
948 RenderBox* contentBox = embeddedContentBox();
952 RenderSVGRoot* svgRoot = toRenderSVGRoot(contentBox);
953 if (svgRoot->everHadLayout() && !svgRoot->needsLayout())
956 // If the embedded SVG document appears the first time, the ownerRenderer has already finished
957 // layout without knowing about the existence of the embedded SVG document, because RenderReplaced
958 // embeddedContentBox() returns 0, as long as the embedded document isn't loaded yet. Before
959 // bothering to lay out the SVG document, mark the ownerRenderer needing layout and ask its
960 // FrameView for a layout. After that the RenderEmbeddedObject (ownerRenderer) carries the
961 // correct size, which RenderSVGRoot::computeReplacedLogicalWidth/Height rely on, when laying
962 // out for the first time, or when the RenderSVGRoot size has changed dynamically (eg. via <script>).
963 RefPtr<FrameView> frameView = ownerRenderer->frame()->view();
965 // Mark the owner renderer as needing layout.
966 ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc();
968 // Synchronously enter layout, to layout the view containing the host object/embed/iframe.
974 void FrameView::layout(bool allowSubtree)
979 // Protect the view from being deleted during layout (in recalcStyle)
980 RefPtr<FrameView> protector(this);
982 bool inChildFrameLayoutWithFrameFlattening = isInChildFrameWithFrameFlattening();
984 if (inChildFrameLayoutWithFrameFlattening) {
985 if (doLayoutWithFrameFlattening(allowSubtree))
989 m_layoutTimer.stop();
990 m_delayedLayout = false;
991 m_setNeedsLayoutWasDeferred = false;
994 // FIXME: Do we need to set m_size.width here?
995 // FIXME: Should we set m_size.height here too?
996 m_size.setWidth(layoutWidth());
1000 // we shouldn't enter layout() while painting
1001 ASSERT(!isPainting());
1005 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
1007 if (!allowSubtree && m_layoutRoot) {
1008 m_layoutRoot->markContainingBlocksForLayout(false);
1012 ASSERT(m_frame->view() == this);
1014 Document* document = m_frame->document();
1015 ASSERT(!document->inPageCache());
1020 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1022 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_postLayoutTasksTimer.isActive() && !inChildFrameLayoutWithFrameFlattening) {
1023 // This is a new top-level layout. If there are any remaining tasks from the previous
1024 // layout, finish them now.
1025 m_inSynchronousPostLayout = true;
1026 performPostLayoutTasks();
1027 m_inSynchronousPostLayout = false;
1030 // Viewport-dependent media queries may cause us to need completely different style information.
1032 if (document->styleResolver()->affectedByViewportChange()) {
1033 document->styleResolverChanged(RecalcStyleImmediately);
1034 InspectorInstrumentation::mediaQueryResultChanged(document);
1036 document->evaluateMediaQueryList();
1038 // Always ensure our style info is up-to-date. This can happen in situations where
1039 // the layout beats any sort of style recalc update that needs to occur.
1040 document->updateStyleIfNeeded();
1042 subtree = m_layoutRoot;
1044 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
1045 // so there's no point to continuing to layout
1046 if (protector->hasOneRef())
1049 root = subtree ? m_layoutRoot : document->renderer();
1051 // FIXME: Do we need to set m_size here?
1054 } // Reset m_layoutSchedulingEnabled to its previous value.
1055 // The only reason the scoping was closed here is allow fontCachePurgePreventer
1056 // to outlive the change and reset of m_layoutSchedulingEnabled.
1058 FontCachePurgePreventer fontCachePurgePreventer;
1061 TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1063 m_nestedLayoutCount++;
1065 if (!m_layoutRoot) {
1066 Document* document = m_frame->document();
1067 Node* body = document->body();
1068 if (body && body->renderer()) {
1069 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
1070 body->renderer()->setChildNeedsLayout(true);
1071 } else if (body->hasTagName(bodyTag)) {
1072 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
1073 body->renderer()->setChildNeedsLayout(true);
1077 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1078 if (m_firstLayout && !m_frame->ownerElement())
1079 printf("Elapsed time before first layout: %d\n", document->elapsedTime());
1083 autoSizeIfEnabled();
1085 ScrollbarMode hMode;
1086 ScrollbarMode vMode;
1087 calculateScrollbarModesForLayout(hMode, vMode);
1089 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
1092 // Now set our scrollbar state for the layout.
1093 ScrollbarMode currentHMode = horizontalScrollbarMode();
1094 ScrollbarMode currentVMode = verticalScrollbarMode();
1096 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
1097 if (m_firstLayout) {
1098 setScrollbarsSuppressed(true);
1100 m_firstLayout = false;
1101 m_firstLayoutCallbackPending = true;
1102 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
1103 m_lastViewportSize = fixedLayoutSize();
1105 m_lastViewportSize = visibleContentRect(true /*includeScrollbars*/).size();
1106 m_lastZoomFactor = root->style()->zoom();
1108 // Set the initial vMode to AlwaysOn if we're auto.
1109 if (vMode == ScrollbarAuto)
1110 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
1111 // Set the initial hMode to AlwaysOff if we're auto.
1112 if (hMode == ScrollbarAuto)
1113 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
1115 setScrollbarModes(hMode, vMode);
1116 setScrollbarsSuppressed(false, true);
1118 setScrollbarModes(hMode, vMode);
1121 LayoutSize oldSize = m_size;
1123 m_size = LayoutSize(layoutWidth(), layoutHeight());
1125 if (oldSize != m_size) {
1126 m_doFullRepaint = true;
1127 if (!m_firstLayout) {
1128 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
1129 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
1130 if (bodyRenderer && bodyRenderer->stretchesToViewport())
1131 bodyRenderer->setChildNeedsLayout(true);
1132 else if (rootRenderer && rootRenderer->stretchesToViewport())
1133 rootRenderer->setChildNeedsLayout(true);
1138 layer = root->enclosingLayer();
1140 m_actionScheduler->pause();
1143 bool disableLayoutState = false;
1145 RenderView* view = root->view();
1146 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
1147 view->pushLayoutState(root);
1149 LayoutStateDisabler layoutStateDisabler(disableLayoutState ? root->view() : 0);
1152 beginDeferredRepaints();
1153 forceLayoutParentViewIfNeeded();
1155 #if ENABLE(TEXT_AUTOSIZING)
1156 bool autosized = document->textAutosizer()->processSubtree(root);
1157 if (autosized && root->needsLayout())
1160 endDeferredRepaints();
1164 root->view()->popLayoutState(root);
1167 } // Reset m_layoutSchedulingEnabled to its previous value.
1169 if (!subtree && !toRenderView(root)->printing())
1172 // Now update the positions of all layers.
1173 beginDeferredRepaints();
1174 bool hasLayerOffset;
1175 LayoutPoint offsetFromRoot = layer->computeOffsetFromRoot(hasLayerOffset);
1176 if (m_doFullRepaint)
1177 root->view()->repaint(); // FIXME: This isn't really right, since the RenderView doesn't fully encompass the visibleContentRect(). It just happens
1178 // to work out most of the time, since first layouts and printing don't have you scrolled anywhere.
1180 layer->updateLayerPositions(hasLayerOffset ? &offsetFromRoot : 0, updateLayerPositionFlags(layer, subtree, m_doFullRepaint));
1181 endDeferredRepaints();
1183 #if USE(ACCELERATED_COMPOSITING)
1184 updateCompositingLayersAfterLayout();
1189 #if PLATFORM(MAC) || PLATFORM(CHROMIUM)
1190 if (AXObjectCache::accessibilityEnabled())
1191 root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true);
1193 #if ENABLE(DASHBOARD_SUPPORT)
1194 updateDashboardRegions();
1197 ASSERT(!root->needsLayout());
1199 updateCanBlitOnScrollRecursively();
1201 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1202 updateOverflowStatus(layoutWidth() < contentsWidth(),
1203 layoutHeight() < contentsHeight());
1205 if (!m_postLayoutTasksTimer.isActive()) {
1206 if (!m_inSynchronousPostLayout) {
1207 if (inChildFrameLayoutWithFrameFlattening) {
1208 if (RenderView* root = rootRenderer(this))
1209 root->updateWidgetPositions();
1211 m_inSynchronousPostLayout = true;
1212 // Calls resumeScheduledEvents()
1213 performPostLayoutTasks();
1214 m_inSynchronousPostLayout = false;
1218 if (!m_postLayoutTasksTimer.isActive() && (needsLayout() || m_inSynchronousPostLayout || inChildFrameLayoutWithFrameFlattening)) {
1219 // If we need layout or are already in a synchronous call to postLayoutTasks(),
1220 // defer widget updates and event dispatch until after we return. postLayoutTasks()
1221 // can make us need to update again, and we can get stuck in a nasty cycle unless
1222 // we call it through the timer here.
1223 m_postLayoutTasksTimer.startOneShot(0);
1224 if (needsLayout()) {
1225 m_actionScheduler->pause();
1230 m_actionScheduler->resume();
1233 InspectorInstrumentation::didLayout(cookie);
1235 m_nestedLayoutCount--;
1236 if (m_nestedLayoutCount)
1239 Page* page = frame() ? frame()->page() : 0;
1243 page->chrome()->client()->layoutUpdated(frame());
1246 RenderBox* FrameView::embeddedContentBox() const
1249 RenderView* root = rootRenderer(this);
1253 RenderObject* rootChild = root->firstChild();
1254 if (!rootChild || !rootChild->isBox())
1257 // Curently only embedded SVG documents participate in the size-negotiation logic.
1258 if (rootChild->isSVGRoot())
1259 return toRenderBox(rootChild);
1265 void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object)
1267 if (!m_widgetUpdateSet)
1268 m_widgetUpdateSet = adoptPtr(new RenderEmbeddedObjectSet);
1270 // Tell the DOM element that it needs a widget update.
1271 Node* node = object->node();
1272 if (node->hasTagName(objectTag) || node->hasTagName(embedTag)) {
1273 HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(node);
1274 pluginElement->setNeedsWidgetUpdate(true);
1277 m_widgetUpdateSet->add(object);
1280 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object)
1282 if (!m_widgetUpdateSet)
1285 m_widgetUpdateSet->remove(object);
1288 void FrameView::setMediaType(const String& mediaType)
1290 m_mediaType = mediaType;
1293 String FrameView::mediaType() const
1295 // See if we have an override type.
1296 String overrideType = m_frame->loader()->client()->overrideMediaType();
1297 if (!overrideType.isNull())
1298 return overrideType;
1302 void FrameView::adjustMediaTypeForPrinting(bool printing)
1305 if (m_mediaTypeWhenNotPrinting.isNull())
1306 m_mediaTypeWhenNotPrinting = mediaType();
1307 setMediaType("print");
1309 if (!m_mediaTypeWhenNotPrinting.isNull())
1310 setMediaType(m_mediaTypeWhenNotPrinting);
1311 m_mediaTypeWhenNotPrinting = String();
1315 bool FrameView::useSlowRepaints(bool considerOverlap) const
1317 bool mustBeSlow = m_slowRepaintObjectCount > 0 || (platformWidget() && hasFixedObjects());
1319 // FIXME: WidgetMac.mm makes the assumption that useSlowRepaints ==
1320 // m_contentIsOpaque, so don't take the fast path for composited layers
1321 // if they are a platform widget in order to get painting correctness
1322 // for transparent layers. See the comment in WidgetMac::paint.
1323 if (contentsInCompositedLayer() && !platformWidget())
1326 #if PLATFORM(CHROMIUM)
1327 // The chromium compositor does not support scrolling a non-composited frame within a composited page through
1328 // the fast scrolling path, so force slow scrolling in that case.
1329 if (m_frame->ownerElement() && !hasCompositedContent() && m_frame->page() && m_frame->page()->mainFrame()->view()->hasCompositedContent())
1333 bool isOverlapped = m_isOverlapped && considerOverlap;
1335 if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque)
1338 if (FrameView* parentView = parentFrameView())
1339 return parentView->useSlowRepaints(considerOverlap);
1344 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1346 return useSlowRepaints(false);
1349 void FrameView::updateCanBlitOnScrollRecursively()
1351 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1352 if (FrameView* view = frame->view())
1353 view->setCanBlitOnScroll(!view->useSlowRepaints());
1357 bool FrameView::contentsInCompositedLayer() const
1359 #if USE(ACCELERATED_COMPOSITING)
1360 RenderView* root = rootRenderer(this);
1361 if (root && root->isComposited()) {
1362 GraphicsLayer* layer = root->layer()->backing()->graphicsLayer();
1363 if (layer && layer->drawsContent())
1370 void FrameView::setCannotBlitToWindow()
1372 m_cannotBlitToWindow = true;
1373 updateCanBlitOnScrollRecursively();
1376 void FrameView::addSlowRepaintObject()
1378 if (!m_slowRepaintObjectCount++) {
1379 updateCanBlitOnScrollRecursively();
1381 if (Page* page = m_frame->page()) {
1382 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1383 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1388 void FrameView::removeSlowRepaintObject()
1390 ASSERT(m_slowRepaintObjectCount > 0);
1391 m_slowRepaintObjectCount--;
1392 if (!m_slowRepaintObjectCount) {
1393 updateCanBlitOnScrollRecursively();
1395 if (Page* page = m_frame->page()) {
1396 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1397 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1402 void FrameView::addFixedObject(RenderObject* object)
1404 if (!m_fixedObjects)
1405 m_fixedObjects = adoptPtr(new FixedObjectSet);
1407 if (!m_fixedObjects->contains(object)) {
1408 m_fixedObjects->add(object);
1409 if (platformWidget())
1410 updateCanBlitOnScrollRecursively();
1412 if (Page* page = m_frame->page()) {
1413 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1414 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1419 void FrameView::removeFixedObject(RenderObject* object)
1421 ASSERT(hasFixedObjects());
1423 if (m_fixedObjects->contains(object)) {
1424 m_fixedObjects->remove(object);
1425 if (Page* page = m_frame->page()) {
1426 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1427 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1430 // FIXME: In addFixedObject() we only call this if there's a platform widget,
1431 // why isn't the same check being made here?
1432 updateCanBlitOnScrollRecursively();
1436 static int fixedPositionScrollOffset(int scrollPosition, int maxValue, int scrollOrigin, float dragFactor)
1441 if (!scrollOrigin) {
1442 if (scrollPosition < 0)
1444 else if (scrollPosition > maxValue)
1445 scrollPosition = maxValue;
1447 if (scrollPosition > 0)
1449 else if (scrollPosition < -maxValue)
1450 scrollPosition = -maxValue;
1453 return scrollPosition * dragFactor;
1456 IntSize FrameView::scrollOffsetForFixedPosition() const
1458 IntRect visibleContentRect = this->visibleContentRect();
1459 IntSize contentsSize = this->contentsSize();
1460 IntPoint scrollPosition = this->scrollPosition();
1461 IntPoint scrollOrigin = this->scrollOrigin();
1463 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
1464 // When showing IME, the fixed position element can be scrolled over maxOffset.
1465 IntSize maxOffset(contentsSize.width(), contentsSize.height());
1467 IntSize maxOffset(contentsSize.width() - visibleContentRect.width(), contentsSize.height() - visibleContentRect.height());
1470 float frameScaleFactor = m_frame ? m_frame->frameScaleFactor() : 1;
1472 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
1473 FloatSize dragFactor = fixedElementsLayoutRelativeToFrame() ? FloatSize(1, 1) : FloatSize(
1474 (contentsSize.width() * frameScaleFactor) / maxOffset.width(),
1475 (contentsSize.height() * frameScaleFactor) / maxOffset.height());
1477 FloatSize dragFactor = fixedElementsLayoutRelativeToFrame() ? FloatSize(1, 1) : FloatSize(
1478 (contentsSize.width() - visibleContentRect.width() * frameScaleFactor) / maxOffset.width(),
1479 (contentsSize.height() - visibleContentRect.height() * frameScaleFactor) / maxOffset.height());
1482 int x = fixedPositionScrollOffset(scrollPosition.x(), maxOffset.width(), scrollOrigin.x(), dragFactor.width() / frameScaleFactor);
1483 int y = fixedPositionScrollOffset(scrollPosition.y(), maxOffset.height(), scrollOrigin.y(), dragFactor.height() / frameScaleFactor);
1485 return IntSize(x, y);
1488 bool FrameView::fixedElementsLayoutRelativeToFrame() const
1491 if (!m_frame->settings())
1494 return m_frame->settings()->fixedElementsLayoutRelativeToFrame();
1497 IntPoint FrameView::currentMousePosition() const
1499 return m_frame ? m_frame->eventHandler()->currentMousePosition() : IntPoint();
1502 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1504 if (!m_fixedObjects || m_fixedObjects->isEmpty()) {
1505 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1509 const bool isCompositedContentLayer = contentsInCompositedLayer();
1511 // Get the rects of the fixed objects visible in the rectToScroll
1512 Region regionToUpdate;
1513 FixedObjectSet::const_iterator end = m_fixedObjects->end();
1514 for (FixedObjectSet::const_iterator it = m_fixedObjects->begin(); it != end; ++it) {
1515 RenderObject* renderer = *it;
1516 if (renderer->style()->position() != FixedPosition)
1518 #if USE(ACCELERATED_COMPOSITING)
1519 if (renderer->isComposited())
1523 // Fixed items should always have layers.
1524 ASSERT(renderer->hasLayer());
1525 RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
1527 #if ENABLE(CSS_FILTERS)
1528 if (layer->hasAncestorWithFilterOutsets()) {
1529 // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot
1530 // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
1534 IntRect updateRect = pixelSnappedIntRect(layer->repaintRectIncludingNonCompositingDescendants());
1535 updateRect = contentsToRootView(updateRect);
1536 if (!isCompositedContentLayer && clipsRepaints())
1537 updateRect.intersect(rectToScroll);
1538 if (!updateRect.isEmpty())
1539 regionToUpdate.unite(updateRect);
1542 // The area to be painted by fixed objects exceeds 50% of the area of the view, we cannot use the fast path.
1543 if (regionToUpdate.totalArea() > (clipRect.width() * clipRect.height() * 0.5))
1547 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1549 // 2) update the area of fixed objects that has been invalidated
1550 Vector<IntRect> subRectsToUpdate = regionToUpdate.rects();
1551 size_t fixObjectsCount = subRectsToUpdate.size();
1552 for (size_t i = 0; i < fixObjectsCount; ++i) {
1553 IntRect updateRect = subRectsToUpdate[i];
1554 IntRect scrolledRect = updateRect;
1555 scrolledRect.move(scrollDelta);
1556 updateRect.unite(scrolledRect);
1557 #if USE(ACCELERATED_COMPOSITING)
1558 if (isCompositedContentLayer) {
1559 updateRect = rootViewToContents(updateRect);
1560 RenderView* root = rootRenderer(this);
1562 root->layer()->setBackingNeedsRepaintInRect(updateRect);
1566 if (clipsRepaints())
1567 updateRect.intersect(rectToScroll);
1568 hostWindow()->invalidateContentsAndRootView(updateRect, false);
1574 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1576 #if USE(ACCELERATED_COMPOSITING)
1577 if (contentsInCompositedLayer()) {
1578 RenderView* root = rootRenderer(this);
1581 IntRect updateRect = visibleContentRect();
1583 // Make sure to "apply" the scale factor here since we're converting from frame view
1584 // coordinates to layer backing coordinates.
1585 updateRect.scale(1 / m_frame->frameScaleFactor());
1587 root->layer()->setBackingNeedsRepaintInRect(updateRect);
1589 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1590 if (isEnclosedInCompositingLayer()) {
1591 LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1592 frameRenderer->borderTop() + frameRenderer->paddingTop(),
1593 visibleWidth(), visibleHeight());
1594 frameRenderer->repaintRectangle(rect);
1600 ScrollView::scrollContentsSlowPath(updateRect);
1603 // Note that this gets called at painting time.
1604 void FrameView::setIsOverlapped(bool isOverlapped)
1606 if (isOverlapped == m_isOverlapped)
1609 m_isOverlapped = isOverlapped;
1610 updateCanBlitOnScrollRecursively();
1612 #if USE(ACCELERATED_COMPOSITING)
1613 if (hasCompositedContentIncludingDescendants()) {
1614 // Overlap can affect compositing tests, so if it changes, we need to trigger
1615 // a layer update in the parent document.
1616 if (Frame* parentFrame = m_frame->tree()->parent()) {
1617 if (RenderView* parentView = parentFrame->contentRenderer()) {
1618 RenderLayerCompositor* compositor = parentView->compositor();
1619 compositor->setCompositingLayersNeedRebuild();
1620 compositor->scheduleCompositingLayerUpdate();
1624 if (RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) {
1625 // We also need to trigger reevaluation for this and all descendant frames,
1626 // since a frame uses compositing if any ancestor is compositing.
1627 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1628 if (RenderView* view = frame->contentRenderer()) {
1629 RenderLayerCompositor* compositor = view->compositor();
1630 compositor->setCompositingLayersNeedRebuild();
1631 compositor->scheduleCompositingLayerUpdate();
1639 bool FrameView::isOverlappedIncludingAncestors() const
1644 if (FrameView* parentView = parentFrameView()) {
1645 if (parentView->isOverlapped())
1652 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1654 if (contentIsOpaque == m_contentIsOpaque)
1657 m_contentIsOpaque = contentIsOpaque;
1658 updateCanBlitOnScrollRecursively();
1661 void FrameView::restoreScrollbar()
1663 setScrollbarsSuppressed(false);
1666 bool FrameView::scrollToFragment(const KURL& url)
1668 // If our URL has no ref, then we have no place we need to jump to.
1669 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1670 // and possibly repaint because :target pseudo class may have been
1671 // set (see bug 11321).
1672 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1675 String fragmentIdentifier = url.fragmentIdentifier();
1676 if (scrollToAnchor(fragmentIdentifier))
1679 // Try again after decoding the ref, based on the document's encoding.
1680 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1681 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1686 bool FrameView::scrollToAnchor(const String& name)
1688 ASSERT(m_frame->document());
1690 if (!m_frame->document()->haveStylesheetsLoaded()) {
1691 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1695 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1697 Element* anchorNode = m_frame->document()->findAnchor(name);
1699 // Setting to null will clear the current target.
1700 m_frame->document()->setCSSTarget(anchorNode);
1703 if (m_frame->document()->isSVGDocument()) {
1704 if (SVGSVGElement* svg = static_cast<SVGDocument*>(m_frame->document())->rootElement()) {
1705 svg->setupInitialView(name, anchorNode);
1712 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1713 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1716 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1720 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1722 m_maintainScrollPositionAnchor = anchorNode;
1723 if (!m_maintainScrollPositionAnchor)
1726 // We need to update the layout before scrolling, otherwise we could
1727 // really mess things up if an anchor scroll comes at a bad moment.
1728 m_frame->document()->updateStyleIfNeeded();
1729 // Only do a layout if changes have occurred that make it necessary.
1730 RenderView* root = rootRenderer(this);
1731 if (root && root->needsLayout())
1737 void FrameView::scrollElementToRect(Element* element, const IntRect& rect)
1739 m_frame->document()->updateLayoutIgnorePendingStylesheets();
1741 LayoutRect bounds = element->getRect();
1742 int centeringOffsetX = (rect.width() - bounds.width()) / 2;
1743 int centeringOffsetY = (rect.height() - bounds.height()) / 2;
1744 setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y()));
1747 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1749 TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1750 m_maintainScrollPositionAnchor = 0;
1752 if (requestScrollPositionUpdate(scrollPoint))
1755 ScrollView::setScrollPosition(scrollPoint);
1758 void FrameView::delegatesScrollingDidChange()
1760 #if USE(ACCELERATED_COMPOSITING)
1761 // When we switch to delgatesScrolling mode, we should destroy the scrolling/clipping layers in RenderLayerCompositor.
1762 if (hasCompositedContent())
1763 clearBackingStores();
1767 void FrameView::setFixedVisibleContentRect(const IntRect& visibleContentRect)
1769 bool visibleContentSizeDidChange = false;
1770 if (visibleContentRect.size() != this->fixedVisibleContentRect().size()) {
1771 // When the viewport size changes or the content is scaled, we need to
1772 // reposition the fixed positioned elements.
1773 if (RenderView* root = rootRenderer(this))
1774 root->setFixedPositionedObjectsNeedLayout();
1775 visibleContentSizeDidChange = true;
1778 IntSize offset = scrollOffset();
1779 ScrollView::setFixedVisibleContentRect(visibleContentRect);
1780 if (offset != scrollOffset()) {
1781 if (m_frame->page()->settings()->acceleratedCompositingForFixedPositionEnabled())
1782 updateFixedElementsAfterScrolling();
1783 scrollAnimator()->setCurrentPosition(scrollPosition());
1784 scrollPositionChanged();
1786 if (visibleContentSizeDidChange) {
1787 // Update the scroll-bars to calculate new page-step size.
1788 updateScrollbars(scrollOffset());
1790 frame()->loader()->client()->didChangeScrollOffset();
1793 void FrameView::scrollPositionChangedViaPlatformWidget()
1795 repaintFixedElementsAfterScrolling();
1796 updateFixedElementsAfterScrolling();
1797 scrollPositionChanged();
1800 void FrameView::scrollPositionChanged()
1802 frame()->eventHandler()->sendScrollEvent();
1803 frame()->eventHandler()->dispatchFakeMouseMoveEventSoon();
1805 #if USE(ACCELERATED_COMPOSITING)
1806 if (RenderView* root = rootRenderer(this)) {
1807 if (root->usesCompositing())
1808 root->compositor()->frameViewDidScroll();
1813 void FrameView::repaintFixedElementsAfterScrolling()
1815 // For fixed position elements, update widget positions and compositing layers after scrolling,
1816 // but only if we're not inside of layout.
1817 if (!m_nestedLayoutCount && hasFixedObjects()) {
1818 if (RenderView* root = rootRenderer(this)) {
1819 root->updateWidgetPositions();
1820 root->layer()->updateLayerPositionsAfterScroll();
1825 void FrameView::updateFixedElementsAfterScrolling()
1827 #if USE(ACCELERATED_COMPOSITING)
1828 if (m_nestedLayoutCount <= 1 && hasFixedObjects()) {
1829 if (RenderView* root = rootRenderer(this)) {
1830 root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
1836 bool FrameView::shouldRubberBandInDirection(ScrollDirection direction) const
1838 Page* page = frame() ? frame()->page() : 0;
1840 return ScrollView::shouldRubberBandInDirection(direction);
1841 return page->chrome()->client()->shouldRubberBandInDirection(direction);
1844 bool FrameView::requestScrollPositionUpdate(const IntPoint& position)
1846 #if ENABLE(THREADED_SCROLLING)
1847 if (Page* page = m_frame->page()) {
1848 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1849 return scrollingCoordinator->requestScrollPositionUpdate(this, position);
1852 UNUSED_PARAM(position);
1858 #if ENABLE(TIZEN_WEBKIT2_HISTORICAL_RESTORE_VISIBLE_CONTENT_RECT)
1859 void FrameView::requestVisibleContentRectRestore(const IntPoint& position, float scale)
1861 Page* page = m_frame->page();
1864 if (page->mainFrame() != m_frame)
1866 page->chrome()->client()->requestVisibleContentRectRestore(position, scale);
1870 HostWindow* FrameView::hostWindow() const
1872 Page* page = frame() ? frame()->page() : 0;
1875 return page->chrome();
1878 const unsigned cRepaintRectUnionThreshold = 25;
1880 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
1882 ASSERT(!m_frame->ownerElement());
1884 if (m_isTrackingRepaints) {
1885 IntRect repaintRect = r;
1886 repaintRect.move(-scrollOffset());
1887 m_trackedRepaintRects.append(repaintRect);
1890 double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay();
1891 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
1892 IntRect paintRect = r;
1893 if (clipsRepaints() && !paintsEntireContents())
1894 paintRect.intersect(visibleContentRect());
1895 if (paintRect.isEmpty())
1897 if (m_repaintCount == cRepaintRectUnionThreshold) {
1898 IntRect unionedRect;
1899 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
1900 unionedRect.unite(pixelSnappedIntRect(m_repaintRects[i]));
1901 m_repaintRects.clear();
1902 m_repaintRects.append(unionedRect);
1904 if (m_repaintCount < cRepaintRectUnionThreshold)
1905 m_repaintRects.append(paintRect);
1907 m_repaintRects[0].unite(paintRect);
1910 if (!m_deferringRepaints)
1911 startDeferredRepaintTimer(delay);
1916 if (!shouldUpdate(immediate))
1919 #if USE(TILED_BACKING_STORE)
1920 if (frame()->tiledBackingStore()) {
1921 frame()->tiledBackingStore()->invalidate(r);
1925 ScrollView::repaintContentRectangle(r, immediate);
1928 void FrameView::contentsResized()
1930 ScrollView::contentsResized();
1934 void FrameView::visibleContentsResized()
1936 // We check to make sure the view is attached to a frame() as this method can
1937 // be triggered before the view is attached by Frame::createView(...) setting
1938 // various values such as setScrollBarModes(...) for example. An ASSERT is
1939 // triggered when a view is layout before being attached to a frame().
1940 if (!frame()->view())
1946 #if USE(ACCELERATED_COMPOSITING)
1947 if (RenderView* root = rootRenderer(this)) {
1948 if (root->usesCompositing())
1949 root->compositor()->frameViewDidChangeSize();
1954 void FrameView::beginDeferredRepaints()
1956 Page* page = m_frame->page();
1957 if (page->mainFrame() != m_frame) {
1958 page->mainFrame()->view()->beginDeferredRepaints();
1962 m_deferringRepaints++;
1965 void FrameView::endDeferredRepaints()
1967 Page* page = m_frame->page();
1968 if (page->mainFrame() != m_frame) {
1969 page->mainFrame()->view()->endDeferredRepaints();
1973 ASSERT(m_deferringRepaints > 0);
1975 if (--m_deferringRepaints)
1978 if (m_deferredRepaintTimer.isActive())
1981 if (double delay = adjustedDeferredRepaintDelay()) {
1982 startDeferredRepaintTimer(delay);
1986 doDeferredRepaints();
1989 void FrameView::startDeferredRepaintTimer(double delay)
1991 if (m_deferredRepaintTimer.isActive())
1994 if (m_disableRepaints)
1997 m_deferredRepaintTimer.startOneShot(delay);
2000 void FrameView::checkStopDelayingDeferredRepaints()
2002 Document* document = m_frame->document();
2003 if (document && (document->parsing() || document->cachedResourceLoader()->requestCount()))
2006 stopDelayingDeferredRepaints();
2009 void FrameView::stopDelayingDeferredRepaints()
2011 if (!m_deferredRepaintTimer.isActive())
2014 m_deferredRepaintTimer.stop();
2016 doDeferredRepaints();
2019 void FrameView::doDeferredRepaints()
2021 if (m_disableRepaints)
2024 ASSERT(!m_deferringRepaints);
2025 if (!shouldUpdate()) {
2026 m_repaintRects.clear();
2030 unsigned size = m_repaintRects.size();
2031 for (unsigned i = 0; i < size; i++) {
2032 #if USE(TILED_BACKING_STORE)
2033 if (frame()->tiledBackingStore()) {
2034 frame()->tiledBackingStore()->invalidate(pixelSnappedIntRect(m_repaintRects[i]));
2038 ScrollView::repaintContentRectangle(pixelSnappedIntRect(m_repaintRects[i]), false);
2040 m_repaintRects.clear();
2043 updateDeferredRepaintDelay();
2046 void FrameView::updateDeferredRepaintDelay()
2048 Document* document = m_frame->document();
2049 if (!document || (!document->parsing() && !document->cachedResourceLoader()->requestCount())) {
2050 m_deferredRepaintDelay = s_deferredRepaintDelay;
2053 if (m_deferredRepaintDelay < s_maxDeferredRepaintDelayDuringLoading) {
2054 m_deferredRepaintDelay += s_deferredRepaintDelayIncrementDuringLoading;
2055 if (m_deferredRepaintDelay > s_maxDeferredRepaintDelayDuringLoading)
2056 m_deferredRepaintDelay = s_maxDeferredRepaintDelayDuringLoading;
2060 void FrameView::resetDeferredRepaintDelay()
2062 m_deferredRepaintDelay = 0;
2063 if (m_deferredRepaintTimer.isActive()) {
2064 m_deferredRepaintTimer.stop();
2065 if (!m_deferringRepaints)
2066 doDeferredRepaints();
2070 double FrameView::adjustedDeferredRepaintDelay() const
2072 ASSERT(!m_deferringRepaints);
2073 if (!m_deferredRepaintDelay)
2075 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
2076 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
2079 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
2081 doDeferredRepaints();
2084 void FrameView::beginDisableRepaints()
2086 m_disableRepaints++;
2089 void FrameView::endDisableRepaints()
2091 ASSERT(m_disableRepaints > 0);
2092 m_disableRepaints--;
2095 void FrameView::layoutTimerFired(Timer<FrameView>*)
2097 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2098 if (!m_frame->document()->ownerElement())
2099 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
2104 void FrameView::scheduleRelayout()
2106 // FIXME: We should assert the page is not in the page cache, but that is causing
2107 // too many false assertions. See <rdar://problem/7218118>.
2108 ASSERT(m_frame->view() == this);
2111 m_layoutRoot->markContainingBlocksForLayout(false);
2114 if (!m_layoutSchedulingEnabled)
2118 if (!m_frame->document()->shouldScheduleLayout())
2121 // When frame flattening is enabled, the contents of the frame could affect the layout of the parent frames.
2122 // Also invalidate parent frame starting from the owner element of this frame.
2123 if (m_frame->ownerRenderer() && isInChildFrameWithFrameFlattening())
2124 m_frame->ownerRenderer()->setNeedsLayout(true, MarkContainingBlockChain);
2126 int delay = m_frame->document()->minimumLayoutDelay();
2127 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
2128 unscheduleRelayout();
2129 if (m_layoutTimer.isActive())
2132 m_delayedLayout = delay != 0;
2134 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2135 if (!m_frame->document()->ownerElement())
2136 printf("Scheduling layout for %d\n", delay);
2139 m_layoutTimer.startOneShot(delay * 0.001);
2142 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
2144 for (RenderObject* r = descendant; r; r = r->container()) {
2151 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
2153 ASSERT(m_frame->view() == this);
2155 RenderView* root = rootRenderer(this);
2156 if (root && root->needsLayout()) {
2158 relayoutRoot->markContainingBlocksForLayout(false);
2162 if (layoutPending() || !m_layoutSchedulingEnabled) {
2163 if (m_layoutRoot != relayoutRoot) {
2164 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
2165 // Keep the current root
2166 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
2167 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2168 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
2169 // Re-root at relayoutRoot
2170 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
2171 m_layoutRoot = relayoutRoot;
2172 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2174 // Just do a full relayout
2176 m_layoutRoot->markContainingBlocksForLayout(false);
2178 relayoutRoot->markContainingBlocksForLayout(false);
2181 } else if (m_layoutSchedulingEnabled) {
2182 int delay = m_frame->document()->minimumLayoutDelay();
2183 m_layoutRoot = relayoutRoot;
2184 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2185 m_delayedLayout = delay != 0;
2186 m_layoutTimer.startOneShot(delay * 0.001);
2190 bool FrameView::layoutPending() const
2192 return m_layoutTimer.isActive();
2195 bool FrameView::needsLayout() const
2197 // This can return true in cases where the document does not have a body yet.
2198 // Document::shouldScheduleLayout takes care of preventing us from scheduling
2199 // layout in that case.
2203 RenderView* root = rootRenderer(this);
2204 return layoutPending()
2205 || (root && root->needsLayout())
2207 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
2210 void FrameView::setNeedsLayout()
2212 if (m_deferSetNeedsLayouts) {
2213 m_setNeedsLayoutWasDeferred = true;
2217 if (RenderView* root = rootRenderer(this))
2218 root->setNeedsLayout(true);
2221 void FrameView::unscheduleRelayout()
2223 if (!m_layoutTimer.isActive())
2226 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
2227 if (!m_frame->document()->ownerElement())
2228 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
2231 m_layoutTimer.stop();
2232 m_delayedLayout = false;
2235 #if ENABLE(REQUEST_ANIMATION_FRAME)
2236 void FrameView::serviceScriptedAnimations(DOMTimeStamp time)
2238 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext()) {
2239 frame->view()->serviceScrollAnimations();
2240 frame->animation()->serviceAnimations();
2243 Vector<RefPtr<Document> > documents;
2244 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext())
2245 documents.append(frame->document());
2247 for (size_t i = 0; i < documents.size(); ++i)
2248 documents[i]->serviceScriptedAnimations(time);
2252 bool FrameView::isTransparent() const
2254 return m_isTransparent;
2257 void FrameView::setTransparent(bool isTransparent)
2259 m_isTransparent = isTransparent;
2262 Color FrameView::baseBackgroundColor() const
2264 return m_baseBackgroundColor;
2267 void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
2269 if (!backgroundColor.isValid())
2270 m_baseBackgroundColor = Color::white;
2272 m_baseBackgroundColor = backgroundColor;
2274 recalculateScrollbarOverlayStyle();
2277 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
2279 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
2280 if (FrameView* view = frame->view()) {
2281 view->setTransparent(transparent);
2282 view->setBaseBackgroundColor(backgroundColor);
2287 bool FrameView::shouldUpdateWhileOffscreen() const
2289 return m_shouldUpdateWhileOffscreen;
2292 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
2294 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
2297 bool FrameView::shouldUpdate(bool immediateRequested) const
2299 if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen())
2304 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
2306 m_actionScheduler->scheduleEvent(event, eventTarget);
2309 void FrameView::pauseScheduledEvents()
2311 m_actionScheduler->pause();
2314 void FrameView::resumeScheduledEvents()
2316 m_actionScheduler->resume();
2319 void FrameView::scrollToAnchor()
2321 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
2325 if (!anchorNode->renderer())
2329 if (anchorNode != m_frame->document())
2330 rect = anchorNode->getRect();
2332 // Scroll nested layers and frames to reveal the anchor.
2333 // Align to the top and to the closest side (this matches other browsers).
2334 anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
2336 if (AXObjectCache::accessibilityEnabled())
2337 m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get());
2339 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
2340 m_maintainScrollPositionAnchor = anchorNode;
2343 void FrameView::updateWidget(RenderEmbeddedObject* object)
2345 ASSERT(!object->node() || object->node()->isElementNode());
2346 Element* ownerElement = static_cast<Element*>(object->node());
2347 // The object may have already been destroyed (thus node cleared),
2348 // but FrameView holds a manual ref, so it won't have been deleted.
2349 ASSERT(m_widgetUpdateSet->contains(object));
2353 // No need to update if it's already crashed or known to be missing.
2354 if (object->showsUnavailablePluginIndicator())
2357 // FIXME: This could turn into a real virtual dispatch if we defined
2358 // updateWidget(PluginCreationOption) on HTMLElement.
2359 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag) || ownerElement->hasTagName(appletTag)) {
2360 HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(ownerElement);
2361 if (pluginElement->needsWidgetUpdate())
2362 pluginElement->updateWidget(CreateAnyWidgetType);
2364 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
2365 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
2366 else if (ownerElement->isMediaElement())
2367 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
2370 ASSERT_NOT_REACHED();
2372 // Caution: it's possible the object was destroyed again, since loading a
2373 // plugin may run any arbitrary javascript.
2374 object->updateWidgetPosition();
2377 bool FrameView::updateWidgets()
2379 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
2382 size_t size = m_widgetUpdateSet->size();
2384 Vector<RenderEmbeddedObject*> objects;
2385 objects.reserveCapacity(size);
2387 RenderEmbeddedObjectSet::const_iterator end = m_widgetUpdateSet->end();
2388 for (RenderEmbeddedObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
2389 objects.uncheckedAppend(*it);
2393 for (size_t i = 0; i < size; ++i) {
2394 RenderEmbeddedObject* object = objects[i];
2395 updateWidget(object);
2396 m_widgetUpdateSet->remove(object);
2399 RenderArena* arena = m_frame->document()->renderArena();
2400 for (size_t i = 0; i < size; ++i)
2401 objects[i]->deref(arena);
2403 return m_widgetUpdateSet->isEmpty();
2406 void FrameView::flushAnyPendingPostLayoutTasks()
2408 if (!m_postLayoutTasksTimer.isActive())
2411 performPostLayoutTasks();
2414 void FrameView::performPostLayoutTasks()
2416 m_postLayoutTasksTimer.stop();
2418 m_frame->selection()->setCaretRectNeedsUpdate();
2419 m_frame->selection()->updateAppearance();
2421 if (m_nestedLayoutCount <= 1) {
2422 if (m_firstLayoutCallbackPending) {
2423 m_firstLayoutCallbackPending = false;
2424 m_frame->loader()->didFirstLayout();
2425 if (Page* page = m_frame->page()) {
2426 if (page->mainFrame() == m_frame)
2427 page->startCountingRelevantRepaintedObjects();
2431 // Ensure that we always send this eventually.
2432 if (!m_frame->document()->parsing() && m_frame->loader()->stateMachine()->committedFirstRealDocumentLoad())
2433 m_isVisuallyNonEmpty = true;
2435 // If the layout was done with pending sheets, we are not in fact visually non-empty yet.
2436 if (m_isVisuallyNonEmpty && !m_frame->document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) {
2437 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
2438 m_frame->loader()->didFirstVisuallyNonEmptyLayout();
2442 m_frame->loader()->client()->dispatchDidLayout();
2444 RenderView* root = rootRenderer(this);
2446 root->updateWidgetPositions();
2448 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
2449 if (updateWidgets())
2453 if (Page* page = m_frame->page()) {
2454 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2455 scrollingCoordinator->frameViewLayoutUpdated(this);
2458 #if USE(ACCELERATED_COMPOSITING)
2459 if (TiledBacking* tiledBacking = this->tiledBacking())
2460 tiledBacking->setCanHaveScrollbars(canHaveScrollbars());
2465 m_actionScheduler->resume();
2467 if (root && !root->printing()) {
2468 IntSize currentSize;
2469 if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
2470 currentSize = fixedLayoutSize();
2472 currentSize = visibleContentRect(true /*includeScrollbars*/).size();
2473 float currentZoomFactor = root->style()->zoom();
2474 bool resized = !m_firstLayout && (currentSize != m_lastViewportSize || currentZoomFactor != m_lastZoomFactor);
2475 m_lastViewportSize = currentSize;
2476 m_lastZoomFactor = currentZoomFactor;
2477 #if ENABLE(TIZEN_BLOCK_SENDING_RESIZE_EVENT_WHILE_LOADING)
2478 DocumentLoader* documentLoader = m_frame->loader()->documentLoader();
2479 if (resized && (!documentLoader || !documentLoader->isLoadingInAPISense())) {
2483 m_frame->eventHandler()->sendResizeEvent();
2485 #if ENABLE(INSPECTOR)
2486 if (InspectorInstrumentation::hasFrontends()) {
2487 if (Page* page = m_frame->page()) {
2488 if (page->mainFrame() == m_frame) {
2489 if (InspectorClient* inspectorClient = page->inspectorController()->inspectorClient())
2490 inspectorClient->didResizeMainFrame(m_frame.get());
2499 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
2501 performPostLayoutTasks();
2504 void FrameView::autoSizeIfEnabled()
2506 if (!m_shouldAutoSize)
2512 TemporaryChange<bool> changeInAutoSize(m_inAutoSize, true);
2514 Document* document = frame()->document();
2518 RenderView* documentView = document->renderView();
2519 Element* documentElement = document->documentElement();
2520 if (!documentView || !documentElement)
2523 RenderBox* documentRenderBox = documentElement->renderBox();
2524 if (!documentRenderBox)
2527 // If this is the first time we run autosize, start from small height and
2528 // allow it to grow.
2529 if (!m_didRunAutosize)
2530 resize(frameRect().width(), m_minAutoSize.height());
2532 IntSize size = frameRect().size();
2534 // Do the resizing twice. The first time is basically a rough calculation using the preferred width
2535 // which may result in a height change during the second iteration.
2536 for (int i = 0; i < 2; i++) {
2537 // Update various sizes including contentsSize, scrollHeight, etc.
2538 document->updateLayoutIgnorePendingStylesheets();
2539 int width = documentView->minPreferredLogicalWidth();
2540 int height = documentRenderBox->scrollHeight();
2541 IntSize newSize(width, height);
2543 // Check to see if a scrollbar is needed for a given dimension and
2544 // if so, increase the other dimension to account for the scrollbar.
2545 // Since the dimensions are only for the view rectangle, once a
2546 // dimension exceeds the maximum, there is no need to increase it further.
2547 if (newSize.width() > m_maxAutoSize.width()) {
2548 RefPtr<Scrollbar> localHorizontalScrollbar = horizontalScrollbar();
2549 if (!localHorizontalScrollbar)
2550 localHorizontalScrollbar = createScrollbar(HorizontalScrollbar);
2551 if (!localHorizontalScrollbar->isOverlayScrollbar())
2552 newSize.setHeight(newSize.height() + localHorizontalScrollbar->height());
2554 // Don't bother checking for a vertical scrollbar because the width is at
2555 // already greater the maximum.
2556 } else if (newSize.height() > m_maxAutoSize.height()) {
2557 RefPtr<Scrollbar> localVerticalScrollbar = verticalScrollbar();
2558 if (!localVerticalScrollbar)
2559 localVerticalScrollbar = createScrollbar(VerticalScrollbar);
2560 if (!localVerticalScrollbar->isOverlayScrollbar())
2561 newSize.setWidth(newSize.width() + localVerticalScrollbar->width());
2563 // Don't bother checking for a horizontal scrollbar because the height is
2564 // already greater the maximum.
2567 // Ensure the size is at least the min bounds.
2568 newSize = newSize.expandedTo(m_minAutoSize);
2570 // Bound the dimensions by the max bounds and determine what scrollbars to show.
2571 ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff;
2572 if (newSize.width() > m_maxAutoSize.width()) {
2573 newSize.setWidth(m_maxAutoSize.width());
2574 horizonalScrollbarMode = ScrollbarAlwaysOn;
2576 ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff;
2577 if (newSize.height() > m_maxAutoSize.height()) {
2578 newSize.setHeight(m_maxAutoSize.height());
2579 verticalScrollbarMode = ScrollbarAlwaysOn;
2582 if (newSize == size)
2585 // Avoid doing resizing to a smaller size while the frame is loading to avoid switching to a small size
2586 // during an intermediate state (and then changing back to a bigger size as the load progresses).
2587 if (!frame()->loader()->isComplete() && (newSize.height() < size.height() || newSize.width() < size.width()))
2589 else if (document->processingLoadEvent())
2590 newSize = newSize.expandedTo(size);
2591 resize(newSize.width(), newSize.height());
2592 // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example,
2593 // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed).
2594 setVerticalScrollbarLock(false);
2595 setHorizontalScrollbarLock(false);
2596 setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true);
2598 m_didRunAutosize = true;
2601 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
2603 if (!m_viewportRenderer)
2606 if (m_overflowStatusDirty) {
2607 m_horizontalOverflow = horizontalOverflow;
2608 m_verticalOverflow = verticalOverflow;
2609 m_overflowStatusDirty = false;
2613 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
2614 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
2616 if (horizontalOverflowChanged || verticalOverflowChanged) {
2617 m_horizontalOverflow = horizontalOverflow;
2618 m_verticalOverflow = verticalOverflow;
2620 m_actionScheduler->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
2621 verticalOverflowChanged, verticalOverflow),
2622 m_viewportRenderer->node());
2627 IntRect FrameView::windowClipRect(bool clipToContents) const
2629 ASSERT(m_frame->view() == this);
2631 if (paintsEntireContents())
2632 return IntRect(IntPoint(), contentsSize());
2634 // Set our clip rect to be our contents.
2635 IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
2636 if (!m_frame || !m_frame->ownerElement())
2639 // Take our owner element and get its clip rect.
2640 HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement();
2641 FrameView* parentView = ownerElement->document()->view();
2643 clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement, true));
2647 IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement, bool clipToLayerContents) const
2649 // The renderer can sometimes be null when style="display:none" interacts
2650 // with external content and plugins.
2651 if (!ownerElement->renderer())
2652 return windowClipRect();
2654 // If we have no layer, just return our window clip rect.
2655 const RenderLayer* enclosingLayer = ownerElement->renderer()->enclosingLayer();
2656 if (!enclosingLayer)
2657 return windowClipRect();
2659 // Apply the clip from the layer.
2661 if (clipToLayerContents)
2662 clipRect = pixelSnappedIntRect(enclosingLayer->childrenClipRect());
2664 clipRect = pixelSnappedIntRect(enclosingLayer->selfClipRect());
2665 clipRect = contentsToWindow(clipRect);
2666 return intersection(clipRect, windowClipRect());
2669 bool FrameView::isActive() const
2671 Page* page = frame()->page();
2672 return page && page->focusController()->isActive();
2675 void FrameView::scrollTo(const IntSize& newOffset)
2677 LayoutSize offset = scrollOffset();
2678 ScrollView::scrollTo(newOffset);
2679 #if ENABLE(TIZEN_FRAMEVIEW_NULL_CHECK_WORKAROUND)
2680 // If it is called from resetScrollbars during FrameView destruction, the frame() can be 0.
2681 // In this case, the below codes that access the frame() shouldn't be executed.
2685 if (offset != scrollOffset())
2686 scrollPositionChanged();
2687 frame()->loader()->client()->didChangeScrollOffset();
2690 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
2692 // Add in our offset within the FrameView.
2693 IntRect dirtyRect = rect;
2694 dirtyRect.moveBy(scrollbar->location());
2695 invalidateRect(dirtyRect);
2698 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
2700 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
2703 IntRect FrameView::windowResizerRect() const
2705 Page* page = frame() ? frame()->page() : 0;
2708 return page->chrome()->windowResizerRect();
2711 void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
2713 Page* page = m_frame->page();
2716 if (page->mainFrame() != m_frame)
2718 page->chrome()->client()->notifyScrollerThumbIsVisibleInRect(scrollerThumb);
2721 bool FrameView::isOnActivePage() const
2725 if (m_frame->view() != this)
2727 if (Document* document = m_frame->document())
2728 return !document->inPageCache();
2732 ScrollableArea* FrameView::enclosingScrollableArea() const
2734 // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer.
2738 IntRect FrameView::scrollableAreaBoundingBox() const
2740 // FIXME: This isn't correct for transformed frames. We probably need to ask the renderer instead.
2744 void FrameView::updateScrollableAreaSet()
2746 // That ensures that only inner frames are cached.
2747 if (!parentFrameView())
2751 // 1) display:none or visibility:hidden set to self or inherited.
2752 // 2) overflow{-x,-y}: hidden;
2753 // 3) scrolling: no;
2756 HTMLFrameOwnerElement* owner = m_frame->ownerElement();
2757 if (!owner || !owner->renderer() || !owner->renderer()->visibleToHitTesting()) {
2758 parentFrameView()->removeScrollableArea(this);
2762 IntSize contentSize = contentsSize();
2763 IntSize visibleContentSize = visibleContentRect().size();
2764 if ((contentSize.height() <= visibleContentSize.height() && contentSize.width() <= visibleContentSize.width())) {
2765 parentFrameView()->removeScrollableArea(this);
2770 ScrollbarMode horizontalMode;
2771 ScrollbarMode verticalMode;
2772 calculateScrollbarModesForLayout(horizontalMode, verticalMode, RulesFromWebContentOnly);
2773 if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff) {
2774 parentFrameView()->removeScrollableArea(this);
2778 parentFrameView()->addScrollableArea(this);
2781 bool FrameView::shouldSuspendScrollAnimations() const
2783 return m_frame->loader()->state() != FrameStateComplete;
2786 void FrameView::scrollbarStyleChanged(int newStyle, bool forceUpdate)
2788 Page* page = m_frame->page();
2791 if (page->mainFrame() != m_frame)
2793 page->chrome()->client()->recommendedScrollbarStyleDidChange(newStyle);
2796 ScrollView::scrollbarStyleChanged(newStyle, forceUpdate);
2799 void FrameView::setAnimatorsAreActive()
2801 Page* page = m_frame->page();
2805 if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
2806 scrollAnimator->setIsActive();
2808 if (!m_scrollableAreas)
2811 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
2812 ScrollableArea* scrollableArea = *it;
2814 ASSERT(scrollableArea->isOnActivePage());
2815 scrollableArea->scrollAnimator()->setIsActive();
2819 void FrameView::notifyPageThatContentAreaWillPaint() const
2821 Page* page = m_frame->page();
2825 contentAreaWillPaint();
2827 if (!m_scrollableAreas)
2830 for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
2831 ScrollableArea* scrollableArea = *it;
2833 if (!scrollableArea->isOnActivePage())
2836 scrollableArea->contentAreaWillPaint();
2840 bool FrameView::scrollAnimatorEnabled() const
2842 #if ENABLE(SMOOTH_SCROLLING)
2843 if (Page* page = m_frame->page())
2844 return page->settings()->scrollAnimatorEnabled();
2850 #if ENABLE(DASHBOARD_SUPPORT)
2851 void FrameView::updateDashboardRegions()
2853 Document* document = m_frame->document();
2854 if (!document->hasDashboardRegions())
2856 Vector<DashboardRegionValue> newRegions;
2857 document->renderBox()->collectDashboardRegions(newRegions);
2858 if (newRegions == document->dashboardRegions())
2860 document->setDashboardRegions(newRegions);
2861 Page* page = m_frame->page();
2864 page->chrome()->client()->dashboardRegionsChanged();
2868 void FrameView::updateScrollCorner()
2870 RenderObject* renderer = 0;
2871 RefPtr<RenderStyle> cornerStyle;
2872 IntRect cornerRect = scrollCornerRect();
2874 if (!cornerRect.isEmpty()) {
2875 // Try the <body> element first as a scroll corner source.
2876 Document* doc = m_frame->document();
2877 Element* body = doc ? doc->body() : 0;
2878 if (body && body->renderer()) {
2879 renderer = body->renderer();
2880 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2884 // If the <body> didn't have a custom style, then the root element might.
2885 Element* docElement = doc ? doc->documentElement() : 0;
2886 if (docElement && docElement->renderer()) {
2887 renderer = docElement->renderer();
2888 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2893 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
2894 if (RenderPart* renderer = m_frame->ownerRenderer())
2895 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2900 if (!m_scrollCorner)
2901 m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document());
2902 m_scrollCorner->setStyle(cornerStyle.release());
2903 invalidateScrollCorner(cornerRect);
2904 } else if (m_scrollCorner) {
2905 m_scrollCorner->destroy();
2909 ScrollView::updateScrollCorner();
2912 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
2914 if (context->updatingControlTints()) {
2915 updateScrollCorner();
2919 if (m_scrollCorner) {
2920 bool needsBackgorund = m_frame->page() && m_frame->page()->mainFrame() == m_frame;
2921 if (needsBackgorund)
2922 context->fillRect(cornerRect, baseBackgroundColor(), ColorSpaceDeviceRGB);
2923 m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect);
2927 ScrollView::paintScrollCorner(context, cornerRect);
2930 void FrameView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
2932 bool needsBackgorund = bar->isCustomScrollbar() && (m_frame->page() && m_frame->page()->mainFrame() == m_frame);
2933 if (needsBackgorund) {
2934 IntRect toFill = bar->frameRect();
2935 toFill.intersect(rect);
2936 context->fillRect(toFill, baseBackgroundColor(), ColorSpaceDeviceRGB);
2939 ScrollView::paintScrollbar(context, bar, rect);
2942 Color FrameView::documentBackgroundColor() const
2944 // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of
2945 // the document and the body against the base background color of the frame view.
2946 // Background images are unfortunately impractical to include.
2948 // Return invalid Color objects whenever there is insufficient information.
2949 if (!frame()->document())
2952 Element* htmlElement = frame()->document()->documentElement();
2953 Element* bodyElement = frame()->document()->body();
2955 // Start with invalid colors.
2956 Color htmlBackgroundColor;
2957 Color bodyBackgroundColor;
2958 if (htmlElement && htmlElement->renderer())
2959 htmlBackgroundColor = htmlElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
2960 if (bodyElement && bodyElement->renderer())
2961 bodyBackgroundColor = bodyElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
2963 if (!bodyBackgroundColor.isValid()) {
2964 if (!htmlBackgroundColor.isValid())
2966 return baseBackgroundColor().blend(htmlBackgroundColor);
2969 if (!htmlBackgroundColor.isValid())
2970 return baseBackgroundColor().blend(bodyBackgroundColor);
2972 // We take the aggregate of the base background color
2973 // the <html> background color, and the <body>
2974 // background color to find the document color. The
2975 // addition of the base background color is not
2976 // technically part of the document background, but it
2977 // otherwise poses problems when the aggregate is not
2979 return baseBackgroundColor().blend(htmlBackgroundColor).blend(bodyBackgroundColor);
2982 bool FrameView::hasCustomScrollbars() const
2984 const HashSet<RefPtr<Widget> >* viewChildren = children();
2985 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2986 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2987 Widget* widget = current->get();
2988 if (widget->isFrameView()) {
2989 if (static_cast<FrameView*>(widget)->hasCustomScrollbars())
2991 } else if (widget->isScrollbar()) {
2992 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
2993 if (scrollbar->isCustomScrollbar())
3001 FrameView* FrameView::parentFrameView() const
3003 if (Frame* parentFrame = m_frame->tree()->parent())
3004 return parentFrame->view();
3009 bool FrameView::isInChildFrameWithFrameFlattening() const
3011 if (!parent() || !m_frame->ownerElement())
3014 // Frame flattening applies when the owner element is either in a frameset or
3015 // an iframe with flattening parameters.
3016 if (m_frame->ownerElement()->hasTagName(iframeTag)) {
3017 RenderIFrame* iframeRenderer = toRenderIFrame(m_frame->ownerElement()->renderPart());
3018 if (iframeRenderer->flattenFrame() || iframeRenderer->isSeamless())
3022 if (!m_frame->settings() || !m_frame->settings()->frameFlatteningEnabled())
3025 if (m_frame->ownerElement()->hasTagName(frameTag))
3031 bool FrameView::doLayoutWithFrameFlattening(bool allowSubtree)
3033 // Try initiating layout from the topmost parent.
3034 FrameView* parentView = parentFrameView();
3039 // In the middle of parent layout, no need to restart from topmost.
3040 if (parentView->m_nestedLayoutCount)
3043 // Parent tree is clean. Starting layout from it would have no effect.
3044 if (!parentView->needsLayout())
3047 while (parentView->parentFrameView())
3048 parentView = parentView->parentFrameView();
3050 parentView->layout(allowSubtree);
3052 RenderObject* root = m_layoutRoot ? m_layoutRoot : m_frame->document()->renderer();
3053 ASSERT_UNUSED(root, !root->needsLayout());
3058 void FrameView::updateControlTints()
3060 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
3061 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
3062 // This is only done if the theme supports control tinting. It's up to the theme and platform
3063 // to define when controls get the tint and to call this function when that changes.
3065 // Optimize the common case where we bring a window to the front while it's still empty.
3066 if (!m_frame || m_frame->document()->url().isEmpty())
3069 RenderView* root = rootRenderer(this);
3070 if ((root && root->theme()->supportsControlTints()) || hasCustomScrollbars())
3071 paintControlTints();
3074 void FrameView::paintControlTints()
3078 PlatformGraphicsContext* const noContext = 0;
3079 GraphicsContext context(noContext);
3080 context.setUpdatingControlTints(true);
3081 if (platformWidget())
3082 paintContents(&context, visibleContentRect());
3084 paint(&context, frameRect());
3087 bool FrameView::wasScrolledByUser() const
3089 return m_wasScrolledByUser;
3092 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
3094 if (m_inProgrammaticScroll)
3096 m_maintainScrollPositionAnchor = 0;
3097 m_wasScrolledByUser = wasScrolledByUser;
3100 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
3105 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get(), p, rect);
3107 Document* document = m_frame->document();
3111 if (document->printing())
3112 fillWithRed = false; // Printing, don't fill with red (can't remember why).
3113 else if (m_frame->ownerElement())
3114 fillWithRed = false; // Subframe, don't fill with red.
3115 else if (isTransparent())
3116 fillWithRed = false; // Transparent, don't fill with red.
3117 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
3118 fillWithRed = false; // Selections are transparent, don't fill with red.
3119 else if (m_nodeToDraw)
3120 fillWithRed = false; // Element images are transparent, don't fill with red.
3125 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
3128 Page* page = m_frame->page();
3129 if (page->mainFrame() == m_frame && page->pagination().mode != Page::Pagination::Unpaginated)
3130 p->fillRect(rect, baseBackgroundColor(), ColorSpaceDeviceRGB);
3132 RenderView* root = rootRenderer(this);
3134 LOG_ERROR("called FrameView::paint with nil renderer");
3138 ASSERT(!needsLayout());
3142 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
3143 if (isTopLevelPainter)
3144 sCurrentPaintTimeStamp = currentTime();
3146 FontCachePurgePreventer fontCachePurgePreventer;
3148 #if USE(ACCELERATED_COMPOSITING)
3149 if (!p->paintingDisabled() && !document->printing())
3150 syncCompositingStateForThisFrame(m_frame.get());
3153 PaintBehavior oldPaintBehavior = m_paintBehavior;
3155 if (FrameView* parentView = parentFrameView()) {
3156 if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
3157 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
3160 if (m_paintBehavior == PaintBehaviorNormal)
3161 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
3163 if (document->printing())
3164 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
3166 bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers;
3167 bool isRootFrame = !m_frame->ownerElement();
3168 if (flatteningPaint && isRootFrame)
3169 notifyWidgetsInAllFrames(WillPaintFlattened);
3171 ASSERT(!m_isPainting);
3172 m_isPainting = true;
3174 // m_nodeToDraw is used to draw only one element (and its descendants)
3175 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
3176 RenderLayer* rootLayer = root->layer();
3178 rootLayer->paint(p, rect, m_paintBehavior, eltRenderer);
3180 if (rootLayer->containsDirtyOverlayScrollbars())
3181 rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer);
3183 m_isPainting = false;
3185 if (flatteningPaint && isRootFrame)
3186 notifyWidgetsInAllFrames(DidPaintFlattened);
3188 m_paintBehavior = oldPaintBehavior;
3189 m_lastPaintTime = currentTime();
3191 #if ENABLE(DASHBOARD_SUPPORT)
3192 // Regions may have changed as a result of the visibility/z-index of element changing.
3193 if (document->dashboardRegionsDirty())
3194 updateDashboardRegions();
3197 if (isTopLevelPainter)
3198 sCurrentPaintTimeStamp = 0;
3200 InspectorInstrumentation::didPaint(cookie);
3203 void FrameView::setPaintBehavior(PaintBehavior behavior)
3205 m_paintBehavior = behavior;
3208 PaintBehavior FrameView::paintBehavior() const
3210 return m_paintBehavior;
3213 bool FrameView::isPainting() const
3215 return m_isPainting;
3218 void FrameView::setNodeToDraw(Node* node)
3220 m_nodeToDraw = node;
3223 void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
3225 if (context->paintingDisabled())
3228 if (m_frame->document()->printing())
3231 Page* page = m_frame->page();
3232 if (page->mainFrame() == m_frame) {
3233 if (page->chrome()->client()->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
3237 ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
3240 void FrameView::updateLayoutAndStyleIfNeededRecursive()
3242 // We have to crawl our entire tree looking for any FrameViews that need
3243 // layout and make sure they are up to date.
3244 // Mac actually tests for intersection with the dirty region and tries not to
3245 // update layout for frames that are outside the dirty region. Not only does this seem
3246 // pointless (since those frames will have set a zero timer to layout anyway), but
3247 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
3248 // region but then become included later by the second frame adding rects to the dirty region
3249 // when it lays out.
3251 m_frame->document()->updateStyleIfNeeded();
3256 // Grab a copy of the children() set, as it may be mutated by the following updateLayoutAndStyleIfNeededRecursive
3257 // calls, as they can potentially re-enter a layout of the parent frame view, which may add/remove scrollbars
3258 // and thus mutates the children() set.
3259 Vector<RefPtr<FrameView> > frameViews;
3260 collectFrameViewChildren(this, frameViews);
3262 const Vector<RefPtr<FrameView> >::iterator end = frameViews.end();
3263 for (Vector<RefPtr<FrameView> >::iterator it = frameViews.begin(); it != end; ++it)
3264 (*it)->updateLayoutAndStyleIfNeededRecursive();
3266 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
3267 // painting, so we need to flush out any deferred repaints too.
3268 flushDeferredRepaints();
3270 // When frame flattening is on, child frame can mark parent frame dirty. In such case, child frame
3271 // needs to call layout on parent frame recursively.
3272 // This assert ensures that parent frames are clean, when child frames finished updating layout and style.
3273 ASSERT(!needsLayout());
3276 void FrameView::flushDeferredRepaints()
3278 if (!m_deferredRepaintTimer.isActive())
3280 m_deferredRepaintTimer.stop();
3281 doDeferredRepaints();
3284 void FrameView::enableAutoSizeMode(bool enable, const IntSize& minSize, const IntSize& maxSize)
3286 ASSERT(!enable || !minSize.isEmpty());
3287 ASSERT(minSize.width() <= maxSize.width());
3288 ASSERT(minSize.height() <= maxSize.height());
3290 if (m_shouldAutoSize == enable && m_minAutoSize == minSize && m_maxAutoSize == maxSize)
3293 m_shouldAutoSize = enable;
3294 m_minAutoSize = minSize;
3295 m_maxAutoSize = maxSize;
3296 m_didRunAutosize = false;
3300 if (m_shouldAutoSize)
3303 // Since autosize mode forces the scrollbar mode, change them to being auto.
3304 setVerticalScrollbarLock(false);
3305 setHorizontalScrollbarLock(false);
3306 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
3309 void FrameView::forceLayout(bool allowSubtree)
3311 layout(allowSubtree);
3314 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor, AdjustViewSizeOrNot shouldAdjustViewSize)
3316 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
3317 // the state of things before and after the layout
3318 if (RenderView* root = rootRenderer(this)) {
3319 float pageLogicalWidth = root->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
3320 float pageLogicalHeight = root->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
3322 LayoutUnit flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
3323 LayoutUnit flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
3324 root->setLogicalWidth(flooredPageLogicalWidth);
3325 root->setPageLogicalHeight(flooredPageLogicalHeight);
3326 root->setNeedsLayoutAndPrefWidthsRecalc();
3329 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
3330 // page width when shrunk, we will lay out at maximum shrink and clip extra content.
3331 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
3332 // implementation should not do this!
3333 bool horizontalWritingMode = root->style()->isHorizontalWritingMode();
3334 const LayoutRect& documentRect = root->documentRect();
3335 LayoutUnit docLogicalWidth = horizontalWritingMode ? documentRect.width() : documentRect.height();
3336 if (docLogicalWidth > pageLogicalWidth) {
3337 int expectedPageWidth = std::min<float>(documentRect.width(), pageSize.width() * maximumShrinkFactor);
3338 int expectedPageHeight = std::min<float>(documentRect.height(), pageSize.height() * maximumShrinkFactor);
3339 FloatSize maxPageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(originalPageSize.width(), originalPageSize.height()), FloatSize(expectedPageWidth, expectedPageHeight));
3340 pageLogicalWidth = horizontalWritingMode ? maxPageSize.width() : maxPageSize.height();
3341 pageLogicalHeight = horizontalWritingMode ? maxPageSize.height() : maxPageSize.width();
3343 flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
3344 flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
3345 root->setLogicalWidth(flooredPageLogicalWidth);
3346 root->setPageLogicalHeight(flooredPageLogicalHeight);
3347 root->setNeedsLayoutAndPrefWidthsRecalc();
3350 const LayoutRect& updatedDocumentRect = root->documentRect();
3351 LayoutUnit docLogicalHeight = horizontalWritingMode ? updatedDocumentRect.height() : updatedDocumentRect.width();
3352 LayoutUnit docLogicalTop = horizontalWritingMode ? updatedDocumentRect.y() : updatedDocumentRect.x();
3353 LayoutUnit docLogicalRight = horizontalWritingMode ? updatedDocumentRect.maxX() : updatedDocumentRect.maxY();
3354 LayoutUnit clippedLogicalLeft = 0;
3355 if (!root->style()->isLeftToRightDirection())
3356 clippedLogicalLeft = docLogicalRight - pageLogicalWidth;
3357 LayoutRect overflow(clippedLogicalLeft, docLogicalTop, pageLogicalWidth, docLogicalHeight);
3359 if (!horizontalWritingMode)
3360 overflow = overflow.transposedRect();
3361 root->clearLayoutOverflow();
3362 root->addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
3366 if (shouldAdjustViewSize)
3370 void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
3372 if (RenderView* root = rootRenderer(this)) {
3373 // Use a context with painting disabled.
3374 GraphicsContext context((PlatformGraphicsContext*)0);
3375 root->setTruncatedAt(static_cast<int>(floorf(oldBottom)));
3376 IntRect dirtyRect(0, static_cast<int>(floorf(oldTop)), root->layoutOverflowRect().maxX(), static_cast<int>(ceilf(oldBottom - oldTop)));
3377 root->setPrintRect(dirtyRect);
3378 root->layer()->paint(&context, dirtyRect);
3379 *newBottom = root->bestTruncatedAt();
3380 if (*newBottom == 0)
3381 *newBottom = oldBottom;
3382 root->setPrintRect(IntRect());
3384 *newBottom = oldBottom;
3387 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
3389 IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
3391 // Convert from page ("absolute") to FrameView coordinates.
3392 if (!delegatesScrolling())
3393 rect.moveBy(-scrollPosition());
3398 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
3400 IntRect rect = viewRect;
3402 // Convert from FrameView coords into page ("absolute") coordinates.
3403 if (!delegatesScrolling())
3404 rect.moveBy(scrollPosition());
3406 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
3407 // move the rect for now.
3408 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
3412 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
3414 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
3416 // Convert from page ("absolute") to FrameView coordinates.
3417 if (!delegatesScrolling())
3418 point.moveBy(-scrollPosition());
3422 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
3424 IntPoint point = viewPoint;
3426 // Convert from FrameView coords into page ("absolute") coordinates.
3427 if (!delegatesScrolling())
3428 point += IntSize(scrollX(), scrollY());
3430 return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
3433 IntRect FrameView::convertToContainingView(const IntRect& localRect) const
3435 if (const ScrollView* parentScrollView = parent()) {
3436 if (parentScrollView->isFrameView()) {
3437 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
3438 // Get our renderer in the parent view
3439 RenderPart* renderer = m_frame->ownerRenderer();
3443 IntRect rect(localRect);
3444 // Add borders and padding??
3445 rect.move(renderer->borderLeft() + renderer->paddingLeft(),
3446 renderer->borderTop() + renderer->paddingTop());
3447 return parentView->convertFromRenderer(renderer, rect);
3450 return Widget::convertToContainingView(localRect);
3456 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
3458 if (const ScrollView* parentScrollView = parent()) {
3459 if (parentScrollView->isFrameView()) {
3460 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
3462 // Get our renderer in the parent view
3463 RenderPart* renderer = m_frame->ownerRenderer();
3467 IntRect rect = parentView->convertToRenderer(renderer, parentRect);
3468 // Subtract borders and padding
3469 rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
3470 -renderer->borderTop() - renderer->paddingTop());
3474 return Widget::convertFromContainingView(parentRect);
3480 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
3482 if (const ScrollView* parentScrollView = parent()) {
3483 if (parentScrollView->isFrameView()) {
3484 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
3486 // Get our renderer in the parent view
3487 RenderPart* renderer = m_frame->ownerRenderer();
3491 IntPoint point(localPoint);
3493 // Add borders and padding
3494 point.move(renderer->borderLeft() + renderer->paddingLeft(),
3495 renderer->borderTop() + renderer->paddingTop());
3496 return parentView->convertFromRenderer(renderer, point);
3499 return Widget::convertToContainingView(localPoint);
3505 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
3507 if (const ScrollView* parentScrollView = parent()) {
3508 if (parentScrollView->isFrameView()) {
3509 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
3511 // Get our renderer in the parent view
3512 RenderPart* renderer = m_frame->ownerRenderer();
3516 IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
3517 // Subtract borders and padding
3518 point.move(-renderer->borderLeft() - renderer->paddingLeft(),
3519 -renderer->borderTop() - renderer->paddingTop());
3523 return Widget::convertFromContainingView(parentPoint);
3530 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
3532 s_deferredRepaintDelay = p;
3535 // Negative value would mean that first few repaints happen without a delay
3536 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)
3538 s_initialDeferredRepaintDelayDuringLoading = p;
3541 // The delay grows on each repaint to this maximum value
3542 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)
3544 s_maxDeferredRepaintDelayDuringLoading = p;
3547 // On each repaint the delay increases by this amount
3548 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)
3550 s_deferredRepaintDelayIncrementDuringLoading = p;
3553 void FrameView::setTracksRepaints(bool trackRepaints)
3555 if (trackRepaints == m_isTrackingRepaints)
3558 m_trackedRepaintRects.clear();
3559 m_isTrackingRepaints = trackRepaints;
3562 void FrameView::addScrollableArea(ScrollableArea* scrollableArea)
3564 if (!m_scrollableAreas)
3565 m_scrollableAreas = adoptPtr(new ScrollableAreaSet);
3566 m_scrollableAreas->add(scrollableArea);
3569 void FrameView::removeScrollableArea(ScrollableArea* scrollableArea)
3571 if (!m_scrollableAreas)
3573 m_scrollableAreas->remove(scrollableArea);
3576 bool FrameView::containsScrollableArea(ScrollableArea* scrollableArea) const
3578 if (!m_scrollableAreas)
3580 return m_scrollableAreas->contains(scrollableArea);
3583 void FrameView::removeChild(Widget* widget)
3585 if (widget->isFrameView())
3586 removeScrollableArea(static_cast<FrameView*>(widget));
3588 ScrollView::removeChild(widget);
3591 bool FrameView::wheelEvent(const PlatformWheelEvent& wheelEvent)
3593 // We don't allow mouse wheeling to happen in a ScrollView that has had its scrollbars explicitly disabled.
3594 if (!canHaveScrollbars())
3598 if (platformWidget())
3602 #if ENABLE(THREADED_SCROLLING)
3603 if (Page* page = m_frame->page()) {
3604 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
3605 if (scrollingCoordinator->coordinatesScrollingForFrameView(this))
3606 return scrollingCoordinator->handleWheelEvent(this, wheelEvent);
3611 return ScrollableArea::handleWheelEvent(wheelEvent);
3615 bool FrameView::isVerticalDocument() const
3617 RenderView* root = rootRenderer(this);
3621 return root->style()->isHorizontalWritingMode();
3624 bool FrameView::isFlippedDocument() const
3626 RenderView* root = rootRenderer(this);
3630 return root->style()->isFlippedBlocksWritingMode();
3633 void FrameView::notifyWidgetsInAllFrames(WidgetNotification notification)
3635 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
3636 if (RenderView* root = frame->contentRenderer())
3637 root->notifyWidgets(notification);
3641 AXObjectCache* FrameView::axObjectCache() const
3643 if (frame() && frame()->document() && frame()->document()->axObjectCacheExists())
3644 return frame()->document()->axObjectCache();
3648 } // namespace WebCore