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