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::avoidScrollbarCreation()
365 // with frame flattening no subframe can have scrollbars
366 // but we also cannot turn scrollbars of as we determine
367 // our flattening policy using that.
369 if (!m_frame->ownerElement())
372 if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
378 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
380 m_canHaveScrollbars = canHaveScrollbars;
381 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
384 void FrameView::updateCanHaveScrollbars()
388 scrollbarModes(hMode, vMode);
389 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
390 setCanHaveScrollbars(false);
392 setCanHaveScrollbars(true);
395 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
397 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
398 Document* doc = m_frame->document();
400 // Try the <body> element first as a scrollbar source.
401 Element* body = doc ? doc->body() : 0;
402 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
403 return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderer()->enclosingBox());
405 // If the <body> didn't have a custom style, then the root element might.
406 Element* docElement = doc ? doc->documentElement() : 0;
407 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
408 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox());
410 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
411 RenderPart* frameRenderer = m_frame->ownerRenderer();
412 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
413 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
415 // Nobody set a custom style, so we just use a native scrollbar.
416 return ScrollView::createScrollbar(orientation);
419 void FrameView::setContentsSize(const IntSize& size)
421 if (size == contentsSize())
424 m_deferSetNeedsLayouts++;
426 ScrollView::setContentsSize(size);
428 Page* page = frame() ? frame()->page() : 0;
432 page->chrome()->contentsSizeChanged(frame(), size); //notify only
434 m_deferSetNeedsLayouts--;
436 if (!m_deferSetNeedsLayouts)
437 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
440 void FrameView::adjustViewSize()
442 ASSERT(m_frame->view() == this);
443 RenderView* root = m_frame->contentRenderer();
447 setContentsSize(IntSize(root->rightLayoutOverflow(), root->bottomLayoutOverflow()));
450 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
452 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
453 // overflow:hidden and overflow:scroll on <body> as applying to the document's
454 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
455 // use the root element.
456 switch (o->style()->overflowX()) {
458 hMode = ScrollbarAlwaysOff;
461 hMode = ScrollbarAlwaysOn;
464 hMode = ScrollbarAuto;
467 // Don't set it at all.
471 switch (o->style()->overflowY()) {
473 vMode = ScrollbarAlwaysOff;
476 vMode = ScrollbarAlwaysOn;
479 vMode = ScrollbarAuto;
482 // Don't set it at all.
486 m_viewportRenderer = o;
489 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode)
491 if (m_canHaveScrollbars) {
492 hMode = ScrollbarAuto;
493 vMode = ScrollbarAuto;
495 hMode = ScrollbarAlwaysOff;
496 vMode = ScrollbarAlwaysOff;
500 Document* document = m_frame->document();
501 Node* documentElement = document->documentElement();
502 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
503 Node* body = document->body();
504 if (body && body->renderer()) {
505 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
506 #if !defined(ANDROID_FLATTEN_IFRAME) && !defined(ANDROID_FLATTEN_FRAMESET)
507 body->renderer()->setChildNeedsLayout(true);
508 vMode = ScrollbarAlwaysOff;
509 hMode = ScrollbarAlwaysOff;
511 } else if (body->hasTagName(bodyTag)) {
512 // It's sufficient to just check the X overflow,
513 // since it's illegal to have visible in only one direction.
514 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
515 applyOverflowToViewport(o, hMode, vMode);
517 } else if (rootRenderer) {
519 if (documentElement->isSVGElement()) {
520 if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight()))
521 rootRenderer->setChildNeedsLayout(true);
523 applyOverflowToViewport(rootRenderer, hMode, vMode);
525 applyOverflowToViewport(rootRenderer, hMode, vMode);
528 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
529 if (m_firstLayout && !document->ownerElement())
530 printf("Elapsed time before first layout: %d\n", document->elapsedTime());
534 HTMLFrameOwnerElement* owner = m_frame->ownerElement();
535 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
536 hMode = ScrollbarAlwaysOff;
537 vMode = ScrollbarAlwaysOff;
541 #if USE(ACCELERATED_COMPOSITING)
542 void FrameView::updateCompositingLayers()
544 RenderView* view = m_frame->contentRenderer();
548 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
549 view->compositor()->cacheAcceleratedCompositingFlags();
550 view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange);
553 void FrameView::setNeedsOneShotDrawingSynchronization()
555 Page* page = frame() ? frame()->page() : 0;
557 page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
560 #endif // USE(ACCELERATED_COMPOSITING)
562 bool FrameView::hasCompositedContent() const
564 #if USE(ACCELERATED_COMPOSITING)
565 if (RenderView* view = m_frame->contentRenderer())
566 return view->compositor()->inCompositingMode();
571 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
572 void FrameView::enterCompositingMode()
574 #if USE(ACCELERATED_COMPOSITING)
575 if (RenderView* view = m_frame->contentRenderer()) {
576 view->compositor()->enableCompositingMode();
578 view->compositor()->scheduleCompositingLayerUpdate();
583 bool FrameView::isEnclosedInCompositingLayer() const
585 #if USE(ACCELERATED_COMPOSITING)
586 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
587 return frameOwnerRenderer && frameOwnerRenderer->containerForRepaint();
593 bool FrameView::syncCompositingStateRecursive()
595 #if USE(ACCELERATED_COMPOSITING)
596 ASSERT(m_frame->view() == this);
597 RenderView* contentRenderer = m_frame->contentRenderer();
598 if (!contentRenderer)
599 return true; // We don't want to keep trying to update layers if we have no renderer.
601 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
602 // layer content to occur before layout has happened, which will cause paintContents() to bail.
606 if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer())
607 rootLayer->syncCompositingState();
609 bool allSubframesSynced = true;
610 const HashSet<RefPtr<Widget> >* viewChildren = children();
611 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
612 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
613 Widget* widget = (*current).get();
614 if (widget->isFrameView()) {
615 bool synced = static_cast<FrameView*>(widget)->syncCompositingStateRecursive();
616 allSubframesSynced &= synced;
619 return allSubframesSynced;
620 #else // USE(ACCELERATED_COMPOSITING)
625 bool FrameView::isSoftwareRenderable() const
627 #if USE(ACCELERATED_COMPOSITING)
628 RenderView* view = m_frame->contentRenderer();
632 return !view->compositor()->has3DContent();
638 void FrameView::didMoveOnscreen()
640 RenderView* view = m_frame->contentRenderer();
642 view->didMoveOnscreen();
645 void FrameView::willMoveOffscreen()
647 RenderView* view = m_frame->contentRenderer();
649 view->willMoveOffscreen();
652 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
654 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
657 void FrameView::layout(bool allowSubtree)
662 m_layoutTimer.stop();
663 m_delayedLayout = false;
664 m_setNeedsLayoutWasDeferred = false;
666 // Protect the view from being deleted during layout (in recalcStyle)
667 RefPtr<FrameView> protector(this);
670 // FIXME: Do we need to set m_size.width here?
671 // FIXME: Should we set m_size.height here too?
672 m_size.setWidth(layoutWidth());
676 // we shouldn't enter layout() while painting
677 ASSERT(!isPainting());
681 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
683 if (!allowSubtree && m_layoutRoot) {
684 m_layoutRoot->markContainingBlocksForLayout(false);
688 ASSERT(m_frame->view() == this);
690 Document* document = m_frame->document();
692 m_layoutSchedulingEnabled = false;
694 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_hasPendingPostLayoutTasks) {
695 // This is a new top-level layout. If there are any remaining tasks from the previous
696 // layout, finish them now.
697 m_inSynchronousPostLayout = true;
698 m_postLayoutTasksTimer.stop();
699 performPostLayoutTasks();
700 m_inSynchronousPostLayout = false;
703 // Viewport-dependent media queries may cause us to need completely different style information.
705 if (document->styleSelector()->affectedByViewportChange())
706 document->styleSelectorChanged(RecalcStyleImmediately);
708 // Always ensure our style info is up-to-date. This can happen in situations where
709 // the layout beats any sort of style recalc update that needs to occur.
710 document->updateStyleIfNeeded();
712 bool subtree = m_layoutRoot;
714 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
715 // so there's no point to continuing to layout
716 if (protector->hasOneRef())
719 RenderObject* root = subtree ? m_layoutRoot : document->renderer();
721 // FIXME: Do we need to set m_size here?
722 m_layoutSchedulingEnabled = true;
726 #ifdef ANDROID_INSTRUMENT
727 if (!m_frame->tree() || !m_frame->tree()->parent())
728 android::TimeCounter::start(android::TimeCounter::LayoutTimeCounter);
731 m_nestedLayoutCount++;
736 calculateScrollbarModesForLayout(hMode, vMode);
738 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
741 // Now set our scrollbar state for the layout.
742 ScrollbarMode currentHMode = horizontalScrollbarMode();
743 ScrollbarMode currentVMode = verticalScrollbarMode();
745 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
747 setScrollbarsSuppressed(true);
749 m_firstLayout = false;
750 m_firstLayoutCallbackPending = true;
751 m_lastLayoutSize = IntSize(width(), height());
752 m_lastZoomFactor = root->style()->zoom();
754 // Set the initial vMode to AlwaysOn if we're auto.
755 if (vMode == ScrollbarAuto)
756 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
757 // Set the initial hMode to AlwaysOff if we're auto.
758 if (hMode == ScrollbarAuto)
759 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
761 setScrollbarModes(hMode, vMode);
762 setScrollbarsSuppressed(false, true);
764 setScrollbarModes(hMode, vMode);
767 IntSize oldSize = m_size;
769 m_size = IntSize(layoutWidth(), layoutHeight());
771 if (oldSize != m_size) {
772 m_doFullRepaint = true;
773 if (!m_firstLayout) {
774 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
775 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
776 if (bodyRenderer && bodyRenderer->stretchesToViewport())
777 bodyRenderer->setChildNeedsLayout(true);
778 else if (rootRenderer && rootRenderer->stretchesToViewport())
779 rootRenderer->setChildNeedsLayout(true);
784 RenderLayer* layer = root->enclosingLayer();
786 pauseScheduledEvents();
788 bool disableLayoutState = false;
790 RenderView* view = root->view();
791 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
792 view->pushLayoutState(root);
793 if (disableLayoutState)
794 view->disableLayoutState();
798 beginDeferredRepaints();
800 endDeferredRepaints();
804 RenderView* view = root->view();
805 view->popLayoutState(root);
806 if (disableLayoutState)
807 view->enableLayoutState();
811 m_frame->selection()->setCaretRectNeedsUpdate();
812 m_frame->selection()->updateAppearance();
814 m_layoutSchedulingEnabled = true;
816 if (!subtree && !toRenderView(root)->printing())
819 // Now update the positions of all layers.
820 beginDeferredRepaints();
821 IntPoint cachedOffset;
822 layer->updateLayerPositions((m_doFullRepaint ? RenderLayer::DoFullRepaint : 0)
823 | RenderLayer::CheckForRepaint
824 | RenderLayer::IsCompositingUpdateRoot
825 | RenderLayer::UpdateCompositingLayers,
826 subtree ? 0 : &cachedOffset);
827 endDeferredRepaints();
829 #if USE(ACCELERATED_COMPOSITING)
830 updateCompositingLayers();
835 #if PLATFORM(MAC) || PLATFORM(CHROMIUM)
836 if (AXObjectCache::accessibilityEnabled())
837 root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true);
839 #if ENABLE(DASHBOARD_SUPPORT)
840 updateDashboardRegions();
843 #ifdef ANDROID_INSTRUMENT
844 if (!m_frame->tree()->parent())
845 android::TimeCounter::record(android::TimeCounter::LayoutTimeCounter, __FUNCTION__);
847 ASSERT(!root->needsLayout());
849 setCanBlitOnScroll(!useSlowRepaints());
851 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
852 updateOverflowStatus(layoutWidth() < contentsWidth(),
853 layoutHeight() < contentsHeight());
855 if (!m_hasPendingPostLayoutTasks) {
856 if (!m_inSynchronousPostLayout) {
857 m_inSynchronousPostLayout = true;
858 // Calls resumeScheduledEvents()
859 performPostLayoutTasks();
860 m_inSynchronousPostLayout = false;
863 if (!m_hasPendingPostLayoutTasks && (needsLayout() || m_inSynchronousPostLayout)) {
864 // If we need layout or are already in a synchronous call to postLayoutTasks(),
865 // defer widget updates and event dispatch until after we return. postLayoutTasks()
866 // can make us need to update again, and we can get stuck in a nasty cycle unless
867 // we call it through the timer here.
868 m_hasPendingPostLayoutTasks = true;
869 m_postLayoutTasksTimer.startOneShot(0);
871 pauseScheduledEvents();
876 resumeScheduledEvents();
877 ASSERT(m_enqueueEvents);
880 InspectorInstrumentation::didLayout(cookie);
882 m_nestedLayoutCount--;
885 void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object)
887 if (!m_widgetUpdateSet)
888 m_widgetUpdateSet.set(new RenderEmbeddedObjectSet);
890 m_widgetUpdateSet->add(object);
893 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object)
895 if (!m_widgetUpdateSet)
898 m_widgetUpdateSet->remove(object);
901 void FrameView::setMediaType(const String& mediaType)
903 m_mediaType = mediaType;
906 String FrameView::mediaType() const
908 // See if we have an override type.
909 String overrideType = m_frame->loader()->client()->overrideMediaType();
910 if (!overrideType.isNull())
915 void FrameView::adjustMediaTypeForPrinting(bool printing)
918 if (m_mediaTypeWhenNotPrinting.isNull())
919 m_mediaTypeWhenNotPrinting = mediaType();
920 setMediaType("print");
922 if (!m_mediaTypeWhenNotPrinting.isNull())
923 setMediaType(m_mediaTypeWhenNotPrinting);
924 m_mediaTypeWhenNotPrinting = String();
928 bool FrameView::useSlowRepaints() const
930 return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || m_isOverlapped || !m_contentIsOpaque;
933 bool FrameView::useSlowRepaintsIfNotOverlapped() const
935 return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || !m_contentIsOpaque;
938 void FrameView::setUseSlowRepaints()
940 m_useSlowRepaints = true;
941 setCanBlitOnScroll(false);
944 void FrameView::addSlowRepaintObject()
946 if (!m_slowRepaintObjectCount)
947 setCanBlitOnScroll(false);
948 m_slowRepaintObjectCount++;
951 void FrameView::removeSlowRepaintObject()
953 ASSERT(m_slowRepaintObjectCount > 0);
954 m_slowRepaintObjectCount--;
955 if (!m_slowRepaintObjectCount)
956 setCanBlitOnScroll(!useSlowRepaints());
959 void FrameView::addFixedObject()
961 if (!m_fixedObjectCount && platformWidget())
962 setCanBlitOnScroll(false);
963 ++m_fixedObjectCount;
966 void FrameView::removeFixedObject()
968 ASSERT(m_fixedObjectCount > 0);
969 --m_fixedObjectCount;
970 if (!m_fixedObjectCount)
971 setCanBlitOnScroll(!useSlowRepaints());
974 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
976 const size_t fixedObjectThreshold = 5;
978 RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0;
979 if (RenderView* root = m_frame->contentRenderer())
980 positionedObjects = root->positionedObjects();
982 if (!positionedObjects || positionedObjects->isEmpty()) {
983 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
987 // Get the rects of the fixed objects visible in the rectToScroll
988 Vector<IntRect, fixedObjectThreshold> subRectToUpdate;
989 bool updateInvalidatedSubRect = true;
990 RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
991 for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
992 RenderBox* renderBox = *it;
993 if (renderBox->style()->position() != FixedPosition)
995 IntRect updateRect = renderBox->layer()->repaintRectIncludingDescendants();
996 updateRect = contentsToWindow(updateRect);
998 updateRect.intersect(rectToScroll);
999 if (!updateRect.isEmpty()) {
1000 if (subRectToUpdate.size() >= fixedObjectThreshold) {
1001 updateInvalidatedSubRect = false;
1004 subRectToUpdate.append(updateRect);
1009 if (updateInvalidatedSubRect) {
1011 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1013 // 2) update the area of fixed objects that has been invalidated
1014 size_t fixObjectsCount = subRectToUpdate.size();
1015 for (size_t i = 0; i < fixObjectsCount; ++i) {
1016 IntRect updateRect = subRectToUpdate[i];
1017 IntRect scrolledRect = updateRect;
1018 scrolledRect.move(scrollDelta);
1019 updateRect.unite(scrolledRect);
1020 updateRect.intersect(rectToScroll);
1021 hostWindow()->invalidateContentsAndWindow(updateRect, false);
1026 // the number of fixed objects exceed the threshold, we cannot use the fast path
1030 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1032 #if USE(ACCELERATED_COMPOSITING)
1033 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1034 if (frameRenderer->containerForRepaint()) {
1035 IntRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1036 frameRenderer->borderTop() + frameRenderer->paddingTop(),
1037 visibleWidth(), visibleHeight());
1038 frameRenderer->repaintRectangle(rect);
1044 ScrollView::scrollContentsSlowPath(updateRect);
1047 // Note that this gets called at painting time.
1048 void FrameView::setIsOverlapped(bool isOverlapped)
1050 if (isOverlapped == m_isOverlapped)
1053 m_isOverlapped = isOverlapped;
1054 setCanBlitOnScroll(!useSlowRepaints());
1056 #if USE(ACCELERATED_COMPOSITING)
1057 // Overlap can affect compositing tests, so if it changes, we need to trigger
1058 // a layer update in the parent document.
1059 if (hasCompositedContent()) {
1060 if (Frame* parentFrame = m_frame->tree()->parent()) {
1061 if (RenderView* parentView = parentFrame->contentRenderer()) {
1062 RenderLayerCompositor* compositor = parentView->compositor();
1063 compositor->setCompositingLayersNeedRebuild();
1064 compositor->scheduleCompositingLayerUpdate();
1071 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1073 if (contentIsOpaque == m_contentIsOpaque)
1076 m_contentIsOpaque = contentIsOpaque;
1077 setCanBlitOnScroll(!useSlowRepaints());
1080 void FrameView::restoreScrollbar()
1082 setScrollbarsSuppressed(false);
1085 bool FrameView::scrollToFragment(const KURL& url)
1087 // If our URL has no ref, then we have no place we need to jump to.
1088 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1089 // and possibly repaint because :target pseudo class may have been
1090 // set (see bug 11321).
1091 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1094 String fragmentIdentifier = url.fragmentIdentifier();
1095 if (scrollToAnchor(fragmentIdentifier))
1098 // Try again after decoding the ref, based on the document's encoding.
1099 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1100 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1105 bool FrameView::scrollToAnchor(const String& name)
1107 ASSERT(m_frame->document());
1109 if (!m_frame->document()->haveStylesheetsLoaded()) {
1110 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1114 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1116 Element* anchorNode = m_frame->document()->findAnchor(name);
1119 if (m_frame->document()->isSVGDocument()) {
1120 if (name.startsWith("xpointer(")) {
1121 // We need to parse the xpointer reference here
1122 } else if (name.startsWith("svgView(")) {
1123 RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement();
1124 if (!svg->currentView()->parseViewSpec(name))
1126 svg->setUseCurrentView(true);
1128 if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) {
1129 RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0;
1130 if (viewElement.get()) {
1131 RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(SVGLocatable::nearestViewportElement(viewElement.get()));
1132 svg->inheritViewAttributes(viewElement.get());
1136 // FIXME: need to decide which <svg> to focus on, and zoom to that one
1137 // FIXME: need to actually "highlight" the viewTarget(s)
1141 m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target.
1143 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1144 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1147 #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR
1148 // TODO(andreip): check with Grace if this is correct.
1149 android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedAction(true);
1151 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1152 #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR
1153 android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedAction(false);
1158 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1160 m_maintainScrollPositionAnchor = anchorNode;
1161 if (!m_maintainScrollPositionAnchor)
1164 // We need to update the layout before scrolling, otherwise we could
1165 // really mess things up if an anchor scroll comes at a bad moment.
1166 m_frame->document()->updateStyleIfNeeded();
1167 // Only do a layout if changes have occurred that make it necessary.
1168 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
1174 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1176 bool wasInProgrammaticScroll = m_inProgrammaticScroll;
1177 m_inProgrammaticScroll = true;
1178 m_maintainScrollPositionAnchor = 0;
1179 ScrollView::setScrollPosition(scrollPoint);
1180 m_inProgrammaticScroll = wasInProgrammaticScroll;
1183 void FrameView::scrollPositionChangedViaPlatformWidget()
1185 repaintFixedElementsAfterScrolling();
1186 scrollPositionChanged();
1189 void FrameView::scrollPositionChanged()
1191 frame()->eventHandler()->sendScrollEvent();
1193 #if USE(ACCELERATED_COMPOSITING)
1194 if (RenderView* root = m_frame->contentRenderer()) {
1195 if (root->usesCompositing())
1196 root->compositor()->frameViewDidScroll(scrollPosition());
1201 void FrameView::repaintFixedElementsAfterScrolling()
1203 // For fixed position elements, update widget positions and compositing layers after scrolling,
1204 // but only if we're not inside of layout.
1205 if (!m_nestedLayoutCount && hasFixedObjects()) {
1206 if (RenderView* root = m_frame->contentRenderer()) {
1207 root->updateWidgetPositions();
1208 root->layer()->updateRepaintRectsAfterScroll();
1209 #if USE(ACCELERATED_COMPOSITING)
1210 root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
1216 HostWindow* FrameView::hostWindow() const
1218 Page* page = frame() ? frame()->page() : 0;
1221 return page->chrome();
1224 const unsigned cRepaintRectUnionThreshold = 25;
1226 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
1228 ASSERT(!m_frame->document()->ownerElement());
1230 double delay = adjustedDeferredRepaintDelay();
1231 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
1232 IntRect paintRect = r;
1233 if (!paintsEntireContents())
1234 paintRect.intersect(visibleContentRect());
1235 #ifdef ANDROID_CAPTURE_OFFSCREEN_PAINTS
1237 ScrollView::platformOffscreenContentRectangle(visibleContentRect(), r);
1239 if (paintRect.isEmpty())
1241 if (m_repaintCount == cRepaintRectUnionThreshold) {
1242 IntRect unionedRect;
1243 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
1244 unionedRect.unite(m_repaintRects[i]);
1245 m_repaintRects.clear();
1246 m_repaintRects.append(unionedRect);
1248 if (m_repaintCount < cRepaintRectUnionThreshold)
1249 m_repaintRects.append(paintRect);
1251 m_repaintRects[0].unite(paintRect);
1254 if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive())
1255 m_deferredRepaintTimer.startOneShot(delay);
1259 if (!immediate && isOffscreen() && !shouldUpdateWhileOffscreen())
1262 #if ENABLE(TILED_BACKING_STORE)
1263 if (frame()->tiledBackingStore()) {
1264 frame()->tiledBackingStore()->invalidate(r);
1268 ScrollView::repaintContentRectangle(r, immediate);
1271 void FrameView::visibleContentsResized()
1273 // We check to make sure the view is attached to a frame() as this method can
1274 // be triggered before the view is attached by Frame::createView(...) setting
1275 // various values such as setScrollBarModes(...) for example. An ASSERT is
1276 // triggered when a view is layout before being attached to a frame().
1277 if (!frame()->view())
1284 void FrameView::beginDeferredRepaints()
1286 Page* page = m_frame->page();
1287 if (page->mainFrame() != m_frame)
1288 return page->mainFrame()->view()->beginDeferredRepaints();
1290 m_deferringRepaints++;
1294 void FrameView::endDeferredRepaints()
1296 Page* page = m_frame->page();
1297 if (page->mainFrame() != m_frame)
1298 return page->mainFrame()->view()->endDeferredRepaints();
1300 ASSERT(m_deferringRepaints > 0);
1302 if (--m_deferringRepaints)
1305 if (m_deferredRepaintTimer.isActive())
1308 if (double delay = adjustedDeferredRepaintDelay()) {
1309 m_deferredRepaintTimer.startOneShot(delay);
1313 doDeferredRepaints();
1316 void FrameView::checkStopDelayingDeferredRepaints()
1318 if (!m_deferredRepaintTimer.isActive())
1321 Document* document = m_frame->document();
1322 if (document && (document->parsing() || document->cachedResourceLoader()->requestCount()))
1325 m_deferredRepaintTimer.stop();
1327 doDeferredRepaints();
1330 void FrameView::doDeferredRepaints()
1332 ASSERT(!m_deferringRepaints);
1333 if (isOffscreen() && !shouldUpdateWhileOffscreen()) {
1334 m_repaintRects.clear();
1338 unsigned size = m_repaintRects.size();
1339 for (unsigned i = 0; i < size; i++) {
1340 #if ENABLE(TILED_BACKING_STORE)
1341 if (frame()->tiledBackingStore()) {
1342 frame()->tiledBackingStore()->invalidate(m_repaintRects[i]);
1346 ScrollView::repaintContentRectangle(m_repaintRects[i], false);
1348 m_repaintRects.clear();
1351 updateDeferredRepaintDelay();
1354 void FrameView::updateDeferredRepaintDelay()
1356 Document* document = m_frame->document();
1357 if (!document || (!document->parsing() && !document->cachedResourceLoader()->requestCount())) {
1358 m_deferredRepaintDelay = s_deferredRepaintDelay;
1361 if (m_deferredRepaintDelay < s_maxDeferredRepaintDelayDuringLoading) {
1362 m_deferredRepaintDelay += s_deferredRepaintDelayIncrementDuringLoading;
1363 if (m_deferredRepaintDelay > s_maxDeferredRepaintDelayDuringLoading)
1364 m_deferredRepaintDelay = s_maxDeferredRepaintDelayDuringLoading;
1368 void FrameView::resetDeferredRepaintDelay()
1370 m_deferredRepaintDelay = 0;
1371 if (m_deferredRepaintTimer.isActive()) {
1372 m_deferredRepaintTimer.stop();
1373 if (!m_deferringRepaints)
1374 doDeferredRepaints();
1378 double FrameView::adjustedDeferredRepaintDelay() const
1380 if (!m_deferredRepaintDelay)
1382 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
1383 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
1386 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
1388 doDeferredRepaints();
1391 void FrameView::layoutTimerFired(Timer<FrameView>*)
1393 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1394 if (!m_frame->document()->ownerElement())
1395 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
1400 void FrameView::scheduleRelayout()
1402 // FIXME: We should assert the page is not in the page cache, but that is causing
1403 // too many false assertions. See <rdar://problem/7218118>.
1404 ASSERT(m_frame->view() == this);
1407 m_layoutRoot->markContainingBlocksForLayout(false);
1410 if (!m_layoutSchedulingEnabled)
1414 if (!m_frame->document()->shouldScheduleLayout())
1417 #if defined(ANDROID_FLATTEN_IFRAME) || defined(ANDROID_FLATTEN_FRAMESET)
1418 // This is the Android frame flattening code. The common code below is not
1419 // used as frameSetFlatteningEnabled() is false on Android.
1420 if (m_frame->ownerRenderer())
1421 m_frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc();
1424 // When frame flattening is enabled, the contents of the frame affects layout of the parent frames.
1425 // Also invalidate parent frame starting from the owner element of this frame.
1426 if (m_frame->settings() && m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) {
1427 if (m_frame->ownerElement()->hasTagName(iframeTag) || m_frame->ownerElement()->hasTagName(frameTag))
1428 m_frame->ownerRenderer()->setNeedsLayout(true, true);
1431 int delay = m_frame->document()->minimumLayoutDelay();
1432 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
1433 unscheduleRelayout();
1434 if (m_layoutTimer.isActive())
1437 m_delayedLayout = delay != 0;
1439 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1440 if (!m_frame->document()->ownerElement())
1441 printf("Scheduling layout for %d\n", delay);
1444 m_layoutTimer.startOneShot(delay * 0.001);
1447 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
1449 for (RenderObject* r = descendant; r; r = r->container()) {
1456 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
1458 ASSERT(m_frame->view() == this);
1460 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) {
1462 relayoutRoot->markContainingBlocksForLayout(false);
1466 if (layoutPending() || !m_layoutSchedulingEnabled) {
1467 if (m_layoutRoot != relayoutRoot) {
1468 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
1469 // Keep the current root
1470 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
1471 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
1472 // Re-root at relayoutRoot
1473 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
1474 m_layoutRoot = relayoutRoot;
1476 // Just do a full relayout
1478 m_layoutRoot->markContainingBlocksForLayout(false);
1480 relayoutRoot->markContainingBlocksForLayout(false);
1483 } else if (m_layoutSchedulingEnabled) {
1484 int delay = m_frame->document()->minimumLayoutDelay();
1485 m_layoutRoot = relayoutRoot;
1486 m_delayedLayout = delay != 0;
1487 m_layoutTimer.startOneShot(delay * 0.001);
1491 bool FrameView::layoutPending() const
1493 return m_layoutTimer.isActive();
1496 bool FrameView::needsLayout() const
1498 // This can return true in cases where the document does not have a body yet.
1499 // Document::shouldScheduleLayout takes care of preventing us from scheduling
1500 // layout in that case.
1503 RenderView* root = m_frame->contentRenderer();
1504 return layoutPending()
1505 || (root && root->needsLayout())
1507 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
1510 void FrameView::setNeedsLayout()
1512 if (m_deferSetNeedsLayouts) {
1513 m_setNeedsLayoutWasDeferred = true;
1516 RenderView* root = m_frame->contentRenderer();
1518 root->setNeedsLayout(true);
1521 void FrameView::unscheduleRelayout()
1523 m_postLayoutTasksTimer.stop();
1525 if (!m_layoutTimer.isActive())
1528 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1529 if (!m_frame->document()->ownerElement())
1530 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
1533 m_layoutTimer.stop();
1534 m_delayedLayout = false;
1537 bool FrameView::isTransparent() const
1539 return m_isTransparent;
1542 void FrameView::setTransparent(bool isTransparent)
1544 m_isTransparent = isTransparent;
1547 Color FrameView::baseBackgroundColor() const
1549 return m_baseBackgroundColor;
1552 void FrameView::setBaseBackgroundColor(Color bc)
1556 m_baseBackgroundColor = bc;
1559 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
1561 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1562 FrameView* view = frame->view();
1566 view->setTransparent(transparent);
1567 view->setBaseBackgroundColor(backgroundColor);
1571 bool FrameView::shouldUpdateWhileOffscreen() const
1573 return m_shouldUpdateWhileOffscreen;
1576 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
1578 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
1581 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
1583 if (!m_enqueueEvents) {
1584 ExceptionCode ec = 0;
1585 eventTarget->dispatchEvent(event, ec);
1589 ScheduledEvent* scheduledEvent = new ScheduledEvent;
1590 scheduledEvent->m_event = event;
1591 scheduledEvent->m_eventTarget = eventTarget;
1592 m_scheduledEvents.append(scheduledEvent);
1595 void FrameView::pauseScheduledEvents()
1597 ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
1601 void FrameView::resumeScheduledEvents()
1604 if (!m_enqueueEvents)
1605 dispatchScheduledEvents();
1606 ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
1609 void FrameView::scrollToAnchor()
1611 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
1615 if (!anchorNode->renderer())
1619 if (anchorNode != m_frame->document())
1620 rect = anchorNode->getRect();
1622 // Scroll nested layers and frames to reveal the anchor.
1623 // Align to the top and to the closest side (this matches other browsers).
1624 anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
1626 if (AXObjectCache::accessibilityEnabled())
1627 m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get());
1629 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
1630 m_maintainScrollPositionAnchor = anchorNode;
1633 void FrameView::updateWidget(RenderEmbeddedObject* object)
1635 ASSERT(!object->node() || object->node()->isElementNode());
1636 Element* ownerElement = static_cast<Element*>(object->node());
1637 // The object may have already been destroyed (thus node cleared),
1638 // but FrameView holds a manual ref, so it won't have been deleted.
1639 ASSERT(m_widgetUpdateSet->contains(object));
1643 // No need to update if it's already crashed or known to be missing.
1644 if (object->pluginCrashedOrWasMissing())
1647 // FIXME: This could turn into a real virtual dispatch if we defined
1648 // updateWidget(bool) on HTMLElement.
1649 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag))
1650 static_cast<HTMLPlugInImageElement*>(ownerElement)->updateWidget(false);
1651 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
1652 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1653 else if (ownerElement->hasTagName(videoTag) || ownerElement->hasTagName(audioTag))
1654 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(false);
1657 ASSERT_NOT_REACHED();
1659 // Caution: it's possible the object was destroyed again, since loading a
1660 // plugin may run any arbitrary javascript.
1661 object->updateWidgetPosition();
1664 bool FrameView::updateWidgets()
1666 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
1669 size_t size = m_widgetUpdateSet->size();
1671 Vector<RenderEmbeddedObject*> objects;
1672 objects.reserveCapacity(size);
1674 RenderEmbeddedObjectSet::const_iterator end = m_widgetUpdateSet->end();
1675 for (RenderEmbeddedObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
1676 objects.uncheckedAppend(*it);
1680 for (size_t i = 0; i < size; ++i) {
1681 RenderEmbeddedObject* object = objects[i];
1682 updateWidget(object);
1683 m_widgetUpdateSet->remove(object);
1686 RenderArena* arena = m_frame->document()->renderArena();
1687 for (size_t i = 0; i < size; ++i)
1688 objects[i]->deref(arena);
1690 return m_widgetUpdateSet->isEmpty();
1693 void FrameView::performPostLayoutTasks()
1695 m_hasPendingPostLayoutTasks = false;
1697 if (m_firstLayoutCallbackPending) {
1698 m_firstLayoutCallbackPending = false;
1699 m_frame->loader()->didFirstLayout();
1702 if (m_isVisuallyNonEmpty && m_firstVisuallyNonEmptyLayoutCallbackPending) {
1703 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
1704 m_frame->loader()->didFirstVisuallyNonEmptyLayout();
1707 RenderView* root = m_frame->contentRenderer();
1709 root->updateWidgetPositions();
1711 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
1712 if (updateWidgets())
1718 resumeScheduledEvents();
1720 if (!root->printing()) {
1721 IntSize currentSize = IntSize(width(), height());
1722 float currentZoomFactor = root->style()->zoom();
1723 bool resized = !m_firstLayout && (currentSize != m_lastLayoutSize || currentZoomFactor != m_lastZoomFactor);
1724 m_lastLayoutSize = currentSize;
1725 m_lastZoomFactor = currentZoomFactor;
1727 m_frame->eventHandler()->sendResizeEvent();
1731 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
1733 performPostLayoutTasks();
1736 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
1738 if (!m_viewportRenderer)
1741 if (m_overflowStatusDirty) {
1742 m_horizontalOverflow = horizontalOverflow;
1743 m_verticalOverflow = verticalOverflow;
1744 m_overflowStatusDirty = false;
1748 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
1749 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
1751 if (horizontalOverflowChanged || verticalOverflowChanged) {
1752 m_horizontalOverflow = horizontalOverflow;
1753 m_verticalOverflow = verticalOverflow;
1755 scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
1756 verticalOverflowChanged, verticalOverflow),
1757 m_viewportRenderer->node());
1762 void FrameView::dispatchScheduledEvents()
1764 if (m_scheduledEvents.isEmpty())
1767 Vector<ScheduledEvent*> scheduledEventsCopy = m_scheduledEvents;
1768 m_scheduledEvents.clear();
1770 Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end();
1771 for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) {
1772 ScheduledEvent* scheduledEvent = *it;
1774 ExceptionCode ec = 0;
1776 // Only dispatch events to nodes that are in the document
1777 if (scheduledEvent->m_eventTarget->inDocument())
1778 scheduledEvent->m_eventTarget->dispatchEvent(scheduledEvent->m_event, ec);
1780 delete scheduledEvent;
1784 IntRect FrameView::windowClipRect(bool clipToContents) const
1786 ASSERT(m_frame->view() == this);
1788 // Set our clip rect to be our contents.
1789 IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
1790 if (!m_frame || !m_frame->document() || !m_frame->document()->ownerElement())
1793 // Take our owner element and get the clip rect from the enclosing layer.
1794 Element* elt = m_frame->document()->ownerElement();
1795 RenderLayer* layer = elt->renderer()->enclosingLayer();
1796 // FIXME: layer should never be null, but sometimes seems to be anyway.
1799 FrameView* parentView = elt->document()->view();
1800 clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
1804 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const
1806 // If we have no layer, just return our window clip rect.
1808 return windowClipRect();
1810 // Apply the clip from the layer.
1812 if (clipToLayerContents)
1813 clipRect = layer->childrenClipRect();
1815 clipRect = layer->selfClipRect();
1816 clipRect = contentsToWindow(clipRect);
1817 return intersection(clipRect, windowClipRect());
1820 bool FrameView::isActive() const
1822 Page* page = frame()->page();
1823 return page && page->focusController()->isActive();
1826 void FrameView::valueChanged(Scrollbar* bar)
1828 // Figure out if we really moved.
1829 IntSize offset = scrollOffset();
1830 ScrollView::valueChanged(bar);
1831 if (offset != scrollOffset())
1832 scrollPositionChanged();
1833 frame()->loader()->client()->didChangeScrollOffset();
1836 void FrameView::valueChanged(const IntSize& scrollDelta)
1838 ScrollView::valueChanged(scrollDelta);
1839 frame()->eventHandler()->sendScrollEvent();
1840 frame()->loader()->client()->didChangeScrollOffset();
1843 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
1845 // Add in our offset within the FrameView.
1846 IntRect dirtyRect = rect;
1847 dirtyRect.move(scrollbar->x(), scrollbar->y());
1848 invalidateRect(dirtyRect);
1851 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
1853 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
1856 IntRect FrameView::windowResizerRect() const
1858 Page* page = frame() ? frame()->page() : 0;
1861 return page->chrome()->windowResizerRect();
1864 #if ENABLE(DASHBOARD_SUPPORT)
1865 void FrameView::updateDashboardRegions()
1867 Document* document = m_frame->document();
1868 if (!document->hasDashboardRegions())
1870 Vector<DashboardRegionValue> newRegions;
1871 document->renderBox()->collectDashboardRegions(newRegions);
1872 if (newRegions == document->dashboardRegions())
1874 document->setDashboardRegions(newRegions);
1875 Page* page = m_frame->page();
1878 page->chrome()->client()->dashboardRegionsChanged();
1882 void FrameView::invalidateScrollCorner()
1884 invalidateRect(scrollCornerRect());
1887 void FrameView::updateScrollCorner()
1889 RenderObject* renderer = 0;
1890 RefPtr<RenderStyle> cornerStyle;
1892 if (!scrollCornerRect().isEmpty()) {
1893 // Try the <body> element first as a scroll corner source.
1894 Document* doc = m_frame->document();
1895 Element* body = doc ? doc->body() : 0;
1896 if (body && body->renderer()) {
1897 renderer = body->renderer();
1898 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
1902 // If the <body> didn't have a custom style, then the root element might.
1903 Element* docElement = doc ? doc->documentElement() : 0;
1904 if (docElement && docElement->renderer()) {
1905 renderer = docElement->renderer();
1906 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
1911 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
1912 if (RenderPart* renderer = m_frame->ownerRenderer())
1913 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
1918 if (!m_scrollCorner)
1919 m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document());
1920 m_scrollCorner->setStyle(cornerStyle.release());
1921 invalidateRect(scrollCornerRect());
1922 } else if (m_scrollCorner) {
1923 m_scrollCorner->destroy();
1928 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
1930 if (context->updatingControlTints()) {
1931 updateScrollCorner();
1935 if (m_scrollCorner) {
1936 m_scrollCorner->paintIntoRect(context, cornerRect.x(), cornerRect.y(), cornerRect);
1940 ScrollView::paintScrollCorner(context, cornerRect);
1943 bool FrameView::hasCustomScrollbars() const
1945 const HashSet<RefPtr<Widget> >* viewChildren = children();
1946 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
1947 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
1948 Widget* widget = current->get();
1949 if (widget->isFrameView()) {
1950 if (static_cast<FrameView*>(widget)->hasCustomScrollbars())
1952 } else if (widget->isScrollbar()) {
1953 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
1954 if (scrollbar->isCustomScrollbar())
1962 void FrameView::updateControlTints()
1964 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
1965 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
1966 // This is only done if the theme supports control tinting. It's up to the theme and platform
1967 // to define when controls get the tint and to call this function when that changes.
1969 // Optimize the common case where we bring a window to the front while it's still empty.
1970 if (!m_frame || m_frame->loader()->url().isEmpty())
1973 if ((m_frame->contentRenderer() && m_frame->contentRenderer()->theme()->supportsControlTints()) || hasCustomScrollbars()) {
1976 PlatformGraphicsContext* const noContext = 0;
1977 GraphicsContext context(noContext);
1978 context.setUpdatingControlTints(true);
1979 if (platformWidget())
1980 paintContents(&context, visibleContentRect());
1982 paint(&context, frameRect());
1986 bool FrameView::wasScrolledByUser() const
1988 return m_wasScrolledByUser;
1991 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
1993 if (m_inProgrammaticScroll)
1995 m_maintainScrollPositionAnchor = 0;
1996 m_wasScrolledByUser = wasScrolledByUser;
1999 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
2004 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get(), rect);
2006 Document* document = frame()->document();
2010 if (document->printing())
2011 fillWithRed = false; // Printing, don't fill with red (can't remember why).
2012 else if (document->ownerElement())
2013 fillWithRed = false; // Subframe, don't fill with red.
2014 else if (isTransparent())
2015 fillWithRed = false; // Transparent, don't fill with red.
2016 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
2017 fillWithRed = false; // Selections are transparent, don't fill with red.
2018 else if (m_nodeToDraw)
2019 fillWithRed = false; // Element images are transparent, don't fill with red.
2024 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
2027 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
2028 if (isTopLevelPainter)
2029 sCurrentPaintTimeStamp = currentTime();
2031 RenderView* contentRenderer = frame()->contentRenderer();
2032 if (!contentRenderer) {
2033 LOG_ERROR("called FrameView::paint with nil renderer");
2037 ASSERT(!needsLayout());
2041 #if USE(ACCELERATED_COMPOSITING)
2042 if (!p->paintingDisabled()) {
2043 if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer())
2044 rootLayer->syncCompositingState();
2048 ASSERT(!m_isPainting);
2050 m_isPainting = true;
2052 // m_nodeToDraw is used to draw only one element (and its descendants)
2053 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
2055 PaintBehavior oldPaintBehavior = m_paintBehavior;
2056 if (m_paintBehavior == PaintBehaviorNormal)
2057 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
2059 if (document->printing())
2060 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2062 contentRenderer->layer()->paint(p, rect, m_paintBehavior, eltRenderer);
2064 m_paintBehavior = oldPaintBehavior;
2066 m_isPainting = false;
2067 m_lastPaintTime = currentTime();
2069 #if ENABLE(DASHBOARD_SUPPORT)
2070 // Regions may have changed as a result of the visibility/z-index of element changing.
2071 if (document->dashboardRegionsDirty())
2072 updateDashboardRegions();
2075 if (isTopLevelPainter)
2076 sCurrentPaintTimeStamp = 0;
2078 InspectorInstrumentation::didPaint(cookie);
2081 void FrameView::setPaintBehavior(PaintBehavior behavior)
2083 m_paintBehavior = behavior;
2086 PaintBehavior FrameView::paintBehavior() const
2088 return m_paintBehavior;
2091 bool FrameView::isPainting() const
2093 return m_isPainting;
2096 void FrameView::setNodeToDraw(Node* node)
2098 m_nodeToDraw = node;
2101 void FrameView::updateLayoutAndStyleIfNeededRecursive()
2103 // We have to crawl our entire tree looking for any FrameViews that need
2104 // layout and make sure they are up to date.
2105 // Mac actually tests for intersection with the dirty region and tries not to
2106 // update layout for frames that are outside the dirty region. Not only does this seem
2107 // pointless (since those frames will have set a zero timer to layout anyway), but
2108 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
2109 // region but then become included later by the second frame adding rects to the dirty region
2110 // when it lays out.
2112 m_frame->document()->updateStyleIfNeeded();
2117 const HashSet<RefPtr<Widget> >* viewChildren = children();
2118 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2119 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2120 Widget* widget = (*current).get();
2121 if (widget->isFrameView())
2122 static_cast<FrameView*>(widget)->updateLayoutAndStyleIfNeededRecursive();
2125 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
2126 // painting, so we need to flush out any deferred repaints too.
2127 flushDeferredRepaints();
2130 void FrameView::flushDeferredRepaints()
2132 if (!m_deferredRepaintTimer.isActive())
2134 m_deferredRepaintTimer.stop();
2135 doDeferredRepaints();
2138 void FrameView::forceLayout(bool allowSubtree)
2140 layout(allowSubtree);
2143 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximumShrinkFactor, Frame::AdjustViewSizeOrNot shouldAdjustViewSize)
2145 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
2146 // the state of things before and after the layout
2147 RenderView *root = toRenderView(m_frame->document()->renderer());
2149 int pageW = ceilf(pageSize.width());
2150 root->setWidth(pageW);
2151 root->setPageHeight(pageSize.height());
2152 root->setNeedsLayoutAndPrefWidthsRecalc();
2155 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
2156 // page width when shrunk, we will lay out at maximum shrink and clip extra content.
2157 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
2158 // implementation should not do this!
2159 int rightmostPos = root->rightmostPosition();
2160 if (rightmostPos > pageSize.width()) {
2161 pageW = std::min<int>(rightmostPos, ceilf(pageSize.width() * maximumShrinkFactor));
2162 if (pageSize.height())
2163 root->setPageHeight(pageW / pageSize.width() * pageSize.height());
2164 root->setWidth(pageW);
2165 root->setNeedsLayoutAndPrefWidthsRecalc();
2167 int docHeight = root->bottomLayoutOverflow();
2168 root->clearLayoutOverflow();
2169 root->addLayoutOverflow(IntRect(0, 0, pageW, docHeight)); // This is how we clip in case we overflow again.
2173 if (shouldAdjustViewSize)
2177 void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
2179 RenderView* root = m_frame->contentRenderer();
2181 // Use a context with painting disabled.
2182 GraphicsContext context((PlatformGraphicsContext*)0);
2183 root->setTruncatedAt((int)floorf(oldBottom));
2184 IntRect dirtyRect(0, (int)floorf(oldTop), root->rightLayoutOverflow(), (int)ceilf(oldBottom - oldTop));
2185 root->setPrintRect(dirtyRect);
2186 root->layer()->paint(&context, dirtyRect);
2187 *newBottom = root->bestTruncatedAt();
2188 if (*newBottom == 0)
2189 *newBottom = oldBottom;
2190 root->setPrintRect(IntRect());
2192 *newBottom = oldBottom;
2195 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
2197 IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
2199 // Convert from page ("absolute") to FrameView coordinates.
2200 rect.move(-scrollX(), -scrollY());
2205 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
2207 IntRect rect = viewRect;
2209 // Convert from FrameView coords into page ("absolute") coordinates.
2210 rect.move(scrollX(), scrollY());
2212 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
2213 // move the rect for now.
2214 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
2218 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
2220 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
2222 // Convert from page ("absolute") to FrameView coordinates.
2223 point.move(-scrollX(), -scrollY());
2227 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
2229 IntPoint point = viewPoint;
2231 // Convert from FrameView coords into page ("absolute") coordinates.
2232 point += IntSize(scrollX(), scrollY());
2234 return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
2237 IntRect FrameView::convertToContainingView(const IntRect& localRect) const
2239 if (const ScrollView* parentScrollView = parent()) {
2240 if (parentScrollView->isFrameView()) {
2241 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2242 // Get our renderer in the parent view
2243 RenderPart* renderer = m_frame->ownerRenderer();
2247 IntRect rect(localRect);
2248 // Add borders and padding??
2249 rect.move(renderer->borderLeft() + renderer->paddingLeft(),
2250 renderer->borderTop() + renderer->paddingTop());
2251 return parentView->convertFromRenderer(renderer, rect);
2254 return Widget::convertToContainingView(localRect);
2260 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
2262 if (const ScrollView* parentScrollView = parent()) {
2263 if (parentScrollView->isFrameView()) {
2264 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2266 // Get our renderer in the parent view
2267 RenderPart* renderer = m_frame->ownerRenderer();
2271 IntRect rect = parentView->convertToRenderer(renderer, parentRect);
2272 // Subtract borders and padding
2273 rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
2274 -renderer->borderTop() - renderer->paddingTop());
2278 return Widget::convertFromContainingView(parentRect);
2284 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
2286 if (const ScrollView* parentScrollView = parent()) {
2287 if (parentScrollView->isFrameView()) {
2288 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2290 // Get our renderer in the parent view
2291 RenderPart* renderer = m_frame->ownerRenderer();
2295 IntPoint point(localPoint);
2297 // Add borders and padding
2298 point.move(renderer->borderLeft() + renderer->paddingLeft(),
2299 renderer->borderTop() + renderer->paddingTop());
2300 return parentView->convertFromRenderer(renderer, point);
2303 return Widget::convertToContainingView(localPoint);
2309 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
2311 if (const ScrollView* parentScrollView = parent()) {
2312 if (parentScrollView->isFrameView()) {
2313 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2315 // Get our renderer in the parent view
2316 RenderPart* renderer = m_frame->ownerRenderer();
2320 IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
2321 // Subtract borders and padding
2322 point.move(-renderer->borderLeft() - renderer->paddingLeft(),
2323 -renderer->borderTop() - renderer->paddingTop());
2327 return Widget::convertFromContainingView(parentPoint);
2334 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
2336 s_deferredRepaintDelay = p;
2339 // Negative value would mean that first few repaints happen without a delay
2340 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)
2342 s_initialDeferredRepaintDelayDuringLoading = p;
2345 // The delay grows on each repaint to this maximum value
2346 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)
2348 s_maxDeferredRepaintDelayDuringLoading = p;
2351 // On each repaint the delay increases by this amount
2352 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)
2354 s_deferredRepaintDelayIncrementDuringLoading = p;
2357 } // namespace WebCore