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 "InspectorTimelineAgent.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 m_canHaveScrollbars = false;
392 m_canHaveScrollbars = 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 #if USE(ACCELERATED_COMPOSITING)
490 void FrameView::updateCompositingLayers()
492 RenderView* view = m_frame->contentRenderer();
496 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
497 view->compositor()->cacheAcceleratedCompositingFlags();
498 view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange);
501 void FrameView::setNeedsOneShotDrawingSynchronization()
503 Page* page = frame() ? frame()->page() : 0;
505 page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
508 #endif // USE(ACCELERATED_COMPOSITING)
510 bool FrameView::hasCompositedContent() const
512 #if USE(ACCELERATED_COMPOSITING)
513 if (RenderView* view = m_frame->contentRenderer())
514 return view->compositor()->inCompositingMode();
519 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
520 void FrameView::enterCompositingMode()
522 #if USE(ACCELERATED_COMPOSITING)
523 if (RenderView* view = m_frame->contentRenderer()) {
524 view->compositor()->enableCompositingMode();
526 view->compositor()->scheduleCompositingLayerUpdate();
531 bool FrameView::isEnclosedInCompositingLayer() const
533 #if USE(ACCELERATED_COMPOSITING)
534 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
535 return frameOwnerRenderer && frameOwnerRenderer->containerForRepaint();
541 bool FrameView::syncCompositingStateRecursive()
543 #if USE(ACCELERATED_COMPOSITING)
544 ASSERT(m_frame->view() == this);
545 RenderView* contentRenderer = m_frame->contentRenderer();
546 if (!contentRenderer)
547 return true; // We don't want to keep trying to update layers if we have no renderer.
549 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
550 // layer content to occur before layout has happened, which will cause paintContents() to bail.
554 if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer())
555 rootLayer->syncCompositingState();
557 bool allSubframesSynced = true;
558 const HashSet<RefPtr<Widget> >* viewChildren = children();
559 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
560 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
561 Widget* widget = (*current).get();
562 if (widget->isFrameView()) {
563 bool synced = static_cast<FrameView*>(widget)->syncCompositingStateRecursive();
564 allSubframesSynced &= synced;
567 return allSubframesSynced;
568 #else // USE(ACCELERATED_COMPOSITING)
573 bool FrameView::isSoftwareRenderable() const
575 #if USE(ACCELERATED_COMPOSITING)
576 RenderView* view = m_frame->contentRenderer();
580 return !view->compositor()->has3DContent();
586 void FrameView::didMoveOnscreen()
588 RenderView* view = m_frame->contentRenderer();
590 view->didMoveOnscreen();
593 void FrameView::willMoveOffscreen()
595 RenderView* view = m_frame->contentRenderer();
597 view->willMoveOffscreen();
600 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
602 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
605 void FrameView::layout(bool allowSubtree)
610 m_layoutTimer.stop();
611 m_delayedLayout = false;
612 m_setNeedsLayoutWasDeferred = false;
614 // Protect the view from being deleted during layout (in recalcStyle)
615 RefPtr<FrameView> protector(this);
618 // FIXME: Do we need to set m_size.width here?
619 // FIXME: Should we set m_size.height here too?
620 m_size.setWidth(layoutWidth());
624 // we shouldn't enter layout() while painting
625 ASSERT(!isPainting());
629 #if ENABLE(INSPECTOR)
630 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent())
631 timelineAgent->willLayout();
634 if (!allowSubtree && m_layoutRoot) {
635 m_layoutRoot->markContainingBlocksForLayout(false);
639 ASSERT(m_frame->view() == this);
641 Document* document = m_frame->document();
643 m_layoutSchedulingEnabled = false;
645 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_hasPendingPostLayoutTasks) {
646 // This is a new top-level layout. If there are any remaining tasks from the previous
647 // layout, finish them now.
648 m_inSynchronousPostLayout = true;
649 m_postLayoutTasksTimer.stop();
650 performPostLayoutTasks();
651 m_inSynchronousPostLayout = false;
654 // Viewport-dependent media queries may cause us to need completely different style information.
656 if (document->styleSelector()->affectedByViewportChange())
657 document->styleSelectorChanged(RecalcStyleImmediately);
659 // Always ensure our style info is up-to-date. This can happen in situations where
660 // the layout beats any sort of style recalc update that needs to occur.
661 document->updateStyleIfNeeded();
663 bool subtree = m_layoutRoot;
665 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
666 // so there's no point to continuing to layout
667 if (protector->hasOneRef())
670 RenderObject* root = subtree ? m_layoutRoot : document->renderer();
672 // FIXME: Do we need to set m_size here?
673 m_layoutSchedulingEnabled = true;
677 #ifdef ANDROID_INSTRUMENT
678 if (!m_frame->tree() || !m_frame->tree()->parent())
679 android::TimeCounter::start(android::TimeCounter::LayoutTimeCounter);
682 m_nestedLayoutCount++;
686 if (m_canHaveScrollbars) {
687 hMode = ScrollbarAuto;
688 vMode = ScrollbarAuto;
690 hMode = ScrollbarAlwaysOff;
691 vMode = ScrollbarAlwaysOff;
695 Node* documentElement = document->documentElement();
696 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
697 Node* body = document->body();
698 if (body && body->renderer()) {
699 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
700 #if !defined(ANDROID_FLATTEN_IFRAME) && !defined(ANDROID_FLATTEN_FRAMESET)
701 body->renderer()->setChildNeedsLayout(true);
702 vMode = ScrollbarAlwaysOff;
703 hMode = ScrollbarAlwaysOff;
705 } else if (body->hasTagName(bodyTag)) {
706 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewHeight())
707 body->renderer()->setChildNeedsLayout(true);
708 // It's sufficient to just check the X overflow,
709 // since it's illegal to have visible in only one direction.
710 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
711 applyOverflowToViewport(o, hMode, vMode);
713 } else if (rootRenderer) {
715 if (documentElement->isSVGElement()) {
716 if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight()))
717 rootRenderer->setChildNeedsLayout(true);
719 applyOverflowToViewport(rootRenderer, hMode, vMode);
721 applyOverflowToViewport(rootRenderer, hMode, vMode);
724 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
725 if (m_firstLayout && !document->ownerElement())
726 printf("Elapsed time before first layout: %d\n", document->elapsedTime());
730 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
733 // Now set our scrollbar state for the layout.
734 ScrollbarMode currentHMode = horizontalScrollbarMode();
735 ScrollbarMode currentVMode = verticalScrollbarMode();
737 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
739 setScrollbarsSuppressed(true);
741 m_firstLayout = false;
742 m_firstLayoutCallbackPending = true;
743 m_lastLayoutSize = IntSize(width(), height());
744 m_lastZoomFactor = root->style()->zoom();
746 // Set the initial vMode to AlwaysOn if we're auto.
747 if (vMode == ScrollbarAuto)
748 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
749 // Set the initial hMode to AlwaysOff if we're auto.
750 if (hMode == ScrollbarAuto)
751 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
753 setScrollbarModes(hMode, vMode);
754 setScrollbarsSuppressed(false, true);
756 setScrollbarModes(hMode, vMode);
759 IntSize oldSize = m_size;
761 m_size = IntSize(layoutWidth(), layoutHeight());
763 if (oldSize != m_size)
764 m_doFullRepaint = true;
767 RenderLayer* layer = root->enclosingLayer();
769 pauseScheduledEvents();
771 bool disableLayoutState = false;
773 RenderView* view = root->view();
774 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
775 view->pushLayoutState(root);
776 if (disableLayoutState)
777 view->disableLayoutState();
781 beginDeferredRepaints();
783 endDeferredRepaints();
787 RenderView* view = root->view();
788 view->popLayoutState(root);
789 if (disableLayoutState)
790 view->enableLayoutState();
794 m_frame->selection()->setCaretRectNeedsUpdate();
795 m_frame->selection()->updateAppearance();
797 m_layoutSchedulingEnabled = true;
799 if (!subtree && !toRenderView(root)->printing())
802 // Now update the positions of all layers.
803 beginDeferredRepaints();
804 IntPoint cachedOffset;
805 layer->updateLayerPositions((m_doFullRepaint ? RenderLayer::DoFullRepaint : 0)
806 | RenderLayer::CheckForRepaint
807 | RenderLayer::IsCompositingUpdateRoot
808 | RenderLayer::UpdateCompositingLayers,
809 subtree ? 0 : &cachedOffset);
810 endDeferredRepaints();
812 #if USE(ACCELERATED_COMPOSITING)
813 updateCompositingLayers();
819 if (AXObjectCache::accessibilityEnabled())
820 root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true);
822 #if ENABLE(DASHBOARD_SUPPORT)
823 updateDashboardRegions();
826 #ifdef ANDROID_INSTRUMENT
827 if (!m_frame->tree()->parent())
828 android::TimeCounter::record(android::TimeCounter::LayoutTimeCounter, __FUNCTION__);
830 ASSERT(!root->needsLayout());
832 setCanBlitOnScroll(!useSlowRepaints());
834 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
835 updateOverflowStatus(layoutWidth() < contentsWidth(),
836 layoutHeight() < contentsHeight());
838 if (!m_hasPendingPostLayoutTasks) {
839 if (!m_inSynchronousPostLayout) {
840 m_inSynchronousPostLayout = true;
841 // Calls resumeScheduledEvents()
842 performPostLayoutTasks();
843 m_inSynchronousPostLayout = false;
846 if (!m_hasPendingPostLayoutTasks && (needsLayout() || m_inSynchronousPostLayout)) {
847 // If we need layout or are already in a synchronous call to postLayoutTasks(),
848 // defer widget updates and event dispatch until after we return. postLayoutTasks()
849 // can make us need to update again, and we can get stuck in a nasty cycle unless
850 // we call it through the timer here.
851 m_hasPendingPostLayoutTasks = true;
852 m_postLayoutTasksTimer.startOneShot(0);
854 pauseScheduledEvents();
859 resumeScheduledEvents();
860 ASSERT(m_enqueueEvents);
863 #if ENABLE(INSPECTOR)
864 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent())
865 timelineAgent->didLayout();
868 m_nestedLayoutCount--;
871 void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object)
873 if (!m_widgetUpdateSet)
874 m_widgetUpdateSet.set(new RenderEmbeddedObjectSet);
876 m_widgetUpdateSet->add(object);
879 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object)
881 if (!m_widgetUpdateSet)
884 m_widgetUpdateSet->remove(object);
887 void FrameView::setMediaType(const String& mediaType)
889 m_mediaType = mediaType;
892 String FrameView::mediaType() const
894 // See if we have an override type.
895 String overrideType = m_frame->loader()->client()->overrideMediaType();
896 if (!overrideType.isNull())
901 void FrameView::adjustMediaTypeForPrinting(bool printing)
904 if (m_mediaTypeWhenNotPrinting.isNull())
905 m_mediaTypeWhenNotPrinting = mediaType();
906 setMediaType("print");
908 if (!m_mediaTypeWhenNotPrinting.isNull())
909 setMediaType(m_mediaTypeWhenNotPrinting);
910 m_mediaTypeWhenNotPrinting = String();
914 bool FrameView::useSlowRepaints() const
916 return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || m_isOverlapped || !m_contentIsOpaque;
919 bool FrameView::useSlowRepaintsIfNotOverlapped() const
921 return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || !m_contentIsOpaque;
924 void FrameView::setUseSlowRepaints()
926 m_useSlowRepaints = true;
927 setCanBlitOnScroll(false);
930 void FrameView::addSlowRepaintObject()
932 if (!m_slowRepaintObjectCount)
933 setCanBlitOnScroll(false);
934 m_slowRepaintObjectCount++;
937 void FrameView::removeSlowRepaintObject()
939 ASSERT(m_slowRepaintObjectCount > 0);
940 m_slowRepaintObjectCount--;
941 if (!m_slowRepaintObjectCount)
942 setCanBlitOnScroll(!useSlowRepaints());
945 void FrameView::addFixedObject()
947 if (!m_fixedObjectCount && platformWidget())
948 setCanBlitOnScroll(false);
949 ++m_fixedObjectCount;
952 void FrameView::removeFixedObject()
954 ASSERT(m_fixedObjectCount > 0);
955 --m_fixedObjectCount;
956 if (!m_fixedObjectCount)
957 setCanBlitOnScroll(!useSlowRepaints());
960 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
962 const size_t fixedObjectThreshold = 5;
964 RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0;
965 if (RenderView* root = m_frame->contentRenderer())
966 positionedObjects = root->positionedObjects();
968 if (!positionedObjects || positionedObjects->isEmpty()) {
969 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
973 // Get the rects of the fixed objects visible in the rectToScroll
974 Vector<IntRect, fixedObjectThreshold> subRectToUpdate;
975 bool updateInvalidatedSubRect = true;
976 RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
977 for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
978 RenderBox* renderBox = *it;
979 if (renderBox->style()->position() != FixedPosition)
981 IntRect updateRect = renderBox->layer()->repaintRectIncludingDescendants();
982 updateRect = contentsToWindow(updateRect);
984 updateRect.intersect(rectToScroll);
985 if (!updateRect.isEmpty()) {
986 if (subRectToUpdate.size() >= fixedObjectThreshold) {
987 updateInvalidatedSubRect = false;
990 subRectToUpdate.append(updateRect);
995 if (updateInvalidatedSubRect) {
997 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
999 // 2) update the area of fixed objects that has been invalidated
1000 size_t fixObjectsCount = subRectToUpdate.size();
1001 for (size_t i = 0; i < fixObjectsCount; ++i) {
1002 IntRect updateRect = subRectToUpdate[i];
1003 IntRect scrolledRect = updateRect;
1004 scrolledRect.move(scrollDelta);
1005 updateRect.unite(scrolledRect);
1006 updateRect.intersect(rectToScroll);
1007 hostWindow()->invalidateContentsAndWindow(updateRect, false);
1012 // the number of fixed objects exceed the threshold, we cannot use the fast path
1016 // Note that this gets called at painting time.
1017 void FrameView::setIsOverlapped(bool isOverlapped)
1019 if (isOverlapped == m_isOverlapped)
1022 m_isOverlapped = isOverlapped;
1023 setCanBlitOnScroll(!useSlowRepaints());
1025 #if USE(ACCELERATED_COMPOSITING)
1026 // Overlap can affect compositing tests, so if it changes, we need to trigger
1027 // a layer update in the parent document.
1028 if (hasCompositedContent()) {
1029 if (Frame* parentFrame = m_frame->tree()->parent()) {
1030 if (RenderView* parentView = parentFrame->contentRenderer()) {
1031 RenderLayerCompositor* compositor = parentView->compositor();
1032 compositor->setCompositingLayersNeedRebuild();
1033 compositor->scheduleCompositingLayerUpdate();
1040 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1042 if (contentIsOpaque == m_contentIsOpaque)
1045 m_contentIsOpaque = contentIsOpaque;
1046 setCanBlitOnScroll(!useSlowRepaints());
1049 void FrameView::restoreScrollbar()
1051 setScrollbarsSuppressed(false);
1054 bool FrameView::scrollToFragment(const KURL& url)
1056 // If our URL has no ref, then we have no place we need to jump to.
1057 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1058 // and possibly repaint because :target pseudo class may have been
1059 // set (see bug 11321).
1060 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1063 String fragmentIdentifier = url.fragmentIdentifier();
1064 if (scrollToAnchor(fragmentIdentifier))
1067 // Try again after decoding the ref, based on the document's encoding.
1068 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1069 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1074 bool FrameView::scrollToAnchor(const String& name)
1076 ASSERT(m_frame->document());
1078 if (!m_frame->document()->haveStylesheetsLoaded()) {
1079 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1083 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1085 Element* anchorNode = m_frame->document()->findAnchor(name);
1088 if (m_frame->document()->isSVGDocument()) {
1089 if (name.startsWith("xpointer(")) {
1090 // We need to parse the xpointer reference here
1091 } else if (name.startsWith("svgView(")) {
1092 RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement();
1093 if (!svg->currentView()->parseViewSpec(name))
1095 svg->setUseCurrentView(true);
1097 if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) {
1098 RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0;
1099 if (viewElement.get()) {
1100 RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(SVGLocatable::nearestViewportElement(viewElement.get()));
1101 svg->inheritViewAttributes(viewElement.get());
1105 // FIXME: need to decide which <svg> to focus on, and zoom to that one
1106 // FIXME: need to actually "highlight" the viewTarget(s)
1110 m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target.
1112 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1113 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1116 #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR
1117 // TODO(andreip): check with Grace if this is correct.
1118 android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedAction(true);
1120 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1121 #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR
1122 android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedAction(false);
1127 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1129 m_maintainScrollPositionAnchor = anchorNode;
1130 if (!m_maintainScrollPositionAnchor)
1133 // We need to update the layout before scrolling, otherwise we could
1134 // really mess things up if an anchor scroll comes at a bad moment.
1135 m_frame->document()->updateStyleIfNeeded();
1136 // Only do a layout if changes have occurred that make it necessary.
1137 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
1143 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1145 bool wasInProgrammaticScroll = m_inProgrammaticScroll;
1146 m_inProgrammaticScroll = true;
1147 m_maintainScrollPositionAnchor = 0;
1148 ScrollView::setScrollPosition(scrollPoint);
1149 m_inProgrammaticScroll = wasInProgrammaticScroll;
1152 void FrameView::scrollPositionChangedViaPlatformWidget()
1154 repaintFixedElementsAfterScrolling();
1155 scrollPositionChanged();
1158 void FrameView::scrollPositionChanged()
1160 frame()->eventHandler()->sendScrollEvent();
1162 #if USE(ACCELERATED_COMPOSITING)
1163 if (RenderView* root = m_frame->contentRenderer()) {
1164 if (root->usesCompositing())
1165 root->compositor()->frameViewDidScroll(scrollPosition());
1170 void FrameView::repaintFixedElementsAfterScrolling()
1172 // For fixed position elements, update widget positions and compositing layers after scrolling,
1173 // but only if we're not inside of layout.
1174 if (!m_nestedLayoutCount && hasFixedObjects()) {
1175 if (RenderView* root = m_frame->contentRenderer()) {
1176 root->updateWidgetPositions();
1177 root->layer()->updateRepaintRectsAfterScroll();
1178 #if USE(ACCELERATED_COMPOSITING)
1179 root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
1185 HostWindow* FrameView::hostWindow() const
1187 Page* page = frame() ? frame()->page() : 0;
1190 return page->chrome();
1193 const unsigned cRepaintRectUnionThreshold = 25;
1195 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
1197 ASSERT(!m_frame->document()->ownerElement());
1199 double delay = adjustedDeferredRepaintDelay();
1200 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
1201 IntRect paintRect = r;
1202 if (!paintsEntireContents())
1203 paintRect.intersect(visibleContentRect());
1204 #ifdef ANDROID_CAPTURE_OFFSCREEN_PAINTS
1206 ScrollView::platformOffscreenContentRectangle(visibleContentRect(), r);
1208 if (paintRect.isEmpty())
1210 if (m_repaintCount == cRepaintRectUnionThreshold) {
1211 IntRect unionedRect;
1212 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
1213 unionedRect.unite(m_repaintRects[i]);
1214 m_repaintRects.clear();
1215 m_repaintRects.append(unionedRect);
1217 if (m_repaintCount < cRepaintRectUnionThreshold)
1218 m_repaintRects.append(paintRect);
1220 m_repaintRects[0].unite(paintRect);
1223 if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive())
1224 m_deferredRepaintTimer.startOneShot(delay);
1228 if (!immediate && isOffscreen() && !shouldUpdateWhileOffscreen())
1231 #if ENABLE(TILED_BACKING_STORE)
1232 if (frame()->tiledBackingStore()) {
1233 frame()->tiledBackingStore()->invalidate(r);
1237 ScrollView::repaintContentRectangle(r, immediate);
1240 void FrameView::visibleContentsResized()
1242 // We check to make sure the view is attached to a frame() as this method can
1243 // be triggered before the view is attached by Frame::createView(...) setting
1244 // various values such as setScrollBarModes(...) for example. An ASSERT is
1245 // triggered when a view is layout before being attached to a frame().
1246 if (!frame()->view())
1253 void FrameView::beginDeferredRepaints()
1255 Page* page = m_frame->page();
1256 if (page->mainFrame() != m_frame)
1257 return page->mainFrame()->view()->beginDeferredRepaints();
1259 m_deferringRepaints++;
1263 void FrameView::endDeferredRepaints()
1265 Page* page = m_frame->page();
1266 if (page->mainFrame() != m_frame)
1267 return page->mainFrame()->view()->endDeferredRepaints();
1269 ASSERT(m_deferringRepaints > 0);
1271 if (--m_deferringRepaints)
1274 if (m_deferredRepaintTimer.isActive())
1277 if (double delay = adjustedDeferredRepaintDelay()) {
1278 m_deferredRepaintTimer.startOneShot(delay);
1282 doDeferredRepaints();
1285 void FrameView::checkStopDelayingDeferredRepaints()
1287 if (!m_deferredRepaintTimer.isActive())
1290 Document* document = m_frame->document();
1291 if (document && (document->parsing() || document->cachedResourceLoader()->requestCount()))
1294 m_deferredRepaintTimer.stop();
1296 doDeferredRepaints();
1299 void FrameView::doDeferredRepaints()
1301 ASSERT(!m_deferringRepaints);
1302 if (isOffscreen() && !shouldUpdateWhileOffscreen()) {
1303 m_repaintRects.clear();
1307 unsigned size = m_repaintRects.size();
1308 for (unsigned i = 0; i < size; i++) {
1309 #if ENABLE(TILED_BACKING_STORE)
1310 if (frame()->tiledBackingStore()) {
1311 frame()->tiledBackingStore()->invalidate(m_repaintRects[i]);
1315 ScrollView::repaintContentRectangle(m_repaintRects[i], false);
1317 m_repaintRects.clear();
1320 updateDeferredRepaintDelay();
1323 void FrameView::updateDeferredRepaintDelay()
1325 Document* document = m_frame->document();
1326 if (!document || (!document->parsing() && !document->cachedResourceLoader()->requestCount())) {
1327 m_deferredRepaintDelay = s_deferredRepaintDelay;
1330 if (m_deferredRepaintDelay < s_maxDeferredRepaintDelayDuringLoading) {
1331 m_deferredRepaintDelay += s_deferredRepaintDelayIncrementDuringLoading;
1332 if (m_deferredRepaintDelay > s_maxDeferredRepaintDelayDuringLoading)
1333 m_deferredRepaintDelay = s_maxDeferredRepaintDelayDuringLoading;
1337 void FrameView::resetDeferredRepaintDelay()
1339 m_deferredRepaintDelay = 0;
1340 if (m_deferredRepaintTimer.isActive()) {
1341 m_deferredRepaintTimer.stop();
1342 if (!m_deferringRepaints)
1343 doDeferredRepaints();
1347 double FrameView::adjustedDeferredRepaintDelay() const
1349 if (!m_deferredRepaintDelay)
1351 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
1352 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
1355 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
1357 doDeferredRepaints();
1360 void FrameView::layoutTimerFired(Timer<FrameView>*)
1362 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1363 if (!m_frame->document()->ownerElement())
1364 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
1369 void FrameView::scheduleRelayout()
1371 // FIXME: We should assert the page is not in the page cache, but that is causing
1372 // too many false assertions. See <rdar://problem/7218118>.
1373 ASSERT(m_frame->view() == this);
1376 m_layoutRoot->markContainingBlocksForLayout(false);
1379 if (!m_layoutSchedulingEnabled)
1383 if (!m_frame->document()->shouldScheduleLayout())
1386 #if defined(ANDROID_FLATTEN_IFRAME) || defined(ANDROID_FLATTEN_FRAMESET)
1387 // This is the Android frame flattening code. The common code below is not
1388 // used as frameSetFlatteningEnabled() is false on Android.
1389 if (m_frame->ownerRenderer())
1390 m_frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc();
1393 // When frame flattening is enabled, the contents of the frame affects layout of the parent frames.
1394 // Also invalidate parent frame starting from the owner element of this frame.
1395 if (m_frame->settings() && m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) {
1396 if (m_frame->ownerElement()->hasTagName(iframeTag) || m_frame->ownerElement()->hasTagName(frameTag))
1397 m_frame->ownerRenderer()->setNeedsLayout(true, true);
1400 int delay = m_frame->document()->minimumLayoutDelay();
1401 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
1402 unscheduleRelayout();
1403 if (m_layoutTimer.isActive())
1406 m_delayedLayout = delay != 0;
1408 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1409 if (!m_frame->document()->ownerElement())
1410 printf("Scheduling layout for %d\n", delay);
1413 m_layoutTimer.startOneShot(delay * 0.001);
1416 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
1418 for (RenderObject* r = descendant; r; r = r->container()) {
1425 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
1427 ASSERT(m_frame->view() == this);
1429 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) {
1431 relayoutRoot->markContainingBlocksForLayout(false);
1435 if (layoutPending() || !m_layoutSchedulingEnabled) {
1436 if (m_layoutRoot != relayoutRoot) {
1437 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
1438 // Keep the current root
1439 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
1440 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
1441 // Re-root at relayoutRoot
1442 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
1443 m_layoutRoot = relayoutRoot;
1445 // Just do a full relayout
1447 m_layoutRoot->markContainingBlocksForLayout(false);
1449 relayoutRoot->markContainingBlocksForLayout(false);
1452 } else if (m_layoutSchedulingEnabled) {
1453 int delay = m_frame->document()->minimumLayoutDelay();
1454 m_layoutRoot = relayoutRoot;
1455 m_delayedLayout = delay != 0;
1456 m_layoutTimer.startOneShot(delay * 0.001);
1460 bool FrameView::layoutPending() const
1462 return m_layoutTimer.isActive();
1465 bool FrameView::needsLayout() const
1467 // This can return true in cases where the document does not have a body yet.
1468 // Document::shouldScheduleLayout takes care of preventing us from scheduling
1469 // layout in that case.
1472 RenderView* root = m_frame->contentRenderer();
1473 return layoutPending()
1474 || (root && root->needsLayout())
1476 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
1479 void FrameView::setNeedsLayout()
1481 if (m_deferSetNeedsLayouts) {
1482 m_setNeedsLayoutWasDeferred = true;
1485 RenderView* root = m_frame->contentRenderer();
1487 root->setNeedsLayout(true);
1490 void FrameView::unscheduleRelayout()
1492 m_postLayoutTasksTimer.stop();
1494 if (!m_layoutTimer.isActive())
1497 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1498 if (!m_frame->document()->ownerElement())
1499 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
1502 m_layoutTimer.stop();
1503 m_delayedLayout = false;
1506 bool FrameView::isTransparent() const
1508 return m_isTransparent;
1511 void FrameView::setTransparent(bool isTransparent)
1513 m_isTransparent = isTransparent;
1516 Color FrameView::baseBackgroundColor() const
1518 return m_baseBackgroundColor;
1521 void FrameView::setBaseBackgroundColor(Color bc)
1525 m_baseBackgroundColor = bc;
1528 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
1530 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1531 FrameView* view = frame->view();
1535 view->setTransparent(transparent);
1536 view->setBaseBackgroundColor(backgroundColor);
1540 bool FrameView::shouldUpdateWhileOffscreen() const
1542 return m_shouldUpdateWhileOffscreen;
1545 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
1547 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
1550 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
1552 if (!m_enqueueEvents) {
1553 ExceptionCode ec = 0;
1554 eventTarget->dispatchEvent(event, ec);
1558 ScheduledEvent* scheduledEvent = new ScheduledEvent;
1559 scheduledEvent->m_event = event;
1560 scheduledEvent->m_eventTarget = eventTarget;
1561 m_scheduledEvents.append(scheduledEvent);
1564 void FrameView::pauseScheduledEvents()
1566 ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
1570 void FrameView::resumeScheduledEvents()
1573 if (!m_enqueueEvents)
1574 dispatchScheduledEvents();
1575 ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
1578 void FrameView::scrollToAnchor()
1580 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
1584 if (!anchorNode->renderer())
1588 if (anchorNode != m_frame->document())
1589 rect = anchorNode->getRect();
1591 // Scroll nested layers and frames to reveal the anchor.
1592 // Align to the top and to the closest side (this matches other browsers).
1593 anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
1595 if (AXObjectCache::accessibilityEnabled())
1596 m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get());
1598 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
1599 m_maintainScrollPositionAnchor = anchorNode;
1602 void FrameView::updateWidget(RenderEmbeddedObject* object)
1604 ASSERT(!object->node() || object->node()->isElementNode());
1605 Element* ownerElement = static_cast<Element*>(object->node());
1606 // The object may have already been destroyed (thus node cleared),
1607 // but FrameView holds a manual ref, so it won't have been deleted.
1608 ASSERT(m_widgetUpdateSet->contains(object));
1612 // No need to update if it's already crashed or known to be missing.
1613 if (object->pluginCrashedOrWasMissing())
1616 // FIXME: This could turn into a real virtual dispatch if we defined
1617 // updateWidget(bool) on HTMLElement.
1618 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag))
1619 static_cast<HTMLPlugInImageElement*>(ownerElement)->updateWidget(false);
1620 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
1621 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1622 else if (ownerElement->hasTagName(videoTag) || ownerElement->hasTagName(audioTag))
1623 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(false);
1626 ASSERT_NOT_REACHED();
1628 // Caution: it's possible the object was destroyed again, since loading a
1629 // plugin may run any arbitrary javascript.
1630 object->updateWidgetPosition();
1633 bool FrameView::updateWidgets()
1635 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
1638 size_t size = m_widgetUpdateSet->size();
1640 Vector<RenderEmbeddedObject*> objects;
1641 objects.reserveCapacity(size);
1643 RenderEmbeddedObjectSet::const_iterator end = m_widgetUpdateSet->end();
1644 for (RenderEmbeddedObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
1645 objects.uncheckedAppend(*it);
1649 for (size_t i = 0; i < size; ++i) {
1650 RenderEmbeddedObject* object = objects[i];
1651 updateWidget(object);
1652 m_widgetUpdateSet->remove(object);
1655 RenderArena* arena = m_frame->document()->renderArena();
1656 for (size_t i = 0; i < size; ++i)
1657 objects[i]->deref(arena);
1659 return m_widgetUpdateSet->isEmpty();
1662 void FrameView::performPostLayoutTasks()
1664 m_hasPendingPostLayoutTasks = false;
1666 if (m_firstLayoutCallbackPending) {
1667 m_firstLayoutCallbackPending = false;
1668 m_frame->loader()->didFirstLayout();
1671 if (m_isVisuallyNonEmpty && m_firstVisuallyNonEmptyLayoutCallbackPending) {
1672 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
1673 m_frame->loader()->didFirstVisuallyNonEmptyLayout();
1676 RenderView* root = m_frame->contentRenderer();
1678 root->updateWidgetPositions();
1680 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
1681 if (updateWidgets())
1687 resumeScheduledEvents();
1689 if (!root->printing()) {
1690 IntSize currentSize = IntSize(width(), height());
1691 float currentZoomFactor = root->style()->zoom();
1692 bool resized = !m_firstLayout && (currentSize != m_lastLayoutSize || currentZoomFactor != m_lastZoomFactor);
1693 m_lastLayoutSize = currentSize;
1694 m_lastZoomFactor = currentZoomFactor;
1696 m_frame->eventHandler()->sendResizeEvent();
1700 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
1702 performPostLayoutTasks();
1705 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
1707 if (!m_viewportRenderer)
1710 if (m_overflowStatusDirty) {
1711 m_horizontalOverflow = horizontalOverflow;
1712 m_verticalOverflow = verticalOverflow;
1713 m_overflowStatusDirty = false;
1717 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
1718 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
1720 if (horizontalOverflowChanged || verticalOverflowChanged) {
1721 m_horizontalOverflow = horizontalOverflow;
1722 m_verticalOverflow = verticalOverflow;
1724 scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
1725 verticalOverflowChanged, verticalOverflow),
1726 m_viewportRenderer->node());
1731 void FrameView::dispatchScheduledEvents()
1733 if (m_scheduledEvents.isEmpty())
1736 Vector<ScheduledEvent*> scheduledEventsCopy = m_scheduledEvents;
1737 m_scheduledEvents.clear();
1739 Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end();
1740 for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) {
1741 ScheduledEvent* scheduledEvent = *it;
1743 ExceptionCode ec = 0;
1745 // Only dispatch events to nodes that are in the document
1746 if (scheduledEvent->m_eventTarget->inDocument())
1747 scheduledEvent->m_eventTarget->dispatchEvent(scheduledEvent->m_event, ec);
1749 delete scheduledEvent;
1753 IntRect FrameView::windowClipRect(bool clipToContents) const
1755 ASSERT(m_frame->view() == this);
1757 // Set our clip rect to be our contents.
1758 IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
1759 if (!m_frame || !m_frame->document() || !m_frame->document()->ownerElement())
1762 // Take our owner element and get the clip rect from the enclosing layer.
1763 Element* elt = m_frame->document()->ownerElement();
1764 RenderLayer* layer = elt->renderer()->enclosingLayer();
1765 // FIXME: layer should never be null, but sometimes seems to be anyway.
1768 FrameView* parentView = elt->document()->view();
1769 clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
1773 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const
1775 // If we have no layer, just return our window clip rect.
1777 return windowClipRect();
1779 // Apply the clip from the layer.
1781 if (clipToLayerContents)
1782 clipRect = layer->childrenClipRect();
1784 clipRect = layer->selfClipRect();
1785 clipRect = contentsToWindow(clipRect);
1786 return intersection(clipRect, windowClipRect());
1789 bool FrameView::isActive() const
1791 Page* page = frame()->page();
1792 return page && page->focusController()->isActive();
1795 void FrameView::valueChanged(Scrollbar* bar)
1797 // Figure out if we really moved.
1798 IntSize offset = scrollOffset();
1799 ScrollView::valueChanged(bar);
1800 if (offset != scrollOffset())
1801 scrollPositionChanged();
1802 frame()->loader()->client()->didChangeScrollOffset();
1805 void FrameView::valueChanged(const IntSize& scrollDelta)
1807 ScrollView::valueChanged(scrollDelta);
1808 frame()->eventHandler()->sendScrollEvent();
1809 frame()->loader()->client()->didChangeScrollOffset();
1812 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
1814 // Add in our offset within the FrameView.
1815 IntRect dirtyRect = rect;
1816 dirtyRect.move(scrollbar->x(), scrollbar->y());
1817 invalidateRect(dirtyRect);
1820 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
1822 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
1825 IntRect FrameView::windowResizerRect() const
1827 Page* page = frame() ? frame()->page() : 0;
1830 return page->chrome()->windowResizerRect();
1833 #if ENABLE(DASHBOARD_SUPPORT)
1834 void FrameView::updateDashboardRegions()
1836 Document* document = m_frame->document();
1837 if (!document->hasDashboardRegions())
1839 Vector<DashboardRegionValue> newRegions;
1840 document->renderBox()->collectDashboardRegions(newRegions);
1841 if (newRegions == document->dashboardRegions())
1843 document->setDashboardRegions(newRegions);
1844 Page* page = m_frame->page();
1847 page->chrome()->client()->dashboardRegionsChanged();
1851 void FrameView::invalidateScrollCorner()
1853 invalidateRect(scrollCornerRect());
1856 void FrameView::updateScrollCorner()
1858 RenderObject* renderer = 0;
1859 RefPtr<RenderStyle> cornerStyle;
1861 if (!scrollCornerRect().isEmpty()) {
1862 // Try the <body> element first as a scroll corner source.
1863 Document* doc = m_frame->document();
1864 Element* body = doc ? doc->body() : 0;
1865 if (body && body->renderer()) {
1866 renderer = body->renderer();
1867 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
1871 // If the <body> didn't have a custom style, then the root element might.
1872 Element* docElement = doc ? doc->documentElement() : 0;
1873 if (docElement && docElement->renderer()) {
1874 renderer = docElement->renderer();
1875 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
1880 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
1881 if (RenderPart* renderer = m_frame->ownerRenderer())
1882 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
1887 if (!m_scrollCorner)
1888 m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document());
1889 m_scrollCorner->setStyle(cornerStyle.release());
1890 invalidateRect(scrollCornerRect());
1891 } else if (m_scrollCorner) {
1892 m_scrollCorner->destroy();
1897 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
1899 if (context->updatingControlTints()) {
1900 updateScrollCorner();
1904 if (m_scrollCorner) {
1905 m_scrollCorner->paintIntoRect(context, cornerRect.x(), cornerRect.y(), cornerRect);
1909 ScrollView::paintScrollCorner(context, cornerRect);
1912 bool FrameView::hasCustomScrollbars() const
1914 const HashSet<RefPtr<Widget> >* viewChildren = children();
1915 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
1916 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
1917 Widget* widget = current->get();
1918 if (widget->isFrameView()) {
1919 if (static_cast<FrameView*>(widget)->hasCustomScrollbars())
1921 } else if (widget->isScrollbar()) {
1922 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
1923 if (scrollbar->isCustomScrollbar())
1931 void FrameView::updateControlTints()
1933 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
1934 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
1935 // This is only done if the theme supports control tinting. It's up to the theme and platform
1936 // to define when controls get the tint and to call this function when that changes.
1938 // Optimize the common case where we bring a window to the front while it's still empty.
1939 if (!m_frame || m_frame->loader()->url().isEmpty())
1942 if ((m_frame->contentRenderer() && m_frame->contentRenderer()->theme()->supportsControlTints()) || hasCustomScrollbars()) {
1945 PlatformGraphicsContext* const noContext = 0;
1946 GraphicsContext context(noContext);
1947 context.setUpdatingControlTints(true);
1948 if (platformWidget())
1949 paintContents(&context, visibleContentRect());
1951 paint(&context, frameRect());
1955 bool FrameView::wasScrolledByUser() const
1957 return m_wasScrolledByUser;
1960 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
1962 if (m_inProgrammaticScroll)
1964 m_maintainScrollPositionAnchor = 0;
1965 m_wasScrolledByUser = wasScrolledByUser;
1968 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
1973 #if ENABLE(INSPECTOR)
1974 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent())
1975 timelineAgent->willPaint(rect);
1978 Document* document = frame()->document();
1982 if (document->printing())
1983 fillWithRed = false; // Printing, don't fill with red (can't remember why).
1984 else if (document->ownerElement())
1985 fillWithRed = false; // Subframe, don't fill with red.
1986 else if (isTransparent())
1987 fillWithRed = false; // Transparent, don't fill with red.
1988 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
1989 fillWithRed = false; // Selections are transparent, don't fill with red.
1990 else if (m_nodeToDraw)
1991 fillWithRed = false; // Element images are transparent, don't fill with red.
1996 p->fillRect(rect, Color(0xFF, 0, 0), DeviceColorSpace);
1999 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
2000 if (isTopLevelPainter)
2001 sCurrentPaintTimeStamp = currentTime();
2003 RenderView* contentRenderer = frame()->contentRenderer();
2004 if (!contentRenderer) {
2005 LOG_ERROR("called FrameView::paint with nil renderer");
2009 ASSERT(!needsLayout());
2013 #if USE(ACCELERATED_COMPOSITING)
2014 if (!p->paintingDisabled()) {
2015 if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer())
2016 rootLayer->syncCompositingState();
2020 ASSERT(!m_isPainting);
2022 m_isPainting = true;
2024 // m_nodeToDraw is used to draw only one element (and its descendants)
2025 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
2027 PaintBehavior oldPaintBehavior = m_paintBehavior;
2028 if (m_paintBehavior == PaintBehaviorNormal)
2029 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
2031 if (document->printing())
2032 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2034 contentRenderer->layer()->paint(p, rect, m_paintBehavior, eltRenderer);
2036 m_paintBehavior = oldPaintBehavior;
2038 m_isPainting = false;
2039 m_lastPaintTime = currentTime();
2041 #if ENABLE(DASHBOARD_SUPPORT)
2042 // Regions may have changed as a result of the visibility/z-index of element changing.
2043 if (document->dashboardRegionsDirty())
2044 updateDashboardRegions();
2047 if (isTopLevelPainter)
2048 sCurrentPaintTimeStamp = 0;
2050 #if ENABLE(INSPECTOR)
2051 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent())
2052 timelineAgent->didPaint();
2056 void FrameView::setPaintBehavior(PaintBehavior behavior)
2058 m_paintBehavior = behavior;
2061 PaintBehavior FrameView::paintBehavior() const
2063 return m_paintBehavior;
2066 bool FrameView::isPainting() const
2068 return m_isPainting;
2071 void FrameView::setNodeToDraw(Node* node)
2073 m_nodeToDraw = node;
2076 void FrameView::updateLayoutAndStyleIfNeededRecursive()
2078 // We have to crawl our entire tree looking for any FrameViews that need
2079 // layout and make sure they are up to date.
2080 // Mac actually tests for intersection with the dirty region and tries not to
2081 // update layout for frames that are outside the dirty region. Not only does this seem
2082 // pointless (since those frames will have set a zero timer to layout anyway), but
2083 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
2084 // region but then become included later by the second frame adding rects to the dirty region
2085 // when it lays out.
2087 m_frame->document()->updateStyleIfNeeded();
2092 const HashSet<RefPtr<Widget> >* viewChildren = children();
2093 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2094 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2095 Widget* widget = (*current).get();
2096 if (widget->isFrameView())
2097 static_cast<FrameView*>(widget)->updateLayoutAndStyleIfNeededRecursive();
2100 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
2101 // painting, so we need to flush out any deferred repaints too.
2102 flushDeferredRepaints();
2105 void FrameView::flushDeferredRepaints()
2107 if (!m_deferredRepaintTimer.isActive())
2109 m_deferredRepaintTimer.stop();
2110 doDeferredRepaints();
2113 void FrameView::forceLayout(bool allowSubtree)
2115 layout(allowSubtree);
2118 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximumShrinkFactor, Frame::AdjustViewSizeOrNot shouldAdjustViewSize)
2120 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
2121 // the state of things before and after the layout
2122 RenderView *root = toRenderView(m_frame->document()->renderer());
2124 int pageW = ceilf(pageSize.width());
2125 root->setWidth(pageW);
2126 root->setPageHeight(pageSize.height());
2127 root->setNeedsLayoutAndPrefWidthsRecalc();
2130 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
2131 // page width when shrunk, we will lay out at maximum shrink and clip extra content.
2132 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
2133 // implementation should not do this!
2134 int rightmostPos = root->rightmostPosition();
2135 if (rightmostPos > pageSize.width()) {
2136 pageW = std::min<int>(rightmostPos, ceilf(pageSize.width() * maximumShrinkFactor));
2137 if (pageSize.height())
2138 root->setPageHeight(pageW / pageSize.width() * pageSize.height());
2139 root->setWidth(pageW);
2140 root->setNeedsLayoutAndPrefWidthsRecalc();
2142 int docHeight = root->bottomLayoutOverflow();
2143 root->clearLayoutOverflow();
2144 root->addLayoutOverflow(IntRect(0, 0, pageW, docHeight)); // This is how we clip in case we overflow again.
2148 if (shouldAdjustViewSize)
2152 void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
2154 RenderView* root = m_frame->contentRenderer();
2156 // Use a context with painting disabled.
2157 GraphicsContext context((PlatformGraphicsContext*)0);
2158 root->setTruncatedAt((int)floorf(oldBottom));
2159 IntRect dirtyRect(0, (int)floorf(oldTop), root->rightLayoutOverflow(), (int)ceilf(oldBottom - oldTop));
2160 root->setPrintRect(dirtyRect);
2161 root->layer()->paint(&context, dirtyRect);
2162 *newBottom = root->bestTruncatedAt();
2163 if (*newBottom == 0)
2164 *newBottom = oldBottom;
2165 root->setPrintRect(IntRect());
2167 *newBottom = oldBottom;
2170 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
2172 IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
2174 // Convert from page ("absolute") to FrameView coordinates.
2175 rect.move(-scrollX(), -scrollY());
2180 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
2182 IntRect rect = viewRect;
2184 // Convert from FrameView coords into page ("absolute") coordinates.
2185 rect.move(scrollX(), scrollY());
2187 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
2188 // move the rect for now.
2189 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
2193 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
2195 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
2197 // Convert from page ("absolute") to FrameView coordinates.
2198 point.move(-scrollX(), -scrollY());
2202 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
2204 IntPoint point = viewPoint;
2206 // Convert from FrameView coords into page ("absolute") coordinates.
2207 point += IntSize(scrollX(), scrollY());
2209 return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
2212 IntRect FrameView::convertToContainingView(const IntRect& localRect) const
2214 if (const ScrollView* parentScrollView = parent()) {
2215 if (parentScrollView->isFrameView()) {
2216 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2217 // Get our renderer in the parent view
2218 RenderPart* renderer = m_frame->ownerRenderer();
2222 IntRect rect(localRect);
2223 // Add borders and padding??
2224 rect.move(renderer->borderLeft() + renderer->paddingLeft(),
2225 renderer->borderTop() + renderer->paddingTop());
2226 return parentView->convertFromRenderer(renderer, rect);
2229 return Widget::convertToContainingView(localRect);
2235 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
2237 if (const ScrollView* parentScrollView = parent()) {
2238 if (parentScrollView->isFrameView()) {
2239 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2241 // Get our renderer in the parent view
2242 RenderPart* renderer = m_frame->ownerRenderer();
2246 IntRect rect = parentView->convertToRenderer(renderer, parentRect);
2247 // Subtract borders and padding
2248 rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
2249 -renderer->borderTop() - renderer->paddingTop());
2253 return Widget::convertFromContainingView(parentRect);
2259 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
2261 if (const ScrollView* parentScrollView = parent()) {
2262 if (parentScrollView->isFrameView()) {
2263 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2265 // Get our renderer in the parent view
2266 RenderPart* renderer = m_frame->ownerRenderer();
2270 IntPoint point(localPoint);
2272 // Add borders and padding
2273 point.move(renderer->borderLeft() + renderer->paddingLeft(),
2274 renderer->borderTop() + renderer->paddingTop());
2275 return parentView->convertFromRenderer(renderer, point);
2278 return Widget::convertToContainingView(localPoint);
2284 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) 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 = parentView->convertToRenderer(renderer, parentPoint);
2296 // Subtract borders and padding
2297 point.move(-renderer->borderLeft() - renderer->paddingLeft(),
2298 -renderer->borderTop() - renderer->paddingTop());
2302 return Widget::convertFromContainingView(parentPoint);
2309 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
2311 s_deferredRepaintDelay = p;
2314 // Negative value would mean that first few repaints happen without a delay
2315 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)
2317 s_initialDeferredRepaintDelayDuringLoading = p;
2320 // The delay grows on each repaint to this maximum value
2321 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)
2323 s_maxDeferredRepaintDelayDuringLoading = p;
2326 // On each repaint the delay increases by this amount
2327 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)
2329 s_deferredRepaintDelayIncrementDuringLoading = p;
2332 } // namespace WebCore