• 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 "core/frame/FrameView.h"
29 
30 #include "HTMLNames.h"
31 #include "RuntimeEnabledFeatures.h"
32 #include "core/accessibility/AXObjectCache.h"
33 #include "core/animation/DocumentAnimations.h"
34 #include "core/css/FontFaceSet.h"
35 #include "core/css/resolver/StyleResolver.h"
36 #include "core/dom/DocumentMarkerController.h"
37 #include "core/editing/FrameSelection.h"
38 #include "core/events/OverflowEvent.h"
39 #include "core/fetch/ResourceFetcher.h"
40 #include "core/fetch/ResourceLoadPriorityOptimizer.h"
41 #include "core/fetch/TextResourceDecoder.h"
42 #include "core/frame/Frame.h"
43 #include "core/frame/GraphicsLayerDebugInfo.h"
44 #include "core/frame/Settings.h"
45 #include "core/frame/animation/AnimationController.h"
46 #include "core/html/HTMLFrameElement.h"
47 #include "core/html/HTMLHtmlElement.h"
48 #include "core/html/HTMLPlugInElement.h"
49 #include "core/inspector/InspectorInstrumentation.h"
50 #include "core/loader/FrameLoader.h"
51 #include "core/loader/FrameLoaderClient.h"
52 #include "core/page/Chrome.h"
53 #include "core/page/ChromeClient.h"
54 #include "core/page/EventHandler.h"
55 #include "core/page/FocusController.h"
56 #include "core/page/FrameTree.h"
57 #include "core/page/scrolling/ScrollingCoordinator.h"
58 #include "core/rendering/CompositedLayerMapping.h"
59 #include "core/rendering/LayoutIndicator.h"
60 #include "core/rendering/RenderCounter.h"
61 #include "core/rendering/RenderEmbeddedObject.h"
62 #include "core/rendering/RenderLayer.h"
63 #include "core/rendering/RenderLayerCompositor.h"
64 #include "core/rendering/RenderPart.h"
65 #include "core/rendering/RenderScrollbar.h"
66 #include "core/rendering/RenderScrollbarPart.h"
67 #include "core/rendering/RenderTheme.h"
68 #include "core/rendering/RenderView.h"
69 #include "core/rendering/TextAutosizer.h"
70 #include "core/rendering/style/RenderStyle.h"
71 #include "core/rendering/svg/RenderSVGRoot.h"
72 #include "core/svg/SVGDocument.h"
73 #include "core/svg/SVGSVGElement.h"
74 #include "platform/TraceEvent.h"
75 #include "platform/fonts/FontCache.h"
76 #include "platform/geometry/FloatRect.h"
77 #include "platform/graphics/GraphicsContext.h"
78 #include "platform/scroll/ScrollAnimator.h"
79 #include "platform/scroll/ScrollbarTheme.h"
80 #include "platform/text/TextStream.h"
81 #include "wtf/CurrentTime.h"
82 #include "wtf/TemporaryChange.h"
83 
84 namespace WebCore {
85 
86 using namespace HTMLNames;
87 
88 double FrameView::s_currentFrameTimeStamp = 0.0;
89 bool FrameView::s_inPaintContents = false;
90 
91 
92 // REPAINT_THROTTLING now chooses default values for throttling parameters.
93 // Should be removed when applications start using runtime configuration.
94 #if ENABLE(REPAINT_THROTTLING)
95 // Normal delay
96 double FrameView::s_normalDeferredRepaintDelay = 0.016;
97 // Negative value would mean that first few repaints happen without a delay
98 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
99 // The delay grows on each repaint to this maximum value
100 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
101 // On each repaint the delay increses by this amount
102 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
103 #else
104 // FIXME: Repaint throttling could be good to have on all platform.
105 // The balance between CPU use and repaint frequency will need some tuning for desktop.
106 // More hooks may be needed to reset the delay on things like GIF and CSS animations.
107 double FrameView::s_normalDeferredRepaintDelay = 0;
108 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
109 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
110 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
111 #endif
112 
113 // The maximum number of updateWidgets iterations that should be done before returning.
114 static const unsigned maxUpdateWidgetsIterations = 2;
115 
updateLayerPositionFlags(RenderLayer * layer,bool isRelayoutingSubtree,bool didFullRepaint)116 static RenderLayer::UpdateLayerPositionsFlags updateLayerPositionFlags(RenderLayer* layer, bool isRelayoutingSubtree, bool didFullRepaint)
117 {
118     RenderLayer::UpdateLayerPositionsFlags flags = RenderLayer::defaultFlags;
119 
120     if (didFullRepaint) {
121         flags &= ~RenderLayer::CheckForRepaint;
122         flags |= RenderLayer::NeedsFullRepaintInBacking;
123     }
124     if (isRelayoutingSubtree && layer->isPaginated())
125         flags |= RenderLayer::UpdatePagination;
126     return flags;
127 }
128 
paginationModeForRenderStyle(RenderStyle * style)129 Pagination::Mode paginationModeForRenderStyle(RenderStyle* style)
130 {
131     EOverflow overflow = style->overflowY();
132     if (overflow != OPAGEDX && overflow != OPAGEDY)
133         return Pagination::Unpaginated;
134 
135     bool isHorizontalWritingMode = style->isHorizontalWritingMode();
136     TextDirection textDirection = style->direction();
137     WritingMode writingMode = style->writingMode();
138 
139     // paged-x always corresponds to LeftToRightPaginated or RightToLeftPaginated. If the WritingMode
140     // is horizontal, then we use TextDirection to choose between those options. If the WritingMode
141     // is vertical, then the direction of the verticality dictates the choice.
142     if (overflow == OPAGEDX) {
143         if ((isHorizontalWritingMode && textDirection == LTR) || writingMode == LeftToRightWritingMode)
144             return Pagination::LeftToRightPaginated;
145         return Pagination::RightToLeftPaginated;
146     }
147 
148     // paged-y always corresponds to TopToBottomPaginated or BottomToTopPaginated. If the WritingMode
149     // is horizontal, then the direction of the horizontality dictates the choice. If the WritingMode
150     // is vertical, then we use TextDirection to choose between those options.
151     if (writingMode == TopToBottomWritingMode || (!isHorizontalWritingMode && textDirection == RTL))
152         return Pagination::TopToBottomPaginated;
153     return Pagination::BottomToTopPaginated;
154 }
155 
DeferredRepaintScope(FrameView & view)156 FrameView::DeferredRepaintScope::DeferredRepaintScope(FrameView& view)
157     : m_view(&view)
158 {
159     m_view->beginDeferredRepaints();
160 }
161 
~DeferredRepaintScope()162 FrameView::DeferredRepaintScope::~DeferredRepaintScope()
163 {
164     m_view->endDeferredRepaints();
165 }
166 
FrameView(Frame * frame)167 FrameView::FrameView(Frame* frame)
168     : m_frame(frame)
169     , m_canHaveScrollbars(true)
170     , m_slowRepaintObjectCount(0)
171     , m_layoutTimer(this, &FrameView::layoutTimerFired)
172     , m_layoutRoot(0)
173     , m_inSynchronousPostLayout(false)
174     , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
175     , m_updateWidgetsTimer(this, &FrameView::updateWidgetsTimerFired)
176     , m_isTransparent(false)
177     , m_baseBackgroundColor(Color::white)
178     , m_mediaType("screen")
179     , m_overflowStatusDirty(true)
180     , m_viewportRenderer(0)
181     , m_wasScrolledByUser(false)
182     , m_inProgrammaticScroll(false)
183     , m_safeToPropagateScrollToParent(true)
184     , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
185     , m_isTrackingRepaints(false)
186     , m_shouldUpdateWhileOffscreen(true)
187     , m_scrollCorner(0)
188     , m_shouldAutoSize(false)
189     , m_inAutoSize(false)
190     , m_didRunAutosize(false)
191     , m_hasSoftwareFilters(false)
192     , m_visibleContentScaleFactor(1)
193     , m_inputEventsScaleFactorForEmulation(1)
194     , m_partialLayout()
195     , m_layoutSizeFixedToFrameSize(true)
196 {
197     ASSERT(m_frame);
198     init();
199 
200     if (!isMainFrame())
201         return;
202 
203     ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed);
204     ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed);
205 }
206 
create(Frame * frame)207 PassRefPtr<FrameView> FrameView::create(Frame* frame)
208 {
209     RefPtr<FrameView> view = adoptRef(new FrameView(frame));
210     view->show();
211     return view.release();
212 }
213 
create(Frame * frame,const IntSize & initialSize)214 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize)
215 {
216     RefPtr<FrameView> view = adoptRef(new FrameView(frame));
217     view->Widget::setFrameRect(IntRect(view->location(), initialSize));
218     view->setLayoutSizeInternal(initialSize);
219 
220     view->show();
221     return view.release();
222 }
223 
~FrameView()224 FrameView::~FrameView()
225 {
226     if (m_postLayoutTasksTimer.isActive())
227         m_postLayoutTasksTimer.stop();
228 
229     removeFromAXObjectCache();
230     resetScrollbars();
231 
232     // Custom scrollbars should already be destroyed at this point
233     ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
234     ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
235 
236     setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
237     setHasVerticalScrollbar(false);
238 
239     ASSERT(!m_scrollCorner);
240 
241     ASSERT(m_frame);
242     ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
243     RenderPart* renderer = m_frame->ownerRenderer();
244     if (renderer && renderer->widget() == this)
245         renderer->setWidget(0);
246 }
247 
reset()248 void FrameView::reset()
249 {
250     m_cannotBlitToWindow = false;
251     m_isOverlapped = false;
252     m_contentIsOpaque = false;
253     m_borderX = 30;
254     m_borderY = 30;
255     m_layoutTimer.stop();
256     m_layoutRoot = 0;
257     m_delayedLayout = false;
258     m_doFullRepaint = true;
259     m_layoutSchedulingEnabled = true;
260     m_inLayout = false;
261     m_doingPreLayoutStyleUpdate = false;
262     m_inSynchronousPostLayout = false;
263     m_layoutCount = 0;
264     m_nestedLayoutCount = 0;
265     m_postLayoutTasksTimer.stop();
266     m_updateWidgetsTimer.stop();
267     m_firstLayout = true;
268     m_firstLayoutCallbackPending = false;
269     m_wasScrolledByUser = false;
270     m_safeToPropagateScrollToParent = true;
271     m_lastViewportSize = IntSize();
272     m_lastZoomFactor = 1.0f;
273     m_deferringRepaints = 0;
274     m_repaintCount = 0;
275     m_repaintRects.clear();
276     m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading;
277     m_deferredRepaintTimer.stop();
278     m_isTrackingRepaints = false;
279     m_trackedRepaintRects.clear();
280     m_lastPaintTime = 0;
281     m_paintBehavior = PaintBehaviorNormal;
282     m_isPainting = false;
283     m_visuallyNonEmptyCharacterCount = 0;
284     m_visuallyNonEmptyPixelCount = 0;
285     m_isVisuallyNonEmpty = false;
286     m_firstVisuallyNonEmptyLayoutCallbackPending = true;
287     m_maintainScrollPositionAnchor = 0;
288     m_partialLayout.reset();
289     m_viewportConstrainedObjects.clear();
290 }
291 
removeFromAXObjectCache()292 void FrameView::removeFromAXObjectCache()
293 {
294     if (AXObjectCache* cache = axObjectCache())
295         cache->remove(this);
296 }
297 
resetScrollbars()298 void FrameView::resetScrollbars()
299 {
300     // Reset the document's scrollbars back to our defaults before we yield the floor.
301     m_firstLayout = true;
302     setScrollbarsSuppressed(true);
303     if (m_canHaveScrollbars)
304         setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
305     else
306         setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
307     setScrollbarsSuppressed(false);
308 }
309 
init()310 void FrameView::init()
311 {
312     reset();
313 
314     m_margins = LayoutSize(-1, -1); // undefined
315     m_size = LayoutSize();
316 
317     // Propagate the marginwidth/height and scrolling modes to the view.
318     Element* ownerElement = m_frame->ownerElement();
319     if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
320         HTMLFrameElementBase* frameElt = toHTMLFrameElementBase(ownerElement);
321         if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
322             setCanHaveScrollbars(false);
323         LayoutUnit marginWidth = frameElt->marginWidth();
324         LayoutUnit marginHeight = frameElt->marginHeight();
325         if (marginWidth != -1)
326             setMarginWidth(marginWidth);
327         if (marginHeight != -1)
328             setMarginHeight(marginHeight);
329     }
330 }
331 
prepareForDetach()332 void FrameView::prepareForDetach()
333 {
334     RELEASE_ASSERT(!isInLayout());
335 
336     if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
337         scrollAnimator->cancelAnimations();
338 
339     detachCustomScrollbars();
340     // When the view is no longer associated with a frame, it needs to be removed from the ax object cache
341     // right now, otherwise it won't be able to reach the topDocument()'s axObject cache later.
342     removeFromAXObjectCache();
343 
344     if (m_frame->page()) {
345         if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator())
346             scrollingCoordinator->willDestroyScrollableArea(this);
347     }
348 }
349 
detachCustomScrollbars()350 void FrameView::detachCustomScrollbars()
351 {
352     Scrollbar* horizontalBar = horizontalScrollbar();
353     if (horizontalBar && horizontalBar->isCustomScrollbar())
354         setHasHorizontalScrollbar(false);
355 
356     Scrollbar* verticalBar = verticalScrollbar();
357     if (verticalBar && verticalBar->isCustomScrollbar())
358         setHasVerticalScrollbar(false);
359 
360     if (m_scrollCorner) {
361         m_scrollCorner->destroy();
362         m_scrollCorner = 0;
363     }
364 }
365 
recalculateScrollbarOverlayStyle()366 void FrameView::recalculateScrollbarOverlayStyle()
367 {
368     ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle();
369     ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault;
370 
371     Color backgroundColor = documentBackgroundColor();
372     if (backgroundColor.isValid()) {
373         // Reduce the background color from RGB to a lightness value
374         // and determine which scrollbar style to use based on a lightness
375         // heuristic.
376         double hue, saturation, lightness;
377         backgroundColor.getHSL(hue, saturation, lightness);
378         if (lightness <= .5)
379             overlayStyle = ScrollbarOverlayStyleLight;
380     }
381 
382     if (oldOverlayStyle != overlayStyle)
383         setScrollbarOverlayStyle(overlayStyle);
384 }
385 
clear()386 void FrameView::clear()
387 {
388     setCanBlitOnScroll(true);
389 
390     reset();
391 
392     if (RenderPart* renderer = m_frame->ownerRenderer())
393         renderer->viewCleared();
394 
395     setScrollbarsSuppressed(true);
396 }
397 
didFirstLayout() const398 bool FrameView::didFirstLayout() const
399 {
400     return !m_firstLayout;
401 }
402 
invalidateRect(const IntRect & rect)403 void FrameView::invalidateRect(const IntRect& rect)
404 {
405     if (!parent()) {
406         if (HostWindow* window = hostWindow())
407             window->invalidateContentsAndRootView(rect);
408         return;
409     }
410 
411     RenderPart* renderer = m_frame->ownerRenderer();
412     if (!renderer)
413         return;
414 
415     IntRect repaintRect = rect;
416     repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
417                      renderer->borderTop() + renderer->paddingTop());
418     renderer->repaintRectangle(repaintRect);
419 }
420 
setFrameRect(const IntRect & newRect)421 void FrameView::setFrameRect(const IntRect& newRect)
422 {
423     IntRect oldRect = frameRect();
424     if (newRect == oldRect)
425         return;
426 
427     // Autosized font sizes depend on the width of the viewing area.
428     if (newRect.width() != oldRect.width()) {
429         Page* page = m_frame->page();
430         if (isMainFrame() && page->settings().textAutosizingEnabled()) {
431             TextAutosizer* textAutosizer = m_frame->document()->textAutosizer();
432             if (textAutosizer) {
433                 for (Frame* frame = page->mainFrame(); frame; frame = frame->tree().traverseNext())
434                     textAutosizer->recalculateMultipliers();
435             }
436         }
437     }
438 
439     ScrollView::setFrameRect(newRect);
440 
441     updateScrollableAreaSet();
442 
443     if (RenderView* renderView = this->renderView()) {
444         if (renderView->usesCompositing())
445             renderView->compositor()->frameViewDidChangeSize();
446     }
447 }
448 
scheduleAnimation()449 bool FrameView::scheduleAnimation()
450 {
451     if (HostWindow* window = hostWindow()) {
452         window->scheduleAnimation();
453         return true;
454     }
455     return false;
456 }
457 
renderView() const458 RenderView* FrameView::renderView() const
459 {
460     return frame().contentRenderer();
461 }
462 
setMarginWidth(LayoutUnit w)463 void FrameView::setMarginWidth(LayoutUnit w)
464 {
465     // make it update the rendering area when set
466     m_margins.setWidth(w);
467 }
468 
setMarginHeight(LayoutUnit h)469 void FrameView::setMarginHeight(LayoutUnit h)
470 {
471     // make it update the rendering area when set
472     m_margins.setHeight(h);
473 }
474 
setCanHaveScrollbars(bool canHaveScrollbars)475 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
476 {
477     m_canHaveScrollbars = canHaveScrollbars;
478     ScrollView::setCanHaveScrollbars(canHaveScrollbars);
479 }
480 
updateCanHaveScrollbars()481 void FrameView::updateCanHaveScrollbars()
482 {
483     ScrollbarMode hMode;
484     ScrollbarMode vMode;
485     scrollbarModes(hMode, vMode);
486     if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
487         setCanHaveScrollbars(false);
488     else
489         setCanHaveScrollbars(true);
490 }
491 
shouldUseCustomScrollbars(Element * & customScrollbarElement,Frame * & customScrollbarFrame)492 bool FrameView::shouldUseCustomScrollbars(Element*& customScrollbarElement, Frame*& customScrollbarFrame)
493 {
494     customScrollbarElement = 0;
495     customScrollbarFrame = 0;
496 
497     if (Settings* settings = m_frame->settings()) {
498         if (!settings->allowCustomScrollbarInMainFrame() && isMainFrame())
499             return false;
500     }
501 
502     // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
503     Document* doc = m_frame->document();
504 
505     // Try the <body> element first as a scrollbar source.
506     Element* body = doc ? doc->body() : 0;
507     if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR)) {
508         customScrollbarElement = body;
509         return true;
510     }
511 
512     // If the <body> didn't have a custom style, then the root element might.
513     Element* docElement = doc ? doc->documentElement() : 0;
514     if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR)) {
515         customScrollbarElement = docElement;
516         return true;
517     }
518 
519     // If we have an owning ipage/Frame element, then it can set the custom scrollbar also.
520     RenderPart* frameRenderer = m_frame->ownerRenderer();
521     if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR)) {
522         customScrollbarFrame = m_frame.get();
523         return true;
524     }
525 
526     return false;
527 }
528 
createScrollbar(ScrollbarOrientation orientation)529 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
530 {
531     Element* customScrollbarElement = 0;
532     Frame* customScrollbarFrame = 0;
533     if (shouldUseCustomScrollbars(customScrollbarElement, customScrollbarFrame))
534         return RenderScrollbar::createCustomScrollbar(this, orientation, customScrollbarElement, customScrollbarFrame);
535 
536     // Nobody set a custom style, so we just use a native scrollbar.
537     return ScrollView::createScrollbar(orientation);
538 }
539 
setContentsSize(const IntSize & size)540 void FrameView::setContentsSize(const IntSize& size)
541 {
542     if (size == contentsSize())
543         return;
544 
545     ScrollView::setContentsSize(size);
546     ScrollView::contentsResized();
547 
548     Page* page = frame().page();
549     if (!page)
550         return;
551 
552     updateScrollableAreaSet();
553 
554     page->chrome().contentsSizeChanged(m_frame.get(), size);
555 }
556 
adjustViewSize()557 void FrameView::adjustViewSize()
558 {
559     RenderView* renderView = this->renderView();
560     if (!renderView)
561         return;
562 
563     ASSERT(m_frame->view() == this);
564 
565     const IntRect rect = renderView->documentRect();
566     const IntSize& size = rect.size();
567     ScrollView::setScrollOrigin(IntPoint(-rect.x(), -rect.y()), !m_frame->document()->printing(), size == contentsSize());
568 
569     setContentsSize(size);
570 }
571 
applyOverflowToViewport(RenderObject * o,ScrollbarMode & hMode,ScrollbarMode & vMode)572 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
573 {
574     // Handle the overflow:hidden/scroll case for the body/html elements.  WinIE treats
575     // overflow:hidden and overflow:scroll on <body> as applying to the document's
576     // scrollbars.  The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
577     // use the root element.
578 
579     EOverflow overflowX = o->style()->overflowX();
580     EOverflow overflowY = o->style()->overflowY();
581 
582     if (o->isSVGRoot()) {
583         // overflow is ignored in stand-alone SVG documents.
584         if (!toRenderSVGRoot(o)->isEmbeddedThroughFrameContainingSVGDocument())
585             return;
586         overflowX = OHIDDEN;
587         overflowY = OHIDDEN;
588     }
589 
590     bool ignoreOverflowHidden = false;
591     if (m_frame->settings()->ignoreMainFrameOverflowHiddenQuirk() && m_frame->isMainFrame())
592         ignoreOverflowHidden = true;
593 
594     switch (overflowX) {
595         case OHIDDEN:
596             if (!ignoreOverflowHidden)
597                 hMode = ScrollbarAlwaysOff;
598             break;
599         case OSCROLL:
600             hMode = ScrollbarAlwaysOn;
601             break;
602         case OAUTO:
603             hMode = ScrollbarAuto;
604             break;
605         default:
606             // Don't set it at all.
607             ;
608     }
609 
610      switch (overflowY) {
611         case OHIDDEN:
612             if (!ignoreOverflowHidden)
613                 vMode = ScrollbarAlwaysOff;
614             break;
615         case OSCROLL:
616             vMode = ScrollbarAlwaysOn;
617             break;
618         case OAUTO:
619             vMode = ScrollbarAuto;
620             break;
621         default:
622             // Don't set it at all. Values of OPAGEDX and OPAGEDY are handled by applyPaginationToViewPort().
623             ;
624     }
625 
626     m_viewportRenderer = o;
627 }
628 
applyPaginationToViewport()629 void FrameView::applyPaginationToViewport()
630 {
631     Document* document = m_frame->document();
632     Node* documentElement = document->documentElement();
633     RenderObject* documentRenderer = documentElement ? documentElement->renderer() : 0;
634     RenderObject* documentOrBodyRenderer = documentRenderer;
635     Node* body = document->body();
636     if (body && body->renderer()) {
637         if (body->hasTagName(bodyTag))
638             documentOrBodyRenderer = documentRenderer->style()->overflowX() == OVISIBLE && isHTMLHtmlElement(documentElement) ? body->renderer() : documentRenderer;
639     }
640 
641     Pagination pagination;
642 
643     if (!documentOrBodyRenderer) {
644         setPagination(pagination);
645         return;
646     }
647 
648     EOverflow overflowY = documentOrBodyRenderer->style()->overflowY();
649     if (overflowY == OPAGEDX || overflowY == OPAGEDY) {
650         pagination.mode = WebCore::paginationModeForRenderStyle(documentOrBodyRenderer->style());
651         pagination.gap = static_cast<unsigned>(documentOrBodyRenderer->style()->columnGap());
652     }
653 
654     setPagination(pagination);
655 }
656 
calculateScrollbarModesForLayout(ScrollbarMode & hMode,ScrollbarMode & vMode,ScrollbarModesCalculationStrategy strategy)657 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy)
658 {
659     m_viewportRenderer = 0;
660 
661     const HTMLFrameOwnerElement* owner = m_frame->ownerElement();
662     if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
663         hMode = ScrollbarAlwaysOff;
664         vMode = ScrollbarAlwaysOff;
665         return;
666     }
667 
668     if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) {
669         hMode = ScrollbarAuto;
670         // Seamless documents begin with heights of 0; we special case that here
671         // to correctly render documents that don't need scrollbars.
672         IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size();
673         bool isSeamlessDocument = frame().document() && frame().document()->shouldDisplaySeamlesslyWithParent();
674         vMode = (isSeamlessDocument && !fullVisibleSize.height()) ? ScrollbarAlwaysOff : ScrollbarAuto;
675     } else {
676         hMode = ScrollbarAlwaysOff;
677         vMode = ScrollbarAlwaysOff;
678     }
679 
680     if (!m_layoutRoot) {
681         Document* document = m_frame->document();
682         Node* documentElement = document->documentElement();
683         RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
684         Node* body = document->body();
685         if (body && body->renderer()) {
686             if (body->hasTagName(framesetTag)) {
687                 vMode = ScrollbarAlwaysOff;
688                 hMode = ScrollbarAlwaysOff;
689             } else if (body->hasTagName(bodyTag)) {
690                 // It's sufficient to just check the X overflow,
691                 // since it's illegal to have visible in only one direction.
692                 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && isHTMLHtmlElement(document->documentElement()) ? body->renderer() : rootRenderer;
693                 if (o->style())
694                     applyOverflowToViewport(o, hMode, vMode);
695             }
696         } else if (rootRenderer)
697             applyOverflowToViewport(rootRenderer, hMode, vMode);
698     }
699 }
700 
updateCompositingLayersAfterStyleChange()701 void FrameView::updateCompositingLayersAfterStyleChange()
702 {
703     TRACE_EVENT0("webkit", "FrameView::updateCompositingLayersAfterStyleChange");
704     RenderView* renderView = this->renderView();
705     if (!renderView)
706         return;
707 
708     // If we expect to update compositing after an incipient layout, don't do so here.
709     if (m_doingPreLayoutStyleUpdate || layoutPending() || renderView->needsLayout())
710         return;
711 
712     // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
713     renderView->compositor()->cacheAcceleratedCompositingFlags();
714 
715     // Sometimes we will change a property (for example, z-index) that will not
716     // cause a layout, but will require us to update compositing state. We only
717     // need to do this if a layout is not already scheduled.
718     if (!needsLayout())
719         renderView->compositor()->updateCompositingRequirementsState();
720 
721     renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterStyleChange);
722 }
723 
updateCompositingLayersAfterLayout()724 void FrameView::updateCompositingLayersAfterLayout()
725 {
726     TRACE_EVENT0("webkit", "FrameView::updateCompositingLayersAfterLayout");
727     RenderView* renderView = this->renderView();
728     if (!renderView)
729         return;
730 
731     // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
732     renderView->compositor()->cacheAcceleratedCompositingFlags();
733     renderView->compositor()->updateCompositingRequirementsState();
734     renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterLayout);
735 }
736 
usesCompositedScrolling() const737 bool FrameView::usesCompositedScrolling() const
738 {
739     RenderView* renderView = this->renderView();
740     if (!renderView)
741         return false;
742     if (m_frame->settings() && m_frame->settings()->compositedScrollingForFramesEnabled())
743         return renderView->compositor()->inForcedCompositingMode();
744     return false;
745 }
746 
layerForScrolling() const747 GraphicsLayer* FrameView::layerForScrolling() const
748 {
749     RenderView* renderView = this->renderView();
750     if (!renderView)
751         return 0;
752     return renderView->compositor()->scrollLayer();
753 }
754 
layerForHorizontalScrollbar() const755 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
756 {
757     RenderView* renderView = this->renderView();
758     if (!renderView)
759         return 0;
760     return renderView->compositor()->layerForHorizontalScrollbar();
761 }
762 
layerForVerticalScrollbar() const763 GraphicsLayer* FrameView::layerForVerticalScrollbar() const
764 {
765     RenderView* renderView = this->renderView();
766     if (!renderView)
767         return 0;
768     return renderView->compositor()->layerForVerticalScrollbar();
769 }
770 
layerForScrollCorner() const771 GraphicsLayer* FrameView::layerForScrollCorner() const
772 {
773     RenderView* renderView = this->renderView();
774     if (!renderView)
775         return 0;
776     return renderView->compositor()->layerForScrollCorner();
777 }
778 
hasCompositedContent() const779 bool FrameView::hasCompositedContent() const
780 {
781     if (RenderView* renderView = this->renderView())
782         return renderView->compositor()->inCompositingMode();
783     return false;
784 }
785 
isEnclosedInCompositingLayer() const786 bool FrameView::isEnclosedInCompositingLayer() const
787 {
788     RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
789     if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
790         return true;
791 
792     if (FrameView* parentView = parentFrameView())
793         return parentView->isEnclosedInCompositingLayer();
794 
795     return false;
796 }
797 
isSoftwareRenderable() const798 bool FrameView::isSoftwareRenderable() const
799 {
800     RenderView* renderView = this->renderView();
801     return !renderView || !renderView->compositor()->has3DContent();
802 }
803 
layoutRoot(bool onlyDuringLayout) const804 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
805 {
806     return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
807 }
808 
collectFrameViewChildren(FrameView * frameView,Vector<RefPtr<FrameView>> & frameViews)809 static inline void collectFrameViewChildren(FrameView* frameView, Vector<RefPtr<FrameView> >& frameViews)
810 {
811     const HashSet<RefPtr<Widget> >* viewChildren = frameView->children();
812     ASSERT(viewChildren);
813 
814     const HashSet<RefPtr<Widget> >::iterator end = viewChildren->end();
815     for (HashSet<RefPtr<Widget> >::iterator current = viewChildren->begin(); current != end; ++current) {
816         Widget* widget = (*current).get();
817         if (widget->isFrameView())
818             frameViews.append(toFrameView(widget));
819     }
820 }
821 
forceLayoutParentViewIfNeeded()822 inline void FrameView::forceLayoutParentViewIfNeeded()
823 {
824     RenderPart* ownerRenderer = m_frame->ownerRenderer();
825     if (!ownerRenderer || !ownerRenderer->frame())
826         return;
827 
828     RenderBox* contentBox = embeddedContentBox();
829     if (!contentBox)
830         return;
831 
832     RenderSVGRoot* svgRoot = toRenderSVGRoot(contentBox);
833     if (svgRoot->everHadLayout() && !svgRoot->needsLayout())
834         return;
835 
836     // If the embedded SVG document appears the first time, the ownerRenderer has already finished
837     // layout without knowing about the existence of the embedded SVG document, because RenderReplaced
838     // embeddedContentBox() returns 0, as long as the embedded document isn't loaded yet. Before
839     // bothering to lay out the SVG document, mark the ownerRenderer needing layout and ask its
840     // FrameView for a layout. After that the RenderEmbeddedObject (ownerRenderer) carries the
841     // correct size, which RenderSVGRoot::computeReplacedLogicalWidth/Height rely on, when laying
842     // out for the first time, or when the RenderSVGRoot size has changed dynamically (eg. via <script>).
843     RefPtr<FrameView> frameView = ownerRenderer->frame()->view();
844 
845     // Mark the owner renderer as needing layout.
846     ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc();
847 
848     // Synchronously enter layout, to layout the view containing the host object/embed/iframe.
849     ASSERT(frameView);
850     frameView->layout();
851 }
852 
performPreLayoutTasks()853 void FrameView::performPreLayoutTasks()
854 {
855     // Don't schedule more layouts, we're in one.
856     TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
857 
858     if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_postLayoutTasksTimer.isActive() && !frame().document()->shouldDisplaySeamlesslyWithParent()) {
859         // This is a new top-level layout. If there are any remaining tasks from the previous layout, finish them now.
860         m_inSynchronousPostLayout = true;
861         performPostLayoutTasks();
862         m_inSynchronousPostLayout = false;
863     }
864 
865     // Viewport-dependent media queries may cause us to need completely different style information.
866     Document* document = m_frame->document();
867     if (!document->styleResolver() || document->styleResolver()->affectedByViewportChange()) {
868         document->styleResolverChanged(RecalcStyleDeferred);
869         document->mediaQueryAffectingValueChanged();
870 
871         // FIXME: This instrumentation event is not strictly accurate since cached media query results
872         //        do not persist across StyleResolver rebuilds.
873         InspectorInstrumentation::mediaQueryResultChanged(document);
874     } else {
875         document->evaluateMediaQueryList();
876     }
877 
878     // If there is any pagination to apply, it will affect the RenderView's style, so we should
879     // take care of that now.
880     applyPaginationToViewport();
881 
882     // Always ensure our style info is up-to-date. This can happen in situations where
883     // the layout beats any sort of style recalc update that needs to occur.
884     TemporaryChange<bool> changeDoingPreLayoutStyleUpdate(m_doingPreLayoutStyleUpdate, true);
885     document->updateStyleIfNeeded();
886 }
887 
performLayout(RenderObject * rootForThisLayout,bool inSubtreeLayout)888 void FrameView::performLayout(RenderObject* rootForThisLayout, bool inSubtreeLayout)
889 {
890     // performLayout is the actual guts of layout().
891     // FIXME: The 300 other lines in layout() probably belong in other helper functions
892     // so that a single human could understand what layout() is actually doing.
893     FrameView::DeferredRepaintScope deferRepaints(*this);
894 
895     {
896         bool disableLayoutState = false;
897         if (inSubtreeLayout) {
898             RenderView* view = rootForThisLayout->view();
899             disableLayoutState = view->shouldDisableLayoutStateForSubtree(rootForThisLayout);
900             view->pushLayoutState(rootForThisLayout);
901         }
902         LayoutStateDisabler layoutStateDisabler(disableLayoutState ? rootForThisLayout->view() : 0);
903 
904         m_inLayout = true;
905 
906         forceLayoutParentViewIfNeeded();
907 
908         // Text Autosizing requires two-pass layout which is incompatible with partial layout.
909         // If enabled, only do partial layout for the second layout.
910         // FIXME (crbug.com/256657): Do not do two layouts for text autosizing.
911         PartialLayoutDisabler partialLayoutDisabler(partialLayout(), m_frame->settings() && m_frame->settings()->textAutosizingEnabled());
912 
913         LayoutIndicator layoutIndicator;
914         rootForThisLayout->layout();
915         gatherDebugLayoutRects(rootForThisLayout);
916 
917         ResourceLoadPriorityOptimizer modifier;
918         rootForThisLayout->didLayout(modifier);
919     }
920 
921     TextAutosizer* textAutosizer = frame().document()->textAutosizer();
922     bool autosized = textAutosizer && textAutosizer->processSubtree(rootForThisLayout);
923     if (autosized && rootForThisLayout->needsLayout()) {
924         TRACE_EVENT0("webkit", "2nd layout due to Text Autosizing");
925         LayoutIndicator layoutIndicator;
926         rootForThisLayout->layout();
927         gatherDebugLayoutRects(rootForThisLayout);
928 
929         ResourceLoadPriorityOptimizer modifier;
930         rootForThisLayout->didLayout(modifier);
931     }
932 
933     m_inLayout = false;
934 
935     if (inSubtreeLayout)
936         rootForThisLayout->view()->popLayoutState(rootForThisLayout);
937 }
938 
scheduleOrPerformPostLayoutTasks()939 void FrameView::scheduleOrPerformPostLayoutTasks()
940 {
941     if (m_postLayoutTasksTimer.isActive())
942         return;
943 
944     // Partial layouts should not happen with synchronous post layouts.
945     ASSERT(!(m_inSynchronousPostLayout && partialLayout().isStopping()));
946 
947     if (!m_inSynchronousPostLayout) {
948         if (frame().document()->shouldDisplaySeamlesslyWithParent()) {
949             if (RenderView* renderView = this->renderView())
950                 renderView->updateWidgetPositions();
951         } else {
952             m_inSynchronousPostLayout = true;
953             // Calls resumeScheduledEvents()
954             performPostLayoutTasks();
955             m_inSynchronousPostLayout = false;
956         }
957     }
958 
959     if (!m_postLayoutTasksTimer.isActive() && (needsLayout() || m_inSynchronousPostLayout || frame().document()->shouldDisplaySeamlesslyWithParent())) {
960         // If we need layout or are already in a synchronous call to postLayoutTasks(),
961         // defer widget updates and event dispatch until after we return. postLayoutTasks()
962         // can make us need to update again, and we can get stuck in a nasty cycle unless
963         // we call it through the timer here.
964         m_postLayoutTasksTimer.startOneShot(0);
965         if (!partialLayout().isStopping() && needsLayout())
966             layout();
967     }
968 }
969 
layout(bool allowSubtree)970 void FrameView::layout(bool allowSubtree)
971 {
972     // We should never layout a Document which is not in a Frame.
973     ASSERT(m_frame);
974     ASSERT(m_frame->view() == this);
975     ASSERT(m_frame->page());
976 
977     if (m_inLayout)
978         return;
979 
980     if (!m_frame->document()->isActive())
981         return;
982 
983     ASSERT(!partialLayout().isStopping());
984 
985     TRACE_EVENT0("webkit", "FrameView::layout");
986     TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "Layout");
987 
988     // Protect the view from being deleted during layout (in recalcStyle)
989     RefPtr<FrameView> protector(this);
990 
991     // Every scroll that happens during layout is programmatic.
992     TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
993 
994     m_layoutTimer.stop();
995     m_delayedLayout = false;
996 
997     // we shouldn't enter layout() while painting
998     ASSERT(!isPainting());
999     if (isPainting())
1000         return;
1001 
1002     // Store the current maximal outline size to use when computing the old/new
1003     // outline rects for repainting.
1004     renderView()->setOldMaximalOutlineSize(renderView()->maximalOutlineSize());
1005 
1006     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
1007 
1008     if (!allowSubtree && m_layoutRoot) {
1009         m_layoutRoot->markContainingBlocksForLayout(false);
1010         m_layoutRoot = 0;
1011     }
1012 
1013     performPreLayoutTasks();
1014 
1015     // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
1016     // so there's no point to continuing to layout
1017     if (protector->hasOneRef())
1018         return;
1019 
1020     Document* document = m_frame->document();
1021     bool inSubtreeLayout = m_layoutRoot;
1022     RenderObject* rootForThisLayout = inSubtreeLayout ? m_layoutRoot : document->renderer();
1023     if (!rootForThisLayout) {
1024         // FIXME: Do we need to set m_size here?
1025         ASSERT_NOT_REACHED();
1026         return;
1027     }
1028 
1029     bool isPartialLayout = partialLayout().isPartialLayout();
1030 
1031     FontCachePurgePreventer fontCachePurgePreventer;
1032     RenderLayer* layer;
1033     {
1034         TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
1035 
1036         m_nestedLayoutCount++;
1037         if (!m_layoutRoot) {
1038             Document* document = m_frame->document();
1039             Node* body = document->body();
1040             if (body && body->renderer()) {
1041                 if (body->hasTagName(framesetTag)) {
1042                     body->renderer()->setChildNeedsLayout();
1043                 } else if (body->hasTagName(bodyTag)) {
1044                     if (!m_firstLayout && m_size.height() != layoutSize().height() && body->renderer()->enclosingBox()->stretchesToViewport())
1045                         body->renderer()->setChildNeedsLayout();
1046                 }
1047             }
1048         }
1049         updateCounters();
1050         autoSizeIfEnabled();
1051 
1052         ScrollbarMode hMode;
1053         ScrollbarMode vMode;
1054         calculateScrollbarModesForLayout(hMode, vMode);
1055 
1056         m_doFullRepaint = !inSubtreeLayout && !isPartialLayout && (m_firstLayout || toRenderView(rootForThisLayout)->document().printing());
1057 
1058         if (!inSubtreeLayout && !isPartialLayout) {
1059             // Now set our scrollbar state for the layout.
1060             ScrollbarMode currentHMode = horizontalScrollbarMode();
1061             ScrollbarMode currentVMode = verticalScrollbarMode();
1062 
1063             if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
1064                 if (m_firstLayout) {
1065                     setScrollbarsSuppressed(true);
1066 
1067                     m_firstLayout = false;
1068                     m_firstLayoutCallbackPending = true;
1069                     m_lastViewportSize = layoutSize(IncludeScrollbars);
1070                     m_lastZoomFactor = rootForThisLayout->style()->zoom();
1071 
1072                     // Set the initial vMode to AlwaysOn if we're auto.
1073                     if (vMode == ScrollbarAuto)
1074                         setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
1075                     // Set the initial hMode to AlwaysOff if we're auto.
1076                     if (hMode == ScrollbarAuto)
1077                         setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
1078 
1079                     setScrollbarModes(hMode, vMode);
1080                     setScrollbarsSuppressed(false, true);
1081                 } else
1082                     setScrollbarModes(hMode, vMode);
1083             }
1084 
1085             LayoutSize oldSize = m_size;
1086 
1087             m_size = LayoutSize(layoutSize().width(), layoutSize().height());
1088 
1089             if (oldSize != m_size) {
1090                 m_doFullRepaint = true;
1091                 if (!m_firstLayout) {
1092                     RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
1093                     RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
1094                     if (bodyRenderer && bodyRenderer->stretchesToViewport())
1095                         bodyRenderer->setChildNeedsLayout();
1096                     else if (rootRenderer && rootRenderer->stretchesToViewport())
1097                         rootRenderer->setChildNeedsLayout();
1098                 }
1099             }
1100         }
1101 
1102         layer = rootForThisLayout->enclosingLayer();
1103 
1104         performLayout(rootForThisLayout, inSubtreeLayout);
1105 
1106         m_layoutRoot = 0;
1107     } // Reset m_layoutSchedulingEnabled to its previous value.
1108 
1109     bool neededFullRepaint = m_doFullRepaint;
1110 
1111     if (!inSubtreeLayout && !isPartialLayout && !toRenderView(rootForThisLayout)->document().printing())
1112         adjustViewSize();
1113 
1114     m_doFullRepaint = neededFullRepaint;
1115 
1116     {
1117         // FIXME: Can this scope just encompass this entire function?
1118         FrameView::DeferredRepaintScope deferRepaints(*this);
1119 
1120         if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) {
1121             if (m_doFullRepaint)
1122                 renderView()->setShouldDoFullRepaintAfterLayout(true);
1123 
1124             if (m_doFullRepaint || !partialLayout().isStopping())
1125                 repaintTree(rootForThisLayout);
1126 
1127         } else if (m_doFullRepaint) {
1128             // FIXME: This isn't really right, since the RenderView doesn't fully encompass
1129             // the visibleContentRect(). It just happens to work out most of the time,
1130             // since first layouts and printing don't have you scrolled anywhere.
1131             renderView()->repaint();
1132         }
1133         layer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPositionFlags(layer, inSubtreeLayout, m_doFullRepaint));
1134     }
1135     updateCompositingLayersAfterLayout();
1136 
1137     m_layoutCount++;
1138 
1139     if (AXObjectCache* cache = rootForThisLayout->document().existingAXObjectCache())
1140         cache->postNotification(rootForThisLayout, AXObjectCache::AXLayoutComplete, true);
1141     updateAnnotatedRegions();
1142 
1143     ASSERT(partialLayout().isStopping() || !rootForThisLayout->needsLayout());
1144 
1145     updateCanBlitOnScrollRecursively();
1146 
1147     if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1148         updateOverflowStatus(layoutSize().width() < contentsWidth(), layoutSize().height() < contentsHeight());
1149 
1150     scheduleOrPerformPostLayoutTasks();
1151 
1152     InspectorInstrumentation::didLayout(cookie, rootForThisLayout);
1153 
1154     m_nestedLayoutCount--;
1155     if (m_nestedLayoutCount)
1156         return;
1157 
1158     if (partialLayout().isStopping())
1159         return;
1160 
1161 #ifndef NDEBUG
1162     // Post-layout assert that nobody was re-marked as needing layout during layout.
1163     document->renderer()->assertSubtreeIsLaidOut();
1164 #endif
1165 
1166     // FIXME: It should be not possible to remove the FrameView from the frame/page during layout
1167     // however m_inLayout is not set for most of this function, so none of our RELEASE_ASSERTS
1168     // in Frame/Page will fire. One of the post-layout tasks is disconnecting the Frame from
1169     // the page in fast/frames/crash-remove-iframe-during-object-beforeload-2.html
1170     // necessitating this check here.
1171     // ASSERT(frame()->page());
1172     if (frame().page())
1173         frame().page()->chrome().client().layoutUpdated(m_frame.get());
1174 }
1175 
1176 // The plan is to move to compositor-queried repainting, in which case this
1177 // method would setNeedsRedraw on the GraphicsLayers with invalidations and
1178 // let the compositor pick which to actually draw.
1179 // See http://crbug.com/306706
repaintTree(RenderObject * root)1180 void FrameView::repaintTree(RenderObject* root)
1181 {
1182     ASSERT(RuntimeEnabledFeatures::repaintAfterLayoutEnabled());
1183     ASSERT(!root->needsLayout());
1184 
1185     for (RenderObject* renderer = root; renderer; renderer = renderer->nextInPreOrder()) {
1186         const LayoutRect& oldRepaintRect = renderer->oldRepaintRect();
1187         const LayoutRect& newRepaintRect = renderer->newRepaintRect();
1188 
1189         LayoutRect oldOutlineRect = oldRepaintRect;
1190         oldOutlineRect.inflate(renderView()->oldMaximalOutlineSize());
1191 
1192         LayoutRect newOutlineRect = newRepaintRect;
1193         newOutlineRect.inflate(renderView()->maximalOutlineSize());
1194 
1195         // FIXME: Currently renderers with layers will get repainted when we call updateLayerPositionsAfterLayout.
1196         // That call should be broken apart to position the layers be done before
1197         // the repaintTree call so this will repaint everything.
1198         bool didFullRepaint = false;
1199         if (!renderer->hasLayer()) {
1200             if (!renderer->layoutDidGetCalled()) {
1201                 if (renderer->shouldDoFullRepaintAfterLayout()) {
1202                     renderer->repaint();
1203                     didFullRepaint = true;
1204                 }
1205 
1206             } else {
1207                 didFullRepaint = renderer->repaintAfterLayoutIfNeeded(renderer->containerForRepaint(), renderer->shouldDoFullRepaintAfterLayout(),
1208                     oldRepaintRect, oldOutlineRect, &newRepaintRect, &newOutlineRect);
1209             }
1210         }
1211         if (!didFullRepaint && renderer->shouldRepaintOverflowIfNeeded())
1212             renderer->repaintOverflow();
1213         renderer->clearRepaintRects();
1214     }
1215     renderView()->setOldMaximalOutlineSize(0);
1216 }
1217 
gatherDebugLayoutRects(RenderObject * layoutRoot)1218 void FrameView::gatherDebugLayoutRects(RenderObject* layoutRoot)
1219 {
1220     bool isTracing;
1221     TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("blink.debug.layout"), &isTracing);
1222     if (!isTracing)
1223         return;
1224     if (!layoutRoot->enclosingLayer()->hasCompositedLayerMapping())
1225         return;
1226     GraphicsLayer* graphicsLayer = layoutRoot->enclosingLayer()->compositedLayerMapping()->mainGraphicsLayer();
1227     if (!graphicsLayer)
1228         return;
1229 
1230     GraphicsLayerDebugInfo* debugInfo = new GraphicsLayerDebugInfo();
1231     for (RenderObject* renderer = layoutRoot; renderer; renderer = renderer->nextInPreOrder()) {
1232         if (renderer->layoutDidGetCalled()) {
1233             LayoutRect rect = renderer->newRepaintRect();
1234             debugInfo->m_currentLayoutRects.append(rect);
1235             renderer->setLayoutDidGetCalled(false);
1236         }
1237     }
1238 
1239     graphicsLayer->setDebugInfo(debugInfo);
1240 }
1241 
1242 
embeddedContentBox() const1243 RenderBox* FrameView::embeddedContentBox() const
1244 {
1245     RenderView* renderView = this->renderView();
1246     if (!renderView)
1247         return 0;
1248 
1249     RenderObject* firstChild = renderView->firstChild();
1250     if (!firstChild || !firstChild->isBox())
1251         return 0;
1252 
1253     // Curently only embedded SVG documents participate in the size-negotiation logic.
1254     if (firstChild->isSVGRoot())
1255         return toRenderBox(firstChild);
1256 
1257     return 0;
1258 }
1259 
addWidgetToUpdate(RenderEmbeddedObject & object)1260 void FrameView::addWidgetToUpdate(RenderEmbeddedObject& object)
1261 {
1262     // Tell the DOM element that it needs a widget update.
1263     Node* node = object.node();
1264     if (node->hasTagName(objectTag) || node->hasTagName(embedTag))
1265         toHTMLPlugInElement(node)->setNeedsWidgetUpdate(true);
1266 
1267     m_widgetUpdateSet.add(&object);
1268 }
1269 
setMediaType(const AtomicString & mediaType)1270 void FrameView::setMediaType(const AtomicString& mediaType)
1271 {
1272     ASSERT(m_frame->document());
1273     m_frame->document()->mediaQueryAffectingValueChanged();
1274     m_mediaType = mediaType;
1275 }
1276 
mediaType() const1277 AtomicString FrameView::mediaType() const
1278 {
1279     // See if we have an override type.
1280     String overrideType;
1281     InspectorInstrumentation::applyEmulatedMedia(m_frame.get(), &overrideType);
1282     if (!overrideType.isNull())
1283         return overrideType;
1284     return m_mediaType;
1285 }
1286 
adjustMediaTypeForPrinting(bool printing)1287 void FrameView::adjustMediaTypeForPrinting(bool printing)
1288 {
1289     if (printing) {
1290         if (m_mediaTypeWhenNotPrinting.isNull())
1291             m_mediaTypeWhenNotPrinting = mediaType();
1292             setMediaType("print");
1293     } else {
1294         if (!m_mediaTypeWhenNotPrinting.isNull())
1295             setMediaType(m_mediaTypeWhenNotPrinting);
1296         m_mediaTypeWhenNotPrinting = nullAtom;
1297     }
1298 }
1299 
useSlowRepaints(bool considerOverlap) const1300 bool FrameView::useSlowRepaints(bool considerOverlap) const
1301 {
1302     bool mustBeSlow = m_slowRepaintObjectCount > 0;
1303 
1304     if (contentsInCompositedLayer())
1305         return mustBeSlow;
1306 
1307     // The chromium compositor does not support scrolling a non-composited frame within a composited page through
1308     // the fast scrolling path, so force slow scrolling in that case.
1309     if (m_frame->ownerElement() && !hasCompositedContent() && m_frame->page() && m_frame->page()->mainFrame()->view()->hasCompositedContent())
1310         return true;
1311 
1312     bool isOverlapped = m_isOverlapped && considerOverlap;
1313 
1314     if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque)
1315         return true;
1316 
1317     if (FrameView* parentView = parentFrameView())
1318         return parentView->useSlowRepaints(considerOverlap);
1319 
1320     return false;
1321 }
1322 
useSlowRepaintsIfNotOverlapped() const1323 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1324 {
1325     return useSlowRepaints(false);
1326 }
1327 
updateCanBlitOnScrollRecursively()1328 void FrameView::updateCanBlitOnScrollRecursively()
1329 {
1330     for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) {
1331         if (FrameView* view = frame->view())
1332             view->setCanBlitOnScroll(!view->useSlowRepaints());
1333     }
1334 }
1335 
contentsInCompositedLayer() const1336 bool FrameView::contentsInCompositedLayer() const
1337 {
1338     RenderView* renderView = this->renderView();
1339     if (renderView && renderView->compositingState() == PaintsIntoOwnBacking) {
1340         GraphicsLayer* layer = renderView->layer()->compositedLayerMapping()->mainGraphicsLayer();
1341         if (layer && layer->drawsContent())
1342             return true;
1343     }
1344 
1345     return false;
1346 }
1347 
setCannotBlitToWindow()1348 void FrameView::setCannotBlitToWindow()
1349 {
1350     m_cannotBlitToWindow = true;
1351     updateCanBlitOnScrollRecursively();
1352 }
1353 
addSlowRepaintObject()1354 void FrameView::addSlowRepaintObject()
1355 {
1356     if (!m_slowRepaintObjectCount++) {
1357         updateCanBlitOnScrollRecursively();
1358 
1359         if (Page* page = m_frame->page()) {
1360             if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1361                 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1362         }
1363     }
1364 }
1365 
removeSlowRepaintObject()1366 void FrameView::removeSlowRepaintObject()
1367 {
1368     ASSERT(m_slowRepaintObjectCount > 0);
1369     m_slowRepaintObjectCount--;
1370     if (!m_slowRepaintObjectCount) {
1371         updateCanBlitOnScrollRecursively();
1372 
1373         if (Page* page = m_frame->page()) {
1374             if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1375                 scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1376         }
1377     }
1378 }
1379 
addViewportConstrainedObject(RenderObject * object)1380 void FrameView::addViewportConstrainedObject(RenderObject* object)
1381 {
1382     if (!m_viewportConstrainedObjects)
1383         m_viewportConstrainedObjects = adoptPtr(new ViewportConstrainedObjectSet);
1384 
1385     if (!m_viewportConstrainedObjects->contains(object)) {
1386         m_viewportConstrainedObjects->add(object);
1387 
1388         if (Page* page = m_frame->page()) {
1389             if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1390                 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1391         }
1392     }
1393 }
1394 
removeViewportConstrainedObject(RenderObject * object)1395 void FrameView::removeViewportConstrainedObject(RenderObject* object)
1396 {
1397     if (m_viewportConstrainedObjects && m_viewportConstrainedObjects->contains(object)) {
1398         m_viewportConstrainedObjects->remove(object);
1399         if (Page* page = m_frame->page()) {
1400             if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1401                 scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1402         }
1403 
1404         // FIXME: In addFixedObject() we only call this if there's a platform widget,
1405         // why isn't the same check being made here?
1406         updateCanBlitOnScrollRecursively();
1407     }
1408 }
1409 
viewportConstrainedVisibleContentRect() const1410 LayoutRect FrameView::viewportConstrainedVisibleContentRect() const
1411 {
1412     LayoutRect viewportRect = visibleContentRect();
1413     // Ignore overhang. No-op when not using rubber banding.
1414     viewportRect.setLocation(clampScrollPosition(scrollPosition()));
1415     return viewportRect;
1416 }
1417 
1418 
scrollOffsetForFixedPosition() const1419 IntSize FrameView::scrollOffsetForFixedPosition() const
1420 {
1421     return toIntSize(clampScrollPosition(scrollPosition()));
1422 }
1423 
lastKnownMousePosition() const1424 IntPoint FrameView::lastKnownMousePosition() const
1425 {
1426     return m_frame->eventHandler().lastKnownMousePosition();
1427 }
1428 
shouldSetCursor() const1429 bool FrameView::shouldSetCursor() const
1430 {
1431     Page* page = frame().page();
1432     return page && page->visibilityState() != PageVisibilityStateHidden && page->focusController().isActive();
1433 }
1434 
scrollContentsFastPath(const IntSize & scrollDelta,const IntRect & rectToScroll,const IntRect & clipRect)1435 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1436 {
1437     if (!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty()) {
1438         hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1439         return true;
1440     }
1441 
1442     const bool isCompositedContentLayer = contentsInCompositedLayer();
1443 
1444     // Get the rects of the fixed objects visible in the rectToScroll
1445     Region regionToUpdate;
1446     ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end();
1447     for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) {
1448         RenderObject* renderer = *it;
1449         if (!renderer->style()->hasViewportConstrainedPosition())
1450             continue;
1451 
1452         // Fixed items should always have layers.
1453         ASSERT(renderer->hasLayer());
1454         RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
1455 
1456         // Layers that paint into their ancestor or into a grouped backing will still need
1457         // to apply a repaint invalidation. If the layer paints into its own backing, then
1458         // it does not need repainting just to scroll.
1459         if (layer->compositingState() == PaintsIntoOwnBacking)
1460             continue;
1461 
1462         if (layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForBoundsOutOfView
1463             || layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForNoVisibleContent) {
1464             // Don't invalidate for invisible fixed layers.
1465             continue;
1466         }
1467 
1468         if (layer->hasAncestorWithFilterOutsets()) {
1469             // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot
1470             // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
1471             return false;
1472         }
1473 
1474         IntRect updateRect = pixelSnappedIntRect(layer->repainter().repaintRectIncludingNonCompositingDescendants());
1475 
1476         RenderLayer* enclosingCompositingLayer = layer->enclosingCompositingLayer(false);
1477         if (enclosingCompositingLayer && !enclosingCompositingLayer->renderer()->isRenderView()) {
1478             // If the fixed-position layer is contained by a composited layer that is not its containing block,
1479             // then we have to invlidate that enclosing layer, not the RenderView.
1480             updateRect.moveBy(scrollPosition());
1481             IntRect previousRect = updateRect;
1482             previousRect.move(scrollDelta);
1483             updateRect.unite(previousRect);
1484             enclosingCompositingLayer->repainter().setBackingNeedsRepaintInRect(updateRect);
1485         } else {
1486             // Coalesce the repaints that will be issued to the renderView.
1487             updateRect = contentsToRootView(updateRect);
1488             if (!isCompositedContentLayer && clipsRepaints())
1489                 updateRect.intersect(rectToScroll);
1490             if (!updateRect.isEmpty())
1491                 regionToUpdate.unite(updateRect);
1492         }
1493     }
1494 
1495     // 1) scroll
1496     hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1497 
1498     // 2) update the area of fixed objects that has been invalidated
1499     Vector<IntRect> subRectsToUpdate = regionToUpdate.rects();
1500     size_t viewportConstrainedObjectsCount = subRectsToUpdate.size();
1501     for (size_t i = 0; i < viewportConstrainedObjectsCount; ++i) {
1502         IntRect updateRect = subRectsToUpdate[i];
1503         IntRect scrolledRect = updateRect;
1504         scrolledRect.move(scrollDelta);
1505         updateRect.unite(scrolledRect);
1506         if (isCompositedContentLayer) {
1507             updateRect = rootViewToContents(updateRect);
1508             ASSERT(renderView());
1509             renderView()->layer()->repainter().setBackingNeedsRepaintInRect(updateRect);
1510             continue;
1511         }
1512         if (clipsRepaints())
1513             updateRect.intersect(rectToScroll);
1514         hostWindow()->invalidateContentsAndRootView(updateRect);
1515     }
1516 
1517     return true;
1518 }
1519 
scrollContentsSlowPath(const IntRect & updateRect)1520 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1521 {
1522     if (contentsInCompositedLayer()) {
1523         IntRect updateRect = visibleContentRect();
1524         ASSERT(renderView());
1525         renderView()->layer()->repainter().setBackingNeedsRepaintInRect(updateRect);
1526     }
1527     if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1528         if (isEnclosedInCompositingLayer()) {
1529             LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1530                             frameRenderer->borderTop() + frameRenderer->paddingTop(),
1531                             visibleWidth(), visibleHeight());
1532             frameRenderer->repaintRectangle(rect);
1533             return;
1534         }
1535     }
1536 
1537     ScrollView::scrollContentsSlowPath(updateRect);
1538 }
1539 
1540 // Note that this gets called at painting time.
setIsOverlapped(bool isOverlapped)1541 void FrameView::setIsOverlapped(bool isOverlapped)
1542 {
1543     if (isOverlapped == m_isOverlapped)
1544         return;
1545 
1546     m_isOverlapped = isOverlapped;
1547     updateCanBlitOnScrollRecursively();
1548 }
1549 
isOverlappedIncludingAncestors() const1550 bool FrameView::isOverlappedIncludingAncestors() const
1551 {
1552     if (isOverlapped())
1553         return true;
1554 
1555     if (FrameView* parentView = parentFrameView()) {
1556         if (parentView->isOverlapped())
1557             return true;
1558     }
1559 
1560     return false;
1561 }
1562 
setContentIsOpaque(bool contentIsOpaque)1563 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1564 {
1565     if (contentIsOpaque == m_contentIsOpaque)
1566         return;
1567 
1568     m_contentIsOpaque = contentIsOpaque;
1569     updateCanBlitOnScrollRecursively();
1570 }
1571 
restoreScrollbar()1572 void FrameView::restoreScrollbar()
1573 {
1574     setScrollbarsSuppressed(false);
1575 }
1576 
scrollToFragment(const KURL & url)1577 bool FrameView::scrollToFragment(const KURL& url)
1578 {
1579     // If our URL has no ref, then we have no place we need to jump to.
1580     // OTOH If CSS target was set previously, we want to set it to 0, recalc
1581     // and possibly repaint because :target pseudo class may have been
1582     // set (see bug 11321).
1583     if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1584         return false;
1585 
1586     String fragmentIdentifier = url.fragmentIdentifier();
1587     if (scrollToAnchor(fragmentIdentifier))
1588         return true;
1589 
1590     // Try again after decoding the ref, based on the document's encoding.
1591     if (m_frame->document()->encoding().isValid())
1592         return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, m_frame->document()->encoding()));
1593 
1594     return false;
1595 }
1596 
scrollToAnchor(const String & name)1597 bool FrameView::scrollToAnchor(const String& name)
1598 {
1599     ASSERT(m_frame->document());
1600 
1601     if (!m_frame->document()->haveStylesheetsLoaded()) {
1602         m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1603         return false;
1604     }
1605 
1606     m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1607 
1608     Element* anchorNode = m_frame->document()->findAnchor(name);
1609 
1610     // Setting to null will clear the current target.
1611     m_frame->document()->setCSSTarget(anchorNode);
1612 
1613     if (m_frame->document()->isSVGDocument()) {
1614         if (SVGSVGElement* svg = toSVGDocument(m_frame->document())->rootElement()) {
1615             svg->setupInitialView(name, anchorNode);
1616             if (!anchorNode)
1617                 return true;
1618         }
1619     }
1620 
1621     // Implement the rule that "" and "top" both mean top of page as in other browsers.
1622     if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1623         return false;
1624 
1625     maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1626 
1627     // If the anchor accepts keyboard focus, move focus there to aid users relying on keyboard navigation.
1628     if (anchorNode && anchorNode->isFocusable())
1629         m_frame->document()->setFocusedElement(anchorNode);
1630 
1631     return true;
1632 }
1633 
maintainScrollPositionAtAnchor(Node * anchorNode)1634 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1635 {
1636     m_maintainScrollPositionAnchor = anchorNode;
1637     if (!m_maintainScrollPositionAnchor)
1638         return;
1639 
1640     // We need to update the layout before scrolling, otherwise we could
1641     // really mess things up if an anchor scroll comes at a bad moment.
1642     m_frame->document()->updateStyleIfNeeded();
1643     // Only do a layout if changes have occurred that make it necessary.
1644     RenderView* renderView = this->renderView();
1645     if (renderView && renderView->needsLayout())
1646         layout();
1647     else
1648         scrollToAnchor();
1649 }
1650 
scrollElementToRect(Element * element,const IntRect & rect)1651 void FrameView::scrollElementToRect(Element* element, const IntRect& rect)
1652 {
1653     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1654 
1655     LayoutRect bounds = element->boundingBox();
1656     int centeringOffsetX = (rect.width() - bounds.width()) / 2;
1657     int centeringOffsetY = (rect.height() - bounds.height()) / 2;
1658     setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y()));
1659 }
1660 
setScrollPosition(const IntPoint & scrollPoint)1661 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1662 {
1663     TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1664     m_maintainScrollPositionAnchor = 0;
1665 
1666     IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint);
1667 
1668     if (newScrollPosition == scrollPosition())
1669         return;
1670 
1671     ScrollView::setScrollPosition(newScrollPosition);
1672 }
1673 
setScrollPositionNonProgrammatically(const IntPoint & scrollPoint)1674 void FrameView::setScrollPositionNonProgrammatically(const IntPoint& scrollPoint)
1675 {
1676     IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint);
1677 
1678     if (newScrollPosition == scrollPosition())
1679         return;
1680 
1681     TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, false);
1682     notifyScrollPositionChanged(newScrollPosition);
1683 }
1684 
setViewportConstrainedObjectsNeedLayout()1685 void FrameView::setViewportConstrainedObjectsNeedLayout()
1686 {
1687     if (!hasViewportConstrainedObjects())
1688         return;
1689 
1690     ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end();
1691     for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) {
1692         RenderObject* renderer = *it;
1693         renderer->setNeedsLayout();
1694     }
1695 }
1696 
layoutSize(IncludeScrollbarsInRect scrollbarInclusion) const1697 IntSize FrameView::layoutSize(IncludeScrollbarsInRect scrollbarInclusion) const
1698 {
1699     return scrollbarInclusion == ExcludeScrollbars ? excludeScrollbars(m_layoutSize) : m_layoutSize;
1700 }
1701 
setLayoutSize(const IntSize & size)1702 void FrameView::setLayoutSize(const IntSize& size)
1703 {
1704     ASSERT(!layoutSizeFixedToFrameSize());
1705 
1706     setLayoutSizeInternal(size);
1707 }
1708 
scrollPositionChanged()1709 void FrameView::scrollPositionChanged()
1710 {
1711     setWasScrolledByUser(true);
1712 
1713     Document* document = m_frame->document();
1714     document->enqueueScrollEventForNode(document);
1715 
1716     m_frame->eventHandler().dispatchFakeMouseMoveEventSoon();
1717 
1718     if (RenderView* renderView = document->renderView()) {
1719         if (renderView->usesCompositing())
1720             renderView->compositor()->frameViewDidScroll();
1721     }
1722 
1723     if (m_frame->document() && m_frame->document()->renderer()) {
1724         ResourceLoadPriorityOptimizer modifier;
1725         m_frame->document()->renderer()->didScroll(modifier);
1726     }
1727 }
1728 
repaintFixedElementsAfterScrolling()1729 void FrameView::repaintFixedElementsAfterScrolling()
1730 {
1731     // For fixed position elements, update widget positions and compositing layers after scrolling,
1732     // but only if we're not inside of layout.
1733     if (!m_nestedLayoutCount && hasViewportConstrainedObjects()) {
1734         if (RenderView* renderView = this->renderView()) {
1735             renderView->updateWidgetPositions();
1736             renderView->layer()->updateLayerPositionsAfterDocumentScroll();
1737         }
1738     }
1739 }
1740 
updateFixedElementsAfterScrolling()1741 void FrameView::updateFixedElementsAfterScrolling()
1742 {
1743     if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) {
1744         if (RenderView* renderView = this->renderView())
1745             renderView->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
1746     }
1747 }
1748 
shouldRubberBandInDirection(ScrollDirection direction) const1749 bool FrameView::shouldRubberBandInDirection(ScrollDirection direction) const
1750 {
1751     Page* page = frame().page();
1752     if (!page)
1753         return ScrollView::shouldRubberBandInDirection(direction);
1754     return page->chrome().client().shouldRubberBandInDirection(direction);
1755 }
1756 
isRubberBandInProgress() const1757 bool FrameView::isRubberBandInProgress() const
1758 {
1759     if (scrollbarsSuppressed())
1760         return false;
1761 
1762     // If the main thread updates the scroll position for this FrameView, we should return
1763     // ScrollAnimator::isRubberBandInProgress().
1764     if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
1765         return scrollAnimator->isRubberBandInProgress();
1766 
1767     return false;
1768 }
1769 
hostWindow() const1770 HostWindow* FrameView::hostWindow() const
1771 {
1772     Page* page = frame().page();
1773     if (!page)
1774         return 0;
1775     return &page->chrome();
1776 }
1777 
1778 const unsigned cRepaintRectUnionThreshold = 25;
1779 
repaintContentRectangle(const IntRect & r)1780 void FrameView::repaintContentRectangle(const IntRect& r)
1781 {
1782     ASSERT(!m_frame->ownerElement());
1783 
1784     if (m_isTrackingRepaints) {
1785         IntRect repaintRect = r;
1786         repaintRect.move(-scrollOffset());
1787         m_trackedRepaintRects.append(repaintRect);
1788     }
1789 
1790     double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay();
1791     if (m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) {
1792         IntRect paintRect = r;
1793         if (clipsRepaints() && !paintsEntireContents())
1794             paintRect.intersect(visibleContentRect());
1795         if (paintRect.isEmpty())
1796             return;
1797         if (m_repaintCount == cRepaintRectUnionThreshold) {
1798             IntRect unionedRect;
1799             for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
1800                 unionedRect.unite(pixelSnappedIntRect(m_repaintRects[i]));
1801             m_repaintRects.clear();
1802             m_repaintRects.append(unionedRect);
1803         }
1804         if (m_repaintCount < cRepaintRectUnionThreshold)
1805             m_repaintRects.append(paintRect);
1806         else
1807             m_repaintRects[0].unite(paintRect);
1808         m_repaintCount++;
1809 
1810         if (!m_deferringRepaints)
1811             startDeferredRepaintTimer(delay);
1812 
1813         return;
1814     }
1815 
1816     if (!shouldUpdate())
1817         return;
1818 
1819     ScrollView::repaintContentRectangle(r);
1820 }
1821 
contentsResized()1822 void FrameView::contentsResized()
1823 {
1824     ScrollView::contentsResized();
1825     setNeedsLayout();
1826 }
1827 
scrollbarExistenceDidChange()1828 void FrameView::scrollbarExistenceDidChange()
1829 {
1830     // We check to make sure the view is attached to a frame() as this method can
1831     // be triggered before the view is attached by Frame::createView(...) setting
1832     // various values such as setScrollBarModes(...) for example.  An ASSERT is
1833     // triggered when a view is layout before being attached to a frame().
1834     if (!frame().view())
1835         return;
1836 
1837     // Note that simply having overlay scrollbars is not sufficient to be
1838     // certain that scrollbars' presence does not impact layout. This should
1839     // also check if custom scrollbars (as reported by shouldUseCustomScrollbars)
1840     // are in use as well.
1841     // http://crbug.com/269692
1842     bool useOverlayScrollbars = ScrollbarTheme::theme()->usesOverlayScrollbars();
1843 
1844     if (!useOverlayScrollbars && needsLayout())
1845         layout();
1846 
1847     if (renderView() && renderView()->usesCompositing()) {
1848         renderView()->compositor()->frameViewScrollbarsExistenceDidChange();
1849 
1850         if (!useOverlayScrollbars)
1851             renderView()->compositor()->frameViewDidChangeSize();
1852     }
1853 }
1854 
beginDeferredRepaints()1855 void FrameView::beginDeferredRepaints()
1856 {
1857     Page* page = m_frame->page();
1858     ASSERT(page);
1859 
1860     if (!isMainFrame()) {
1861         page->mainFrame()->view()->beginDeferredRepaints();
1862         return;
1863     }
1864 
1865     m_deferringRepaints++;
1866 }
1867 
endDeferredRepaints()1868 void FrameView::endDeferredRepaints()
1869 {
1870     Page* page = m_frame->page();
1871     ASSERT(page);
1872 
1873     if (!isMainFrame()) {
1874         page->mainFrame()->view()->endDeferredRepaints();
1875         return;
1876     }
1877 
1878     ASSERT(m_deferringRepaints > 0);
1879 
1880     if (--m_deferringRepaints)
1881         return;
1882 
1883     if (m_deferredRepaintTimer.isActive())
1884         return;
1885 
1886     if (double delay = adjustedDeferredRepaintDelay()) {
1887         startDeferredRepaintTimer(delay);
1888         return;
1889     }
1890 
1891     doDeferredRepaints();
1892 }
1893 
startDeferredRepaintTimer(double delay)1894 void FrameView::startDeferredRepaintTimer(double delay)
1895 {
1896     if (m_deferredRepaintTimer.isActive())
1897         return;
1898 
1899     m_deferredRepaintTimer.startOneShot(delay);
1900 }
1901 
handleLoadCompleted()1902 void FrameView::handleLoadCompleted()
1903 {
1904     // Once loading has completed, allow autoSize one last opportunity to
1905     // reduce the size of the frame.
1906     autoSizeIfEnabled();
1907     if (shouldUseLoadTimeDeferredRepaintDelay())
1908         return;
1909     m_deferredRepaintDelay = s_normalDeferredRepaintDelay;
1910     flushDeferredRepaints();
1911 }
1912 
flushDeferredRepaints()1913 void FrameView::flushDeferredRepaints()
1914 {
1915     if (!m_deferredRepaintTimer.isActive())
1916         return;
1917     m_deferredRepaintTimer.stop();
1918     doDeferredRepaints();
1919 }
1920 
doDeferredRepaints()1921 void FrameView::doDeferredRepaints()
1922 {
1923     ASSERT(!m_deferringRepaints);
1924     if (!shouldUpdate()) {
1925         m_repaintRects.clear();
1926         m_repaintCount = 0;
1927         return;
1928     }
1929     unsigned size = m_repaintRects.size();
1930     for (unsigned i = 0; i < size; i++) {
1931         ScrollView::repaintContentRectangle(pixelSnappedIntRect(m_repaintRects[i]));
1932     }
1933     m_repaintRects.clear();
1934     m_repaintCount = 0;
1935 
1936     updateDeferredRepaintDelayAfterRepaint();
1937 }
1938 
shouldUseLoadTimeDeferredRepaintDelay() const1939 bool FrameView::shouldUseLoadTimeDeferredRepaintDelay() const
1940 {
1941     // Don't defer after the initial load of the page has been completed.
1942     if (m_frame->tree().top()->document()->loadEventFinished())
1943         return false;
1944     Document* document = m_frame->document();
1945     if (!document)
1946         return false;
1947     if (document->parsing())
1948         return true;
1949     if (document->fetcher()->requestCount())
1950         return true;
1951     return false;
1952 }
1953 
updateDeferredRepaintDelayAfterRepaint()1954 void FrameView::updateDeferredRepaintDelayAfterRepaint()
1955 {
1956     if (!shouldUseLoadTimeDeferredRepaintDelay()) {
1957         m_deferredRepaintDelay = s_normalDeferredRepaintDelay;
1958         return;
1959     }
1960     double incrementedRepaintDelay = m_deferredRepaintDelay + s_deferredRepaintDelayIncrementDuringLoading;
1961     m_deferredRepaintDelay = std::min(incrementedRepaintDelay, s_maxDeferredRepaintDelayDuringLoading);
1962 }
1963 
resetDeferredRepaintDelay()1964 void FrameView::resetDeferredRepaintDelay()
1965 {
1966     m_deferredRepaintDelay = 0;
1967     if (m_deferredRepaintTimer.isActive()) {
1968         m_deferredRepaintTimer.stop();
1969         if (!m_deferringRepaints)
1970             doDeferredRepaints();
1971     }
1972 }
1973 
adjustedDeferredRepaintDelay() const1974 double FrameView::adjustedDeferredRepaintDelay() const
1975 {
1976     ASSERT(!m_deferringRepaints);
1977     if (!m_deferredRepaintDelay)
1978         return 0;
1979     double timeSinceLastPaint = currentTime() - m_lastPaintTime;
1980     return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
1981 }
1982 
deferredRepaintTimerFired(Timer<FrameView> *)1983 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
1984 {
1985     doDeferredRepaints();
1986 }
1987 
layoutTimerFired(Timer<FrameView> *)1988 void FrameView::layoutTimerFired(Timer<FrameView>*)
1989 {
1990     layout();
1991 }
1992 
scheduleRelayout()1993 void FrameView::scheduleRelayout()
1994 {
1995     ASSERT(m_frame->view() == this);
1996 
1997     if (m_layoutRoot) {
1998         m_layoutRoot->markContainingBlocksForLayout(false);
1999         m_layoutRoot = 0;
2000     }
2001     if (!m_layoutSchedulingEnabled)
2002         return;
2003     if (!needsLayout())
2004         return;
2005     if (!m_frame->document()->shouldScheduleLayout())
2006         return;
2007     InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2008 
2009     // When frame seamless is enabled, the contents of the frame could affect the layout of the parent frames.
2010     // Also invalidate parent frame starting from the owner element of this frame.
2011     if (m_frame->ownerRenderer() && m_frame->document()->shouldDisplaySeamlesslyWithParent())
2012         m_frame->ownerRenderer()->setNeedsLayout();
2013 
2014     int delay = m_frame->document()->minimumLayoutDelay();
2015     if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
2016         unscheduleRelayout();
2017     if (m_layoutTimer.isActive())
2018         return;
2019 
2020     m_delayedLayout = delay != 0;
2021     m_layoutTimer.startOneShot(delay * 0.001);
2022 }
2023 
isObjectAncestorContainerOf(RenderObject * ancestor,RenderObject * descendant)2024 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
2025 {
2026     for (RenderObject* r = descendant; r; r = r->container()) {
2027         if (r == ancestor)
2028             return true;
2029     }
2030     return false;
2031 }
2032 
scheduleRelayoutOfSubtree(RenderObject * relayoutRoot)2033 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
2034 {
2035     ASSERT(m_frame->view() == this);
2036 
2037     RenderView* renderView = this->renderView();
2038     if (renderView && renderView->needsLayout()) {
2039         if (relayoutRoot)
2040             relayoutRoot->markContainingBlocksForLayout(false);
2041         return;
2042     }
2043 
2044     if (layoutPending() || !m_layoutSchedulingEnabled) {
2045         if (m_layoutRoot != relayoutRoot) {
2046             if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
2047                 // Keep the current root
2048                 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
2049                 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2050             } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
2051                 // Re-root at relayoutRoot
2052                 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
2053                 m_layoutRoot = relayoutRoot;
2054                 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2055                 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2056             } else {
2057                 // Just do a full relayout
2058                 if (m_layoutRoot)
2059                     m_layoutRoot->markContainingBlocksForLayout(false);
2060                 m_layoutRoot = 0;
2061                 relayoutRoot->markContainingBlocksForLayout(false);
2062                 InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2063             }
2064         }
2065     } else if (m_layoutSchedulingEnabled) {
2066         int delay = m_frame->document()->minimumLayoutDelay();
2067         m_layoutRoot = relayoutRoot;
2068         ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
2069         InspectorInstrumentation::didInvalidateLayout(m_frame.get());
2070         m_delayedLayout = delay != 0;
2071         m_layoutTimer.startOneShot(delay * 0.001);
2072     }
2073 }
2074 
layoutPending() const2075 bool FrameView::layoutPending() const
2076 {
2077     return m_layoutTimer.isActive();
2078 }
2079 
needsLayout() const2080 bool FrameView::needsLayout() const
2081 {
2082     // This can return true in cases where the document does not have a body yet.
2083     // Document::shouldScheduleLayout takes care of preventing us from scheduling
2084     // layout in that case.
2085 
2086     RenderView* renderView = this->renderView();
2087     return layoutPending()
2088         || (renderView && renderView->needsLayout())
2089         || m_layoutRoot;
2090 }
2091 
setNeedsLayout()2092 void FrameView::setNeedsLayout()
2093 {
2094     if (RenderView* renderView = this->renderView())
2095         renderView->setNeedsLayout();
2096 }
2097 
unscheduleRelayout()2098 void FrameView::unscheduleRelayout()
2099 {
2100     if (!m_layoutTimer.isActive())
2101         return;
2102 
2103     m_layoutTimer.stop();
2104     m_delayedLayout = false;
2105 }
2106 
serviceScriptedAnimations(double monotonicAnimationStartTime)2107 void FrameView::serviceScriptedAnimations(double monotonicAnimationStartTime)
2108 {
2109     for (RefPtr<Frame> frame = m_frame; frame; frame = frame->tree().traverseNext()) {
2110         frame->view()->serviceScrollAnimations();
2111         if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled())
2112             frame->animation().serviceAnimations();
2113 
2114         DocumentAnimations::serviceOnAnimationFrame(*frame->document(), monotonicAnimationStartTime);
2115     }
2116 
2117     Vector<RefPtr<Document> > documents;
2118     for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext())
2119         documents.append(frame->document());
2120 
2121     for (size_t i = 0; i < documents.size(); ++i)
2122         documents[i]->serviceScriptedAnimations(monotonicAnimationStartTime);
2123 }
2124 
isTransparent() const2125 bool FrameView::isTransparent() const
2126 {
2127     return m_isTransparent;
2128 }
2129 
setTransparent(bool isTransparent)2130 void FrameView::setTransparent(bool isTransparent)
2131 {
2132     m_isTransparent = isTransparent;
2133     if (renderView() && renderView()->layer()->hasCompositedLayerMapping())
2134         renderView()->layer()->compositedLayerMapping()->updateContentsOpaque();
2135 }
2136 
hasOpaqueBackground() const2137 bool FrameView::hasOpaqueBackground() const
2138 {
2139     return !m_isTransparent && !m_baseBackgroundColor.hasAlpha();
2140 }
2141 
baseBackgroundColor() const2142 Color FrameView::baseBackgroundColor() const
2143 {
2144     return m_baseBackgroundColor;
2145 }
2146 
setBaseBackgroundColor(const Color & backgroundColor)2147 void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
2148 {
2149     if (!backgroundColor.isValid())
2150         m_baseBackgroundColor = Color::white;
2151     else
2152         m_baseBackgroundColor = backgroundColor;
2153 
2154     if (renderView() && renderView()->layer()->hasCompositedLayerMapping()) {
2155         CompositedLayerMappingPtr compositedLayerMapping = renderView()->layer()->compositedLayerMapping();
2156         compositedLayerMapping->updateContentsOpaque();
2157         if (compositedLayerMapping->mainGraphicsLayer())
2158             compositedLayerMapping->mainGraphicsLayer()->setNeedsDisplay();
2159     }
2160     recalculateScrollbarOverlayStyle();
2161 }
2162 
updateBackgroundRecursively(const Color & backgroundColor,bool transparent)2163 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
2164 {
2165     for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) {
2166         if (FrameView* view = frame->view()) {
2167             view->setTransparent(transparent);
2168             view->setBaseBackgroundColor(backgroundColor);
2169         }
2170     }
2171 }
2172 
shouldUpdateWhileOffscreen() const2173 bool FrameView::shouldUpdateWhileOffscreen() const
2174 {
2175     return m_shouldUpdateWhileOffscreen;
2176 }
2177 
setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)2178 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
2179 {
2180     m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
2181 }
2182 
shouldUpdate() const2183 bool FrameView::shouldUpdate() const
2184 {
2185     if (isOffscreen() && !shouldUpdateWhileOffscreen())
2186         return false;
2187     return true;
2188 }
2189 
scrollToAnchor()2190 void FrameView::scrollToAnchor()
2191 {
2192     RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
2193     if (!anchorNode)
2194         return;
2195 
2196     if (!anchorNode->renderer())
2197         return;
2198 
2199     LayoutRect rect;
2200     if (anchorNode != m_frame->document())
2201         rect = anchorNode->boundingBox();
2202 
2203     // Scroll nested layers and frames to reveal the anchor.
2204     // Align to the top and to the closest side (this matches other browsers).
2205     anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
2206 
2207     if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache())
2208         cache->handleScrolledToAnchor(anchorNode.get());
2209 
2210     // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
2211     m_maintainScrollPositionAnchor = anchorNode;
2212 }
2213 
updateWidgets()2214 bool FrameView::updateWidgets()
2215 {
2216     if (m_nestedLayoutCount > 1 || m_widgetUpdateSet.isEmpty())
2217         return true;
2218 
2219     // Need to swap because script will run inside the below loop and invalidate the iterator.
2220     EmbeddedObjectSet objects;
2221     objects.swap(m_widgetUpdateSet);
2222 
2223     for (EmbeddedObjectSet::iterator it = objects.begin(); it != objects.end(); ++it) {
2224         RenderEmbeddedObject& object = **it;
2225         HTMLPlugInElement* element = toHTMLPlugInElement(object.node());
2226 
2227         // The object may have already been destroyed (thus node cleared),
2228         // but FrameView holds a manual ref, so it won't have been deleted.
2229         if (!element)
2230             continue;
2231 
2232         // No need to update if it's already crashed or known to be missing.
2233         if (object.showsUnavailablePluginIndicator())
2234             continue;
2235 
2236         if (element->needsWidgetUpdate())
2237             element->updateWidget();
2238         object.updateWidgetPosition();
2239 
2240         // Prevent plugins from causing infinite updates of themselves.
2241         // FIXME: Do we really need to prevent this?
2242         m_widgetUpdateSet.remove(&object);
2243     }
2244 
2245     return m_widgetUpdateSet.isEmpty();
2246 }
2247 
updateWidgetsTimerFired(Timer<FrameView> *)2248 void FrameView::updateWidgetsTimerFired(Timer<FrameView>*)
2249 {
2250     RefPtr<FrameView> protect(this);
2251     m_updateWidgetsTimer.stop();
2252     for (unsigned i = 0; i < maxUpdateWidgetsIterations; ++i) {
2253         if (updateWidgets())
2254             return;
2255     }
2256 }
2257 
flushAnyPendingPostLayoutTasks()2258 void FrameView::flushAnyPendingPostLayoutTasks()
2259 {
2260     if (m_postLayoutTasksTimer.isActive())
2261         performPostLayoutTasks();
2262     if (m_updateWidgetsTimer.isActive())
2263         updateWidgetsTimerFired(0);
2264 }
2265 
performPostLayoutTasks()2266 void FrameView::performPostLayoutTasks()
2267 {
2268     TRACE_EVENT0("webkit", "FrameView::performPostLayoutTasks");
2269     RefPtr<FrameView> protect(this);
2270 
2271     m_postLayoutTasksTimer.stop();
2272 
2273     m_frame->selection().setCaretRectNeedsUpdate();
2274     m_frame->selection().updateAppearance();
2275 
2276     if (m_nestedLayoutCount <= 1) {
2277         if (m_firstLayoutCallbackPending) {
2278             m_firstLayoutCallbackPending = false;
2279             m_frame->loader().didFirstLayout();
2280         }
2281 
2282         // Ensure that we always send this eventually.
2283         if (!m_frame->document()->parsing() && m_frame->loader().stateMachine()->committedFirstRealDocumentLoad())
2284             m_isVisuallyNonEmpty = true;
2285 
2286         // If the layout was done with pending sheets, we are not in fact visually non-empty yet.
2287         if (m_isVisuallyNonEmpty && !m_frame->document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) {
2288             m_firstVisuallyNonEmptyLayoutCallbackPending = false;
2289             // FIXME: This callback is probably not needed, but is currently used
2290             // by android for setting the background color.
2291             m_frame->loader().client()->dispatchDidFirstVisuallyNonEmptyLayout();
2292         }
2293     }
2294 
2295     FontFaceSet::didLayout(m_frame->document());
2296 
2297     RenderView* renderView = this->renderView();
2298     if (renderView)
2299         renderView->updateWidgetPositions();
2300 
2301     if (!m_updateWidgetsTimer.isActive())
2302         m_updateWidgetsTimer.startOneShot(0);
2303 
2304     if (Page* page = m_frame->page()) {
2305         if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2306             scrollingCoordinator->notifyLayoutUpdated();
2307     }
2308 
2309     scrollToAnchor();
2310 
2311     sendResizeEventIfNeeded();
2312 }
2313 
sendResizeEventIfNeeded()2314 void FrameView::sendResizeEventIfNeeded()
2315 {
2316     ASSERT(m_frame);
2317 
2318     RenderView* renderView = this->renderView();
2319     if (!renderView || renderView->document().printing())
2320         return;
2321 
2322     IntSize currentSize = layoutSize(IncludeScrollbars);
2323     float currentZoomFactor = renderView->style()->zoom();
2324 
2325     bool shouldSendResizeEvent = currentSize != m_lastViewportSize || currentZoomFactor != m_lastZoomFactor;
2326 
2327     m_lastViewportSize = currentSize;
2328     m_lastZoomFactor = currentZoomFactor;
2329 
2330     if (!shouldSendResizeEvent)
2331         return;
2332 
2333     m_frame->document()->enqueueResizeEvent();
2334 
2335     if (isMainFrame())
2336         InspectorInstrumentation::didResizeMainFrame(m_frame->page());
2337 }
2338 
postLayoutTimerFired(Timer<FrameView> *)2339 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
2340 {
2341     performPostLayoutTasks();
2342 }
2343 
updateCounters()2344 void FrameView::updateCounters()
2345 {
2346     RenderView* view = renderView();
2347     if (!view->hasRenderCounters())
2348         return;
2349 
2350     for (RenderObject* renderer = view; renderer; renderer = renderer->nextInPreOrder()) {
2351         if (!renderer->isCounter())
2352             continue;
2353 
2354         toRenderCounter(renderer)->updateCounter();
2355     }
2356 }
2357 
autoSizeIfEnabled()2358 void FrameView::autoSizeIfEnabled()
2359 {
2360     if (!m_shouldAutoSize)
2361         return;
2362 
2363     if (m_inAutoSize)
2364         return;
2365 
2366     TemporaryChange<bool> changeInAutoSize(m_inAutoSize, true);
2367 
2368     Document* document = frame().document();
2369     if (!document)
2370         return;
2371 
2372     RenderView* documentView = document->renderView();
2373     Element* documentElement = document->documentElement();
2374     if (!documentView || !documentElement)
2375         return;
2376 
2377     RenderBox* documentRenderBox = documentElement->renderBox();
2378     if (!documentRenderBox)
2379         return;
2380 
2381     // If this is the first time we run autosize, start from small height and
2382     // allow it to grow.
2383     if (!m_didRunAutosize)
2384         resize(frameRect().width(), m_minAutoSize.height());
2385 
2386     IntSize size = frameRect().size();
2387 
2388     // Do the resizing twice. The first time is basically a rough calculation using the preferred width
2389     // which may result in a height change during the second iteration.
2390     for (int i = 0; i < 2; i++) {
2391         // Update various sizes including contentsSize, scrollHeight, etc.
2392         document->updateLayoutIgnorePendingStylesheets();
2393         int width = documentView->minPreferredLogicalWidth();
2394         int height = documentRenderBox->scrollHeight();
2395         IntSize newSize(width, height);
2396 
2397         // Check to see if a scrollbar is needed for a given dimension and
2398         // if so, increase the other dimension to account for the scrollbar.
2399         // Since the dimensions are only for the view rectangle, once a
2400         // dimension exceeds the maximum, there is no need to increase it further.
2401         if (newSize.width() > m_maxAutoSize.width()) {
2402             RefPtr<Scrollbar> localHorizontalScrollbar = horizontalScrollbar();
2403             if (!localHorizontalScrollbar)
2404                 localHorizontalScrollbar = createScrollbar(HorizontalScrollbar);
2405             if (!localHorizontalScrollbar->isOverlayScrollbar())
2406                 newSize.setHeight(newSize.height() + localHorizontalScrollbar->height());
2407 
2408             // Don't bother checking for a vertical scrollbar because the width is at
2409             // already greater the maximum.
2410         } else if (newSize.height() > m_maxAutoSize.height()) {
2411             RefPtr<Scrollbar> localVerticalScrollbar = verticalScrollbar();
2412             if (!localVerticalScrollbar)
2413                 localVerticalScrollbar = createScrollbar(VerticalScrollbar);
2414             if (!localVerticalScrollbar->isOverlayScrollbar())
2415                 newSize.setWidth(newSize.width() + localVerticalScrollbar->width());
2416 
2417             // Don't bother checking for a horizontal scrollbar because the height is
2418             // already greater the maximum.
2419         }
2420 
2421         // Ensure the size is at least the min bounds.
2422         newSize = newSize.expandedTo(m_minAutoSize);
2423 
2424         // Bound the dimensions by the max bounds and determine what scrollbars to show.
2425         ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff;
2426         if (newSize.width() > m_maxAutoSize.width()) {
2427             newSize.setWidth(m_maxAutoSize.width());
2428             horizonalScrollbarMode = ScrollbarAlwaysOn;
2429         }
2430         ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff;
2431         if (newSize.height() > m_maxAutoSize.height()) {
2432             newSize.setHeight(m_maxAutoSize.height());
2433             verticalScrollbarMode = ScrollbarAlwaysOn;
2434         }
2435 
2436         if (newSize == size)
2437             continue;
2438 
2439         // While loading only allow the size to increase (to avoid twitching during intermediate smaller states)
2440         // unless autoresize has just been turned on or the maximum size is smaller than the current size.
2441         if (m_didRunAutosize && size.height() <= m_maxAutoSize.height() && size.width() <= m_maxAutoSize.width()
2442             && !m_frame->document()->loadEventFinished() && (newSize.height() < size.height() || newSize.width() < size.width()))
2443             break;
2444 
2445         resize(newSize.width(), newSize.height());
2446         // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example,
2447         // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed).
2448         setVerticalScrollbarLock(false);
2449         setHorizontalScrollbarLock(false);
2450         setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true);
2451     }
2452     m_didRunAutosize = true;
2453 }
2454 
updateOverflowStatus(bool horizontalOverflow,bool verticalOverflow)2455 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
2456 {
2457     if (!m_viewportRenderer)
2458         return;
2459 
2460     if (m_overflowStatusDirty) {
2461         m_horizontalOverflow = horizontalOverflow;
2462         m_verticalOverflow = verticalOverflow;
2463         m_overflowStatusDirty = false;
2464         return;
2465     }
2466 
2467     bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
2468     bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
2469 
2470     if (horizontalOverflowChanged || verticalOverflowChanged) {
2471         m_horizontalOverflow = horizontalOverflow;
2472         m_verticalOverflow = verticalOverflow;
2473 
2474         RefPtr<OverflowEvent> event = OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow);
2475         event->setTarget(m_viewportRenderer->node());
2476         m_frame->document()->enqueueAnimationFrameEvent(event.release());
2477     }
2478 
2479 }
2480 
pagination() const2481 const Pagination& FrameView::pagination() const
2482 {
2483     if (m_pagination != Pagination())
2484         return m_pagination;
2485 
2486     if (isMainFrame())
2487         return m_frame->page()->pagination();
2488 
2489     return m_pagination;
2490 }
2491 
setPagination(const Pagination & pagination)2492 void FrameView::setPagination(const Pagination& pagination)
2493 {
2494     if (m_pagination == pagination)
2495         return;
2496 
2497     m_pagination = pagination;
2498 
2499     m_frame->document()->styleResolverChanged(RecalcStyleDeferred);
2500 }
2501 
windowClipRect(bool clipToContents) const2502 IntRect FrameView::windowClipRect(bool clipToContents) const
2503 {
2504     ASSERT(m_frame->view() == this);
2505 
2506     if (paintsEntireContents())
2507         return IntRect(IntPoint(), contentsSize());
2508 
2509     // Set our clip rect to be our contents.
2510     IntRect clipRect = contentsToWindow(visibleContentRect(clipToContents ? ExcludeScrollbars : IncludeScrollbars));
2511     if (!m_frame->ownerElement())
2512         return clipRect;
2513 
2514     // Take our owner element and get its clip rect.
2515     HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement();
2516     FrameView* parentView = ownerElement->document().view();
2517     if (parentView)
2518         clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement, true));
2519     return clipRect;
2520 }
2521 
windowClipRectForFrameOwner(const HTMLFrameOwnerElement * ownerElement,bool clipToLayerContents) const2522 IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement, bool clipToLayerContents) const
2523 {
2524     // The renderer can sometimes be null when style="display:none" interacts
2525     // with external content and plugins.
2526     if (!ownerElement->renderer())
2527         return windowClipRect();
2528 
2529     // If we have no layer, just return our window clip rect.
2530     const RenderLayer* enclosingLayer = ownerElement->renderer()->enclosingLayer();
2531     if (!enclosingLayer)
2532         return windowClipRect();
2533 
2534     // Apply the clip from the layer.
2535     IntRect clipRect;
2536     if (clipToLayerContents)
2537         clipRect = pixelSnappedIntRect(enclosingLayer->childrenClipRect());
2538     else
2539         clipRect = pixelSnappedIntRect(enclosingLayer->selfClipRect());
2540     clipRect = contentsToWindow(clipRect);
2541     return intersection(clipRect, windowClipRect());
2542 }
2543 
isActive() const2544 bool FrameView::isActive() const
2545 {
2546     Page* page = frame().page();
2547     return page && page->focusController().isActive();
2548 }
2549 
scrollTo(const IntSize & newOffset)2550 void FrameView::scrollTo(const IntSize& newOffset)
2551 {
2552     LayoutSize offset = scrollOffset();
2553     ScrollView::scrollTo(newOffset);
2554     if (offset != scrollOffset())
2555         scrollPositionChanged();
2556     frame().loader().client()->didChangeScrollOffset();
2557 }
2558 
invalidateScrollbarRect(Scrollbar * scrollbar,const IntRect & rect)2559 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
2560 {
2561     // Add in our offset within the FrameView.
2562     IntRect dirtyRect = rect;
2563     dirtyRect.moveBy(scrollbar->location());
2564     invalidateRect(dirtyRect);
2565 }
2566 
getTickmarks(Vector<IntRect> & tickmarks) const2567 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
2568 {
2569     tickmarks = frame().document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
2570 }
2571 
windowResizerRect() const2572 IntRect FrameView::windowResizerRect() const
2573 {
2574     Page* page = frame().page();
2575     if (!page)
2576         return IntRect();
2577     return page->chrome().windowResizerRect();
2578 }
2579 
setVisibleContentScaleFactor(float visibleContentScaleFactor)2580 void FrameView::setVisibleContentScaleFactor(float visibleContentScaleFactor)
2581 {
2582     if (m_visibleContentScaleFactor == visibleContentScaleFactor)
2583         return;
2584 
2585     m_visibleContentScaleFactor = visibleContentScaleFactor;
2586     updateScrollbars(scrollOffset());
2587 }
2588 
setInputEventsTransformForEmulation(const IntSize & offset,float contentScaleFactor)2589 void FrameView::setInputEventsTransformForEmulation(const IntSize& offset, float contentScaleFactor)
2590 {
2591     m_inputEventsOffsetForEmulation = offset;
2592     m_inputEventsScaleFactorForEmulation = contentScaleFactor;
2593 }
2594 
inputEventsOffsetForEmulation() const2595 IntSize FrameView::inputEventsOffsetForEmulation() const
2596 {
2597     return m_inputEventsOffsetForEmulation;
2598 }
2599 
inputEventsScaleFactor() const2600 float FrameView::inputEventsScaleFactor() const
2601 {
2602     return visibleContentScaleFactor() * m_inputEventsScaleFactorForEmulation;
2603 }
2604 
scrollbarsCanBeActive() const2605 bool FrameView::scrollbarsCanBeActive() const
2606 {
2607     if (m_frame->view() != this)
2608         return false;
2609 
2610     return !!m_frame->document();
2611 }
2612 
enclosingScrollableArea() const2613 ScrollableArea* FrameView::enclosingScrollableArea() const
2614 {
2615     // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer.
2616     return 0;
2617 }
2618 
scrollableAreaBoundingBox() const2619 IntRect FrameView::scrollableAreaBoundingBox() const
2620 {
2621     RenderPart* ownerRenderer = frame().ownerRenderer();
2622     if (!ownerRenderer)
2623         return frameRect();
2624 
2625     return ownerRenderer->absoluteContentQuad().enclosingBoundingBox();
2626 }
2627 
isScrollable()2628 bool FrameView::isScrollable()
2629 {
2630     // Check for:
2631     // 1) If there an actual overflow.
2632     // 2) display:none or visibility:hidden set to self or inherited.
2633     // 3) overflow{-x,-y}: hidden;
2634     // 4) scrolling: no;
2635 
2636     // Covers #1
2637     IntSize contentsSize = this->contentsSize();
2638     IntSize visibleContentSize = visibleContentRect().size();
2639     if ((contentsSize.height() <= visibleContentSize.height() && contentsSize.width() <= visibleContentSize.width()))
2640         return false;
2641 
2642     // Covers #2.
2643     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
2644     if (owner && (!owner->renderer() || !owner->renderer()->visibleToHitTesting()))
2645         return false;
2646 
2647     // Cover #3 and #4.
2648     ScrollbarMode horizontalMode;
2649     ScrollbarMode verticalMode;
2650     calculateScrollbarModesForLayout(horizontalMode, verticalMode, RulesFromWebContentOnly);
2651     if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff)
2652         return false;
2653 
2654     return true;
2655 }
2656 
updateScrollableAreaSet()2657 void FrameView::updateScrollableAreaSet()
2658 {
2659     // That ensures that only inner frames are cached.
2660     FrameView* parentFrameView = this->parentFrameView();
2661     if (!parentFrameView)
2662         return;
2663 
2664     if (!isScrollable()) {
2665         parentFrameView->removeScrollableArea(this);
2666         return;
2667     }
2668 
2669     parentFrameView->addScrollableArea(this);
2670 }
2671 
shouldSuspendScrollAnimations() const2672 bool FrameView::shouldSuspendScrollAnimations() const
2673 {
2674     return m_frame->loader().state() != FrameStateComplete;
2675 }
2676 
scrollbarStyleChanged(int newStyle,bool forceUpdate)2677 void FrameView::scrollbarStyleChanged(int newStyle, bool forceUpdate)
2678 {
2679     if (!isMainFrame())
2680         return;
2681 
2682     if (forceUpdate)
2683         ScrollView::scrollbarStyleChanged(newStyle, forceUpdate);
2684 }
2685 
setAnimatorsAreActive()2686 void FrameView::setAnimatorsAreActive()
2687 {
2688     Page* page = m_frame->page();
2689     if (!page)
2690         return;
2691 
2692     if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
2693         scrollAnimator->setIsActive();
2694 
2695     if (!m_scrollableAreas)
2696         return;
2697 
2698     for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
2699         ScrollableArea* scrollableArea = *it;
2700 
2701         ASSERT(scrollableArea->scrollbarsCanBeActive());
2702         scrollableArea->scrollAnimator()->setIsActive();
2703     }
2704 }
2705 
notifyPageThatContentAreaWillPaint() const2706 void FrameView::notifyPageThatContentAreaWillPaint() const
2707 {
2708     Page* page = m_frame->page();
2709     if (!page)
2710         return;
2711 
2712     contentAreaWillPaint();
2713 
2714     if (!m_scrollableAreas)
2715         return;
2716 
2717     for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
2718         ScrollableArea* scrollableArea = *it;
2719 
2720         if (!scrollableArea->scrollbarsCanBeActive())
2721             continue;
2722 
2723         scrollableArea->contentAreaWillPaint();
2724     }
2725 }
2726 
scrollAnimatorEnabled() const2727 bool FrameView::scrollAnimatorEnabled() const
2728 {
2729     if (m_frame->settings())
2730         return m_frame->settings()->scrollAnimatorEnabled();
2731     return false;
2732 }
2733 
updateAnnotatedRegions()2734 void FrameView::updateAnnotatedRegions()
2735 {
2736     Document* document = m_frame->document();
2737     if (!document->hasAnnotatedRegions())
2738         return;
2739     Vector<AnnotatedRegionValue> newRegions;
2740     document->renderBox()->collectAnnotatedRegions(newRegions);
2741     if (newRegions == document->annotatedRegions())
2742         return;
2743     document->setAnnotatedRegions(newRegions);
2744     if (Page* page = m_frame->page())
2745         page->chrome().client().annotatedRegionsChanged();
2746 }
2747 
updateScrollCorner()2748 void FrameView::updateScrollCorner()
2749 {
2750     RefPtr<RenderStyle> cornerStyle;
2751     IntRect cornerRect = scrollCornerRect();
2752     Document* doc = m_frame->document();
2753 
2754     if (doc && !cornerRect.isEmpty()) {
2755         // Try the <body> element first as a scroll corner source.
2756         if (Element* body = doc->body()) {
2757             if (RenderObject* renderer = body->renderer())
2758                 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
2759         }
2760 
2761         if (!cornerStyle) {
2762             // If the <body> didn't have a custom style, then the root element might.
2763             if (Element* docElement = doc->documentElement()) {
2764                 if (RenderObject* renderer = docElement->renderer())
2765                     cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
2766             }
2767         }
2768 
2769         if (!cornerStyle) {
2770             // If we have an owning ipage/Frame element, then it can set the custom scrollbar also.
2771             if (RenderPart* renderer = m_frame->ownerRenderer())
2772                 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
2773         }
2774     }
2775 
2776     if (cornerStyle) {
2777         if (!m_scrollCorner)
2778             m_scrollCorner = RenderScrollbarPart::createAnonymous(doc);
2779         m_scrollCorner->setStyle(cornerStyle.release());
2780         invalidateScrollCorner(cornerRect);
2781     } else if (m_scrollCorner) {
2782         m_scrollCorner->destroy();
2783         m_scrollCorner = 0;
2784     }
2785 
2786     ScrollView::updateScrollCorner();
2787 }
2788 
paintScrollCorner(GraphicsContext * context,const IntRect & cornerRect)2789 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
2790 {
2791     if (context->updatingControlTints()) {
2792         updateScrollCorner();
2793         return;
2794     }
2795 
2796     if (m_scrollCorner) {
2797         bool needsBackgorund = isMainFrame();
2798         if (needsBackgorund)
2799             context->fillRect(cornerRect, baseBackgroundColor());
2800         m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect);
2801         return;
2802     }
2803 
2804     ScrollView::paintScrollCorner(context, cornerRect);
2805 }
2806 
paintScrollbar(GraphicsContext * context,Scrollbar * bar,const IntRect & rect)2807 void FrameView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
2808 {
2809     bool needsBackgorund = bar->isCustomScrollbar() && isMainFrame();
2810     if (needsBackgorund) {
2811         IntRect toFill = bar->frameRect();
2812         toFill.intersect(rect);
2813         context->fillRect(toFill, baseBackgroundColor());
2814     }
2815 
2816     ScrollView::paintScrollbar(context, bar, rect);
2817 }
2818 
documentBackgroundColor() const2819 Color FrameView::documentBackgroundColor() const
2820 {
2821     // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of
2822     // the document and the body against the base background color of the frame view.
2823     // Background images are unfortunately impractical to include.
2824 
2825     // Return invalid Color objects whenever there is insufficient information.
2826     if (!frame().document())
2827         return Color();
2828 
2829     Element* htmlElement = frame().document()->documentElement();
2830     Element* bodyElement = frame().document()->body();
2831 
2832     // Start with invalid colors.
2833     Color htmlBackgroundColor;
2834     Color bodyBackgroundColor;
2835     if (htmlElement && htmlElement->renderer())
2836         htmlBackgroundColor = htmlElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
2837     if (bodyElement && bodyElement->renderer())
2838         bodyBackgroundColor = bodyElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
2839 
2840     if (!bodyBackgroundColor.isValid()) {
2841         if (!htmlBackgroundColor.isValid())
2842             return Color();
2843         return baseBackgroundColor().blend(htmlBackgroundColor);
2844     }
2845 
2846     if (!htmlBackgroundColor.isValid())
2847         return baseBackgroundColor().blend(bodyBackgroundColor);
2848 
2849     // We take the aggregate of the base background color
2850     // the <html> background color, and the <body>
2851     // background color to find the document color. The
2852     // addition of the base background color is not
2853     // technically part of the document background, but it
2854     // otherwise poses problems when the aggregate is not
2855     // fully opaque.
2856     return baseBackgroundColor().blend(htmlBackgroundColor).blend(bodyBackgroundColor);
2857 }
2858 
hasCustomScrollbars() const2859 bool FrameView::hasCustomScrollbars() const
2860 {
2861     const HashSet<RefPtr<Widget> >* viewChildren = children();
2862     HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2863     for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2864         Widget* widget = current->get();
2865         if (widget->isFrameView()) {
2866             if (toFrameView(widget)->hasCustomScrollbars())
2867                 return true;
2868         } else if (widget->isScrollbar()) {
2869             Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
2870             if (scrollbar->isCustomScrollbar())
2871                 return true;
2872         }
2873     }
2874 
2875     return false;
2876 }
2877 
parentFrameView() const2878 FrameView* FrameView::parentFrameView() const
2879 {
2880     if (!parent())
2881         return 0;
2882 
2883     if (Frame* parentFrame = m_frame->tree().parent())
2884         return parentFrame->view();
2885 
2886     return 0;
2887 }
2888 
updateControlTints()2889 void FrameView::updateControlTints()
2890 {
2891     // This is called when control tints are changed from aqua/graphite to clear and vice versa.
2892     // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
2893     // This is only done if the theme supports control tinting. It's up to the theme and platform
2894     // to define when controls get the tint and to call this function when that changes.
2895 
2896     // Optimize the common case where we bring a window to the front while it's still empty.
2897     if (m_frame->document()->url().isEmpty())
2898         return;
2899 
2900     if (RenderTheme::theme().supportsControlTints() || hasCustomScrollbars())
2901         paintControlTints();
2902 }
2903 
paintControlTints()2904 void FrameView::paintControlTints()
2905 {
2906     if (needsLayout())
2907         layout();
2908     // FIXME: The use of paint seems like overkill: crbug.com/236892
2909     GraphicsContext context(0); // NULL canvas to get a non-painting context.
2910     context.setUpdatingControlTints(true);
2911     paint(&context, frameRect());
2912 }
2913 
wasScrolledByUser() const2914 bool FrameView::wasScrolledByUser() const
2915 {
2916     return m_wasScrolledByUser;
2917 }
2918 
setWasScrolledByUser(bool wasScrolledByUser)2919 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
2920 {
2921     if (m_inProgrammaticScroll)
2922         return;
2923     m_maintainScrollPositionAnchor = 0;
2924     m_wasScrolledByUser = wasScrolledByUser;
2925 }
2926 
paintContents(GraphicsContext * p,const IntRect & rect)2927 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
2928 {
2929     Document* document = m_frame->document();
2930 
2931 #ifndef NDEBUG
2932     bool fillWithRed;
2933     if (document->printing())
2934         fillWithRed = false; // Printing, don't fill with red (can't remember why).
2935     else if (m_frame->ownerElement())
2936         fillWithRed = false; // Subframe, don't fill with red.
2937     else if (isTransparent())
2938         fillWithRed = false; // Transparent, don't fill with red.
2939     else if (m_paintBehavior & PaintBehaviorSelectionOnly)
2940         fillWithRed = false; // Selections are transparent, don't fill with red.
2941     else if (m_nodeToDraw)
2942         fillWithRed = false; // Element images are transparent, don't fill with red.
2943     else
2944         fillWithRed = true;
2945 
2946     if (fillWithRed)
2947         p->fillRect(rect, Color(0xFF, 0, 0));
2948 #endif
2949 
2950     RenderView* renderView = this->renderView();
2951     if (!renderView) {
2952         WTF_LOG_ERROR("called FrameView::paint with nil renderer");
2953         return;
2954     }
2955 
2956     ASSERT(!needsLayout());
2957     if (needsLayout())
2958         return;
2959 
2960     InspectorInstrumentation::willPaint(renderView, 0);
2961 
2962     bool isTopLevelPainter = !s_inPaintContents;
2963     s_inPaintContents = true;
2964 
2965     FontCachePurgePreventer fontCachePurgePreventer;
2966 
2967     PaintBehavior oldPaintBehavior = m_paintBehavior;
2968 
2969     if (FrameView* parentView = parentFrameView()) {
2970         if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
2971             m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2972     }
2973 
2974     if (m_paintBehavior == PaintBehaviorNormal)
2975         document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
2976 
2977     if (document->printing())
2978         m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2979 
2980     ASSERT(!m_isPainting);
2981     m_isPainting = true;
2982 
2983     // m_nodeToDraw is used to draw only one element (and its descendants)
2984     RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
2985     RenderLayer* rootLayer = renderView->layer();
2986 
2987 #ifndef NDEBUG
2988     renderView->assertSubtreeIsLaidOut();
2989     RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(rootLayer->renderer());
2990 #endif
2991 
2992     RenderObject* enclosingLayerRenderer = eltRenderer->enclosingLayer() ? eltRenderer->enclosingLayer()->renderer() : eltRenderer;
2993     rootLayer->paint(p, rect, m_paintBehavior, enclosingLayerRenderer);
2994 
2995     if (rootLayer->containsDirtyOverlayScrollbars())
2996         rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer);
2997 
2998     m_isPainting = false;
2999 
3000     m_paintBehavior = oldPaintBehavior;
3001     m_lastPaintTime = currentTime();
3002 
3003     // Regions may have changed as a result of the visibility/z-index of element changing.
3004     if (document->annotatedRegionsDirty())
3005         updateAnnotatedRegions();
3006 
3007     if (isTopLevelPainter) {
3008         // Everythin that happens after paintContents completions is considered
3009         // to be part of the next frame.
3010         s_currentFrameTimeStamp = currentTime();
3011         s_inPaintContents = false;
3012     }
3013 
3014     InspectorInstrumentation::didPaint(renderView, 0, p, rect);
3015 }
3016 
setPaintBehavior(PaintBehavior behavior)3017 void FrameView::setPaintBehavior(PaintBehavior behavior)
3018 {
3019     m_paintBehavior = behavior;
3020 }
3021 
paintBehavior() const3022 PaintBehavior FrameView::paintBehavior() const
3023 {
3024     return m_paintBehavior;
3025 }
3026 
isPainting() const3027 bool FrameView::isPainting() const
3028 {
3029     return m_isPainting;
3030 }
3031 
setNodeToDraw(Node * node)3032 void FrameView::setNodeToDraw(Node* node)
3033 {
3034     m_nodeToDraw = node;
3035 }
3036 
paintOverhangAreas(GraphicsContext * context,const IntRect & horizontalOverhangArea,const IntRect & verticalOverhangArea,const IntRect & dirtyRect)3037 void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
3038 {
3039     if (context->paintingDisabled())
3040         return;
3041 
3042     if (m_frame->document()->printing())
3043         return;
3044 
3045     if (isMainFrame()) {
3046         if (m_frame->page()->chrome().client().paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
3047             return;
3048     }
3049 
3050     ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
3051 }
3052 
updateLayoutAndStyleIfNeededRecursive()3053 void FrameView::updateLayoutAndStyleIfNeededRecursive()
3054 {
3055     // We have to crawl our entire tree looking for any FrameViews that need
3056     // layout and make sure they are up to date.
3057     // Mac actually tests for intersection with the dirty region and tries not to
3058     // update layout for frames that are outside the dirty region.  Not only does this seem
3059     // pointless (since those frames will have set a zero timer to layout anyway), but
3060     // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
3061     // region but then become included later by the second frame adding rects to the dirty region
3062     // when it lays out.
3063 
3064     m_frame->document()->updateStyleIfNeeded();
3065 
3066     if (needsLayout())
3067         layout();
3068 
3069     // Grab a copy of the children() set, as it may be mutated by the following updateLayoutAndStyleIfNeededRecursive
3070     // calls, as they can potentially re-enter a layout of the parent frame view, which may add/remove scrollbars
3071     // and thus mutates the children() set.
3072     Vector<RefPtr<FrameView> > frameViews;
3073     collectFrameViewChildren(this, frameViews);
3074 
3075     const Vector<RefPtr<FrameView> >::iterator end = frameViews.end();
3076     for (Vector<RefPtr<FrameView> >::iterator it = frameViews.begin(); it != end; ++it)
3077         (*it)->updateLayoutAndStyleIfNeededRecursive();
3078 
3079     // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
3080     // painting, so we need to flush out any deferred repaints too.
3081     flushDeferredRepaints();
3082 
3083     // When seamless is on, child frame can mark parent frame dirty. In such case, child frame
3084     // needs to call layout on parent frame recursively.
3085     // This assert ensures that parent frames are clean, when child frames finished updating layout and style.
3086     ASSERT(!needsLayout());
3087 }
3088 
enableAutoSizeMode(bool enable,const IntSize & minSize,const IntSize & maxSize)3089 void FrameView::enableAutoSizeMode(bool enable, const IntSize& minSize, const IntSize& maxSize)
3090 {
3091     ASSERT(!enable || !minSize.isEmpty());
3092     ASSERT(minSize.width() <= maxSize.width());
3093     ASSERT(minSize.height() <= maxSize.height());
3094 
3095     if (m_shouldAutoSize == enable && m_minAutoSize == minSize && m_maxAutoSize == maxSize)
3096         return;
3097 
3098 
3099     m_shouldAutoSize = enable;
3100     m_minAutoSize = minSize;
3101     m_maxAutoSize = maxSize;
3102     m_didRunAutosize = false;
3103 
3104     setLayoutSizeFixedToFrameSize(enable);
3105     setNeedsLayout();
3106     scheduleRelayout();
3107     if (m_shouldAutoSize)
3108         return;
3109 
3110     // Since autosize mode forces the scrollbar mode, change them to being auto.
3111     setVerticalScrollbarLock(false);
3112     setHorizontalScrollbarLock(false);
3113     setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
3114 }
3115 
forceLayout(bool allowSubtree)3116 void FrameView::forceLayout(bool allowSubtree)
3117 {
3118     layout(allowSubtree);
3119 }
3120 
forceLayoutForPagination(const FloatSize & pageSize,const FloatSize & originalPageSize,float maximumShrinkFactor,AdjustViewSizeOrNot shouldAdjustViewSize)3121 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor, AdjustViewSizeOrNot shouldAdjustViewSize)
3122 {
3123     // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
3124     // the state of things before and after the layout
3125     if (RenderView* renderView = this->renderView()) {
3126         float pageLogicalWidth = renderView->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
3127         float pageLogicalHeight = renderView->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
3128 
3129         LayoutUnit flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
3130         LayoutUnit flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
3131         renderView->setLogicalWidth(flooredPageLogicalWidth);
3132         renderView->setPageLogicalHeight(flooredPageLogicalHeight);
3133         renderView->setNeedsLayoutAndPrefWidthsRecalc();
3134         forceLayout();
3135 
3136         // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
3137         // page width when shrunk, we will lay out at maximum shrink and clip extra content.
3138         // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
3139         // implementation should not do this!
3140         bool horizontalWritingMode = renderView->style()->isHorizontalWritingMode();
3141         const LayoutRect& documentRect = renderView->documentRect();
3142         LayoutUnit docLogicalWidth = horizontalWritingMode ? documentRect.width() : documentRect.height();
3143         if (docLogicalWidth > pageLogicalWidth) {
3144             int expectedPageWidth = std::min<float>(documentRect.width(), pageSize.width() * maximumShrinkFactor);
3145             int expectedPageHeight = std::min<float>(documentRect.height(), pageSize.height() * maximumShrinkFactor);
3146             FloatSize maxPageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(originalPageSize.width(), originalPageSize.height()), FloatSize(expectedPageWidth, expectedPageHeight));
3147             pageLogicalWidth = horizontalWritingMode ? maxPageSize.width() : maxPageSize.height();
3148             pageLogicalHeight = horizontalWritingMode ? maxPageSize.height() : maxPageSize.width();
3149 
3150             flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
3151             flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
3152             renderView->setLogicalWidth(flooredPageLogicalWidth);
3153             renderView->setPageLogicalHeight(flooredPageLogicalHeight);
3154             renderView->setNeedsLayoutAndPrefWidthsRecalc();
3155             forceLayout();
3156 
3157             const LayoutRect& updatedDocumentRect = renderView->documentRect();
3158             LayoutUnit docLogicalHeight = horizontalWritingMode ? updatedDocumentRect.height() : updatedDocumentRect.width();
3159             LayoutUnit docLogicalTop = horizontalWritingMode ? updatedDocumentRect.y() : updatedDocumentRect.x();
3160             LayoutUnit docLogicalRight = horizontalWritingMode ? updatedDocumentRect.maxX() : updatedDocumentRect.maxY();
3161             LayoutUnit clippedLogicalLeft = 0;
3162             if (!renderView->style()->isLeftToRightDirection())
3163                 clippedLogicalLeft = docLogicalRight - pageLogicalWidth;
3164             LayoutRect overflow(clippedLogicalLeft, docLogicalTop, pageLogicalWidth, docLogicalHeight);
3165 
3166             if (!horizontalWritingMode)
3167                 overflow = overflow.transposedRect();
3168             renderView->clearLayoutOverflow();
3169             renderView->addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
3170         }
3171     }
3172 
3173     if (shouldAdjustViewSize)
3174         adjustViewSize();
3175 }
3176 
convertFromRenderer(const RenderObject * renderer,const IntRect & rendererRect) const3177 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
3178 {
3179     IntRect rect = pixelSnappedIntRect(enclosingLayoutRect(renderer->localToAbsoluteQuad(FloatRect(rendererRect)).boundingBox()));
3180 
3181     // Convert from page ("absolute") to FrameView coordinates.
3182     rect.moveBy(-scrollPosition());
3183 
3184     return rect;
3185 }
3186 
convertToRenderer(const RenderObject * renderer,const IntRect & viewRect) const3187 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
3188 {
3189     IntRect rect = viewRect;
3190 
3191     // Convert from FrameView coords into page ("absolute") coordinates.
3192     rect.moveBy(scrollPosition());
3193 
3194     // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
3195     // move the rect for now.
3196     rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), UseTransforms)));
3197     return rect;
3198 }
3199 
convertFromRenderer(const RenderObject * renderer,const IntPoint & rendererPoint) const3200 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
3201 {
3202     IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, UseTransforms));
3203 
3204     // Convert from page ("absolute") to FrameView coordinates.
3205     point.moveBy(-scrollPosition());
3206     return point;
3207 }
3208 
convertToRenderer(const RenderObject * renderer,const IntPoint & viewPoint) const3209 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
3210 {
3211     IntPoint point = viewPoint;
3212 
3213     // Convert from FrameView coords into page ("absolute") coordinates.
3214     point += IntSize(scrollX(), scrollY());
3215 
3216     return roundedIntPoint(renderer->absoluteToLocal(point, UseTransforms));
3217 }
3218 
convertToContainingView(const IntRect & localRect) const3219 IntRect FrameView::convertToContainingView(const IntRect& localRect) const
3220 {
3221     if (const ScrollView* parentScrollView = toScrollView(parent())) {
3222         if (parentScrollView->isFrameView()) {
3223             const FrameView* parentView = toFrameView(parentScrollView);
3224             // Get our renderer in the parent view
3225             RenderPart* renderer = m_frame->ownerRenderer();
3226             if (!renderer)
3227                 return localRect;
3228 
3229             IntRect rect(localRect);
3230             // Add borders and padding??
3231             rect.move(renderer->borderLeft() + renderer->paddingLeft(),
3232                 renderer->borderTop() + renderer->paddingTop());
3233             return parentView->convertFromRenderer(renderer, rect);
3234         }
3235 
3236         return Widget::convertToContainingView(localRect);
3237     }
3238 
3239     return localRect;
3240 }
3241 
convertFromContainingView(const IntRect & parentRect) const3242 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
3243 {
3244     if (const ScrollView* parentScrollView = toScrollView(parent())) {
3245         if (parentScrollView->isFrameView()) {
3246             const FrameView* parentView = toFrameView(parentScrollView);
3247 
3248             // Get our renderer in the parent view
3249             RenderPart* renderer = m_frame->ownerRenderer();
3250             if (!renderer)
3251                 return parentRect;
3252 
3253             IntRect rect = parentView->convertToRenderer(renderer, parentRect);
3254             // Subtract borders and padding
3255             rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
3256                       -renderer->borderTop() - renderer->paddingTop());
3257             return rect;
3258         }
3259 
3260         return Widget::convertFromContainingView(parentRect);
3261     }
3262 
3263     return parentRect;
3264 }
3265 
convertToContainingView(const IntPoint & localPoint) const3266 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
3267 {
3268     if (const ScrollView* parentScrollView = toScrollView(parent())) {
3269         if (parentScrollView->isFrameView()) {
3270             const FrameView* parentView = toFrameView(parentScrollView);
3271 
3272             // Get our renderer in the parent view
3273             RenderPart* renderer = m_frame->ownerRenderer();
3274             if (!renderer)
3275                 return localPoint;
3276 
3277             IntPoint point(localPoint);
3278 
3279             // Add borders and padding
3280             point.move(renderer->borderLeft() + renderer->paddingLeft(),
3281                        renderer->borderTop() + renderer->paddingTop());
3282             return parentView->convertFromRenderer(renderer, point);
3283         }
3284 
3285         return Widget::convertToContainingView(localPoint);
3286     }
3287 
3288     return localPoint;
3289 }
3290 
convertFromContainingView(const IntPoint & parentPoint) const3291 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
3292 {
3293     if (const ScrollView* parentScrollView = toScrollView(parent())) {
3294         if (parentScrollView->isFrameView()) {
3295             const FrameView* parentView = toFrameView(parentScrollView);
3296 
3297             // Get our renderer in the parent view
3298             RenderPart* renderer = m_frame->ownerRenderer();
3299             if (!renderer)
3300                 return parentPoint;
3301 
3302             IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
3303             // Subtract borders and padding
3304             point.move(-renderer->borderLeft() - renderer->paddingLeft(),
3305                        -renderer->borderTop() - renderer->paddingTop());
3306             return point;
3307         }
3308 
3309         return Widget::convertFromContainingView(parentPoint);
3310     }
3311 
3312     return parentPoint;
3313 }
3314 
3315 // Normal delay
setRepaintThrottlingDeferredRepaintDelay(double p)3316 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
3317 {
3318     s_normalDeferredRepaintDelay = p;
3319 }
3320 
3321 // Negative value would mean that first few repaints happen without a delay
setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)3322 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)
3323 {
3324     s_initialDeferredRepaintDelayDuringLoading = p;
3325 }
3326 
3327 // The delay grows on each repaint to this maximum value
setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)3328 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)
3329 {
3330     s_maxDeferredRepaintDelayDuringLoading = p;
3331 }
3332 
3333 // On each repaint the delay increases by this amount
setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)3334 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)
3335 {
3336     s_deferredRepaintDelayIncrementDuringLoading = p;
3337 }
3338 
setTracksRepaints(bool trackRepaints)3339 void FrameView::setTracksRepaints(bool trackRepaints)
3340 {
3341     if (trackRepaints == m_isTrackingRepaints)
3342         return;
3343 
3344     for (Frame* frame = m_frame->tree().top(); frame; frame = frame->tree().traverseNext()) {
3345         if (RenderView* renderView = frame->contentRenderer())
3346             renderView->compositor()->setTracksRepaints(trackRepaints);
3347     }
3348 
3349     resetTrackedRepaints();
3350     m_isTrackingRepaints = trackRepaints;
3351 }
3352 
resetTrackedRepaints()3353 void FrameView::resetTrackedRepaints()
3354 {
3355     m_trackedRepaintRects.clear();
3356     if (RenderView* renderView = this->renderView())
3357         renderView->compositor()->resetTrackedRepaintRects();
3358 }
3359 
trackedRepaintRectsAsText() const3360 String FrameView::trackedRepaintRectsAsText() const
3361 {
3362     TextStream ts;
3363     if (!m_trackedRepaintRects.isEmpty()) {
3364         ts << "(repaint rects\n";
3365         for (size_t i = 0; i < m_trackedRepaintRects.size(); ++i)
3366             ts << "  (rect " << m_trackedRepaintRects[i].x() << " " << m_trackedRepaintRects[i].y() << " " << m_trackedRepaintRects[i].width() << " " << m_trackedRepaintRects[i].height() << ")\n";
3367         ts << ")\n";
3368     }
3369     return ts.release();
3370 }
3371 
addResizerArea(RenderBox * resizerBox)3372 void FrameView::addResizerArea(RenderBox* resizerBox)
3373 {
3374     if (!m_resizerAreas)
3375         m_resizerAreas = adoptPtr(new ResizerAreaSet);
3376     m_resizerAreas->add(resizerBox);
3377 }
3378 
removeResizerArea(RenderBox * resizerBox)3379 void FrameView::removeResizerArea(RenderBox* resizerBox)
3380 {
3381     if (!m_resizerAreas)
3382         return;
3383 
3384     ResizerAreaSet::iterator it = m_resizerAreas->find(resizerBox);
3385     if (it != m_resizerAreas->end())
3386         m_resizerAreas->remove(it);
3387 }
3388 
addScrollableArea(ScrollableArea * scrollableArea)3389 bool FrameView::addScrollableArea(ScrollableArea* scrollableArea)
3390 {
3391     ASSERT(scrollableArea);
3392     if (!m_scrollableAreas)
3393         m_scrollableAreas = adoptPtr(new ScrollableAreaSet);
3394     return m_scrollableAreas->add(scrollableArea).isNewEntry;
3395 }
3396 
removeScrollableArea(ScrollableArea * scrollableArea)3397 bool FrameView::removeScrollableArea(ScrollableArea* scrollableArea)
3398 {
3399     if (!m_scrollableAreas)
3400         return false;
3401 
3402     ScrollableAreaSet::iterator it = m_scrollableAreas->find(scrollableArea);
3403     if (it == m_scrollableAreas->end())
3404         return false;
3405 
3406     m_scrollableAreas->remove(it);
3407     return true;
3408 }
3409 
containsScrollableArea(const ScrollableArea * scrollableArea) const3410 bool FrameView::containsScrollableArea(const ScrollableArea* scrollableArea) const
3411 {
3412     ASSERT(scrollableArea);
3413     if (!m_scrollableAreas || !scrollableArea)
3414         return false;
3415     return m_scrollableAreas->contains(const_cast<ScrollableArea*>(scrollableArea));
3416 }
3417 
removeChild(Widget * widget)3418 void FrameView::removeChild(Widget* widget)
3419 {
3420     if (widget->isFrameView())
3421         removeScrollableArea(toFrameView(widget));
3422 
3423     ScrollView::removeChild(widget);
3424 }
3425 
wheelEvent(const PlatformWheelEvent & wheelEvent)3426 bool FrameView::wheelEvent(const PlatformWheelEvent& wheelEvent)
3427 {
3428     // Note that to allow for rubber-band over-scroll behavior, even non-scrollable views
3429     // should handle wheel events.
3430 #if !USE(RUBBER_BANDING)
3431     if (!isScrollable())
3432         return false;
3433 #endif
3434 
3435     // We don't allow mouse wheeling to happen in a ScrollView that has had its scrollbars explicitly disabled.
3436     if (!canHaveScrollbars())
3437         return false;
3438 
3439     return ScrollableArea::handleWheelEvent(wheelEvent);
3440 }
3441 
isVerticalDocument() const3442 bool FrameView::isVerticalDocument() const
3443 {
3444     RenderView* renderView = this->renderView();
3445     if (!renderView)
3446         return true;
3447 
3448     return renderView->style()->isHorizontalWritingMode();
3449 }
3450 
isFlippedDocument() const3451 bool FrameView::isFlippedDocument() const
3452 {
3453     RenderView* renderView = this->renderView();
3454     if (!renderView)
3455         return false;
3456 
3457     return renderView->style()->isFlippedBlocksWritingMode();
3458 }
3459 
axObjectCache() const3460 AXObjectCache* FrameView::axObjectCache() const
3461 {
3462     if (frame().document())
3463         return frame().document()->existingAXObjectCache();
3464     return 0;
3465 }
3466 
setCursor(const Cursor & cursor)3467 void FrameView::setCursor(const Cursor& cursor)
3468 {
3469     Page* page = frame().page();
3470     if (!page)
3471         return;
3472     page->chrome().setCursor(cursor);
3473 }
3474 
isMainFrame() const3475 bool FrameView::isMainFrame() const
3476 {
3477     return m_frame->isMainFrame();
3478 }
3479 
frameRectsChanged()3480 void FrameView::frameRectsChanged()
3481 {
3482     if (layoutSizeFixedToFrameSize())
3483         setLayoutSizeInternal(frameRect().size());
3484 
3485     ScrollView::frameRectsChanged();
3486 }
3487 
setLayoutSizeInternal(const IntSize & size)3488 void FrameView::setLayoutSizeInternal(const IntSize& size)
3489 {
3490     if (m_layoutSize == size)
3491         return;
3492 
3493     m_layoutSize = size;
3494     contentsResized();
3495 }
3496 
didAddScrollbar(Scrollbar * scrollbar,ScrollbarOrientation orientation)3497 void FrameView::didAddScrollbar(Scrollbar* scrollbar, ScrollbarOrientation orientation)
3498 {
3499     ScrollableArea::didAddScrollbar(scrollbar, orientation);
3500     if (AXObjectCache* cache = axObjectCache())
3501         cache->handleScrollbarUpdate(this);
3502 }
3503 
willRemoveScrollbar(Scrollbar * scrollbar,ScrollbarOrientation orientation)3504 void FrameView::willRemoveScrollbar(Scrollbar* scrollbar, ScrollbarOrientation orientation)
3505 {
3506     ScrollableArea::willRemoveScrollbar(scrollbar, orientation);
3507     if (AXObjectCache* cache = axObjectCache()) {
3508         cache->remove(scrollbar);
3509         cache->handleScrollbarUpdate(this);
3510     }
3511 }
3512 
3513 } // namespace WebCore
3514