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