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 "CSSStyleSelector.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"
40 #include "FrameLoader.h"
41 #include "FrameLoaderClient.h"
42 #include "FrameTree.h"
43 #include "GraphicsContext.h"
44 #include "HTMLDocument.h"
45 #include "HTMLFrameElement.h"
46 #include "HTMLFrameSetElement.h"
47 #include "HTMLNames.h"
48 #include "HTMLPlugInImageElement.h"
49 #include "InspectorInstrumentation.h"
50 #include "OverflowEvent.h"
51 #include "RenderEmbeddedObject.h"
52 #include "RenderFullScreen.h"
53 #include "RenderLayer.h"
54 #include "RenderPart.h"
55 #include "RenderScrollbar.h"
56 #include "RenderScrollbarPart.h"
57 #include "RenderTheme.h"
58 #include "RenderView.h"
59 #include "ScrollAnimator.h"
61 #include "TextResourceDecoder.h"
62 #include <wtf/CurrentTime.h>
64 #if USE(ACCELERATED_COMPOSITING)
65 #include "RenderLayerCompositor.h"
69 #include "SVGDocument.h"
70 #include "SVGLocatable.h"
72 #include "SVGPreserveAspectRatio.h"
73 #include "SVGSVGElement.h"
74 #include "SVGViewElement.h"
75 #include "SVGViewSpec.h"
78 #if ENABLE(TILED_BACKING_STORE)
79 #include "TiledBackingStore.h"
84 using namespace HTMLNames;
86 double FrameView::sCurrentPaintTimeStamp = 0.0;
88 // REPAINT_THROTTLING now chooses default values for throttling parameters.
89 // Should be removed when applications start using runtime configuration.
90 #if ENABLE(REPAINT_THROTTLING)
92 double FrameView::s_deferredRepaintDelay = 0.025;
93 // Negative value would mean that first few repaints happen without a delay
94 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
95 // The delay grows on each repaint to this maximum value
96 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
97 // On each repaint the delay increses by this amount
98 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
100 // FIXME: Repaint throttling could be good to have on all platform.
101 // The balance between CPU use and repaint frequency will need some tuning for desktop.
102 // More hooks may be needed to reset the delay on things like GIF and CSS animations.
103 double FrameView::s_deferredRepaintDelay = 0;
104 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
105 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
106 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
109 // The maximum number of updateWidgets iterations that should be done before returning.
110 static const unsigned maxUpdateWidgetsIterations = 2;
112 struct ScheduledEvent {
113 WTF_MAKE_NONCOPYABLE(ScheduledEvent); WTF_MAKE_FAST_ALLOCATED;
116 RefPtr<Event> m_event;
117 RefPtr<Node> m_eventTarget;
120 FrameView::FrameView(Frame* frame)
122 , m_canHaveScrollbars(true)
123 , m_slowRepaintObjectCount(0)
124 , m_fixedObjectCount(0)
125 , m_layoutTimer(this, &FrameView::layoutTimerFired)
127 , m_hasPendingPostLayoutTasks(false)
128 , m_inSynchronousPostLayout(false)
129 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
130 , m_isTransparent(false)
131 , m_baseBackgroundColor(Color::white)
132 , m_mediaType("screen")
134 , m_overflowStatusDirty(true)
135 , m_viewportRenderer(0)
136 , m_wasScrolledByUser(false)
137 , m_inProgrammaticScroll(false)
138 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
139 , m_shouldUpdateWhileOffscreen(true)
140 , m_deferSetNeedsLayouts(0)
141 , m_setNeedsLayoutWasDeferred(false)
147 PassRefPtr<FrameView> FrameView::create(Frame* frame)
149 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
151 return view.release();
154 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize)
156 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
157 view->Widget::setFrameRect(IntRect(view->pos(), initialSize));
159 return view.release();
162 FrameView::~FrameView()
164 if (m_hasPendingPostLayoutTasks) {
165 m_postLayoutTasksTimer.stop();
166 m_scheduledEvents.clear();
170 if (AXObjectCache::accessibilityEnabled() && axObjectCache())
171 axObjectCache()->remove(this);
175 // Custom scrollbars should already be destroyed at this point
176 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
177 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
179 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
180 setHasVerticalScrollbar(false);
182 ASSERT(!m_scrollCorner);
183 ASSERT(m_scheduledEvents.isEmpty());
184 ASSERT(!m_enqueueEvents);
187 ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
188 RenderPart* renderer = m_frame->ownerRenderer();
189 if (renderer && renderer->widget() == this)
190 renderer->setWidget(0);
194 void FrameView::reset()
196 m_useSlowRepaints = false;
197 m_isOverlapped = false;
198 m_contentIsOpaque = false;
201 m_layoutTimer.stop();
203 m_delayedLayout = false;
204 m_doFullRepaint = true;
205 m_layoutSchedulingEnabled = true;
207 m_inSynchronousPostLayout = false;
208 m_hasPendingPostLayoutTasks = false;
210 m_nestedLayoutCount = 0;
211 m_postLayoutTasksTimer.stop();
212 m_firstLayout = true;
213 m_firstLayoutCallbackPending = false;
214 m_wasScrolledByUser = false;
215 m_lastLayoutSize = IntSize();
216 m_lastZoomFactor = 1.0f;
217 m_deferringRepaints = 0;
219 m_repaintRects.clear();
220 m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading;
221 m_deferredRepaintTimer.stop();
223 m_paintBehavior = PaintBehaviorNormal;
224 m_isPainting = false;
225 m_isVisuallyNonEmpty = false;
226 m_firstVisuallyNonEmptyLayoutCallbackPending = true;
227 m_maintainScrollPositionAnchor = 0;
230 bool FrameView::isFrameView() const
235 void FrameView::clearFrame()
240 void FrameView::resetScrollbars()
242 // Reset the document's scrollbars back to our defaults before we yield the floor.
243 m_firstLayout = true;
244 setScrollbarsSuppressed(true);
245 if (m_canHaveScrollbars)
246 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
248 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
249 setScrollbarsSuppressed(false);
252 void FrameView::init()
256 m_margins = IntSize(-1, -1); // undefined
259 // Propagate the marginwidth/height and scrolling modes to the view.
260 Element* ownerElement = m_frame && m_frame->document() ? m_frame->document()->ownerElement() : 0;
261 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
262 HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement);
263 if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
264 setCanHaveScrollbars(false);
265 int marginWidth = frameElt->marginWidth();
266 int marginHeight = frameElt->marginHeight();
267 if (marginWidth != -1)
268 setMarginWidth(marginWidth);
269 if (marginHeight != -1)
270 setMarginHeight(marginHeight);
274 void FrameView::detachCustomScrollbars()
279 Scrollbar* horizontalBar = horizontalScrollbar();
280 if (horizontalBar && horizontalBar->isCustomScrollbar())
281 setHasHorizontalScrollbar(false);
283 Scrollbar* verticalBar = verticalScrollbar();
284 if (verticalBar && verticalBar->isCustomScrollbar())
285 setHasVerticalScrollbar(false);
287 if (m_scrollCorner) {
288 m_scrollCorner->destroy();
293 void FrameView::clear()
295 setCanBlitOnScroll(true);
300 if (RenderPart* renderer = m_frame->ownerRenderer())
301 renderer->viewCleared();
304 setScrollbarsSuppressed(true);
307 bool FrameView::didFirstLayout() const
309 return !m_firstLayout;
312 void FrameView::invalidateRect(const IntRect& rect)
315 if (hostWindow() && shouldUpdate())
316 hostWindow()->invalidateContentsAndWindow(rect, false /*immediate*/);
323 RenderPart* renderer = m_frame->ownerRenderer();
327 IntRect repaintRect = rect;
328 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
329 renderer->borderTop() + renderer->paddingTop());
330 renderer->repaintRectangle(repaintRect);
333 void FrameView::setFrameRect(const IntRect& newRect)
335 IntRect oldRect = frameRect();
336 if (newRect == oldRect)
339 ScrollView::setFrameRect(newRect);
341 #if USE(ACCELERATED_COMPOSITING)
342 if (RenderView* root = m_frame->contentRenderer()) {
343 if (root->usesCompositing())
344 root->compositor()->frameViewDidChangeSize();
349 #if ENABLE(REQUEST_ANIMATION_FRAME)
350 void FrameView::scheduleAnimation()
353 hostWindow()->scheduleAnimation();
357 void FrameView::setMarginWidth(int w)
359 // make it update the rendering area when set
360 m_margins.setWidth(w);
363 void FrameView::setMarginHeight(int h)
365 // make it update the rendering area when set
366 m_margins.setHeight(h);
369 bool FrameView::avoidScrollbarCreation() const
373 // with frame flattening no subframe can have scrollbars
374 // but we also cannot turn scrollbars of as we determine
375 // our flattening policy using that.
377 if (!m_frame->ownerElement())
380 if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
386 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
388 m_canHaveScrollbars = canHaveScrollbars;
389 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
392 void FrameView::updateCanHaveScrollbars()
396 scrollbarModes(hMode, vMode);
397 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
398 setCanHaveScrollbars(false);
400 setCanHaveScrollbars(true);
403 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
405 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
406 Document* doc = m_frame->document();
408 // Try the <body> element first as a scrollbar source.
409 Element* body = doc ? doc->body() : 0;
410 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
411 return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderer()->enclosingBox());
413 // If the <body> didn't have a custom style, then the root element might.
414 Element* docElement = doc ? doc->documentElement() : 0;
415 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
416 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox());
418 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
419 RenderPart* frameRenderer = m_frame->ownerRenderer();
420 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
421 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
423 // Nobody set a custom style, so we just use a native scrollbar.
424 return ScrollView::createScrollbar(orientation);
427 void FrameView::setContentsSize(const IntSize& size)
429 if (size == contentsSize())
432 m_deferSetNeedsLayouts++;
434 ScrollView::setContentsSize(size);
435 scrollAnimator()->contentsResized();
437 Page* page = frame() ? frame()->page() : 0;
441 page->chrome()->contentsSizeChanged(frame(), size); //notify only
443 m_deferSetNeedsLayouts--;
445 if (!m_deferSetNeedsLayouts)
446 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
449 void FrameView::adjustViewSize()
451 ASSERT(m_frame->view() == this);
452 RenderView* root = m_frame->contentRenderer();
456 IntSize size = IntSize(root->docWidth(), root->docHeight());
458 ScrollView::setScrollOrigin(IntPoint(-root->docLeft(), -root->docTop()), !m_frame->document()->printing(), size == contentsSize());
460 setContentsSize(size);
463 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
465 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
466 // overflow:hidden and overflow:scroll on <body> as applying to the document's
467 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
468 // use the root element.
469 switch (o->style()->overflowX()) {
471 hMode = ScrollbarAlwaysOff;
474 hMode = ScrollbarAlwaysOn;
477 hMode = ScrollbarAuto;
480 // Don't set it at all.
484 switch (o->style()->overflowY()) {
486 vMode = ScrollbarAlwaysOff;
489 vMode = ScrollbarAlwaysOn;
492 vMode = ScrollbarAuto;
495 // Don't set it at all.
499 m_viewportRenderer = o;
502 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode)
504 const HTMLFrameOwnerElement* owner = m_frame->ownerElement();
505 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
506 hMode = ScrollbarAlwaysOff;
507 vMode = ScrollbarAlwaysOff;
511 if (m_canHaveScrollbars) {
512 hMode = ScrollbarAuto;
513 vMode = ScrollbarAuto;
515 hMode = ScrollbarAlwaysOff;
516 vMode = ScrollbarAlwaysOff;
520 Document* document = m_frame->document();
521 Node* documentElement = document->documentElement();
522 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
523 Node* body = document->body();
524 if (body && body->renderer()) {
525 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
526 vMode = ScrollbarAlwaysOff;
527 hMode = ScrollbarAlwaysOff;
528 } else if (body->hasTagName(bodyTag)) {
529 // It's sufficient to just check the X overflow,
530 // since it's illegal to have visible in only one direction.
531 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
532 applyOverflowToViewport(o, hMode, vMode);
534 } else if (rootRenderer) {
536 if (!documentElement->isSVGElement())
537 applyOverflowToViewport(rootRenderer, hMode, vMode);
539 applyOverflowToViewport(rootRenderer, hMode, vMode);
545 #if ENABLE(FULLSCREEN_API) && USE(ACCELERATED_COMPOSITING)
546 static bool isDocumentRunningFullScreenAnimation(Document* document)
548 return document->webkitIsFullScreen() && document->fullScreenRenderer() && document->fullScreenRenderer()->isAnimating();
552 #if USE(ACCELERATED_COMPOSITING)
553 void FrameView::updateCompositingLayers()
555 RenderView* view = m_frame->contentRenderer();
559 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
560 view->compositor()->cacheAcceleratedCompositingFlags();
561 view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange);
563 #if ENABLE(FULLSCREEN_API)
564 Document* document = m_frame->document();
565 if (isDocumentRunningFullScreenAnimation(document))
566 view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange, document->fullScreenRenderer()->layer());
570 bool FrameView::syncCompositingStateForThisFrame()
572 ASSERT(m_frame->view() == this);
573 RenderView* view = m_frame->contentRenderer();
575 return true; // We don't want to keep trying to update layers if we have no renderer.
577 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
578 // layer content to occur before layout has happened, which will cause paintContents() to bail.
582 view->compositor()->flushPendingLayerChanges();
584 #if ENABLE(FULLSCREEN_API)
585 // The fullScreenRenderer's graphicsLayer has been re-parented, and the above recursive syncCompositingState
586 // call will not cause the subtree under it to repaint. Explicitly call the syncCompositingState on
587 // the fullScreenRenderer's graphicsLayer here:
588 Document* document = m_frame->document();
589 if (isDocumentRunningFullScreenAnimation(document)) {
590 RenderLayerBacking* backing = document->fullScreenRenderer()->layer()->backing();
591 if (GraphicsLayer* fullScreenLayer = backing->graphicsLayer())
592 fullScreenLayer->syncCompositingState();
598 void FrameView::setNeedsOneShotDrawingSynchronization()
600 Page* page = frame() ? frame()->page() : 0;
602 page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
605 #endif // USE(ACCELERATED_COMPOSITING)
607 bool FrameView::hasCompositedContent() const
609 #if USE(ACCELERATED_COMPOSITING)
610 if (RenderView* view = m_frame->contentRenderer())
611 return view->compositor()->inCompositingMode();
616 bool FrameView::hasCompositedContentIncludingDescendants() const
618 #if USE(ACCELERATED_COMPOSITING)
619 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
620 RenderView* renderView = frame->contentRenderer();
621 RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0;
623 if (compositor->inCompositingMode())
626 if (!RenderLayerCompositor::allowsIndependentlyCompositedIFrames(this))
634 bool FrameView::hasCompositingAncestor() const
636 #if USE(ACCELERATED_COMPOSITING)
637 for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) {
638 if (FrameView* view = frame->view()) {
639 if (view->hasCompositedContent())
647 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
648 void FrameView::enterCompositingMode()
650 #if USE(ACCELERATED_COMPOSITING)
651 if (RenderView* view = m_frame->contentRenderer()) {
652 view->compositor()->enableCompositingMode();
654 view->compositor()->scheduleCompositingLayerUpdate();
659 bool FrameView::isEnclosedInCompositingLayer() const
661 #if USE(ACCELERATED_COMPOSITING)
662 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
663 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
666 if (Frame* parentFrame = m_frame->tree()->parent()) {
667 if (FrameView* parentView = parentFrame->view())
668 return parentView->isEnclosedInCompositingLayer();
674 bool FrameView::syncCompositingStateIncludingSubframes()
676 #if USE(ACCELERATED_COMPOSITING)
677 bool allFramesSynced = syncCompositingStateForThisFrame();
679 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame.get())) {
680 bool synced = child->view()->syncCompositingStateForThisFrame();
681 allFramesSynced &= synced;
683 return allFramesSynced;
684 #else // USE(ACCELERATED_COMPOSITING)
689 bool FrameView::isSoftwareRenderable() const
691 #if USE(ACCELERATED_COMPOSITING)
692 RenderView* view = m_frame->contentRenderer();
696 return !view->compositor()->has3DContent();
702 void FrameView::didMoveOnscreen()
704 RenderView* view = m_frame->contentRenderer();
706 view->didMoveOnscreen();
707 scrollAnimator()->contentAreaDidShow();
710 void FrameView::willMoveOffscreen()
712 RenderView* view = m_frame->contentRenderer();
714 view->willMoveOffscreen();
715 scrollAnimator()->contentAreaDidHide();
718 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
720 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
723 void FrameView::layout(bool allowSubtree)
728 m_layoutTimer.stop();
729 m_delayedLayout = false;
730 m_setNeedsLayoutWasDeferred = false;
732 // Protect the view from being deleted during layout (in recalcStyle)
733 RefPtr<FrameView> protector(this);
736 // FIXME: Do we need to set m_size.width here?
737 // FIXME: Should we set m_size.height here too?
738 m_size.setWidth(layoutWidth());
742 // we shouldn't enter layout() while painting
743 ASSERT(!isPainting());
747 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
749 if (!allowSubtree && m_layoutRoot) {
750 m_layoutRoot->markContainingBlocksForLayout(false);
754 ASSERT(m_frame->view() == this);
756 Document* document = m_frame->document();
758 m_layoutSchedulingEnabled = false;
760 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_hasPendingPostLayoutTasks) {
761 // This is a new top-level layout. If there are any remaining tasks from the previous
762 // layout, finish them now.
763 m_inSynchronousPostLayout = true;
764 m_postLayoutTasksTimer.stop();
765 performPostLayoutTasks();
766 m_inSynchronousPostLayout = false;
769 // Viewport-dependent media queries may cause us to need completely different style information.
771 if (document->styleSelector()->affectedByViewportChange())
772 document->styleSelectorChanged(RecalcStyleImmediately);
774 // Always ensure our style info is up-to-date. This can happen in situations where
775 // the layout beats any sort of style recalc update that needs to occur.
776 document->updateStyleIfNeeded();
778 bool subtree = m_layoutRoot;
780 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
781 // so there's no point to continuing to layout
782 if (protector->hasOneRef())
785 RenderObject* root = subtree ? m_layoutRoot : document->renderer();
787 // FIXME: Do we need to set m_size here?
788 m_layoutSchedulingEnabled = true;
792 m_nestedLayoutCount++;
795 Document* document = m_frame->document();
796 Node* documentElement = document->documentElement();
797 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
798 Node* body = document->body();
799 if (body && body->renderer()) {
800 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
801 body->renderer()->setChildNeedsLayout(true);
802 } else if (body->hasTagName(bodyTag)) {
803 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
804 body->renderer()->setChildNeedsLayout(true);
806 } else if (rootRenderer) {
808 if (documentElement->isSVGElement()) {
809 if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight()))
810 rootRenderer->setChildNeedsLayout(true);
815 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
816 if (m_firstLayout && !document->ownerElement())
817 printf("Elapsed time before first layout: %d\n", document->elapsedTime());
823 calculateScrollbarModesForLayout(hMode, vMode);
825 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
828 // Now set our scrollbar state for the layout.
829 ScrollbarMode currentHMode = horizontalScrollbarMode();
830 ScrollbarMode currentVMode = verticalScrollbarMode();
832 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
834 setScrollbarsSuppressed(true);
836 m_firstLayout = false;
837 m_firstLayoutCallbackPending = true;
838 m_lastLayoutSize = IntSize(width(), height());
839 m_lastZoomFactor = root->style()->zoom();
841 // Set the initial vMode to AlwaysOn if we're auto.
842 if (vMode == ScrollbarAuto)
843 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
844 // Set the initial hMode to AlwaysOff if we're auto.
845 if (hMode == ScrollbarAuto)
846 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
848 setScrollbarModes(hMode, vMode);
849 setScrollbarsSuppressed(false, true);
851 setScrollbarModes(hMode, vMode);
854 IntSize oldSize = m_size;
856 m_size = IntSize(layoutWidth(), layoutHeight());
858 if (oldSize != m_size) {
859 m_doFullRepaint = true;
860 if (!m_firstLayout) {
861 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
862 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
863 if (bodyRenderer && bodyRenderer->stretchesToViewport())
864 bodyRenderer->setChildNeedsLayout(true);
865 else if (rootRenderer && rootRenderer->stretchesToViewport())
866 rootRenderer->setChildNeedsLayout(true);
871 RenderLayer* layer = root->enclosingLayer();
873 pauseScheduledEvents();
875 bool disableLayoutState = false;
877 RenderView* view = root->view();
878 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
879 view->pushLayoutState(root);
880 if (disableLayoutState)
881 view->disableLayoutState();
885 beginDeferredRepaints();
887 endDeferredRepaints();
891 RenderView* view = root->view();
892 view->popLayoutState(root);
893 if (disableLayoutState)
894 view->enableLayoutState();
898 m_frame->selection()->setCaretRectNeedsUpdate();
899 m_frame->selection()->updateAppearance();
901 m_layoutSchedulingEnabled = true;
903 if (!subtree && !toRenderView(root)->printing())
906 // Now update the positions of all layers.
907 beginDeferredRepaints();
908 IntPoint cachedOffset;
909 layer->updateLayerPositions((m_doFullRepaint ? RenderLayer::DoFullRepaint : 0)
910 | RenderLayer::CheckForRepaint
911 | RenderLayer::IsCompositingUpdateRoot
912 | RenderLayer::UpdateCompositingLayers,
913 subtree ? 0 : &cachedOffset);
914 endDeferredRepaints();
916 #if USE(ACCELERATED_COMPOSITING)
917 updateCompositingLayers();
922 #if PLATFORM(MAC) || PLATFORM(CHROMIUM)
923 if (AXObjectCache::accessibilityEnabled())
924 root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true);
926 #if ENABLE(DASHBOARD_SUPPORT)
927 updateDashboardRegions();
930 ASSERT(!root->needsLayout());
932 updateCanBlitOnScrollRecursively();
934 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
935 updateOverflowStatus(layoutWidth() < contentsWidth(),
936 layoutHeight() < contentsHeight());
938 if (!m_hasPendingPostLayoutTasks) {
939 if (!m_inSynchronousPostLayout) {
940 m_inSynchronousPostLayout = true;
941 // Calls resumeScheduledEvents()
942 performPostLayoutTasks();
943 m_inSynchronousPostLayout = false;
946 if (!m_hasPendingPostLayoutTasks && (needsLayout() || m_inSynchronousPostLayout)) {
947 // If we need layout or are already in a synchronous call to postLayoutTasks(),
948 // defer widget updates and event dispatch until after we return. postLayoutTasks()
949 // can make us need to update again, and we can get stuck in a nasty cycle unless
950 // we call it through the timer here.
951 m_hasPendingPostLayoutTasks = true;
952 m_postLayoutTasksTimer.startOneShot(0);
954 pauseScheduledEvents();
959 resumeScheduledEvents();
960 ASSERT(m_enqueueEvents);
963 InspectorInstrumentation::didLayout(cookie);
965 m_nestedLayoutCount--;
968 void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object)
970 if (!m_widgetUpdateSet)
971 m_widgetUpdateSet.set(new RenderEmbeddedObjectSet);
973 m_widgetUpdateSet->add(object);
976 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object)
978 if (!m_widgetUpdateSet)
981 m_widgetUpdateSet->remove(object);
984 void FrameView::setMediaType(const String& mediaType)
986 m_mediaType = mediaType;
989 String FrameView::mediaType() const
991 // See if we have an override type.
992 String overrideType = m_frame->loader()->client()->overrideMediaType();
993 if (!overrideType.isNull())
998 void FrameView::adjustMediaTypeForPrinting(bool printing)
1001 if (m_mediaTypeWhenNotPrinting.isNull())
1002 m_mediaTypeWhenNotPrinting = mediaType();
1003 setMediaType("print");
1005 if (!m_mediaTypeWhenNotPrinting.isNull())
1006 setMediaType(m_mediaTypeWhenNotPrinting);
1007 m_mediaTypeWhenNotPrinting = String();
1011 bool FrameView::useSlowRepaints() const
1013 if (m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || m_isOverlapped || !m_contentIsOpaque)
1016 if (Frame* parentFrame = m_frame->tree()->parent()) {
1017 if (FrameView* parentView = parentFrame->view())
1018 return parentView->useSlowRepaints();
1024 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1026 if (m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || !m_contentIsOpaque)
1029 if (Frame* parentFrame = m_frame->tree()->parent()) {
1030 if (FrameView* parentView = parentFrame->view())
1031 return parentView->useSlowRepaintsIfNotOverlapped();
1037 void FrameView::updateCanBlitOnScrollRecursively()
1039 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1040 if (FrameView* view = frame->view())
1041 view->setCanBlitOnScroll(!view->useSlowRepaints());
1045 void FrameView::setUseSlowRepaints()
1047 m_useSlowRepaints = true;
1048 updateCanBlitOnScrollRecursively();
1051 void FrameView::addSlowRepaintObject()
1053 if (!m_slowRepaintObjectCount)
1054 updateCanBlitOnScrollRecursively();
1055 m_slowRepaintObjectCount++;
1058 void FrameView::removeSlowRepaintObject()
1060 ASSERT(m_slowRepaintObjectCount > 0);
1061 m_slowRepaintObjectCount--;
1062 if (!m_slowRepaintObjectCount)
1063 updateCanBlitOnScrollRecursively();
1066 void FrameView::addFixedObject()
1068 if (!m_fixedObjectCount && platformWidget())
1069 updateCanBlitOnScrollRecursively();
1070 ++m_fixedObjectCount;
1073 void FrameView::removeFixedObject()
1075 ASSERT(m_fixedObjectCount > 0);
1076 --m_fixedObjectCount;
1077 if (!m_fixedObjectCount)
1078 updateCanBlitOnScrollRecursively();
1081 IntPoint FrameView::currentMousePosition() const
1083 return m_frame ? m_frame->eventHandler()->currentMousePosition() : IntPoint();
1086 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1088 const size_t fixedObjectThreshold = 5;
1090 RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0;
1091 if (RenderView* root = m_frame->contentRenderer())
1092 positionedObjects = root->positionedObjects();
1094 if (!positionedObjects || positionedObjects->isEmpty()) {
1095 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1099 // Get the rects of the fixed objects visible in the rectToScroll
1100 Vector<IntRect, fixedObjectThreshold> subRectToUpdate;
1101 bool updateInvalidatedSubRect = true;
1102 RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
1103 for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
1104 RenderBox* renderBox = *it;
1105 if (renderBox->style()->position() != FixedPosition)
1107 IntRect updateRect = renderBox->layer()->repaintRectIncludingDescendants();
1108 updateRect = contentsToWindow(updateRect);
1109 if (clipsRepaints())
1110 updateRect.intersect(rectToScroll);
1111 if (!updateRect.isEmpty()) {
1112 if (subRectToUpdate.size() >= fixedObjectThreshold) {
1113 updateInvalidatedSubRect = false;
1116 subRectToUpdate.append(updateRect);
1121 if (updateInvalidatedSubRect) {
1123 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1125 // 2) update the area of fixed objects that has been invalidated
1126 size_t fixObjectsCount = subRectToUpdate.size();
1127 for (size_t i = 0; i < fixObjectsCount; ++i) {
1128 IntRect updateRect = subRectToUpdate[i];
1129 IntRect scrolledRect = updateRect;
1130 scrolledRect.move(scrollDelta);
1131 updateRect.unite(scrolledRect);
1132 if (clipsRepaints())
1133 updateRect.intersect(rectToScroll);
1134 hostWindow()->invalidateContentsAndWindow(updateRect, false);
1139 // the number of fixed objects exceed the threshold, we cannot use the fast path
1143 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1145 #if USE(ACCELERATED_COMPOSITING)
1146 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1147 if (frameRenderer->containerForRepaint()) {
1148 IntRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1149 frameRenderer->borderTop() + frameRenderer->paddingTop(),
1150 visibleWidth(), visibleHeight());
1151 frameRenderer->repaintRectangle(rect);
1157 ScrollView::scrollContentsSlowPath(updateRect);
1160 // Note that this gets called at painting time.
1161 void FrameView::setIsOverlapped(bool isOverlapped)
1163 if (isOverlapped == m_isOverlapped)
1166 m_isOverlapped = isOverlapped;
1167 updateCanBlitOnScrollRecursively();
1169 #if USE(ACCELERATED_COMPOSITING)
1170 if (hasCompositedContentIncludingDescendants()) {
1171 // Overlap can affect compositing tests, so if it changes, we need to trigger
1172 // a layer update in the parent document.
1173 if (Frame* parentFrame = m_frame->tree()->parent()) {
1174 if (RenderView* parentView = parentFrame->contentRenderer()) {
1175 RenderLayerCompositor* compositor = parentView->compositor();
1176 compositor->setCompositingLayersNeedRebuild();
1177 compositor->scheduleCompositingLayerUpdate();
1181 if (RenderLayerCompositor::allowsIndependentlyCompositedIFrames(this)) {
1182 // We also need to trigger reevaluation for this and all descendant frames,
1183 // since a frame uses compositing if any ancestor is compositing.
1184 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1185 if (RenderView* view = frame->contentRenderer()) {
1186 RenderLayerCompositor* compositor = view->compositor();
1187 compositor->setCompositingLayersNeedRebuild();
1188 compositor->scheduleCompositingLayerUpdate();
1196 bool FrameView::isOverlappedIncludingAncestors() const
1201 if (Frame* parentFrame = m_frame->tree()->parent()) {
1202 if (FrameView* parentView = parentFrame->view()) {
1203 if (parentView->isOverlapped())
1211 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1213 if (contentIsOpaque == m_contentIsOpaque)
1216 m_contentIsOpaque = contentIsOpaque;
1217 updateCanBlitOnScrollRecursively();
1220 void FrameView::restoreScrollbar()
1222 setScrollbarsSuppressed(false);
1225 bool FrameView::scrollToFragment(const KURL& url)
1227 // If our URL has no ref, then we have no place we need to jump to.
1228 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1229 // and possibly repaint because :target pseudo class may have been
1230 // set (see bug 11321).
1231 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1234 String fragmentIdentifier = url.fragmentIdentifier();
1235 if (scrollToAnchor(fragmentIdentifier))
1238 // Try again after decoding the ref, based on the document's encoding.
1239 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1240 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1245 bool FrameView::scrollToAnchor(const String& name)
1247 ASSERT(m_frame->document());
1249 if (!m_frame->document()->haveStylesheetsLoaded()) {
1250 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1254 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1256 Element* anchorNode = m_frame->document()->findAnchor(name);
1259 if (m_frame->document()->isSVGDocument()) {
1260 if (name.startsWith("xpointer(")) {
1261 // We need to parse the xpointer reference here
1262 } else if (name.startsWith("svgView(")) {
1263 RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement();
1264 if (!svg->currentView()->parseViewSpec(name))
1266 svg->setUseCurrentView(true);
1268 if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) {
1269 RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0;
1270 if (viewElement.get()) {
1271 SVGElement* element = SVGLocatable::nearestViewportElement(viewElement.get());
1272 if (element->hasTagName(SVGNames::svgTag)) {
1273 RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(element);
1274 svg->inheritViewAttributes(viewElement.get());
1279 // FIXME: need to decide which <svg> to focus on, and zoom to that one
1280 // FIXME: need to actually "highlight" the viewTarget(s)
1284 m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target.
1286 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1287 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1290 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1294 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1296 m_maintainScrollPositionAnchor = anchorNode;
1297 if (!m_maintainScrollPositionAnchor)
1300 // We need to update the layout before scrolling, otherwise we could
1301 // really mess things up if an anchor scroll comes at a bad moment.
1302 m_frame->document()->updateStyleIfNeeded();
1303 // Only do a layout if changes have occurred that make it necessary.
1304 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
1310 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1312 bool wasInProgrammaticScroll = m_inProgrammaticScroll;
1313 m_inProgrammaticScroll = true;
1314 m_maintainScrollPositionAnchor = 0;
1315 ScrollView::setScrollPosition(scrollPoint);
1316 m_inProgrammaticScroll = wasInProgrammaticScroll;
1319 void FrameView::scrollPositionChangedViaPlatformWidget()
1321 repaintFixedElementsAfterScrolling();
1322 scrollPositionChanged();
1325 void FrameView::scrollPositionChanged()
1327 frame()->eventHandler()->sendScrollEvent();
1329 #if USE(ACCELERATED_COMPOSITING)
1330 if (RenderView* root = m_frame->contentRenderer()) {
1331 if (root->usesCompositing())
1332 root->compositor()->frameViewDidScroll(scrollPosition());
1337 void FrameView::repaintFixedElementsAfterScrolling()
1339 // For fixed position elements, update widget positions and compositing layers after scrolling,
1340 // but only if we're not inside of layout.
1341 if (!m_nestedLayoutCount && hasFixedObjects()) {
1342 if (RenderView* root = m_frame->contentRenderer()) {
1343 root->updateWidgetPositions();
1344 root->layer()->updateRepaintRectsAfterScroll();
1345 #if USE(ACCELERATED_COMPOSITING)
1346 root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
1352 HostWindow* FrameView::hostWindow() const
1354 Page* page = frame() ? frame()->page() : 0;
1357 return page->chrome();
1360 const unsigned cRepaintRectUnionThreshold = 25;
1362 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
1364 ASSERT(!m_frame->document()->ownerElement());
1366 double delay = adjustedDeferredRepaintDelay();
1367 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
1368 IntRect paintRect = r;
1369 if (clipsRepaints() && !paintsEntireContents())
1370 paintRect.intersect(visibleContentRect());
1371 if (paintRect.isEmpty())
1373 if (m_repaintCount == cRepaintRectUnionThreshold) {
1374 IntRect unionedRect;
1375 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
1376 unionedRect.unite(m_repaintRects[i]);
1377 m_repaintRects.clear();
1378 m_repaintRects.append(unionedRect);
1380 if (m_repaintCount < cRepaintRectUnionThreshold)
1381 m_repaintRects.append(paintRect);
1383 m_repaintRects[0].unite(paintRect);
1386 if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive())
1387 m_deferredRepaintTimer.startOneShot(delay);
1391 if (!shouldUpdate(immediate))
1394 #if ENABLE(TILED_BACKING_STORE)
1395 if (frame()->tiledBackingStore()) {
1396 frame()->tiledBackingStore()->invalidate(r);
1400 ScrollView::repaintContentRectangle(r, immediate);
1403 void FrameView::contentsResized()
1405 scrollAnimator()->contentsResized();
1409 void FrameView::visibleContentsResized()
1411 // We check to make sure the view is attached to a frame() as this method can
1412 // be triggered before the view is attached by Frame::createView(...) setting
1413 // various values such as setScrollBarModes(...) for example. An ASSERT is
1414 // triggered when a view is layout before being attached to a frame().
1415 if (!frame()->view())
1422 void FrameView::beginDeferredRepaints()
1424 Page* page = m_frame->page();
1425 if (page->mainFrame() != m_frame)
1426 return page->mainFrame()->view()->beginDeferredRepaints();
1428 m_deferringRepaints++;
1432 void FrameView::endDeferredRepaints()
1434 Page* page = m_frame->page();
1435 if (page->mainFrame() != m_frame)
1436 return page->mainFrame()->view()->endDeferredRepaints();
1438 ASSERT(m_deferringRepaints > 0);
1440 if (--m_deferringRepaints)
1443 if (m_deferredRepaintTimer.isActive())
1446 if (double delay = adjustedDeferredRepaintDelay()) {
1447 m_deferredRepaintTimer.startOneShot(delay);
1451 doDeferredRepaints();
1454 void FrameView::checkStopDelayingDeferredRepaints()
1456 if (!m_deferredRepaintTimer.isActive())
1459 Document* document = m_frame->document();
1460 if (document && (document->parsing() || document->cachedResourceLoader()->requestCount()))
1463 m_deferredRepaintTimer.stop();
1465 doDeferredRepaints();
1468 void FrameView::doDeferredRepaints()
1470 ASSERT(!m_deferringRepaints);
1471 if (!shouldUpdate()) {
1472 m_repaintRects.clear();
1476 unsigned size = m_repaintRects.size();
1477 for (unsigned i = 0; i < size; i++) {
1478 #if ENABLE(TILED_BACKING_STORE)
1479 if (frame()->tiledBackingStore()) {
1480 frame()->tiledBackingStore()->invalidate(m_repaintRects[i]);
1484 ScrollView::repaintContentRectangle(m_repaintRects[i], false);
1486 m_repaintRects.clear();
1489 updateDeferredRepaintDelay();
1492 void FrameView::updateDeferredRepaintDelay()
1494 Document* document = m_frame->document();
1495 if (!document || (!document->parsing() && !document->cachedResourceLoader()->requestCount())) {
1496 m_deferredRepaintDelay = s_deferredRepaintDelay;
1499 if (m_deferredRepaintDelay < s_maxDeferredRepaintDelayDuringLoading) {
1500 m_deferredRepaintDelay += s_deferredRepaintDelayIncrementDuringLoading;
1501 if (m_deferredRepaintDelay > s_maxDeferredRepaintDelayDuringLoading)
1502 m_deferredRepaintDelay = s_maxDeferredRepaintDelayDuringLoading;
1506 void FrameView::resetDeferredRepaintDelay()
1508 m_deferredRepaintDelay = 0;
1509 if (m_deferredRepaintTimer.isActive()) {
1510 m_deferredRepaintTimer.stop();
1511 if (!m_deferringRepaints)
1512 doDeferredRepaints();
1516 double FrameView::adjustedDeferredRepaintDelay() const
1518 if (!m_deferredRepaintDelay)
1520 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
1521 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
1524 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
1526 doDeferredRepaints();
1529 void FrameView::layoutTimerFired(Timer<FrameView>*)
1531 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1532 if (!m_frame->document()->ownerElement())
1533 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
1538 void FrameView::scheduleRelayout()
1540 // FIXME: We should assert the page is not in the page cache, but that is causing
1541 // too many false assertions. See <rdar://problem/7218118>.
1542 ASSERT(m_frame->view() == this);
1545 m_layoutRoot->markContainingBlocksForLayout(false);
1548 if (!m_layoutSchedulingEnabled)
1552 if (!m_frame->document()->shouldScheduleLayout())
1555 // When frame flattening is enabled, the contents of the frame affects layout of the parent frames.
1556 // Also invalidate parent frame starting from the owner element of this frame.
1557 if (m_frame->settings() && m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) {
1558 if (m_frame->ownerElement()->hasTagName(iframeTag) || m_frame->ownerElement()->hasTagName(frameTag))
1559 m_frame->ownerRenderer()->setNeedsLayout(true, true);
1562 int delay = m_frame->document()->minimumLayoutDelay();
1563 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
1564 unscheduleRelayout();
1565 if (m_layoutTimer.isActive())
1568 m_delayedLayout = delay != 0;
1570 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1571 if (!m_frame->document()->ownerElement())
1572 printf("Scheduling layout for %d\n", delay);
1575 m_layoutTimer.startOneShot(delay * 0.001);
1578 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
1580 for (RenderObject* r = descendant; r; r = r->container()) {
1587 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
1589 ASSERT(m_frame->view() == this);
1591 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) {
1593 relayoutRoot->markContainingBlocksForLayout(false);
1597 if (layoutPending() || !m_layoutSchedulingEnabled) {
1598 if (m_layoutRoot != relayoutRoot) {
1599 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
1600 // Keep the current root
1601 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
1602 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
1603 // Re-root at relayoutRoot
1604 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
1605 m_layoutRoot = relayoutRoot;
1607 // Just do a full relayout
1609 m_layoutRoot->markContainingBlocksForLayout(false);
1611 relayoutRoot->markContainingBlocksForLayout(false);
1614 } else if (m_layoutSchedulingEnabled) {
1615 int delay = m_frame->document()->minimumLayoutDelay();
1616 m_layoutRoot = relayoutRoot;
1617 m_delayedLayout = delay != 0;
1618 m_layoutTimer.startOneShot(delay * 0.001);
1622 bool FrameView::layoutPending() const
1624 return m_layoutTimer.isActive();
1627 bool FrameView::needsLayout() const
1629 // This can return true in cases where the document does not have a body yet.
1630 // Document::shouldScheduleLayout takes care of preventing us from scheduling
1631 // layout in that case.
1634 RenderView* root = m_frame->contentRenderer();
1635 return layoutPending()
1636 || (root && root->needsLayout())
1638 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
1641 void FrameView::setNeedsLayout()
1643 if (m_deferSetNeedsLayouts) {
1644 m_setNeedsLayoutWasDeferred = true;
1647 RenderView* root = m_frame->contentRenderer();
1649 root->setNeedsLayout(true);
1652 void FrameView::unscheduleRelayout()
1654 m_postLayoutTasksTimer.stop();
1656 if (!m_layoutTimer.isActive())
1659 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1660 if (!m_frame->document()->ownerElement())
1661 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
1664 m_layoutTimer.stop();
1665 m_delayedLayout = false;
1668 #if ENABLE(REQUEST_ANIMATION_FRAME)
1669 void FrameView::serviceScriptedAnimations(DOMTimeStamp time)
1671 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext())
1672 frame->document()->serviceScriptedAnimations(time);
1676 bool FrameView::isTransparent() const
1678 return m_isTransparent;
1681 void FrameView::setTransparent(bool isTransparent)
1683 m_isTransparent = isTransparent;
1686 Color FrameView::baseBackgroundColor() const
1688 return m_baseBackgroundColor;
1691 void FrameView::setBaseBackgroundColor(Color bc)
1695 m_baseBackgroundColor = bc;
1698 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
1700 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1701 if (FrameView* view = frame->view()) {
1702 view->setTransparent(transparent);
1703 view->setBaseBackgroundColor(backgroundColor);
1708 bool FrameView::shouldUpdateWhileOffscreen() const
1710 return m_shouldUpdateWhileOffscreen;
1713 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
1715 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
1718 bool FrameView::shouldUpdate(bool immediateRequested) const
1720 if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen())
1722 if (!m_frame || !m_frame->document() || m_frame->document()->mayCauseFlashOfUnstyledContent())
1727 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
1729 if (!m_enqueueEvents) {
1730 ExceptionCode ec = 0;
1731 eventTarget->dispatchEvent(event, ec);
1735 ScheduledEvent* scheduledEvent = new ScheduledEvent;
1736 scheduledEvent->m_event = event;
1737 scheduledEvent->m_eventTarget = eventTarget;
1738 m_scheduledEvents.append(scheduledEvent);
1741 void FrameView::pauseScheduledEvents()
1743 ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
1747 void FrameView::resumeScheduledEvents()
1750 if (!m_enqueueEvents)
1751 dispatchScheduledEvents();
1752 ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
1755 void FrameView::scrollToAnchor()
1757 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
1761 if (!anchorNode->renderer())
1765 if (anchorNode != m_frame->document())
1766 rect = anchorNode->getRect();
1768 // Scroll nested layers and frames to reveal the anchor.
1769 // Align to the top and to the closest side (this matches other browsers).
1770 anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
1772 if (AXObjectCache::accessibilityEnabled())
1773 m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get());
1775 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
1776 m_maintainScrollPositionAnchor = anchorNode;
1779 void FrameView::updateWidget(RenderEmbeddedObject* object)
1781 ASSERT(!object->node() || object->node()->isElementNode());
1782 Element* ownerElement = static_cast<Element*>(object->node());
1783 // The object may have already been destroyed (thus node cleared),
1784 // but FrameView holds a manual ref, so it won't have been deleted.
1785 ASSERT(m_widgetUpdateSet->contains(object));
1789 // No need to update if it's already crashed or known to be missing.
1790 if (object->pluginCrashedOrWasMissing())
1793 // FIXME: This could turn into a real virtual dispatch if we defined
1794 // updateWidget(bool) on HTMLElement.
1795 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag))
1796 static_cast<HTMLPlugInImageElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
1797 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
1798 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1799 else if (ownerElement->hasTagName(videoTag) || ownerElement->hasTagName(audioTag))
1800 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
1803 ASSERT_NOT_REACHED();
1805 // Caution: it's possible the object was destroyed again, since loading a
1806 // plugin may run any arbitrary javascript.
1807 object->updateWidgetPosition();
1810 bool FrameView::updateWidgets()
1812 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
1815 size_t size = m_widgetUpdateSet->size();
1817 Vector<RenderEmbeddedObject*> objects;
1818 objects.reserveCapacity(size);
1820 RenderEmbeddedObjectSet::const_iterator end = m_widgetUpdateSet->end();
1821 for (RenderEmbeddedObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
1822 objects.uncheckedAppend(*it);
1826 for (size_t i = 0; i < size; ++i) {
1827 RenderEmbeddedObject* object = objects[i];
1828 updateWidget(object);
1829 m_widgetUpdateSet->remove(object);
1832 RenderArena* arena = m_frame->document()->renderArena();
1833 for (size_t i = 0; i < size; ++i)
1834 objects[i]->deref(arena);
1836 return m_widgetUpdateSet->isEmpty();
1839 void FrameView::performPostLayoutTasks()
1841 m_hasPendingPostLayoutTasks = false;
1843 if (m_firstLayoutCallbackPending) {
1844 m_firstLayoutCallbackPending = false;
1845 m_frame->loader()->didFirstLayout();
1848 if (m_isVisuallyNonEmpty && m_firstVisuallyNonEmptyLayoutCallbackPending) {
1849 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
1850 m_frame->loader()->didFirstVisuallyNonEmptyLayout();
1853 RenderView* root = m_frame->contentRenderer();
1855 root->updateWidgetPositions();
1857 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
1858 if (updateWidgets())
1864 resumeScheduledEvents();
1866 if (!root->printing()) {
1867 IntSize currentSize = IntSize(width(), height());
1868 float currentZoomFactor = root->style()->zoom();
1869 bool resized = !m_firstLayout && (currentSize != m_lastLayoutSize || currentZoomFactor != m_lastZoomFactor);
1870 m_lastLayoutSize = currentSize;
1871 m_lastZoomFactor = currentZoomFactor;
1873 m_frame->eventHandler()->sendResizeEvent();
1877 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
1879 performPostLayoutTasks();
1882 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
1884 if (!m_viewportRenderer)
1887 if (m_overflowStatusDirty) {
1888 m_horizontalOverflow = horizontalOverflow;
1889 m_verticalOverflow = verticalOverflow;
1890 m_overflowStatusDirty = false;
1894 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
1895 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
1897 if (horizontalOverflowChanged || verticalOverflowChanged) {
1898 m_horizontalOverflow = horizontalOverflow;
1899 m_verticalOverflow = verticalOverflow;
1901 scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
1902 verticalOverflowChanged, verticalOverflow),
1903 m_viewportRenderer->node());
1908 void FrameView::dispatchScheduledEvents()
1910 if (m_scheduledEvents.isEmpty())
1913 Vector<ScheduledEvent*> scheduledEventsCopy = m_scheduledEvents;
1914 m_scheduledEvents.clear();
1916 Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end();
1917 for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) {
1918 ScheduledEvent* scheduledEvent = *it;
1920 ExceptionCode ec = 0;
1922 // Only dispatch events to nodes that are in the document
1923 if (scheduledEvent->m_eventTarget->inDocument())
1924 scheduledEvent->m_eventTarget->dispatchEvent(scheduledEvent->m_event, ec);
1926 delete scheduledEvent;
1930 IntRect FrameView::windowClipRect(bool clipToContents) const
1932 ASSERT(m_frame->view() == this);
1934 if (paintsEntireContents())
1935 return IntRect(IntPoint(0, 0), contentsSize());
1937 // Set our clip rect to be our contents.
1938 IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
1939 if (!m_frame || !m_frame->document() || !m_frame->document()->ownerElement())
1942 // Take our owner element and get the clip rect from the enclosing layer.
1943 Element* elt = m_frame->document()->ownerElement();
1944 RenderLayer* layer = elt->renderer()->enclosingLayer();
1945 // FIXME: layer should never be null, but sometimes seems to be anyway.
1948 FrameView* parentView = elt->document()->view();
1949 clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
1953 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const
1955 // If we have no layer, just return our window clip rect.
1957 return windowClipRect();
1959 // Apply the clip from the layer.
1961 if (clipToLayerContents)
1962 clipRect = layer->childrenClipRect();
1964 clipRect = layer->selfClipRect();
1965 clipRect = contentsToWindow(clipRect);
1966 return intersection(clipRect, windowClipRect());
1969 bool FrameView::isActive() const
1971 Page* page = frame()->page();
1972 return page && page->focusController()->isActive();
1975 void FrameView::scrollTo(const IntSize& newOffset)
1977 IntSize offset = scrollOffset();
1978 ScrollView::scrollTo(newOffset);
1979 if (offset != scrollOffset())
1980 scrollPositionChanged();
1981 frame()->loader()->client()->didChangeScrollOffset();
1984 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
1986 // Add in our offset within the FrameView.
1987 IntRect dirtyRect = rect;
1988 dirtyRect.move(scrollbar->x(), scrollbar->y());
1989 invalidateRect(dirtyRect);
1992 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
1994 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
1997 IntRect FrameView::windowResizerRect() const
1999 Page* page = frame() ? frame()->page() : 0;
2002 return page->chrome()->windowResizerRect();
2005 #if ENABLE(DASHBOARD_SUPPORT)
2006 void FrameView::updateDashboardRegions()
2008 Document* document = m_frame->document();
2009 if (!document->hasDashboardRegions())
2011 Vector<DashboardRegionValue> newRegions;
2012 document->renderBox()->collectDashboardRegions(newRegions);
2013 if (newRegions == document->dashboardRegions())
2015 document->setDashboardRegions(newRegions);
2016 Page* page = m_frame->page();
2019 page->chrome()->client()->dashboardRegionsChanged();
2023 void FrameView::invalidateScrollCorner()
2025 invalidateRect(scrollCornerRect());
2028 void FrameView::updateScrollCorner()
2030 RenderObject* renderer = 0;
2031 RefPtr<RenderStyle> cornerStyle;
2033 if (!scrollCornerRect().isEmpty()) {
2034 // Try the <body> element first as a scroll corner source.
2035 Document* doc = m_frame->document();
2036 Element* body = doc ? doc->body() : 0;
2037 if (body && body->renderer()) {
2038 renderer = body->renderer();
2039 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2043 // If the <body> didn't have a custom style, then the root element might.
2044 Element* docElement = doc ? doc->documentElement() : 0;
2045 if (docElement && docElement->renderer()) {
2046 renderer = docElement->renderer();
2047 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2052 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
2053 if (RenderPart* renderer = m_frame->ownerRenderer())
2054 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2059 if (!m_scrollCorner)
2060 m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document());
2061 m_scrollCorner->setStyle(cornerStyle.release());
2062 invalidateRect(scrollCornerRect());
2063 } else if (m_scrollCorner) {
2064 m_scrollCorner->destroy();
2069 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
2071 if (context->updatingControlTints()) {
2072 updateScrollCorner();
2076 if (m_scrollCorner) {
2077 m_scrollCorner->paintIntoRect(context, cornerRect.x(), cornerRect.y(), cornerRect);
2081 ScrollView::paintScrollCorner(context, cornerRect);
2084 bool FrameView::hasCustomScrollbars() const
2086 const HashSet<RefPtr<Widget> >* viewChildren = children();
2087 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2088 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2089 Widget* widget = current->get();
2090 if (widget->isFrameView()) {
2091 if (static_cast<FrameView*>(widget)->hasCustomScrollbars())
2093 } else if (widget->isScrollbar()) {
2094 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
2095 if (scrollbar->isCustomScrollbar())
2103 void FrameView::updateControlTints()
2105 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
2106 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
2107 // This is only done if the theme supports control tinting. It's up to the theme and platform
2108 // to define when controls get the tint and to call this function when that changes.
2110 // Optimize the common case where we bring a window to the front while it's still empty.
2111 if (!m_frame || m_frame->document()->url().isEmpty())
2114 if ((m_frame->contentRenderer() && m_frame->contentRenderer()->theme()->supportsControlTints()) || hasCustomScrollbars()) {
2117 PlatformGraphicsContext* const noContext = 0;
2118 GraphicsContext context(noContext);
2119 context.setUpdatingControlTints(true);
2120 if (platformWidget())
2121 paintContents(&context, visibleContentRect());
2123 paint(&context, frameRect());
2127 bool FrameView::wasScrolledByUser() const
2129 return m_wasScrolledByUser;
2132 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
2134 if (m_inProgrammaticScroll)
2136 m_maintainScrollPositionAnchor = 0;
2137 m_wasScrolledByUser = wasScrolledByUser;
2140 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
2145 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get(), rect);
2147 Document* document = frame()->document();
2151 if (document->printing())
2152 fillWithRed = false; // Printing, don't fill with red (can't remember why).
2153 else if (document->ownerElement())
2154 fillWithRed = false; // Subframe, don't fill with red.
2155 else if (isTransparent())
2156 fillWithRed = false; // Transparent, don't fill with red.
2157 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
2158 fillWithRed = false; // Selections are transparent, don't fill with red.
2159 else if (m_nodeToDraw)
2160 fillWithRed = false; // Element images are transparent, don't fill with red.
2165 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
2168 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
2169 if (isTopLevelPainter)
2170 sCurrentPaintTimeStamp = currentTime();
2172 RenderView* contentRenderer = frame()->contentRenderer();
2173 if (!contentRenderer) {
2174 LOG_ERROR("called FrameView::paint with nil renderer");
2178 ASSERT(!needsLayout());
2182 #if USE(ACCELERATED_COMPOSITING)
2183 if (!p->paintingDisabled())
2184 syncCompositingStateForThisFrame();
2187 PaintBehavior oldPaintBehavior = m_paintBehavior;
2188 if (m_paintBehavior == PaintBehaviorNormal)
2189 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
2191 if (document->printing())
2192 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2194 bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers;
2195 bool isRootFrame = !document->ownerElement();
2196 if (flatteningPaint && isRootFrame)
2197 notifyWidgetsInAllFrames(WillPaintFlattened);
2199 ASSERT(!m_isPainting);
2200 m_isPainting = true;
2202 // m_nodeToDraw is used to draw only one element (and its descendants)
2203 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
2205 contentRenderer->layer()->paint(p, rect, m_paintBehavior, eltRenderer);
2207 m_isPainting = false;
2209 if (flatteningPaint && isRootFrame)
2210 notifyWidgetsInAllFrames(DidPaintFlattened);
2212 m_paintBehavior = oldPaintBehavior;
2213 m_lastPaintTime = currentTime();
2215 #if ENABLE(DASHBOARD_SUPPORT)
2216 // Regions may have changed as a result of the visibility/z-index of element changing.
2217 if (document->dashboardRegionsDirty())
2218 updateDashboardRegions();
2221 if (isTopLevelPainter)
2222 sCurrentPaintTimeStamp = 0;
2224 InspectorInstrumentation::didPaint(cookie);
2227 void FrameView::setPaintBehavior(PaintBehavior behavior)
2229 m_paintBehavior = behavior;
2232 PaintBehavior FrameView::paintBehavior() const
2234 return m_paintBehavior;
2237 bool FrameView::isPainting() const
2239 return m_isPainting;
2242 void FrameView::setNodeToDraw(Node* node)
2244 m_nodeToDraw = node;
2247 void FrameView::updateLayoutAndStyleIfNeededRecursive()
2249 // We have to crawl our entire tree looking for any FrameViews that need
2250 // layout and make sure they are up to date.
2251 // Mac actually tests for intersection with the dirty region and tries not to
2252 // update layout for frames that are outside the dirty region. Not only does this seem
2253 // pointless (since those frames will have set a zero timer to layout anyway), but
2254 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
2255 // region but then become included later by the second frame adding rects to the dirty region
2256 // when it lays out.
2258 m_frame->document()->updateStyleIfNeeded();
2263 const HashSet<RefPtr<Widget> >* viewChildren = children();
2264 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2265 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2266 Widget* widget = (*current).get();
2267 if (widget->isFrameView())
2268 static_cast<FrameView*>(widget)->updateLayoutAndStyleIfNeededRecursive();
2271 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
2272 // painting, so we need to flush out any deferred repaints too.
2273 flushDeferredRepaints();
2276 void FrameView::flushDeferredRepaints()
2278 if (!m_deferredRepaintTimer.isActive())
2280 m_deferredRepaintTimer.stop();
2281 doDeferredRepaints();
2284 void FrameView::forceLayout(bool allowSubtree)
2286 layout(allowSubtree);
2289 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximumShrinkFactor, Frame::AdjustViewSizeOrNot shouldAdjustViewSize)
2291 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
2292 // the state of things before and after the layout
2293 RenderView *root = toRenderView(m_frame->document()->renderer());
2295 float pageLogicalWidth = root->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
2296 float pageLogicalHeight = root->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
2298 int flooredPageLogicalWidth = static_cast<int>(pageLogicalWidth);
2299 root->setLogicalWidth(flooredPageLogicalWidth);
2300 root->setPageLogicalHeight(pageLogicalHeight);
2301 root->setNeedsLayoutAndPrefWidthsRecalc();
2304 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
2305 // page width when shrunk, we will lay out at maximum shrink and clip extra content.
2306 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
2307 // implementation should not do this!
2308 int docLogicalWidth = root->style()->isHorizontalWritingMode() ? root->docWidth() : root->docHeight();
2309 if (docLogicalWidth > pageLogicalWidth) {
2310 flooredPageLogicalWidth = std::min<int>(docLogicalWidth, pageLogicalWidth * maximumShrinkFactor);
2311 if (pageLogicalHeight)
2312 root->setPageLogicalHeight(flooredPageLogicalWidth / pageSize.width() * pageSize.height());
2313 root->setLogicalWidth(flooredPageLogicalWidth);
2314 root->setNeedsLayoutAndPrefWidthsRecalc();
2316 root->clearLayoutOverflow();
2317 int docLogicalHeight = root->style()->isHorizontalWritingMode() ? root->docHeight() : root->docWidth();
2318 int docLogicalTop = root->style()->isHorizontalWritingMode() ? root->docTop() : root->docLeft();
2319 int docLogicalRight = root->style()->isHorizontalWritingMode() ? root->docRight() : root->docBottom();
2320 int clippedLogicalLeft = 0;
2321 if (!root->style()->isLeftToRightDirection())
2322 clippedLogicalLeft = docLogicalRight - flooredPageLogicalWidth;
2323 IntRect overflow(clippedLogicalLeft, docLogicalTop, flooredPageLogicalWidth, docLogicalHeight);
2324 if (!root->style()->isHorizontalWritingMode())
2325 overflow = overflow.transposedRect();
2326 root->addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
2330 if (shouldAdjustViewSize)
2334 void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
2336 RenderView* root = m_frame->contentRenderer();
2338 // Use a context with painting disabled.
2339 GraphicsContext context((PlatformGraphicsContext*)0);
2340 root->setTruncatedAt((int)floorf(oldBottom));
2341 IntRect dirtyRect(0, (int)floorf(oldTop), root->rightLayoutOverflow(), (int)ceilf(oldBottom - oldTop));
2342 root->setPrintRect(dirtyRect);
2343 root->layer()->paint(&context, dirtyRect);
2344 *newBottom = root->bestTruncatedAt();
2345 if (*newBottom == 0)
2346 *newBottom = oldBottom;
2347 root->setPrintRect(IntRect());
2349 *newBottom = oldBottom;
2352 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
2354 IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
2356 // Convert from page ("absolute") to FrameView coordinates.
2357 rect.move(-scrollX(), -scrollY());
2362 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
2364 IntRect rect = viewRect;
2366 // Convert from FrameView coords into page ("absolute") coordinates.
2367 rect.move(scrollX(), scrollY());
2369 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
2370 // move the rect for now.
2371 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
2375 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
2377 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
2379 // Convert from page ("absolute") to FrameView coordinates.
2380 point.move(-scrollX(), -scrollY());
2384 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
2386 IntPoint point = viewPoint;
2388 // Convert from FrameView coords into page ("absolute") coordinates.
2389 point += IntSize(scrollX(), scrollY());
2391 return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
2394 IntRect FrameView::convertToContainingView(const IntRect& localRect) const
2396 if (const ScrollView* parentScrollView = parent()) {
2397 if (parentScrollView->isFrameView()) {
2398 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2399 // Get our renderer in the parent view
2400 RenderPart* renderer = m_frame->ownerRenderer();
2404 IntRect rect(localRect);
2405 // Add borders and padding??
2406 rect.move(renderer->borderLeft() + renderer->paddingLeft(),
2407 renderer->borderTop() + renderer->paddingTop());
2408 return parentView->convertFromRenderer(renderer, rect);
2411 return Widget::convertToContainingView(localRect);
2417 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
2419 if (const ScrollView* parentScrollView = parent()) {
2420 if (parentScrollView->isFrameView()) {
2421 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2423 // Get our renderer in the parent view
2424 RenderPart* renderer = m_frame->ownerRenderer();
2428 IntRect rect = parentView->convertToRenderer(renderer, parentRect);
2429 // Subtract borders and padding
2430 rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
2431 -renderer->borderTop() - renderer->paddingTop());
2435 return Widget::convertFromContainingView(parentRect);
2441 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
2443 if (const ScrollView* parentScrollView = parent()) {
2444 if (parentScrollView->isFrameView()) {
2445 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2447 // Get our renderer in the parent view
2448 RenderPart* renderer = m_frame->ownerRenderer();
2452 IntPoint point(localPoint);
2454 // Add borders and padding
2455 point.move(renderer->borderLeft() + renderer->paddingLeft(),
2456 renderer->borderTop() + renderer->paddingTop());
2457 return parentView->convertFromRenderer(renderer, point);
2460 return Widget::convertToContainingView(localPoint);
2466 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
2468 if (const ScrollView* parentScrollView = parent()) {
2469 if (parentScrollView->isFrameView()) {
2470 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2472 // Get our renderer in the parent view
2473 RenderPart* renderer = m_frame->ownerRenderer();
2477 IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
2478 // Subtract borders and padding
2479 point.move(-renderer->borderLeft() - renderer->paddingLeft(),
2480 -renderer->borderTop() - renderer->paddingTop());
2484 return Widget::convertFromContainingView(parentPoint);
2491 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
2493 s_deferredRepaintDelay = p;
2496 // Negative value would mean that first few repaints happen without a delay
2497 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)
2499 s_initialDeferredRepaintDelayDuringLoading = p;
2502 // The delay grows on each repaint to this maximum value
2503 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)
2505 s_maxDeferredRepaintDelayDuringLoading = p;
2508 // On each repaint the delay increases by this amount
2509 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)
2511 s_deferredRepaintDelayIncrementDuringLoading = p;
2514 bool FrameView::isVerticalDocument() const
2518 Document* doc = m_frame->document();
2521 RenderObject* renderView = doc->renderer();
2524 return renderView->style()->isHorizontalWritingMode();
2527 bool FrameView::isFlippedDocument() const
2531 Document* doc = m_frame->document();
2534 RenderObject* renderView = doc->renderer();
2537 return renderView->style()->isFlippedBlocksWritingMode();
2540 void FrameView::notifyWidgetsInAllFrames(WidgetNotification notification)
2542 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
2543 if (RenderView* root = frame->contentRenderer())
2544 root->notifyWidgets(notification);
2548 AXObjectCache* FrameView::axObjectCache() const
2550 if (frame() && frame()->document() && frame()->document()->axObjectCacheExists())
2551 return frame()->document()->axObjectCache();
2555 } // namespace WebCore