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