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 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
513 body->renderer()->setChildNeedsLayout(true);
514 // It's sufficient to just check the X overflow,
515 // since it's illegal to have visible in only one direction.
516 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
517 applyOverflowToViewport(o, hMode, vMode);
519 } else if (rootRenderer) {
521 if (documentElement->isSVGElement()) {
522 if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight()))
523 rootRenderer->setChildNeedsLayout(true);
525 applyOverflowToViewport(rootRenderer, hMode, vMode);
527 applyOverflowToViewport(rootRenderer, hMode, vMode);
530 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
531 if (m_firstLayout && !document->ownerElement())
532 printf("Elapsed time before first layout: %d\n", document->elapsedTime());
536 HTMLFrameOwnerElement* owner = m_frame->ownerElement();
537 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
538 hMode = ScrollbarAlwaysOff;
539 vMode = ScrollbarAlwaysOff;
543 #if USE(ACCELERATED_COMPOSITING)
544 void FrameView::updateCompositingLayers()
546 RenderView* view = m_frame->contentRenderer();
550 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
551 view->compositor()->cacheAcceleratedCompositingFlags();
552 view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange);
555 void FrameView::setNeedsOneShotDrawingSynchronization()
557 Page* page = frame() ? frame()->page() : 0;
559 page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
562 #endif // USE(ACCELERATED_COMPOSITING)
564 bool FrameView::hasCompositedContent() const
566 #if USE(ACCELERATED_COMPOSITING)
567 if (RenderView* view = m_frame->contentRenderer())
568 return view->compositor()->inCompositingMode();
573 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
574 void FrameView::enterCompositingMode()
576 #if USE(ACCELERATED_COMPOSITING)
577 if (RenderView* view = m_frame->contentRenderer()) {
578 view->compositor()->enableCompositingMode();
580 view->compositor()->scheduleCompositingLayerUpdate();
585 bool FrameView::isEnclosedInCompositingLayer() const
587 #if USE(ACCELERATED_COMPOSITING)
588 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
589 return frameOwnerRenderer && frameOwnerRenderer->containerForRepaint();
595 bool FrameView::syncCompositingStateRecursive()
597 #if USE(ACCELERATED_COMPOSITING)
598 ASSERT(m_frame->view() == this);
599 RenderView* contentRenderer = m_frame->contentRenderer();
600 if (!contentRenderer)
601 return true; // We don't want to keep trying to update layers if we have no renderer.
603 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
604 // layer content to occur before layout has happened, which will cause paintContents() to bail.
608 if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer())
609 rootLayer->syncCompositingState();
611 bool allSubframesSynced = true;
612 const HashSet<RefPtr<Widget> >* viewChildren = children();
613 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
614 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
615 Widget* widget = (*current).get();
616 if (widget->isFrameView()) {
617 bool synced = static_cast<FrameView*>(widget)->syncCompositingStateRecursive();
618 allSubframesSynced &= synced;
621 return allSubframesSynced;
622 #else // USE(ACCELERATED_COMPOSITING)
627 bool FrameView::isSoftwareRenderable() const
629 #if USE(ACCELERATED_COMPOSITING)
630 RenderView* view = m_frame->contentRenderer();
634 return !view->compositor()->has3DContent();
640 void FrameView::didMoveOnscreen()
642 RenderView* view = m_frame->contentRenderer();
644 view->didMoveOnscreen();
647 void FrameView::willMoveOffscreen()
649 RenderView* view = m_frame->contentRenderer();
651 view->willMoveOffscreen();
654 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
656 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
659 void FrameView::layout(bool allowSubtree)
664 m_layoutTimer.stop();
665 m_delayedLayout = false;
666 m_setNeedsLayoutWasDeferred = false;
668 // Protect the view from being deleted during layout (in recalcStyle)
669 RefPtr<FrameView> protector(this);
672 // FIXME: Do we need to set m_size.width here?
673 // FIXME: Should we set m_size.height here too?
674 m_size.setWidth(layoutWidth());
678 // we shouldn't enter layout() while painting
679 ASSERT(!isPainting());
683 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
685 if (!allowSubtree && m_layoutRoot) {
686 m_layoutRoot->markContainingBlocksForLayout(false);
690 ASSERT(m_frame->view() == this);
692 Document* document = m_frame->document();
694 m_layoutSchedulingEnabled = false;
696 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_hasPendingPostLayoutTasks) {
697 // This is a new top-level layout. If there are any remaining tasks from the previous
698 // layout, finish them now.
699 m_inSynchronousPostLayout = true;
700 m_postLayoutTasksTimer.stop();
701 performPostLayoutTasks();
702 m_inSynchronousPostLayout = false;
705 // Viewport-dependent media queries may cause us to need completely different style information.
707 if (document->styleSelector()->affectedByViewportChange())
708 document->styleSelectorChanged(RecalcStyleImmediately);
710 // Always ensure our style info is up-to-date. This can happen in situations where
711 // the layout beats any sort of style recalc update that needs to occur.
712 document->updateStyleIfNeeded();
714 bool subtree = m_layoutRoot;
716 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
717 // so there's no point to continuing to layout
718 if (protector->hasOneRef())
721 RenderObject* root = subtree ? m_layoutRoot : document->renderer();
723 // FIXME: Do we need to set m_size here?
724 m_layoutSchedulingEnabled = true;
728 #ifdef ANDROID_INSTRUMENT
729 if (!m_frame->tree() || !m_frame->tree()->parent())
730 android::TimeCounter::start(android::TimeCounter::LayoutTimeCounter);
733 m_nestedLayoutCount++;
738 calculateScrollbarModesForLayout(hMode, vMode);
740 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
743 // Now set our scrollbar state for the layout.
744 ScrollbarMode currentHMode = horizontalScrollbarMode();
745 ScrollbarMode currentVMode = verticalScrollbarMode();
747 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
749 setScrollbarsSuppressed(true);
751 m_firstLayout = false;
752 m_firstLayoutCallbackPending = true;
753 m_lastLayoutSize = IntSize(width(), height());
754 m_lastZoomFactor = root->style()->zoom();
756 // Set the initial vMode to AlwaysOn if we're auto.
757 if (vMode == ScrollbarAuto)
758 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
759 // Set the initial hMode to AlwaysOff if we're auto.
760 if (hMode == ScrollbarAuto)
761 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
763 setScrollbarModes(hMode, vMode);
764 setScrollbarsSuppressed(false, true);
766 setScrollbarModes(hMode, vMode);
769 IntSize oldSize = m_size;
771 m_size = IntSize(layoutWidth(), layoutHeight());
773 if (oldSize != m_size)
774 m_doFullRepaint = true;
777 RenderLayer* layer = root->enclosingLayer();
779 pauseScheduledEvents();
781 bool disableLayoutState = false;
783 RenderView* view = root->view();
784 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
785 view->pushLayoutState(root);
786 if (disableLayoutState)
787 view->disableLayoutState();
791 beginDeferredRepaints();
793 endDeferredRepaints();
797 RenderView* view = root->view();
798 view->popLayoutState(root);
799 if (disableLayoutState)
800 view->enableLayoutState();
804 m_frame->selection()->setCaretRectNeedsUpdate();
805 m_frame->selection()->updateAppearance();
807 m_layoutSchedulingEnabled = true;
809 if (!subtree && !toRenderView(root)->printing())
812 // Now update the positions of all layers.
813 beginDeferredRepaints();
814 IntPoint cachedOffset;
815 layer->updateLayerPositions((m_doFullRepaint ? RenderLayer::DoFullRepaint : 0)
816 | RenderLayer::CheckForRepaint
817 | RenderLayer::IsCompositingUpdateRoot
818 | RenderLayer::UpdateCompositingLayers,
819 subtree ? 0 : &cachedOffset);
820 endDeferredRepaints();
822 #if USE(ACCELERATED_COMPOSITING)
823 updateCompositingLayers();
828 #if PLATFORM(MAC) || PLATFORM(CHROMIUM)
829 if (AXObjectCache::accessibilityEnabled())
830 root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true);
832 #if ENABLE(DASHBOARD_SUPPORT)
833 updateDashboardRegions();
836 #ifdef ANDROID_INSTRUMENT
837 if (!m_frame->tree()->parent())
838 android::TimeCounter::record(android::TimeCounter::LayoutTimeCounter, __FUNCTION__);
840 ASSERT(!root->needsLayout());
842 setCanBlitOnScroll(!useSlowRepaints());
844 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
845 updateOverflowStatus(layoutWidth() < contentsWidth(),
846 layoutHeight() < contentsHeight());
848 if (!m_hasPendingPostLayoutTasks) {
849 if (!m_inSynchronousPostLayout) {
850 m_inSynchronousPostLayout = true;
851 // Calls resumeScheduledEvents()
852 performPostLayoutTasks();
853 m_inSynchronousPostLayout = false;
856 if (!m_hasPendingPostLayoutTasks && (needsLayout() || m_inSynchronousPostLayout)) {
857 // If we need layout or are already in a synchronous call to postLayoutTasks(),
858 // defer widget updates and event dispatch until after we return. postLayoutTasks()
859 // can make us need to update again, and we can get stuck in a nasty cycle unless
860 // we call it through the timer here.
861 m_hasPendingPostLayoutTasks = true;
862 m_postLayoutTasksTimer.startOneShot(0);
864 pauseScheduledEvents();
869 resumeScheduledEvents();
870 ASSERT(m_enqueueEvents);
873 InspectorInstrumentation::didLayout(cookie);
875 m_nestedLayoutCount--;
878 void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object)
880 if (!m_widgetUpdateSet)
881 m_widgetUpdateSet.set(new RenderEmbeddedObjectSet);
883 m_widgetUpdateSet->add(object);
886 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object)
888 if (!m_widgetUpdateSet)
891 m_widgetUpdateSet->remove(object);
894 void FrameView::setMediaType(const String& mediaType)
896 m_mediaType = mediaType;
899 String FrameView::mediaType() const
901 // See if we have an override type.
902 String overrideType = m_frame->loader()->client()->overrideMediaType();
903 if (!overrideType.isNull())
908 void FrameView::adjustMediaTypeForPrinting(bool printing)
911 if (m_mediaTypeWhenNotPrinting.isNull())
912 m_mediaTypeWhenNotPrinting = mediaType();
913 setMediaType("print");
915 if (!m_mediaTypeWhenNotPrinting.isNull())
916 setMediaType(m_mediaTypeWhenNotPrinting);
917 m_mediaTypeWhenNotPrinting = String();
921 bool FrameView::useSlowRepaints() const
923 return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || m_isOverlapped || !m_contentIsOpaque;
926 bool FrameView::useSlowRepaintsIfNotOverlapped() const
928 return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || !m_contentIsOpaque;
931 void FrameView::setUseSlowRepaints()
933 m_useSlowRepaints = true;
934 setCanBlitOnScroll(false);
937 void FrameView::addSlowRepaintObject()
939 if (!m_slowRepaintObjectCount)
940 setCanBlitOnScroll(false);
941 m_slowRepaintObjectCount++;
944 void FrameView::removeSlowRepaintObject()
946 ASSERT(m_slowRepaintObjectCount > 0);
947 m_slowRepaintObjectCount--;
948 if (!m_slowRepaintObjectCount)
949 setCanBlitOnScroll(!useSlowRepaints());
952 void FrameView::addFixedObject()
954 if (!m_fixedObjectCount && platformWidget())
955 setCanBlitOnScroll(false);
956 ++m_fixedObjectCount;
959 void FrameView::removeFixedObject()
961 ASSERT(m_fixedObjectCount > 0);
962 --m_fixedObjectCount;
963 if (!m_fixedObjectCount)
964 setCanBlitOnScroll(!useSlowRepaints());
967 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
969 const size_t fixedObjectThreshold = 5;
971 RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0;
972 if (RenderView* root = m_frame->contentRenderer())
973 positionedObjects = root->positionedObjects();
975 if (!positionedObjects || positionedObjects->isEmpty()) {
976 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
980 // Get the rects of the fixed objects visible in the rectToScroll
981 Vector<IntRect, fixedObjectThreshold> subRectToUpdate;
982 bool updateInvalidatedSubRect = true;
983 RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
984 for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
985 RenderBox* renderBox = *it;
986 if (renderBox->style()->position() != FixedPosition)
988 IntRect updateRect = renderBox->layer()->repaintRectIncludingDescendants();
989 updateRect = contentsToWindow(updateRect);
991 updateRect.intersect(rectToScroll);
992 if (!updateRect.isEmpty()) {
993 if (subRectToUpdate.size() >= fixedObjectThreshold) {
994 updateInvalidatedSubRect = false;
997 subRectToUpdate.append(updateRect);
1002 if (updateInvalidatedSubRect) {
1004 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1006 // 2) update the area of fixed objects that has been invalidated
1007 size_t fixObjectsCount = subRectToUpdate.size();
1008 for (size_t i = 0; i < fixObjectsCount; ++i) {
1009 IntRect updateRect = subRectToUpdate[i];
1010 IntRect scrolledRect = updateRect;
1011 scrolledRect.move(scrollDelta);
1012 updateRect.unite(scrolledRect);
1013 updateRect.intersect(rectToScroll);
1014 hostWindow()->invalidateContentsAndWindow(updateRect, false);
1019 // the number of fixed objects exceed the threshold, we cannot use the fast path
1023 // Note that this gets called at painting time.
1024 void FrameView::setIsOverlapped(bool isOverlapped)
1026 if (isOverlapped == m_isOverlapped)
1029 m_isOverlapped = isOverlapped;
1030 setCanBlitOnScroll(!useSlowRepaints());
1032 #if USE(ACCELERATED_COMPOSITING)
1033 // Overlap can affect compositing tests, so if it changes, we need to trigger
1034 // a layer update in the parent document.
1035 if (hasCompositedContent()) {
1036 if (Frame* parentFrame = m_frame->tree()->parent()) {
1037 if (RenderView* parentView = parentFrame->contentRenderer()) {
1038 RenderLayerCompositor* compositor = parentView->compositor();
1039 compositor->setCompositingLayersNeedRebuild();
1040 compositor->scheduleCompositingLayerUpdate();
1047 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1049 if (contentIsOpaque == m_contentIsOpaque)
1052 m_contentIsOpaque = contentIsOpaque;
1053 setCanBlitOnScroll(!useSlowRepaints());
1056 void FrameView::restoreScrollbar()
1058 setScrollbarsSuppressed(false);
1061 bool FrameView::scrollToFragment(const KURL& url)
1063 // If our URL has no ref, then we have no place we need to jump to.
1064 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1065 // and possibly repaint because :target pseudo class may have been
1066 // set (see bug 11321).
1067 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1070 String fragmentIdentifier = url.fragmentIdentifier();
1071 if (scrollToAnchor(fragmentIdentifier))
1074 // Try again after decoding the ref, based on the document's encoding.
1075 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1076 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1081 bool FrameView::scrollToAnchor(const String& name)
1083 ASSERT(m_frame->document());
1085 if (!m_frame->document()->haveStylesheetsLoaded()) {
1086 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1090 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1092 Element* anchorNode = m_frame->document()->findAnchor(name);
1095 if (m_frame->document()->isSVGDocument()) {
1096 if (name.startsWith("xpointer(")) {
1097 // We need to parse the xpointer reference here
1098 } else if (name.startsWith("svgView(")) {
1099 RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement();
1100 if (!svg->currentView()->parseViewSpec(name))
1102 svg->setUseCurrentView(true);
1104 if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) {
1105 RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0;
1106 if (viewElement.get()) {
1107 RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(SVGLocatable::nearestViewportElement(viewElement.get()));
1108 svg->inheritViewAttributes(viewElement.get());
1112 // FIXME: need to decide which <svg> to focus on, and zoom to that one
1113 // FIXME: need to actually "highlight" the viewTarget(s)
1117 m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target.
1119 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1120 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1123 #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR
1124 // TODO(andreip): check with Grace if this is correct.
1125 android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedAction(true);
1127 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1128 #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR
1129 android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedAction(false);
1134 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1136 m_maintainScrollPositionAnchor = anchorNode;
1137 if (!m_maintainScrollPositionAnchor)
1140 // We need to update the layout before scrolling, otherwise we could
1141 // really mess things up if an anchor scroll comes at a bad moment.
1142 m_frame->document()->updateStyleIfNeeded();
1143 // Only do a layout if changes have occurred that make it necessary.
1144 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
1150 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1152 bool wasInProgrammaticScroll = m_inProgrammaticScroll;
1153 m_inProgrammaticScroll = true;
1154 m_maintainScrollPositionAnchor = 0;
1155 ScrollView::setScrollPosition(scrollPoint);
1156 m_inProgrammaticScroll = wasInProgrammaticScroll;
1159 void FrameView::scrollPositionChangedViaPlatformWidget()
1161 repaintFixedElementsAfterScrolling();
1162 scrollPositionChanged();
1165 void FrameView::scrollPositionChanged()
1167 frame()->eventHandler()->sendScrollEvent();
1169 #if USE(ACCELERATED_COMPOSITING)
1170 if (RenderView* root = m_frame->contentRenderer()) {
1171 if (root->usesCompositing())
1172 root->compositor()->frameViewDidScroll(scrollPosition());
1177 void FrameView::repaintFixedElementsAfterScrolling()
1179 // For fixed position elements, update widget positions and compositing layers after scrolling,
1180 // but only if we're not inside of layout.
1181 if (!m_nestedLayoutCount && hasFixedObjects()) {
1182 if (RenderView* root = m_frame->contentRenderer()) {
1183 root->updateWidgetPositions();
1184 root->layer()->updateRepaintRectsAfterScroll();
1185 #if USE(ACCELERATED_COMPOSITING)
1186 root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
1192 HostWindow* FrameView::hostWindow() const
1194 Page* page = frame() ? frame()->page() : 0;
1197 return page->chrome();
1200 const unsigned cRepaintRectUnionThreshold = 25;
1202 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
1204 ASSERT(!m_frame->document()->ownerElement());
1206 double delay = adjustedDeferredRepaintDelay();
1207 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
1208 IntRect paintRect = r;
1209 if (!paintsEntireContents())
1210 paintRect.intersect(visibleContentRect());
1211 #ifdef ANDROID_CAPTURE_OFFSCREEN_PAINTS
1213 ScrollView::platformOffscreenContentRectangle(visibleContentRect(), r);
1215 if (paintRect.isEmpty())
1217 if (m_repaintCount == cRepaintRectUnionThreshold) {
1218 IntRect unionedRect;
1219 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
1220 unionedRect.unite(m_repaintRects[i]);
1221 m_repaintRects.clear();
1222 m_repaintRects.append(unionedRect);
1224 if (m_repaintCount < cRepaintRectUnionThreshold)
1225 m_repaintRects.append(paintRect);
1227 m_repaintRects[0].unite(paintRect);
1230 if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive())
1231 m_deferredRepaintTimer.startOneShot(delay);
1235 if (!immediate && isOffscreen() && !shouldUpdateWhileOffscreen())
1238 #if ENABLE(TILED_BACKING_STORE)
1239 if (frame()->tiledBackingStore()) {
1240 frame()->tiledBackingStore()->invalidate(r);
1244 ScrollView::repaintContentRectangle(r, immediate);
1247 void FrameView::visibleContentsResized()
1249 // We check to make sure the view is attached to a frame() as this method can
1250 // be triggered before the view is attached by Frame::createView(...) setting
1251 // various values such as setScrollBarModes(...) for example. An ASSERT is
1252 // triggered when a view is layout before being attached to a frame().
1253 if (!frame()->view())
1260 void FrameView::beginDeferredRepaints()
1262 Page* page = m_frame->page();
1263 if (page->mainFrame() != m_frame)
1264 return page->mainFrame()->view()->beginDeferredRepaints();
1266 m_deferringRepaints++;
1270 void FrameView::endDeferredRepaints()
1272 Page* page = m_frame->page();
1273 if (page->mainFrame() != m_frame)
1274 return page->mainFrame()->view()->endDeferredRepaints();
1276 ASSERT(m_deferringRepaints > 0);
1278 if (--m_deferringRepaints)
1281 if (m_deferredRepaintTimer.isActive())
1284 if (double delay = adjustedDeferredRepaintDelay()) {
1285 m_deferredRepaintTimer.startOneShot(delay);
1289 doDeferredRepaints();
1292 void FrameView::checkStopDelayingDeferredRepaints()
1294 if (!m_deferredRepaintTimer.isActive())
1297 Document* document = m_frame->document();
1298 if (document && (document->parsing() || document->cachedResourceLoader()->requestCount()))
1301 m_deferredRepaintTimer.stop();
1303 doDeferredRepaints();
1306 void FrameView::doDeferredRepaints()
1308 ASSERT(!m_deferringRepaints);
1309 if (isOffscreen() && !shouldUpdateWhileOffscreen()) {
1310 m_repaintRects.clear();
1314 unsigned size = m_repaintRects.size();
1315 for (unsigned i = 0; i < size; i++) {
1316 #if ENABLE(TILED_BACKING_STORE)
1317 if (frame()->tiledBackingStore()) {
1318 frame()->tiledBackingStore()->invalidate(m_repaintRects[i]);
1322 ScrollView::repaintContentRectangle(m_repaintRects[i], false);
1324 m_repaintRects.clear();
1327 updateDeferredRepaintDelay();
1330 void FrameView::updateDeferredRepaintDelay()
1332 Document* document = m_frame->document();
1333 if (!document || (!document->parsing() && !document->cachedResourceLoader()->requestCount())) {
1334 m_deferredRepaintDelay = s_deferredRepaintDelay;
1337 if (m_deferredRepaintDelay < s_maxDeferredRepaintDelayDuringLoading) {
1338 m_deferredRepaintDelay += s_deferredRepaintDelayIncrementDuringLoading;
1339 if (m_deferredRepaintDelay > s_maxDeferredRepaintDelayDuringLoading)
1340 m_deferredRepaintDelay = s_maxDeferredRepaintDelayDuringLoading;
1344 void FrameView::resetDeferredRepaintDelay()
1346 m_deferredRepaintDelay = 0;
1347 if (m_deferredRepaintTimer.isActive()) {
1348 m_deferredRepaintTimer.stop();
1349 if (!m_deferringRepaints)
1350 doDeferredRepaints();
1354 double FrameView::adjustedDeferredRepaintDelay() const
1356 if (!m_deferredRepaintDelay)
1358 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
1359 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
1362 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
1364 doDeferredRepaints();
1367 void FrameView::layoutTimerFired(Timer<FrameView>*)
1369 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1370 if (!m_frame->document()->ownerElement())
1371 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
1376 void FrameView::scheduleRelayout()
1378 // FIXME: We should assert the page is not in the page cache, but that is causing
1379 // too many false assertions. See <rdar://problem/7218118>.
1380 ASSERT(m_frame->view() == this);
1383 m_layoutRoot->markContainingBlocksForLayout(false);
1386 if (!m_layoutSchedulingEnabled)
1390 if (!m_frame->document()->shouldScheduleLayout())
1393 #if defined(ANDROID_FLATTEN_IFRAME) || defined(ANDROID_FLATTEN_FRAMESET)
1394 // This is the Android frame flattening code. The common code below is not
1395 // used as frameSetFlatteningEnabled() is false on Android.
1396 if (m_frame->ownerRenderer())
1397 m_frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc();
1400 // When frame flattening is enabled, the contents of the frame affects layout of the parent frames.
1401 // Also invalidate parent frame starting from the owner element of this frame.
1402 if (m_frame->settings() && m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) {
1403 if (m_frame->ownerElement()->hasTagName(iframeTag) || m_frame->ownerElement()->hasTagName(frameTag))
1404 m_frame->ownerRenderer()->setNeedsLayout(true, true);
1407 int delay = m_frame->document()->minimumLayoutDelay();
1408 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
1409 unscheduleRelayout();
1410 if (m_layoutTimer.isActive())
1413 m_delayedLayout = delay != 0;
1415 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1416 if (!m_frame->document()->ownerElement())
1417 printf("Scheduling layout for %d\n", delay);
1420 m_layoutTimer.startOneShot(delay * 0.001);
1423 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
1425 for (RenderObject* r = descendant; r; r = r->container()) {
1432 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
1434 ASSERT(m_frame->view() == this);
1436 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) {
1438 relayoutRoot->markContainingBlocksForLayout(false);
1442 if (layoutPending() || !m_layoutSchedulingEnabled) {
1443 if (m_layoutRoot != relayoutRoot) {
1444 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
1445 // Keep the current root
1446 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
1447 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
1448 // Re-root at relayoutRoot
1449 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
1450 m_layoutRoot = relayoutRoot;
1452 // Just do a full relayout
1454 m_layoutRoot->markContainingBlocksForLayout(false);
1456 relayoutRoot->markContainingBlocksForLayout(false);
1459 } else if (m_layoutSchedulingEnabled) {
1460 int delay = m_frame->document()->minimumLayoutDelay();
1461 m_layoutRoot = relayoutRoot;
1462 m_delayedLayout = delay != 0;
1463 m_layoutTimer.startOneShot(delay * 0.001);
1467 bool FrameView::layoutPending() const
1469 return m_layoutTimer.isActive();
1472 bool FrameView::needsLayout() const
1474 // This can return true in cases where the document does not have a body yet.
1475 // Document::shouldScheduleLayout takes care of preventing us from scheduling
1476 // layout in that case.
1479 RenderView* root = m_frame->contentRenderer();
1480 return layoutPending()
1481 || (root && root->needsLayout())
1483 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
1486 void FrameView::setNeedsLayout()
1488 if (m_deferSetNeedsLayouts) {
1489 m_setNeedsLayoutWasDeferred = true;
1492 RenderView* root = m_frame->contentRenderer();
1494 root->setNeedsLayout(true);
1497 void FrameView::unscheduleRelayout()
1499 m_postLayoutTasksTimer.stop();
1501 if (!m_layoutTimer.isActive())
1504 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1505 if (!m_frame->document()->ownerElement())
1506 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
1509 m_layoutTimer.stop();
1510 m_delayedLayout = false;
1513 bool FrameView::isTransparent() const
1515 return m_isTransparent;
1518 void FrameView::setTransparent(bool isTransparent)
1520 m_isTransparent = isTransparent;
1523 Color FrameView::baseBackgroundColor() const
1525 return m_baseBackgroundColor;
1528 void FrameView::setBaseBackgroundColor(Color bc)
1532 m_baseBackgroundColor = bc;
1535 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
1537 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1538 FrameView* view = frame->view();
1542 view->setTransparent(transparent);
1543 view->setBaseBackgroundColor(backgroundColor);
1547 bool FrameView::shouldUpdateWhileOffscreen() const
1549 return m_shouldUpdateWhileOffscreen;
1552 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
1554 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
1557 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
1559 if (!m_enqueueEvents) {
1560 ExceptionCode ec = 0;
1561 eventTarget->dispatchEvent(event, ec);
1565 ScheduledEvent* scheduledEvent = new ScheduledEvent;
1566 scheduledEvent->m_event = event;
1567 scheduledEvent->m_eventTarget = eventTarget;
1568 m_scheduledEvents.append(scheduledEvent);
1571 void FrameView::pauseScheduledEvents()
1573 ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
1577 void FrameView::resumeScheduledEvents()
1580 if (!m_enqueueEvents)
1581 dispatchScheduledEvents();
1582 ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
1585 void FrameView::scrollToAnchor()
1587 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
1591 if (!anchorNode->renderer())
1595 if (anchorNode != m_frame->document())
1596 rect = anchorNode->getRect();
1598 // Scroll nested layers and frames to reveal the anchor.
1599 // Align to the top and to the closest side (this matches other browsers).
1600 anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
1602 if (AXObjectCache::accessibilityEnabled())
1603 m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get());
1605 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
1606 m_maintainScrollPositionAnchor = anchorNode;
1609 void FrameView::updateWidget(RenderEmbeddedObject* object)
1611 ASSERT(!object->node() || object->node()->isElementNode());
1612 Element* ownerElement = static_cast<Element*>(object->node());
1613 // The object may have already been destroyed (thus node cleared),
1614 // but FrameView holds a manual ref, so it won't have been deleted.
1615 ASSERT(m_widgetUpdateSet->contains(object));
1619 // No need to update if it's already crashed or known to be missing.
1620 if (object->pluginCrashedOrWasMissing())
1623 // FIXME: This could turn into a real virtual dispatch if we defined
1624 // updateWidget(bool) on HTMLElement.
1625 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag))
1626 static_cast<HTMLPlugInImageElement*>(ownerElement)->updateWidget(false);
1627 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
1628 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1629 else if (ownerElement->hasTagName(videoTag) || ownerElement->hasTagName(audioTag))
1630 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(false);
1633 ASSERT_NOT_REACHED();
1635 // Caution: it's possible the object was destroyed again, since loading a
1636 // plugin may run any arbitrary javascript.
1637 object->updateWidgetPosition();
1640 bool FrameView::updateWidgets()
1642 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
1645 size_t size = m_widgetUpdateSet->size();
1647 Vector<RenderEmbeddedObject*> objects;
1648 objects.reserveCapacity(size);
1650 RenderEmbeddedObjectSet::const_iterator end = m_widgetUpdateSet->end();
1651 for (RenderEmbeddedObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
1652 objects.uncheckedAppend(*it);
1656 for (size_t i = 0; i < size; ++i) {
1657 RenderEmbeddedObject* object = objects[i];
1658 updateWidget(object);
1659 m_widgetUpdateSet->remove(object);
1662 RenderArena* arena = m_frame->document()->renderArena();
1663 for (size_t i = 0; i < size; ++i)
1664 objects[i]->deref(arena);
1666 return m_widgetUpdateSet->isEmpty();
1669 void FrameView::performPostLayoutTasks()
1671 m_hasPendingPostLayoutTasks = false;
1673 if (m_firstLayoutCallbackPending) {
1674 m_firstLayoutCallbackPending = false;
1675 m_frame->loader()->didFirstLayout();
1678 if (m_isVisuallyNonEmpty && m_firstVisuallyNonEmptyLayoutCallbackPending) {
1679 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
1680 m_frame->loader()->didFirstVisuallyNonEmptyLayout();
1683 RenderView* root = m_frame->contentRenderer();
1685 root->updateWidgetPositions();
1687 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
1688 if (updateWidgets())
1694 resumeScheduledEvents();
1696 if (!root->printing()) {
1697 IntSize currentSize = IntSize(width(), height());
1698 float currentZoomFactor = root->style()->zoom();
1699 bool resized = !m_firstLayout && (currentSize != m_lastLayoutSize || currentZoomFactor != m_lastZoomFactor);
1700 m_lastLayoutSize = currentSize;
1701 m_lastZoomFactor = currentZoomFactor;
1703 m_frame->eventHandler()->sendResizeEvent();
1707 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
1709 performPostLayoutTasks();
1712 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
1714 if (!m_viewportRenderer)
1717 if (m_overflowStatusDirty) {
1718 m_horizontalOverflow = horizontalOverflow;
1719 m_verticalOverflow = verticalOverflow;
1720 m_overflowStatusDirty = false;
1724 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
1725 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
1727 if (horizontalOverflowChanged || verticalOverflowChanged) {
1728 m_horizontalOverflow = horizontalOverflow;
1729 m_verticalOverflow = verticalOverflow;
1731 scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
1732 verticalOverflowChanged, verticalOverflow),
1733 m_viewportRenderer->node());
1738 void FrameView::dispatchScheduledEvents()
1740 if (m_scheduledEvents.isEmpty())
1743 Vector<ScheduledEvent*> scheduledEventsCopy = m_scheduledEvents;
1744 m_scheduledEvents.clear();
1746 Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end();
1747 for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) {
1748 ScheduledEvent* scheduledEvent = *it;
1750 ExceptionCode ec = 0;
1752 // Only dispatch events to nodes that are in the document
1753 if (scheduledEvent->m_eventTarget->inDocument())
1754 scheduledEvent->m_eventTarget->dispatchEvent(scheduledEvent->m_event, ec);
1756 delete scheduledEvent;
1760 IntRect FrameView::windowClipRect(bool clipToContents) const
1762 ASSERT(m_frame->view() == this);
1764 // Set our clip rect to be our contents.
1765 IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
1766 if (!m_frame || !m_frame->document() || !m_frame->document()->ownerElement())
1769 // Take our owner element and get the clip rect from the enclosing layer.
1770 Element* elt = m_frame->document()->ownerElement();
1771 RenderLayer* layer = elt->renderer()->enclosingLayer();
1772 // FIXME: layer should never be null, but sometimes seems to be anyway.
1775 FrameView* parentView = elt->document()->view();
1776 clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
1780 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const
1782 // If we have no layer, just return our window clip rect.
1784 return windowClipRect();
1786 // Apply the clip from the layer.
1788 if (clipToLayerContents)
1789 clipRect = layer->childrenClipRect();
1791 clipRect = layer->selfClipRect();
1792 clipRect = contentsToWindow(clipRect);
1793 return intersection(clipRect, windowClipRect());
1796 bool FrameView::isActive() const
1798 Page* page = frame()->page();
1799 return page && page->focusController()->isActive();
1802 void FrameView::valueChanged(Scrollbar* bar)
1804 // Figure out if we really moved.
1805 IntSize offset = scrollOffset();
1806 ScrollView::valueChanged(bar);
1807 if (offset != scrollOffset())
1808 scrollPositionChanged();
1809 frame()->loader()->client()->didChangeScrollOffset();
1812 void FrameView::valueChanged(const IntSize& scrollDelta)
1814 ScrollView::valueChanged(scrollDelta);
1815 frame()->eventHandler()->sendScrollEvent();
1816 frame()->loader()->client()->didChangeScrollOffset();
1819 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
1821 // Add in our offset within the FrameView.
1822 IntRect dirtyRect = rect;
1823 dirtyRect.move(scrollbar->x(), scrollbar->y());
1824 invalidateRect(dirtyRect);
1827 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
1829 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
1832 IntRect FrameView::windowResizerRect() const
1834 Page* page = frame() ? frame()->page() : 0;
1837 return page->chrome()->windowResizerRect();
1840 #if ENABLE(DASHBOARD_SUPPORT)
1841 void FrameView::updateDashboardRegions()
1843 Document* document = m_frame->document();
1844 if (!document->hasDashboardRegions())
1846 Vector<DashboardRegionValue> newRegions;
1847 document->renderBox()->collectDashboardRegions(newRegions);
1848 if (newRegions == document->dashboardRegions())
1850 document->setDashboardRegions(newRegions);
1851 Page* page = m_frame->page();
1854 page->chrome()->client()->dashboardRegionsChanged();
1858 void FrameView::invalidateScrollCorner()
1860 invalidateRect(scrollCornerRect());
1863 void FrameView::updateScrollCorner()
1865 RenderObject* renderer = 0;
1866 RefPtr<RenderStyle> cornerStyle;
1868 if (!scrollCornerRect().isEmpty()) {
1869 // Try the <body> element first as a scroll corner source.
1870 Document* doc = m_frame->document();
1871 Element* body = doc ? doc->body() : 0;
1872 if (body && body->renderer()) {
1873 renderer = body->renderer();
1874 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
1878 // If the <body> didn't have a custom style, then the root element might.
1879 Element* docElement = doc ? doc->documentElement() : 0;
1880 if (docElement && docElement->renderer()) {
1881 renderer = docElement->renderer();
1882 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
1887 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
1888 if (RenderPart* renderer = m_frame->ownerRenderer())
1889 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
1894 if (!m_scrollCorner)
1895 m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document());
1896 m_scrollCorner->setStyle(cornerStyle.release());
1897 invalidateRect(scrollCornerRect());
1898 } else if (m_scrollCorner) {
1899 m_scrollCorner->destroy();
1904 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
1906 if (context->updatingControlTints()) {
1907 updateScrollCorner();
1911 if (m_scrollCorner) {
1912 m_scrollCorner->paintIntoRect(context, cornerRect.x(), cornerRect.y(), cornerRect);
1916 ScrollView::paintScrollCorner(context, cornerRect);
1919 bool FrameView::hasCustomScrollbars() const
1921 const HashSet<RefPtr<Widget> >* viewChildren = children();
1922 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
1923 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
1924 Widget* widget = current->get();
1925 if (widget->isFrameView()) {
1926 if (static_cast<FrameView*>(widget)->hasCustomScrollbars())
1928 } else if (widget->isScrollbar()) {
1929 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
1930 if (scrollbar->isCustomScrollbar())
1938 void FrameView::updateControlTints()
1940 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
1941 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
1942 // This is only done if the theme supports control tinting. It's up to the theme and platform
1943 // to define when controls get the tint and to call this function when that changes.
1945 // Optimize the common case where we bring a window to the front while it's still empty.
1946 if (!m_frame || m_frame->loader()->url().isEmpty())
1949 if ((m_frame->contentRenderer() && m_frame->contentRenderer()->theme()->supportsControlTints()) || hasCustomScrollbars()) {
1952 PlatformGraphicsContext* const noContext = 0;
1953 GraphicsContext context(noContext);
1954 context.setUpdatingControlTints(true);
1955 if (platformWidget())
1956 paintContents(&context, visibleContentRect());
1958 paint(&context, frameRect());
1962 bool FrameView::wasScrolledByUser() const
1964 return m_wasScrolledByUser;
1967 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
1969 if (m_inProgrammaticScroll)
1971 m_maintainScrollPositionAnchor = 0;
1972 m_wasScrolledByUser = wasScrolledByUser;
1975 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
1980 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get(), rect);
1982 Document* document = frame()->document();
1986 if (document->printing())
1987 fillWithRed = false; // Printing, don't fill with red (can't remember why).
1988 else if (document->ownerElement())
1989 fillWithRed = false; // Subframe, don't fill with red.
1990 else if (isTransparent())
1991 fillWithRed = false; // Transparent, don't fill with red.
1992 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
1993 fillWithRed = false; // Selections are transparent, don't fill with red.
1994 else if (m_nodeToDraw)
1995 fillWithRed = false; // Element images are transparent, don't fill with red.
2000 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
2003 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
2004 if (isTopLevelPainter)
2005 sCurrentPaintTimeStamp = currentTime();
2007 RenderView* contentRenderer = frame()->contentRenderer();
2008 if (!contentRenderer) {
2009 LOG_ERROR("called FrameView::paint with nil renderer");
2013 ASSERT(!needsLayout());
2017 #if USE(ACCELERATED_COMPOSITING)
2018 if (!p->paintingDisabled()) {
2019 if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer())
2020 rootLayer->syncCompositingState();
2024 ASSERT(!m_isPainting);
2026 m_isPainting = true;
2028 // m_nodeToDraw is used to draw only one element (and its descendants)
2029 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
2031 PaintBehavior oldPaintBehavior = m_paintBehavior;
2032 if (m_paintBehavior == PaintBehaviorNormal)
2033 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
2035 if (document->printing())
2036 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2038 contentRenderer->layer()->paint(p, rect, m_paintBehavior, eltRenderer);
2040 m_paintBehavior = oldPaintBehavior;
2042 m_isPainting = false;
2043 m_lastPaintTime = currentTime();
2045 #if ENABLE(DASHBOARD_SUPPORT)
2046 // Regions may have changed as a result of the visibility/z-index of element changing.
2047 if (document->dashboardRegionsDirty())
2048 updateDashboardRegions();
2051 if (isTopLevelPainter)
2052 sCurrentPaintTimeStamp = 0;
2054 InspectorInstrumentation::didPaint(cookie);
2057 void FrameView::setPaintBehavior(PaintBehavior behavior)
2059 m_paintBehavior = behavior;
2062 PaintBehavior FrameView::paintBehavior() const
2064 return m_paintBehavior;
2067 bool FrameView::isPainting() const
2069 return m_isPainting;
2072 void FrameView::setNodeToDraw(Node* node)
2074 m_nodeToDraw = node;
2077 void FrameView::updateLayoutAndStyleIfNeededRecursive()
2079 // We have to crawl our entire tree looking for any FrameViews that need
2080 // layout and make sure they are up to date.
2081 // Mac actually tests for intersection with the dirty region and tries not to
2082 // update layout for frames that are outside the dirty region. Not only does this seem
2083 // pointless (since those frames will have set a zero timer to layout anyway), but
2084 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
2085 // region but then become included later by the second frame adding rects to the dirty region
2086 // when it lays out.
2088 m_frame->document()->updateStyleIfNeeded();
2093 const HashSet<RefPtr<Widget> >* viewChildren = children();
2094 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2095 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2096 Widget* widget = (*current).get();
2097 if (widget->isFrameView())
2098 static_cast<FrameView*>(widget)->updateLayoutAndStyleIfNeededRecursive();
2101 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
2102 // painting, so we need to flush out any deferred repaints too.
2103 flushDeferredRepaints();
2106 void FrameView::flushDeferredRepaints()
2108 if (!m_deferredRepaintTimer.isActive())
2110 m_deferredRepaintTimer.stop();
2111 doDeferredRepaints();
2114 void FrameView::forceLayout(bool allowSubtree)
2116 layout(allowSubtree);
2119 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximumShrinkFactor, Frame::AdjustViewSizeOrNot shouldAdjustViewSize)
2121 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
2122 // the state of things before and after the layout
2123 RenderView *root = toRenderView(m_frame->document()->renderer());
2125 int pageW = ceilf(pageSize.width());
2126 root->setWidth(pageW);
2127 root->setPageHeight(pageSize.height());
2128 root->setNeedsLayoutAndPrefWidthsRecalc();
2131 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
2132 // page width when shrunk, we will lay out at maximum shrink and clip extra content.
2133 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
2134 // implementation should not do this!
2135 int rightmostPos = root->rightmostPosition();
2136 if (rightmostPos > pageSize.width()) {
2137 pageW = std::min<int>(rightmostPos, ceilf(pageSize.width() * maximumShrinkFactor));
2138 if (pageSize.height())
2139 root->setPageHeight(pageW / pageSize.width() * pageSize.height());
2140 root->setWidth(pageW);
2141 root->setNeedsLayoutAndPrefWidthsRecalc();
2143 int docHeight = root->bottomLayoutOverflow();
2144 root->clearLayoutOverflow();
2145 root->addLayoutOverflow(IntRect(0, 0, pageW, docHeight)); // This is how we clip in case we overflow again.
2149 if (shouldAdjustViewSize)
2153 void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
2155 RenderView* root = m_frame->contentRenderer();
2157 // Use a context with painting disabled.
2158 GraphicsContext context((PlatformGraphicsContext*)0);
2159 root->setTruncatedAt((int)floorf(oldBottom));
2160 IntRect dirtyRect(0, (int)floorf(oldTop), root->rightLayoutOverflow(), (int)ceilf(oldBottom - oldTop));
2161 root->setPrintRect(dirtyRect);
2162 root->layer()->paint(&context, dirtyRect);
2163 *newBottom = root->bestTruncatedAt();
2164 if (*newBottom == 0)
2165 *newBottom = oldBottom;
2166 root->setPrintRect(IntRect());
2168 *newBottom = oldBottom;
2171 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
2173 IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
2175 // Convert from page ("absolute") to FrameView coordinates.
2176 rect.move(-scrollX(), -scrollY());
2181 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
2183 IntRect rect = viewRect;
2185 // Convert from FrameView coords into page ("absolute") coordinates.
2186 rect.move(scrollX(), scrollY());
2188 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
2189 // move the rect for now.
2190 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
2194 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
2196 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
2198 // Convert from page ("absolute") to FrameView coordinates.
2199 point.move(-scrollX(), -scrollY());
2203 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
2205 IntPoint point = viewPoint;
2207 // Convert from FrameView coords into page ("absolute") coordinates.
2208 point += IntSize(scrollX(), scrollY());
2210 return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
2213 IntRect FrameView::convertToContainingView(const IntRect& localRect) const
2215 if (const ScrollView* parentScrollView = parent()) {
2216 if (parentScrollView->isFrameView()) {
2217 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2218 // Get our renderer in the parent view
2219 RenderPart* renderer = m_frame->ownerRenderer();
2223 IntRect rect(localRect);
2224 // Add borders and padding??
2225 rect.move(renderer->borderLeft() + renderer->paddingLeft(),
2226 renderer->borderTop() + renderer->paddingTop());
2227 return parentView->convertFromRenderer(renderer, rect);
2230 return Widget::convertToContainingView(localRect);
2236 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
2238 if (const ScrollView* parentScrollView = parent()) {
2239 if (parentScrollView->isFrameView()) {
2240 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 = parentView->convertToRenderer(renderer, parentRect);
2248 // Subtract borders and padding
2249 rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
2250 -renderer->borderTop() - renderer->paddingTop());
2254 return Widget::convertFromContainingView(parentRect);
2260 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) 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 IntPoint point(localPoint);
2273 // Add borders and padding
2274 point.move(renderer->borderLeft() + renderer->paddingLeft(),
2275 renderer->borderTop() + renderer->paddingTop());
2276 return parentView->convertFromRenderer(renderer, point);
2279 return Widget::convertToContainingView(localPoint);
2285 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
2287 if (const ScrollView* parentScrollView = parent()) {
2288 if (parentScrollView->isFrameView()) {
2289 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2291 // Get our renderer in the parent view
2292 RenderPart* renderer = m_frame->ownerRenderer();
2296 IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
2297 // Subtract borders and padding
2298 point.move(-renderer->borderLeft() - renderer->paddingLeft(),
2299 -renderer->borderTop() - renderer->paddingTop());
2303 return Widget::convertFromContainingView(parentPoint);
2310 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
2312 s_deferredRepaintDelay = p;
2315 // Negative value would mean that first few repaints happen without a delay
2316 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)
2318 s_initialDeferredRepaintDelayDuringLoading = p;
2321 // The delay grows on each repaint to this maximum value
2322 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)
2324 s_maxDeferredRepaintDelayDuringLoading = p;
2327 // On each repaint the delay increases by this amount
2328 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)
2330 s_deferredRepaintDelayIncrementDuringLoading = p;
2333 } // namespace WebCore