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"
33 #include "ChromeClient.h"
34 #include "DocLoader.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 "InspectorTimelineAgent.h"
48 #include "OverflowEvent.h"
49 #include "RenderEmbeddedObject.h"
50 #include "RenderLayer.h"
51 #include "RenderPart.h"
52 #include "RenderScrollbar.h"
53 #include "RenderScrollbarPart.h"
54 #include "RenderTheme.h"
55 #include "RenderView.h"
57 #include "TextResourceDecoder.h"
58 #include <wtf/CurrentTime.h>
60 #ifdef ANDROID_INSTRUMENT
61 #include "FrameTree.h"
62 #include "TimeCounter.h"
65 #if USE(ACCELERATED_COMPOSITING)
66 #include "RenderLayerCompositor.h"
70 #include "SVGDocument.h"
71 #include "SVGLocatable.h"
73 #include "SVGPreserveAspectRatio.h"
74 #include "SVGSVGElement.h"
75 #include "SVGViewElement.h"
76 #include "SVGViewSpec.h"
79 #if ENABLE(TILED_BACKING_STORE)
80 #include "TiledBackingStore.h"
84 #include "WebCoreFrameBridge.h"
89 using namespace HTMLNames;
91 double FrameView::sCurrentPaintTimeStamp = 0.0;
93 // REPAINT_THROTTLING now chooses default values for throttling parameters.
94 // Should be removed when applications start using runtime configuration.
95 #if ENABLE(REPAINT_THROTTLING)
97 double FrameView::s_deferredRepaintDelay = 0.025;
98 // Negative value would mean that first few repaints happen without a delay
99 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
100 // The delay grows on each repaint to this maximum value
101 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
102 // On each repaint the delay increses by this amount
103 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
105 // FIXME: Repaint throttling could be good to have on all platform.
106 // The balance between CPU use and repaint frequency will need some tuning for desktop.
107 // More hooks may be needed to reset the delay on things like GIF and CSS animations.
108 double FrameView::s_deferredRepaintDelay = 0;
109 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
110 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
111 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
114 // The maximum number of updateWidgets iterations that should be done before returning.
115 static const unsigned maxUpdateWidgetsIterations = 2;
117 struct ScheduledEvent : Noncopyable {
118 RefPtr<Event> m_event;
119 RefPtr<Node> m_eventTarget;
122 static inline float parentZoomFactor(Frame* frame)
124 Frame* parent = frame->tree()->parent();
127 FrameView* parentView = parent->view();
130 return parentView->zoomFactor();
133 FrameView::FrameView(Frame* frame)
135 , m_canHaveScrollbars(true)
136 , m_slowRepaintObjectCount(0)
137 , m_fixedObjectCount(0)
138 , m_layoutTimer(this, &FrameView::layoutTimerFired)
140 , m_hasPendingPostLayoutTasks(false)
141 , m_inSynchronousPostLayout(false)
142 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
143 , m_isTransparent(false)
144 , m_baseBackgroundColor(Color::white)
145 , m_mediaType("screen")
147 , m_overflowStatusDirty(true)
148 , m_viewportRenderer(0)
149 , m_wasScrolledByUser(false)
150 , m_inProgrammaticScroll(false)
151 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
152 , m_shouldUpdateWhileOffscreen(true)
153 , m_deferSetNeedsLayouts(0)
154 , m_setNeedsLayoutWasDeferred(false)
156 , m_zoomFactor(parentZoomFactor(frame))
161 PassRefPtr<FrameView> FrameView::create(Frame* frame)
163 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
165 return view.release();
168 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize)
170 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
171 view->Widget::setFrameRect(IntRect(view->pos(), initialSize));
173 return view.release();
176 FrameView::~FrameView()
178 if (m_hasPendingPostLayoutTasks) {
179 m_postLayoutTasksTimer.stop();
180 m_scheduledEvents.clear();
186 // Custom scrollbars should already be destroyed at this point
187 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
188 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
190 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
191 setHasVerticalScrollbar(false);
193 ASSERT(!m_scrollCorner);
194 ASSERT(m_scheduledEvents.isEmpty());
195 ASSERT(!m_enqueueEvents);
198 ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
199 RenderPart* renderer = m_frame->ownerRenderer();
200 if (renderer && renderer->widget() == this)
201 renderer->setWidget(0);
205 void FrameView::reset()
207 m_useSlowRepaints = false;
208 m_isOverlapped = false;
209 m_contentIsOpaque = false;
212 m_layoutTimer.stop();
214 m_delayedLayout = false;
215 m_doFullRepaint = true;
216 m_layoutSchedulingEnabled = true;
218 m_inSynchronousPostLayout = false;
219 m_hasPendingPostLayoutTasks = false;
221 m_nestedLayoutCount = 0;
222 m_postLayoutTasksTimer.stop();
223 m_firstLayout = true;
224 m_firstLayoutCallbackPending = false;
225 m_wasScrolledByUser = false;
226 m_lastLayoutSize = IntSize();
227 m_lastZoomFactor = 1.0f;
229 m_deferringRepaints = 0;
231 m_repaintRects.clear();
232 m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading;
233 m_deferredRepaintTimer.stop();
235 m_paintBehavior = PaintBehaviorNormal;
236 m_isPainting = false;
237 m_isVisuallyNonEmpty = false;
238 m_firstVisuallyNonEmptyLayoutCallbackPending = true;
239 m_maintainScrollPositionAnchor = 0;
242 bool FrameView::isFrameView() const
247 void FrameView::clearFrame()
252 void FrameView::resetScrollbars()
254 // Reset the document's scrollbars back to our defaults before we yield the floor.
255 m_firstLayout = true;
256 setScrollbarsSuppressed(true);
257 if (m_canHaveScrollbars)
258 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
260 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
261 setScrollbarsSuppressed(false);
264 void FrameView::init()
268 m_margins = IntSize(-1, -1); // undefined
271 // Propagate the marginwidth/height and scrolling modes to the view.
272 Element* ownerElement = m_frame && m_frame->document() ? m_frame->document()->ownerElement() : 0;
273 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
274 HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement);
275 if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
276 setCanHaveScrollbars(false);
277 int marginWidth = frameElt->getMarginWidth();
278 int marginHeight = frameElt->getMarginHeight();
279 if (marginWidth != -1)
280 setMarginWidth(marginWidth);
281 if (marginHeight != -1)
282 setMarginHeight(marginHeight);
286 void FrameView::detachCustomScrollbars()
291 Scrollbar* horizontalBar = horizontalScrollbar();
292 if (horizontalBar && horizontalBar->isCustomScrollbar())
293 setHasHorizontalScrollbar(false);
295 Scrollbar* verticalBar = verticalScrollbar();
296 if (verticalBar && verticalBar->isCustomScrollbar())
297 setHasVerticalScrollbar(false);
299 if (m_scrollCorner) {
300 m_scrollCorner->destroy();
305 void FrameView::clear()
307 setCanBlitOnScroll(true);
312 if (RenderPart* renderer = m_frame->ownerRenderer())
313 renderer->viewCleared();
316 setScrollbarsSuppressed(true);
319 bool FrameView::didFirstLayout() const
321 return !m_firstLayout;
324 void FrameView::invalidateRect(const IntRect& rect)
328 hostWindow()->invalidateContentsAndWindow(rect, false /*immediate*/);
335 RenderPart* renderer = m_frame->ownerRenderer();
339 IntRect repaintRect = rect;
340 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
341 renderer->borderTop() + renderer->paddingTop());
342 renderer->repaintRectangle(repaintRect);
345 void FrameView::setFrameRect(const IntRect& newRect)
347 IntRect oldRect = frameRect();
348 if (newRect == oldRect)
351 ScrollView::setFrameRect(newRect);
353 #if USE(ACCELERATED_COMPOSITING)
354 if (RenderView* root = m_frame->contentRenderer()) {
355 if (root->usesCompositing())
356 root->compositor()->frameViewDidChangeSize();
361 void FrameView::setMarginWidth(int w)
363 // make it update the rendering area when set
364 m_margins.setWidth(w);
367 void FrameView::setMarginHeight(int h)
369 // make it update the rendering area when set
370 m_margins.setHeight(h);
373 bool FrameView::avoidScrollbarCreation()
377 // with frame flattening no subframe can have scrollbars
378 // but we also cannot turn scrollbars of as we determine
379 // our flattening policy using that.
381 if (!m_frame->ownerElement())
384 if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
390 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
392 m_canHaveScrollbars = canHaveScrollbars;
393 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
396 void FrameView::updateCanHaveScrollbars()
400 scrollbarModes(hMode, vMode);
401 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
402 m_canHaveScrollbars = false;
404 m_canHaveScrollbars = true;
407 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
409 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
410 Document* doc = m_frame->document();
412 // Try the <body> element first as a scrollbar source.
413 Element* body = doc ? doc->body() : 0;
414 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
415 return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderer()->enclosingBox());
417 // If the <body> didn't have a custom style, then the root element might.
418 Element* docElement = doc ? doc->documentElement() : 0;
419 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
420 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox());
422 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
423 RenderPart* frameRenderer = m_frame->ownerRenderer();
424 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
425 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
427 // Nobody set a custom style, so we just use a native scrollbar.
428 return ScrollView::createScrollbar(orientation);
431 void FrameView::setContentsSize(const IntSize& size)
433 if (size == contentsSize())
436 m_deferSetNeedsLayouts++;
438 ScrollView::setContentsSize(size);
440 Page* page = frame() ? frame()->page() : 0;
444 page->chrome()->contentsSizeChanged(frame(), size); //notify only
446 m_deferSetNeedsLayouts--;
448 if (!m_deferSetNeedsLayouts)
449 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
452 void FrameView::adjustViewSize()
454 ASSERT(m_frame->view() == this);
455 RenderView* root = m_frame->contentRenderer();
459 setContentsSize(IntSize(root->rightLayoutOverflow(), root->bottomLayoutOverflow()));
462 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
464 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
465 // overflow:hidden and overflow:scroll on <body> as applying to the document's
466 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
467 // use the root element.
468 switch (o->style()->overflowX()) {
470 hMode = ScrollbarAlwaysOff;
473 hMode = ScrollbarAlwaysOn;
476 hMode = ScrollbarAuto;
479 // Don't set it at all.
483 switch (o->style()->overflowY()) {
485 vMode = ScrollbarAlwaysOff;
488 vMode = ScrollbarAlwaysOn;
491 vMode = ScrollbarAuto;
494 // Don't set it at all.
498 m_viewportRenderer = o;
501 #if USE(ACCELERATED_COMPOSITING)
502 void FrameView::updateCompositingLayers()
504 RenderView* view = m_frame->contentRenderer();
508 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
509 view->compositor()->cacheAcceleratedCompositingFlags();
510 view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange);
513 void FrameView::setNeedsOneShotDrawingSynchronization()
515 Page* page = frame() ? frame()->page() : 0;
517 page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
520 #endif // USE(ACCELERATED_COMPOSITING)
522 bool FrameView::hasCompositedContent() const
524 #if USE(ACCELERATED_COMPOSITING)
525 if (RenderView* view = m_frame->contentRenderer())
526 return view->compositor()->inCompositingMode();
531 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
532 void FrameView::enterCompositingMode()
534 #if USE(ACCELERATED_COMPOSITING)
535 if (RenderView* view = m_frame->contentRenderer()) {
536 view->compositor()->enableCompositingMode();
538 view->compositor()->scheduleCompositingLayerUpdate();
543 bool FrameView::isEnclosedInCompositingLayer() const
545 #if USE(ACCELERATED_COMPOSITING)
546 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
547 return frameOwnerRenderer && frameOwnerRenderer->containerForRepaint();
553 bool FrameView::syncCompositingStateRecursive()
555 #if USE(ACCELERATED_COMPOSITING)
556 ASSERT(m_frame->view() == this);
557 RenderView* contentRenderer = m_frame->contentRenderer();
558 if (!contentRenderer)
559 return true; // We don't want to keep trying to update layers if we have no renderer.
561 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
562 // layer content to occur before layout has happened, which will cause paintContents() to bail.
566 if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer())
567 rootLayer->syncCompositingState();
569 bool allSubframesSynced = true;
570 const HashSet<RefPtr<Widget> >* viewChildren = children();
571 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
572 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
573 Widget* widget = (*current).get();
574 if (widget->isFrameView()) {
575 bool synced = static_cast<FrameView*>(widget)->syncCompositingStateRecursive();
576 allSubframesSynced &= synced;
579 return allSubframesSynced;
580 #else // USE(ACCELERATED_COMPOSITING)
585 bool FrameView::isSoftwareRenderable() const
587 #if USE(ACCELERATED_COMPOSITING)
588 RenderView* view = m_frame->contentRenderer();
592 return !view->compositor()->has3DContent();
598 void FrameView::didMoveOnscreen()
600 RenderView* view = m_frame->contentRenderer();
602 view->didMoveOnscreen();
605 void FrameView::willMoveOffscreen()
607 RenderView* view = m_frame->contentRenderer();
609 view->willMoveOffscreen();
612 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
614 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
617 void FrameView::layout(bool allowSubtree)
622 m_layoutTimer.stop();
623 m_delayedLayout = false;
624 m_setNeedsLayoutWasDeferred = false;
626 // Protect the view from being deleted during layout (in recalcStyle)
627 RefPtr<FrameView> protector(this);
630 // FIXME: Do we need to set m_size.width here?
631 // FIXME: Should we set m_size.height here too?
632 m_size.setWidth(layoutWidth());
636 // we shouldn't enter layout() while painting
637 ASSERT(!isPainting());
641 #if ENABLE(INSPECTOR)
642 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent())
643 timelineAgent->willLayout();
646 if (!allowSubtree && m_layoutRoot) {
647 m_layoutRoot->markContainingBlocksForLayout(false);
651 ASSERT(m_frame->view() == this);
653 Document* document = m_frame->document();
655 m_layoutSchedulingEnabled = false;
657 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_hasPendingPostLayoutTasks) {
658 // This is a new top-level layout. If there are any remaining tasks from the previous
659 // layout, finish them now.
660 m_inSynchronousPostLayout = true;
661 m_postLayoutTasksTimer.stop();
662 performPostLayoutTasks();
663 m_inSynchronousPostLayout = false;
666 // Viewport-dependent media queries may cause us to need completely different style information.
668 if (document->styleSelector()->affectedByViewportChange())
669 document->styleSelectorChanged(RecalcStyleImmediately);
671 // Always ensure our style info is up-to-date. This can happen in situations where
672 // the layout beats any sort of style recalc update that needs to occur.
673 document->updateStyleIfNeeded();
675 bool subtree = m_layoutRoot;
677 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
678 // so there's no point to continuing to layout
679 if (protector->hasOneRef())
682 RenderObject* root = subtree ? m_layoutRoot : document->renderer();
684 // FIXME: Do we need to set m_size here?
685 m_layoutSchedulingEnabled = true;
689 #ifdef ANDROID_INSTRUMENT
690 if (!m_frame->tree() || !m_frame->tree()->parent())
691 android::TimeCounter::start(android::TimeCounter::LayoutTimeCounter);
694 m_nestedLayoutCount++;
698 if (m_canHaveScrollbars) {
699 hMode = ScrollbarAuto;
700 vMode = ScrollbarAuto;
702 hMode = ScrollbarAlwaysOff;
703 vMode = ScrollbarAlwaysOff;
707 Node* documentElement = document->documentElement();
708 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
709 Node* body = document->body();
710 if (body && body->renderer()) {
711 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
712 #if !defined(ANDROID_FLATTEN_IFRAME) && !defined(ANDROID_FLATTEN_FRAMESET)
713 body->renderer()->setChildNeedsLayout(true);
714 vMode = ScrollbarAlwaysOff;
715 hMode = ScrollbarAlwaysOff;
717 } else if (body->hasTagName(bodyTag)) {
718 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewHeight())
719 body->renderer()->setChildNeedsLayout(true);
720 // It's sufficient to just check the X overflow,
721 // since it's illegal to have visible in only one direction.
722 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
723 applyOverflowToViewport(o, hMode, vMode);
725 } else if (rootRenderer) {
727 if (documentElement->isSVGElement()) {
728 if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight()))
729 rootRenderer->setChildNeedsLayout(true);
731 applyOverflowToViewport(rootRenderer, hMode, vMode);
733 applyOverflowToViewport(rootRenderer, hMode, vMode);
736 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
737 if (m_firstLayout && !document->ownerElement())
738 printf("Elapsed time before first layout: %d\n", document->elapsedTime());
742 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
745 // Now set our scrollbar state for the layout.
746 ScrollbarMode currentHMode = horizontalScrollbarMode();
747 ScrollbarMode currentVMode = verticalScrollbarMode();
749 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
751 setScrollbarsSuppressed(true);
753 m_firstLayout = false;
754 m_firstLayoutCallbackPending = true;
755 m_lastLayoutSize = IntSize(width(), height());
756 m_lastZoomFactor = root->style()->zoom();
758 // Set the initial vMode to AlwaysOn if we're auto.
759 if (vMode == ScrollbarAuto)
760 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
761 // Set the initial hMode to AlwaysOff if we're auto.
762 if (hMode == ScrollbarAuto)
763 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
765 setScrollbarModes(hMode, vMode);
766 setScrollbarsSuppressed(false, true);
768 setScrollbarModes(hMode, vMode);
771 IntSize oldSize = m_size;
773 m_size = IntSize(layoutWidth(), layoutHeight());
775 if (oldSize != m_size)
776 m_doFullRepaint = true;
779 RenderLayer* layer = root->enclosingLayer();
781 pauseScheduledEvents();
783 bool disableLayoutState = false;
785 RenderView* view = root->view();
786 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
787 view->pushLayoutState(root);
788 if (disableLayoutState)
789 view->disableLayoutState();
793 beginDeferredRepaints();
795 endDeferredRepaints();
799 RenderView* view = root->view();
800 view->popLayoutState();
801 if (disableLayoutState)
802 view->enableLayoutState();
806 m_frame->selection()->setCaretRectNeedsUpdate();
807 m_frame->selection()->updateAppearance();
809 m_layoutSchedulingEnabled = true;
811 if (!subtree && !toRenderView(root)->printing())
814 // Now update the positions of all layers.
815 beginDeferredRepaints();
816 IntPoint cachedOffset;
817 layer->updateLayerPositions((m_doFullRepaint ? RenderLayer::DoFullRepaint : 0)
818 | RenderLayer::CheckForRepaint
819 | RenderLayer::IsCompositingUpdateRoot
820 | RenderLayer::UpdateCompositingLayers,
821 subtree ? 0 : &cachedOffset);
822 endDeferredRepaints();
824 #if USE(ACCELERATED_COMPOSITING)
825 updateCompositingLayers();
831 if (AXObjectCache::accessibilityEnabled())
832 root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true);
834 #if ENABLE(DASHBOARD_SUPPORT)
835 updateDashboardRegions();
838 #ifdef ANDROID_INSTRUMENT
839 if (!m_frame->tree()->parent())
840 android::TimeCounter::record(android::TimeCounter::LayoutTimeCounter, __FUNCTION__);
842 ASSERT(!root->needsLayout());
844 setCanBlitOnScroll(!useSlowRepaints());
846 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
847 updateOverflowStatus(layoutWidth() < contentsWidth(),
848 layoutHeight() < contentsHeight());
850 if (!m_hasPendingPostLayoutTasks) {
851 if (!m_inSynchronousPostLayout) {
852 m_inSynchronousPostLayout = true;
853 // Calls resumeScheduledEvents()
854 performPostLayoutTasks();
855 m_inSynchronousPostLayout = false;
858 if (!m_hasPendingPostLayoutTasks && (needsLayout() || m_inSynchronousPostLayout)) {
859 // If we need layout or are already in a synchronous call to postLayoutTasks(),
860 // defer widget updates and event dispatch until after we return. postLayoutTasks()
861 // can make us need to update again, and we can get stuck in a nasty cycle unless
862 // we call it through the timer here.
863 m_hasPendingPostLayoutTasks = true;
864 m_postLayoutTasksTimer.startOneShot(0);
866 pauseScheduledEvents();
871 resumeScheduledEvents();
872 ASSERT(m_enqueueEvents);
875 #if ENABLE(INSPECTOR)
876 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent())
877 timelineAgent->didLayout();
880 m_nestedLayoutCount--;
883 void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object)
885 if (!m_widgetUpdateSet)
886 m_widgetUpdateSet.set(new RenderEmbeddedObjectSet);
888 m_widgetUpdateSet->add(object);
891 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object)
893 if (!m_widgetUpdateSet)
896 m_widgetUpdateSet->remove(object);
899 void FrameView::setMediaType(const String& mediaType)
901 m_mediaType = mediaType;
904 String FrameView::mediaType() const
906 // See if we have an override type.
907 String overrideType = m_frame->loader()->client()->overrideMediaType();
908 if (!overrideType.isNull())
913 void FrameView::adjustMediaTypeForPrinting(bool printing)
916 if (m_mediaTypeWhenNotPrinting.isNull())
917 m_mediaTypeWhenNotPrinting = mediaType();
918 setMediaType("print");
920 if (!m_mediaTypeWhenNotPrinting.isNull())
921 setMediaType(m_mediaTypeWhenNotPrinting);
922 m_mediaTypeWhenNotPrinting = String();
926 bool FrameView::useSlowRepaints() const
928 return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || m_isOverlapped || !m_contentIsOpaque;
931 bool FrameView::useSlowRepaintsIfNotOverlapped() const
933 return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || !m_contentIsOpaque;
936 void FrameView::setUseSlowRepaints()
938 m_useSlowRepaints = true;
939 setCanBlitOnScroll(false);
942 void FrameView::addSlowRepaintObject()
944 if (!m_slowRepaintObjectCount)
945 setCanBlitOnScroll(false);
946 m_slowRepaintObjectCount++;
949 void FrameView::removeSlowRepaintObject()
951 ASSERT(m_slowRepaintObjectCount > 0);
952 m_slowRepaintObjectCount--;
953 if (!m_slowRepaintObjectCount)
954 setCanBlitOnScroll(!useSlowRepaints());
957 void FrameView::addFixedObject()
959 if (!m_fixedObjectCount && platformWidget())
960 setCanBlitOnScroll(false);
961 ++m_fixedObjectCount;
964 void FrameView::removeFixedObject()
966 ASSERT(m_fixedObjectCount > 0);
967 --m_fixedObjectCount;
968 if (!m_fixedObjectCount)
969 setCanBlitOnScroll(!useSlowRepaints());
972 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
974 const size_t fixedObjectThreshold = 5;
976 RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0;
977 if (RenderView* root = m_frame->contentRenderer())
978 positionedObjects = root->positionedObjects();
980 if (!positionedObjects || positionedObjects->isEmpty()) {
981 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
985 // Get the rects of the fixed objects visible in the rectToScroll
986 Vector<IntRect, fixedObjectThreshold> subRectToUpdate;
987 bool updateInvalidatedSubRect = true;
988 RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
989 for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
990 RenderBox* renderBox = *it;
991 if (renderBox->style()->position() != FixedPosition)
993 IntRect updateRect = renderBox->layer()->repaintRectIncludingDescendants();
994 updateRect = contentsToWindow(updateRect);
996 updateRect.intersect(rectToScroll);
997 if (!updateRect.isEmpty()) {
998 if (subRectToUpdate.size() >= fixedObjectThreshold) {
999 updateInvalidatedSubRect = false;
1002 subRectToUpdate.append(updateRect);
1007 if (updateInvalidatedSubRect) {
1009 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1011 // 2) update the area of fixed objects that has been invalidated
1012 size_t fixObjectsCount = subRectToUpdate.size();
1013 for (size_t i = 0; i < fixObjectsCount; ++i) {
1014 IntRect updateRect = subRectToUpdate[i];
1015 IntRect scrolledRect = updateRect;
1016 scrolledRect.move(scrollDelta);
1017 updateRect.unite(scrolledRect);
1018 updateRect.intersect(rectToScroll);
1019 hostWindow()->invalidateContentsAndWindow(updateRect, false);
1024 // the number of fixed objects exceed the threshold, we cannot use the fast path
1028 // Note that this gets called at painting time.
1029 void FrameView::setIsOverlapped(bool isOverlapped)
1031 if (isOverlapped == m_isOverlapped)
1034 m_isOverlapped = isOverlapped;
1035 setCanBlitOnScroll(!useSlowRepaints());
1037 #if USE(ACCELERATED_COMPOSITING)
1038 // Overlap can affect compositing tests, so if it changes, we need to trigger
1039 // a layer update in the parent document.
1040 if (hasCompositedContent()) {
1041 if (Frame* parentFrame = m_frame->tree()->parent()) {
1042 if (RenderView* parentView = parentFrame->contentRenderer()) {
1043 RenderLayerCompositor* compositor = parentView->compositor();
1044 compositor->setCompositingLayersNeedRebuild();
1045 compositor->scheduleCompositingLayerUpdate();
1052 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1054 if (contentIsOpaque == m_contentIsOpaque)
1057 m_contentIsOpaque = contentIsOpaque;
1058 setCanBlitOnScroll(!useSlowRepaints());
1061 void FrameView::restoreScrollbar()
1063 setScrollbarsSuppressed(false);
1066 bool FrameView::scrollToFragment(const KURL& url)
1068 // If our URL has no ref, then we have no place we need to jump to.
1069 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1070 // and possibly repaint because :target pseudo class may have been
1071 // set (see bug 11321).
1072 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1075 String fragmentIdentifier = url.fragmentIdentifier();
1076 if (scrollToAnchor(fragmentIdentifier))
1079 // Try again after decoding the ref, based on the document's encoding.
1080 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1081 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1086 bool FrameView::scrollToAnchor(const String& name)
1088 ASSERT(m_frame->document());
1090 if (!m_frame->document()->haveStylesheetsLoaded()) {
1091 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1095 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1097 Element* anchorNode = m_frame->document()->findAnchor(name);
1100 if (m_frame->document()->isSVGDocument()) {
1101 if (name.startsWith("xpointer(")) {
1102 // We need to parse the xpointer reference here
1103 } else if (name.startsWith("svgView(")) {
1104 RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement();
1105 if (!svg->currentView()->parseViewSpec(name))
1107 svg->setUseCurrentView(true);
1109 if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) {
1110 RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0;
1111 if (viewElement.get()) {
1112 RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(SVGLocatable::nearestViewportElement(viewElement.get()));
1113 svg->inheritViewAttributes(viewElement.get());
1117 // FIXME: need to decide which <svg> to focus on, and zoom to that one
1118 // FIXME: need to actually "highlight" the viewTarget(s)
1122 m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target.
1124 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1125 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1128 #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR
1129 // TODO(andreip): check with Grace if this is correct.
1130 android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedAction(true);
1132 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1133 #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR
1134 android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedAction(false);
1139 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1141 m_maintainScrollPositionAnchor = anchorNode;
1142 if (!m_maintainScrollPositionAnchor)
1145 // We need to update the layout before scrolling, otherwise we could
1146 // really mess things up if an anchor scroll comes at a bad moment.
1147 m_frame->document()->updateStyleIfNeeded();
1148 // Only do a layout if changes have occurred that make it necessary.
1149 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
1155 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1157 bool wasInProgrammaticScroll = m_inProgrammaticScroll;
1158 m_inProgrammaticScroll = true;
1159 m_maintainScrollPositionAnchor = 0;
1160 ScrollView::setScrollPosition(scrollPoint);
1161 m_inProgrammaticScroll = wasInProgrammaticScroll;
1164 void FrameView::scrollPositionChangedViaPlatformWidget()
1166 repaintFixedElementsAfterScrolling();
1167 scrollPositionChanged();
1170 void FrameView::scrollPositionChanged()
1172 frame()->eventHandler()->sendScrollEvent();
1174 #if USE(ACCELERATED_COMPOSITING)
1175 if (RenderView* root = m_frame->contentRenderer()) {
1176 if (root->usesCompositing())
1177 root->compositor()->frameViewDidScroll(scrollPosition());
1182 void FrameView::repaintFixedElementsAfterScrolling()
1184 // For fixed position elements, update widget positions and compositing layers after scrolling,
1185 // but only if we're not inside of layout.
1186 if (!m_nestedLayoutCount && hasFixedObjects()) {
1187 if (RenderView* root = m_frame->contentRenderer()) {
1188 root->updateWidgetPositions();
1189 root->layer()->updateRepaintRectsAfterScroll();
1190 #if USE(ACCELERATED_COMPOSITING)
1191 root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
1197 HostWindow* FrameView::hostWindow() const
1199 Page* page = frame() ? frame()->page() : 0;
1202 return page->chrome();
1205 const unsigned cRepaintRectUnionThreshold = 25;
1207 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
1209 ASSERT(!m_frame->document()->ownerElement());
1211 double delay = adjustedDeferredRepaintDelay();
1212 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
1213 IntRect paintRect = r;
1214 if (!paintsEntireContents())
1215 paintRect.intersect(visibleContentRect());
1216 #ifdef ANDROID_CAPTURE_OFFSCREEN_PAINTS
1218 ScrollView::platformOffscreenContentRectangle(visibleContentRect(), r);
1220 if (paintRect.isEmpty())
1222 if (m_repaintCount == cRepaintRectUnionThreshold) {
1223 IntRect unionedRect;
1224 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
1225 unionedRect.unite(m_repaintRects[i]);
1226 m_repaintRects.clear();
1227 m_repaintRects.append(unionedRect);
1229 if (m_repaintCount < cRepaintRectUnionThreshold)
1230 m_repaintRects.append(paintRect);
1232 m_repaintRects[0].unite(paintRect);
1235 if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive())
1236 m_deferredRepaintTimer.startOneShot(delay);
1240 if (!immediate && isOffscreen() && !shouldUpdateWhileOffscreen())
1243 #if ENABLE(TILED_BACKING_STORE)
1244 if (frame()->tiledBackingStore()) {
1245 frame()->tiledBackingStore()->invalidate(r);
1249 ScrollView::repaintContentRectangle(r, immediate);
1252 void FrameView::visibleContentsResized()
1254 // We check to make sure the view is attached to a frame() as this method can
1255 // be triggered before the view is attached by Frame::createView(...) setting
1256 // various values such as setScrollBarModes(...) for example. An ASSERT is
1257 // triggered when a view is layout before being attached to a frame().
1258 if (!frame()->view())
1265 void FrameView::beginDeferredRepaints()
1267 Page* page = m_frame->page();
1268 if (page->mainFrame() != m_frame)
1269 return page->mainFrame()->view()->beginDeferredRepaints();
1271 m_deferringRepaints++;
1275 void FrameView::endDeferredRepaints()
1277 Page* page = m_frame->page();
1278 if (page->mainFrame() != m_frame)
1279 return page->mainFrame()->view()->endDeferredRepaints();
1281 ASSERT(m_deferringRepaints > 0);
1283 if (--m_deferringRepaints)
1286 if (m_deferredRepaintTimer.isActive())
1289 if (double delay = adjustedDeferredRepaintDelay()) {
1290 m_deferredRepaintTimer.startOneShot(delay);
1294 doDeferredRepaints();
1297 void FrameView::checkStopDelayingDeferredRepaints()
1299 if (!m_deferredRepaintTimer.isActive())
1302 Document* document = m_frame->document();
1303 if (document && (document->parsing() || document->docLoader()->requestCount()))
1306 m_deferredRepaintTimer.stop();
1308 doDeferredRepaints();
1311 void FrameView::doDeferredRepaints()
1313 ASSERT(!m_deferringRepaints);
1314 if (isOffscreen() && !shouldUpdateWhileOffscreen()) {
1315 m_repaintRects.clear();
1319 unsigned size = m_repaintRects.size();
1320 for (unsigned i = 0; i < size; i++) {
1321 #if ENABLE(TILED_BACKING_STORE)
1322 if (frame()->tiledBackingStore()) {
1323 frame()->tiledBackingStore()->invalidate(m_repaintRects[i]);
1327 ScrollView::repaintContentRectangle(m_repaintRects[i], false);
1329 m_repaintRects.clear();
1332 updateDeferredRepaintDelay();
1335 void FrameView::updateDeferredRepaintDelay()
1337 Document* document = m_frame->document();
1338 if (!document || (!document->parsing() && !document->docLoader()->requestCount())) {
1339 m_deferredRepaintDelay = s_deferredRepaintDelay;
1342 if (m_deferredRepaintDelay < s_maxDeferredRepaintDelayDuringLoading) {
1343 m_deferredRepaintDelay += s_deferredRepaintDelayIncrementDuringLoading;
1344 if (m_deferredRepaintDelay > s_maxDeferredRepaintDelayDuringLoading)
1345 m_deferredRepaintDelay = s_maxDeferredRepaintDelayDuringLoading;
1349 void FrameView::resetDeferredRepaintDelay()
1351 m_deferredRepaintDelay = 0;
1352 if (m_deferredRepaintTimer.isActive()) {
1353 m_deferredRepaintTimer.stop();
1354 if (!m_deferringRepaints)
1355 doDeferredRepaints();
1359 double FrameView::adjustedDeferredRepaintDelay() const
1361 if (!m_deferredRepaintDelay)
1363 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
1364 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
1367 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
1369 doDeferredRepaints();
1372 void FrameView::layoutTimerFired(Timer<FrameView>*)
1374 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1375 if (!m_frame->document()->ownerElement())
1376 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
1381 void FrameView::scheduleRelayout()
1383 // FIXME: We should assert the page is not in the page cache, but that is causing
1384 // too many false assertions. See <rdar://problem/7218118>.
1385 ASSERT(m_frame->view() == this);
1388 m_layoutRoot->markContainingBlocksForLayout(false);
1391 if (!m_layoutSchedulingEnabled)
1395 if (!m_frame->document()->shouldScheduleLayout())
1398 #if defined(ANDROID_FLATTEN_IFRAME) || defined(ANDROID_FLATTEN_FRAMESET)
1399 // This is the Android frame flattening code. The common code below is not
1400 // used as frameSetFlatteningEnabled() is false on Android.
1401 if (m_frame->ownerRenderer())
1402 m_frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc();
1405 // When frame flattening is enabled, the contents of the frame affects layout of the parent frames.
1406 // Also invalidate parent frame starting from the owner element of this frame.
1407 if (m_frame->settings() && m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) {
1408 if (m_frame->ownerElement()->hasTagName(iframeTag) || m_frame->ownerElement()->hasTagName(frameTag))
1409 m_frame->ownerRenderer()->setNeedsLayout(true, true);
1412 int delay = m_frame->document()->minimumLayoutDelay();
1413 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
1414 unscheduleRelayout();
1415 if (m_layoutTimer.isActive())
1418 m_delayedLayout = delay != 0;
1420 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1421 if (!m_frame->document()->ownerElement())
1422 printf("Scheduling layout for %d\n", delay);
1425 m_layoutTimer.startOneShot(delay * 0.001);
1428 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
1430 for (RenderObject* r = descendant; r; r = r->container()) {
1437 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
1439 ASSERT(m_frame->view() == this);
1441 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) {
1443 relayoutRoot->markContainingBlocksForLayout(false);
1447 if (layoutPending() || !m_layoutSchedulingEnabled) {
1448 if (m_layoutRoot != relayoutRoot) {
1449 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
1450 // Keep the current root
1451 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
1452 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
1453 // Re-root at relayoutRoot
1454 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
1455 m_layoutRoot = relayoutRoot;
1457 // Just do a full relayout
1459 m_layoutRoot->markContainingBlocksForLayout(false);
1461 relayoutRoot->markContainingBlocksForLayout(false);
1464 } else if (m_layoutSchedulingEnabled) {
1465 int delay = m_frame->document()->minimumLayoutDelay();
1466 m_layoutRoot = relayoutRoot;
1467 m_delayedLayout = delay != 0;
1468 m_layoutTimer.startOneShot(delay * 0.001);
1472 bool FrameView::layoutPending() const
1474 return m_layoutTimer.isActive();
1477 bool FrameView::needsLayout() const
1479 // This can return true in cases where the document does not have a body yet.
1480 // Document::shouldScheduleLayout takes care of preventing us from scheduling
1481 // layout in that case.
1484 RenderView* root = m_frame->contentRenderer();
1485 return layoutPending()
1486 || (root && root->needsLayout())
1488 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
1491 void FrameView::setNeedsLayout()
1493 if (m_deferSetNeedsLayouts) {
1494 m_setNeedsLayoutWasDeferred = true;
1497 RenderView* root = m_frame->contentRenderer();
1499 root->setNeedsLayout(true);
1502 void FrameView::unscheduleRelayout()
1504 m_postLayoutTasksTimer.stop();
1506 if (!m_layoutTimer.isActive())
1509 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1510 if (!m_frame->document()->ownerElement())
1511 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
1514 m_layoutTimer.stop();
1515 m_delayedLayout = false;
1518 bool FrameView::isTransparent() const
1520 return m_isTransparent;
1523 void FrameView::setTransparent(bool isTransparent)
1525 m_isTransparent = isTransparent;
1528 Color FrameView::baseBackgroundColor() const
1530 return m_baseBackgroundColor;
1533 void FrameView::setBaseBackgroundColor(Color bc)
1537 m_baseBackgroundColor = bc;
1540 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
1542 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1543 FrameView* view = frame->view();
1547 view->setTransparent(transparent);
1548 view->setBaseBackgroundColor(backgroundColor);
1552 bool FrameView::shouldUpdateWhileOffscreen() const
1554 return m_shouldUpdateWhileOffscreen;
1557 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
1559 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
1562 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
1564 if (!m_enqueueEvents) {
1565 ExceptionCode ec = 0;
1566 eventTarget->dispatchEvent(event, ec);
1570 ScheduledEvent* scheduledEvent = new ScheduledEvent;
1571 scheduledEvent->m_event = event;
1572 scheduledEvent->m_eventTarget = eventTarget;
1573 m_scheduledEvents.append(scheduledEvent);
1576 void FrameView::pauseScheduledEvents()
1578 ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
1582 void FrameView::resumeScheduledEvents()
1585 if (!m_enqueueEvents)
1586 dispatchScheduledEvents();
1587 ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
1590 void FrameView::scrollToAnchor()
1592 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
1596 if (!anchorNode->renderer())
1600 if (anchorNode != m_frame->document())
1601 rect = anchorNode->getRect();
1603 // Scroll nested layers and frames to reveal the anchor.
1604 // Align to the top and to the closest side (this matches other browsers).
1605 anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
1607 if (AXObjectCache::accessibilityEnabled())
1608 m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get());
1610 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
1611 m_maintainScrollPositionAnchor = anchorNode;
1614 bool FrameView::updateWidgets()
1616 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
1619 size_t size = m_widgetUpdateSet->size();
1621 Vector<RenderEmbeddedObject*> objects;
1622 objects.reserveCapacity(size);
1624 RenderEmbeddedObjectSet::const_iterator end = m_widgetUpdateSet->end();
1625 for (RenderEmbeddedObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
1626 objects.uncheckedAppend(*it);
1630 for (size_t i = 0; i < size; ++i) {
1631 RenderEmbeddedObject* object = objects[i];
1633 // The object may have been destroyed, but our manual ref() keeps the object from being deleted.
1634 object->updateWidget(false);
1635 object->updateWidgetPosition();
1637 m_widgetUpdateSet->remove(object);
1640 RenderArena* arena = m_frame->document()->renderArena();
1641 for (size_t i = 0; i < size; ++i)
1642 objects[i]->deref(arena);
1644 return m_widgetUpdateSet->isEmpty();
1647 void FrameView::performPostLayoutTasks()
1649 m_hasPendingPostLayoutTasks = false;
1651 if (m_firstLayoutCallbackPending) {
1652 m_firstLayoutCallbackPending = false;
1653 m_frame->loader()->didFirstLayout();
1656 if (m_isVisuallyNonEmpty && m_firstVisuallyNonEmptyLayoutCallbackPending) {
1657 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
1658 m_frame->loader()->didFirstVisuallyNonEmptyLayout();
1661 RenderView* root = m_frame->contentRenderer();
1663 root->updateWidgetPositions();
1665 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
1666 if (updateWidgets())
1672 resumeScheduledEvents();
1674 if (!root->printing()) {
1675 IntSize currentSize = IntSize(width(), height());
1676 float currentZoomFactor = root->style()->zoom();
1677 bool resized = !m_firstLayout && (currentSize != m_lastLayoutSize || currentZoomFactor != m_lastZoomFactor);
1678 m_lastLayoutSize = currentSize;
1679 m_lastZoomFactor = currentZoomFactor;
1681 m_frame->eventHandler()->sendResizeEvent();
1685 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
1687 performPostLayoutTasks();
1690 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
1692 if (!m_viewportRenderer)
1695 if (m_overflowStatusDirty) {
1696 m_horizontalOverflow = horizontalOverflow;
1697 m_verticalOverflow = verticalOverflow;
1698 m_overflowStatusDirty = false;
1702 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
1703 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
1705 if (horizontalOverflowChanged || verticalOverflowChanged) {
1706 m_horizontalOverflow = horizontalOverflow;
1707 m_verticalOverflow = verticalOverflow;
1709 scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
1710 verticalOverflowChanged, verticalOverflow),
1711 m_viewportRenderer->node());
1716 void FrameView::dispatchScheduledEvents()
1718 if (m_scheduledEvents.isEmpty())
1721 Vector<ScheduledEvent*> scheduledEventsCopy = m_scheduledEvents;
1722 m_scheduledEvents.clear();
1724 Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end();
1725 for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) {
1726 ScheduledEvent* scheduledEvent = *it;
1728 ExceptionCode ec = 0;
1730 // Only dispatch events to nodes that are in the document
1731 if (scheduledEvent->m_eventTarget->inDocument())
1732 scheduledEvent->m_eventTarget->dispatchEvent(scheduledEvent->m_event, ec);
1734 delete scheduledEvent;
1738 IntRect FrameView::windowClipRect(bool clipToContents) const
1740 ASSERT(m_frame->view() == this);
1742 // Set our clip rect to be our contents.
1743 IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
1744 if (!m_frame || !m_frame->document() || !m_frame->document()->ownerElement())
1747 // Take our owner element and get the clip rect from the enclosing layer.
1748 Element* elt = m_frame->document()->ownerElement();
1749 RenderLayer* layer = elt->renderer()->enclosingLayer();
1750 // FIXME: layer should never be null, but sometimes seems to be anyway.
1753 FrameView* parentView = elt->document()->view();
1754 clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
1758 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const
1760 // If we have no layer, just return our window clip rect.
1762 return windowClipRect();
1764 // Apply the clip from the layer.
1766 if (clipToLayerContents)
1767 clipRect = layer->childrenClipRect();
1769 clipRect = layer->selfClipRect();
1770 clipRect = contentsToWindow(clipRect);
1771 return intersection(clipRect, windowClipRect());
1774 bool FrameView::isActive() const
1776 Page* page = frame()->page();
1777 return page && page->focusController()->isActive();
1780 void FrameView::valueChanged(Scrollbar* bar)
1782 // Figure out if we really moved.
1783 IntSize offset = scrollOffset();
1784 ScrollView::valueChanged(bar);
1785 if (offset != scrollOffset())
1786 scrollPositionChanged();
1787 frame()->loader()->client()->didChangeScrollOffset();
1790 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
1792 // Add in our offset within the FrameView.
1793 IntRect dirtyRect = rect;
1794 dirtyRect.move(scrollbar->x(), scrollbar->y());
1795 invalidateRect(dirtyRect);
1798 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
1800 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
1803 IntRect FrameView::windowResizerRect() const
1805 Page* page = frame() ? frame()->page() : 0;
1808 return page->chrome()->windowResizerRect();
1811 #if ENABLE(DASHBOARD_SUPPORT)
1812 void FrameView::updateDashboardRegions()
1814 Document* document = m_frame->document();
1815 if (!document->hasDashboardRegions())
1817 Vector<DashboardRegionValue> newRegions;
1818 document->renderBox()->collectDashboardRegions(newRegions);
1819 if (newRegions == document->dashboardRegions())
1821 document->setDashboardRegions(newRegions);
1822 Page* page = m_frame->page();
1825 page->chrome()->client()->dashboardRegionsChanged();
1829 void FrameView::invalidateScrollCorner()
1831 invalidateRect(scrollCornerRect());
1834 void FrameView::updateScrollCorner()
1836 RenderObject* renderer = 0;
1837 RefPtr<RenderStyle> cornerStyle;
1839 if (!scrollCornerRect().isEmpty()) {
1840 // Try the <body> element first as a scroll corner source.
1841 Document* doc = m_frame->document();
1842 Element* body = doc ? doc->body() : 0;
1843 if (body && body->renderer()) {
1844 renderer = body->renderer();
1845 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
1849 // If the <body> didn't have a custom style, then the root element might.
1850 Element* docElement = doc ? doc->documentElement() : 0;
1851 if (docElement && docElement->renderer()) {
1852 renderer = docElement->renderer();
1853 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
1858 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
1859 if (RenderPart* renderer = m_frame->ownerRenderer())
1860 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
1865 if (!m_scrollCorner)
1866 m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document());
1867 m_scrollCorner->setStyle(cornerStyle.release());
1868 invalidateRect(scrollCornerRect());
1869 } else if (m_scrollCorner) {
1870 m_scrollCorner->destroy();
1875 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
1877 if (context->updatingControlTints()) {
1878 updateScrollCorner();
1882 if (m_scrollCorner) {
1883 m_scrollCorner->paintIntoRect(context, cornerRect.x(), cornerRect.y(), cornerRect);
1887 ScrollView::paintScrollCorner(context, cornerRect);
1890 bool FrameView::hasCustomScrollbars() const
1892 const HashSet<RefPtr<Widget> >* viewChildren = children();
1893 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
1894 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
1895 Widget* widget = current->get();
1896 if (widget->isFrameView()) {
1897 if (static_cast<FrameView*>(widget)->hasCustomScrollbars())
1899 } else if (widget->isScrollbar()) {
1900 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
1901 if (scrollbar->isCustomScrollbar())
1909 void FrameView::updateControlTints()
1911 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
1912 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
1913 // This is only done if the theme supports control tinting. It's up to the theme and platform
1914 // to define when controls get the tint and to call this function when that changes.
1916 // Optimize the common case where we bring a window to the front while it's still empty.
1917 if (!m_frame || m_frame->loader()->url().isEmpty())
1920 if ((m_frame->contentRenderer() && m_frame->contentRenderer()->theme()->supportsControlTints()) || hasCustomScrollbars()) {
1923 PlatformGraphicsContext* const noContext = 0;
1924 GraphicsContext context(noContext);
1925 context.setUpdatingControlTints(true);
1926 if (platformWidget())
1927 paintContents(&context, visibleContentRect());
1929 paint(&context, frameRect());
1933 bool FrameView::wasScrolledByUser() const
1935 return m_wasScrolledByUser;
1938 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
1940 if (m_inProgrammaticScroll)
1942 m_maintainScrollPositionAnchor = 0;
1943 m_wasScrolledByUser = wasScrolledByUser;
1946 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
1951 #if ENABLE(INSPECTOR)
1952 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent())
1953 timelineAgent->willPaint(rect);
1956 Document* document = frame()->document();
1960 if (document->printing())
1961 fillWithRed = false; // Printing, don't fill with red (can't remember why).
1962 else if (document->ownerElement())
1963 fillWithRed = false; // Subframe, don't fill with red.
1964 else if (isTransparent())
1965 fillWithRed = false; // Transparent, don't fill with red.
1966 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
1967 fillWithRed = false; // Selections are transparent, don't fill with red.
1968 else if (m_nodeToDraw)
1969 fillWithRed = false; // Element images are transparent, don't fill with red.
1974 p->fillRect(rect, Color(0xFF, 0, 0), DeviceColorSpace);
1977 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
1978 if (isTopLevelPainter)
1979 sCurrentPaintTimeStamp = currentTime();
1981 RenderView* contentRenderer = frame()->contentRenderer();
1982 if (!contentRenderer) {
1983 LOG_ERROR("called FrameView::paint with nil renderer");
1987 ASSERT(!needsLayout());
1991 #if USE(ACCELERATED_COMPOSITING)
1992 if (!p->paintingDisabled()) {
1993 if (GraphicsLayer* rootLayer = contentRenderer->compositor()->rootPlatformLayer())
1994 rootLayer->syncCompositingState();
1998 ASSERT(!m_isPainting);
2000 m_isPainting = true;
2002 // m_nodeToDraw is used to draw only one element (and its descendants)
2003 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
2005 PaintBehavior oldPaintBehavior = m_paintBehavior;
2006 if (m_paintBehavior == PaintBehaviorNormal)
2007 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
2009 if (document->printing())
2010 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2012 contentRenderer->layer()->paint(p, rect, m_paintBehavior, eltRenderer);
2014 m_paintBehavior = oldPaintBehavior;
2016 m_isPainting = false;
2017 m_lastPaintTime = currentTime();
2019 #if ENABLE(DASHBOARD_SUPPORT)
2020 // Regions may have changed as a result of the visibility/z-index of element changing.
2021 if (document->dashboardRegionsDirty())
2022 updateDashboardRegions();
2025 if (isTopLevelPainter)
2026 sCurrentPaintTimeStamp = 0;
2028 #if ENABLE(INSPECTOR)
2029 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent())
2030 timelineAgent->didPaint();
2034 void FrameView::setPaintBehavior(PaintBehavior behavior)
2036 m_paintBehavior = behavior;
2039 PaintBehavior FrameView::paintBehavior() const
2041 return m_paintBehavior;
2044 bool FrameView::isPainting() const
2046 return m_isPainting;
2049 void FrameView::setNodeToDraw(Node* node)
2051 m_nodeToDraw = node;
2054 void FrameView::updateLayoutAndStyleIfNeededRecursive()
2056 // We have to crawl our entire tree looking for any FrameViews that need
2057 // layout and make sure they are up to date.
2058 // Mac actually tests for intersection with the dirty region and tries not to
2059 // update layout for frames that are outside the dirty region. Not only does this seem
2060 // pointless (since those frames will have set a zero timer to layout anyway), but
2061 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
2062 // region but then become included later by the second frame adding rects to the dirty region
2063 // when it lays out.
2065 m_frame->document()->updateStyleIfNeeded();
2070 const HashSet<RefPtr<Widget> >* viewChildren = children();
2071 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2072 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2073 Widget* widget = (*current).get();
2074 if (widget->isFrameView())
2075 static_cast<FrameView*>(widget)->updateLayoutAndStyleIfNeededRecursive();
2078 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
2079 // painting, so we need to flush out any deferred repaints too.
2080 flushDeferredRepaints();
2083 void FrameView::flushDeferredRepaints()
2085 if (!m_deferredRepaintTimer.isActive())
2087 m_deferredRepaintTimer.stop();
2088 doDeferredRepaints();
2091 void FrameView::forceLayout(bool allowSubtree)
2093 layout(allowSubtree);
2094 // We cannot unschedule a pending relayout, since the force can be called with
2095 // a tiny rectangle from a drawRect update. By unscheduling we in effect
2096 // "validate" and stop the necessary full repaint from occurring. Basically any basic
2097 // append/remove DHTML is broken by this call. For now, I have removed the optimization
2098 // until we have a better invalidation stategy. -dwh
2099 //unscheduleRelayout();
2102 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximumShrinkFactor, Frame::AdjustViewSizeOrNot shouldAdjustViewSize)
2104 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
2105 // the state of things before and after the layout
2106 RenderView *root = toRenderView(m_frame->document()->renderer());
2108 int pageW = ceilf(pageSize.width());
2109 m_pageHeight = pageSize.height() ? pageSize.height() : visibleHeight();
2110 root->setWidth(pageW);
2111 root->setNeedsLayoutAndPrefWidthsRecalc();
2114 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
2115 // page width when shrunk, we will lay out at maximum shrink and clip extra content.
2116 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
2117 // implementation should not do this!
2118 int rightmostPos = root->rightmostPosition();
2119 if (rightmostPos > pageSize.width()) {
2120 pageW = std::min<int>(rightmostPos, ceilf(pageSize.width() * maximumShrinkFactor));
2121 if (pageSize.height())
2122 m_pageHeight = pageW / pageSize.width() * pageSize.height();
2123 root->setWidth(pageW);
2124 root->setNeedsLayoutAndPrefWidthsRecalc();
2129 if (shouldAdjustViewSize)
2134 void FrameView::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
2136 RenderView* root = m_frame->contentRenderer();
2138 // Use a context with painting disabled.
2139 GraphicsContext context((PlatformGraphicsContext*)0);
2140 root->setTruncatedAt((int)floorf(oldBottom));
2141 IntRect dirtyRect(0, (int)floorf(oldTop), root->rightLayoutOverflow(), (int)ceilf(oldBottom - oldTop));
2142 root->layer()->paint(&context, dirtyRect);
2143 *newBottom = root->bestTruncatedAt();
2144 if (*newBottom == 0)
2145 *newBottom = oldBottom;
2147 *newBottom = oldBottom;
2150 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
2152 IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
2154 // Convert from page ("absolute") to FrameView coordinates.
2155 rect.move(-scrollX(), -scrollY());
2160 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
2162 IntRect rect = viewRect;
2164 // Convert from FrameView coords into page ("absolute") coordinates.
2165 rect.move(scrollX(), scrollY());
2167 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
2168 // move the rect for now.
2169 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
2173 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
2175 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
2177 // Convert from page ("absolute") to FrameView coordinates.
2178 point.move(-scrollX(), -scrollY());
2182 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
2184 IntPoint point = viewPoint;
2186 // Convert from FrameView coords into page ("absolute") coordinates.
2187 point += IntSize(scrollX(), scrollY());
2189 return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
2192 IntRect FrameView::convertToContainingView(const IntRect& localRect) const
2194 if (const ScrollView* parentScrollView = parent()) {
2195 if (parentScrollView->isFrameView()) {
2196 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2197 // Get our renderer in the parent view
2198 RenderPart* renderer = m_frame->ownerRenderer();
2202 IntRect rect(localRect);
2203 // Add borders and padding??
2204 rect.move(renderer->borderLeft() + renderer->paddingLeft(),
2205 renderer->borderTop() + renderer->paddingTop());
2206 return parentView->convertFromRenderer(renderer, rect);
2209 return Widget::convertToContainingView(localRect);
2215 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
2217 if (const ScrollView* parentScrollView = parent()) {
2218 if (parentScrollView->isFrameView()) {
2219 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2221 // Get our renderer in the parent view
2222 RenderPart* renderer = m_frame->ownerRenderer();
2226 IntRect rect = parentView->convertToRenderer(renderer, parentRect);
2227 // Subtract borders and padding
2228 rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
2229 -renderer->borderTop() - renderer->paddingTop());
2233 return Widget::convertFromContainingView(parentRect);
2239 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
2241 if (const ScrollView* parentScrollView = parent()) {
2242 if (parentScrollView->isFrameView()) {
2243 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2245 // Get our renderer in the parent view
2246 RenderPart* renderer = m_frame->ownerRenderer();
2250 IntPoint point(localPoint);
2252 // Add borders and padding
2253 point.move(renderer->borderLeft() + renderer->paddingLeft(),
2254 renderer->borderTop() + renderer->paddingTop());
2255 return parentView->convertFromRenderer(renderer, point);
2258 return Widget::convertToContainingView(localPoint);
2264 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
2266 if (const ScrollView* parentScrollView = parent()) {
2267 if (parentScrollView->isFrameView()) {
2268 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2270 // Get our renderer in the parent view
2271 RenderPart* renderer = m_frame->ownerRenderer();
2275 IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
2276 // Subtract borders and padding
2277 point.move(-renderer->borderLeft() - renderer->paddingLeft(),
2278 -renderer->borderTop() - renderer->paddingTop());
2282 return Widget::convertFromContainingView(parentPoint);
2288 bool FrameView::shouldApplyTextZoom() const
2290 if (m_zoomFactor == 1)
2294 Page* page = m_frame->page();
2295 return page && page->settings()->zoomMode() == ZoomTextOnly;
2298 bool FrameView::shouldApplyPageZoom() const
2300 if (m_zoomFactor == 1)
2304 Page* page = m_frame->page();
2305 return page && page->settings()->zoomMode() == ZoomPage;
2308 void FrameView::setZoomFactor(float percent, ZoomMode mode)
2313 Page* page = m_frame->page();
2317 if (m_zoomFactor == percent && page->settings()->zoomMode() == mode)
2320 Document* document = m_frame->document();
2325 // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
2326 // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification.
2327 if (document->isSVGDocument()) {
2328 if (!static_cast<SVGDocument*>(document)->zoomAndPanEnabled())
2330 if (document->renderer())
2331 document->renderer()->setNeedsLayout(true);
2335 if (mode == ZoomPage) {
2336 // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
2337 IntPoint scrollPosition = this->scrollPosition();
2338 float percentDifference = (percent / m_zoomFactor);
2339 setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
2342 m_zoomFactor = percent;
2343 page->settings()->setZoomMode(mode);
2345 document->recalcStyle(Node::Force);
2347 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
2348 if (FrameView* childView = child->view())
2349 childView->setZoomFactor(m_zoomFactor, mode);
2352 if (document->renderer() && document->renderer()->needsLayout() && didFirstLayout())
2358 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
2360 s_deferredRepaintDelay = p;
2363 // Negative value would mean that first few repaints happen without a delay
2364 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)
2366 s_initialDeferredRepaintDelayDuringLoading = p;
2369 // The delay grows on each repaint to this maximum value
2370 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)
2372 s_maxDeferredRepaintDelayDuringLoading = p;
2375 // On each repaint the delay increases by this amount
2376 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)
2378 s_deferredRepaintDelayIncrementDuringLoading = p;
2381 } // namespace WebCore