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 "EventHandler.h"
36 #include "FloatRect.h"
37 #include "FocusController.h"
39 #include "FrameLoader.h"
40 #include "FrameLoaderClient.h"
41 #include "FrameTree.h"
42 #include "GraphicsContext.h"
43 #include "HTMLDocument.h"
44 #include "HTMLFrameElement.h"
45 #include "HTMLFrameSetElement.h"
46 #include "HTMLNames.h"
47 #include "HTMLPlugInImageElement.h"
48 #include "InspectorInstrumentation.h"
49 #include "OverflowEvent.h"
50 #include "RenderEmbeddedObject.h"
51 #include "RenderLayer.h"
52 #include "RenderPart.h"
53 #include "RenderScrollbar.h"
54 #include "RenderScrollbarPart.h"
55 #include "RenderTheme.h"
56 #include "RenderView.h"
58 #include "TextResourceDecoder.h"
59 #include <wtf/CurrentTime.h>
61 #ifdef ANDROID_INSTRUMENT
62 #include "FrameTree.h"
63 #include "TimeCounter.h"
66 #if USE(ACCELERATED_COMPOSITING)
67 #include "RenderLayerCompositor.h"
71 #include "SVGDocument.h"
72 #include "SVGLocatable.h"
74 #include "SVGPreserveAspectRatio.h"
75 #include "SVGSVGElement.h"
76 #include "SVGViewElement.h"
77 #include "SVGViewSpec.h"
80 #if ENABLE(TILED_BACKING_STORE)
81 #include "TiledBackingStore.h"
85 #include "WebCoreFrameBridge.h"
90 using namespace HTMLNames;
92 double FrameView::sCurrentPaintTimeStamp = 0.0;
94 // REPAINT_THROTTLING now chooses default values for throttling parameters.
95 // Should be removed when applications start using runtime configuration.
96 #if ENABLE(REPAINT_THROTTLING)
98 double FrameView::s_deferredRepaintDelay = 0.025;
99 // Negative value would mean that first few repaints happen without a delay
100 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
101 // The delay grows on each repaint to this maximum value
102 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
103 // On each repaint the delay increses by this amount
104 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
106 // FIXME: Repaint throttling could be good to have on all platform.
107 // The balance between CPU use and repaint frequency will need some tuning for desktop.
108 // More hooks may be needed to reset the delay on things like GIF and CSS animations.
109 double FrameView::s_deferredRepaintDelay = 0;
110 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
111 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
112 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
115 // The maximum number of updateWidgets iterations that should be done before returning.
116 static const unsigned maxUpdateWidgetsIterations = 2;
118 struct ScheduledEvent : Noncopyable {
119 RefPtr<Event> m_event;
120 RefPtr<Node> m_eventTarget;
123 FrameView::FrameView(Frame* frame)
125 , m_canHaveScrollbars(true)
126 , m_slowRepaintObjectCount(0)
127 , m_fixedObjectCount(0)
128 , m_layoutTimer(this, &FrameView::layoutTimerFired)
130 , m_hasPendingPostLayoutTasks(false)
131 , m_inSynchronousPostLayout(false)
132 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
133 , m_isTransparent(false)
134 , m_baseBackgroundColor(Color::white)
135 , m_mediaType("screen")
137 , m_overflowStatusDirty(true)
138 , m_viewportRenderer(0)
139 , m_wasScrolledByUser(false)
140 , m_inProgrammaticScroll(false)
141 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
142 , m_shouldUpdateWhileOffscreen(true)
143 , m_deferSetNeedsLayouts(0)
144 , m_setNeedsLayoutWasDeferred(false)
150 PassRefPtr<FrameView> FrameView::create(Frame* frame)
152 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
154 return view.release();
157 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize)
159 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
160 view->Widget::setFrameRect(IntRect(view->pos(), initialSize));
162 return view.release();
165 FrameView::~FrameView()
167 if (m_hasPendingPostLayoutTasks) {
168 m_postLayoutTasksTimer.stop();
169 m_scheduledEvents.clear();
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->getMarginWidth();
266 int marginHeight = frameElt->getMarginHeight();
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)
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 void FrameView::setMarginWidth(int w)
351 // make it update the rendering area when set
352 m_margins.setWidth(w);
355 void FrameView::setMarginHeight(int h)
357 // make it update the rendering area when set
358 m_margins.setHeight(h);
361 bool FrameView::delegatesScrolling()
368 return m_frame->settings() && m_frame->settings()->shouldDelegateScrolling();
371 bool FrameView::avoidScrollbarCreation()
375 // with frame flattening no subframe can have scrollbars
376 // but we also cannot turn scrollbars of as we determine
377 // our flattening policy using that.
379 if (!m_frame->ownerElement())
382 if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
388 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
390 m_canHaveScrollbars = canHaveScrollbars;
391 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
394 void FrameView::updateCanHaveScrollbars()
398 scrollbarModes(hMode, vMode);
399 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
400 setCanHaveScrollbars(false);
402 setCanHaveScrollbars(true);
405 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
407 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
408 Document* doc = m_frame->document();
410 // Try the <body> element first as a scrollbar source.
411 Element* body = doc ? doc->body() : 0;
412 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
413 return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderer()->enclosingBox());
415 // If the <body> didn't have a custom style, then the root element might.
416 Element* docElement = doc ? doc->documentElement() : 0;
417 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
418 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox());
420 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
421 RenderPart* frameRenderer = m_frame->ownerRenderer();
422 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
423 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
425 // Nobody set a custom style, so we just use a native scrollbar.
426 return ScrollView::createScrollbar(orientation);
429 void FrameView::setContentsSize(const IntSize& size)
431 if (size == contentsSize())
434 m_deferSetNeedsLayouts++;
436 ScrollView::setContentsSize(size);
438 Page* page = frame() ? frame()->page() : 0;
442 page->chrome()->contentsSizeChanged(frame(), size); //notify only
444 m_deferSetNeedsLayouts--;
446 if (!m_deferSetNeedsLayouts)
447 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
450 void FrameView::adjustViewSize()
452 ASSERT(m_frame->view() == this);
453 RenderView* root = m_frame->contentRenderer();
457 setContentsSize(IntSize(root->rightLayoutOverflow(), root->bottomLayoutOverflow()));
460 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
462 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
463 // overflow:hidden and overflow:scroll on <body> as applying to the document's
464 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
465 // use the root element.
466 switch (o->style()->overflowX()) {
468 hMode = ScrollbarAlwaysOff;
471 hMode = ScrollbarAlwaysOn;
474 hMode = ScrollbarAuto;
477 // Don't set it at all.
481 switch (o->style()->overflowY()) {
483 vMode = ScrollbarAlwaysOff;
486 vMode = ScrollbarAlwaysOn;
489 vMode = ScrollbarAuto;
492 // Don't set it at all.
496 m_viewportRenderer = o;
499 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode)
501 if (m_canHaveScrollbars) {
502 hMode = ScrollbarAuto;
503 vMode = ScrollbarAuto;
505 hMode = ScrollbarAlwaysOff;
506 vMode = ScrollbarAlwaysOff;
510 Document* document = m_frame->document();
511 Node* documentElement = document->documentElement();
512 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
513 Node* body = document->body();
514 if (body && body->renderer()) {
515 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
516 #if !defined(ANDROID_FLATTEN_IFRAME) && !defined(ANDROID_FLATTEN_FRAMESET)
517 body->renderer()->setChildNeedsLayout(true);
518 vMode = ScrollbarAlwaysOff;
519 hMode = ScrollbarAlwaysOff;
521 } else if (body->hasTagName(bodyTag)) {
522 // It's sufficient to just check the X overflow,
523 // since it's illegal to have visible in only one direction.
524 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
525 applyOverflowToViewport(o, hMode, vMode);
527 } else if (rootRenderer) {
529 if (documentElement->isSVGElement()) {
530 if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight()))
531 rootRenderer->setChildNeedsLayout(true);
533 applyOverflowToViewport(rootRenderer, hMode, vMode);
535 applyOverflowToViewport(rootRenderer, hMode, vMode);
538 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
539 if (m_firstLayout && !document->ownerElement())
540 printf("Elapsed time before first layout: %d\n", document->elapsedTime());
544 HTMLFrameOwnerElement* owner = m_frame->ownerElement();
545 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
546 hMode = ScrollbarAlwaysOff;
547 vMode = ScrollbarAlwaysOff;
551 #if USE(ACCELERATED_COMPOSITING)
552 void FrameView::updateCompositingLayers()
554 RenderView* view = m_frame->contentRenderer();
557 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
558 // Enter compositing mode for child frames that have layout dimensions.
559 if (hasOverflowScroll())
560 enterCompositingMode();
563 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
564 view->compositor()->cacheAcceleratedCompositingFlags();
565 view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange);
568 void FrameView::setNeedsOneShotDrawingSynchronization()
570 Page* page = frame() ? frame()->page() : 0;
572 page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
575 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
576 bool FrameView::hasOverflowScroll() const
578 RenderObject* ownerRenderer = m_frame->ownerRenderer();
579 if (!ownerRenderer || !ownerRenderer->isRenderIFrame())
581 RenderLayer* layer = ownerRenderer->enclosingLayer();
582 // Make sure the layer has visible content or descendants.
583 if (!layer->hasVisibleContent() && !layer->hasVisibleDescendant())
585 // If either layout dimension is 0, return false.
586 if (!layoutWidth() || !layoutHeight())
589 scrollbarModes(h, v);
590 if (h == ScrollbarAlwaysOff || v == ScrollbarAlwaysOff)
592 if (contentsWidth() <= layoutWidth() && contentsHeight() <= layoutHeight())
597 #endif // USE(ACCELERATED_COMPOSITING)
599 bool FrameView::hasCompositedContent() const
601 #if USE(ACCELERATED_COMPOSITING)
602 if (RenderView* view = m_frame->contentRenderer())
603 return view->compositor()->inCompositingMode();
608 bool FrameView::hasCompositedContentIncludingDescendants() const
610 #if USE(ACCELERATED_COMPOSITING)
611 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
612 RenderView* renderView = frame->contentRenderer();
613 RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0;
615 if (compositor->inCompositingMode())
618 if (!RenderLayerCompositor::allowsIndependentlyCompositedIFrames(this))
626 bool FrameView::hasCompositingAncestor() const
628 #if USE(ACCELERATED_COMPOSITING)
629 for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) {
630 if (FrameView* view = frame->view()) {
631 if (view->hasCompositedContent())
639 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
640 void FrameView::enterCompositingMode()
642 #if USE(ACCELERATED_COMPOSITING)
643 if (RenderView* view = m_frame->contentRenderer()) {
644 view->compositor()->enableCompositingMode();
646 view->compositor()->scheduleCompositingLayerUpdate();
651 bool FrameView::isEnclosedInCompositingLayer() const
653 #if USE(ACCELERATED_COMPOSITING)
654 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
655 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
658 if (Frame* parentFrame = m_frame->tree()->parent()) {
659 if (FrameView* parentView = parentFrame->view())
660 return parentView->isEnclosedInCompositingLayer();
666 bool FrameView::syncCompositingStateRecursive()
668 #if USE(ACCELERATED_COMPOSITING)
669 ASSERT(m_frame->view() == this);
670 RenderView* contentRenderer = m_frame->contentRenderer();
671 if (!contentRenderer)
672 return true; // We don't want to keep trying to update layers if we have no renderer.
674 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
675 // layer content to occur before layout has happened, which will cause paintContents() to bail.
679 if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer())
680 rootLayer->syncCompositingState();
682 bool allSubframesSynced = true;
683 const HashSet<RefPtr<Widget> >* viewChildren = children();
684 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
685 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
686 Widget* widget = (*current).get();
687 if (widget->isFrameView()) {
688 bool synced = static_cast<FrameView*>(widget)->syncCompositingStateRecursive();
689 allSubframesSynced &= synced;
692 return allSubframesSynced;
693 #else // USE(ACCELERATED_COMPOSITING)
698 bool FrameView::isSoftwareRenderable() const
700 #if USE(ACCELERATED_COMPOSITING)
701 RenderView* view = m_frame->contentRenderer();
705 return !view->compositor()->has3DContent();
711 void FrameView::didMoveOnscreen()
713 RenderView* view = m_frame->contentRenderer();
715 view->didMoveOnscreen();
718 void FrameView::willMoveOffscreen()
720 RenderView* view = m_frame->contentRenderer();
722 view->willMoveOffscreen();
725 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
727 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
730 void FrameView::layout(bool allowSubtree)
735 m_layoutTimer.stop();
736 m_delayedLayout = false;
737 m_setNeedsLayoutWasDeferred = false;
739 // Protect the view from being deleted during layout (in recalcStyle)
740 RefPtr<FrameView> protector(this);
743 // FIXME: Do we need to set m_size.width here?
744 // FIXME: Should we set m_size.height here too?
745 m_size.setWidth(layoutWidth());
749 // we shouldn't enter layout() while painting
750 ASSERT(!isPainting());
754 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
756 if (!allowSubtree && m_layoutRoot) {
757 m_layoutRoot->markContainingBlocksForLayout(false);
761 ASSERT(m_frame->view() == this);
763 Document* document = m_frame->document();
765 m_layoutSchedulingEnabled = false;
767 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_hasPendingPostLayoutTasks) {
768 // This is a new top-level layout. If there are any remaining tasks from the previous
769 // layout, finish them now.
770 m_inSynchronousPostLayout = true;
771 m_postLayoutTasksTimer.stop();
772 performPostLayoutTasks();
773 m_inSynchronousPostLayout = false;
776 // Viewport-dependent media queries may cause us to need completely different style information.
778 if (document->styleSelector()->affectedByViewportChange())
779 document->styleSelectorChanged(RecalcStyleImmediately);
781 // Always ensure our style info is up-to-date. This can happen in situations where
782 // the layout beats any sort of style recalc update that needs to occur.
783 document->updateStyleIfNeeded();
785 bool subtree = m_layoutRoot;
787 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
788 // so there's no point to continuing to layout
789 if (protector->hasOneRef())
792 RenderObject* root = subtree ? m_layoutRoot : document->renderer();
794 // FIXME: Do we need to set m_size here?
795 m_layoutSchedulingEnabled = true;
799 #ifdef ANDROID_INSTRUMENT
800 if (!m_frame->tree() || !m_frame->tree()->parent())
801 android::TimeCounter::start(android::TimeCounter::LayoutTimeCounter);
804 m_nestedLayoutCount++;
809 calculateScrollbarModesForLayout(hMode, vMode);
811 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
814 // Now set our scrollbar state for the layout.
815 ScrollbarMode currentHMode = horizontalScrollbarMode();
816 ScrollbarMode currentVMode = verticalScrollbarMode();
818 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
820 setScrollbarsSuppressed(true);
822 m_firstLayout = false;
823 m_firstLayoutCallbackPending = true;
824 m_lastLayoutSize = IntSize(width(), height());
825 m_lastZoomFactor = root->style()->zoom();
827 // Set the initial vMode to AlwaysOn if we're auto.
828 if (vMode == ScrollbarAuto)
829 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
830 // Set the initial hMode to AlwaysOff if we're auto.
831 if (hMode == ScrollbarAuto)
832 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
834 setScrollbarModes(hMode, vMode);
835 setScrollbarsSuppressed(false, true);
837 setScrollbarModes(hMode, vMode);
840 IntSize oldSize = m_size;
842 m_size = IntSize(layoutWidth(), layoutHeight());
844 if (oldSize != m_size) {
845 m_doFullRepaint = true;
846 if (!m_firstLayout) {
847 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
848 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
849 if (bodyRenderer && bodyRenderer->stretchesToViewport())
850 bodyRenderer->setChildNeedsLayout(true);
851 else if (rootRenderer && rootRenderer->stretchesToViewport())
852 rootRenderer->setChildNeedsLayout(true);
857 RenderLayer* layer = root->enclosingLayer();
859 pauseScheduledEvents();
861 bool disableLayoutState = false;
863 RenderView* view = root->view();
864 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
865 view->pushLayoutState(root);
866 if (disableLayoutState)
867 view->disableLayoutState();
871 beginDeferredRepaints();
873 endDeferredRepaints();
877 RenderView* view = root->view();
878 view->popLayoutState(root);
879 if (disableLayoutState)
880 view->enableLayoutState();
884 m_frame->selection()->setCaretRectNeedsUpdate();
885 m_frame->selection()->updateAppearance();
887 m_layoutSchedulingEnabled = true;
889 if (!subtree && !toRenderView(root)->printing())
892 // Now update the positions of all layers.
893 beginDeferredRepaints();
894 IntPoint cachedOffset;
895 layer->updateLayerPositions((m_doFullRepaint ? RenderLayer::DoFullRepaint : 0)
896 | RenderLayer::CheckForRepaint
897 | RenderLayer::IsCompositingUpdateRoot
898 | RenderLayer::UpdateCompositingLayers,
899 subtree ? 0 : &cachedOffset);
900 endDeferredRepaints();
902 #if USE(ACCELERATED_COMPOSITING)
903 updateCompositingLayers();
908 #if PLATFORM(MAC) || PLATFORM(CHROMIUM)
909 if (AXObjectCache::accessibilityEnabled())
910 root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true);
912 #if ENABLE(DASHBOARD_SUPPORT)
913 updateDashboardRegions();
916 #ifdef ANDROID_INSTRUMENT
917 if (!m_frame->tree()->parent())
918 android::TimeCounter::record(android::TimeCounter::LayoutTimeCounter, __FUNCTION__);
920 ASSERT(!root->needsLayout());
922 updateCanBlitOnScrollRecursively();
924 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
925 updateOverflowStatus(layoutWidth() < contentsWidth(),
926 layoutHeight() < contentsHeight());
928 if (!m_hasPendingPostLayoutTasks) {
929 if (!m_inSynchronousPostLayout) {
930 m_inSynchronousPostLayout = true;
931 // Calls resumeScheduledEvents()
932 performPostLayoutTasks();
933 m_inSynchronousPostLayout = false;
936 if (!m_hasPendingPostLayoutTasks && (needsLayout() || m_inSynchronousPostLayout)) {
937 // If we need layout or are already in a synchronous call to postLayoutTasks(),
938 // defer widget updates and event dispatch until after we return. postLayoutTasks()
939 // can make us need to update again, and we can get stuck in a nasty cycle unless
940 // we call it through the timer here.
941 m_hasPendingPostLayoutTasks = true;
942 m_postLayoutTasksTimer.startOneShot(0);
944 pauseScheduledEvents();
949 resumeScheduledEvents();
950 ASSERT(m_enqueueEvents);
953 InspectorInstrumentation::didLayout(cookie);
955 m_nestedLayoutCount--;
958 void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object)
960 if (!m_widgetUpdateSet)
961 m_widgetUpdateSet.set(new RenderEmbeddedObjectSet);
963 m_widgetUpdateSet->add(object);
966 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object)
968 if (!m_widgetUpdateSet)
971 m_widgetUpdateSet->remove(object);
974 void FrameView::setMediaType(const String& mediaType)
976 m_mediaType = mediaType;
979 String FrameView::mediaType() const
981 // See if we have an override type.
982 String overrideType = m_frame->loader()->client()->overrideMediaType();
983 if (!overrideType.isNull())
988 void FrameView::adjustMediaTypeForPrinting(bool printing)
991 if (m_mediaTypeWhenNotPrinting.isNull())
992 m_mediaTypeWhenNotPrinting = mediaType();
993 setMediaType("print");
995 if (!m_mediaTypeWhenNotPrinting.isNull())
996 setMediaType(m_mediaTypeWhenNotPrinting);
997 m_mediaTypeWhenNotPrinting = String();
1001 bool FrameView::useSlowRepaints() const
1003 if (m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || m_isOverlapped || !m_contentIsOpaque)
1006 if (Frame* parentFrame = m_frame->tree()->parent()) {
1007 if (FrameView* parentView = parentFrame->view())
1008 return parentView->useSlowRepaints();
1014 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1016 if (m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || !m_contentIsOpaque)
1019 if (Frame* parentFrame = m_frame->tree()->parent()) {
1020 if (FrameView* parentView = parentFrame->view())
1021 return parentView->useSlowRepaintsIfNotOverlapped();
1027 void FrameView::updateCanBlitOnScrollRecursively()
1029 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1030 if (FrameView* view = frame->view())
1031 view->setCanBlitOnScroll(!view->useSlowRepaints());
1035 void FrameView::setUseSlowRepaints()
1037 m_useSlowRepaints = true;
1038 updateCanBlitOnScrollRecursively();
1041 void FrameView::addSlowRepaintObject()
1043 if (!m_slowRepaintObjectCount)
1044 updateCanBlitOnScrollRecursively();
1045 m_slowRepaintObjectCount++;
1048 void FrameView::removeSlowRepaintObject()
1050 ASSERT(m_slowRepaintObjectCount > 0);
1051 m_slowRepaintObjectCount--;
1052 if (!m_slowRepaintObjectCount)
1053 updateCanBlitOnScrollRecursively();
1056 void FrameView::addFixedObject()
1058 if (!m_fixedObjectCount && platformWidget())
1059 updateCanBlitOnScrollRecursively();
1060 ++m_fixedObjectCount;
1063 void FrameView::removeFixedObject()
1065 ASSERT(m_fixedObjectCount > 0);
1066 --m_fixedObjectCount;
1067 if (!m_fixedObjectCount)
1068 updateCanBlitOnScrollRecursively();
1071 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1073 const size_t fixedObjectThreshold = 5;
1075 RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0;
1076 if (RenderView* root = m_frame->contentRenderer())
1077 positionedObjects = root->positionedObjects();
1079 if (!positionedObjects || positionedObjects->isEmpty()) {
1080 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1084 // Get the rects of the fixed objects visible in the rectToScroll
1085 Vector<IntRect, fixedObjectThreshold> subRectToUpdate;
1086 bool updateInvalidatedSubRect = true;
1087 RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
1088 for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
1089 RenderBox* renderBox = *it;
1090 if (renderBox->style()->position() != FixedPosition)
1092 IntRect updateRect = renderBox->layer()->repaintRectIncludingDescendants();
1093 updateRect = contentsToWindow(updateRect);
1095 updateRect.intersect(rectToScroll);
1096 if (!updateRect.isEmpty()) {
1097 if (subRectToUpdate.size() >= fixedObjectThreshold) {
1098 updateInvalidatedSubRect = false;
1101 subRectToUpdate.append(updateRect);
1106 if (updateInvalidatedSubRect) {
1108 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1110 // 2) update the area of fixed objects that has been invalidated
1111 size_t fixObjectsCount = subRectToUpdate.size();
1112 for (size_t i = 0; i < fixObjectsCount; ++i) {
1113 IntRect updateRect = subRectToUpdate[i];
1114 IntRect scrolledRect = updateRect;
1115 scrolledRect.move(scrollDelta);
1116 updateRect.unite(scrolledRect);
1117 updateRect.intersect(rectToScroll);
1118 hostWindow()->invalidateContentsAndWindow(updateRect, false);
1123 // the number of fixed objects exceed the threshold, we cannot use the fast path
1127 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1129 #if USE(ACCELERATED_COMPOSITING)
1130 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1131 if (frameRenderer->containerForRepaint()) {
1132 IntRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1133 frameRenderer->borderTop() + frameRenderer->paddingTop(),
1134 visibleWidth(), visibleHeight());
1135 frameRenderer->repaintRectangle(rect);
1141 ScrollView::scrollContentsSlowPath(updateRect);
1144 // Note that this gets called at painting time.
1145 void FrameView::setIsOverlapped(bool isOverlapped)
1147 if (isOverlapped == m_isOverlapped)
1150 m_isOverlapped = isOverlapped;
1151 updateCanBlitOnScrollRecursively();
1153 #if USE(ACCELERATED_COMPOSITING)
1154 if (hasCompositedContentIncludingDescendants()) {
1155 // Overlap can affect compositing tests, so if it changes, we need to trigger
1156 // a layer update in the parent document.
1157 if (Frame* parentFrame = m_frame->tree()->parent()) {
1158 if (RenderView* parentView = parentFrame->contentRenderer()) {
1159 RenderLayerCompositor* compositor = parentView->compositor();
1160 compositor->setCompositingLayersNeedRebuild();
1161 compositor->scheduleCompositingLayerUpdate();
1165 if (RenderLayerCompositor::allowsIndependentlyCompositedIFrames(this)) {
1166 // We also need to trigger reevaluation for this and all descendant frames,
1167 // since a frame uses compositing if any ancestor is compositing.
1168 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1169 if (RenderView* view = frame->contentRenderer()) {
1170 RenderLayerCompositor* compositor = view->compositor();
1171 compositor->setCompositingLayersNeedRebuild();
1172 compositor->scheduleCompositingLayerUpdate();
1180 bool FrameView::isOverlappedIncludingAncestors() const
1185 if (Frame* parentFrame = m_frame->tree()->parent()) {
1186 if (FrameView* parentView = parentFrame->view()) {
1187 if (parentView->isOverlapped())
1195 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1197 if (contentIsOpaque == m_contentIsOpaque)
1200 m_contentIsOpaque = contentIsOpaque;
1201 updateCanBlitOnScrollRecursively();
1204 void FrameView::restoreScrollbar()
1206 setScrollbarsSuppressed(false);
1209 bool FrameView::scrollToFragment(const KURL& url)
1211 // If our URL has no ref, then we have no place we need to jump to.
1212 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1213 // and possibly repaint because :target pseudo class may have been
1214 // set (see bug 11321).
1215 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1218 String fragmentIdentifier = url.fragmentIdentifier();
1219 if (scrollToAnchor(fragmentIdentifier))
1222 // Try again after decoding the ref, based on the document's encoding.
1223 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1224 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1229 bool FrameView::scrollToAnchor(const String& name)
1231 ASSERT(m_frame->document());
1233 if (!m_frame->document()->haveStylesheetsLoaded()) {
1234 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1238 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1240 Element* anchorNode = m_frame->document()->findAnchor(name);
1243 if (m_frame->document()->isSVGDocument()) {
1244 if (name.startsWith("xpointer(")) {
1245 // We need to parse the xpointer reference here
1246 } else if (name.startsWith("svgView(")) {
1247 RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement();
1248 if (!svg->currentView()->parseViewSpec(name))
1250 svg->setUseCurrentView(true);
1252 if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) {
1253 RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0;
1254 if (viewElement.get()) {
1255 RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(SVGLocatable::nearestViewportElement(viewElement.get()));
1256 svg->inheritViewAttributes(viewElement.get());
1260 // FIXME: need to decide which <svg> to focus on, and zoom to that one
1261 // FIXME: need to actually "highlight" the viewTarget(s)
1265 m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target.
1267 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1268 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1271 #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR
1272 // TODO(andreip): check with Grace if this is correct.
1273 android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedAction(true);
1275 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1276 #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR
1277 android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedAction(false);
1282 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1284 m_maintainScrollPositionAnchor = anchorNode;
1285 if (!m_maintainScrollPositionAnchor)
1288 // We need to update the layout before scrolling, otherwise we could
1289 // really mess things up if an anchor scroll comes at a bad moment.
1290 m_frame->document()->updateStyleIfNeeded();
1291 // Only do a layout if changes have occurred that make it necessary.
1292 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
1298 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1300 bool wasInProgrammaticScroll = m_inProgrammaticScroll;
1301 m_inProgrammaticScroll = true;
1302 m_maintainScrollPositionAnchor = 0;
1303 ScrollView::setScrollPosition(scrollPoint);
1304 m_inProgrammaticScroll = wasInProgrammaticScroll;
1307 void FrameView::scrollPositionChangedViaPlatformWidget()
1309 repaintFixedElementsAfterScrolling();
1310 scrollPositionChanged();
1313 void FrameView::scrollPositionChanged()
1315 frame()->eventHandler()->sendScrollEvent();
1317 #if USE(ACCELERATED_COMPOSITING)
1318 if (RenderView* root = m_frame->contentRenderer()) {
1319 if (root->usesCompositing())
1320 root->compositor()->frameViewDidScroll(scrollPosition());
1325 void FrameView::repaintFixedElementsAfterScrolling()
1327 // For fixed position elements, update widget positions and compositing layers after scrolling,
1328 // but only if we're not inside of layout.
1329 if (!m_nestedLayoutCount && hasFixedObjects()) {
1330 if (RenderView* root = m_frame->contentRenderer()) {
1331 root->updateWidgetPositions();
1332 root->layer()->updateRepaintRectsAfterScroll();
1333 #if USE(ACCELERATED_COMPOSITING)
1334 root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
1340 HostWindow* FrameView::hostWindow() const
1342 Page* page = frame() ? frame()->page() : 0;
1345 return page->chrome();
1348 const unsigned cRepaintRectUnionThreshold = 25;
1350 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
1352 ASSERT(!m_frame->document()->ownerElement());
1354 double delay = adjustedDeferredRepaintDelay();
1355 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
1356 IntRect paintRect = r;
1357 if (!paintsEntireContents())
1358 paintRect.intersect(visibleContentRect());
1359 #ifdef ANDROID_CAPTURE_OFFSCREEN_PAINTS
1361 ScrollView::platformOffscreenContentRectangle(visibleContentRect(), r);
1363 if (paintRect.isEmpty())
1365 if (m_repaintCount == cRepaintRectUnionThreshold) {
1366 IntRect unionedRect;
1367 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
1368 unionedRect.unite(m_repaintRects[i]);
1369 m_repaintRects.clear();
1370 m_repaintRects.append(unionedRect);
1372 if (m_repaintCount < cRepaintRectUnionThreshold)
1373 m_repaintRects.append(paintRect);
1375 m_repaintRects[0].unite(paintRect);
1378 if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive())
1379 m_deferredRepaintTimer.startOneShot(delay);
1383 if (!immediate && isOffscreen() && !shouldUpdateWhileOffscreen())
1386 #if ENABLE(TILED_BACKING_STORE)
1387 if (frame()->tiledBackingStore()) {
1388 frame()->tiledBackingStore()->invalidate(r);
1392 ScrollView::repaintContentRectangle(r, immediate);
1395 void FrameView::visibleContentsResized()
1397 // We check to make sure the view is attached to a frame() as this method can
1398 // be triggered before the view is attached by Frame::createView(...) setting
1399 // various values such as setScrollBarModes(...) for example. An ASSERT is
1400 // triggered when a view is layout before being attached to a frame().
1401 if (!frame()->view())
1408 void FrameView::beginDeferredRepaints()
1410 Page* page = m_frame->page();
1411 if (page->mainFrame() != m_frame)
1412 return page->mainFrame()->view()->beginDeferredRepaints();
1414 m_deferringRepaints++;
1418 void FrameView::endDeferredRepaints()
1420 Page* page = m_frame->page();
1421 if (page->mainFrame() != m_frame)
1422 return page->mainFrame()->view()->endDeferredRepaints();
1424 ASSERT(m_deferringRepaints > 0);
1426 if (--m_deferringRepaints)
1429 if (m_deferredRepaintTimer.isActive())
1432 if (double delay = adjustedDeferredRepaintDelay()) {
1433 m_deferredRepaintTimer.startOneShot(delay);
1437 doDeferredRepaints();
1440 void FrameView::checkStopDelayingDeferredRepaints()
1442 if (!m_deferredRepaintTimer.isActive())
1445 Document* document = m_frame->document();
1446 if (document && (document->parsing() || document->cachedResourceLoader()->requestCount()))
1449 m_deferredRepaintTimer.stop();
1451 doDeferredRepaints();
1454 void FrameView::doDeferredRepaints()
1456 ASSERT(!m_deferringRepaints);
1457 if (isOffscreen() && !shouldUpdateWhileOffscreen()) {
1458 m_repaintRects.clear();
1462 unsigned size = m_repaintRects.size();
1463 for (unsigned i = 0; i < size; i++) {
1464 #if ENABLE(TILED_BACKING_STORE)
1465 if (frame()->tiledBackingStore()) {
1466 frame()->tiledBackingStore()->invalidate(m_repaintRects[i]);
1470 ScrollView::repaintContentRectangle(m_repaintRects[i], false);
1472 m_repaintRects.clear();
1475 updateDeferredRepaintDelay();
1478 void FrameView::updateDeferredRepaintDelay()
1480 Document* document = m_frame->document();
1481 if (!document || (!document->parsing() && !document->cachedResourceLoader()->requestCount())) {
1482 m_deferredRepaintDelay = s_deferredRepaintDelay;
1485 if (m_deferredRepaintDelay < s_maxDeferredRepaintDelayDuringLoading) {
1486 m_deferredRepaintDelay += s_deferredRepaintDelayIncrementDuringLoading;
1487 if (m_deferredRepaintDelay > s_maxDeferredRepaintDelayDuringLoading)
1488 m_deferredRepaintDelay = s_maxDeferredRepaintDelayDuringLoading;
1492 void FrameView::resetDeferredRepaintDelay()
1494 m_deferredRepaintDelay = 0;
1495 if (m_deferredRepaintTimer.isActive()) {
1496 m_deferredRepaintTimer.stop();
1497 if (!m_deferringRepaints)
1498 doDeferredRepaints();
1502 double FrameView::adjustedDeferredRepaintDelay() const
1504 if (!m_deferredRepaintDelay)
1506 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
1507 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
1510 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
1512 doDeferredRepaints();
1515 void FrameView::layoutTimerFired(Timer<FrameView>*)
1517 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1518 if (!m_frame->document()->ownerElement())
1519 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
1524 void FrameView::scheduleRelayout()
1526 // FIXME: We should assert the page is not in the page cache, but that is causing
1527 // too many false assertions. See <rdar://problem/7218118>.
1528 ASSERT(m_frame->view() == this);
1531 m_layoutRoot->markContainingBlocksForLayout(false);
1534 if (!m_layoutSchedulingEnabled)
1538 if (!m_frame->document()->shouldScheduleLayout())
1541 #if defined(ANDROID_FLATTEN_IFRAME) || defined(ANDROID_FLATTEN_FRAMESET)
1542 // This is the Android frame flattening code. The common code below is not
1543 // used as frameSetFlatteningEnabled() is false on Android.
1544 if (m_frame->ownerRenderer())
1545 m_frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc();
1548 // When frame flattening is enabled, the contents of the frame affects layout of the parent frames.
1549 // Also invalidate parent frame starting from the owner element of this frame.
1550 if (m_frame->settings() && m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) {
1551 if (m_frame->ownerElement()->hasTagName(iframeTag) || m_frame->ownerElement()->hasTagName(frameTag))
1552 m_frame->ownerRenderer()->setNeedsLayout(true, true);
1555 int delay = m_frame->document()->minimumLayoutDelay();
1556 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
1557 unscheduleRelayout();
1558 if (m_layoutTimer.isActive())
1561 m_delayedLayout = delay != 0;
1563 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1564 if (!m_frame->document()->ownerElement())
1565 printf("Scheduling layout for %d\n", delay);
1568 m_layoutTimer.startOneShot(delay * 0.001);
1571 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
1573 for (RenderObject* r = descendant; r; r = r->container()) {
1580 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
1582 ASSERT(m_frame->view() == this);
1584 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) {
1586 relayoutRoot->markContainingBlocksForLayout(false);
1590 if (layoutPending() || !m_layoutSchedulingEnabled) {
1591 if (m_layoutRoot != relayoutRoot) {
1592 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
1593 // Keep the current root
1594 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
1595 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
1596 // Re-root at relayoutRoot
1597 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
1598 m_layoutRoot = relayoutRoot;
1600 // Just do a full relayout
1602 m_layoutRoot->markContainingBlocksForLayout(false);
1604 relayoutRoot->markContainingBlocksForLayout(false);
1607 } else if (m_layoutSchedulingEnabled) {
1608 int delay = m_frame->document()->minimumLayoutDelay();
1609 m_layoutRoot = relayoutRoot;
1610 m_delayedLayout = delay != 0;
1611 m_layoutTimer.startOneShot(delay * 0.001);
1615 bool FrameView::layoutPending() const
1617 return m_layoutTimer.isActive();
1620 bool FrameView::needsLayout() const
1622 // This can return true in cases where the document does not have a body yet.
1623 // Document::shouldScheduleLayout takes care of preventing us from scheduling
1624 // layout in that case.
1627 RenderView* root = m_frame->contentRenderer();
1628 return layoutPending()
1629 || (root && root->needsLayout())
1631 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
1634 void FrameView::setNeedsLayout()
1636 if (m_deferSetNeedsLayouts) {
1637 m_setNeedsLayoutWasDeferred = true;
1640 RenderView* root = m_frame->contentRenderer();
1642 root->setNeedsLayout(true);
1645 void FrameView::unscheduleRelayout()
1647 m_postLayoutTasksTimer.stop();
1649 if (!m_layoutTimer.isActive())
1652 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1653 if (!m_frame->document()->ownerElement())
1654 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
1657 m_layoutTimer.stop();
1658 m_delayedLayout = false;
1661 bool FrameView::isTransparent() const
1663 return m_isTransparent;
1666 void FrameView::setTransparent(bool isTransparent)
1668 m_isTransparent = isTransparent;
1671 Color FrameView::baseBackgroundColor() const
1673 return m_baseBackgroundColor;
1676 void FrameView::setBaseBackgroundColor(Color bc)
1680 m_baseBackgroundColor = bc;
1683 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
1685 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1686 if (FrameView* view = frame->view()) {
1687 view->setTransparent(transparent);
1688 view->setBaseBackgroundColor(backgroundColor);
1693 bool FrameView::shouldUpdateWhileOffscreen() const
1695 return m_shouldUpdateWhileOffscreen;
1698 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
1700 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
1703 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
1705 if (!m_enqueueEvents) {
1706 ExceptionCode ec = 0;
1707 eventTarget->dispatchEvent(event, ec);
1711 ScheduledEvent* scheduledEvent = new ScheduledEvent;
1712 scheduledEvent->m_event = event;
1713 scheduledEvent->m_eventTarget = eventTarget;
1714 m_scheduledEvents.append(scheduledEvent);
1717 void FrameView::pauseScheduledEvents()
1719 ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
1723 void FrameView::resumeScheduledEvents()
1726 if (!m_enqueueEvents)
1727 dispatchScheduledEvents();
1728 ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
1731 void FrameView::scrollToAnchor()
1733 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
1737 if (!anchorNode->renderer())
1741 if (anchorNode != m_frame->document())
1742 rect = anchorNode->getRect();
1744 // Scroll nested layers and frames to reveal the anchor.
1745 // Align to the top and to the closest side (this matches other browsers).
1746 anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
1748 if (AXObjectCache::accessibilityEnabled())
1749 m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get());
1751 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
1752 m_maintainScrollPositionAnchor = anchorNode;
1755 void FrameView::updateWidget(RenderEmbeddedObject* object)
1757 ASSERT(!object->node() || object->node()->isElementNode());
1758 Element* ownerElement = static_cast<Element*>(object->node());
1759 // The object may have already been destroyed (thus node cleared),
1760 // but FrameView holds a manual ref, so it won't have been deleted.
1761 ASSERT(m_widgetUpdateSet->contains(object));
1765 // No need to update if it's already crashed or known to be missing.
1766 if (object->pluginCrashedOrWasMissing())
1769 // FIXME: This could turn into a real virtual dispatch if we defined
1770 // updateWidget(bool) on HTMLElement.
1771 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag))
1772 static_cast<HTMLPlugInImageElement*>(ownerElement)->updateWidget(false);
1773 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
1774 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1775 else if (ownerElement->hasTagName(videoTag) || ownerElement->hasTagName(audioTag))
1776 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(false);
1779 ASSERT_NOT_REACHED();
1781 // Caution: it's possible the object was destroyed again, since loading a
1782 // plugin may run any arbitrary javascript.
1783 object->updateWidgetPosition();
1786 bool FrameView::updateWidgets()
1788 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
1791 size_t size = m_widgetUpdateSet->size();
1793 Vector<RenderEmbeddedObject*> objects;
1794 objects.reserveCapacity(size);
1796 RenderEmbeddedObjectSet::const_iterator end = m_widgetUpdateSet->end();
1797 for (RenderEmbeddedObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
1798 objects.uncheckedAppend(*it);
1802 for (size_t i = 0; i < size; ++i) {
1803 RenderEmbeddedObject* object = objects[i];
1804 updateWidget(object);
1805 m_widgetUpdateSet->remove(object);
1808 RenderArena* arena = m_frame->document()->renderArena();
1809 for (size_t i = 0; i < size; ++i)
1810 objects[i]->deref(arena);
1812 return m_widgetUpdateSet->isEmpty();
1815 void FrameView::performPostLayoutTasks()
1817 m_hasPendingPostLayoutTasks = false;
1819 if (m_firstLayoutCallbackPending) {
1820 m_firstLayoutCallbackPending = false;
1821 m_frame->loader()->didFirstLayout();
1824 if (m_isVisuallyNonEmpty && m_firstVisuallyNonEmptyLayoutCallbackPending) {
1825 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
1826 m_frame->loader()->didFirstVisuallyNonEmptyLayout();
1829 RenderView* root = m_frame->contentRenderer();
1831 root->updateWidgetPositions();
1833 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
1834 if (updateWidgets())
1840 resumeScheduledEvents();
1842 if (!root->printing()) {
1843 IntSize currentSize = IntSize(width(), height());
1844 float currentZoomFactor = root->style()->zoom();
1845 bool resized = !m_firstLayout && (currentSize != m_lastLayoutSize || currentZoomFactor != m_lastZoomFactor);
1846 m_lastLayoutSize = currentSize;
1847 m_lastZoomFactor = currentZoomFactor;
1849 m_frame->eventHandler()->sendResizeEvent();
1853 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
1855 performPostLayoutTasks();
1858 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
1860 if (!m_viewportRenderer)
1863 if (m_overflowStatusDirty) {
1864 m_horizontalOverflow = horizontalOverflow;
1865 m_verticalOverflow = verticalOverflow;
1866 m_overflowStatusDirty = false;
1870 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
1871 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
1873 if (horizontalOverflowChanged || verticalOverflowChanged) {
1874 m_horizontalOverflow = horizontalOverflow;
1875 m_verticalOverflow = verticalOverflow;
1877 scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
1878 verticalOverflowChanged, verticalOverflow),
1879 m_viewportRenderer->node());
1884 void FrameView::dispatchScheduledEvents()
1886 if (m_scheduledEvents.isEmpty())
1889 Vector<ScheduledEvent*> scheduledEventsCopy = m_scheduledEvents;
1890 m_scheduledEvents.clear();
1892 Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end();
1893 for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) {
1894 ScheduledEvent* scheduledEvent = *it;
1896 ExceptionCode ec = 0;
1898 // Only dispatch events to nodes that are in the document
1899 if (scheduledEvent->m_eventTarget->inDocument())
1900 scheduledEvent->m_eventTarget->dispatchEvent(scheduledEvent->m_event, ec);
1902 delete scheduledEvent;
1906 IntRect FrameView::windowClipRect(bool clipToContents) const
1908 ASSERT(m_frame->view() == this);
1910 if (paintsEntireContents())
1911 return IntRect(IntPoint(0, 0), contentsSize());
1913 // Set our clip rect to be our contents.
1914 IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
1915 if (!m_frame || !m_frame->document() || !m_frame->document()->ownerElement())
1918 // Take our owner element and get the clip rect from the enclosing layer.
1919 Element* elt = m_frame->document()->ownerElement();
1920 RenderLayer* layer = elt->renderer()->enclosingLayer();
1921 // FIXME: layer should never be null, but sometimes seems to be anyway.
1924 FrameView* parentView = elt->document()->view();
1925 clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
1929 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const
1931 // If we have no layer, just return our window clip rect.
1933 return windowClipRect();
1935 // Apply the clip from the layer.
1937 if (clipToLayerContents)
1938 clipRect = layer->childrenClipRect();
1940 clipRect = layer->selfClipRect();
1941 clipRect = contentsToWindow(clipRect);
1942 return intersection(clipRect, windowClipRect());
1945 bool FrameView::isActive() const
1947 Page* page = frame()->page();
1948 return page && page->focusController()->isActive();
1951 void FrameView::valueChanged(Scrollbar* bar)
1953 // Figure out if we really moved.
1954 IntSize offset = scrollOffset();
1955 ScrollView::valueChanged(bar);
1956 if (offset != scrollOffset())
1957 scrollPositionChanged();
1958 frame()->loader()->client()->didChangeScrollOffset();
1961 void FrameView::valueChanged(const IntSize& scrollDelta)
1963 ScrollView::valueChanged(scrollDelta);
1964 frame()->eventHandler()->sendScrollEvent();
1965 frame()->loader()->client()->didChangeScrollOffset();
1968 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
1970 // Add in our offset within the FrameView.
1971 IntRect dirtyRect = rect;
1972 dirtyRect.move(scrollbar->x(), scrollbar->y());
1973 invalidateRect(dirtyRect);
1976 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
1978 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
1981 IntRect FrameView::windowResizerRect() const
1983 Page* page = frame() ? frame()->page() : 0;
1986 return page->chrome()->windowResizerRect();
1989 #if ENABLE(DASHBOARD_SUPPORT)
1990 void FrameView::updateDashboardRegions()
1992 Document* document = m_frame->document();
1993 if (!document->hasDashboardRegions())
1995 Vector<DashboardRegionValue> newRegions;
1996 document->renderBox()->collectDashboardRegions(newRegions);
1997 if (newRegions == document->dashboardRegions())
1999 document->setDashboardRegions(newRegions);
2000 Page* page = m_frame->page();
2003 page->chrome()->client()->dashboardRegionsChanged();
2007 void FrameView::invalidateScrollCorner()
2009 invalidateRect(scrollCornerRect());
2012 void FrameView::updateScrollCorner()
2014 RenderObject* renderer = 0;
2015 RefPtr<RenderStyle> cornerStyle;
2017 if (!scrollCornerRect().isEmpty()) {
2018 // Try the <body> element first as a scroll corner source.
2019 Document* doc = m_frame->document();
2020 Element* body = doc ? doc->body() : 0;
2021 if (body && body->renderer()) {
2022 renderer = body->renderer();
2023 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2027 // If the <body> didn't have a custom style, then the root element might.
2028 Element* docElement = doc ? doc->documentElement() : 0;
2029 if (docElement && docElement->renderer()) {
2030 renderer = docElement->renderer();
2031 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2036 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
2037 if (RenderPart* renderer = m_frame->ownerRenderer())
2038 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2043 if (!m_scrollCorner)
2044 m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document());
2045 m_scrollCorner->setStyle(cornerStyle.release());
2046 invalidateRect(scrollCornerRect());
2047 } else if (m_scrollCorner) {
2048 m_scrollCorner->destroy();
2053 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
2055 if (context->updatingControlTints()) {
2056 updateScrollCorner();
2060 if (m_scrollCorner) {
2061 m_scrollCorner->paintIntoRect(context, cornerRect.x(), cornerRect.y(), cornerRect);
2065 ScrollView::paintScrollCorner(context, cornerRect);
2068 bool FrameView::hasCustomScrollbars() const
2070 const HashSet<RefPtr<Widget> >* viewChildren = children();
2071 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2072 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2073 Widget* widget = current->get();
2074 if (widget->isFrameView()) {
2075 if (static_cast<FrameView*>(widget)->hasCustomScrollbars())
2077 } else if (widget->isScrollbar()) {
2078 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
2079 if (scrollbar->isCustomScrollbar())
2087 void FrameView::updateControlTints()
2089 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
2090 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
2091 // This is only done if the theme supports control tinting. It's up to the theme and platform
2092 // to define when controls get the tint and to call this function when that changes.
2094 // Optimize the common case where we bring a window to the front while it's still empty.
2095 if (!m_frame || m_frame->loader()->url().isEmpty())
2098 if ((m_frame->contentRenderer() && m_frame->contentRenderer()->theme()->supportsControlTints()) || hasCustomScrollbars()) {
2101 PlatformGraphicsContext* const noContext = 0;
2102 GraphicsContext context(noContext);
2103 context.setUpdatingControlTints(true);
2104 if (platformWidget())
2105 paintContents(&context, visibleContentRect());
2107 paint(&context, frameRect());
2111 bool FrameView::wasScrolledByUser() const
2113 return m_wasScrolledByUser;
2116 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
2118 if (m_inProgrammaticScroll)
2120 m_maintainScrollPositionAnchor = 0;
2121 m_wasScrolledByUser = wasScrolledByUser;
2124 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
2129 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get(), rect);
2131 Document* document = frame()->document();
2135 if (document->printing())
2136 fillWithRed = false; // Printing, don't fill with red (can't remember why).
2137 else if (document->ownerElement())
2138 fillWithRed = false; // Subframe, don't fill with red.
2139 else if (isTransparent())
2140 fillWithRed = false; // Transparent, don't fill with red.
2141 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
2142 fillWithRed = false; // Selections are transparent, don't fill with red.
2143 else if (m_nodeToDraw)
2144 fillWithRed = false; // Element images are transparent, don't fill with red.
2149 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
2152 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
2153 if (isTopLevelPainter)
2154 sCurrentPaintTimeStamp = currentTime();
2156 RenderView* contentRenderer = frame()->contentRenderer();
2157 if (!contentRenderer) {
2158 LOG_ERROR("called FrameView::paint with nil renderer");
2162 ASSERT(!needsLayout());
2166 #if USE(ACCELERATED_COMPOSITING)
2167 if (!p->paintingDisabled()) {
2168 if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer())
2169 rootLayer->syncCompositingState();
2173 ASSERT(!m_isPainting);
2175 m_isPainting = true;
2177 // m_nodeToDraw is used to draw only one element (and its descendants)
2178 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
2180 PaintBehavior oldPaintBehavior = m_paintBehavior;
2181 if (m_paintBehavior == PaintBehaviorNormal)
2182 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
2184 if (document->printing())
2185 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2187 contentRenderer->layer()->paint(p, rect, m_paintBehavior, eltRenderer);
2189 m_paintBehavior = oldPaintBehavior;
2191 m_isPainting = false;
2192 m_lastPaintTime = currentTime();
2194 #if ENABLE(DASHBOARD_SUPPORT)
2195 // Regions may have changed as a result of the visibility/z-index of element changing.
2196 if (document->dashboardRegionsDirty())
2197 updateDashboardRegions();
2200 if (isTopLevelPainter)
2201 sCurrentPaintTimeStamp = 0;
2203 InspectorInstrumentation::didPaint(cookie);
2206 void FrameView::setPaintBehavior(PaintBehavior behavior)
2208 m_paintBehavior = behavior;
2211 PaintBehavior FrameView::paintBehavior() const
2213 return m_paintBehavior;
2216 bool FrameView::isPainting() const
2218 return m_isPainting;
2221 void FrameView::setNodeToDraw(Node* node)
2223 m_nodeToDraw = node;
2226 void FrameView::updateLayoutAndStyleIfNeededRecursive()
2228 // We have to crawl our entire tree looking for any FrameViews that need
2229 // layout and make sure they are up to date.
2230 // Mac actually tests for intersection with the dirty region and tries not to
2231 // update layout for frames that are outside the dirty region. Not only does this seem
2232 // pointless (since those frames will have set a zero timer to layout anyway), but
2233 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
2234 // region but then become included later by the second frame adding rects to the dirty region
2235 // when it lays out.
2237 m_frame->document()->updateStyleIfNeeded();
2242 const HashSet<RefPtr<Widget> >* viewChildren = children();
2243 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2244 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2245 Widget* widget = (*current).get();
2246 if (widget->isFrameView())
2247 static_cast<FrameView*>(widget)->updateLayoutAndStyleIfNeededRecursive();
2250 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
2251 // painting, so we need to flush out any deferred repaints too.
2252 flushDeferredRepaints();
2255 void FrameView::flushDeferredRepaints()
2257 if (!m_deferredRepaintTimer.isActive())
2259 m_deferredRepaintTimer.stop();
2260 doDeferredRepaints();
2263 void FrameView::forceLayout(bool allowSubtree)
2265 layout(allowSubtree);
2268 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximumShrinkFactor, Frame::AdjustViewSizeOrNot shouldAdjustViewSize)
2270 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
2271 // the state of things before and after the layout
2272 RenderView *root = toRenderView(m_frame->document()->renderer());
2274 int pageW = ceilf(pageSize.width());
2275 root->setWidth(pageW);
2276 root->setPageHeight(pageSize.height());
2277 root->setNeedsLayoutAndPrefWidthsRecalc();
2280 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
2281 // page width when shrunk, we will lay out at maximum shrink and clip extra content.
2282 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
2283 // implementation should not do this!
2284 int rightmostPos = root->rightmostPosition();
2285 if (rightmostPos > pageSize.width()) {
2286 pageW = std::min<int>(rightmostPos, ceilf(pageSize.width() * maximumShrinkFactor));
2287 if (pageSize.height())
2288 root->setPageHeight(pageW / pageSize.width() * pageSize.height());
2289 root->setWidth(pageW);
2290 root->setNeedsLayoutAndPrefWidthsRecalc();
2292 int docHeight = root->bottomLayoutOverflow();
2293 root->clearLayoutOverflow();
2294 root->addLayoutOverflow(IntRect(0, 0, pageW, docHeight)); // This is how we clip in case we overflow again.
2298 if (shouldAdjustViewSize)
2302 void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
2304 RenderView* root = m_frame->contentRenderer();
2306 // Use a context with painting disabled.
2307 GraphicsContext context((PlatformGraphicsContext*)0);
2308 root->setTruncatedAt((int)floorf(oldBottom));
2309 IntRect dirtyRect(0, (int)floorf(oldTop), root->rightLayoutOverflow(), (int)ceilf(oldBottom - oldTop));
2310 root->setPrintRect(dirtyRect);
2311 root->layer()->paint(&context, dirtyRect);
2312 *newBottom = root->bestTruncatedAt();
2313 if (*newBottom == 0)
2314 *newBottom = oldBottom;
2315 root->setPrintRect(IntRect());
2317 *newBottom = oldBottom;
2320 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
2322 IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
2324 // Convert from page ("absolute") to FrameView coordinates.
2325 rect.move(-scrollX(), -scrollY());
2330 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
2332 IntRect rect = viewRect;
2334 // Convert from FrameView coords into page ("absolute") coordinates.
2335 rect.move(scrollX(), scrollY());
2337 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
2338 // move the rect for now.
2339 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
2343 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
2345 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
2347 // Convert from page ("absolute") to FrameView coordinates.
2348 point.move(-scrollX(), -scrollY());
2352 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
2354 IntPoint point = viewPoint;
2356 // Convert from FrameView coords into page ("absolute") coordinates.
2357 point += IntSize(scrollX(), scrollY());
2359 return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
2362 IntRect FrameView::convertToContainingView(const IntRect& localRect) const
2364 if (const ScrollView* parentScrollView = parent()) {
2365 if (parentScrollView->isFrameView()) {
2366 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2367 // Get our renderer in the parent view
2368 RenderPart* renderer = m_frame->ownerRenderer();
2372 IntRect rect(localRect);
2373 // Add borders and padding??
2374 rect.move(renderer->borderLeft() + renderer->paddingLeft(),
2375 renderer->borderTop() + renderer->paddingTop());
2376 return parentView->convertFromRenderer(renderer, rect);
2379 return Widget::convertToContainingView(localRect);
2385 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
2387 if (const ScrollView* parentScrollView = parent()) {
2388 if (parentScrollView->isFrameView()) {
2389 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2391 // Get our renderer in the parent view
2392 RenderPart* renderer = m_frame->ownerRenderer();
2396 IntRect rect = parentView->convertToRenderer(renderer, parentRect);
2397 // Subtract borders and padding
2398 rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
2399 -renderer->borderTop() - renderer->paddingTop());
2403 return Widget::convertFromContainingView(parentRect);
2409 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
2411 if (const ScrollView* parentScrollView = parent()) {
2412 if (parentScrollView->isFrameView()) {
2413 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2415 // Get our renderer in the parent view
2416 RenderPart* renderer = m_frame->ownerRenderer();
2420 IntPoint point(localPoint);
2422 // Add borders and padding
2423 point.move(renderer->borderLeft() + renderer->paddingLeft(),
2424 renderer->borderTop() + renderer->paddingTop());
2425 return parentView->convertFromRenderer(renderer, point);
2428 return Widget::convertToContainingView(localPoint);
2434 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
2436 if (const ScrollView* parentScrollView = parent()) {
2437 if (parentScrollView->isFrameView()) {
2438 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2440 // Get our renderer in the parent view
2441 RenderPart* renderer = m_frame->ownerRenderer();
2445 IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
2446 // Subtract borders and padding
2447 point.move(-renderer->borderLeft() - renderer->paddingLeft(),
2448 -renderer->borderTop() - renderer->paddingTop());
2452 return Widget::convertFromContainingView(parentPoint);
2459 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
2461 s_deferredRepaintDelay = p;
2464 // Negative value would mean that first few repaints happen without a delay
2465 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)
2467 s_initialDeferredRepaintDelayDuringLoading = p;
2470 // The delay grows on each repaint to this maximum value
2471 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)
2473 s_maxDeferredRepaintDelayDuringLoading = p;
2476 // On each repaint the delay increases by this amount
2477 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)
2479 s_deferredRepaintDelayIncrementDuringLoading = p;
2482 } // namespace WebCore