1 /*
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.
10  *
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.
15  *
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.
20  *
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.
25  */
26 
27 #include "config.h"
28 #include "FrameView.h"
29 
30 #include "AXObjectCache.h"
31 #include "CSSStyleSelector.h"
32 #include "CachedResourceLoader.h"
33 #include "Chrome.h"
34 #include "ChromeClient.h"
35 #include "DocumentMarkerController.h"
36 #include "EventHandler.h"
37 #include "FloatRect.h"
38 #include "FocusController.h"
39 #include "Frame.h"
40 #include "FrameActionScheduler.h"
41 #include "FrameLoader.h"
42 #include "FrameLoaderClient.h"
43 #include "FrameTree.h"
44 #include "GraphicsContext.h"
45 #include "HTMLDocument.h"
46 #include "HTMLFrameElement.h"
47 #include "HTMLFrameSetElement.h"
48 #include "HTMLNames.h"
49 #include "HTMLPlugInImageElement.h"
50 #include "InspectorInstrumentation.h"
51 #include "OverflowEvent.h"
52 #include "RenderEmbeddedObject.h"
53 #include "RenderFullScreen.h"
54 #include "RenderLayer.h"
55 #include "RenderPart.h"
56 #include "RenderScrollbar.h"
57 #include "RenderScrollbarPart.h"
58 #include "RenderTheme.h"
59 #include "RenderView.h"
60 #include "ScrollAnimator.h"
61 #include "Settings.h"
62 #include "TextResourceDecoder.h"
63 #include <wtf/CurrentTime.h>
64 
65 #if USE(ACCELERATED_COMPOSITING)
66 #include "RenderLayerCompositor.h"
67 #endif
68 
69 #if ENABLE(SVG)
70 #include "SVGDocument.h"
71 #include "SVGLocatable.h"
72 #include "SVGNames.h"
73 #include "SVGPreserveAspectRatio.h"
74 #include "SVGSVGElement.h"
75 #include "SVGViewElement.h"
76 #include "SVGViewSpec.h"
77 #endif
78 
79 #if ENABLE(TILED_BACKING_STORE)
80 #include "TiledBackingStore.h"
81 #endif
82 
83 namespace WebCore {
84 
85 using namespace HTMLNames;
86 
87 double FrameView::sCurrentPaintTimeStamp = 0.0;
88 
89 // REPAINT_THROTTLING now chooses default values for throttling parameters.
90 // Should be removed when applications start using runtime configuration.
91 #if ENABLE(REPAINT_THROTTLING)
92 // Normal delay
93 double FrameView::s_deferredRepaintDelay = 0.025;
94 // Negative value would mean that first few repaints happen without a delay
95 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
96 // The delay grows on each repaint to this maximum value
97 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
98 // On each repaint the delay increses by this amount
99 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
100 #else
101 // FIXME: Repaint throttling could be good to have on all platform.
102 // The balance between CPU use and repaint frequency will need some tuning for desktop.
103 // More hooks may be needed to reset the delay on things like GIF and CSS animations.
104 double FrameView::s_deferredRepaintDelay = 0;
105 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
106 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
107 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
108 #endif
109 
110 // The maximum number of updateWidgets iterations that should be done before returning.
111 static const unsigned maxUpdateWidgetsIterations = 2;
112 
FrameView(Frame * frame)113 FrameView::FrameView(Frame* frame)
114     : m_frame(frame)
115     , m_canHaveScrollbars(true)
116     , m_slowRepaintObjectCount(0)
117     , m_fixedObjectCount(0)
118     , m_layoutTimer(this, &FrameView::layoutTimerFired)
119     , m_layoutRoot(0)
120     , m_hasPendingPostLayoutTasks(false)
121     , m_inSynchronousPostLayout(false)
122     , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
123     , m_isTransparent(false)
124     , m_baseBackgroundColor(Color::white)
125     , m_mediaType("screen")
126     , m_actionScheduler(adoptPtr(new FrameActionScheduler))
127     , m_overflowStatusDirty(true)
128     , m_viewportRenderer(0)
129     , m_wasScrolledByUser(false)
130     , m_inProgrammaticScroll(false)
131     , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
132     , m_shouldUpdateWhileOffscreen(true)
133     , m_deferSetNeedsLayouts(0)
134     , m_setNeedsLayoutWasDeferred(false)
135     , m_scrollCorner(0)
136 {
137     init();
138 
139     if (m_frame) {
140         if (Page* page = m_frame->page()) {
141             m_page = page;
142             m_page->addScrollableArea(this);
143 
144             if (m_frame == m_page->mainFrame()) {
145                 ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed);
146                 ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed);
147             }
148         }
149     }
150 }
151 
create(Frame * frame)152 PassRefPtr<FrameView> FrameView::create(Frame* frame)
153 {
154     RefPtr<FrameView> view = adoptRef(new FrameView(frame));
155     view->show();
156     return view.release();
157 }
158 
create(Frame * frame,const IntSize & initialSize)159 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize)
160 {
161     RefPtr<FrameView> view = adoptRef(new FrameView(frame));
162     view->Widget::setFrameRect(IntRect(view->pos(), initialSize));
163     view->setInitialBoundsSize(initialSize);
164     view->show();
165     return view.release();
166 }
167 
~FrameView()168 FrameView::~FrameView()
169 {
170     if (m_hasPendingPostLayoutTasks) {
171         m_postLayoutTasksTimer.stop();
172         m_actionScheduler->clear();
173     }
174 
175     if (AXObjectCache::accessibilityEnabled() && axObjectCache())
176         axObjectCache()->remove(this);
177 
178     resetScrollbars();
179 
180     // Custom scrollbars should already be destroyed at this point
181     ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
182     ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
183 
184     setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
185     setHasVerticalScrollbar(false);
186 
187     ASSERT(!m_scrollCorner);
188     ASSERT(m_actionScheduler->isEmpty());
189 
190     if (m_page)
191         m_page->removeScrollableArea(this);
192 
193     if (m_frame) {
194         ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
195         RenderPart* renderer = m_frame->ownerRenderer();
196         if (renderer && renderer->widget() == this)
197             renderer->setWidget(0);
198     }
199 }
200 
reset()201 void FrameView::reset()
202 {
203     m_useSlowRepaints = false;
204     m_isOverlapped = false;
205     m_contentIsOpaque = false;
206     m_borderX = 30;
207     m_borderY = 30;
208     m_layoutTimer.stop();
209     m_layoutRoot = 0;
210     m_delayedLayout = false;
211     m_doFullRepaint = true;
212     m_layoutSchedulingEnabled = true;
213     m_inLayout = false;
214     m_inSynchronousPostLayout = false;
215     m_hasPendingPostLayoutTasks = false;
216     m_layoutCount = 0;
217     m_nestedLayoutCount = 0;
218     m_postLayoutTasksTimer.stop();
219     m_firstLayout = true;
220     m_firstLayoutCallbackPending = false;
221     m_wasScrolledByUser = false;
222     m_lastLayoutSize = IntSize();
223     m_lastZoomFactor = 1.0f;
224     m_deferringRepaints = 0;
225     m_repaintCount = 0;
226     m_repaintRects.clear();
227     m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading;
228     m_deferredRepaintTimer.stop();
229     m_lastPaintTime = 0;
230     m_paintBehavior = PaintBehaviorNormal;
231     m_isPainting = false;
232     m_isVisuallyNonEmpty = false;
233     m_firstVisuallyNonEmptyLayoutCallbackPending = true;
234     m_maintainScrollPositionAnchor = 0;
235 }
236 
isFrameView() const237 bool FrameView::isFrameView() const
238 {
239     return true;
240 }
241 
clearFrame()242 void FrameView::clearFrame()
243 {
244     m_frame = 0;
245 }
246 
resetScrollbars()247 void FrameView::resetScrollbars()
248 {
249     // Reset the document's scrollbars back to our defaults before we yield the floor.
250     m_firstLayout = true;
251     setScrollbarsSuppressed(true);
252     if (m_canHaveScrollbars)
253         setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
254     else
255         setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
256     setScrollbarsSuppressed(false);
257 }
258 
resetScrollbarsAndClearContentsSize()259 void FrameView::resetScrollbarsAndClearContentsSize()
260 {
261     resetScrollbars();
262 
263     setScrollbarsSuppressed(true);
264     setContentsSize(IntSize());
265     setScrollbarsSuppressed(false);
266 }
267 
init()268 void FrameView::init()
269 {
270     reset();
271 
272     m_margins = IntSize(-1, -1); // undefined
273     m_size = IntSize();
274 
275     // Propagate the marginwidth/height and scrolling modes to the view.
276     Element* ownerElement = m_frame ? m_frame->ownerElement() : 0;
277     if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
278         HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement);
279         if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
280             setCanHaveScrollbars(false);
281         int marginWidth = frameElt->marginWidth();
282         int marginHeight = frameElt->marginHeight();
283         if (marginWidth != -1)
284             setMarginWidth(marginWidth);
285         if (marginHeight != -1)
286             setMarginHeight(marginHeight);
287     }
288 }
289 
detachCustomScrollbars()290 void FrameView::detachCustomScrollbars()
291 {
292     if (!m_frame)
293         return;
294 
295     Scrollbar* horizontalBar = horizontalScrollbar();
296     if (horizontalBar && horizontalBar->isCustomScrollbar())
297         setHasHorizontalScrollbar(false);
298 
299     Scrollbar* verticalBar = verticalScrollbar();
300     if (verticalBar && verticalBar->isCustomScrollbar())
301         setHasVerticalScrollbar(false);
302 
303     if (m_scrollCorner) {
304         m_scrollCorner->destroy();
305         m_scrollCorner = 0;
306     }
307 }
308 
recommendedScrollbarOverlayStyle() const309 ScrollbarOverlayStyle FrameView::recommendedScrollbarOverlayStyle() const
310 {
311     Color bgColor = m_frame->getDocumentBackgroundColor();
312     if (!bgColor.isValid())
313         return ScrollbarOverlayStyleDefault;
314 
315     // Reduce the background color from RGB to a lightness value
316     // and determine which scrollbar style to use based on a lightness
317     // heuristic.
318     double hue, saturation, lightness;
319     bgColor.getHSL(hue, saturation, lightness);
320     if (lightness > .5)
321         return ScrollbarOverlayStyleDefault;
322 
323     return ScrollbarOverlayStyleLight;
324 }
325 
clear()326 void FrameView::clear()
327 {
328     setCanBlitOnScroll(true);
329 
330     reset();
331 
332     if (m_frame) {
333         if (RenderPart* renderer = m_frame->ownerRenderer())
334             renderer->viewCleared();
335     }
336 
337     setScrollbarsSuppressed(true);
338 }
339 
didFirstLayout() const340 bool FrameView::didFirstLayout() const
341 {
342     return !m_firstLayout;
343 }
344 
invalidateRect(const IntRect & rect)345 void FrameView::invalidateRect(const IntRect& rect)
346 {
347     if (!parent()) {
348         if (hostWindow())
349             hostWindow()->invalidateContentsAndWindow(rect, false /*immediate*/);
350         return;
351     }
352 
353     if (!m_frame)
354         return;
355 
356     RenderPart* renderer = m_frame->ownerRenderer();
357     if (!renderer)
358         return;
359 
360     IntRect repaintRect = rect;
361     repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
362                      renderer->borderTop() + renderer->paddingTop());
363     renderer->repaintRectangle(repaintRect);
364 }
365 
setFrameRect(const IntRect & newRect)366 void FrameView::setFrameRect(const IntRect& newRect)
367 {
368     IntRect oldRect = frameRect();
369     if (newRect == oldRect)
370         return;
371 
372     ScrollView::setFrameRect(newRect);
373 
374 #if USE(ACCELERATED_COMPOSITING)
375     if (RenderView* root = m_frame->contentRenderer()) {
376         if (root->usesCompositing())
377             root->compositor()->frameViewDidChangeSize();
378     }
379 #endif
380 }
381 
382 #if ENABLE(REQUEST_ANIMATION_FRAME)
scheduleAnimation()383 void FrameView::scheduleAnimation()
384 {
385     if (hostWindow())
386         hostWindow()->scheduleAnimation();
387 }
388 #endif
389 
setMarginWidth(int w)390 void FrameView::setMarginWidth(int w)
391 {
392     // make it update the rendering area when set
393     m_margins.setWidth(w);
394 }
395 
setMarginHeight(int h)396 void FrameView::setMarginHeight(int h)
397 {
398     // make it update the rendering area when set
399     m_margins.setHeight(h);
400 }
401 
avoidScrollbarCreation() const402 bool FrameView::avoidScrollbarCreation() const
403 {
404     ASSERT(m_frame);
405 
406     // with frame flattening no subframe can have scrollbars
407     // but we also cannot turn scrollbars of as we determine
408     // our flattening policy using that.
409 
410     if (!m_frame->ownerElement())
411         return false;
412 
413     if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
414         return true;
415 
416     return false;
417 }
418 
setCanHaveScrollbars(bool canHaveScrollbars)419 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
420 {
421     m_canHaveScrollbars = canHaveScrollbars;
422     ScrollView::setCanHaveScrollbars(canHaveScrollbars);
423 }
424 
updateCanHaveScrollbars()425 void FrameView::updateCanHaveScrollbars()
426 {
427     ScrollbarMode hMode;
428     ScrollbarMode vMode;
429     scrollbarModes(hMode, vMode);
430     if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
431         setCanHaveScrollbars(false);
432     else
433         setCanHaveScrollbars(true);
434 }
435 
createScrollbar(ScrollbarOrientation orientation)436 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
437 {
438     // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
439     Document* doc = m_frame->document();
440 
441     // Try the <body> element first as a scrollbar source.
442     Element* body = doc ? doc->body() : 0;
443     if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
444         return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderer()->enclosingBox());
445 
446     // If the <body> didn't have a custom style, then the root element might.
447     Element* docElement = doc ? doc->documentElement() : 0;
448     if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
449         return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox());
450 
451     // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
452     RenderPart* frameRenderer = m_frame->ownerRenderer();
453     if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
454         return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
455 
456     // Nobody set a custom style, so we just use a native scrollbar.
457     return ScrollView::createScrollbar(orientation);
458 }
459 
setContentsSize(const IntSize & size)460 void FrameView::setContentsSize(const IntSize& size)
461 {
462     if (size == contentsSize())
463         return;
464 
465     m_deferSetNeedsLayouts++;
466 
467     ScrollView::setContentsSize(size);
468     scrollAnimator()->contentsResized();
469 
470     Page* page = frame() ? frame()->page() : 0;
471     if (!page)
472         return;
473 
474     page->chrome()->contentsSizeChanged(frame(), size); //notify only
475 
476     m_deferSetNeedsLayouts--;
477 
478     if (!m_deferSetNeedsLayouts)
479         m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
480 }
481 
adjustViewSize()482 void FrameView::adjustViewSize()
483 {
484     ASSERT(m_frame->view() == this);
485     RenderView* root = m_frame->contentRenderer();
486     if (!root)
487         return;
488 
489     IntSize size = IntSize(root->docWidth(), root->docHeight());
490 
491     ScrollView::setScrollOrigin(IntPoint(-root->docLeft(), -root->docTop()), !m_frame->document()->printing(), size == contentsSize());
492 
493     setContentsSize(size);
494 }
495 
applyOverflowToViewport(RenderObject * o,ScrollbarMode & hMode,ScrollbarMode & vMode)496 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
497 {
498     // Handle the overflow:hidden/scroll case for the body/html elements.  WinIE treats
499     // overflow:hidden and overflow:scroll on <body> as applying to the document's
500     // scrollbars.  The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
501     // use the root element.
502     switch (o->style()->overflowX()) {
503         case OHIDDEN:
504             hMode = ScrollbarAlwaysOff;
505             break;
506         case OSCROLL:
507             hMode = ScrollbarAlwaysOn;
508             break;
509         case OAUTO:
510             hMode = ScrollbarAuto;
511             break;
512         default:
513             // Don't set it at all.
514             ;
515     }
516 
517      switch (o->style()->overflowY()) {
518         case OHIDDEN:
519             vMode = ScrollbarAlwaysOff;
520             break;
521         case OSCROLL:
522             vMode = ScrollbarAlwaysOn;
523             break;
524         case OAUTO:
525             vMode = ScrollbarAuto;
526             break;
527         default:
528             // Don't set it at all.
529             ;
530     }
531 
532     m_viewportRenderer = o;
533 }
534 
calculateScrollbarModesForLayout(ScrollbarMode & hMode,ScrollbarMode & vMode)535 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode)
536 {
537     m_viewportRenderer = 0;
538 
539     const HTMLFrameOwnerElement* owner = m_frame->ownerElement();
540     if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
541         hMode = ScrollbarAlwaysOff;
542         vMode = ScrollbarAlwaysOff;
543         return;
544     }
545 
546     if (m_canHaveScrollbars) {
547         hMode = ScrollbarAuto;
548         vMode = ScrollbarAuto;
549     } else {
550         hMode = ScrollbarAlwaysOff;
551         vMode = ScrollbarAlwaysOff;
552     }
553 
554     if (!m_layoutRoot) {
555         Document* document = m_frame->document();
556         Node* documentElement = document->documentElement();
557         RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
558         Node* body = document->body();
559         if (body && body->renderer()) {
560             if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
561                 vMode = ScrollbarAlwaysOff;
562                 hMode = ScrollbarAlwaysOff;
563             } else if (body->hasTagName(bodyTag)) {
564                 // It's sufficient to just check the X overflow,
565                 // since it's illegal to have visible in only one direction.
566                 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
567                 applyOverflowToViewport(o, hMode, vMode);
568             }
569         } else if (rootRenderer) {
570 #if ENABLE(SVG)
571             if (!documentElement->isSVGElement())
572                 applyOverflowToViewport(rootRenderer, hMode, vMode);
573 #else
574             applyOverflowToViewport(rootRenderer, hMode, vMode);
575 #endif
576         }
577     }
578 }
579 
580 #if ENABLE(FULLSCREEN_API) && USE(ACCELERATED_COMPOSITING)
isDocumentRunningFullScreenAnimation(Document * document)581 static bool isDocumentRunningFullScreenAnimation(Document* document)
582 {
583     return document->webkitIsFullScreen() && document->fullScreenRenderer() && document->fullScreenRenderer()->isAnimating();
584 }
585 #endif
586 
587 #if USE(ACCELERATED_COMPOSITING)
updateCompositingLayers()588 void FrameView::updateCompositingLayers()
589 {
590     RenderView* view = m_frame->contentRenderer();
591     if (!view)
592         return;
593 
594     // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
595     view->compositor()->cacheAcceleratedCompositingFlags();
596     view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange);
597 
598 #if ENABLE(FULLSCREEN_API)
599     Document* document = m_frame->document();
600     if (isDocumentRunningFullScreenAnimation(document))
601         view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange, document->fullScreenRenderer()->layer());
602 #endif
603 }
604 
layerForHorizontalScrollbar() const605 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
606 {
607     RenderView* view = m_frame->contentRenderer();
608     if (!view)
609         return 0;
610     return view->compositor()->layerForHorizontalScrollbar();
611 }
612 
layerForVerticalScrollbar() const613 GraphicsLayer* FrameView::layerForVerticalScrollbar() const
614 {
615     RenderView* view = m_frame->contentRenderer();
616     if (!view)
617         return 0;
618     return view->compositor()->layerForVerticalScrollbar();
619 }
620 
layerForScrollCorner() const621 GraphicsLayer* FrameView::layerForScrollCorner() const
622 {
623     RenderView* view = m_frame->contentRenderer();
624     if (!view)
625         return 0;
626     return view->compositor()->layerForScrollCorner();
627 }
628 
syncCompositingStateForThisFrame()629 bool FrameView::syncCompositingStateForThisFrame()
630 {
631     ASSERT(m_frame->view() == this);
632     RenderView* view = m_frame->contentRenderer();
633     if (!view)
634         return true; // We don't want to keep trying to update layers if we have no renderer.
635 
636     // If we sync compositing layers when a layout is pending, we may cause painting of compositing
637     // layer content to occur before layout has happened, which will cause paintContents() to bail.
638     if (needsLayout())
639         return false;
640 
641     if (GraphicsLayer* graphicsLayer = view->compositor()->layerForHorizontalScrollbar())
642         graphicsLayer->syncCompositingStateForThisLayerOnly();
643     if (GraphicsLayer* graphicsLayer = view->compositor()->layerForVerticalScrollbar())
644         graphicsLayer->syncCompositingStateForThisLayerOnly();
645     if (GraphicsLayer* graphicsLayer = view->compositor()->layerForScrollCorner())
646         graphicsLayer->syncCompositingStateForThisLayerOnly();
647 
648     view->compositor()->flushPendingLayerChanges();
649 
650 #if ENABLE(FULLSCREEN_API)
651     // The fullScreenRenderer's graphicsLayer  has been re-parented, and the above recursive syncCompositingState
652     // call will not cause the subtree under it to repaint.  Explicitly call the syncCompositingState on
653     // the fullScreenRenderer's graphicsLayer here:
654     Document* document = m_frame->document();
655     if (isDocumentRunningFullScreenAnimation(document)) {
656         RenderLayerBacking* backing = document->fullScreenRenderer()->layer()->backing();
657         if (GraphicsLayer* fullScreenLayer = backing->graphicsLayer())
658             fullScreenLayer->syncCompositingState();
659     }
660 #endif
661     return true;
662 }
663 
setNeedsOneShotDrawingSynchronization()664 void FrameView::setNeedsOneShotDrawingSynchronization()
665 {
666     Page* page = frame() ? frame()->page() : 0;
667     if (page)
668         page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
669 }
670 
671 #endif // USE(ACCELERATED_COMPOSITING)
672 
hasCompositedContent() const673 bool FrameView::hasCompositedContent() const
674 {
675 #if USE(ACCELERATED_COMPOSITING)
676     if (RenderView* view = m_frame->contentRenderer())
677         return view->compositor()->inCompositingMode();
678 #endif
679     return false;
680 }
681 
hasCompositedContentIncludingDescendants() const682 bool FrameView::hasCompositedContentIncludingDescendants() const
683 {
684 #if USE(ACCELERATED_COMPOSITING)
685     for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
686         RenderView* renderView = frame->contentRenderer();
687         RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0;
688         if (compositor) {
689             if (compositor->inCompositingMode())
690                 return true;
691 
692             if (!RenderLayerCompositor::allowsIndependentlyCompositedFrames(this))
693                 break;
694         }
695     }
696 #endif
697     return false;
698 }
699 
hasCompositingAncestor() const700 bool FrameView::hasCompositingAncestor() const
701 {
702 #if USE(ACCELERATED_COMPOSITING)
703     for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) {
704         if (FrameView* view = frame->view()) {
705             if (view->hasCompositedContent())
706                 return true;
707         }
708     }
709 #endif
710     return false;
711 }
712 
713 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
enterCompositingMode()714 void FrameView::enterCompositingMode()
715 {
716 #if USE(ACCELERATED_COMPOSITING)
717     if (RenderView* view = m_frame->contentRenderer()) {
718         view->compositor()->enableCompositingMode();
719         if (!needsLayout())
720             view->compositor()->scheduleCompositingLayerUpdate();
721     }
722 #endif
723 }
724 
isEnclosedInCompositingLayer() const725 bool FrameView::isEnclosedInCompositingLayer() const
726 {
727 #if USE(ACCELERATED_COMPOSITING)
728     RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
729     if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
730         return true;
731 
732     if (FrameView* parentView = parentFrameView())
733         return parentView->isEnclosedInCompositingLayer();
734 #endif
735     return false;
736 }
737 
syncCompositingStateIncludingSubframes()738 bool FrameView::syncCompositingStateIncludingSubframes()
739 {
740 #if USE(ACCELERATED_COMPOSITING)
741     bool allFramesSynced = syncCompositingStateForThisFrame();
742 
743     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame.get())) {
744         bool synced = child->view()->syncCompositingStateForThisFrame();
745         allFramesSynced &= synced;
746     }
747     return allFramesSynced;
748 #else // USE(ACCELERATED_COMPOSITING)
749     return true;
750 #endif
751 }
752 
isSoftwareRenderable() const753 bool FrameView::isSoftwareRenderable() const
754 {
755 #if USE(ACCELERATED_COMPOSITING)
756     RenderView* view = m_frame->contentRenderer();
757     if (!view)
758         return true;
759 
760     return !view->compositor()->has3DContent();
761 #else
762     return true;
763 #endif
764 }
765 
didMoveOnscreen()766 void FrameView::didMoveOnscreen()
767 {
768     RenderView* view = m_frame->contentRenderer();
769     if (view)
770         view->didMoveOnscreen();
771     scrollAnimator()->contentAreaDidShow();
772 }
773 
willMoveOffscreen()774 void FrameView::willMoveOffscreen()
775 {
776     RenderView* view = m_frame->contentRenderer();
777     if (view)
778         view->willMoveOffscreen();
779     scrollAnimator()->contentAreaDidHide();
780 }
781 
layoutRoot(bool onlyDuringLayout) const782 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
783 {
784     return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
785 }
786 
layout(bool allowSubtree)787 void FrameView::layout(bool allowSubtree)
788 {
789     if (m_inLayout)
790         return;
791 
792     bool inSubframeLayoutWithFrameFlattening = parent() && m_frame->settings() && m_frame->settings()->frameFlatteningEnabled();
793 
794     if (inSubframeLayoutWithFrameFlattening) {
795         if (parent()->isFrameView()) {
796             FrameView* parentView =   static_cast<FrameView*>(parent());
797             if (!parentView->m_nestedLayoutCount) {
798                 while (parentView->parent() && parentView->parent()->isFrameView())
799                     parentView = static_cast<FrameView*>(parentView->parent());
800                 parentView->layout(allowSubtree);
801                 return;
802             }
803         }
804     }
805 
806     m_layoutTimer.stop();
807     m_delayedLayout = false;
808     m_setNeedsLayoutWasDeferred = false;
809 
810     // Protect the view from being deleted during layout (in recalcStyle)
811     RefPtr<FrameView> protector(this);
812 
813     if (!m_frame) {
814         // FIXME: Do we need to set m_size.width here?
815         // FIXME: Should we set m_size.height here too?
816         m_size.setWidth(layoutWidth());
817         return;
818     }
819 
820     // we shouldn't enter layout() while painting
821     ASSERT(!isPainting());
822     if (isPainting())
823         return;
824 
825     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
826 
827     if (!allowSubtree && m_layoutRoot) {
828         m_layoutRoot->markContainingBlocksForLayout(false);
829         m_layoutRoot = 0;
830     }
831 
832     ASSERT(m_frame->view() == this);
833 
834     Document* document = m_frame->document();
835 
836     m_layoutSchedulingEnabled = false;
837 
838     if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_hasPendingPostLayoutTasks && !inSubframeLayoutWithFrameFlattening) {
839         // This is a new top-level layout. If there are any remaining tasks from the previous
840         // layout, finish them now.
841         m_inSynchronousPostLayout = true;
842         m_postLayoutTasksTimer.stop();
843         performPostLayoutTasks();
844         m_inSynchronousPostLayout = false;
845     }
846 
847     // Viewport-dependent media queries may cause us to need completely different style information.
848     // Check that here.
849     if (document->styleSelector()->affectedByViewportChange())
850         document->styleSelectorChanged(RecalcStyleImmediately);
851 
852     // Always ensure our style info is up-to-date.  This can happen in situations where
853     // the layout beats any sort of style recalc update that needs to occur.
854     document->updateStyleIfNeeded();
855 
856     bool subtree = m_layoutRoot;
857 
858     // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
859     // so there's no point to continuing to layout
860     if (protector->hasOneRef())
861         return;
862 
863     RenderObject* root = subtree ? m_layoutRoot : document->renderer();
864     if (!root) {
865         // FIXME: Do we need to set m_size here?
866         m_layoutSchedulingEnabled = true;
867         return;
868     }
869 
870     m_nestedLayoutCount++;
871 
872     if (!m_layoutRoot) {
873         Document* document = m_frame->document();
874         Node* documentElement = document->documentElement();
875         RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
876         Node* body = document->body();
877         if (body && body->renderer()) {
878             if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
879                 body->renderer()->setChildNeedsLayout(true);
880             } else if (body->hasTagName(bodyTag)) {
881                 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
882                     body->renderer()->setChildNeedsLayout(true);
883             }
884         } else if (rootRenderer) {
885 #if ENABLE(SVG)
886             if (documentElement->isSVGElement()) {
887                 if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight()))
888                     rootRenderer->setChildNeedsLayout(true);
889             }
890 #endif
891         }
892 
893 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
894         if (m_firstLayout && !m_frame->ownerElement())
895             printf("Elapsed time before first layout: %d\n", document->elapsedTime());
896 #endif
897     }
898 
899     ScrollbarMode hMode;
900     ScrollbarMode vMode;
901     calculateScrollbarModesForLayout(hMode, vMode);
902 
903     m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
904 
905     if (!subtree) {
906         // Now set our scrollbar state for the layout.
907         ScrollbarMode currentHMode = horizontalScrollbarMode();
908         ScrollbarMode currentVMode = verticalScrollbarMode();
909 
910         if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
911             if (m_firstLayout) {
912                 setScrollbarsSuppressed(true);
913 
914                 m_firstLayout = false;
915                 m_firstLayoutCallbackPending = true;
916                 m_lastLayoutSize = IntSize(width(), height());
917                 m_lastZoomFactor = root->style()->zoom();
918 
919                 // Set the initial vMode to AlwaysOn if we're auto.
920                 if (vMode == ScrollbarAuto)
921                     setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
922                 // Set the initial hMode to AlwaysOff if we're auto.
923                 if (hMode == ScrollbarAuto)
924                     setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
925 
926                 setScrollbarModes(hMode, vMode);
927                 setScrollbarsSuppressed(false, true);
928             } else
929                 setScrollbarModes(hMode, vMode);
930         }
931 
932         IntSize oldSize = m_size;
933 
934         m_size = IntSize(layoutWidth(), layoutHeight());
935 
936         if (oldSize != m_size) {
937             m_doFullRepaint = true;
938             if (!m_firstLayout) {
939                 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
940                 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
941                 if (bodyRenderer && bodyRenderer->stretchesToViewport())
942                     bodyRenderer->setChildNeedsLayout(true);
943                 else if (rootRenderer && rootRenderer->stretchesToViewport())
944                     rootRenderer->setChildNeedsLayout(true);
945             }
946         }
947     }
948 
949     RenderLayer* layer = root->enclosingLayer();
950 
951     m_actionScheduler->pause();
952 
953     bool disableLayoutState = false;
954     if (subtree) {
955         RenderView* view = root->view();
956         disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
957         view->pushLayoutState(root);
958         if (disableLayoutState)
959             view->disableLayoutState();
960     }
961 
962     m_inLayout = true;
963     beginDeferredRepaints();
964     root->layout();
965     endDeferredRepaints();
966     m_inLayout = false;
967 
968     if (subtree) {
969         RenderView* view = root->view();
970         view->popLayoutState(root);
971         if (disableLayoutState)
972             view->enableLayoutState();
973     }
974     m_layoutRoot = 0;
975 
976     m_layoutSchedulingEnabled = true;
977 
978     if (!subtree && !toRenderView(root)->printing())
979         adjustViewSize();
980 
981     // Now update the positions of all layers.
982     beginDeferredRepaints();
983     IntPoint cachedOffset;
984     if (m_doFullRepaint)
985         root->view()->repaint(); // FIXME: This isn't really right, since the RenderView doesn't fully encompass the visibleContentRect(). It just happens
986                                  // to work out most of the time, since first layouts and printing don't have you scrolled anywhere.
987     layer->updateLayerPositions((m_doFullRepaint ? 0 : RenderLayer::CheckForRepaint)
988                                 | RenderLayer::IsCompositingUpdateRoot
989                                 | RenderLayer::UpdateCompositingLayers,
990                                 subtree ? 0 : &cachedOffset);
991     endDeferredRepaints();
992 
993 #if USE(ACCELERATED_COMPOSITING)
994     updateCompositingLayers();
995 #endif
996 
997     m_layoutCount++;
998 
999 #if PLATFORM(MAC) || PLATFORM(CHROMIUM)
1000     if (AXObjectCache::accessibilityEnabled())
1001         root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true);
1002 #endif
1003 #if ENABLE(DASHBOARD_SUPPORT)
1004     updateDashboardRegions();
1005 #endif
1006 
1007     ASSERT(!root->needsLayout());
1008 
1009     updateCanBlitOnScrollRecursively();
1010 
1011     if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1012         updateOverflowStatus(layoutWidth() < contentsWidth(),
1013                              layoutHeight() < contentsHeight());
1014 
1015     if (!m_hasPendingPostLayoutTasks) {
1016         if (!m_inSynchronousPostLayout) {
1017             if (inSubframeLayoutWithFrameFlattening)
1018                 m_frame->contentRenderer()->updateWidgetPositions();
1019             else {
1020                 m_inSynchronousPostLayout = true;
1021                 // Calls resumeScheduledEvents()
1022                 performPostLayoutTasks();
1023                 m_inSynchronousPostLayout = false;
1024             }
1025         }
1026 
1027         if (!m_hasPendingPostLayoutTasks && (needsLayout() || m_inSynchronousPostLayout || inSubframeLayoutWithFrameFlattening)) {
1028             // If we need layout or are already in a synchronous call to postLayoutTasks(),
1029             // defer widget updates and event dispatch until after we return. postLayoutTasks()
1030             // can make us need to update again, and we can get stuck in a nasty cycle unless
1031             // we call it through the timer here.
1032             m_hasPendingPostLayoutTasks = true;
1033             m_postLayoutTasksTimer.startOneShot(0);
1034             if (needsLayout()) {
1035                 m_actionScheduler->pause();
1036                 layout();
1037             }
1038         }
1039     } else {
1040         m_actionScheduler->resume();
1041     }
1042 
1043     InspectorInstrumentation::didLayout(cookie);
1044 
1045     m_nestedLayoutCount--;
1046 }
1047 
addWidgetToUpdate(RenderEmbeddedObject * object)1048 void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object)
1049 {
1050     if (!m_widgetUpdateSet)
1051         m_widgetUpdateSet = adoptPtr(new RenderEmbeddedObjectSet);
1052 
1053     m_widgetUpdateSet->add(object);
1054 }
1055 
removeWidgetToUpdate(RenderEmbeddedObject * object)1056 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object)
1057 {
1058     if (!m_widgetUpdateSet)
1059         return;
1060 
1061     m_widgetUpdateSet->remove(object);
1062 }
1063 
setMediaType(const String & mediaType)1064 void FrameView::setMediaType(const String& mediaType)
1065 {
1066     m_mediaType = mediaType;
1067 }
1068 
mediaType() const1069 String FrameView::mediaType() const
1070 {
1071     // See if we have an override type.
1072     String overrideType = m_frame->loader()->client()->overrideMediaType();
1073     if (!overrideType.isNull())
1074         return overrideType;
1075     return m_mediaType;
1076 }
1077 
adjustMediaTypeForPrinting(bool printing)1078 void FrameView::adjustMediaTypeForPrinting(bool printing)
1079 {
1080     if (printing) {
1081         if (m_mediaTypeWhenNotPrinting.isNull())
1082             m_mediaTypeWhenNotPrinting = mediaType();
1083 
1084         String mediaType = (m_frame && m_frame->settings())?m_frame->settings()->printingMediaType():"print";
1085         setMediaType(mediaType);
1086     } else {
1087         if (!m_mediaTypeWhenNotPrinting.isNull())
1088             setMediaType(m_mediaTypeWhenNotPrinting);
1089         m_mediaTypeWhenNotPrinting = String();
1090     }
1091 }
1092 
useSlowRepaints() const1093 bool FrameView::useSlowRepaints() const
1094 {
1095     if (m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || m_isOverlapped || !m_contentIsOpaque)
1096         return true;
1097 
1098     if (FrameView* parentView = parentFrameView())
1099         return parentView->useSlowRepaints();
1100 
1101     return false;
1102 }
1103 
useSlowRepaintsIfNotOverlapped() const1104 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1105 {
1106     if (m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || !m_contentIsOpaque)
1107         return true;
1108 
1109     if (FrameView* parentView = parentFrameView())
1110         return parentView->useSlowRepaintsIfNotOverlapped();
1111 
1112     return false;
1113 }
1114 
updateCanBlitOnScrollRecursively()1115 void FrameView::updateCanBlitOnScrollRecursively()
1116 {
1117     for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1118         if (FrameView* view = frame->view())
1119             view->setCanBlitOnScroll(!view->useSlowRepaints());
1120     }
1121 }
1122 
setUseSlowRepaints()1123 void FrameView::setUseSlowRepaints()
1124 {
1125     m_useSlowRepaints = true;
1126     updateCanBlitOnScrollRecursively();
1127 }
1128 
addSlowRepaintObject()1129 void FrameView::addSlowRepaintObject()
1130 {
1131     if (!m_slowRepaintObjectCount)
1132         updateCanBlitOnScrollRecursively();
1133     m_slowRepaintObjectCount++;
1134 }
1135 
removeSlowRepaintObject()1136 void FrameView::removeSlowRepaintObject()
1137 {
1138     ASSERT(m_slowRepaintObjectCount > 0);
1139     m_slowRepaintObjectCount--;
1140     if (!m_slowRepaintObjectCount)
1141         updateCanBlitOnScrollRecursively();
1142 }
1143 
addFixedObject()1144 void FrameView::addFixedObject()
1145 {
1146     if (!m_fixedObjectCount && platformWidget())
1147         updateCanBlitOnScrollRecursively();
1148     ++m_fixedObjectCount;
1149 }
1150 
removeFixedObject()1151 void FrameView::removeFixedObject()
1152 {
1153     ASSERT(m_fixedObjectCount > 0);
1154     --m_fixedObjectCount;
1155     if (!m_fixedObjectCount)
1156         updateCanBlitOnScrollRecursively();
1157 }
1158 
scrollXForFixedPosition() const1159 int FrameView::scrollXForFixedPosition() const
1160 {
1161     int visibleContentWidth = visibleContentRect().width();
1162     int maxX = contentsWidth() - visibleContentWidth;
1163 
1164     if (maxX == 0)
1165         return 0;
1166 
1167     int x = scrollX();
1168 
1169     if (!ScrollView::scrollOrigin().x()) {
1170         if (x < 0)
1171             x = 0;
1172         else if (x > maxX)
1173             x = maxX;
1174     } else {
1175         if (x > 0)
1176             x = 0;
1177         else if (x < -maxX)
1178             x = -maxX;
1179     }
1180 
1181     if (!m_frame)
1182         return x;
1183 
1184     float pageScaleFactor = m_frame->pageScaleFactor();
1185 
1186     // When the page is scaled, the scaled "viewport" with respect to which fixed object are positioned
1187     // doesn't move as fast as the content view, so that when the content is scrolled all the way to the
1188     // end, the bottom of the scaled "viewport" touches the bottom of the real viewport.
1189     float dragFactor = (contentsWidth() - visibleContentWidth * pageScaleFactor) / maxX;
1190 
1191     return x * dragFactor / pageScaleFactor;
1192 }
1193 
scrollYForFixedPosition() const1194 int FrameView::scrollYForFixedPosition() const
1195 {
1196     int visibleContentHeight = visibleContentRect().height();
1197 
1198     int maxY = contentsHeight() - visibleContentHeight;
1199     if (maxY == 0)
1200         return 0;
1201 
1202     int y = scrollY();
1203 
1204     if (!ScrollView::scrollOrigin().y()) {
1205         if (y < 0)
1206             y = 0;
1207         else if (y > maxY)
1208             y = maxY;
1209     } else {
1210         if (y > 0)
1211             y = 0;
1212         else if (y < -maxY)
1213             y = -maxY;
1214     }
1215 
1216     if (!m_frame)
1217         return y;
1218 
1219     float pageScaleFactor = m_frame->pageScaleFactor();
1220     float dragFactor = (contentsHeight() - visibleContentHeight * pageScaleFactor) / maxY;
1221 
1222     return y * dragFactor / pageScaleFactor;
1223 }
1224 
scrollOffsetForFixedPosition() const1225 IntSize FrameView::scrollOffsetForFixedPosition() const
1226 {
1227     return IntSize(scrollXForFixedPosition(), scrollYForFixedPosition());
1228 }
1229 
currentMousePosition() const1230 IntPoint FrameView::currentMousePosition() const
1231 {
1232     return m_frame ? m_frame->eventHandler()->currentMousePosition() : IntPoint();
1233 }
1234 
scrollContentsFastPath(const IntSize & scrollDelta,const IntRect & rectToScroll,const IntRect & clipRect)1235 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1236 {
1237     const size_t fixedObjectThreshold = 5;
1238 
1239     RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0;
1240     if (RenderView* root = m_frame->contentRenderer())
1241         positionedObjects = root->positionedObjects();
1242 
1243     if (!positionedObjects || positionedObjects->isEmpty()) {
1244         hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1245         return true;
1246     }
1247 
1248     // Get the rects of the fixed objects visible in the rectToScroll
1249     Vector<IntRect, fixedObjectThreshold> subRectToUpdate;
1250     bool updateInvalidatedSubRect = true;
1251     RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
1252     for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
1253         RenderBox* renderBox = *it;
1254         if (renderBox->style()->position() != FixedPosition)
1255             continue;
1256         IntRect updateRect = renderBox->layer()->repaintRectIncludingDescendants();
1257         updateRect = contentsToWindow(updateRect);
1258         if (clipsRepaints())
1259             updateRect.intersect(rectToScroll);
1260         if (!updateRect.isEmpty()) {
1261             if (subRectToUpdate.size() >= fixedObjectThreshold) {
1262                 updateInvalidatedSubRect = false;
1263                 break;
1264             }
1265             subRectToUpdate.append(updateRect);
1266         }
1267     }
1268 
1269     // Scroll the view
1270     if (updateInvalidatedSubRect) {
1271         // 1) scroll
1272         hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1273 
1274         // 2) update the area of fixed objects that has been invalidated
1275         size_t fixObjectsCount = subRectToUpdate.size();
1276         for (size_t i = 0; i < fixObjectsCount; ++i) {
1277             IntRect updateRect = subRectToUpdate[i];
1278             IntRect scrolledRect = updateRect;
1279             scrolledRect.move(scrollDelta);
1280             updateRect.unite(scrolledRect);
1281             if (clipsRepaints())
1282                 updateRect.intersect(rectToScroll);
1283             hostWindow()->invalidateContentsAndWindow(updateRect, false);
1284         }
1285         return true;
1286     }
1287 
1288     // the number of fixed objects exceed the threshold, we cannot use the fast path
1289     return false;
1290 }
1291 
scrollContentsSlowPath(const IntRect & updateRect)1292 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1293 {
1294 #if USE(ACCELERATED_COMPOSITING)
1295     if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1296         if (frameRenderer->containerForRepaint()) {
1297             IntRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1298                          frameRenderer->borderTop() + frameRenderer->paddingTop(),
1299                          visibleWidth(), visibleHeight());
1300             frameRenderer->repaintRectangle(rect);
1301             return;
1302         }
1303     }
1304 #endif
1305 
1306     ScrollView::scrollContentsSlowPath(updateRect);
1307 }
1308 
1309 // Note that this gets called at painting time.
setIsOverlapped(bool isOverlapped)1310 void FrameView::setIsOverlapped(bool isOverlapped)
1311 {
1312     if (isOverlapped == m_isOverlapped)
1313         return;
1314 
1315     m_isOverlapped = isOverlapped;
1316     updateCanBlitOnScrollRecursively();
1317 
1318 #if USE(ACCELERATED_COMPOSITING)
1319     if (hasCompositedContentIncludingDescendants()) {
1320         // Overlap can affect compositing tests, so if it changes, we need to trigger
1321         // a layer update in the parent document.
1322         if (Frame* parentFrame = m_frame->tree()->parent()) {
1323             if (RenderView* parentView = parentFrame->contentRenderer()) {
1324                 RenderLayerCompositor* compositor = parentView->compositor();
1325                 compositor->setCompositingLayersNeedRebuild();
1326                 compositor->scheduleCompositingLayerUpdate();
1327             }
1328         }
1329 
1330         if (RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) {
1331             // We also need to trigger reevaluation for this and all descendant frames,
1332             // since a frame uses compositing if any ancestor is compositing.
1333             for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1334                 if (RenderView* view = frame->contentRenderer()) {
1335                     RenderLayerCompositor* compositor = view->compositor();
1336                     compositor->setCompositingLayersNeedRebuild();
1337                     compositor->scheduleCompositingLayerUpdate();
1338                 }
1339             }
1340         }
1341     }
1342 #endif
1343 }
1344 
isOverlappedIncludingAncestors() const1345 bool FrameView::isOverlappedIncludingAncestors() const
1346 {
1347     if (isOverlapped())
1348         return true;
1349 
1350     if (FrameView* parentView = parentFrameView()) {
1351         if (parentView->isOverlapped())
1352             return true;
1353     }
1354 
1355     return false;
1356 }
1357 
setContentIsOpaque(bool contentIsOpaque)1358 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1359 {
1360     if (contentIsOpaque == m_contentIsOpaque)
1361         return;
1362 
1363     m_contentIsOpaque = contentIsOpaque;
1364     updateCanBlitOnScrollRecursively();
1365 }
1366 
restoreScrollbar()1367 void FrameView::restoreScrollbar()
1368 {
1369     setScrollbarsSuppressed(false);
1370 }
1371 
scrollToFragment(const KURL & url)1372 bool FrameView::scrollToFragment(const KURL& url)
1373 {
1374     // If our URL has no ref, then we have no place we need to jump to.
1375     // OTOH If CSS target was set previously, we want to set it to 0, recalc
1376     // and possibly repaint because :target pseudo class may have been
1377     // set (see bug 11321).
1378     if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1379         return false;
1380 
1381     String fragmentIdentifier = url.fragmentIdentifier();
1382     if (scrollToAnchor(fragmentIdentifier))
1383         return true;
1384 
1385     // Try again after decoding the ref, based on the document's encoding.
1386     if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1387         return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1388 
1389     return false;
1390 }
1391 
scrollToAnchor(const String & name)1392 bool FrameView::scrollToAnchor(const String& name)
1393 {
1394     ASSERT(m_frame->document());
1395 
1396     if (!m_frame->document()->haveStylesheetsLoaded()) {
1397         m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1398         return false;
1399     }
1400 
1401     m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1402 
1403     Element* anchorNode = m_frame->document()->findAnchor(name);
1404 
1405 #if ENABLE(SVG)
1406     if (m_frame->document()->isSVGDocument()) {
1407         if (name.startsWith("xpointer(")) {
1408             // We need to parse the xpointer reference here
1409         } else if (name.startsWith("svgView(")) {
1410             RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement();
1411             if (!svg->currentView()->parseViewSpec(name))
1412                 return false;
1413             svg->setUseCurrentView(true);
1414         } else {
1415             if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) {
1416                 RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0;
1417                 if (viewElement.get()) {
1418                     SVGElement* element = SVGLocatable::nearestViewportElement(viewElement.get());
1419                     if (element->hasTagName(SVGNames::svgTag)) {
1420                         RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(element);
1421                         svg->inheritViewAttributes(viewElement.get());
1422                     }
1423                 }
1424             }
1425         }
1426         // FIXME: need to decide which <svg> to focus on, and zoom to that one
1427         // FIXME: need to actually "highlight" the viewTarget(s)
1428     }
1429 #endif
1430 
1431     m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target.
1432 
1433     // Implement the rule that "" and "top" both mean top of page as in other browsers.
1434     if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1435         return false;
1436 
1437     maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1438     return true;
1439 }
1440 
maintainScrollPositionAtAnchor(Node * anchorNode)1441 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1442 {
1443     m_maintainScrollPositionAnchor = anchorNode;
1444     if (!m_maintainScrollPositionAnchor)
1445         return;
1446 
1447     // We need to update the layout before scrolling, otherwise we could
1448     // really mess things up if an anchor scroll comes at a bad moment.
1449     m_frame->document()->updateStyleIfNeeded();
1450     // Only do a layout if changes have occurred that make it necessary.
1451     if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
1452         layout();
1453     else
1454         scrollToAnchor();
1455 }
1456 
setScrollPosition(const IntPoint & scrollPoint)1457 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1458 {
1459     bool wasInProgrammaticScroll = m_inProgrammaticScroll;
1460     m_inProgrammaticScroll = true;
1461     m_maintainScrollPositionAnchor = 0;
1462     ScrollView::setScrollPosition(scrollPoint);
1463     m_inProgrammaticScroll = wasInProgrammaticScroll;
1464 }
1465 
scrollPositionChangedViaPlatformWidget()1466 void FrameView::scrollPositionChangedViaPlatformWidget()
1467 {
1468     repaintFixedElementsAfterScrolling();
1469     scrollPositionChanged();
1470 }
1471 
scrollPositionChanged()1472 void FrameView::scrollPositionChanged()
1473 {
1474     frame()->eventHandler()->sendScrollEvent();
1475 
1476 #if USE(ACCELERATED_COMPOSITING)
1477     if (RenderView* root = m_frame->contentRenderer()) {
1478         if (root->usesCompositing())
1479             root->compositor()->frameViewDidScroll(scrollPosition());
1480     }
1481 #endif
1482 }
1483 
repaintFixedElementsAfterScrolling()1484 void FrameView::repaintFixedElementsAfterScrolling()
1485 {
1486     // For fixed position elements, update widget positions and compositing layers after scrolling,
1487     // but only if we're not inside of layout.
1488     if (!m_nestedLayoutCount && hasFixedObjects()) {
1489         if (RenderView* root = m_frame->contentRenderer()) {
1490             root->updateWidgetPositions();
1491             root->layer()->updateRepaintRectsAfterScroll();
1492 #if USE(ACCELERATED_COMPOSITING)
1493             root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
1494 #endif
1495         }
1496     }
1497 }
1498 
hostWindow() const1499 HostWindow* FrameView::hostWindow() const
1500 {
1501     Page* page = frame() ? frame()->page() : 0;
1502     if (!page)
1503         return 0;
1504     return page->chrome();
1505 }
1506 
1507 const unsigned cRepaintRectUnionThreshold = 25;
1508 
repaintContentRectangle(const IntRect & r,bool immediate)1509 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
1510 {
1511     ASSERT(!m_frame->ownerElement());
1512 
1513     double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay();
1514     if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
1515         IntRect paintRect = r;
1516         if (clipsRepaints() && !paintsEntireContents())
1517             paintRect.intersect(visibleContentRect());
1518         if (paintRect.isEmpty())
1519             return;
1520         if (m_repaintCount == cRepaintRectUnionThreshold) {
1521             IntRect unionedRect;
1522             for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
1523                 unionedRect.unite(m_repaintRects[i]);
1524             m_repaintRects.clear();
1525             m_repaintRects.append(unionedRect);
1526         }
1527         if (m_repaintCount < cRepaintRectUnionThreshold)
1528             m_repaintRects.append(paintRect);
1529         else
1530             m_repaintRects[0].unite(paintRect);
1531         m_repaintCount++;
1532 
1533         if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive())
1534              m_deferredRepaintTimer.startOneShot(delay);
1535         return;
1536     }
1537 
1538     if (!shouldUpdate(immediate))
1539         return;
1540 
1541 #if ENABLE(TILED_BACKING_STORE)
1542     if (frame()->tiledBackingStore()) {
1543         frame()->tiledBackingStore()->invalidate(r);
1544         return;
1545     }
1546 #endif
1547     ScrollView::repaintContentRectangle(r, immediate);
1548 }
1549 
contentsResized()1550 void FrameView::contentsResized()
1551 {
1552     scrollAnimator()->contentsResized();
1553     setNeedsLayout();
1554 }
1555 
visibleContentsResized()1556 void FrameView::visibleContentsResized()
1557 {
1558     // We check to make sure the view is attached to a frame() as this method can
1559     // be triggered before the view is attached by Frame::createView(...) setting
1560     // various values such as setScrollBarModes(...) for example.  An ASSERT is
1561     // triggered when a view is layout before being attached to a frame().
1562     if (!frame()->view())
1563         return;
1564 
1565     if (needsLayout())
1566         layout();
1567 
1568 #if USE(ACCELERATED_COMPOSITING)
1569     if (RenderView* root = m_frame->contentRenderer()) {
1570         if (root->usesCompositing())
1571             root->compositor()->frameViewDidChangeSize();
1572     }
1573 #endif
1574 }
1575 
beginDeferredRepaints()1576 void FrameView::beginDeferredRepaints()
1577 {
1578     Page* page = m_frame->page();
1579     if (page->mainFrame() != m_frame)
1580         return page->mainFrame()->view()->beginDeferredRepaints();
1581 
1582     m_deferringRepaints++;
1583 }
1584 
1585 
endDeferredRepaints()1586 void FrameView::endDeferredRepaints()
1587 {
1588     Page* page = m_frame->page();
1589     if (page->mainFrame() != m_frame)
1590         return page->mainFrame()->view()->endDeferredRepaints();
1591 
1592     ASSERT(m_deferringRepaints > 0);
1593 
1594     if (--m_deferringRepaints)
1595         return;
1596 
1597     if (m_deferredRepaintTimer.isActive())
1598         return;
1599 
1600     if (double delay = adjustedDeferredRepaintDelay()) {
1601         m_deferredRepaintTimer.startOneShot(delay);
1602         return;
1603     }
1604 
1605     doDeferredRepaints();
1606 }
1607 
checkStopDelayingDeferredRepaints()1608 void FrameView::checkStopDelayingDeferredRepaints()
1609 {
1610     if (!m_deferredRepaintTimer.isActive())
1611         return;
1612 
1613     Document* document = m_frame->document();
1614     if (document && (document->parsing() || document->cachedResourceLoader()->requestCount()))
1615         return;
1616 
1617     m_deferredRepaintTimer.stop();
1618 
1619     doDeferredRepaints();
1620 }
1621 
doDeferredRepaints()1622 void FrameView::doDeferredRepaints()
1623 {
1624     ASSERT(!m_deferringRepaints);
1625     if (!shouldUpdate()) {
1626         m_repaintRects.clear();
1627         m_repaintCount = 0;
1628         return;
1629     }
1630     unsigned size = m_repaintRects.size();
1631     for (unsigned i = 0; i < size; i++) {
1632 #if ENABLE(TILED_BACKING_STORE)
1633         if (frame()->tiledBackingStore()) {
1634             frame()->tiledBackingStore()->invalidate(m_repaintRects[i]);
1635             continue;
1636         }
1637 #endif
1638         ScrollView::repaintContentRectangle(m_repaintRects[i], false);
1639     }
1640     m_repaintRects.clear();
1641     m_repaintCount = 0;
1642 
1643     updateDeferredRepaintDelay();
1644 }
1645 
updateDeferredRepaintDelay()1646 void FrameView::updateDeferredRepaintDelay()
1647 {
1648     Document* document = m_frame->document();
1649     if (!document || (!document->parsing() && !document->cachedResourceLoader()->requestCount())) {
1650         m_deferredRepaintDelay = s_deferredRepaintDelay;
1651         return;
1652     }
1653     if (m_deferredRepaintDelay < s_maxDeferredRepaintDelayDuringLoading) {
1654         m_deferredRepaintDelay += s_deferredRepaintDelayIncrementDuringLoading;
1655         if (m_deferredRepaintDelay > s_maxDeferredRepaintDelayDuringLoading)
1656             m_deferredRepaintDelay = s_maxDeferredRepaintDelayDuringLoading;
1657     }
1658 }
1659 
resetDeferredRepaintDelay()1660 void FrameView::resetDeferredRepaintDelay()
1661 {
1662     m_deferredRepaintDelay = 0;
1663     if (m_deferredRepaintTimer.isActive()) {
1664         m_deferredRepaintTimer.stop();
1665         if (!m_deferringRepaints)
1666             doDeferredRepaints();
1667     }
1668 }
1669 
adjustedDeferredRepaintDelay() const1670 double FrameView::adjustedDeferredRepaintDelay() const
1671 {
1672     ASSERT(!m_deferringRepaints);
1673     if (!m_deferredRepaintDelay)
1674         return 0;
1675     double timeSinceLastPaint = currentTime() - m_lastPaintTime;
1676     return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
1677 }
1678 
deferredRepaintTimerFired(Timer<FrameView> *)1679 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
1680 {
1681     doDeferredRepaints();
1682 }
1683 
layoutTimerFired(Timer<FrameView> *)1684 void FrameView::layoutTimerFired(Timer<FrameView>*)
1685 {
1686 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1687     if (!m_frame->document()->ownerElement())
1688         printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
1689 #endif
1690     layout();
1691 }
1692 
scheduleRelayout()1693 void FrameView::scheduleRelayout()
1694 {
1695     // FIXME: We should assert the page is not in the page cache, but that is causing
1696     // too many false assertions.  See <rdar://problem/7218118>.
1697     ASSERT(m_frame->view() == this);
1698 
1699     if (m_layoutRoot) {
1700         m_layoutRoot->markContainingBlocksForLayout(false);
1701         m_layoutRoot = 0;
1702     }
1703     if (!m_layoutSchedulingEnabled)
1704         return;
1705     if (!needsLayout())
1706         return;
1707     if (!m_frame->document()->shouldScheduleLayout())
1708         return;
1709 
1710     // When frame flattening is enabled, the contents of the frame affects layout of the parent frames.
1711     // Also invalidate parent frame starting from the owner element of this frame.
1712     if (m_frame->settings() && m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) {
1713         if (m_frame->ownerElement()->hasTagName(iframeTag) || m_frame->ownerElement()->hasTagName(frameTag))
1714             m_frame->ownerRenderer()->setNeedsLayout(true, true);
1715     }
1716 
1717     int delay = m_frame->document()->minimumLayoutDelay();
1718     if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
1719         unscheduleRelayout();
1720     if (m_layoutTimer.isActive())
1721         return;
1722 
1723     m_delayedLayout = delay != 0;
1724 
1725 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1726     if (!m_frame->document()->ownerElement())
1727         printf("Scheduling layout for %d\n", delay);
1728 #endif
1729 
1730     m_layoutTimer.startOneShot(delay * 0.001);
1731 }
1732 
isObjectAncestorContainerOf(RenderObject * ancestor,RenderObject * descendant)1733 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
1734 {
1735     for (RenderObject* r = descendant; r; r = r->container()) {
1736         if (r == ancestor)
1737             return true;
1738     }
1739     return false;
1740 }
1741 
scheduleRelayoutOfSubtree(RenderObject * relayoutRoot)1742 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
1743 {
1744     ASSERT(m_frame->view() == this);
1745 
1746     if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) {
1747         if (relayoutRoot)
1748             relayoutRoot->markContainingBlocksForLayout(false);
1749         return;
1750     }
1751 
1752     if (layoutPending() || !m_layoutSchedulingEnabled) {
1753         if (m_layoutRoot != relayoutRoot) {
1754             if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
1755                 // Keep the current root
1756                 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
1757                 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
1758             } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
1759                 // Re-root at relayoutRoot
1760                 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
1761                 m_layoutRoot = relayoutRoot;
1762                 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
1763             } else {
1764                 // Just do a full relayout
1765                 if (m_layoutRoot)
1766                     m_layoutRoot->markContainingBlocksForLayout(false);
1767                 m_layoutRoot = 0;
1768                 relayoutRoot->markContainingBlocksForLayout(false);
1769             }
1770         }
1771     } else if (m_layoutSchedulingEnabled) {
1772         int delay = m_frame->document()->minimumLayoutDelay();
1773         m_layoutRoot = relayoutRoot;
1774         ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
1775         m_delayedLayout = delay != 0;
1776         m_layoutTimer.startOneShot(delay * 0.001);
1777     }
1778 }
1779 
layoutPending() const1780 bool FrameView::layoutPending() const
1781 {
1782     return m_layoutTimer.isActive();
1783 }
1784 
needsLayout() const1785 bool FrameView::needsLayout() const
1786 {
1787     // This can return true in cases where the document does not have a body yet.
1788     // Document::shouldScheduleLayout takes care of preventing us from scheduling
1789     // layout in that case.
1790     if (!m_frame)
1791         return false;
1792     RenderView* root = m_frame->contentRenderer();
1793     return layoutPending()
1794         || (root && root->needsLayout())
1795         || m_layoutRoot
1796         || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
1797 }
1798 
setNeedsLayout()1799 void FrameView::setNeedsLayout()
1800 {
1801     if (m_deferSetNeedsLayouts) {
1802         m_setNeedsLayoutWasDeferred = true;
1803         return;
1804     }
1805     RenderView* root = m_frame->contentRenderer();
1806     if (root)
1807         root->setNeedsLayout(true);
1808 }
1809 
unscheduleRelayout()1810 void FrameView::unscheduleRelayout()
1811 {
1812     m_postLayoutTasksTimer.stop();
1813 
1814     if (!m_layoutTimer.isActive())
1815         return;
1816 
1817 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1818     if (!m_frame->document()->ownerElement())
1819         printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
1820 #endif
1821 
1822     m_layoutTimer.stop();
1823     m_delayedLayout = false;
1824 }
1825 
1826 #if ENABLE(REQUEST_ANIMATION_FRAME)
serviceScriptedAnimations(DOMTimeStamp time)1827 void FrameView::serviceScriptedAnimations(DOMTimeStamp time)
1828 {
1829     for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext())
1830         frame->document()->serviceScriptedAnimations(time);
1831 }
1832 #endif
1833 
isTransparent() const1834 bool FrameView::isTransparent() const
1835 {
1836     return m_isTransparent;
1837 }
1838 
setTransparent(bool isTransparent)1839 void FrameView::setTransparent(bool isTransparent)
1840 {
1841     m_isTransparent = isTransparent;
1842 }
1843 
baseBackgroundColor() const1844 Color FrameView::baseBackgroundColor() const
1845 {
1846     return m_baseBackgroundColor;
1847 }
1848 
setBaseBackgroundColor(const Color & backgroundColor)1849 void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
1850 {
1851     if (!backgroundColor.isValid())
1852         m_baseBackgroundColor = Color::white;
1853     else
1854         m_baseBackgroundColor = backgroundColor;
1855 }
1856 
updateBackgroundRecursively(const Color & backgroundColor,bool transparent)1857 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
1858 {
1859     for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1860         if (FrameView* view = frame->view()) {
1861             view->setTransparent(transparent);
1862             view->setBaseBackgroundColor(backgroundColor);
1863         }
1864     }
1865 }
1866 
shouldUpdateWhileOffscreen() const1867 bool FrameView::shouldUpdateWhileOffscreen() const
1868 {
1869     return m_shouldUpdateWhileOffscreen;
1870 }
1871 
setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)1872 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
1873 {
1874     m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
1875 }
1876 
shouldUpdate(bool immediateRequested) const1877 bool FrameView::shouldUpdate(bool immediateRequested) const
1878 {
1879     if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen())
1880         return false;
1881     return true;
1882 }
1883 
scheduleEvent(PassRefPtr<Event> event,PassRefPtr<Node> eventTarget)1884 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
1885 {
1886     m_actionScheduler->scheduleEvent(event, eventTarget);
1887 }
1888 
pauseScheduledEvents()1889 void FrameView::pauseScheduledEvents()
1890 {
1891     m_actionScheduler->pause();
1892 }
1893 
resumeScheduledEvents()1894 void FrameView::resumeScheduledEvents()
1895 {
1896     m_actionScheduler->resume();
1897 }
1898 
scrollToAnchor()1899 void FrameView::scrollToAnchor()
1900 {
1901     RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
1902     if (!anchorNode)
1903         return;
1904 
1905     if (!anchorNode->renderer())
1906         return;
1907 
1908     IntRect rect;
1909     if (anchorNode != m_frame->document())
1910         rect = anchorNode->getRect();
1911 
1912     // Scroll nested layers and frames to reveal the anchor.
1913     // Align to the top and to the closest side (this matches other browsers).
1914     anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
1915 
1916     if (AXObjectCache::accessibilityEnabled())
1917         m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get());
1918 
1919     // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
1920     m_maintainScrollPositionAnchor = anchorNode;
1921 }
1922 
updateWidget(RenderEmbeddedObject * object)1923 void FrameView::updateWidget(RenderEmbeddedObject* object)
1924 {
1925     ASSERT(!object->node() || object->node()->isElementNode());
1926     Element* ownerElement = static_cast<Element*>(object->node());
1927     // The object may have already been destroyed (thus node cleared),
1928     // but FrameView holds a manual ref, so it won't have been deleted.
1929     ASSERT(m_widgetUpdateSet->contains(object));
1930     if (!ownerElement)
1931         return;
1932 
1933     // No need to update if it's already crashed or known to be missing.
1934     if (object->pluginCrashedOrWasMissing())
1935         return;
1936 
1937     // FIXME: This could turn into a real virtual dispatch if we defined
1938     // updateWidget(bool) on HTMLElement.
1939     if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag))
1940         static_cast<HTMLPlugInImageElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
1941     // FIXME: It is not clear that Media elements need or want this updateWidget() call.
1942 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1943     else if (ownerElement->isMediaElement())
1944         static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
1945 #endif
1946     else
1947         ASSERT_NOT_REACHED();
1948 
1949     // Caution: it's possible the object was destroyed again, since loading a
1950     // plugin may run any arbitrary javascript.
1951     object->updateWidgetPosition();
1952 }
1953 
updateWidgets()1954 bool FrameView::updateWidgets()
1955 {
1956     if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
1957         return true;
1958 
1959     size_t size = m_widgetUpdateSet->size();
1960 
1961     Vector<RenderEmbeddedObject*> objects;
1962     objects.reserveCapacity(size);
1963 
1964     RenderEmbeddedObjectSet::const_iterator end = m_widgetUpdateSet->end();
1965     for (RenderEmbeddedObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
1966         objects.uncheckedAppend(*it);
1967         (*it)->ref();
1968     }
1969 
1970     for (size_t i = 0; i < size; ++i) {
1971         RenderEmbeddedObject* object = objects[i];
1972         updateWidget(object);
1973         m_widgetUpdateSet->remove(object);
1974     }
1975 
1976     RenderArena* arena = m_frame->document()->renderArena();
1977     for (size_t i = 0; i < size; ++i)
1978         objects[i]->deref(arena);
1979 
1980     return m_widgetUpdateSet->isEmpty();
1981 }
1982 
flushAnyPendingPostLayoutTasks()1983 void FrameView::flushAnyPendingPostLayoutTasks()
1984 {
1985     if (!m_hasPendingPostLayoutTasks)
1986         return;
1987 
1988     m_postLayoutTasksTimer.stop();
1989     performPostLayoutTasks();
1990 }
1991 
performPostLayoutTasks()1992 void FrameView::performPostLayoutTasks()
1993 {
1994     m_hasPendingPostLayoutTasks = false;
1995 
1996     m_frame->selection()->setCaretRectNeedsUpdate();
1997     m_frame->selection()->updateAppearance();
1998 
1999     if (m_nestedLayoutCount <= 1) {
2000         if (m_firstLayoutCallbackPending) {
2001             m_firstLayoutCallbackPending = false;
2002             m_frame->loader()->didFirstLayout();
2003         }
2004 
2005         if (m_isVisuallyNonEmpty && m_firstVisuallyNonEmptyLayoutCallbackPending) {
2006             m_firstVisuallyNonEmptyLayoutCallbackPending = false;
2007             m_frame->loader()->didFirstVisuallyNonEmptyLayout();
2008         }
2009     }
2010 
2011     RenderView* root = m_frame->contentRenderer();
2012 
2013     root->updateWidgetPositions();
2014 
2015     for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
2016         if (updateWidgets())
2017             break;
2018     }
2019 
2020     scrollToAnchor();
2021 
2022     m_actionScheduler->resume();
2023 
2024     if (!root->printing()) {
2025         IntSize currentSize = IntSize(width(), height());
2026         float currentZoomFactor = root->style()->zoom();
2027         bool resized = !m_firstLayout && (currentSize != m_lastLayoutSize || currentZoomFactor != m_lastZoomFactor);
2028         m_lastLayoutSize = currentSize;
2029         m_lastZoomFactor = currentZoomFactor;
2030         if (resized)
2031             m_frame->eventHandler()->sendResizeEvent();
2032     }
2033 }
2034 
postLayoutTimerFired(Timer<FrameView> *)2035 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
2036 {
2037     performPostLayoutTasks();
2038 }
2039 
updateOverflowStatus(bool horizontalOverflow,bool verticalOverflow)2040 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
2041 {
2042     if (!m_viewportRenderer)
2043         return;
2044 
2045     if (m_overflowStatusDirty) {
2046         m_horizontalOverflow = horizontalOverflow;
2047         m_verticalOverflow = verticalOverflow;
2048         m_overflowStatusDirty = false;
2049         return;
2050     }
2051 
2052     bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
2053     bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
2054 
2055     if (horizontalOverflowChanged || verticalOverflowChanged) {
2056         m_horizontalOverflow = horizontalOverflow;
2057         m_verticalOverflow = verticalOverflow;
2058 
2059         m_actionScheduler->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
2060             verticalOverflowChanged, verticalOverflow),
2061             m_viewportRenderer->node());
2062     }
2063 
2064 }
2065 
windowClipRect(bool clipToContents) const2066 IntRect FrameView::windowClipRect(bool clipToContents) const
2067 {
2068     ASSERT(m_frame->view() == this);
2069 
2070     if (paintsEntireContents())
2071         return IntRect(IntPoint(0, 0), contentsSize());
2072 
2073     // Set our clip rect to be our contents.
2074     IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
2075     if (!m_frame || !m_frame->ownerElement())
2076         return clipRect;
2077 
2078     // Take our owner element and get the clip rect from the enclosing layer.
2079     Element* elt = m_frame->ownerElement();
2080     // The renderer can sometimes be null when style="display:none" interacts
2081     // with external content and plugins.
2082     RenderLayer* layer = elt->renderer() ? elt->renderer()->enclosingLayer() : 0;
2083     if (!layer)
2084         return clipRect;
2085     FrameView* parentView = elt->document()->view();
2086     clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
2087     return clipRect;
2088 }
2089 
windowClipRectForLayer(const RenderLayer * layer,bool clipToLayerContents) const2090 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const
2091 {
2092     // If we have no layer, just return our window clip rect.
2093     if (!layer)
2094         return windowClipRect();
2095 
2096     // Apply the clip from the layer.
2097     IntRect clipRect;
2098     if (clipToLayerContents)
2099         clipRect = layer->childrenClipRect();
2100     else
2101         clipRect = layer->selfClipRect();
2102     clipRect = contentsToWindow(clipRect);
2103     return intersection(clipRect, windowClipRect());
2104 }
2105 
isActive() const2106 bool FrameView::isActive() const
2107 {
2108     Page* page = frame()->page();
2109     return page && page->focusController()->isActive();
2110 }
2111 
scrollTo(const IntSize & newOffset)2112 void FrameView::scrollTo(const IntSize& newOffset)
2113 {
2114     IntSize offset = scrollOffset();
2115     ScrollView::scrollTo(newOffset);
2116     if (offset != scrollOffset())
2117         scrollPositionChanged();
2118     frame()->loader()->client()->didChangeScrollOffset();
2119 }
2120 
invalidateScrollbarRect(Scrollbar * scrollbar,const IntRect & rect)2121 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
2122 {
2123     // Add in our offset within the FrameView.
2124     IntRect dirtyRect = rect;
2125     dirtyRect.move(scrollbar->x(), scrollbar->y());
2126     invalidateRect(dirtyRect);
2127 }
2128 
getTickmarks(Vector<IntRect> & tickmarks) const2129 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
2130 {
2131     tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
2132 }
2133 
windowResizerRect() const2134 IntRect FrameView::windowResizerRect() const
2135 {
2136     Page* page = frame() ? frame()->page() : 0;
2137     if (!page)
2138         return IntRect();
2139     return page->chrome()->windowResizerRect();
2140 }
2141 
didCompleteRubberBand(const IntSize & initialOverhang) const2142 void FrameView::didCompleteRubberBand(const IntSize& initialOverhang) const
2143 {
2144     Page* page = m_frame->page();
2145     if (!page)
2146         return;
2147     if (page->mainFrame() != m_frame)
2148         return;
2149     return page->chrome()->client()->didCompleteRubberBandForMainFrame(initialOverhang);
2150 }
2151 
scrollbarStyleChanged()2152 void FrameView::scrollbarStyleChanged()
2153 {
2154     Page* page = m_frame->page();
2155     if (!page)
2156         return;
2157     page->setNeedsRecalcStyleInAllFrames();
2158 }
2159 
setVisibleScrollerThumbRect(const IntRect & scrollerThumb)2160 void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
2161 {
2162     Page* page = m_frame->page();
2163     if (!page)
2164         return;
2165     if (page->mainFrame() != m_frame)
2166         return;
2167     return page->chrome()->client()->notifyScrollerThumbIsVisibleInRect(scrollerThumb);
2168 }
2169 
shouldSuspendScrollAnimations() const2170 bool FrameView::shouldSuspendScrollAnimations() const
2171 {
2172     return m_frame->loader()->state() != FrameStateComplete;
2173 }
2174 
notifyPageThatContentAreaWillPaint() const2175 void FrameView::notifyPageThatContentAreaWillPaint() const
2176 {
2177     Page* page = m_frame->page();
2178     const HashSet<ScrollableArea*>* scrollableAreas = page->scrollableAreaSet();
2179     if (!scrollableAreas)
2180         return;
2181 
2182     HashSet<ScrollableArea*>::const_iterator end = scrollableAreas->end();
2183     for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(); it != end; ++it)
2184         (*it)->scrollAnimator()->contentAreaWillPaint();
2185 }
2186 
2187 #if ENABLE(DASHBOARD_SUPPORT)
updateDashboardRegions()2188 void FrameView::updateDashboardRegions()
2189 {
2190     Document* document = m_frame->document();
2191     if (!document->hasDashboardRegions())
2192         return;
2193     Vector<DashboardRegionValue> newRegions;
2194     document->renderBox()->collectDashboardRegions(newRegions);
2195     if (newRegions == document->dashboardRegions())
2196         return;
2197     document->setDashboardRegions(newRegions);
2198     Page* page = m_frame->page();
2199     if (!page)
2200         return;
2201     page->chrome()->client()->dashboardRegionsChanged();
2202 }
2203 #endif
2204 
updateScrollCorner()2205 void FrameView::updateScrollCorner()
2206 {
2207     RenderObject* renderer = 0;
2208     RefPtr<RenderStyle> cornerStyle;
2209 
2210     if (!scrollCornerRect().isEmpty()) {
2211         // Try the <body> element first as a scroll corner source.
2212         Document* doc = m_frame->document();
2213         Element* body = doc ? doc->body() : 0;
2214         if (body && body->renderer()) {
2215             renderer = body->renderer();
2216             cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2217         }
2218 
2219         if (!cornerStyle) {
2220             // If the <body> didn't have a custom style, then the root element might.
2221             Element* docElement = doc ? doc->documentElement() : 0;
2222             if (docElement && docElement->renderer()) {
2223                 renderer = docElement->renderer();
2224                 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2225             }
2226         }
2227 
2228         if (!cornerStyle) {
2229             // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
2230             if (RenderPart* renderer = m_frame->ownerRenderer())
2231                 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2232         }
2233     }
2234 
2235     if (cornerStyle) {
2236         if (!m_scrollCorner)
2237             m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document());
2238         m_scrollCorner->setStyle(cornerStyle.release());
2239         invalidateScrollCorner();
2240     } else if (m_scrollCorner) {
2241         m_scrollCorner->destroy();
2242         m_scrollCorner = 0;
2243     }
2244 
2245     ScrollView::updateScrollCorner();
2246 }
2247 
paintScrollCorner(GraphicsContext * context,const IntRect & cornerRect)2248 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
2249 {
2250     if (context->updatingControlTints()) {
2251         updateScrollCorner();
2252         return;
2253     }
2254 
2255     if (m_scrollCorner) {
2256         m_scrollCorner->paintIntoRect(context, cornerRect.x(), cornerRect.y(), cornerRect);
2257         return;
2258     }
2259 
2260     ScrollView::paintScrollCorner(context, cornerRect);
2261 }
2262 
hasCustomScrollbars() const2263 bool FrameView::hasCustomScrollbars() const
2264 {
2265     const HashSet<RefPtr<Widget> >* viewChildren = children();
2266     HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2267     for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2268         Widget* widget = current->get();
2269         if (widget->isFrameView()) {
2270             if (static_cast<FrameView*>(widget)->hasCustomScrollbars())
2271                 return true;
2272         } else if (widget->isScrollbar()) {
2273             Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
2274             if (scrollbar->isCustomScrollbar())
2275                 return true;
2276         }
2277     }
2278 
2279     return false;
2280 }
2281 
clearOwningRendererForCustomScrollbars(RenderBox * box)2282 void FrameView::clearOwningRendererForCustomScrollbars(RenderBox* box)
2283 {
2284     const HashSet<RefPtr<Widget> >* viewChildren = children();
2285     HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2286     for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2287         Widget* widget = current->get();
2288         if (widget->isScrollbar()) {
2289             Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
2290             if (scrollbar->isCustomScrollbar()) {
2291                 RenderScrollbar* customScrollbar = toRenderScrollbar(scrollbar);
2292                 if (customScrollbar->owningRenderer() == box)
2293                     customScrollbar->clearOwningRenderer();
2294             }
2295         }
2296     }
2297 }
2298 
parentFrameView() const2299 FrameView* FrameView::parentFrameView() const
2300 {
2301     if (Widget* parentView = parent()) {
2302         if (parentView->isFrameView())
2303             return static_cast<FrameView*>(parentView);
2304     }
2305     return 0;
2306 }
2307 
updateControlTints()2308 void FrameView::updateControlTints()
2309 {
2310     // This is called when control tints are changed from aqua/graphite to clear and vice versa.
2311     // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
2312     // This is only done if the theme supports control tinting. It's up to the theme and platform
2313     // to define when controls get the tint and to call this function when that changes.
2314 
2315     // Optimize the common case where we bring a window to the front while it's still empty.
2316     if (!m_frame || m_frame->document()->url().isEmpty())
2317         return;
2318 
2319     if ((m_frame->contentRenderer() && m_frame->contentRenderer()->theme()->supportsControlTints()) || hasCustomScrollbars())  {
2320         if (needsLayout())
2321             layout();
2322         PlatformGraphicsContext* const noContext = 0;
2323         GraphicsContext context(noContext);
2324         context.setUpdatingControlTints(true);
2325         if (platformWidget())
2326             paintContents(&context, visibleContentRect());
2327         else
2328             paint(&context, frameRect());
2329     }
2330 }
2331 
wasScrolledByUser() const2332 bool FrameView::wasScrolledByUser() const
2333 {
2334     return m_wasScrolledByUser;
2335 }
2336 
setWasScrolledByUser(bool wasScrolledByUser)2337 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
2338 {
2339     if (m_inProgrammaticScroll)
2340         return;
2341     m_maintainScrollPositionAnchor = 0;
2342     m_wasScrolledByUser = wasScrolledByUser;
2343 }
2344 
paintContents(GraphicsContext * p,const IntRect & rect)2345 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
2346 {
2347     if (!frame())
2348         return;
2349 
2350     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get(), rect);
2351 
2352     Document* document = m_frame->document();
2353 
2354 #ifndef NDEBUG
2355     bool fillWithRed;
2356     if (document->printing())
2357         fillWithRed = false; // Printing, don't fill with red (can't remember why).
2358     else if (m_frame->ownerElement())
2359         fillWithRed = false; // Subframe, don't fill with red.
2360     else if (isTransparent())
2361         fillWithRed = false; // Transparent, don't fill with red.
2362     else if (m_paintBehavior & PaintBehaviorSelectionOnly)
2363         fillWithRed = false; // Selections are transparent, don't fill with red.
2364     else if (m_nodeToDraw)
2365         fillWithRed = false; // Element images are transparent, don't fill with red.
2366     else
2367         fillWithRed = true;
2368 
2369     if (fillWithRed)
2370         p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
2371 #endif
2372 
2373     bool isTopLevelPainter = !sCurrentPaintTimeStamp;
2374     if (isTopLevelPainter)
2375         sCurrentPaintTimeStamp = currentTime();
2376 
2377     RenderView* contentRenderer = frame()->contentRenderer();
2378     if (!contentRenderer) {
2379         LOG_ERROR("called FrameView::paint with nil renderer");
2380         return;
2381     }
2382 
2383     ASSERT(!needsLayout());
2384     if (needsLayout())
2385         return;
2386 
2387 #if USE(ACCELERATED_COMPOSITING)
2388     if (!p->paintingDisabled())
2389         syncCompositingStateForThisFrame();
2390 #endif
2391 
2392     PaintBehavior oldPaintBehavior = m_paintBehavior;
2393 
2394     if (FrameView* parentView = parentFrameView()) {
2395         if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
2396             m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2397     }
2398 
2399     if (m_paintBehavior == PaintBehaviorNormal)
2400         document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
2401 
2402     if (document->printing())
2403         m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2404 
2405     bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers;
2406     bool isRootFrame = !m_frame->ownerElement();
2407     if (flatteningPaint && isRootFrame)
2408         notifyWidgetsInAllFrames(WillPaintFlattened);
2409 
2410     ASSERT(!m_isPainting);
2411     m_isPainting = true;
2412 
2413     // m_nodeToDraw is used to draw only one element (and its descendants)
2414     RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
2415     RenderLayer* rootLayer = contentRenderer->layer();
2416 
2417     rootLayer->paint(p, rect, m_paintBehavior, eltRenderer);
2418 
2419     if (rootLayer->containsDirtyOverlayScrollbars())
2420         rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer);
2421 
2422     m_isPainting = false;
2423 
2424     if (flatteningPaint && isRootFrame)
2425         notifyWidgetsInAllFrames(DidPaintFlattened);
2426 
2427     m_paintBehavior = oldPaintBehavior;
2428     m_lastPaintTime = currentTime();
2429 
2430 #if ENABLE(DASHBOARD_SUPPORT)
2431     // Regions may have changed as a result of the visibility/z-index of element changing.
2432     if (document->dashboardRegionsDirty())
2433         updateDashboardRegions();
2434 #endif
2435 
2436     if (isTopLevelPainter)
2437         sCurrentPaintTimeStamp = 0;
2438 
2439     InspectorInstrumentation::didPaint(cookie);
2440 }
2441 
setPaintBehavior(PaintBehavior behavior)2442 void FrameView::setPaintBehavior(PaintBehavior behavior)
2443 {
2444     m_paintBehavior = behavior;
2445 }
2446 
paintBehavior() const2447 PaintBehavior FrameView::paintBehavior() const
2448 {
2449     return m_paintBehavior;
2450 }
2451 
isPainting() const2452 bool FrameView::isPainting() const
2453 {
2454     return m_isPainting;
2455 }
2456 
setNodeToDraw(Node * node)2457 void FrameView::setNodeToDraw(Node* node)
2458 {
2459     m_nodeToDraw = node;
2460 }
2461 
paintOverhangAreas(GraphicsContext * context,const IntRect & horizontalOverhangArea,const IntRect & verticalOverhangArea,const IntRect & dirtyRect)2462 void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
2463 {
2464     if (context->paintingDisabled())
2465         return;
2466 
2467     if (m_frame->document()->printing())
2468         return;
2469 
2470     Page* page = m_frame->page();
2471     if (page->mainFrame() == m_frame) {
2472         if (page->chrome()->client()->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
2473             return;
2474     }
2475 
2476     return ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
2477 }
2478 
updateLayoutAndStyleIfNeededRecursive()2479 void FrameView::updateLayoutAndStyleIfNeededRecursive()
2480 {
2481     // We have to crawl our entire tree looking for any FrameViews that need
2482     // layout and make sure they are up to date.
2483     // Mac actually tests for intersection with the dirty region and tries not to
2484     // update layout for frames that are outside the dirty region.  Not only does this seem
2485     // pointless (since those frames will have set a zero timer to layout anyway), but
2486     // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
2487     // region but then become included later by the second frame adding rects to the dirty region
2488     // when it lays out.
2489 
2490     m_frame->document()->updateStyleIfNeeded();
2491 
2492     if (needsLayout())
2493         layout();
2494 
2495     const HashSet<RefPtr<Widget> >* viewChildren = children();
2496     HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2497     for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2498         Widget* widget = (*current).get();
2499         if (widget->isFrameView())
2500             static_cast<FrameView*>(widget)->updateLayoutAndStyleIfNeededRecursive();
2501     }
2502 
2503     // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
2504     // painting, so we need to flush out any deferred repaints too.
2505     flushDeferredRepaints();
2506 }
2507 
flushDeferredRepaints()2508 void FrameView::flushDeferredRepaints()
2509 {
2510     if (!m_deferredRepaintTimer.isActive())
2511         return;
2512     m_deferredRepaintTimer.stop();
2513     doDeferredRepaints();
2514 }
2515 
forceLayout(bool allowSubtree)2516 void FrameView::forceLayout(bool allowSubtree)
2517 {
2518     layout(allowSubtree);
2519 }
2520 
forceLayoutForPagination(const FloatSize & pageSize,float maximumShrinkFactor,Frame::AdjustViewSizeOrNot shouldAdjustViewSize)2521 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximumShrinkFactor, Frame::AdjustViewSizeOrNot shouldAdjustViewSize)
2522 {
2523     // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
2524     // the state of things before and after the layout
2525     RenderView *root = toRenderView(m_frame->document()->renderer());
2526     if (root) {
2527         float pageLogicalWidth = root->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
2528         float pageLogicalHeight = root->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
2529 
2530         int flooredPageLogicalWidth = static_cast<int>(pageLogicalWidth);
2531         root->setLogicalWidth(flooredPageLogicalWidth);
2532         root->setPageLogicalHeight(pageLogicalHeight);
2533         root->setNeedsLayoutAndPrefWidthsRecalc();
2534         forceLayout();
2535 
2536         // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
2537         // page width when shrunk, we will lay out at maximum shrink and clip extra content.
2538         // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
2539         // implementation should not do this!
2540         int docLogicalWidth = root->style()->isHorizontalWritingMode() ? root->docWidth() : root->docHeight();
2541         if (docLogicalWidth > pageLogicalWidth) {
2542             flooredPageLogicalWidth = std::min<int>(docLogicalWidth, pageLogicalWidth * maximumShrinkFactor);
2543             if (pageLogicalHeight)
2544                 root->setPageLogicalHeight(flooredPageLogicalWidth / pageSize.width() * pageSize.height());
2545             root->setLogicalWidth(flooredPageLogicalWidth);
2546             root->setNeedsLayoutAndPrefWidthsRecalc();
2547             forceLayout();
2548             int docLogicalHeight = root->style()->isHorizontalWritingMode() ? root->docHeight() : root->docWidth();
2549             int docLogicalTop = root->style()->isHorizontalWritingMode() ? root->docTop() : root->docLeft();
2550             int docLogicalRight = root->style()->isHorizontalWritingMode() ? root->docRight() : root->docBottom();
2551             int clippedLogicalLeft = 0;
2552             if (!root->style()->isLeftToRightDirection())
2553                 clippedLogicalLeft = docLogicalRight - flooredPageLogicalWidth;
2554             IntRect overflow(clippedLogicalLeft, docLogicalTop, flooredPageLogicalWidth, docLogicalHeight);
2555             if (!root->style()->isHorizontalWritingMode())
2556                 overflow = overflow.transposedRect();
2557             root->clearLayoutOverflow();
2558             root->addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
2559         }
2560     }
2561 
2562     if (shouldAdjustViewSize)
2563         adjustViewSize();
2564 }
2565 
adjustPageHeightDeprecated(float * newBottom,float oldTop,float oldBottom,float)2566 void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
2567 {
2568     RenderView* root = m_frame->contentRenderer();
2569     if (root) {
2570         // Use a context with painting disabled.
2571         GraphicsContext context((PlatformGraphicsContext*)0);
2572         root->setTruncatedAt((int)floorf(oldBottom));
2573         IntRect dirtyRect(0, (int)floorf(oldTop), root->maxXLayoutOverflow(), (int)ceilf(oldBottom - oldTop));
2574         root->setPrintRect(dirtyRect);
2575         root->layer()->paint(&context, dirtyRect);
2576         *newBottom = root->bestTruncatedAt();
2577         if (*newBottom == 0)
2578             *newBottom = oldBottom;
2579         root->setPrintRect(IntRect());
2580     } else
2581         *newBottom = oldBottom;
2582 }
2583 
convertFromRenderer(const RenderObject * renderer,const IntRect & rendererRect) const2584 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
2585 {
2586     IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
2587 
2588     // Convert from page ("absolute") to FrameView coordinates.
2589     rect.move(-scrollX(), -scrollY());
2590 
2591     return rect;
2592 }
2593 
convertToRenderer(const RenderObject * renderer,const IntRect & viewRect) const2594 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
2595 {
2596     IntRect rect = viewRect;
2597 
2598     // Convert from FrameView coords into page ("absolute") coordinates.
2599     rect.move(scrollX(), scrollY());
2600 
2601     // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
2602     // move the rect for now.
2603     rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
2604     return rect;
2605 }
2606 
convertFromRenderer(const RenderObject * renderer,const IntPoint & rendererPoint) const2607 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
2608 {
2609     IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
2610 
2611     // Convert from page ("absolute") to FrameView coordinates.
2612     point.move(-scrollX(), -scrollY());
2613     return point;
2614 }
2615 
convertToRenderer(const RenderObject * renderer,const IntPoint & viewPoint) const2616 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
2617 {
2618     IntPoint point = viewPoint;
2619 
2620     // Convert from FrameView coords into page ("absolute") coordinates.
2621     point += IntSize(scrollX(), scrollY());
2622 
2623     return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
2624 }
2625 
convertToContainingView(const IntRect & localRect) const2626 IntRect FrameView::convertToContainingView(const IntRect& localRect) const
2627 {
2628     if (const ScrollView* parentScrollView = parent()) {
2629         if (parentScrollView->isFrameView()) {
2630             const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2631             // Get our renderer in the parent view
2632             RenderPart* renderer = m_frame->ownerRenderer();
2633             if (!renderer)
2634                 return localRect;
2635 
2636             IntRect rect(localRect);
2637             // Add borders and padding??
2638             rect.move(renderer->borderLeft() + renderer->paddingLeft(),
2639                       renderer->borderTop() + renderer->paddingTop());
2640             return parentView->convertFromRenderer(renderer, rect);
2641         }
2642 
2643         return Widget::convertToContainingView(localRect);
2644     }
2645 
2646     return localRect;
2647 }
2648 
convertFromContainingView(const IntRect & parentRect) const2649 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
2650 {
2651     if (const ScrollView* parentScrollView = parent()) {
2652         if (parentScrollView->isFrameView()) {
2653             const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2654 
2655             // Get our renderer in the parent view
2656             RenderPart* renderer = m_frame->ownerRenderer();
2657             if (!renderer)
2658                 return parentRect;
2659 
2660             IntRect rect = parentView->convertToRenderer(renderer, parentRect);
2661             // Subtract borders and padding
2662             rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
2663                       -renderer->borderTop() - renderer->paddingTop());
2664             return rect;
2665         }
2666 
2667         return Widget::convertFromContainingView(parentRect);
2668     }
2669 
2670     return parentRect;
2671 }
2672 
convertToContainingView(const IntPoint & localPoint) const2673 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
2674 {
2675     if (const ScrollView* parentScrollView = parent()) {
2676         if (parentScrollView->isFrameView()) {
2677             const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2678 
2679             // Get our renderer in the parent view
2680             RenderPart* renderer = m_frame->ownerRenderer();
2681             if (!renderer)
2682                 return localPoint;
2683 
2684             IntPoint point(localPoint);
2685 
2686             // Add borders and padding
2687             point.move(renderer->borderLeft() + renderer->paddingLeft(),
2688                        renderer->borderTop() + renderer->paddingTop());
2689             return parentView->convertFromRenderer(renderer, point);
2690         }
2691 
2692         return Widget::convertToContainingView(localPoint);
2693     }
2694 
2695     return localPoint;
2696 }
2697 
convertFromContainingView(const IntPoint & parentPoint) const2698 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
2699 {
2700     if (const ScrollView* parentScrollView = parent()) {
2701         if (parentScrollView->isFrameView()) {
2702             const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2703 
2704             // Get our renderer in the parent view
2705             RenderPart* renderer = m_frame->ownerRenderer();
2706             if (!renderer)
2707                 return parentPoint;
2708 
2709             IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
2710             // Subtract borders and padding
2711             point.move(-renderer->borderLeft() - renderer->paddingLeft(),
2712                        -renderer->borderTop() - renderer->paddingTop());
2713             return point;
2714         }
2715 
2716         return Widget::convertFromContainingView(parentPoint);
2717     }
2718 
2719     return parentPoint;
2720 }
2721 
2722 // Normal delay
setRepaintThrottlingDeferredRepaintDelay(double p)2723 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
2724 {
2725     s_deferredRepaintDelay = p;
2726 }
2727 
2728 // Negative value would mean that first few repaints happen without a delay
setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)2729 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)
2730 {
2731     s_initialDeferredRepaintDelayDuringLoading = p;
2732 }
2733 
2734 // The delay grows on each repaint to this maximum value
setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)2735 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)
2736 {
2737     s_maxDeferredRepaintDelayDuringLoading = p;
2738 }
2739 
2740 // On each repaint the delay increases by this amount
setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)2741 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)
2742 {
2743     s_deferredRepaintDelayIncrementDuringLoading = p;
2744 }
2745 
isVerticalDocument() const2746 bool FrameView::isVerticalDocument() const
2747 {
2748     if (!m_frame)
2749         return true;
2750     Document* doc = m_frame->document();
2751     if (!doc)
2752         return true;
2753     RenderObject* renderView = doc->renderer();
2754     if (!renderView)
2755         return true;
2756     return renderView->style()->isHorizontalWritingMode();
2757 }
2758 
isFlippedDocument() const2759 bool FrameView::isFlippedDocument() const
2760 {
2761     if (!m_frame)
2762         return false;
2763     Document* doc = m_frame->document();
2764     if (!doc)
2765         return false;
2766     RenderObject* renderView = doc->renderer();
2767     if (!renderView)
2768         return false;
2769     return renderView->style()->isFlippedBlocksWritingMode();
2770 }
2771 
notifyWidgetsInAllFrames(WidgetNotification notification)2772 void FrameView::notifyWidgetsInAllFrames(WidgetNotification notification)
2773 {
2774     for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
2775         if (RenderView* root = frame->contentRenderer())
2776             root->notifyWidgets(notification);
2777     }
2778 }
2779 
axObjectCache() const2780 AXObjectCache* FrameView::axObjectCache() const
2781 {
2782     if (frame() && frame()->document() && frame()->document()->axObjectCacheExists())
2783         return frame()->document()->axObjectCache();
2784     return 0;
2785 }
2786 
2787 } // namespace WebCore
2788