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.
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.
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.
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.
28 #include "core/frame/FrameView.h"
30 #include "core/HTMLNames.h"
31 #include "core/MediaTypeNames.h"
32 #include "core/compositing/DisplayListCompositingBuilder.h"
33 #include "core/css/FontFaceSet.h"
34 #include "core/css/resolver/StyleResolver.h"
35 #include "core/dom/AXObjectCache.h"
36 #include "core/dom/Fullscreen.h"
37 #include "core/editing/EditingUtilities.h"
38 #include "core/editing/FrameSelection.h"
39 #include "core/editing/RenderedPosition.h"
40 #include "core/editing/markers/DocumentMarkerController.h"
41 #include "core/fetch/ResourceFetcher.h"
42 #include "core/fetch/ResourceLoadPriorityOptimizer.h"
43 #include "core/frame/FrameHost.h"
44 #include "core/frame/LocalFrame.h"
45 #include "core/frame/Settings.h"
46 #include "core/html/HTMLFrameElement.h"
47 #include "core/html/HTMLPlugInElement.h"
48 #include "core/html/HTMLTextFormControlElement.h"
49 #include "core/html/parser/TextResourceDecoder.h"
50 #include "core/input/EventHandler.h"
51 #include "core/inspector/InspectorInstrumentation.h"
52 #include "core/inspector/InspectorTraceEvents.h"
53 #include "core/layout/LayoutAnalyzer.h"
54 #include "core/layout/LayoutCounter.h"
55 #include "core/layout/LayoutEmbeddedObject.h"
56 #include "core/layout/LayoutInline.h"
57 #include "core/layout/LayoutListBox.h"
58 #include "core/layout/LayoutPart.h"
59 #include "core/layout/LayoutScrollbar.h"
60 #include "core/layout/LayoutScrollbarPart.h"
61 #include "core/layout/LayoutTableCell.h"
62 #include "core/layout/LayoutTheme.h"
63 #include "core/layout/LayoutView.h"
64 #include "core/layout/ScrollAlignment.h"
65 #include "core/layout/TextAutosizer.h"
66 #include "core/layout/TracedLayoutObject.h"
67 #include "core/layout/compositing/CompositedDeprecatedPaintLayerMapping.h"
68 #include "core/layout/compositing/CompositedSelection.h"
69 #include "core/layout/compositing/DeprecatedPaintLayerCompositor.h"
70 #include "core/layout/svg/LayoutSVGRoot.h"
71 #include "core/loader/FrameLoader.h"
72 #include "core/loader/FrameLoaderClient.h"
73 #include "core/page/AutoscrollController.h"
74 #include "core/page/ChromeClient.h"
75 #include "core/page/FocusController.h"
76 #include "core/page/FrameTree.h"
77 #include "core/page/Page.h"
78 #include "core/page/scrolling/ScrollingCoordinator.h"
79 #include "core/paint/DeprecatedPaintLayer.h"
80 #include "core/paint/FramePainter.h"
81 #include "core/style/ComputedStyle.h"
82 #include "core/svg/SVGDocumentExtensions.h"
83 #include "core/svg/SVGSVGElement.h"
84 #include "platform/HostWindow.h"
85 #include "platform/RuntimeEnabledFeatures.h"
86 #include "platform/ScriptForbiddenScope.h"
87 #include "platform/TraceEvent.h"
88 #include "platform/TracedValue.h"
89 #include "platform/fonts/FontCache.h"
90 #include "platform/geometry/DoubleRect.h"
91 #include "platform/geometry/FloatRect.h"
92 #include "platform/geometry/LayoutRect.h"
93 #include "platform/graphics/GraphicsContext.h"
94 #include "platform/graphics/GraphicsLayer.h"
95 #include "platform/graphics/GraphicsLayerDebugInfo.h"
96 #include "platform/graphics/paint/DisplayItemList.h"
97 #include "platform/scroll/ScrollAnimator.h"
98 #include "platform/text/TextStream.h"
99 #include "wtf/CurrentTime.h"
100 #include "wtf/StdLibExtras.h"
101 #include "wtf/TemporaryChange.h"
105 using namespace HTMLNames
;
107 // The maximum number of updateWidgets iterations that should be done before returning.
108 static const unsigned maxUpdateWidgetsIterations
= 2;
109 static const double resourcePriorityUpdateDelayAfterScroll
= 0.250;
111 static bool s_initialTrackAllPaintInvalidations
= false;
113 FrameView::FrameView(LocalFrame
* frame
)
115 , m_displayMode(WebDisplayModeBrowser
)
116 , m_canHaveScrollbars(true)
117 , m_slowRepaintObjectCount(0)
118 , m_hasPendingLayout(false)
119 , m_inSynchronousPostLayout(false)
120 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired
)
121 , m_updateWidgetsTimer(this, &FrameView::updateWidgetsTimerFired
)
122 , m_isTransparent(false)
123 , m_baseBackgroundColor(Color::white
)
124 , m_mediaType(MediaTypeNames::screen
)
125 , m_safeToPropagateScrollToParent(true)
126 , m_isTrackingPaintInvalidations(false)
127 , m_scrollCorner(nullptr)
128 , m_inputEventsScaleFactorForEmulation(1)
129 , m_layoutSizeFixedToFrameSize(true)
130 , m_didScrollTimer(this, &FrameView::didScrollTimerFired
)
131 , m_topControlsViewportAdjustment(0)
132 , m_needsUpdateWidgetPositions(false)
134 , m_hasBeenDisposed(false)
136 , m_horizontalScrollbarMode(ScrollbarAuto
)
137 , m_verticalScrollbarMode(ScrollbarAuto
)
138 , m_horizontalScrollbarLock(false)
139 , m_verticalScrollbarLock(false)
140 , m_scrollbarsAvoidingResizer(0)
141 , m_scrollbarsSuppressed(false)
142 , m_inUpdateScrollbars(false)
143 , m_clipsRepaints(true)
144 , m_frameTimingRequestsDirty(true)
151 PassRefPtrWillBeRawPtr
<FrameView
> FrameView::create(LocalFrame
* frame
)
153 RefPtrWillBeRawPtr
<FrameView
> view
= adoptRefWillBeNoop(new FrameView(frame
));
155 return view
.release();
158 PassRefPtrWillBeRawPtr
<FrameView
> FrameView::create(LocalFrame
* frame
, const IntSize
& initialSize
)
160 RefPtrWillBeRawPtr
<FrameView
> view
= adoptRefWillBeNoop(new FrameView(frame
));
161 view
->Widget::setFrameRect(IntRect(view
->location(), initialSize
));
162 view
->setLayoutSizeInternal(initialSize
);
165 return view
.release();
168 FrameView::~FrameView()
170 ASSERT(m_hasBeenDisposed
);
172 // Verify that the LocalFrame has a different FrameView or
173 // that it is being detached and destructed.
174 ASSERT(frame().view() != this || !layoutView());
178 DEFINE_TRACE(FrameView
)
181 visitor
->trace(m_frame
);
182 visitor
->trace(m_nodeToDraw
);
183 visitor
->trace(m_scrollAnchor
);
184 visitor
->trace(m_scrollableAreas
);
185 visitor
->trace(m_animatingScrollableAreas
);
186 visitor
->trace(m_autoSizeInfo
);
187 visitor
->trace(m_horizontalScrollbar
);
188 visitor
->trace(m_verticalScrollbar
);
189 visitor
->trace(m_children
);
190 visitor
->trace(m_viewportScrollableArea
);
192 Widget::trace(visitor
);
193 ScrollableArea::trace(visitor
);
196 void FrameView::reset()
198 m_hasPendingLayout
= false;
199 m_doFullPaintInvalidation
= false;
200 m_layoutSchedulingEnabled
= true;
201 m_inPerformLayout
= false;
202 m_inSynchronousPostLayout
= false;
204 m_nestedLayoutCount
= 0;
205 m_postLayoutTasksTimer
.stop();
206 m_updateWidgetsTimer
.stop();
207 m_firstLayout
= true;
208 m_safeToPropagateScrollToParent
= true;
209 m_lastViewportSize
= IntSize();
210 m_lastZoomFactor
= 1.0f
;
211 m_isTrackingPaintInvalidations
= s_initialTrackAllPaintInvalidations
;
213 m_isPainting
= false;
214 m_visuallyNonEmptyCharacterCount
= 0;
215 m_visuallyNonEmptyPixelCount
= 0;
216 m_isVisuallyNonEmpty
= false;
218 m_viewportConstrainedObjects
.clear();
219 m_layoutSubtreeRootList
.clear();
222 void FrameView::removeFromAXObjectCache()
224 if (AXObjectCache
* cache
= axObjectCache()) {
226 cache
->childrenChanged(m_frame
->pagePopupOwner());
230 void FrameView::init()
234 m_size
= LayoutSize();
236 // Propagate the marginwidth/height and scrolling modes to the view.
237 // FIXME: Do we need to do this for OOPI?
238 Element
* ownerElement
= m_frame
->deprecatedLocalOwner();
239 if (ownerElement
&& (isHTMLFrameElement(*ownerElement
) || isHTMLIFrameElement(*ownerElement
))) {
240 HTMLFrameElementBase
* frameElt
= toHTMLFrameElementBase(ownerElement
);
241 if (frameElt
->scrollingMode() == ScrollbarAlwaysOff
)
242 setCanHaveScrollbars(false);
246 void FrameView::dispose()
248 RELEASE_ASSERT(!isInPerformLayout());
250 if (ScrollAnimator
* scrollAnimator
= existingScrollAnimator())
251 scrollAnimator
->cancelAnimations();
252 cancelProgrammaticScrollAnimation();
256 // When the view is no longer associated with a frame, it needs to be removed from the ax object cache
257 // right now, otherwise it won't be able to reach the topDocument()'s axObject cache later.
258 removeFromAXObjectCache();
260 if (ScrollingCoordinator
* scrollingCoordinator
= this->scrollingCoordinator())
261 scrollingCoordinator
->willDestroyScrollableArea(this);
263 // Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing
264 // partially destroyed |this| via |m_autoSizeInfo->m_frameView|.
265 m_autoSizeInfo
.clear();
267 if (m_postLayoutTasksTimer
.isActive())
268 m_postLayoutTasksTimer
.stop();
270 if (m_didScrollTimer
.isActive())
271 m_didScrollTimer
.stop();
273 // FIXME: Do we need to do something here for OOPI?
274 HTMLFrameOwnerElement
* ownerElement
= m_frame
->deprecatedLocalOwner();
275 // TODO(dcheng): It seems buggy that we can have an owner element that
276 // points to another Widget.
277 if (ownerElement
&& ownerElement
->ownedWidget() == this)
278 ownerElement
->setWidget(nullptr);
281 m_hasBeenDisposed
= true;
285 void FrameView::detachScrollbars()
287 // Previously, we detached custom scrollbars as early as possible to prevent
288 // Document::detach() from messing with the view such that its scroll bars
289 // won't be torn down. However, scripting in Document::detach() is forbidden
290 // now, so it's not clear if these edge cases can still happen.
291 // However, for Oilpan, we still need to remove the native scrollbars before
292 // we lose the connection to the HostWindow, so we just unconditionally
293 // detach any scrollbars now.
294 setHasHorizontalScrollbar(false);
295 setHasVerticalScrollbar(false);
297 if (m_scrollCorner
) {
298 m_scrollCorner
->destroy();
299 m_scrollCorner
= nullptr;
303 void FrameView::recalculateCustomScrollbarStyle()
305 bool didStyleChange
= false;
306 if (m_horizontalScrollbar
&& m_horizontalScrollbar
->isCustomScrollbar()) {
307 m_horizontalScrollbar
->styleChanged();
308 didStyleChange
= true;
310 if (m_verticalScrollbar
&& m_verticalScrollbar
->isCustomScrollbar()) {
311 m_verticalScrollbar
->styleChanged();
312 didStyleChange
= true;
314 if (didStyleChange
) {
315 updateScrollbarGeometry();
316 updateScrollCorner();
317 positionScrollbarLayers();
321 void FrameView::invalidateAllCustomScrollbarsOnActiveChanged()
323 bool usesWindowInactiveSelector
= m_frame
->document()->styleEngine().usesWindowInactiveSelector();
325 const ChildrenWidgetSet
* viewChildren
= children();
326 for (const RefPtrWillBeMember
<Widget
>& child
: *viewChildren
) {
327 Widget
* widget
= child
.get();
328 if (widget
->isFrameView())
329 toFrameView(widget
)->invalidateAllCustomScrollbarsOnActiveChanged();
330 else if (usesWindowInactiveSelector
&& widget
->isScrollbar() && toScrollbar(widget
)->isCustomScrollbar())
331 toScrollbar(widget
)->styleChanged();
333 if (usesWindowInactiveSelector
)
334 recalculateCustomScrollbarStyle();
337 void FrameView::recalculateScrollbarOverlayStyle()
339 ScrollbarOverlayStyle oldOverlayStyle
= scrollbarOverlayStyle();
340 ScrollbarOverlayStyle overlayStyle
= ScrollbarOverlayStyleDefault
;
342 Color backgroundColor
= documentBackgroundColor();
343 // Reduce the background color from RGB to a lightness value
344 // and determine which scrollbar style to use based on a lightness
346 double hue
, saturation
, lightness
;
347 backgroundColor
.getHSL(hue
, saturation
, lightness
);
349 overlayStyle
= ScrollbarOverlayStyleLight
;
351 if (oldOverlayStyle
!= overlayStyle
)
352 setScrollbarOverlayStyle(overlayStyle
);
355 void FrameView::clear()
358 setScrollbarsSuppressed(true);
361 bool FrameView::didFirstLayout() const
363 return !m_firstLayout
;
366 void FrameView::invalidateRect(const IntRect
& rect
)
368 // For querying DeprecatedPaintLayer::compositingState() when invalidating scrollbars.
369 // FIXME: do all scrollbar invalidations after layout of all frames is complete. It's currently not recursively true.
370 DisableCompositingQueryAsserts disabler
;
372 if (HostWindow
* window
= hostWindow())
373 window
->invalidateRect(rect
);
377 LayoutPart
* layoutObject
= m_frame
->ownerLayoutObject();
381 IntRect paintInvalidationRect
= rect
;
382 paintInvalidationRect
.move(layoutObject
->borderLeft() + layoutObject
->paddingLeft(),
383 layoutObject
->borderTop() + layoutObject
->paddingTop());
384 // FIXME: We should not allow paint invalidation out of paint invalidation state. crbug.com/457415
385 DisablePaintInvalidationStateAsserts paintInvalidationAssertDisabler
;
386 layoutObject
->invalidatePaintRectangle(LayoutRect(paintInvalidationRect
));
389 void FrameView::setFrameRect(const IntRect
& newRect
)
391 IntRect oldRect
= frameRect();
392 if (newRect
== oldRect
)
395 Widget::setFrameRect(newRect
);
397 updateScrollbars(scrollOffsetDouble());
400 updateScrollableAreaSet();
402 if (LayoutView
* layoutView
= this->layoutView()) {
403 if (layoutView
->usesCompositing())
404 layoutView
->compositor()->frameViewDidChangeSize();
407 viewportSizeChanged(newRect
.width() != oldRect
.width(), newRect
.height() != oldRect
.height());
409 if (oldRect
.size() != newRect
.size()) {
410 if (m_frame
->isMainFrame())
411 m_frame
->host()->visualViewport().mainFrameDidChangeSize();
412 frame().loader().restoreScrollPositionAndViewState();
416 Page
* FrameView::page() const
418 return frame().page();
421 LayoutView
* FrameView::layoutView() const
423 return frame().contentLayoutObject();
426 ScrollingCoordinator
* FrameView::scrollingCoordinator()
429 return p
? p
->scrollingCoordinator() : 0;
432 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars
)
434 m_canHaveScrollbars
= canHaveScrollbars
;
436 ScrollbarMode newVerticalMode
= m_verticalScrollbarMode
;
437 if (canHaveScrollbars
&& m_verticalScrollbarMode
== ScrollbarAlwaysOff
)
438 newVerticalMode
= ScrollbarAuto
;
439 else if (!canHaveScrollbars
)
440 newVerticalMode
= ScrollbarAlwaysOff
;
442 ScrollbarMode newHorizontalMode
= m_horizontalScrollbarMode
;
443 if (canHaveScrollbars
&& m_horizontalScrollbarMode
== ScrollbarAlwaysOff
)
444 newHorizontalMode
= ScrollbarAuto
;
445 else if (!canHaveScrollbars
)
446 newHorizontalMode
= ScrollbarAlwaysOff
;
448 setScrollbarModes(newHorizontalMode
, newVerticalMode
);
451 bool FrameView::shouldUseCustomScrollbars(Element
*& customScrollbarElement
, LocalFrame
*& customScrollbarFrame
) const
453 customScrollbarElement
= nullptr;
454 customScrollbarFrame
= nullptr;
456 if (Settings
* settings
= m_frame
->settings()) {
457 if (!settings
->allowCustomScrollbarInMainFrame() && m_frame
->isMainFrame())
461 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
462 Document
* doc
= m_frame
->document();
464 // Try the <body> element first as a scrollbar source.
465 Element
* body
= doc
? doc
->body() : 0;
466 if (body
&& body
->layoutObject() && body
->layoutObject()->style()->hasPseudoStyle(SCROLLBAR
)) {
467 customScrollbarElement
= body
;
471 // If the <body> didn't have a custom style, then the root element might.
472 Element
* docElement
= doc
? doc
->documentElement() : 0;
473 if (docElement
&& docElement
->layoutObject() && docElement
->layoutObject()->style()->hasPseudoStyle(SCROLLBAR
)) {
474 customScrollbarElement
= docElement
;
478 // If we have an owning ipage/LocalFrame element, then it can set the custom scrollbar also.
479 LayoutPart
* frameLayoutObject
= m_frame
->ownerLayoutObject();
480 if (frameLayoutObject
&& frameLayoutObject
->style()->hasPseudoStyle(SCROLLBAR
)) {
481 customScrollbarFrame
= m_frame
.get();
488 PassRefPtrWillBeRawPtr
<Scrollbar
> FrameView::createScrollbar(ScrollbarOrientation orientation
)
490 Element
* customScrollbarElement
= nullptr;
491 LocalFrame
* customScrollbarFrame
= nullptr;
492 if (shouldUseCustomScrollbars(customScrollbarElement
, customScrollbarFrame
))
493 return LayoutScrollbar::createCustomScrollbar(this, orientation
, customScrollbarElement
, customScrollbarFrame
);
495 // Nobody set a custom style, so we just use a native scrollbar.
496 return Scrollbar::create(this, orientation
, RegularScrollbar
);
499 void FrameView::setContentsSize(const IntSize
& size
)
501 if (size
== contentsSize())
504 m_contentsSize
= size
;
505 updateScrollbars(scrollOffsetDouble());
506 ScrollableArea::contentsResized();
508 Page
* page
= frame().page();
512 updateScrollableAreaSet();
514 page
->chromeClient().contentsSizeChanged(m_frame
.get(), size
);
515 frame().loader().restoreScrollPositionAndViewState();
518 void FrameView::adjustViewSize()
520 LayoutView
* layoutView
= this->layoutView();
524 ASSERT(m_frame
->view() == this);
526 const IntRect rect
= layoutView
->documentRect();
527 const IntSize
& size
= rect
.size();
528 setScrollOrigin(IntPoint(-rect
.x(), -rect
.y()), !m_frame
->document()->printing(), size
== contentsSize());
530 setContentsSize(size
);
533 void FrameView::applyOverflowToViewport(LayoutObject
* o
, ScrollbarMode
& hMode
, ScrollbarMode
& vMode
)
535 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
536 // overflow:hidden and overflow:scroll on <body> as applying to the document's
537 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
538 // use the root element.
540 EOverflow overflowX
= o
->style()->overflowX();
541 EOverflow overflowY
= o
->style()->overflowY();
543 if (o
->isSVGRoot()) {
544 // Don't allow overflow to affect <img> and css backgrounds
545 if (toLayoutSVGRoot(o
)->isEmbeddedThroughSVGImage())
548 // FIXME: evaluate if we can allow overflow for these cases too.
549 // Overflow is always hidden when stand-alone SVG documents are embedded.
550 if (toLayoutSVGRoot(o
)->isEmbeddedThroughFrameContainingSVGDocument()) {
558 if (!shouldIgnoreOverflowHidden())
559 hMode
= ScrollbarAlwaysOff
;
562 hMode
= ScrollbarAlwaysOn
;
565 hMode
= ScrollbarAuto
;
568 // Don't set it at all.
574 if (!shouldIgnoreOverflowHidden())
575 vMode
= ScrollbarAlwaysOff
;
578 vMode
= ScrollbarAlwaysOn
;
581 vMode
= ScrollbarAuto
;
584 // Don't set it at all.
589 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode
& hMode
, ScrollbarMode
& vMode
, ScrollbarModesCalculationStrategy strategy
)
591 // FIXME: How do we handle this for OOPI?
592 const HTMLFrameOwnerElement
* owner
= m_frame
->deprecatedLocalOwner();
593 if (owner
&& (owner
->scrollingMode() == ScrollbarAlwaysOff
)) {
594 hMode
= ScrollbarAlwaysOff
;
595 vMode
= ScrollbarAlwaysOff
;
599 if (m_canHaveScrollbars
|| strategy
== RulesFromWebContentOnly
) {
600 hMode
= ScrollbarAuto
;
601 vMode
= ScrollbarAuto
;
603 hMode
= ScrollbarAlwaysOff
;
604 vMode
= ScrollbarAlwaysOff
;
607 if (!isSubtreeLayout()) {
608 Document
* document
= m_frame
->document();
609 Node
* body
= document
->body();
610 if (isHTMLFrameSetElement(body
) && body
->layoutObject()) {
611 vMode
= ScrollbarAlwaysOff
;
612 hMode
= ScrollbarAlwaysOff
;
613 } else if (LayoutObject
* viewport
= viewportLayoutObject()) {
614 if (viewport
->style())
615 applyOverflowToViewport(viewport
, hMode
, vMode
);
620 void FrameView::updateAcceleratedCompositingSettings()
622 if (LayoutView
* layoutView
= this->layoutView())
623 layoutView
->compositor()->updateAcceleratedCompositingSettings();
626 void FrameView::recalcOverflowAfterStyleChange()
628 LayoutView
* layoutView
= this->layoutView();
629 RELEASE_ASSERT(layoutView
);
630 if (!layoutView
->needsOverflowRecalcAfterStyleChange())
633 layoutView
->recalcOverflowAfterStyleChange();
635 // Changing overflow should notify scrolling coordinator to ensures that it
636 // updates non-fast scroll rects even if there is no layout.
637 if (ScrollingCoordinator
* scrollingCoordinator
= this->scrollingCoordinator())
638 scrollingCoordinator
->notifyOverflowUpdated();
640 IntRect documentRect
= layoutView
->documentRect();
641 if (scrollOrigin() == -documentRect
.location() && contentsSize() == documentRect
.size())
647 InUpdateScrollbarsScope
inUpdateScrollbarsScope(this);
649 bool shouldHaveHorizontalScrollbar
= false;
650 bool shouldHaveVerticalScrollbar
= false;
651 computeScrollbarExistence(shouldHaveHorizontalScrollbar
, shouldHaveVerticalScrollbar
, documentRect
.size());
653 bool hasHorizontalScrollbar
= horizontalScrollbar();
654 bool hasVerticalScrollbar
= verticalScrollbar();
655 if (hasHorizontalScrollbar
!= shouldHaveHorizontalScrollbar
656 || hasVerticalScrollbar
!= shouldHaveVerticalScrollbar
) {
662 updateScrollbarGeometry();
665 bool FrameView::usesCompositedScrolling() const
667 LayoutView
* layoutView
= this->layoutView();
670 if (m_frame
->settings() && m_frame
->settings()->preferCompositingToLCDTextEnabled())
671 return layoutView
->compositor()->inCompositingMode();
675 GraphicsLayer
* FrameView::layerForScrolling() const
677 LayoutView
* layoutView
= this->layoutView();
680 return layoutView
->compositor()->frameScrollLayer();
683 GraphicsLayer
* FrameView::layerForHorizontalScrollbar() const
685 LayoutView
* layoutView
= this->layoutView();
688 return layoutView
->compositor()->layerForHorizontalScrollbar();
691 GraphicsLayer
* FrameView::layerForVerticalScrollbar() const
693 LayoutView
* layoutView
= this->layoutView();
696 return layoutView
->compositor()->layerForVerticalScrollbar();
699 GraphicsLayer
* FrameView::layerForScrollCorner() const
701 LayoutView
* layoutView
= this->layoutView();
704 return layoutView
->compositor()->layerForScrollCorner();
707 bool FrameView::isEnclosedInCompositingLayer() const
709 // FIXME: It's a bug that compositing state isn't always up to date when this is called. crbug.com/366314
710 DisableCompositingQueryAsserts disabler
;
712 LayoutObject
* frameOwnerLayoutObject
= m_frame
->ownerLayoutObject();
713 return frameOwnerLayoutObject
&& frameOwnerLayoutObject
->enclosingLayer()->enclosingLayerForPaintInvalidationCrossingFrameBoundaries();
716 void FrameView::countObjectsNeedingLayout(unsigned& needsLayoutObjects
, unsigned& totalObjects
, bool& isSubtree
)
718 needsLayoutObjects
= 0;
720 isSubtree
= isSubtreeLayout();
722 m_layoutSubtreeRootList
.countObjectsNeedingLayout(needsLayoutObjects
, totalObjects
);
724 LayoutSubtreeRootList::countObjectsNeedingLayoutInRoot(layoutView(), needsLayoutObjects
, totalObjects
);
727 inline void FrameView::forceLayoutParentViewIfNeeded()
729 LayoutPart
* ownerLayoutObject
= m_frame
->ownerLayoutObject();
730 if (!ownerLayoutObject
|| !ownerLayoutObject
->frame())
733 LayoutBox
* contentBox
= embeddedContentBox();
737 LayoutSVGRoot
* svgRoot
= toLayoutSVGRoot(contentBox
);
738 if (svgRoot
->everHadLayout() && !svgRoot
->needsLayout())
741 // If the embedded SVG document appears the first time, the ownerLayoutObject has already finished
742 // layout without knowing about the existence of the embedded SVG document, because LayoutReplaced
743 // embeddedContentBox() returns 0, as long as the embedded document isn't loaded yet. Before
744 // bothering to lay out the SVG document, mark the ownerLayoutObject needing layout and ask its
745 // FrameView for a layout. After that the LayoutEmbeddedObject (ownerLayoutObject) carries the
746 // correct size, which LayoutSVGRoot::computeReplacedLogicalWidth/Height rely on, when laying
747 // out for the first time, or when the LayoutSVGRoot size has changed dynamically (eg. via <script>).
748 RefPtrWillBeRawPtr
<FrameView
> frameView
= ownerLayoutObject
->frame()->view();
750 // Mark the owner layoutObject as needing layout.
751 ownerLayoutObject
->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::Unknown
);
753 // Synchronously enter layout, to layout the view containing the host object/embed/iframe.
758 void FrameView::performPreLayoutTasks()
760 TRACE_EVENT0("blink,benchmark", "FrameView::performPreLayoutTasks");
761 lifecycle().advanceTo(DocumentLifecycle::InPreLayout
);
763 // Don't schedule more layouts, we're in one.
764 TemporaryChange
<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled
, false);
766 if (!m_nestedLayoutCount
&& !m_inSynchronousPostLayout
&& m_postLayoutTasksTimer
.isActive()) {
767 // This is a new top-level layout. If there are any remaining tasks from the previous layout, finish them now.
768 m_inSynchronousPostLayout
= true;
769 performPostLayoutTasks();
770 m_inSynchronousPostLayout
= false;
773 bool wasResized
= wasViewportResized();
774 Document
* document
= m_frame
->document();
776 // Viewport-dependent media queries may cause us to need completely different style information.
777 if (!document
->styleResolver() || (wasResized
&& document
->styleResolver()->mediaQueryAffectedByViewportChange())) {
778 document
->mediaQueryAffectingValueChanged();
779 } else if (wasResized
) {
780 document
->evaluateMediaQueryList();
783 document
->updateLayoutTreeIfNeeded();
784 lifecycle().advanceTo(DocumentLifecycle::StyleClean
);
786 if (m_frame
->isMainFrame() && !m_viewportScrollableArea
) {
787 ScrollableArea
& visualViewport
= m_frame
->host()->visualViewport();
788 ScrollableArea
* layoutViewport
= layoutViewportScrollableArea();
789 bool invertScrollOrder
= m_frame
->settings()->invertViewportScrollOrder();
790 ASSERT(layoutViewport
);
791 m_viewportScrollableArea
= RootFrameViewport::create(visualViewport
, *layoutViewport
, invertScrollOrder
);
795 static inline void layoutFromRootObject(LayoutObject
& root
)
797 LayoutState
layoutState(root
);
801 void FrameView::prepareLayoutAnalyzer()
803 bool isTracing
= false;
804 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("blink.debug.layout"), &isTracing
);
810 m_analyzer
= adoptPtr(new LayoutAnalyzer());
814 PassRefPtr
<TracedValue
> FrameView::analyzerCounters()
817 return TracedValue::create();
818 RefPtr
<TracedValue
> value
= m_analyzer
->toTracedValue();
819 value
->setString("host", layoutView()->document().location()->host());
823 #define PERFORM_LAYOUT_TRACE_CATEGORIES "blink,benchmark," TRACE_DISABLED_BY_DEFAULT("blink.debug.layout")
825 void FrameView::performLayout(bool inSubtreeLayout
)
827 ASSERT(inSubtreeLayout
|| m_layoutSubtreeRootList
.isEmpty());
829 TRACE_EVENT_BEGIN0(PERFORM_LAYOUT_TRACE_CATEGORIES
, "FrameView::performLayout");
830 prepareLayoutAnalyzer();
832 ScriptForbiddenScope forbidScript
;
834 ASSERT(!isInPerformLayout());
835 lifecycle().advanceTo(DocumentLifecycle::InPerformLayout
);
837 TemporaryChange
<bool> changeInPerformLayout(m_inPerformLayout
, true);
839 // performLayout is the actual guts of layout().
840 // FIXME: The 300 other lines in layout() probably belong in other helper functions
841 // so that a single human could understand what layout() is actually doing.
843 forceLayoutParentViewIfNeeded();
845 if (inSubtreeLayout
) {
847 m_analyzer
->increment(LayoutAnalyzer::PerformLayoutRootLayoutObjects
, m_layoutSubtreeRootList
.size());
848 while (LayoutObject
* root
= m_layoutSubtreeRootList
.takeDeepestRoot()) {
849 if (!root
->needsLayout())
851 layoutFromRootObject(*root
);
853 // We need to ensure that we mark up all layoutObjects up to the LayoutView
854 // for paint invalidation. This simplifies our code as we just always
855 // do a full tree walk.
856 if (LayoutObject
* container
= root
->container())
857 container
->setMayNeedPaintInvalidation();
860 layoutFromRootObject(*layoutView());
863 ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->updateAllImageResourcePriorities();
865 lifecycle().advanceTo(DocumentLifecycle::AfterPerformLayout
);
867 TRACE_EVENT_END1(PERFORM_LAYOUT_TRACE_CATEGORIES
, "FrameView::performLayout",
868 "counters", analyzerCounters());
871 void FrameView::scheduleOrPerformPostLayoutTasks()
873 if (m_postLayoutTasksTimer
.isActive())
876 if (!m_inSynchronousPostLayout
) {
877 m_inSynchronousPostLayout
= true;
878 // Calls resumeScheduledEvents()
879 performPostLayoutTasks();
880 m_inSynchronousPostLayout
= false;
883 if (!m_postLayoutTasksTimer
.isActive() && (needsLayout() || m_inSynchronousPostLayout
)) {
884 // If we need layout or are already in a synchronous call to postLayoutTasks(),
885 // defer widget updates and event dispatch until after we return. postLayoutTasks()
886 // can make us need to update again, and we can get stuck in a nasty cycle unless
887 // we call it through the timer here.
888 m_postLayoutTasksTimer
.startOneShot(0, FROM_HERE
);
894 void FrameView::layout()
896 // We should never layout a Document which is not in a LocalFrame.
898 ASSERT(m_frame
->view() == this);
899 ASSERT(m_frame
->page());
901 ScriptForbiddenScope forbidScript
;
903 if (isInPerformLayout() || !m_frame
->document()->isActive())
906 TRACE_EVENT0("blink,benchmark", "FrameView::layout");
907 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "Layout");
909 // Protect the view from being deleted during layout (in recalcStyle)
910 RefPtrWillBeRawPtr
<FrameView
> protector(this);
913 m_autoSizeInfo
->autoSizeIfNeeded();
915 m_hasPendingLayout
= false;
916 DocumentLifecycle::Scope
lifecycleScope(lifecycle(), DocumentLifecycle::LayoutClean
);
918 RELEASE_ASSERT(!isPainting());
920 TRACE_EVENT_BEGIN1("devtools.timeline", "Layout", "beginData", InspectorLayoutEvent::beginData(this));
922 performPreLayoutTasks();
925 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
926 // so there's no point to continuing to layout
927 if (protector
->hasOneRef())
931 Document
* document
= m_frame
->document();
933 // If the layout view was marked as needing layout after we added items in the subtree roots we need
934 // to clear the roots and do the layout from the layoutView.
935 if (layoutView()->needsLayout())
936 clearLayoutSubtreeRootsAndMarkContainingBlocks();
937 layoutView()->clearHitTestCache();
939 bool inSubtreeLayout
= isSubtreeLayout();
941 // FIXME: The notion of a single root for layout is no longer applicable. Remove or update this code. crbug.com/460596
942 LayoutObject
* rootForThisLayout
= inSubtreeLayout
? m_layoutSubtreeRootList
.randomRoot() : layoutView();
943 if (!rootForThisLayout
) {
944 // FIXME: Do we need to set m_size here?
945 ASSERT_NOT_REACHED();
949 FontCachePurgePreventer fontCachePurgePreventer
;
951 TemporaryChange
<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled
, false);
953 m_nestedLayoutCount
++;
954 if (!inSubtreeLayout
) {
955 clearLayoutSubtreeRootsAndMarkContainingBlocks();
956 Node
* body
= document
->body();
957 if (body
&& body
->layoutObject()) {
958 if (isHTMLFrameSetElement(*body
)) {
959 body
->layoutObject()->setChildNeedsLayout();
960 } else if (isHTMLBodyElement(*body
)) {
961 if (!m_firstLayout
&& m_size
.height() != layoutSize().height() && body
->layoutObject()->enclosingBox()->stretchesToViewport())
962 body
->layoutObject()->setChildNeedsLayout();
970 calculateScrollbarModesForLayout(hMode
, vMode
);
972 if (!inSubtreeLayout
) {
973 // Now set our scrollbar state for the layout.
974 ScrollbarMode currentHMode
= horizontalScrollbarMode();
975 ScrollbarMode currentVMode
= verticalScrollbarMode();
978 setScrollbarsSuppressed(true);
980 m_doFullPaintInvalidation
= true;
981 m_firstLayout
= false;
982 m_lastViewportSize
= layoutSize(IncludeScrollbars
);
983 m_lastZoomFactor
= layoutView()->style()->zoom();
985 // Set the initial vMode to AlwaysOn if we're auto.
986 if (vMode
== ScrollbarAuto
)
987 setVerticalScrollbarMode(ScrollbarAlwaysOn
); // This causes a vertical scrollbar to appear.
988 // Set the initial hMode to AlwaysOff if we're auto.
989 if (hMode
== ScrollbarAuto
)
990 setHorizontalScrollbarMode(ScrollbarAlwaysOff
); // This causes a horizontal scrollbar to disappear.
992 setScrollbarModes(hMode
, vMode
);
993 setScrollbarsSuppressed(false, true);
994 } else if (hMode
!= currentHMode
|| vMode
!= currentVMode
) {
995 setScrollbarModes(hMode
, vMode
);
998 if (needsScrollbarReconstruction())
999 updateScrollbars(scrollOffsetDouble());
1001 LayoutSize oldSize
= m_size
;
1003 m_size
= LayoutSize(layoutSize().width(), layoutSize().height());
1005 if (oldSize
!= m_size
&& !m_firstLayout
) {
1006 LayoutBox
* rootLayoutObject
= document
->documentElement() ? document
->documentElement()->layoutBox() : 0;
1007 LayoutBox
* bodyLayoutObject
= rootLayoutObject
&& document
->body() ? document
->body()->layoutBox() : 0;
1008 if (bodyLayoutObject
&& bodyLayoutObject
->stretchesToViewport())
1009 bodyLayoutObject
->setChildNeedsLayout();
1010 else if (rootLayoutObject
&& rootLayoutObject
->stretchesToViewport())
1011 rootLayoutObject
->setChildNeedsLayout();
1014 // We need to set m_doFullPaintInvalidation before triggering layout as LayoutObject::checkForPaintInvalidation
1015 // checks the boolean to disable local paint invalidations.
1016 m_doFullPaintInvalidation
|= layoutView()->shouldDoFullPaintInvalidationForNextLayout();
1019 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink.debug.layout"), "LayoutTree",
1020 this, TracedLayoutObject::create(*layoutView(), false));
1022 performLayout(inSubtreeLayout
);
1024 ASSERT(m_layoutSubtreeRootList
.isEmpty());
1025 } // Reset m_layoutSchedulingEnabled to its previous value.
1027 if (!inSubtreeLayout
&& !document
->printing())
1030 m_frameTimingRequestsDirty
= true;
1032 // FIXME: Could find the common ancestor layer of all dirty subtrees and mark from there. crbug.com/462719
1033 layoutView()->enclosingLayer()->updateLayerPositionsAfterLayout();
1035 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink.debug.layout"), "LayoutTree",
1036 this, TracedLayoutObject::create(*layoutView(), true));
1038 layoutView()->compositor()->didLayout();
1042 if (AXObjectCache
* cache
= document
->axObjectCache()) {
1043 const KURL
& url
= document
->url();
1044 if (url
.isValid() && !url
.isAboutBlankURL())
1045 cache
->handleLayoutComplete(document
);
1047 updateAnnotatedRegions();
1049 scheduleOrPerformPostLayoutTasks();
1051 // FIXME: The notion of a single root for layout is no longer applicable. Remove or update this code. crbug.com/460596
1052 TRACE_EVENT_END1("devtools.timeline", "Layout", "endData", InspectorLayoutEvent::endData(rootForThisLayout
));
1053 InspectorInstrumentation::didUpdateLayout(m_frame
.get());
1055 m_nestedLayoutCount
--;
1056 if (m_nestedLayoutCount
)
1060 // Post-layout assert that nobody was re-marked as needing layout during layout.
1061 layoutView()->assertSubtreeIsLaidOut();
1064 // Ensure that we become visually non-empty eventually.
1065 // TODO(esprehn): This should check isRenderingReady() instead.
1066 if (!frame().document()->parsing() && frame().loader().stateMachine()->committedFirstRealDocumentLoad())
1067 m_isVisuallyNonEmpty
= true;
1069 // FIXME: It should be not possible to remove the FrameView from the frame/page during layout
1070 // however m_inPerformLayout is not set for most of this function, so none of our RELEASE_ASSERTS
1071 // in LocalFrame/Page will fire. One of the post-layout tasks is disconnecting the LocalFrame from
1072 // the page in fast/frames/crash-remove-iframe-during-object-beforeload-2.html
1073 // necessitating this check here.
1074 // ASSERT(frame()->page());
1076 frame().page()->chromeClient().layoutUpdated(m_frame
.get());
1078 frame().document()->layoutUpdated();
1081 // The plan is to move to compositor-queried paint invalidation, in which case this
1082 // method would setNeedsRedraw on the GraphicsLayers with invalidations and
1083 // let the compositor pick which to actually draw.
1084 // See http://crbug.com/306706
1085 void FrameView::invalidateTreeIfNeeded(PaintInvalidationState
& paintInvalidationState
)
1087 lifecycle().advanceTo(DocumentLifecycle::InPaintInvalidation
);
1089 ASSERT(layoutView());
1090 LayoutView
& rootForPaintInvalidation
= *layoutView();
1091 ASSERT(!rootForPaintInvalidation
.needsLayout());
1093 TRACE_EVENT1("blink", "FrameView::invalidateTree", "root", rootForPaintInvalidation
.debugName().ascii());
1095 rootForPaintInvalidation
.invalidateTreeIfNeeded(paintInvalidationState
);
1097 // Invalidate the paint of the frameviews scrollbars if needed
1098 if (hasVerticalBarDamage())
1099 invalidateRect(verticalBarDamage());
1100 if (hasHorizontalBarDamage())
1101 invalidateRect(horizontalBarDamage());
1102 resetScrollbarDamage();
1105 layoutView()->assertSubtreeClearedPaintInvalidationState();
1108 if (m_frame
->selection().isCaretBoundsDirty())
1109 m_frame
->selection().invalidateCaretRect();
1111 m_doFullPaintInvalidation
= false;
1112 lifecycle().advanceTo(DocumentLifecycle::PaintInvalidationClean
);
1115 DocumentLifecycle
& FrameView::lifecycle() const
1117 return m_frame
->document()->lifecycle();
1120 LayoutBox
* FrameView::embeddedContentBox() const
1122 LayoutView
* layoutView
= this->layoutView();
1126 LayoutObject
* firstChild
= layoutView
->firstChild();
1127 if (!firstChild
|| !firstChild
->isBox())
1130 // Curently only embedded SVG documents participate in the size-negotiation logic.
1131 if (firstChild
->isSVGRoot())
1132 return toLayoutBox(firstChild
);
1138 void FrameView::addPart(LayoutPart
* object
)
1140 m_parts
.add(object
);
1143 void FrameView::removePart(LayoutPart
* object
)
1145 m_parts
.remove(object
);
1148 void FrameView::updateWidgetPositions()
1150 Vector
<RefPtr
<LayoutPart
>> parts
;
1151 copyToVector(m_parts
, parts
);
1153 // Script or plugins could detach the frame so abort processing if that happens.
1155 for (size_t i
= 0; i
< parts
.size() && layoutView(); ++i
)
1156 parts
[i
]->updateWidgetPosition();
1158 for (size_t i
= 0; i
< parts
.size() && layoutView(); ++i
)
1159 parts
[i
]->widgetPositionsUpdated();
1162 void FrameView::addPartToUpdate(LayoutEmbeddedObject
& object
)
1164 ASSERT(isInPerformLayout());
1165 // Tell the DOM element that it needs a widget update.
1166 Node
* node
= object
.node();
1168 if (isHTMLObjectElement(*node
) || isHTMLEmbedElement(*node
))
1169 toHTMLPlugInElement(node
)->setNeedsWidgetUpdate(true);
1171 m_partUpdateSet
.add(&object
);
1174 void FrameView::setDisplayMode(WebDisplayMode mode
)
1176 if (mode
== m_displayMode
)
1179 m_displayMode
= mode
;
1181 if (m_frame
->document())
1182 m_frame
->document()->mediaQueryAffectingValueChanged();
1185 void FrameView::setMediaType(const AtomicString
& mediaType
)
1187 ASSERT(m_frame
->document());
1188 m_frame
->document()->mediaQueryAffectingValueChanged();
1189 m_mediaType
= mediaType
;
1192 AtomicString
FrameView::mediaType() const
1194 // See if we have an override type.
1195 if (m_frame
->settings() && !m_frame
->settings()->mediaTypeOverride().isEmpty())
1196 return AtomicString(m_frame
->settings()->mediaTypeOverride());
1200 void FrameView::adjustMediaTypeForPrinting(bool printing
)
1203 if (m_mediaTypeWhenNotPrinting
.isNull())
1204 m_mediaTypeWhenNotPrinting
= mediaType();
1205 setMediaType(MediaTypeNames::print
);
1207 if (!m_mediaTypeWhenNotPrinting
.isNull())
1208 setMediaType(m_mediaTypeWhenNotPrinting
);
1209 m_mediaTypeWhenNotPrinting
= nullAtom
;
1213 bool FrameView::contentsInCompositedLayer() const
1215 LayoutView
* layoutView
= this->layoutView();
1216 return layoutView
&& layoutView
->compositingState() == PaintsIntoOwnBacking
;
1219 void FrameView::addSlowRepaintObject()
1221 if (!m_slowRepaintObjectCount
++) {
1222 if (ScrollingCoordinator
* scrollingCoordinator
= this->scrollingCoordinator())
1223 scrollingCoordinator
->frameViewHasSlowRepaintObjectsDidChange(this);
1227 void FrameView::removeSlowRepaintObject()
1229 ASSERT(m_slowRepaintObjectCount
> 0);
1230 m_slowRepaintObjectCount
--;
1231 if (!m_slowRepaintObjectCount
) {
1232 if (ScrollingCoordinator
* scrollingCoordinator
= this->scrollingCoordinator())
1233 scrollingCoordinator
->frameViewHasSlowRepaintObjectsDidChange(this);
1237 void FrameView::addViewportConstrainedObject(LayoutObject
* object
)
1239 if (!m_viewportConstrainedObjects
)
1240 m_viewportConstrainedObjects
= adoptPtr(new ViewportConstrainedObjectSet
);
1242 if (!m_viewportConstrainedObjects
->contains(object
)) {
1243 m_viewportConstrainedObjects
->add(object
);
1245 if (ScrollingCoordinator
* scrollingCoordinator
= this->scrollingCoordinator())
1246 scrollingCoordinator
->frameViewFixedObjectsDidChange(this);
1250 void FrameView::removeViewportConstrainedObject(LayoutObject
* object
)
1252 if (m_viewportConstrainedObjects
&& m_viewportConstrainedObjects
->contains(object
)) {
1253 m_viewportConstrainedObjects
->remove(object
);
1255 if (ScrollingCoordinator
* scrollingCoordinator
= this->scrollingCoordinator())
1256 scrollingCoordinator
->frameViewFixedObjectsDidChange(this);
1260 void FrameView::viewportSizeChanged(bool widthChanged
, bool heightChanged
)
1262 if (!hasViewportConstrainedObjects())
1265 for (const auto& viewportConstrainedObject
: *m_viewportConstrainedObjects
) {
1266 LayoutObject
* layoutObject
= viewportConstrainedObject
;
1267 const ComputedStyle
& style
= layoutObject
->styleRef();
1269 if (style
.width().isFixed() && (style
.left().isAuto() || style
.right().isAuto()))
1270 layoutObject
->setNeedsPositionedMovementLayout();
1272 layoutObject
->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::SizeChanged
);
1274 if (heightChanged
) {
1275 if (style
.height().isFixed() && (style
.top().isAuto() || style
.bottom().isAuto()))
1276 layoutObject
->setNeedsPositionedMovementLayout();
1278 layoutObject
->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::SizeChanged
);
1283 IntPoint
FrameView::lastKnownMousePosition() const
1285 return m_frame
->eventHandler().lastKnownMousePosition();
1288 bool FrameView::shouldSetCursor() const
1290 Page
* page
= frame().page();
1291 return page
&& page
->visibilityState() != PageVisibilityStateHidden
&& page
->focusController().isActive() && page
->settings().deviceSupportsMouse();
1294 void FrameView::scrollContentsIfNeededRecursive()
1296 scrollContentsIfNeeded();
1298 for (Frame
* child
= m_frame
->tree().firstChild(); child
; child
= child
->tree().nextSibling()) {
1299 if (!child
->isLocalFrame())
1301 if (FrameView
* view
= toLocalFrame(child
)->view())
1302 view
->scrollContentsIfNeededRecursive();
1306 bool FrameView::invalidateViewportConstrainedObjects()
1308 for (const auto& viewportConstrainedObject
: *m_viewportConstrainedObjects
) {
1309 LayoutObject
* layoutObject
= viewportConstrainedObject
;
1310 ASSERT(layoutObject
->style()->hasViewportConstrainedPosition());
1311 ASSERT(layoutObject
->hasLayer());
1312 DeprecatedPaintLayer
* layer
= toLayoutBoxModelObject(layoutObject
)->layer();
1314 if (layer
->isPaintInvalidationContainer())
1317 if (layer
->subtreeIsInvisible())
1320 // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot
1321 // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
1322 if (layer
->hasAncestorWithFilterOutsets())
1325 TRACE_EVENT_INSTANT1(
1326 TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"),
1327 "ScrollInvalidationTracking",
1328 TRACE_EVENT_SCOPE_THREAD
,
1330 InspectorScrollInvalidationTrackingEvent::data(*layoutObject
));
1332 layoutObject
->setShouldDoFullPaintInvalidationIncludingNonCompositingDescendants();
1337 bool FrameView::scrollContentsFastPath(const IntSize
& scrollDelta
)
1339 if (!contentsInCompositedLayer() || hasSlowRepaintObjects())
1342 if (!m_viewportConstrainedObjects
|| m_viewportConstrainedObjects
->isEmpty()) {
1343 InspectorInstrumentation::didUpdateLayout(m_frame
.get());
1347 if (!invalidateViewportConstrainedObjects())
1350 InspectorInstrumentation::didUpdateLayout(m_frame
.get());
1354 void FrameView::scrollContentsSlowPath(const IntRect
& updateRect
)
1356 TRACE_EVENT0("blink", "FrameView::scrollContentsSlowPath");
1357 // We need full invalidation during slow scrolling. For slimming paint, full invalidation
1358 // of the LayoutView is not enough. We also need to invalidate all of the objects.
1359 // FIXME: Find out what are enough to invalidate in slow path scrolling. crbug.com/451090#9.
1360 ASSERT(layoutView());
1361 if (contentsInCompositedLayer())
1362 layoutView()->layer()->compositedDeprecatedPaintLayerMapping()->setContentsNeedDisplay();
1364 layoutView()->setShouldDoFullPaintInvalidationIncludingNonCompositingDescendants();
1367 if (contentsInCompositedLayer()) {
1368 IntRect updateRect
= visibleContentRect();
1369 ASSERT(layoutView());
1370 // FIXME: We should not allow paint invalidation out of paint invalidation state. crbug.com/457415
1371 DisablePaintInvalidationStateAsserts disabler
;
1372 layoutView()->invalidatePaintRectangle(LayoutRect(updateRect
));
1374 if (LayoutPart
* frameLayoutObject
= m_frame
->ownerLayoutObject()) {
1375 if (isEnclosedInCompositingLayer()) {
1376 LayoutRect
rect(frameLayoutObject
->borderLeft() + frameLayoutObject
->paddingLeft(),
1377 frameLayoutObject
->borderTop() + frameLayoutObject
->paddingTop(),
1378 visibleWidth(), visibleHeight());
1379 // FIXME: We should not allow paint invalidation out of paint invalidation state. crbug.com/457415
1380 DisablePaintInvalidationStateAsserts disabler
;
1381 frameLayoutObject
->invalidatePaintRectangle(rect
);
1386 hostWindow()->invalidateRect(updateRect
);
1389 void FrameView::restoreScrollbar()
1391 setScrollbarsSuppressed(false);
1394 bool FrameView::processUrlFragment(const KURL
& url
, UrlFragmentBehavior behavior
)
1396 // If our URL has no ref, then we have no place we need to jump to.
1397 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1398 // and possibly paint invalidation because :target pseudo class may have been
1399 // set (see bug 11321).
1400 // Similarly for svg, if we had a previous svgView() then we need to reset
1401 // the initial view if we don't have a fragment.
1402 if (!url
.hasFragmentIdentifier() && !m_frame
->document()->cssTarget() && !m_frame
->document()->isSVGDocument())
1405 String fragmentIdentifier
= url
.fragmentIdentifier();
1406 if (processUrlFragmentHelper(fragmentIdentifier
, behavior
))
1409 // Try again after decoding the ref, based on the document's encoding.
1410 if (m_frame
->document()->encoding().isValid())
1411 return processUrlFragmentHelper(decodeURLEscapeSequences(fragmentIdentifier
, m_frame
->document()->encoding()), behavior
);
1416 bool FrameView::processUrlFragmentHelper(const String
& name
, UrlFragmentBehavior behavior
)
1418 ASSERT(m_frame
->document());
1420 if (behavior
== UrlFragmentScroll
&& !m_frame
->document()->isRenderingReady()) {
1421 m_frame
->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1425 m_frame
->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1427 Element
* anchorNode
= m_frame
->document()->findAnchor(name
);
1429 // Setting to null will clear the current target.
1430 m_frame
->document()->setCSSTarget(anchorNode
);
1432 if (m_frame
->document()->isSVGDocument()) {
1433 if (SVGSVGElement
* svg
= SVGDocumentExtensions::rootElement(*m_frame
->document())) {
1434 svg
->setupInitialView(name
, anchorNode
);
1440 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1441 if (!anchorNode
&& !(name
.isEmpty() || equalIgnoringCase(name
, "top")))
1444 if (behavior
== UrlFragmentScroll
)
1445 maintainScrollPositionAtAnchor(anchorNode
? static_cast<Node
*>(anchorNode
) : m_frame
->document());
1447 // If the anchor accepts keyboard focus, move focus there to aid users relying on keyboard navigation.
1448 // If anchorNode is not focusable, setFocusedElement() will still clear focus, which matches the behavior of other browsers.
1450 m_frame
->document()->setFocusedElement(anchorNode
);
1455 void FrameView::maintainScrollPositionAtAnchor(Node
* anchorNode
)
1458 m_scrollAnchor
= anchorNode
;
1460 // We need to update the layout tree before scrolling.
1461 m_frame
->document()->updateLayoutTreeIfNeeded();
1463 // If layout is needed, we will scroll in performPostLayoutTasks. Otherwise, scroll immediately.
1464 LayoutView
* layoutView
= this->layoutView();
1465 if (layoutView
&& layoutView
->needsLayout())
1471 void FrameView::clearScrollAnchor()
1473 m_scrollAnchor
= nullptr;
1476 void FrameView::setScrollPosition(const DoublePoint
& scrollPoint
, ScrollType scrollType
, ScrollBehavior scrollBehavior
)
1478 DoublePoint newScrollPosition
= clampScrollPosition(scrollPoint
);
1479 if (newScrollPosition
== scrollPositionDouble())
1482 if (scrollBehavior
== ScrollBehaviorAuto
)
1483 scrollBehavior
= scrollBehaviorStyle();
1485 ScrollableArea::setScrollPosition(newScrollPosition
, scrollType
, scrollBehavior
);
1488 void FrameView::didUpdateElasticOverscroll()
1490 Page
* page
= frame().page();
1493 FloatSize elasticOverscroll
= page
->chromeClient().elasticOverscroll();
1494 if (m_horizontalScrollbar
) {
1495 float delta
= elasticOverscroll
.width() - m_horizontalScrollbar
->elasticOverscroll();
1497 m_horizontalScrollbar
->setElasticOverscroll(elasticOverscroll
.width());
1498 scrollAnimator()->notifyContentAreaScrolled(FloatSize(delta
, 0));
1499 if (!m_scrollbarsSuppressed
)
1500 m_horizontalScrollbar
->invalidate();
1503 if (m_verticalScrollbar
) {
1504 float delta
= elasticOverscroll
.height() - m_verticalScrollbar
->elasticOverscroll();
1506 m_verticalScrollbar
->setElasticOverscroll(elasticOverscroll
.height());
1507 scrollAnimator()->notifyContentAreaScrolled(FloatSize(0, delta
));
1508 if (!m_scrollbarsSuppressed
)
1509 m_verticalScrollbar
->invalidate();
1514 IntSize
FrameView::layoutSize(IncludeScrollbarsInRect scrollbarInclusion
) const
1516 return scrollbarInclusion
== ExcludeScrollbars
? excludeScrollbars(m_layoutSize
) : m_layoutSize
;
1519 void FrameView::setLayoutSize(const IntSize
& size
)
1521 ASSERT(!layoutSizeFixedToFrameSize());
1523 setLayoutSizeInternal(size
);
1526 void FrameView::scrollPositionChanged()
1528 Document
* document
= m_frame
->document();
1529 document
->enqueueScrollEventForNode(document
);
1531 m_frame
->eventHandler().dispatchFakeMouseMoveEventSoon();
1533 if (LayoutView
* layoutView
= document
->layoutView()) {
1534 if (layoutView
->usesCompositing())
1535 layoutView
->compositor()->frameViewDidScroll();
1538 if (m_didScrollTimer
.isActive())
1539 m_didScrollTimer
.stop();
1540 m_didScrollTimer
.startOneShot(resourcePriorityUpdateDelayAfterScroll
, FROM_HERE
);
1542 if (AXObjectCache
* cache
= m_frame
->document()->existingAXObjectCache())
1543 cache
->handleScrollPositionChanged(this);
1545 layoutView()->clearHitTestCache();
1546 frame().loader().saveScrollState();
1549 void FrameView::didScrollTimerFired(Timer
<FrameView
>*)
1551 if (m_frame
->document() && m_frame
->document()->layoutView()) {
1552 ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->updateAllImageResourcePriorities();
1556 void FrameView::updateLayersAndCompositingAfterScrollIfNeeded()
1558 // Nothing to do after scrolling if there are no fixed position elements.
1559 if (!hasViewportConstrainedObjects())
1562 RefPtrWillBeRawPtr
<FrameView
> protect(this);
1564 // If there fixed position elements, scrolling may cause compositing layers to change.
1565 // Update widget and layer positions after scrolling, but only if we're not inside of
1567 if (!m_nestedLayoutCount
) {
1568 updateWidgetPositions();
1569 if (LayoutView
* layoutView
= this->layoutView())
1570 layoutView
->layer()->setNeedsCompositingInputsUpdate();
1574 bool FrameView::computeCompositedSelection(LocalFrame
& frame
, CompositedSelection
& selection
)
1576 const VisibleSelection
& visibleSelection
= frame
.selection().selection();
1577 if (!visibleSelection
.isCaretOrRange())
1580 // Non-editable caret selections lack any kind of UI affordance, and
1581 // needn't be tracked by the client.
1582 if (visibleSelection
.isCaret() && !visibleSelection
.isContentEditable())
1585 VisiblePosition
visibleStart(visibleSelection
.visibleStart());
1586 RenderedPosition
renderedStart(visibleStart
);
1587 renderedStart
.positionInGraphicsLayerBacking(selection
.start
);
1588 if (!selection
.start
.layer
)
1591 if (visibleSelection
.isCaret()) {
1592 selection
.end
= selection
.start
;
1594 VisiblePosition
visibleEnd(visibleSelection
.visibleEnd());
1595 RenderedPosition
renderedEnd(visibleEnd
);
1596 renderedEnd
.positionInGraphicsLayerBacking(selection
.end
);
1597 if (!selection
.end
.layer
)
1601 selection
.type
= visibleSelection
.selectionType();
1602 selection
.isEditable
= visibleSelection
.isContentEditable();
1603 if (selection
.isEditable
) {
1604 if (HTMLTextFormControlElement
* enclosingTextFormControlElement
= enclosingTextFormControl(visibleSelection
.rootEditableElement()))
1605 selection
.isEmptyTextFormControl
= enclosingTextFormControlElement
->value().isEmpty();
1607 selection
.start
.isTextDirectionRTL
= primaryDirectionOf(*visibleSelection
.start().anchorNode()) == RTL
;
1608 selection
.end
.isTextDirectionRTL
= primaryDirectionOf(*visibleSelection
.end().anchorNode()) == RTL
;
1613 void FrameView::updateCompositedSelectionIfNeeded()
1615 if (!RuntimeEnabledFeatures::compositedSelectionUpdateEnabled())
1618 TRACE_EVENT0("blink", "FrameView::updateCompositedSelectionIfNeeded");
1620 Page
* page
= frame().page();
1623 CompositedSelection selection
;
1624 Frame
* focusedFrame
= page
->focusController().focusedOrMainFrame();
1625 LocalFrame
* localFrame
= focusedFrame
->isLocalFrame() ? toLocalFrame(focusedFrame
) : nullptr;
1626 if (!localFrame
|| !computeCompositedSelection(*localFrame
, selection
)) {
1627 page
->chromeClient().clearCompositedSelection();
1631 page
->chromeClient().updateCompositedSelection(selection
);
1634 HostWindow
* FrameView::hostWindow() const
1636 Page
* page
= frame().page();
1639 return &page
->chromeClient();
1642 void FrameView::contentRectangleForPaintInvalidation(const IntRect
& rectInContent
)
1644 ASSERT(!m_frame
->ownerLayoutObject());
1646 IntRect paintRect
= rectInContent
;
1647 if (clipsPaintInvalidations())
1648 paintRect
.intersect(visibleContentRect());
1649 if (paintRect
.isEmpty())
1652 if (HostWindow
* window
= hostWindow())
1653 window
->invalidateRect(contentsToRootFrame(paintRect
));
1656 void FrameView::contentsResized()
1658 if (m_frame
->isMainFrame() && m_frame
->document()) {
1659 if (TextAutosizer
* textAutosizer
= m_frame
->document()->textAutosizer())
1660 textAutosizer
->updatePageInfoInAllFrames();
1663 ScrollableArea::contentsResized();
1667 void FrameView::scrollbarExistenceDidChange()
1669 // We check to make sure the view is attached to a frame() as this method can
1670 // be triggered before the view is attached by LocalFrame::createView(...) setting
1671 // various values such as setScrollBarModes(...) for example. An ASSERT is
1672 // triggered when a view is layout before being attached to a frame().
1673 if (!frame().view())
1676 bool hasOverlayScrollbars
= this->hasOverlayScrollbars();
1678 // FIXME: this call to layout() could be called within FrameView::layout(), but before performLayout(),
1679 // causing double-layout. See also crbug.com/429242.
1680 if (!hasOverlayScrollbars
&& needsLayout())
1683 if (layoutView() && layoutView()->usesCompositing()) {
1684 layoutView()->compositor()->frameViewScrollbarsExistenceDidChange();
1686 if (!hasOverlayScrollbars
)
1687 layoutView()->compositor()->frameViewDidChangeSize();
1691 void FrameView::handleLoadCompleted()
1693 // Once loading has completed, allow autoSize one last opportunity to
1694 // reduce the size of the frame.
1696 m_autoSizeInfo
->autoSizeIfNeeded();
1698 // If there is a pending layout, the scroll anchor will be cleared when it finishes.
1700 clearScrollAnchor();
1703 void FrameView::clearLayoutSubtreeRoot(const LayoutObject
& root
)
1705 m_layoutSubtreeRootList
.removeRoot(const_cast<LayoutObject
&>(root
));
1708 void FrameView::clearLayoutSubtreeRootsAndMarkContainingBlocks()
1710 m_layoutSubtreeRootList
.clearAndMarkContainingBlocksForLayout();
1713 void FrameView::scheduleRelayout()
1715 ASSERT(m_frame
->view() == this);
1717 if (!m_layoutSchedulingEnabled
)
1721 if (!m_frame
->document()->shouldScheduleLayout())
1723 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "InvalidateLayout", TRACE_EVENT_SCOPE_THREAD
, "data", InspectorInvalidateLayoutEvent::data(m_frame
.get()));
1725 clearLayoutSubtreeRootsAndMarkContainingBlocks();
1727 if (m_hasPendingLayout
)
1729 m_hasPendingLayout
= true;
1731 page()->animator().scheduleVisualUpdate(m_frame
.get());
1732 lifecycle().ensureStateAtMost(DocumentLifecycle::StyleClean
);
1735 void FrameView::scheduleRelayoutOfSubtree(LayoutObject
* relayoutRoot
)
1737 ASSERT(m_frame
->view() == this);
1739 // FIXME: Should this call shouldScheduleLayout instead?
1740 if (!m_frame
->document()->isActive())
1743 LayoutView
* layoutView
= this->layoutView();
1744 if (layoutView
&& layoutView
->needsLayout()) {
1746 relayoutRoot
->markContainerChainForLayout(false);
1750 if (relayoutRoot
== layoutView
)
1751 m_layoutSubtreeRootList
.clearAndMarkContainingBlocksForLayout();
1753 m_layoutSubtreeRootList
.addRoot(*relayoutRoot
);
1755 if (m_layoutSchedulingEnabled
) {
1756 m_hasPendingLayout
= true;
1758 page()->animator().scheduleVisualUpdate(m_frame
.get());
1759 lifecycle().ensureStateAtMost(DocumentLifecycle::StyleClean
);
1761 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "InvalidateLayout", TRACE_EVENT_SCOPE_THREAD
, "data", InspectorInvalidateLayoutEvent::data(m_frame
.get()));
1764 bool FrameView::layoutPending() const
1766 // FIXME: This should check Document::lifecycle instead.
1767 return m_hasPendingLayout
;
1770 bool FrameView::isInPerformLayout() const
1772 ASSERT(m_inPerformLayout
== (lifecycle().state() == DocumentLifecycle::InPerformLayout
));
1773 return m_inPerformLayout
;
1776 bool FrameView::needsLayout() const
1778 // This can return true in cases where the document does not have a body yet.
1779 // Document::shouldScheduleLayout takes care of preventing us from scheduling
1780 // layout in that case.
1782 LayoutView
* layoutView
= this->layoutView();
1783 return layoutPending()
1784 || (layoutView
&& layoutView
->needsLayout())
1785 || isSubtreeLayout();
1788 void FrameView::setNeedsLayout()
1790 LayoutBox
* box
= embeddedContentBox();
1791 // It's illegal to ask for layout changes during the layout compositing or paint invalidation step.
1792 // FIXME: the third conditional is a hack to support embedded SVG. See FrameView::forceLayoutParentViewIfNeeded and crbug.com/442939
1793 RELEASE_ASSERT(!m_frame
->document() || m_frame
->document()->lifecycle().stateAllowsLayoutInvalidation() || (box
&& box
->isSVGRoot()));
1795 if (LayoutView
* layoutView
= this->layoutView())
1796 layoutView
->setNeedsLayout(LayoutInvalidationReason::Unknown
);
1799 bool FrameView::isTransparent() const
1801 return m_isTransparent
;
1804 void FrameView::setTransparent(bool isTransparent
)
1806 m_isTransparent
= isTransparent
;
1807 DisableCompositingQueryAsserts disabler
;
1808 if (layoutView() && layoutView()->layer()->hasCompositedDeprecatedPaintLayerMapping())
1809 layoutView()->layer()->compositedDeprecatedPaintLayerMapping()->updateContentsOpaque();
1812 bool FrameView::hasOpaqueBackground() const
1814 return !m_isTransparent
&& !m_baseBackgroundColor
.hasAlpha();
1817 Color
FrameView::baseBackgroundColor() const
1819 return m_baseBackgroundColor
;
1822 void FrameView::setBaseBackgroundColor(const Color
& backgroundColor
)
1824 m_baseBackgroundColor
= backgroundColor
;
1826 if (layoutView() && layoutView()->layer()->hasCompositedDeprecatedPaintLayerMapping()) {
1827 CompositedDeprecatedPaintLayerMapping
* compositedDeprecatedPaintLayerMapping
= layoutView()->layer()->compositedDeprecatedPaintLayerMapping();
1828 compositedDeprecatedPaintLayerMapping
->updateContentsOpaque();
1829 if (compositedDeprecatedPaintLayerMapping
->mainGraphicsLayer())
1830 compositedDeprecatedPaintLayerMapping
->mainGraphicsLayer()->setNeedsDisplay();
1832 recalculateScrollbarOverlayStyle();
1835 void FrameView::updateBackgroundRecursively(const Color
& backgroundColor
, bool transparent
)
1837 for (Frame
* frame
= m_frame
.get(); frame
; frame
= frame
->tree().traverseNext(m_frame
.get())) {
1838 if (!frame
->isLocalFrame())
1840 if (FrameView
* view
= toLocalFrame(frame
)->view()) {
1841 view
->setTransparent(transparent
);
1842 view
->setBaseBackgroundColor(backgroundColor
);
1847 void FrameView::scrollToAnchor()
1849 RefPtrWillBeRawPtr
<Node
> anchorNode
= m_scrollAnchor
;
1853 if (!anchorNode
->layoutObject())
1856 // Scrolling is disabled during updateScrollbars (see isProgrammaticallyScrollable).
1857 // Bail now to avoid clearing m_scrollAnchor before we actually have a chance to scroll.
1858 if (m_inUpdateScrollbars
)
1862 if (anchorNode
!= m_frame
->document()) {
1863 rect
= anchorNode
->boundingBox();
1864 } else if (m_frame
->settings() && m_frame
->settings()->rootLayerScrolls()) {
1865 if (Element
* documentElement
= m_frame
->document()->documentElement())
1866 rect
= documentElement
->boundingBox();
1869 RefPtrWillBeRawPtr
<Frame
> boundaryFrame
= m_frame
->findUnsafeParentScrollPropagationBoundary();
1871 // FIXME: Handle RemoteFrames
1872 if (boundaryFrame
&& boundaryFrame
->isLocalFrame())
1873 toLocalFrame(boundaryFrame
.get())->view()->setSafeToPropagateScrollToParent(false);
1875 // Scroll nested layers and frames to reveal the anchor.
1876 // Align to the top and to the closest side (this matches other browsers).
1877 anchorNode
->layoutObject()->scrollRectToVisible(rect
, ScrollAlignment::alignToEdgeIfNeeded
, ScrollAlignment::alignTopAlways
);
1879 if (boundaryFrame
&& boundaryFrame
->isLocalFrame())
1880 toLocalFrame(boundaryFrame
.get())->view()->setSafeToPropagateScrollToParent(true);
1882 if (AXObjectCache
* cache
= m_frame
->document()->existingAXObjectCache())
1883 cache
->handleScrolledToAnchor(anchorNode
.get());
1885 // The scroll anchor should only be maintained while the frame is still loading.
1886 // If the frame is done loading, clear the anchor now. Otherwise, restore it
1887 // since it may have been cleared during scrollRectToVisible.
1888 m_scrollAnchor
= m_frame
->document()->isLoadCompleted() ? nullptr : anchorNode
;
1891 bool FrameView::updateWidgets()
1893 // This is always called from updateWidgetsTimerFired.
1894 // m_updateWidgetsTimer should only be scheduled if we have widgets to update.
1895 // Thus I believe we can stop checking isEmpty here, and just ASSERT isEmpty:
1896 // FIXME: This assert has been temporarily removed due to https://crbug.com/430344
1897 if (m_nestedLayoutCount
> 1 || m_partUpdateSet
.isEmpty())
1900 // Need to swap because script will run inside the below loop and invalidate the iterator.
1901 EmbeddedObjectSet objects
;
1902 objects
.swap(m_partUpdateSet
);
1904 for (const auto& embeddedObject
: objects
) {
1905 LayoutEmbeddedObject
& object
= *embeddedObject
;
1906 HTMLPlugInElement
* element
= toHTMLPlugInElement(object
.node());
1908 // The object may have already been destroyed (thus node cleared),
1909 // but FrameView holds a manual ref, so it won't have been deleted.
1913 // No need to update if it's already crashed or known to be missing.
1914 if (object
.showsUnavailablePluginIndicator())
1917 if (element
->needsWidgetUpdate())
1918 element
->updateWidget();
1919 object
.updateWidgetPosition();
1921 // Prevent plugins from causing infinite updates of themselves.
1922 // FIXME: Do we really need to prevent this?
1923 m_partUpdateSet
.remove(&object
);
1926 return m_partUpdateSet
.isEmpty();
1929 void FrameView::updateWidgetsTimerFired(Timer
<FrameView
>*)
1931 ASSERT(!isInPerformLayout());
1932 RefPtrWillBeRawPtr
<FrameView
> protect(this);
1933 m_updateWidgetsTimer
.stop();
1934 for (unsigned i
= 0; i
< maxUpdateWidgetsIterations
; ++i
) {
1935 if (updateWidgets())
1940 void FrameView::flushAnyPendingPostLayoutTasks()
1942 ASSERT(!isInPerformLayout());
1943 if (m_postLayoutTasksTimer
.isActive())
1944 performPostLayoutTasks();
1945 if (m_updateWidgetsTimer
.isActive())
1946 updateWidgetsTimerFired(0);
1949 void FrameView::scheduleUpdateWidgetsIfNecessary()
1951 ASSERT(!isInPerformLayout());
1952 if (m_updateWidgetsTimer
.isActive() || m_partUpdateSet
.isEmpty())
1954 m_updateWidgetsTimer
.startOneShot(0, FROM_HERE
);
1957 void FrameView::performPostLayoutTasks()
1959 // FIXME: We can reach here, even when the page is not active!
1960 // http/tests/inspector/elements/html-link-import.html and many other
1961 // tests hit that case.
1962 // We should ASSERT(isActive()); or at least return early if we can!
1963 ASSERT(!isInPerformLayout()); // Always before or after performLayout(), part of the highest-level layout() call.
1964 TRACE_EVENT0("blink,benchmark", "FrameView::performPostLayoutTasks");
1965 RefPtrWillBeRawPtr
<FrameView
> protect(this);
1967 m_postLayoutTasksTimer
.stop();
1969 m_frame
->selection().setCaretRectNeedsUpdate();
1970 m_frame
->selection().updateAppearance();
1972 ASSERT(m_frame
->document());
1974 FontFaceSet::didLayout(*m_frame
->document());
1975 // Cursor update scheduling is done by the local root, which is the main frame if there
1976 // are no RemoteFrame ancestors in the frame tree. Use of localFrameRoot() is
1977 // discouraged but will change when cursor update scheduling is moved from EventHandler
1978 // to PageEventHandler.
1979 frame().localFrameRoot()->eventHandler().scheduleCursorUpdate();
1981 updateWidgetPositions();
1983 // Plugins could have torn down the page inside updateWidgetPositions().
1987 scheduleUpdateWidgetsIfNecessary();
1989 if (ScrollingCoordinator
* scrollingCoordinator
= this->scrollingCoordinator())
1990 scrollingCoordinator
->notifyLayoutUpdated();
1994 sendResizeEventIfNeeded();
1997 bool FrameView::wasViewportResized()
2000 LayoutView
* layoutView
= this->layoutView();
2003 ASSERT(layoutView
->style());
2004 return (layoutSize(IncludeScrollbars
) != m_lastViewportSize
|| layoutView
->style()->zoom() != m_lastZoomFactor
);
2007 void FrameView::sendResizeEventIfNeeded()
2011 LayoutView
* layoutView
= this->layoutView();
2012 if (!layoutView
|| layoutView
->document().printing())
2015 if (!wasViewportResized())
2018 m_lastViewportSize
= layoutSize(IncludeScrollbars
);
2019 m_lastZoomFactor
= layoutView
->style()->zoom();
2021 m_frame
->document()->enqueueResizeEvent();
2023 if (m_frame
->isMainFrame())
2024 InspectorInstrumentation::didResizeMainFrame(m_frame
.get());
2027 void FrameView::postLayoutTimerFired(Timer
<FrameView
>*)
2029 performPostLayoutTasks();
2032 void FrameView::updateCounters()
2034 LayoutView
* view
= layoutView();
2035 if (!view
->hasLayoutCounters())
2038 for (LayoutObject
* layoutObject
= view
; layoutObject
; layoutObject
= layoutObject
->nextInPreOrder()) {
2039 if (!layoutObject
->isCounter())
2042 toLayoutCounter(layoutObject
)->updateCounter();
2046 IntRect
FrameView::windowClipRect(IncludeScrollbarsInRect scrollbarInclusion
) const
2048 ASSERT(m_frame
->view() == this);
2050 // Set our clip rect to be our contents.
2051 IntRect clipRect
= contentsToRootFrame(visibleContentRect(scrollbarInclusion
));
2052 if (!m_frame
->deprecatedLocalOwner())
2055 // Take our owner element and get its clip rect.
2056 // FIXME: Do we need to do this for remote frames?
2057 HTMLFrameOwnerElement
* ownerElement
= m_frame
->deprecatedLocalOwner();
2058 FrameView
* parentView
= ownerElement
->document().view();
2060 clipRect
.intersect(parentView
->clipRectsForFrameOwner(ownerElement
, nullptr));
2064 IntRect
FrameView::clipRectsForFrameOwner(const HTMLFrameOwnerElement
* ownerElement
, IntRect
* unobscuredRect
) const
2066 ASSERT(ownerElement
);
2069 *unobscuredRect
= IntRect();
2071 // The layoutObject can sometimes be null when style="display:none" interacts
2072 // with external content and plugins.
2073 if (!ownerElement
->layoutObject())
2074 return windowClipRect();
2076 // If we have no layer, just return our window clip rect.
2077 const DeprecatedPaintLayer
* enclosingLayer
= ownerElement
->layoutObject()->enclosingLayer();
2078 if (!enclosingLayer
)
2079 return windowClipRect();
2081 // FIXME: childrenClipRect relies on compositingState, which is not necessarily up to date.
2082 // https://code.google.com/p/chromium/issues/detail?id=343769
2083 DisableCompositingQueryAsserts disabler
;
2085 // Apply the clip from the layer.
2086 IntRect elementRect
= contentsToRootFrame(pixelSnappedIntRect(enclosingLayer
->clipper().childrenClipRect()));
2088 if (unobscuredRect
) {
2089 *unobscuredRect
= elementRect
;
2091 // If element is not in root frame, clip to the local frame.
2092 // FIXME: Do we need to do this for remote frames?
2093 if (m_frame
->deprecatedLocalOwner())
2094 unobscuredRect
->intersect(contentsToRootFrame(visibleContentRect()));
2097 return intersection(elementRect
, windowClipRect());
2100 bool FrameView::shouldUseIntegerScrollOffset() const
2102 if (m_frame
->settings() && !m_frame
->settings()->preferCompositingToLCDTextEnabled())
2105 return ScrollableArea::shouldUseIntegerScrollOffset();
2108 bool FrameView::isActive() const
2110 Page
* page
= frame().page();
2111 return page
&& page
->focusController().isActive();
2114 void FrameView::scrollTo(const DoublePoint
& newPosition
)
2116 DoublePoint oldPosition
= m_scrollPosition
;
2117 DoubleSize scrollDelta
= newPosition
- oldPosition
;
2118 if (scrollDelta
.isZero())
2121 if (m_frame
->settings() && m_frame
->settings()->rootLayerScrolls()) {
2122 // Don't scroll the FrameView!
2123 ASSERT_NOT_REACHED();
2126 m_scrollPosition
= newPosition
;
2128 if (!scrollbarsSuppressed())
2129 m_pendingScrollDelta
+= scrollDelta
;
2131 clearScrollAnchor();
2132 updateLayersAndCompositingAfterScrollIfNeeded();
2133 scrollPositionChanged();
2134 frame().loader().client()->didChangeScrollOffset();
2137 void FrameView::invalidatePaintForTickmarks() const
2139 if (Scrollbar
* scrollbar
= verticalScrollbar())
2140 scrollbar
->invalidate();
2143 void FrameView::invalidateScrollbarRect(Scrollbar
* scrollbar
, const IntRect
& rect
)
2145 // Add in our offset within the FrameView.
2146 IntRect dirtyRect
= rect
;
2147 dirtyRect
.moveBy(scrollbar
->location());
2149 layoutView()->invalidateDisplayItemClient(*scrollbar
);
2151 if (isInPerformLayout())
2152 addScrollbarDamage(scrollbar
, rect
);
2154 invalidateRect(dirtyRect
);
2157 void FrameView::getTickmarks(Vector
<IntRect
>& tickmarks
) const
2159 if (!m_tickmarks
.isEmpty())
2160 tickmarks
= m_tickmarks
;
2162 tickmarks
= frame().document()->markers().renderedRectsForMarkers(DocumentMarker::TextMatch
);
2165 IntRect
FrameView::windowResizerRect() const
2167 if (Page
* page
= frame().page())
2168 return page
->chromeClient().windowResizerRect();
2172 void FrameView::setInputEventsTransformForEmulation(const IntSize
& offset
, float contentScaleFactor
)
2174 m_inputEventsOffsetForEmulation
= offset
;
2175 m_inputEventsScaleFactorForEmulation
= contentScaleFactor
;
2178 IntSize
FrameView::inputEventsOffsetForEmulation() const
2180 return m_inputEventsOffsetForEmulation
;
2183 float FrameView::inputEventsScaleFactor() const
2185 float pageScale
= m_frame
->host()->visualViewport().scale();
2186 return pageScale
* m_inputEventsScaleFactorForEmulation
;
2189 bool FrameView::scrollbarsCanBeActive() const
2191 if (m_frame
->view() != this)
2194 return !!m_frame
->document();
2197 void FrameView::scrollbarVisibilityChanged()
2199 if (LayoutView
* view
= layoutView())
2200 view
->clearHitTestCache();
2203 IntRect
FrameView::scrollableAreaBoundingBox() const
2205 LayoutPart
* ownerLayoutObject
= frame().ownerLayoutObject();
2206 if (!ownerLayoutObject
)
2209 return ownerLayoutObject
->absoluteContentQuad().enclosingBoundingBox();
2213 bool FrameView::isScrollable()
2215 return scrollingReasons() == Scrollable
;
2218 bool FrameView::isProgrammaticallyScrollable()
2220 return !m_inUpdateScrollbars
;
2223 FrameView::ScrollingReasons
FrameView::scrollingReasons()
2226 // 1) If there an actual overflow.
2227 // 2) display:none or visibility:hidden set to self or inherited.
2228 // 3) overflow{-x,-y}: hidden;
2229 // 4) scrolling: no;
2232 IntSize contentsSize
= this->contentsSize();
2233 IntSize visibleContentSize
= visibleContentRect().size();
2234 if ((contentsSize
.height() <= visibleContentSize
.height() && contentsSize
.width() <= visibleContentSize
.width()))
2235 return NotScrollableNoOverflow
;
2238 // FIXME: Do we need to fix this for OOPI?
2239 HTMLFrameOwnerElement
* owner
= m_frame
->deprecatedLocalOwner();
2240 if (owner
&& (!owner
->layoutObject() || !owner
->layoutObject()->visibleToHitTesting()))
2241 return NotScrollableNotVisible
;
2244 ScrollbarMode horizontalMode
;
2245 ScrollbarMode verticalMode
;
2246 calculateScrollbarModesForLayout(horizontalMode
, verticalMode
, RulesFromWebContentOnly
);
2247 if (horizontalMode
== ScrollbarAlwaysOff
&& verticalMode
== ScrollbarAlwaysOff
)
2248 return NotScrollableExplicitlyDisabled
;
2253 void FrameView::updateScrollableAreaSet()
2255 // That ensures that only inner frames are cached.
2256 FrameView
* parentFrameView
= this->parentFrameView();
2257 if (!parentFrameView
)
2260 if (!isScrollable()) {
2261 parentFrameView
->removeScrollableArea(this);
2265 parentFrameView
->addScrollableArea(this);
2268 bool FrameView::shouldSuspendScrollAnimations() const
2270 return !m_frame
->document()->loadEventFinished();
2273 void FrameView::scrollbarStyleChanged()
2275 // FIXME: Why does this only apply to the main frame?
2276 if (!m_frame
->isMainFrame())
2278 adjustScrollbarOpacity();
2280 updateScrollbars(scrollOffsetDouble());
2281 positionScrollbarLayers();
2284 void FrameView::notifyPageThatContentAreaWillPaint() const
2286 Page
* page
= m_frame
->page();
2290 contentAreaWillPaint();
2292 if (!m_scrollableAreas
)
2295 for (const auto& scrollableArea
: *m_scrollableAreas
) {
2296 if (!scrollableArea
->scrollbarsCanBeActive())
2299 scrollableArea
->contentAreaWillPaint();
2303 bool FrameView::scrollAnimatorEnabled() const
2305 return m_frame
->settings() && m_frame
->settings()->scrollAnimatorEnabled();
2308 void FrameView::updateAnnotatedRegions()
2310 Document
* document
= m_frame
->document();
2311 if (!document
->hasAnnotatedRegions())
2313 Vector
<AnnotatedRegionValue
> newRegions
;
2314 collectAnnotatedRegions(*(document
->layoutBox()), newRegions
);
2315 if (newRegions
== document
->annotatedRegions())
2317 document
->setAnnotatedRegions(newRegions
);
2318 if (Page
* page
= m_frame
->page())
2319 page
->chromeClient().annotatedRegionsChanged();
2322 void FrameView::updateScrollCorner()
2324 RefPtr
<ComputedStyle
> cornerStyle
;
2325 IntRect cornerRect
= scrollCornerRect();
2326 Document
* doc
= m_frame
->document();
2328 if (doc
&& !cornerRect
.isEmpty()) {
2329 // Try the <body> element first as a scroll corner source.
2330 if (Element
* body
= doc
->body()) {
2331 if (LayoutObject
* layoutObject
= body
->layoutObject())
2332 cornerStyle
= layoutObject
->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER
), layoutObject
->style());
2336 // If the <body> didn't have a custom style, then the root element might.
2337 if (Element
* docElement
= doc
->documentElement()) {
2338 if (LayoutObject
* layoutObject
= docElement
->layoutObject())
2339 cornerStyle
= layoutObject
->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER
), layoutObject
->style());
2344 // If we have an owning ipage/LocalFrame element, then it can set the custom scrollbar also.
2345 if (LayoutPart
* layoutObject
= m_frame
->ownerLayoutObject())
2346 cornerStyle
= layoutObject
->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER
), layoutObject
->style());
2351 if (!m_scrollCorner
)
2352 m_scrollCorner
= LayoutScrollbarPart::createAnonymous(doc
);
2353 m_scrollCorner
->setStyle(cornerStyle
.release());
2354 invalidateScrollCorner(cornerRect
);
2355 } else if (m_scrollCorner
) {
2356 m_scrollCorner
->destroy();
2357 m_scrollCorner
= nullptr;
2361 Color
FrameView::documentBackgroundColor() const
2363 // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of
2364 // the document and the body against the base background color of the frame view.
2365 // Background images are unfortunately impractical to include.
2367 Color result
= baseBackgroundColor();
2368 if (!frame().document())
2371 Element
* htmlElement
= frame().document()->documentElement();
2372 Element
* bodyElement
= frame().document()->body();
2374 // We take the aggregate of the base background color
2375 // the <html> background color, and the <body>
2376 // background color to find the document color. The
2377 // addition of the base background color is not
2378 // technically part of the document background, but it
2379 // otherwise poses problems when the aggregate is not
2381 if (htmlElement
&& htmlElement
->layoutObject())
2382 result
= result
.blend(htmlElement
->layoutObject()->resolveColor(CSSPropertyBackgroundColor
));
2383 if (bodyElement
&& bodyElement
->layoutObject())
2384 result
= result
.blend(bodyElement
->layoutObject()->resolveColor(CSSPropertyBackgroundColor
));
2389 FrameView
* FrameView::parentFrameView() const
2394 Frame
* parentFrame
= m_frame
->tree().parent();
2395 if (parentFrame
&& parentFrame
->isLocalFrame())
2396 return toLocalFrame(parentFrame
)->view();
2401 bool FrameView::isPainting() const
2403 return m_isPainting
;
2406 void FrameView::setNodeToDraw(Node
* node
)
2408 m_nodeToDraw
= node
;
2411 void FrameView::updateWidgetPositionsIfNeeded()
2413 if (!m_needsUpdateWidgetPositions
)
2416 m_needsUpdateWidgetPositions
= false;
2418 updateWidgetPositions();
2421 void FrameView::updateAllLifecyclePhases(const LayoutRect
& interestRect
)
2423 frame().localFrameRoot()->view()->updateLifecyclePhasesInternal(AllPhases
, interestRect
);
2426 // TODO(chrishtr): add a scrolling update lifecycle phase.
2427 void FrameView::updateLifecycleToCompositingCleanPlusScrolling()
2429 frame().localFrameRoot()->view()->updateLifecyclePhasesInternal(OnlyUpToCompositingCleanPlusScrolling
);
2432 void FrameView::updateLifecyclePhasesInternal(LifeCycleUpdateOption phases
, const LayoutRect
& interestRect
)
2434 // This must be called from the root frame, since it recurses down, not up.
2435 // Otherwise the lifecycles of the frames might be out of sync.
2436 ASSERT(m_frame
->isLocalRoot());
2438 // Updating layout can run script, which can tear down the FrameView.
2439 RefPtrWillBeRawPtr
<FrameView
> protector(this);
2441 updateStyleAndLayoutIfNeededRecursive();
2443 if (LayoutView
* view
= layoutView()) {
2444 TRACE_EVENT1("devtools.timeline", "UpdateLayerTree", "data", InspectorUpdateLayerTreeEvent::data(m_frame
.get()));
2446 // This was required for slimming paint v1 but is only temporarily
2447 // needed for slimming paint v2.
2448 view
->compositor()->updateIfNeededRecursive();
2449 scrollContentsIfNeededRecursive();
2451 ASSERT(lifecycle().state() >= DocumentLifecycle::CompositingClean
);
2453 if (phases
== AllPhases
) {
2454 invalidateTreeIfNeededRecursive();
2456 if (view
->compositor()->inCompositingMode())
2457 scrollingCoordinator()->updateAfterCompositingChangeIfNeeded();
2459 updateCompositedSelectionIfNeeded();
2461 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
2462 paintForSlimmingPaintV2(interestRect
);
2463 compositeForSlimmingPaintV2();
2466 if (RuntimeEnabledFeatures::frameTimingSupportEnabled())
2467 updateFrameTimingRequestsIfNeeded();
2469 ASSERT(!view
->hasPendingSelection());
2470 ASSERT(lifecycle().state() == DocumentLifecycle::PaintInvalidationClean
2471 || (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && lifecycle().state() == DocumentLifecycle::CompositingForSlimmingPaintV2Clean
));
2476 void FrameView::paintForSlimmingPaintV2(const LayoutRect
& interestRect
)
2478 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
2479 ASSERT(frame() == page()->mainFrame() || (!frame().tree().parent()->isLocalFrame()));
2481 LayoutView
* view
= layoutView();
2483 GraphicsLayer
* rootGraphicsLayer
= view
->layer()->graphicsLayerBacking();
2485 // Detached frames can have no root graphics layer.
2486 if (!rootGraphicsLayer
)
2489 lifecycle().advanceTo(DocumentLifecycle::InPaintForSlimmingPaintV2
);
2491 GraphicsContext
context(rootGraphicsLayer
->displayItemList());
2492 rootGraphicsLayer
->paint(context
, roundedIntRect(interestRect
));
2494 lifecycle().advanceTo(DocumentLifecycle::PaintForSlimmingPaintV2Clean
);
2497 void FrameView::compositeForSlimmingPaintV2()
2499 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
2500 ASSERT(frame() == page()->mainFrame() || (!frame().tree().parent()->isLocalFrame()));
2502 GraphicsLayer
* rootGraphicsLayer
= layoutView()->layer()->graphicsLayerBacking();
2504 // Detached frames can have no root graphics layer.
2505 if (!rootGraphicsLayer
)
2508 lifecycle().advanceTo(DocumentLifecycle::InCompositingForSlimmingPaintV2
);
2510 DisplayListDiff displayListDiff
;
2511 rootGraphicsLayer
->displayItemList()->commitNewDisplayItems(&displayListDiff
);
2513 DisplayListCompositingBuilder
compositingBuilder(*rootGraphicsLayer
->displayItemList(), displayListDiff
);
2514 OwnPtr
<CompositedDisplayList
> compositedDisplayList
= adoptPtr(new CompositedDisplayList());
2515 compositingBuilder
.build(*compositedDisplayList
);
2516 page()->setCompositedDisplayList(compositedDisplayList
.release());
2518 lifecycle().advanceTo(DocumentLifecycle::CompositingForSlimmingPaintV2Clean
);
2521 void FrameView::updateFrameTimingRequestsIfNeeded()
2523 GraphicsLayerFrameTimingRequests graphicsLayerTimingRequests
;
2524 // TODO(mpb) use a 'dirty' bit to not call this every time.
2525 collectFrameTimingRequestsRecursive(graphicsLayerTimingRequests
);
2527 for (const auto& iter
: graphicsLayerTimingRequests
) {
2528 const GraphicsLayer
* graphicsLayer
= iter
.key
;
2529 graphicsLayer
->platformLayer()->setFrameTimingRequests(iter
.value
);
2533 void FrameView::updateStyleAndLayoutIfNeededRecursive()
2535 // We have to crawl our entire subtree looking for any FrameViews that need
2536 // layout and make sure they are up to date.
2537 // Mac actually tests for intersection with the dirty region and tries not to
2538 // update layout for frames that are outside the dirty region. Not only does this seem
2539 // pointless (since those frames will have set a zero timer to layout anyway), but
2540 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
2541 // region but then become included later by the second frame adding rects to the dirty region
2542 // when it lays out.
2544 m_frame
->document()->updateLayoutTreeIfNeeded();
2549 // FIXME: Calling layout() shouldn't trigger script execution or have any
2550 // observable effects on the frame tree but we're not quite there yet.
2551 WillBeHeapVector
<RefPtrWillBeMember
<FrameView
>> frameViews
;
2552 for (Frame
* child
= m_frame
->tree().firstChild(); child
; child
= child
->tree().nextSibling()) {
2553 if (!child
->isLocalFrame())
2555 if (FrameView
* view
= toLocalFrame(child
)->view())
2556 frameViews
.append(view
);
2559 for (const auto& frameView
: frameViews
)
2560 frameView
->updateStyleAndLayoutIfNeededRecursive();
2562 // When an <iframe> gets composited, it triggers an extra style recalc in its containing FrameView.
2563 // To avoid pushing an invalid tree for display, we have to check for this case and do another
2564 // style recalc. The extra style recalc needs to happen after our child <iframes> were updated.
2565 // FIXME: We shouldn't be triggering an extra style recalc in the first place.
2566 if (m_frame
->document()->hasSVGFilterElementsRequiringLayerUpdate()) {
2567 m_frame
->document()->updateLayoutTreeIfNeeded();
2573 // These asserts ensure that parent frames are clean, when child frames finished updating layout and style.
2574 ASSERT(!needsLayout());
2575 ASSERT(!m_frame
->document()->hasSVGFilterElementsRequiringLayerUpdate());
2577 m_frame
->document()->layoutView()->assertLaidOut();
2580 updateWidgetPositionsIfNeeded();
2583 void FrameView::invalidateTreeIfNeededRecursive()
2585 ASSERT(layoutView());
2586 TRACE_EVENT1("blink", "FrameView::invalidateTreeIfNeededRecursive", "root", layoutView()->debugName().ascii());
2588 Vector
<LayoutObject
*> pendingDelayedPaintInvalidations
;
2589 PaintInvalidationState
rootPaintInvalidationState(*layoutView(), pendingDelayedPaintInvalidations
);
2591 invalidateTreeIfNeeded(rootPaintInvalidationState
);
2593 // Some frames may be not reached during the above invalidateTreeIfNeeded because
2594 // - the frame is a detached frame; or
2595 // - it didn't need paint invalidation.
2596 // We need to call invalidateTreeIfNeededRecursive() for such frames to finish required
2597 // paint invalidation and advance their life cycle state.
2598 for (Frame
* child
= m_frame
->tree().firstChild(); child
; child
= child
->tree().nextSibling()) {
2599 if (!child
->isLocalFrame())
2601 FrameView
* childFrameView
= toLocalFrame(child
)->view();
2602 if (childFrameView
->lifecycle().state() < DocumentLifecycle::PaintInvalidationClean
)
2603 childFrameView
->invalidateTreeIfNeededRecursive();
2606 // Process objects needing paint invalidation on the next frame. See the definition of PaintInvalidationDelayedFull for more details.
2607 for (auto& target
: pendingDelayedPaintInvalidations
)
2608 target
->setShouldDoFullPaintInvalidation(PaintInvalidationDelayedFull
);
2611 void FrameView::enableAutoSizeMode(const IntSize
& minSize
, const IntSize
& maxSize
)
2613 if (!m_autoSizeInfo
)
2614 m_autoSizeInfo
= FrameViewAutoSizeInfo::create(this);
2616 m_autoSizeInfo
->configureAutoSizeMode(minSize
, maxSize
);
2617 setLayoutSizeFixedToFrameSize(true);
2622 void FrameView::disableAutoSizeMode()
2624 if (!m_autoSizeInfo
)
2627 setLayoutSizeFixedToFrameSize(false);
2631 // Since autosize mode forces the scrollbar mode, change them to being auto.
2632 setVerticalScrollbarLock(false);
2633 setHorizontalScrollbarLock(false);
2634 setScrollbarModes(ScrollbarAuto
, ScrollbarAuto
);
2635 m_autoSizeInfo
.clear();
2638 void FrameView::forceLayoutForPagination(const FloatSize
& pageSize
, const FloatSize
& originalPageSize
, float maximumShrinkFactor
)
2640 // Dumping externalRepresentation(m_frame->layoutObject()).ascii() is a good trick to see
2641 // the state of things before and after the layout
2642 if (LayoutView
* layoutView
= this->layoutView()) {
2643 float pageLogicalWidth
= layoutView
->style()->isHorizontalWritingMode() ? pageSize
.width() : pageSize
.height();
2644 float pageLogicalHeight
= layoutView
->style()->isHorizontalWritingMode() ? pageSize
.height() : pageSize
.width();
2646 LayoutUnit flooredPageLogicalWidth
= static_cast<LayoutUnit
>(pageLogicalWidth
);
2647 LayoutUnit flooredPageLogicalHeight
= static_cast<LayoutUnit
>(pageLogicalHeight
);
2648 layoutView
->setLogicalWidth(flooredPageLogicalWidth
);
2649 layoutView
->setPageLogicalHeight(flooredPageLogicalHeight
);
2650 layoutView
->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::PrintingChanged
);
2653 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
2654 // page width when shrunk, we will lay out at maximum shrink and clip extra content.
2655 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
2656 // implementation should not do this!
2657 bool horizontalWritingMode
= layoutView
->style()->isHorizontalWritingMode();
2658 const LayoutRect
& documentRect
= LayoutRect(layoutView
->documentRect());
2659 LayoutUnit docLogicalWidth
= horizontalWritingMode
? documentRect
.width() : documentRect
.height();
2660 if (docLogicalWidth
> pageLogicalWidth
) {
2661 FloatSize
expectedPageSize(std::min
<float>(documentRect
.width().toFloat(), pageSize
.width() * maximumShrinkFactor
), std::min
<float>(documentRect
.height().toFloat(), pageSize
.height() * maximumShrinkFactor
));
2662 FloatSize maxPageSize
= m_frame
->resizePageRectsKeepingRatio(FloatSize(originalPageSize
.width(), originalPageSize
.height()), expectedPageSize
);
2663 pageLogicalWidth
= horizontalWritingMode
? maxPageSize
.width() : maxPageSize
.height();
2664 pageLogicalHeight
= horizontalWritingMode
? maxPageSize
.height() : maxPageSize
.width();
2666 flooredPageLogicalWidth
= static_cast<LayoutUnit
>(pageLogicalWidth
);
2667 flooredPageLogicalHeight
= static_cast<LayoutUnit
>(pageLogicalHeight
);
2668 layoutView
->setLogicalWidth(flooredPageLogicalWidth
);
2669 layoutView
->setPageLogicalHeight(flooredPageLogicalHeight
);
2670 layoutView
->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::PrintingChanged
);
2673 const LayoutRect
& updatedDocumentRect
= LayoutRect(layoutView
->documentRect());
2674 LayoutUnit docLogicalHeight
= horizontalWritingMode
? updatedDocumentRect
.height() : updatedDocumentRect
.width();
2675 LayoutUnit docLogicalTop
= horizontalWritingMode
? updatedDocumentRect
.y() : updatedDocumentRect
.x();
2676 LayoutUnit docLogicalRight
= horizontalWritingMode
? updatedDocumentRect
.maxX() : updatedDocumentRect
.maxY();
2677 LayoutUnit clippedLogicalLeft
= 0;
2678 if (!layoutView
->style()->isLeftToRightDirection())
2679 clippedLogicalLeft
= docLogicalRight
- pageLogicalWidth
;
2680 LayoutRect
overflow(clippedLogicalLeft
, docLogicalTop
, pageLogicalWidth
, docLogicalHeight
);
2682 if (!horizontalWritingMode
)
2683 overflow
= overflow
.transposedRect();
2684 layoutView
->clearLayoutOverflow();
2685 layoutView
->addLayoutOverflow(overflow
); // This is how we clip in case we overflow again.
2692 IntRect
FrameView::convertFromLayoutObject(const LayoutObject
& layoutObject
, const IntRect
& layoutObjectRect
) const
2694 IntRect rect
= pixelSnappedIntRect(enclosingLayoutRect(layoutObject
.localToAbsoluteQuad(FloatRect(layoutObjectRect
)).boundingBox()));
2696 // Convert from page ("absolute") to FrameView coordinates.
2697 rect
.moveBy(-scrollPosition());
2702 IntRect
FrameView::convertToLayoutObject(const LayoutObject
& layoutObject
, const IntRect
& frameRect
) const
2704 IntRect rectInContent
= frameToContents(frameRect
);
2706 // Convert from FrameView coords into page ("absolute") coordinates.
2707 rectInContent
.moveBy(scrollPosition());
2709 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
2710 // move the rect for now.
2711 rectInContent
.setLocation(roundedIntPoint(layoutObject
.absoluteToLocal(rectInContent
.location(), UseTransforms
)));
2712 return rectInContent
;
2715 IntPoint
FrameView::convertFromLayoutObject(const LayoutObject
& layoutObject
, const IntPoint
& layoutObjectPoint
) const
2717 IntPoint point
= roundedIntPoint(layoutObject
.localToAbsolute(layoutObjectPoint
, UseTransforms
));
2719 // Convert from page ("absolute") to FrameView coordinates.
2720 point
.moveBy(-scrollPosition());
2724 IntPoint
FrameView::convertToLayoutObject(const LayoutObject
& layoutObject
, const IntPoint
& framePoint
) const
2726 IntPoint point
= framePoint
;
2728 // Convert from FrameView coords into page ("absolute") coordinates.
2729 point
+= IntSize(scrollX(), scrollY());
2731 return roundedIntPoint(layoutObject
.absoluteToLocal(point
, UseTransforms
));
2734 IntRect
FrameView::convertToContainingView(const IntRect
& localRect
) const
2736 if (const FrameView
* parentView
= toFrameView(parent())) {
2737 // Get our layoutObject in the parent view
2738 LayoutPart
* layoutObject
= m_frame
->ownerLayoutObject();
2742 IntRect
rect(localRect
);
2743 // Add borders and padding??
2744 rect
.move(layoutObject
->borderLeft() + layoutObject
->paddingLeft(),
2745 layoutObject
->borderTop() + layoutObject
->paddingTop());
2746 return parentView
->convertFromLayoutObject(*layoutObject
, rect
);
2752 IntRect
FrameView::convertFromContainingView(const IntRect
& parentRect
) const
2754 if (const FrameView
* parentView
= toFrameView(parent())) {
2755 // Get our layoutObject in the parent view
2756 LayoutPart
* layoutObject
= m_frame
->ownerLayoutObject();
2760 IntRect rect
= parentView
->convertToLayoutObject(*layoutObject
, parentRect
);
2761 // Subtract borders and padding
2762 rect
.move(-layoutObject
->borderLeft() - layoutObject
->paddingLeft(),
2763 -layoutObject
->borderTop() - layoutObject
->paddingTop());
2770 IntPoint
FrameView::convertToContainingView(const IntPoint
& localPoint
) const
2772 if (const FrameView
* parentView
= toFrameView(parent())) {
2773 // Get our layoutObject in the parent view
2774 LayoutPart
* layoutObject
= m_frame
->ownerLayoutObject();
2778 IntPoint
point(localPoint
);
2780 // Add borders and padding
2781 point
.move(layoutObject
->borderLeft() + layoutObject
->paddingLeft(),
2782 layoutObject
->borderTop() + layoutObject
->paddingTop());
2783 return parentView
->convertFromLayoutObject(*layoutObject
, point
);
2789 IntPoint
FrameView::convertFromContainingView(const IntPoint
& parentPoint
) const
2791 if (const FrameView
* parentView
= toFrameView(parent())) {
2792 // Get our layoutObject in the parent view
2793 LayoutPart
* layoutObject
= m_frame
->ownerLayoutObject();
2797 IntPoint point
= parentView
->convertToLayoutObject(*layoutObject
, parentPoint
);
2798 // Subtract borders and padding
2799 point
.move(-layoutObject
->borderLeft() - layoutObject
->paddingLeft(),
2800 -layoutObject
->borderTop() - layoutObject
->paddingTop());
2807 void FrameView::setInitialTracksPaintInvalidationsForTesting(bool trackPaintInvalidations
)
2809 s_initialTrackAllPaintInvalidations
= trackPaintInvalidations
;
2812 void FrameView::setTracksPaintInvalidations(bool trackPaintInvalidations
)
2814 if (trackPaintInvalidations
== m_isTrackingPaintInvalidations
)
2817 for (Frame
* frame
= m_frame
->tree().top(); frame
; frame
= frame
->tree().traverseNext()) {
2818 if (!frame
->isLocalFrame())
2820 if (LayoutView
* layoutView
= toLocalFrame(frame
)->contentLayoutObject())
2821 layoutView
->compositor()->setTracksPaintInvalidations(trackPaintInvalidations
);
2824 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"),
2825 "FrameView::setTracksPaintInvalidations", TRACE_EVENT_SCOPE_GLOBAL
, "enabled", trackPaintInvalidations
);
2827 resetTrackedPaintInvalidations();
2828 m_isTrackingPaintInvalidations
= trackPaintInvalidations
;
2831 void FrameView::resetTrackedPaintInvalidations()
2833 if (LayoutView
* layoutView
= this->layoutView())
2834 layoutView
->compositor()->resetTrackedPaintInvalidationRects();
2837 void FrameView::addResizerArea(LayoutBox
& resizerBox
)
2839 if (!m_resizerAreas
)
2840 m_resizerAreas
= adoptPtr(new ResizerAreaSet
);
2841 m_resizerAreas
->add(&resizerBox
);
2844 void FrameView::removeResizerArea(LayoutBox
& resizerBox
)
2846 if (!m_resizerAreas
)
2849 ResizerAreaSet::iterator it
= m_resizerAreas
->find(&resizerBox
);
2850 if (it
!= m_resizerAreas
->end())
2851 m_resizerAreas
->remove(it
);
2854 void FrameView::addScrollableArea(ScrollableArea
* scrollableArea
)
2856 ASSERT(scrollableArea
);
2857 if (!m_scrollableAreas
)
2858 m_scrollableAreas
= adoptPtrWillBeNoop(new ScrollableAreaSet
);
2859 m_scrollableAreas
->add(scrollableArea
);
2861 if (ScrollingCoordinator
* scrollingCoordinator
= this->scrollingCoordinator())
2862 scrollingCoordinator
->scrollableAreasDidChange();
2865 void FrameView::removeScrollableArea(ScrollableArea
* scrollableArea
)
2867 if (!m_scrollableAreas
)
2869 m_scrollableAreas
->remove(scrollableArea
);
2871 if (ScrollingCoordinator
* scrollingCoordinator
= this->scrollingCoordinator())
2872 scrollingCoordinator
->scrollableAreasDidChange();
2875 void FrameView::addAnimatingScrollableArea(ScrollableArea
* scrollableArea
)
2877 ASSERT(scrollableArea
);
2878 if (!m_animatingScrollableAreas
)
2879 m_animatingScrollableAreas
= adoptPtrWillBeNoop(new ScrollableAreaSet
);
2880 m_animatingScrollableAreas
->add(scrollableArea
);
2883 void FrameView::removeAnimatingScrollableArea(ScrollableArea
* scrollableArea
)
2885 if (!m_animatingScrollableAreas
)
2887 m_animatingScrollableAreas
->remove(scrollableArea
);
2890 void FrameView::setParent(Widget
* parentView
)
2892 if (parentView
== parent())
2895 if (m_scrollbarsAvoidingResizer
&& parent())
2896 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(-m_scrollbarsAvoidingResizer
);
2898 Widget::setParent(parentView
);
2900 if (m_scrollbarsAvoidingResizer
&& parent())
2901 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(m_scrollbarsAvoidingResizer
);
2903 updateScrollableAreaSet();
2906 void FrameView::removeChild(Widget
* child
)
2908 ASSERT(child
->parent() == this);
2910 if (child
->isFrameView())
2911 removeScrollableArea(toFrameView(child
));
2913 child
->setParent(0);
2914 m_children
.remove(child
);
2917 bool FrameView::isVerticalDocument() const
2919 LayoutView
* layoutView
= this->layoutView();
2923 return layoutView
->style()->isHorizontalWritingMode();
2926 bool FrameView::isFlippedDocument() const
2928 LayoutView
* layoutView
= this->layoutView();
2932 return layoutView
->hasFlippedBlocksWritingMode();
2935 bool FrameView::visualViewportSuppliesScrollbars() const
2937 return m_frame
->isMainFrame() && m_frame
->settings() && m_frame
->settings()->viewportMetaEnabled();
2940 AXObjectCache
* FrameView::axObjectCache() const
2942 if (frame().document())
2943 return frame().document()->existingAXObjectCache();
2947 void FrameView::setCursor(const Cursor
& cursor
)
2949 Page
* page
= frame().page();
2950 if (!page
|| !page
->settings().deviceSupportsMouse())
2952 page
->chromeClient().setCursor(cursor
);
2955 void FrameView::frameRectsChanged()
2957 TRACE_EVENT0("blink", "FrameView::frameRectsChanged");
2958 if (layoutSizeFixedToFrameSize())
2959 setLayoutSizeInternal(frameRect().size());
2961 for (const auto& child
: m_children
)
2962 child
->frameRectsChanged();
2965 void FrameView::setLayoutSizeInternal(const IntSize
& size
)
2967 if (m_layoutSize
== size
)
2970 m_layoutSize
= size
;
2972 if (Document
* document
= m_frame
->document()) {
2973 if (document
->isActive())
2974 document
->notifyResizeForViewportUnits();
2980 void FrameView::didAddScrollbar(Scrollbar
* scrollbar
, ScrollbarOrientation orientation
)
2982 ScrollableArea::didAddScrollbar(scrollbar
, orientation
);
2983 if (AXObjectCache
* cache
= axObjectCache())
2984 cache
->handleScrollbarUpdate(this);
2987 void FrameView::setTopControlsViewportAdjustment(float adjustment
)
2989 m_topControlsViewportAdjustment
= adjustment
;
2992 IntPoint
FrameView::maximumScrollPosition() const
2994 // Make the same calculation as in CC's LayerImpl::MaxScrollOffset()
2995 // FIXME: We probably shouldn't be storing the bounds in a float. crbug.com/422331.
2996 IntSize visibleSize
= visibleContentSize(ExcludeScrollbars
) + topControlsSize();
2997 IntSize contentBounds
= contentsSize();
2998 IntPoint maximumPosition
= -scrollOrigin() + (contentBounds
- visibleSize
);
2999 return maximumPosition
.expandedTo(minimumScrollPosition());
3002 void FrameView::addChild(PassRefPtrWillBeRawPtr
<Widget
> prpChild
)
3004 Widget
* child
= prpChild
.get();
3005 ASSERT(child
!= this && !child
->parent());
3006 child
->setParent(this);
3007 m_children
.add(prpChild
);
3010 void FrameView::setHasHorizontalScrollbar(bool hasBar
)
3012 if (hasBar
== !!m_horizontalScrollbar
)
3016 m_horizontalScrollbar
= createScrollbar(HorizontalScrollbar
);
3017 addChild(m_horizontalScrollbar
.get());
3018 didAddScrollbar(m_horizontalScrollbar
.get(), HorizontalScrollbar
);
3019 m_horizontalScrollbar
->styleChanged();
3021 willRemoveScrollbar(m_horizontalScrollbar
.get(), HorizontalScrollbar
);
3022 if (AXObjectCache
* cache
= axObjectCache())
3023 cache
->remove(m_horizontalScrollbar
.get());
3024 // If the scrollbar has been marked as overlapping the window resizer,
3025 // then its removal should reduce the count.
3026 if (m_horizontalScrollbar
->overlapsResizer())
3027 adjustScrollbarsAvoidingResizerCount(-1);
3028 removeChild(m_horizontalScrollbar
.get());
3029 m_horizontalScrollbar
->disconnectFromScrollableArea();
3030 m_horizontalScrollbar
= nullptr;
3031 if (AXObjectCache
* cache
= axObjectCache())
3032 cache
->handleScrollbarUpdate(this);
3035 invalidateScrollCorner(scrollCornerRect());
3038 void FrameView::setHasVerticalScrollbar(bool hasBar
)
3040 if (hasBar
== !!m_verticalScrollbar
)
3044 m_verticalScrollbar
= createScrollbar(VerticalScrollbar
);
3045 addChild(m_verticalScrollbar
.get());
3046 didAddScrollbar(m_verticalScrollbar
.get(), VerticalScrollbar
);
3047 m_verticalScrollbar
->styleChanged();
3049 willRemoveScrollbar(m_verticalScrollbar
.get(), VerticalScrollbar
);
3050 if (AXObjectCache
* cache
= axObjectCache())
3051 cache
->remove(m_verticalScrollbar
.get());
3052 // If the scrollbar has been marked as overlapping the window resizer,
3053 // then its removal should reduce the count.
3054 if (m_verticalScrollbar
->overlapsResizer())
3055 adjustScrollbarsAvoidingResizerCount(-1);
3056 removeChild(m_verticalScrollbar
.get());
3057 m_verticalScrollbar
->disconnectFromScrollableArea();
3058 m_verticalScrollbar
= nullptr;
3059 if (AXObjectCache
* cache
= axObjectCache())
3060 cache
->handleScrollbarUpdate(this);
3063 invalidateScrollCorner(scrollCornerRect());
3066 void FrameView::setScrollbarModes(ScrollbarMode horizontalMode
, ScrollbarMode verticalMode
,
3067 bool horizontalLock
, bool verticalLock
)
3069 bool needsUpdate
= false;
3071 // If the page's overflow setting has disabled scrolling, do not allow anything to override that setting.
3072 // http://crbug.com/426447
3073 LayoutObject
* viewport
= viewportLayoutObject();
3074 if (viewport
&& !shouldIgnoreOverflowHidden()) {
3075 if (viewport
->style()->overflowX() == OHIDDEN
)
3076 horizontalMode
= ScrollbarAlwaysOff
;
3077 if (viewport
->style()->overflowY() == OHIDDEN
)
3078 verticalMode
= ScrollbarAlwaysOff
;
3081 if (horizontalMode
!= horizontalScrollbarMode() && !m_horizontalScrollbarLock
) {
3082 m_horizontalScrollbarMode
= horizontalMode
;
3086 if (verticalMode
!= verticalScrollbarMode() && !m_verticalScrollbarLock
) {
3087 m_verticalScrollbarMode
= verticalMode
;
3092 setHorizontalScrollbarLock();
3095 setVerticalScrollbarLock();
3100 updateScrollbars(scrollOffsetDouble());
3102 if (!layerForScrolling())
3104 WebLayer
* layer
= layerForScrolling()->platformLayer();
3107 layer
->setUserScrollable(userInputScrollable(HorizontalScrollbar
), userInputScrollable(VerticalScrollbar
));
3110 void FrameView::setClipsRepaints(bool clipsRepaints
)
3112 m_clipsRepaints
= clipsRepaints
;
3115 IntSize
FrameView::visibleContentSize(IncludeScrollbarsInRect scrollbarInclusion
) const
3117 return scrollbarInclusion
== ExcludeScrollbars
? excludeScrollbars(frameRect().size()) : frameRect().size();
3120 IntRect
FrameView::visibleContentRect(IncludeScrollbarsInRect scrollbarInclusion
) const
3122 return IntRect(flooredIntPoint(m_scrollPosition
), visibleContentSize(scrollbarInclusion
));
3125 IntSize
FrameView::contentsSize() const
3127 return m_contentsSize
;
3130 IntPoint
FrameView::minimumScrollPosition() const
3132 return IntPoint(-scrollOrigin().x(), -scrollOrigin().y());
3135 void FrameView::adjustScrollbarOpacity()
3137 if (m_horizontalScrollbar
&& layerForHorizontalScrollbar()) {
3138 bool isOpaqueScrollbar
= !m_horizontalScrollbar
->isOverlayScrollbar();
3139 layerForHorizontalScrollbar()->setContentsOpaque(isOpaqueScrollbar
);
3141 if (m_verticalScrollbar
&& layerForVerticalScrollbar()) {
3142 bool isOpaqueScrollbar
= !m_verticalScrollbar
->isOverlayScrollbar();
3143 layerForVerticalScrollbar()->setContentsOpaque(isOpaqueScrollbar
);
3147 int FrameView::scrollSize(ScrollbarOrientation orientation
) const
3149 Scrollbar
* scrollbar
= ((orientation
== HorizontalScrollbar
) ? m_horizontalScrollbar
: m_verticalScrollbar
).get();
3151 // If no scrollbars are present, the content may still be scrollable.
3153 IntSize scrollSize
= m_contentsSize
- visibleContentRect().size();
3154 scrollSize
.clampNegativeToZero();
3155 return orientation
== HorizontalScrollbar
? scrollSize
.width() : scrollSize
.height();
3158 return scrollbar
->totalSize() - scrollbar
->visibleSize();
3161 void FrameView::setScrollOffset(const IntPoint
& offset
, ScrollType
)
3163 scrollTo(clampScrollPosition(offset
));
3166 void FrameView::setScrollOffset(const DoublePoint
& offset
, ScrollType
)
3168 scrollTo(clampScrollPosition(offset
));
3171 void FrameView::windowResizerRectChanged()
3173 updateScrollbars(scrollOffsetDouble());
3176 bool FrameView::hasOverlayScrollbars() const
3179 return (m_horizontalScrollbar
&& m_horizontalScrollbar
->isOverlayScrollbar())
3180 || (m_verticalScrollbar
&& m_verticalScrollbar
->isOverlayScrollbar());
3183 void FrameView::computeScrollbarExistence(bool& newHasHorizontalScrollbar
, bool& newHasVerticalScrollbar
, const IntSize
& docSize
, ComputeScrollbarExistenceOption option
) const
3185 bool hasHorizontalScrollbar
= m_horizontalScrollbar
;
3186 bool hasVerticalScrollbar
= m_verticalScrollbar
;
3188 newHasHorizontalScrollbar
= hasHorizontalScrollbar
;
3189 newHasVerticalScrollbar
= hasVerticalScrollbar
;
3191 if (m_frame
->settings() && m_frame
->settings()->rootLayerScrolls())
3194 ScrollbarMode hScroll
= m_horizontalScrollbarMode
;
3195 ScrollbarMode vScroll
= m_verticalScrollbarMode
;
3197 if (hScroll
!= ScrollbarAuto
)
3198 newHasHorizontalScrollbar
= (hScroll
== ScrollbarAlwaysOn
);
3199 if (vScroll
!= ScrollbarAuto
)
3200 newHasVerticalScrollbar
= (vScroll
== ScrollbarAlwaysOn
);
3202 if (m_scrollbarsSuppressed
|| (hScroll
!= ScrollbarAuto
&& vScroll
!= ScrollbarAuto
))
3205 if (hScroll
== ScrollbarAuto
)
3206 newHasHorizontalScrollbar
= docSize
.width() > visibleWidth();
3207 if (vScroll
== ScrollbarAuto
)
3208 newHasVerticalScrollbar
= docSize
.height() > visibleHeight();
3210 if (hasOverlayScrollbars())
3213 IntSize fullVisibleSize
= visibleContentRect(IncludeScrollbars
).size();
3215 bool attemptToRemoveScrollbars
= (option
== FirstPass
3216 && docSize
.width() <= fullVisibleSize
.width() && docSize
.height() <= fullVisibleSize
.height());
3217 if (attemptToRemoveScrollbars
) {
3218 if (hScroll
== ScrollbarAuto
)
3219 newHasHorizontalScrollbar
= false;
3220 if (vScroll
== ScrollbarAuto
)
3221 newHasVerticalScrollbar
= false;
3225 void FrameView::updateScrollbarGeometry()
3227 if (m_horizontalScrollbar
) {
3228 int clientWidth
= visibleWidth();
3229 IntRect
oldRect(m_horizontalScrollbar
->frameRect());
3230 IntRect
hBarRect((shouldPlaceVerticalScrollbarOnLeft() && m_verticalScrollbar
) ? m_verticalScrollbar
->width() : 0,
3231 height() - m_horizontalScrollbar
->height(),
3232 width() - (m_verticalScrollbar
? m_verticalScrollbar
->width() : 0),
3233 m_horizontalScrollbar
->height());
3234 m_horizontalScrollbar
->setFrameRect(adjustScrollbarRectForResizer(hBarRect
, m_horizontalScrollbar
.get()));
3235 if (!m_scrollbarsSuppressed
&& oldRect
!= m_horizontalScrollbar
->frameRect())
3236 m_horizontalScrollbar
->invalidate();
3238 if (m_scrollbarsSuppressed
)
3239 m_horizontalScrollbar
->setSuppressInvalidation(true);
3240 m_horizontalScrollbar
->setEnabled(contentsWidth() > clientWidth
);
3241 m_horizontalScrollbar
->setProportion(clientWidth
, contentsWidth());
3242 m_horizontalScrollbar
->offsetDidChange();
3243 if (m_scrollbarsSuppressed
)
3244 m_horizontalScrollbar
->setSuppressInvalidation(false);
3247 if (m_verticalScrollbar
) {
3248 int clientHeight
= visibleHeight();
3249 IntRect
oldRect(m_verticalScrollbar
->frameRect());
3250 IntRect
vBarRect(shouldPlaceVerticalScrollbarOnLeft() ? 0 : (width() - m_verticalScrollbar
->width()),
3252 m_verticalScrollbar
->width(),
3253 height() - (m_horizontalScrollbar
? m_horizontalScrollbar
->height() : 0));
3254 m_verticalScrollbar
->setFrameRect(adjustScrollbarRectForResizer(vBarRect
, m_verticalScrollbar
.get()));
3255 if (!m_scrollbarsSuppressed
&& oldRect
!= m_verticalScrollbar
->frameRect())
3256 m_verticalScrollbar
->invalidate();
3258 if (m_scrollbarsSuppressed
)
3259 m_verticalScrollbar
->setSuppressInvalidation(true);
3260 m_verticalScrollbar
->setEnabled(contentsHeight() > clientHeight
);
3261 m_verticalScrollbar
->setProportion(clientHeight
, contentsHeight());
3262 m_verticalScrollbar
->offsetDidChange();
3263 if (m_scrollbarsSuppressed
)
3264 m_verticalScrollbar
->setSuppressInvalidation(false);
3268 IntRect
FrameView::adjustScrollbarRectForResizer(const IntRect
& rect
, Scrollbar
* scrollbar
)
3270 // Get our window resizer rect and see if we overlap. Adjust to avoid the overlap
3272 IntRect
adjustedRect(rect
);
3273 bool overlapsResizer
= false;
3274 if (!rect
.isEmpty() && !windowResizerRect().isEmpty()) {
3275 IntRect resizerRect
= convertFromContainingWindow(windowResizerRect());
3276 if (rect
.intersects(resizerRect
)) {
3277 if (scrollbar
->orientation() == HorizontalScrollbar
) {
3278 int overlap
= rect
.maxX() - resizerRect
.x();
3279 if (overlap
> 0 && resizerRect
.maxX() >= rect
.maxX()) {
3280 adjustedRect
.setWidth(rect
.width() - overlap
);
3281 overlapsResizer
= true;
3284 int overlap
= rect
.maxY() - resizerRect
.y();
3285 if (overlap
> 0 && resizerRect
.maxY() >= rect
.maxY()) {
3286 adjustedRect
.setHeight(rect
.height() - overlap
);
3287 overlapsResizer
= true;
3292 if (overlapsResizer
!= scrollbar
->overlapsResizer()) {
3293 scrollbar
->setOverlapsResizer(overlapsResizer
);
3294 adjustScrollbarsAvoidingResizerCount(overlapsResizer
? 1 : -1);
3296 return adjustedRect
;
3299 bool FrameView::adjustScrollbarExistence(ComputeScrollbarExistenceOption option
)
3301 ASSERT(m_inUpdateScrollbars
);
3303 // If we came in here with the view already needing a layout, then go ahead and do that
3304 // first. (This will be the common case, e.g., when the page changes due to window resizing for example).
3305 // This layout will not re-enter updateScrollbars and does not count towards our max layout pass total.
3306 if (!m_scrollbarsSuppressed
)
3307 scrollbarExistenceDidChange();
3309 bool hasHorizontalScrollbar
= m_horizontalScrollbar
;
3310 bool hasVerticalScrollbar
= m_verticalScrollbar
;
3312 bool newHasHorizontalScrollbar
= false;
3313 bool newHasVerticalScrollbar
= false;
3314 computeScrollbarExistence(newHasHorizontalScrollbar
, newHasVerticalScrollbar
, contentsSize(), option
);
3316 bool scrollbarExistenceChanged
= hasHorizontalScrollbar
!= newHasHorizontalScrollbar
|| hasVerticalScrollbar
!= newHasVerticalScrollbar
;
3317 if (!scrollbarExistenceChanged
)
3320 setHasHorizontalScrollbar(newHasHorizontalScrollbar
);
3321 setHasVerticalScrollbar(newHasVerticalScrollbar
);
3323 if (m_scrollbarsSuppressed
)
3326 if (!hasOverlayScrollbars())
3328 scrollbarExistenceDidChange();
3332 bool FrameView::needsScrollbarReconstruction() const
3334 Element
* customScrollbarElement
= nullptr;
3335 LocalFrame
* customScrollbarFrame
= nullptr;
3336 bool shouldUseCustom
= shouldUseCustomScrollbars(customScrollbarElement
, customScrollbarFrame
);
3338 bool hasAnyScrollbar
= m_horizontalScrollbar
|| m_verticalScrollbar
;
3339 bool hasCustom
= (m_horizontalScrollbar
&& m_horizontalScrollbar
->isCustomScrollbar())
3340 || (m_verticalScrollbar
&& m_verticalScrollbar
->isCustomScrollbar());
3342 return hasAnyScrollbar
&& (shouldUseCustom
!= hasCustom
);
3345 bool FrameView::shouldIgnoreOverflowHidden() const
3347 return m_frame
->settings()->ignoreMainFrameOverflowHiddenQuirk() && m_frame
->isMainFrame();
3350 void FrameView::updateScrollbars(const DoubleSize
& desiredOffset
)
3352 // Avoid drawing two sets of scrollbars when visual viewport is enabled.
3353 if (visualViewportSuppliesScrollbars()) {
3354 setHasHorizontalScrollbar(false);
3355 setHasVerticalScrollbar(false);
3356 setScrollOffsetFromUpdateScrollbars(desiredOffset
);
3360 if (m_inUpdateScrollbars
)
3362 InUpdateScrollbarsScope
inUpdateScrollbarsScope(this);
3364 IntSize oldVisibleSize
= visibleContentSize();
3366 bool scrollbarExistenceChanged
= false;
3368 if (needsScrollbarReconstruction()) {
3369 setHasHorizontalScrollbar(false);
3370 setHasVerticalScrollbar(false);
3371 scrollbarExistenceChanged
= true;
3374 int maxUpdateScrollbarsPass
= hasOverlayScrollbars() || m_scrollbarsSuppressed
? 1 : 3;
3375 for (int updateScrollbarsPass
= 0; updateScrollbarsPass
< maxUpdateScrollbarsPass
; updateScrollbarsPass
++) {
3376 if (!adjustScrollbarExistence(updateScrollbarsPass
? Incremental
: FirstPass
))
3378 scrollbarExistenceChanged
= true;
3381 updateScrollbarGeometry();
3383 if (scrollbarExistenceChanged
) {
3384 // FIXME: Is frameRectsChanged really necessary here? Have any frame rects changed?
3385 frameRectsChanged();
3386 positionScrollbarLayers();
3387 updateScrollCorner();
3390 // FIXME: We don't need to do this if we are composited.
3391 IntSize newVisibleSize
= visibleContentSize();
3392 if (newVisibleSize
.width() > oldVisibleSize
.width()) {
3393 if (shouldPlaceVerticalScrollbarOnLeft())
3394 invalidateRect(IntRect(0, 0, newVisibleSize
.width() - oldVisibleSize
.width(), newVisibleSize
.height()));
3396 invalidateRect(IntRect(oldVisibleSize
.width(), 0, newVisibleSize
.width() - oldVisibleSize
.width(), newVisibleSize
.height()));
3398 if (newVisibleSize
.height() > oldVisibleSize
.height())
3399 invalidateRect(IntRect(0, oldVisibleSize
.height(), newVisibleSize
.width(), newVisibleSize
.height() - oldVisibleSize
.height()));
3401 setScrollOffsetFromUpdateScrollbars(desiredOffset
);
3404 void FrameView::setScrollOffsetFromUpdateScrollbars(const DoubleSize
& offset
)
3406 DoublePoint adjustedScrollPosition
= clampScrollPosition(DoublePoint(offset
));
3408 if (adjustedScrollPosition
!= scrollPositionDouble() || scrollOriginChanged()) {
3409 ScrollableArea::setScrollPosition(adjustedScrollPosition
, ProgrammaticScroll
);
3410 resetScrollOriginChanged();
3414 IntRect
FrameView::rectToCopyOnScroll() const
3416 IntRect scrollViewRect
= convertToContainingWindow(IntRect((shouldPlaceVerticalScrollbarOnLeft() && verticalScrollbar()) ? verticalScrollbar()->width() : 0, 0, visibleWidth(), visibleHeight()));
3417 if (hasOverlayScrollbars()) {
3418 int verticalScrollbarWidth
= (verticalScrollbar() && !hasLayerForVerticalScrollbar()) ? verticalScrollbar()->width() : 0;
3419 int horizontalScrollbarHeight
= (horizontalScrollbar() && !hasLayerForHorizontalScrollbar()) ? horizontalScrollbar()->height() : 0;
3421 scrollViewRect
.setWidth(scrollViewRect
.width() - verticalScrollbarWidth
);
3422 scrollViewRect
.setHeight(scrollViewRect
.height() - horizontalScrollbarHeight
);
3424 return scrollViewRect
;
3427 void FrameView::scrollContentsIfNeeded()
3429 if (m_pendingScrollDelta
.isZero())
3431 DoubleSize scrollDelta
= m_pendingScrollDelta
;
3432 m_pendingScrollDelta
= DoubleSize();
3433 // FIXME: Change scrollContents() to take DoubleSize. crbug.com/414283.
3434 scrollContents(flooredIntSize(scrollDelta
));
3437 void FrameView::scrollContents(const IntSize
& scrollDelta
)
3439 HostWindow
* window
= hostWindow();
3443 TRACE_EVENT0("blink", "FrameView::scrollContents");
3445 IntRect clipRect
= windowClipRect();
3446 IntRect updateRect
= clipRect
;
3447 updateRect
.intersect(rectToCopyOnScroll());
3449 if (!scrollContentsFastPath(-scrollDelta
))
3450 scrollContentsSlowPath(updateRect
);
3452 // This call will move children with native widgets (plugins) and invalidate them as well.
3453 frameRectsChanged();
3456 IntPoint
FrameView::contentsToFrame(const IntPoint
& pointInContentSpace
) const
3458 return pointInContentSpace
- scrollOffset();
3461 IntRect
FrameView::contentsToFrame(const IntRect
& rectInContentSpace
) const
3463 return IntRect(contentsToFrame(rectInContentSpace
.location()), rectInContentSpace
.size());
3466 FloatPoint
FrameView::frameToContents(const FloatPoint
& pointInFrame
) const
3468 return pointInFrame
+ scrollOffset();
3471 IntPoint
FrameView::frameToContents(const IntPoint
& pointInFrame
) const
3473 return pointInFrame
+ scrollOffset();
3476 IntRect
FrameView::frameToContents(const IntRect
& rectInFrame
) const
3478 return IntRect(frameToContents(rectInFrame
.location()), rectInFrame
.size());
3481 IntPoint
FrameView::rootFrameToContents(const IntPoint
& rootFramePoint
) const
3483 IntPoint framePoint
= convertFromContainingWindow(rootFramePoint
);
3484 return frameToContents(framePoint
);
3487 IntRect
FrameView::rootFrameToContents(const IntRect
& rootFrameRect
) const
3489 return IntRect(rootFrameToContents(rootFrameRect
.location()), rootFrameRect
.size());
3492 IntPoint
FrameView::contentsToRootFrame(const IntPoint
& contentsPoint
) const
3494 IntPoint framePoint
= contentsToFrame(contentsPoint
);
3495 return convertToContainingWindow(framePoint
);
3498 IntRect
FrameView::contentsToRootFrame(const IntRect
& contentsRect
) const
3500 IntRect rectInFrame
= contentsToFrame(contentsRect
);
3501 return convertToContainingWindow(rectInFrame
);
3504 FloatPoint
FrameView::rootFrameToContents(const FloatPoint
& windowPoint
) const
3506 FloatPoint framePoint
= convertFromContainingWindow(windowPoint
);
3507 return frameToContents(framePoint
);
3510 IntRect
FrameView::viewportToContents(const IntRect
& rectInViewport
) const
3512 IntRect rectInRootFrame
= m_frame
->host()->visualViewport().viewportToRootFrame(rectInViewport
);
3513 IntRect frameRect
= convertFromContainingWindow(rectInRootFrame
);
3514 return frameToContents(frameRect
);
3517 IntPoint
FrameView::viewportToContents(const IntPoint
& pointInViewport
) const
3519 IntPoint pointInRootFrame
= m_frame
->host()->visualViewport().viewportToRootFrame(pointInViewport
);
3520 IntPoint pointInFrame
= convertFromContainingWindow(pointInRootFrame
);
3521 return frameToContents(pointInFrame
);
3524 IntRect
FrameView::contentsToViewport(const IntRect
& rectInContents
) const
3526 IntRect rectInFrame
= contentsToFrame(rectInContents
);
3527 IntRect rectInRootFrame
= convertToContainingWindow(rectInFrame
);
3528 return m_frame
->host()->visualViewport().rootFrameToViewport(rectInRootFrame
);
3531 IntPoint
FrameView::contentsToViewport(const IntPoint
& pointInContents
) const
3533 IntPoint pointInFrame
= contentsToFrame(pointInContents
);
3534 IntPoint pointInRootFrame
= convertToContainingWindow(pointInFrame
);
3535 return m_frame
->host()->visualViewport().rootFrameToViewport(pointInRootFrame
);
3538 IntRect
FrameView::contentsToScreen(const IntRect
& rect
) const
3540 HostWindow
* window
= hostWindow();
3543 return window
->viewportToScreen(contentsToViewport(rect
));
3546 IntRect
FrameView::soonToBeRemovedContentsToUnscaledViewport(const IntRect
& rectInContents
) const
3548 IntRect rectInFrame
= contentsToFrame(rectInContents
);
3549 IntRect rectInRootFrame
= convertToContainingWindow(rectInFrame
);
3550 return enclosingIntRect(m_frame
->host()->visualViewport().mainViewToViewportCSSPixels(rectInRootFrame
));
3553 IntPoint
FrameView::soonToBeRemovedUnscaledViewportToContents(const IntPoint
& pointInViewport
) const
3555 IntPoint pointInRootFrame
= flooredIntPoint(m_frame
->host()->visualViewport().viewportCSSPixelsToRootFrame(pointInViewport
));
3556 IntPoint pointInThisFrame
= convertFromContainingWindow(pointInRootFrame
);
3557 return frameToContents(pointInThisFrame
);
3560 bool FrameView::containsScrollbarsAvoidingResizer() const
3562 return !m_scrollbarsAvoidingResizer
;
3565 void FrameView::adjustScrollbarsAvoidingResizerCount(int overlapDelta
)
3567 int oldCount
= m_scrollbarsAvoidingResizer
;
3568 m_scrollbarsAvoidingResizer
+= overlapDelta
;
3570 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(overlapDelta
);
3571 } else if (!scrollbarsSuppressed()) {
3572 // If we went from n to 0 or from 0 to n and we're the outermost view,
3573 // we need to invalidate the windowResizerRect(), since it will now need to paint
3575 if ((oldCount
> 0 && m_scrollbarsAvoidingResizer
== 0)
3576 || (oldCount
== 0 && m_scrollbarsAvoidingResizer
> 0))
3577 invalidateRect(windowResizerRect());
3581 void FrameView::setScrollbarsSuppressed(bool suppressed
, bool repaintOnUnsuppress
)
3583 if (suppressed
== m_scrollbarsSuppressed
)
3586 m_scrollbarsSuppressed
= suppressed
;
3588 if (repaintOnUnsuppress
&& !suppressed
) {
3589 if (m_horizontalScrollbar
)
3590 m_horizontalScrollbar
->invalidate();
3591 if (m_verticalScrollbar
)
3592 m_verticalScrollbar
->invalidate();
3594 // Invalidate the scroll corner too on unsuppress.
3595 invalidateScrollCorner(scrollCornerRect());
3599 Scrollbar
* FrameView::scrollbarAtRootFramePoint(const IntPoint
& pointInRootFrame
)
3601 IntPoint pointInFrame
= convertFromContainingWindow(pointInRootFrame
);
3602 return scrollbarAtFramePoint(pointInFrame
);
3605 Scrollbar
* FrameView::scrollbarAtFramePoint(const IntPoint
& pointInFrame
)
3607 if (m_horizontalScrollbar
&& m_horizontalScrollbar
->shouldParticipateInHitTesting() && m_horizontalScrollbar
->frameRect().contains(pointInFrame
))
3608 return m_horizontalScrollbar
.get();
3609 if (m_verticalScrollbar
&& m_verticalScrollbar
->shouldParticipateInHitTesting() && m_verticalScrollbar
->frameRect().contains(pointInFrame
))
3610 return m_verticalScrollbar
.get();
3614 static void positionScrollbarLayer(GraphicsLayer
* graphicsLayer
, Scrollbar
* scrollbar
)
3616 if (!graphicsLayer
|| !scrollbar
)
3619 IntRect scrollbarRect
= scrollbar
->frameRect();
3620 graphicsLayer
->setPosition(scrollbarRect
.location());
3622 if (scrollbarRect
.size() == graphicsLayer
->size())
3625 graphicsLayer
->setSize(scrollbarRect
.size());
3627 if (graphicsLayer
->hasContentsLayer()) {
3628 graphicsLayer
->setContentsRect(IntRect(0, 0, scrollbarRect
.width(), scrollbarRect
.height()));
3632 graphicsLayer
->setDrawsContent(true);
3633 graphicsLayer
->setNeedsDisplay();
3636 static void positionScrollCornerLayer(GraphicsLayer
* graphicsLayer
, const IntRect
& cornerRect
)
3640 graphicsLayer
->setDrawsContent(!cornerRect
.isEmpty());
3641 graphicsLayer
->setPosition(cornerRect
.location());
3642 if (cornerRect
.size() != graphicsLayer
->size())
3643 graphicsLayer
->setNeedsDisplay();
3644 graphicsLayer
->setSize(cornerRect
.size());
3647 void FrameView::positionScrollbarLayers()
3649 positionScrollbarLayer(layerForHorizontalScrollbar(), horizontalScrollbar());
3650 positionScrollbarLayer(layerForVerticalScrollbar(), verticalScrollbar());
3651 positionScrollCornerLayer(layerForScrollCorner(), scrollCornerRect());
3654 bool FrameView::userInputScrollable(ScrollbarOrientation orientation
) const
3656 Document
* document
= frame().document();
3657 Element
* fullscreenElement
= Fullscreen::fullscreenElementFrom(*document
);
3658 if (fullscreenElement
&& fullscreenElement
!= document
->documentElement())
3661 if (frame().settings() && frame().settings()->rootLayerScrolls())
3664 ScrollbarMode mode
= (orientation
== HorizontalScrollbar
) ?
3665 m_horizontalScrollbarMode
: m_verticalScrollbarMode
;
3667 return mode
== ScrollbarAuto
|| mode
== ScrollbarAlwaysOn
;
3670 bool FrameView::shouldPlaceVerticalScrollbarOnLeft() const
3675 LayoutRect
FrameView::scrollIntoView(const LayoutRect
& rectInContent
, const ScrollAlignment
& alignX
, const ScrollAlignment
& alignY
)
3677 LayoutRect
viewRect(visibleContentRect());
3678 LayoutRect exposeRect
= ScrollAlignment::getRectToExpose(viewRect
, rectInContent
, alignX
, alignY
);
3680 double xOffset
= exposeRect
.x();
3681 double yOffset
= exposeRect
.y();
3683 setScrollPosition(DoublePoint(xOffset
, yOffset
), ProgrammaticScroll
);
3685 // Scrolling the FrameView cannot change the input rect's location relative to the document.
3686 return rectInContent
;
3689 IntRect
FrameView::scrollCornerRect() const
3693 if (hasOverlayScrollbars())
3696 if (m_horizontalScrollbar
&& width() - m_horizontalScrollbar
->width() > 0) {
3697 cornerRect
.unite(IntRect(shouldPlaceVerticalScrollbarOnLeft() ? 0 : m_horizontalScrollbar
->width(),
3698 height() - m_horizontalScrollbar
->height(),
3699 width() - m_horizontalScrollbar
->width(),
3700 m_horizontalScrollbar
->height()));
3703 if (m_verticalScrollbar
&& height() - m_verticalScrollbar
->height() > 0) {
3704 cornerRect
.unite(IntRect(shouldPlaceVerticalScrollbarOnLeft() ? 0 : (width() - m_verticalScrollbar
->width()),
3705 m_verticalScrollbar
->height(),
3706 m_verticalScrollbar
->width(),
3707 height() - m_verticalScrollbar
->height()));
3713 bool FrameView::isScrollCornerVisible() const
3715 return !scrollCornerRect().isEmpty();
3718 void FrameView::invalidateScrollCornerRect(const IntRect
& rect
)
3720 invalidateRect(rect
);
3722 layoutView()->invalidateDisplayItemClientForNonCompositingDescendantsOf(*m_scrollCorner
);
3725 ScrollBehavior
FrameView::scrollBehaviorStyle() const
3727 Element
* scrollElement
= m_frame
->document()->scrollingElement();
3728 LayoutObject
* layoutObject
= scrollElement
? scrollElement
->layoutObject() : nullptr;
3729 if (layoutObject
&& layoutObject
->style()->scrollBehavior() == ScrollBehaviorSmooth
)
3730 return ScrollBehaviorSmooth
;
3732 return ScrollBehaviorInstant
;
3735 void FrameView::paint(GraphicsContext
* context
, const IntRect
& rect
)
3737 paint(context
, GlobalPaintNormalPhase
, rect
);
3740 void FrameView::paint(GraphicsContext
* context
, const GlobalPaintFlags globalPaintFlags
, const IntRect
& rect
)
3742 FramePainter(*this).paint(context
, globalPaintFlags
, rect
);
3745 void FrameView::paintContents(GraphicsContext
* context
, const GlobalPaintFlags globalPaintFlags
, const IntRect
& damageRect
)
3747 FramePainter(*this).paintContents(context
, globalPaintFlags
, damageRect
);
3750 bool FrameView::isPointInScrollbarCorner(const IntPoint
& windowPoint
)
3752 if (!scrollbarCornerPresent())
3755 IntPoint framePoint
= convertFromContainingWindow(windowPoint
);
3757 if (m_horizontalScrollbar
) {
3758 int horizontalScrollbarYMin
= m_horizontalScrollbar
->frameRect().y();
3759 int horizontalScrollbarYMax
= m_horizontalScrollbar
->frameRect().y() + m_horizontalScrollbar
->frameRect().height();
3760 int horizontalScrollbarXMin
= m_horizontalScrollbar
->frameRect().x() + m_horizontalScrollbar
->frameRect().width();
3762 return framePoint
.y() > horizontalScrollbarYMin
&& framePoint
.y() < horizontalScrollbarYMax
&& framePoint
.x() > horizontalScrollbarXMin
;
3765 int verticalScrollbarXMin
= m_verticalScrollbar
->frameRect().x();
3766 int verticalScrollbarXMax
= m_verticalScrollbar
->frameRect().x() + m_verticalScrollbar
->frameRect().width();
3767 int verticalScrollbarYMin
= m_verticalScrollbar
->frameRect().y() + m_verticalScrollbar
->frameRect().height();
3769 return framePoint
.x() > verticalScrollbarXMin
&& framePoint
.x() < verticalScrollbarXMax
&& framePoint
.y() > verticalScrollbarYMin
;
3772 bool FrameView::scrollbarCornerPresent() const
3774 return (m_horizontalScrollbar
&& width() - m_horizontalScrollbar
->width() > 0)
3775 || (m_verticalScrollbar
&& height() - m_verticalScrollbar
->height() > 0);
3778 IntRect
FrameView::convertFromScrollbarToContainingView(const Scrollbar
* scrollbar
, const IntRect
& localRect
) const
3780 // Scrollbars won't be transformed within us
3781 IntRect newRect
= localRect
;
3782 newRect
.moveBy(scrollbar
->location());
3786 IntRect
FrameView::convertFromContainingViewToScrollbar(const Scrollbar
* scrollbar
, const IntRect
& parentRect
) const
3788 IntRect newRect
= parentRect
;
3789 // Scrollbars won't be transformed within us
3790 newRect
.moveBy(-scrollbar
->location());
3794 // FIXME: test these on windows
3795 IntPoint
FrameView::convertFromScrollbarToContainingView(const Scrollbar
* scrollbar
, const IntPoint
& localPoint
) const
3797 // Scrollbars won't be transformed within us
3798 IntPoint newPoint
= localPoint
;
3799 newPoint
.moveBy(scrollbar
->location());
3803 IntPoint
FrameView::convertFromContainingViewToScrollbar(const Scrollbar
* scrollbar
, const IntPoint
& parentPoint
) const
3805 IntPoint newPoint
= parentPoint
;
3806 // Scrollbars won't be transformed within us
3807 newPoint
.moveBy(-scrollbar
->location());
3811 void FrameView::setParentVisible(bool visible
)
3813 if (isParentVisible() == visible
)
3816 Widget::setParentVisible(visible
);
3818 if (!isSelfVisible())
3821 for (const auto& child
: m_children
)
3822 child
->setParentVisible(visible
);
3825 void FrameView::show()
3827 if (!isSelfVisible()) {
3828 setSelfVisible(true);
3829 updateScrollableAreaSet();
3830 if (isParentVisible()) {
3831 for (const auto& child
: m_children
)
3832 child
->setParentVisible(true);
3839 void FrameView::hide()
3841 if (isSelfVisible()) {
3842 if (isParentVisible()) {
3843 for (const auto& child
: m_children
)
3844 child
->setParentVisible(false);
3846 setSelfVisible(false);
3847 updateScrollableAreaSet();
3853 void FrameView::setScrollOrigin(const IntPoint
& origin
, bool updatePositionAtAll
, bool updatePositionSynchronously
)
3855 if (scrollOrigin() == origin
)
3858 ScrollableArea::setScrollOrigin(origin
);
3860 // Update if the scroll origin changes, since our position will be different if the content size did not change.
3861 if (updatePositionAtAll
&& updatePositionSynchronously
)
3862 updateScrollbars(scrollOffsetDouble());
3865 int FrameView::viewportWidth() const
3867 int viewportWidth
= layoutSize(IncludeScrollbars
).width();
3868 return adjustForAbsoluteZoom(viewportWidth
, layoutView());
3871 ScrollableArea
* FrameView::scrollableArea()
3873 if (m_viewportScrollableArea
)
3874 return m_viewportScrollableArea
.get();
3876 return layoutViewportScrollableArea();
3879 ScrollableArea
* FrameView::layoutViewportScrollableArea()
3881 Settings
* settings
= frame().settings();
3882 if (!settings
|| !settings
->rootLayerScrolls())
3885 LayoutView
* layoutView
= this->layoutView();
3886 return layoutView
? layoutView
->scrollableArea() : nullptr;
3889 LayoutObject
* FrameView::viewportLayoutObject()
3891 if (Document
* document
= frame().document()) {
3892 if (Element
* element
= document
->viewportDefiningElement())
3893 return element
->layoutObject();
3898 void FrameView::collectAnnotatedRegions(LayoutObject
& layoutObject
, Vector
<AnnotatedRegionValue
>& regions
)
3900 // LayoutTexts don't have their own style, they just use their parent's style,
3901 // so we don't want to include them.
3902 if (layoutObject
.isText())
3905 layoutObject
.addAnnotatedRegions(regions
);
3906 for (LayoutObject
* curr
= layoutObject
.slowFirstChild(); curr
; curr
= curr
->nextSibling())
3907 collectAnnotatedRegions(*curr
, regions
);
3910 void FrameView::collectFrameTimingRequestsRecursive(GraphicsLayerFrameTimingRequests
& graphicsLayerTimingRequests
)
3912 if (!m_frameTimingRequestsDirty
)
3915 collectFrameTimingRequests(graphicsLayerTimingRequests
);
3917 for (Frame
* child
= m_frame
->tree().firstChild(); child
; child
= child
->tree().nextSibling()) {
3918 if (!child
->isLocalFrame())
3921 toLocalFrame(child
)->view()->collectFrameTimingRequestsRecursive(graphicsLayerTimingRequests
);
3923 m_frameTimingRequestsDirty
= false;
3926 void FrameView::collectFrameTimingRequests(GraphicsLayerFrameTimingRequests
& graphicsLayerTimingRequests
)
3928 if (!m_frame
->isLocalFrame())
3930 Frame
* frame
= m_frame
.get();
3931 LocalFrame
* localFrame
= toLocalFrame(frame
);
3932 LayoutRect viewRect
= localFrame
->contentLayoutObject()->viewRect();
3933 const LayoutBoxModelObject
* paintInvalidationContainer
= localFrame
->contentLayoutObject()->containerForPaintInvalidation();
3934 const GraphicsLayer
* graphicsLayer
= paintInvalidationContainer
->enclosingLayer()->graphicsLayerBacking();
3939 DeprecatedPaintLayer::mapRectToPaintInvalidationBacking(localFrame
->contentLayoutObject(), paintInvalidationContainer
, viewRect
);
3941 graphicsLayerTimingRequests
.add(graphicsLayer
, Vector
<std::pair
<int64_t, WebRect
>>()).storedValue
->value
.append(std::make_pair(m_frame
->frameID(), enclosingIntRect(viewRect
)));
3944 } // namespace blink