blob: 709ec18135c0a371b54ab6f8dc772b498631a2ce [file] [log] [blame]
/*
Copyright (C) 1997 Martin Jones (mjones@kde.org)
(C) 1998 Waldo Bastian (bastian@kde.org)
(C) 1998, 1999 Torben Weis (weis@kde.org)
(C) 1999 Lars Knoll (knoll@kde.org)
(C) 1999 Antti Koivisto (koivisto@kde.org)
Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef FrameView_h
#define FrameView_h
#include "core/CoreExport.h"
#include "core/dom/DocumentLifecycle.h"
#include "core/frame/FrameViewAutoSizeInfo.h"
#include "core/frame/LayoutSubtreeRootList.h"
#include "core/frame/RootFrameViewport.h"
#include "core/layout/LayoutAnalyzer.h"
#include "core/paint/PaintInvalidationCapableScrollableArea.h"
#include "core/paint/PaintPhase.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/Widget.h"
#include "platform/geometry/IntRect.h"
#include "platform/geometry/LayoutRect.h"
#include "platform/graphics/Color.h"
#include "platform/graphics/paint/ClipPaintPropertyNode.h"
#include "platform/graphics/paint/TransformPaintPropertyNode.h"
#include "platform/scroll/ScrollTypes.h"
#include "platform/scroll/Scrollbar.h"
#include "public/platform/WebDisplayMode.h"
#include "public/platform/WebRect.h"
#include "wtf/Allocator.h"
#include "wtf/Forward.h"
#include "wtf/HashSet.h"
#include "wtf/ListHashSet.h"
#include "wtf/OwnPtr.h"
#include "wtf/TemporaryChange.h"
#include "wtf/text/WTFString.h"
namespace blink {
class AXObjectCache;
class CancellableTaskFactory;
class ComputedStyle;
class DocumentLifecycle;
class Cursor;
class Element;
class FloatSize;
class HTMLFrameOwnerElement;
class LayoutPart;
class LocalFrame;
class KURL;
class Node;
class LayoutBox;
class LayoutEmbeddedObject;
class LayoutObject;
class LayoutScrollbarPart;
class LayoutView;
class PaintInvalidationState;
class Page;
class ScrollingCoordinator;
class TracedValue;
struct AnnotatedRegionValue;
struct CompositedSelection;
typedef unsigned long long DOMTimeStamp;
class CORE_EXPORT FrameView final : public Widget, public PaintInvalidationCapableScrollableArea {
WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(FrameView);
friend class PaintControllerPaintTestBase;
friend class Internals;
friend class LayoutPart; // for invalidateTreeIfNeeded
public:
static PassRefPtrWillBeRawPtr<FrameView> create(LocalFrame*);
static PassRefPtrWillBeRawPtr<FrameView> create(LocalFrame*, const IntSize& initialSize);
~FrameView() override;
void invalidateRect(const IntRect&) override;
void setFrameRect(const IntRect&) override;
LocalFrame& frame() const
{
ASSERT(m_frame);
return *m_frame;
}
Page* page() const;
LayoutView* layoutView() const;
void setCanHaveScrollbars(bool);
PassRefPtrWillBeRawPtr<Scrollbar> createScrollbar(ScrollbarOrientation);
void setContentsSize(const IntSize&);
void layout();
bool didFirstLayout() const;
void scheduleRelayout();
void scheduleRelayoutOfSubtree(LayoutObject*);
bool layoutPending() const;
bool isInPerformLayout() const;
void clearLayoutSubtreeRoot(const LayoutObject&);
int layoutCount() const { return m_layoutCount; }
void countObjectsNeedingLayout(unsigned& needsLayoutObjects, unsigned& totalObjects, bool& isPartial);
bool needsLayout() const;
void setNeedsLayout();
void setNeedsUpdateWidgetGeometries() { m_needsUpdateWidgetGeometries = true; }
// Methods for getting/setting the size Blink should use to layout the contents.
// NOTE: Scrollbar exclusion is based on the FrameView's scrollbars. To exclude
// scrollbars on the root PaintLayer, use LayoutView::layoutSize.
IntSize layoutSize(IncludeScrollbarsInRect = ExcludeScrollbars) const;
void setLayoutSize(const IntSize&);
// If this is set to false, the layout size will need to be explicitly set by the owner.
// E.g. WebViewImpl sets its mainFrame's layout size manually
void setLayoutSizeFixedToFrameSize(bool isFixed) { m_layoutSizeFixedToFrameSize = isFixed; }
bool layoutSizeFixedToFrameSize() { return m_layoutSizeFixedToFrameSize; }
bool needsFullPaintInvalidation() const { return m_doFullPaintInvalidation; }
void updateAcceleratedCompositingSettings();
void recalcOverflowAfterStyleChange();
bool isEnclosedInCompositingLayer() const;
void dispose() override;
void detachScrollbars();
void recalculateCustomScrollbarStyle();
void invalidateAllCustomScrollbarsOnActiveChanged();
virtual void recalculateScrollbarOverlayStyle();
void clear();
bool isTransparent() const;
void setTransparent(bool isTransparent);
// True if the FrameView is not transparent, and the base background color is opaque.
bool hasOpaqueBackground() const;
Color baseBackgroundColor() const;
void setBaseBackgroundColor(const Color&);
void updateBackgroundRecursively(const Color&, bool);
void adjustViewSize();
// Scale used to convert incoming input events.
float inputEventsScaleFactor() const;
// Offset used to convert incoming input events while emulating device metics.
IntSize inputEventsOffsetForEmulation() const;
void setInputEventsTransformForEmulation(const IntSize&, float);
void setScrollPosition(const DoublePoint&, ScrollType, ScrollBehavior = ScrollBehaviorInstant) override;
void didUpdateElasticOverscroll();
void viewportSizeChanged(bool widthChanged, bool heightChanged);
AtomicString mediaType() const;
void setMediaType(const AtomicString&);
void adjustMediaTypeForPrinting(bool printing);
WebDisplayMode displayMode() { return m_displayMode; }
void setDisplayMode(WebDisplayMode);
// Fixed-position objects.
typedef HashSet<LayoutObject*> ViewportConstrainedObjectSet;
void addViewportConstrainedObject(LayoutObject*);
void removeViewportConstrainedObject(LayoutObject*);
const ViewportConstrainedObjectSet* viewportConstrainedObjects() const { return m_viewportConstrainedObjects.get(); }
bool hasViewportConstrainedObjects() const { return m_viewportConstrainedObjects && m_viewportConstrainedObjects->size() > 0; }
// Objects with background-attachment:fixed.
void addBackgroundAttachmentFixedObject(LayoutObject*);
void removeBackgroundAttachmentFixedObject(LayoutObject*);
bool hasBackgroundAttachmentFixedObjects() const { return m_backgroundAttachmentFixedObjects.size(); }
void invalidateBackgroundAttachmentFixedObjects();
void handleLoadCompleted();
void updateDocumentAnnotatedRegions() const;
void restoreScrollbar();
void postLayoutTimerFired(Timer<FrameView>*);
bool safeToPropagateScrollToParent() const { return m_safeToPropagateScrollToParent; }
void setSafeToPropagateScrollToParent(bool isSafe) { m_safeToPropagateScrollToParent = isSafe; }
void addPart(LayoutPart*);
void removePart(LayoutPart*);
void updateWidgetGeometries();
void addPartToUpdate(LayoutEmbeddedObject&);
void setIsPainting(bool val) const { m_isPainting = val; }
bool isPainting() const;
void setNodeToDraw(Node*);
Node* nodeToDraw() const { return m_nodeToDraw.get(); }
Color documentBackgroundColor() const;
// Run all needed lifecycle stages. After calling this method, all frames will be in the lifecycle state PaintInvalidationClean.
// If lifecycle throttling is allowed (see DocumentLifecycle::PreventThrottlingScope), some frames may skip the lifecycle update
// (e.g., based on visibility) and will not end up being PaintInvalidationClean.
void updateAllLifecyclePhases();
// Computes the style, layout and compositing lifecycle stages if needed. After calling this method, all frames will be in a lifecycle
// state >= CompositingClean, and scrolling has been updated (unless throttling is allowed).
void updateLifecycleToCompositingCleanPlusScrolling();
// Computes only the style and layout lifecycle stages.
// After calling this method, all frames will be in a lifecycle state >= LayoutClean (unless throttling is allowed).
void updateLifecycleToLayoutClean();
void scheduleVisualUpdateForPaintInvalidationIfNeeded();
bool invalidateViewportConstrainedObjects();
void incrementVisuallyNonEmptyCharacterCount(unsigned);
void incrementVisuallyNonEmptyPixelCount(const IntSize&);
bool isVisuallyNonEmpty() const { return m_isVisuallyNonEmpty; }
void setIsVisuallyNonEmpty() { m_isVisuallyNonEmpty = true; }
void enableAutoSizeMode(const IntSize& minSize, const IntSize& maxSize);
void disableAutoSizeMode();
void forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor);
enum UrlFragmentBehavior {
UrlFragmentScroll,
UrlFragmentDontScroll
};
bool processUrlFragment(const KURL&, UrlFragmentBehavior = UrlFragmentScroll);
void clearScrollAnchor();
// Methods to convert points and rects between the coordinate space of the layoutObject, and this view.
IntRect convertFromLayoutObject(const LayoutObject&, const IntRect&) const;
IntRect convertToLayoutObject(const LayoutObject&, const IntRect&) const;
IntPoint convertFromLayoutObject(const LayoutObject&, const IntPoint&) const;
IntPoint convertToLayoutObject(const LayoutObject&, const IntPoint&) const;
bool isFrameViewScrollCorner(LayoutScrollbarPart* scrollCorner) const { return m_scrollCorner == scrollCorner; }
enum ScrollingReasons {
Scrollable,
NotScrollableNoOverflow,
NotScrollableNotVisible,
NotScrollableExplicitlyDisabled
};
ScrollingReasons scrollingReasons();
bool isScrollable() override;
bool isProgrammaticallyScrollable() override;
enum ScrollbarModesCalculationStrategy { RulesFromWebContentOnly, AnyRule };
void calculateScrollbarModes(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy = AnyRule);
IntPoint lastKnownMousePosition() const override;
bool shouldSetCursor() const;
void setCursor(const Cursor&);
bool scrollbarsCanBeActive() const override;
void scrollbarVisibilityChanged() override;
// FIXME: Remove this method once plugin loading is decoupled from layout.
void flushAnyPendingPostLayoutTasks();
bool shouldSuspendScrollAnimations() const override;
void scrollbarStyleChanged() override;
LayoutBox* embeddedContentBox() const;
static void setInitialTracksPaintInvalidationsForTesting(bool);
void setTracksPaintInvalidations(bool);
bool isTrackingPaintInvalidations() const { return m_isTrackingPaintInvalidations; }
void resetTrackedPaintInvalidations();
using ScrollableAreaSet = WillBeHeapHashSet<RawPtrWillBeMember<ScrollableArea>>;
void addScrollableArea(ScrollableArea*);
void removeScrollableArea(ScrollableArea*);
const ScrollableAreaSet* scrollableAreas() const { return m_scrollableAreas.get(); }
void addAnimatingScrollableArea(ScrollableArea*);
void removeAnimatingScrollableArea(ScrollableArea*);
const ScrollableAreaSet* animatingScrollableAreas() const { return m_animatingScrollableAreas.get(); }
// With CSS style "resize:" enabled, a little resizer handle will appear at the bottom
// right of the object. We keep track of these resizer areas for checking if touches
// (implemented using Scroll gesture) are targeting the resizer.
typedef HashSet<LayoutBox*> ResizerAreaSet;
void addResizerArea(LayoutBox&);
void removeResizerArea(LayoutBox&);
const ResizerAreaSet* resizerAreas() const { return m_resizerAreas.get(); }
bool shouldUseIntegerScrollOffset() const override;
bool isActive() const override;
// Override scrollbar notifications to update the AXObject cache.
void didAddScrollbar(Scrollbar&, ScrollbarOrientation) override;
// FIXME: This should probably be renamed as the 'inSubtreeLayout' parameter
// passed around the FrameView layout methods can be true while this returns
// false.
bool isSubtreeLayout() const { return !m_layoutSubtreeRootList.isEmpty(); }
// Sets the tickmarks for the FrameView, overriding the default behavior
// which is to display the tickmarks corresponding to find results.
// If |m_tickmarks| is empty, the default behavior is restored.
void setTickmarks(const Vector<IntRect>& tickmarks)
{
m_tickmarks = tickmarks;
invalidatePaintForTickmarks();
}
void invalidatePaintForTickmarks();
// Since the compositor can resize the viewport due to top controls and
// commit scroll offsets before a WebView::resize occurs, we need to adjust
// our scroll extents to prevent clamping the scroll offsets.
void setTopControlsViewportAdjustment(float);
IntSize topControlsSize() const { return IntSize(0, roundf(m_topControlsViewportAdjustment)); }
IntPoint maximumScrollPosition() const override;
// ScrollableArea interface
void scrollControlWasSetNeedsPaintInvalidation() override { }
void getTickmarks(Vector<IntRect>&) const override;
void scrollTo(const DoublePoint&);
IntRect scrollableAreaBoundingBox() const override;
bool scrollAnimatorEnabled() const override;
bool usesCompositedScrolling() const override;
GraphicsLayer* layerForScrolling() const override;
GraphicsLayer* layerForHorizontalScrollbar() const override;
GraphicsLayer* layerForVerticalScrollbar() const override;
GraphicsLayer* layerForScrollCorner() const override;
int scrollSize(ScrollbarOrientation) const override;
bool isScrollCornerVisible() const override;
bool userInputScrollable(ScrollbarOrientation) const override;
bool shouldPlaceVerticalScrollbarOnLeft() const override;
Widget* widget() override;
LayoutRect scrollIntoView(
const LayoutRect& rectInContent,
const ScrollAlignment& alignX,
const ScrollAlignment& alignY,
ScrollType = ProgrammaticScroll) override;
// The window that hosts the FrameView. The FrameView will communicate scrolls and repaints to the
// host window in the window's coordinate space.
HostWindow* hostWindow() const;
// Returns a clip rect in host window coordinates. Used to clip the blit on a scroll.
IntRect windowClipRect(IncludeScrollbarsInRect = ExcludeScrollbars) const;
typedef WillBeHeapHashSet<RefPtrWillBeMember<Widget>> ChildrenWidgetSet;
// Functions for child manipulation and inspection.
void setParent(Widget*) override;
void removeChild(Widget*);
void addChild(PassRefPtrWillBeRawPtr<Widget>);
const ChildrenWidgetSet* children() const { return &m_children; }
// If the scroll view does not use a native widget, then it will have cross-platform Scrollbars. These functions
// can be used to obtain those scrollbars.
Scrollbar* horizontalScrollbar() const override { return m_horizontalScrollbar.get(); }
Scrollbar* verticalScrollbar() const override { return m_verticalScrollbar.get(); }
LayoutScrollbarPart* scrollCorner() const override { return m_scrollCorner; }
void positionScrollbarLayers();
// Functions for setting and retrieving the scrolling mode in each axis (horizontal/vertical). The mode has values of
// AlwaysOff, AlwaysOn, and Auto. AlwaysOff means never show a scrollbar, AlwaysOn means always show a scrollbar.
// Auto means show a scrollbar only when one is needed.
// Note that for platforms with native widgets, these modes are considered advisory. In other words the underlying native
// widget may choose not to honor the requested modes.
void setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode, bool horizontalLock = false, bool verticalLock = false);
void setHorizontalScrollbarMode(ScrollbarMode mode, bool lock = false) { setScrollbarModes(mode, verticalScrollbarMode(), lock, verticalScrollbarLock()); }
void setVerticalScrollbarMode(ScrollbarMode mode, bool lock = false) { setScrollbarModes(horizontalScrollbarMode(), mode, horizontalScrollbarLock(), lock); }
ScrollbarMode horizontalScrollbarMode() const { return m_horizontalScrollbarMode; }
ScrollbarMode verticalScrollbarMode() const { return m_verticalScrollbarMode; }
void setHorizontalScrollbarLock(bool lock = true) { m_horizontalScrollbarLock = lock; }
bool horizontalScrollbarLock() const { return m_horizontalScrollbarLock; }
void setVerticalScrollbarLock(bool lock = true) { m_verticalScrollbarLock = lock; }
bool verticalScrollbarLock() const { return m_verticalScrollbarLock; }
void setScrollingModesLock(bool lock = true) { m_horizontalScrollbarLock = m_verticalScrollbarLock = lock; }
bool canHaveScrollbars() const { return horizontalScrollbarMode() != ScrollbarAlwaysOff || verticalScrollbarMode() != ScrollbarAlwaysOff; }
// The visible content rect has a location that is the scrolled offset of
// the document. The width and height are the layout viewport width and
// height. By default the scrollbars themselves are excluded from this
// rectangle, but an optional boolean argument allows them to be included.
IntRect visibleContentRect(IncludeScrollbarsInRect = ExcludeScrollbars) const override;
IntSize visibleContentSize(IncludeScrollbarsInRect = ExcludeScrollbars) const;
// Functions for getting/setting the size of the document contained inside the FrameView (as an IntSize or as individual width and height
// values).
IntSize contentsSize() const override; // Always at least as big as the visibleWidth()/visibleHeight().
int contentsWidth() const { return contentsSize().width(); }
int contentsHeight() const { return contentsSize().height(); }
// Functions for querying the current scrolled position (both as a point, a size, or as individual X and Y values).
// Be careful in using the Double version scrollPositionDouble() and scrollOffsetDouble(). They are meant to be
// used to communicate the fractional scroll position/offset with chromium compositor which can do sub-pixel positioning.
// Do not call these if the scroll position/offset is used in Blink for positioning. Use the Int version instead.
IntPoint scrollPosition() const override { return visibleContentRect().location(); }
DoublePoint scrollPositionDouble() const override { return m_scrollPosition; }
IntSize scrollOffset() const { return toIntSize(visibleContentRect().location()); } // Gets the scrolled position as an IntSize. Convenient for adding to other sizes.
DoubleSize scrollOffsetDouble() const { return DoubleSize(m_scrollPosition.x(), m_scrollPosition.y()); }
DoubleSize pendingScrollDelta() const { return m_pendingScrollDelta; }
IntPoint minimumScrollPosition() const override; // The minimum position we can be scrolled to.
int scrollX() const { return scrollPosition().x(); }
int scrollY() const { return scrollPosition().y(); }
// Scroll the actual contents of the view (either blitting or invalidating as needed).
void scrollContents(const IntSize& scrollDelta);
// This gives us a means of blocking updating our scrollbars until the first layout has occurred.
void setScrollbarsSuppressed(bool suppressed) { m_scrollbarsSuppressed = suppressed; }
bool scrollbarsSuppressed() const { return m_scrollbarsSuppressed; }
// Methods for converting between this frame and other coordinate spaces.
// For definitions and an explanation of the varous spaces, please see:
// http://www.chromium.org/developers/design-documents/blink-coordinate-spaces
IntPoint rootFrameToContents(const IntPoint&) const;
FloatPoint rootFrameToContents(const FloatPoint&) const;
IntRect rootFrameToContents(const IntRect&) const;
IntPoint contentsToRootFrame(const IntPoint&) const;
IntRect contentsToRootFrame(const IntRect&) const;
IntRect viewportToContents(const IntRect&) const;
IntRect contentsToViewport(const IntRect&) const;
IntPoint contentsToViewport(const IntPoint&) const;
IntPoint viewportToContents(const IntPoint&) const;
// FIXME: Some external callers expect to get back a rect that's positioned
// in viewport space, but sized in CSS pixels. This is an artifact of the
// old pinch-zoom path. These callers should be converted to expect a rect
// fully in viewport space. crbug.com/459591.
IntRect soonToBeRemovedContentsToUnscaledViewport(const IntRect&) const;
IntPoint soonToBeRemovedUnscaledViewportToContents(const IntPoint&) const;
// Methods for converting between Frame and Content (i.e. Document) coordinates.
// Frame coordinates are relative to the top left corner of the frame and so
// they are affected by scroll offset. Content coordinates are relative to the
// document's top left corner and thus are not affected by scroll offset.
IntPoint contentsToFrame(const IntPoint&) const;
IntRect contentsToFrame(const IntRect&) const;
IntPoint frameToContents(const IntPoint&) const;
FloatPoint frameToContents(const FloatPoint&) const;
IntRect frameToContents(const IntRect&) const;
// Functions for converting to screen coordinates.
IntRect contentsToScreen(const IntRect&) const;
// These functions are used to enable scrollbars to avoid window resizer controls that overlap the scroll view.
// This happens only on Mac OS X 10.6.
IntRect windowResizerRect() const;
bool containsScrollbarsAvoidingResizer() const;
void adjustScrollbarsAvoidingResizerCount(int overlapDelta);
void windowResizerRectChanged();
// For platforms that need to hit test scrollbars from within the engine's event handlers (like Win32).
Scrollbar* scrollbarAtFramePoint(const IntPoint&);
IntPoint convertChildToSelf(const Widget* child, const IntPoint& point) const override
{
IntPoint newPoint = point;
if (!isFrameViewScrollbar(child))
newPoint = contentsToFrame(point);
newPoint.moveBy(child->location());
return newPoint;
}
IntPoint convertSelfToChild(const Widget* child, const IntPoint& point) const override
{
IntPoint newPoint = point;
if (!isFrameViewScrollbar(child))
newPoint = frameToContents(point);
newPoint.moveBy(-child->location());
return newPoint;
}
// Widget override. Handles painting of the contents of the view as well as the scrollbars.
void paint(GraphicsContext&, const CullRect&) const override;
void paint(GraphicsContext&, const GlobalPaintFlags, const CullRect&) const;
void paintContents(GraphicsContext&, const GlobalPaintFlags, const IntRect& damageRect) const;
// Widget overrides to ensure that our children's visibility status is kept up to date when we get shown and hidden.
void show() override;
void hide() override;
void setParentVisible(bool) override;
bool isPointInScrollbarCorner(const IntPoint&);
bool scrollbarCornerPresent() const;
IntRect scrollCornerRect() const override;
IntRect convertFromScrollbarToContainingWidget(const Scrollbar&, const IntRect&) const override;
IntRect convertFromContainingWidgetToScrollbar(const Scrollbar&, const IntRect&) const override;
IntPoint convertFromScrollbarToContainingWidget(const Scrollbar&, const IntPoint&) const override;
IntPoint convertFromContainingWidgetToScrollbar(const Scrollbar&, const IntPoint&) const override;
bool isFrameView() const override { return true; }
DECLARE_VIRTUAL_TRACE();
void notifyPageThatContentAreaWillPaint() const;
FrameView* parentFrameView() const;
// Returns the scrollable area for the frame. For the root frame, this will
// be the RootFrameViewport, which adds pinch-zoom semantics to scrolling.
// For non-root frames, this will be the the ScrollableArea used by the
// FrameView, depending on whether root-layer-scrolls is enabled.
ScrollableArea* scrollableArea();
// Used to get at the underlying layoutViewport in the rare instances where
// we actually want to scroll *just* the layout viewport (e.g. when sending
// deltas from CC). For typical scrolling cases, use scrollableArea().
ScrollableArea* layoutViewportScrollableArea();
int viewportWidth() const;
LayoutAnalyzer* layoutAnalyzer() { return m_analyzer.get(); }
// Returns true if the default scrolling direction is vertical. i.e. writing mode
// is horiziontal. In a vertical document, a spacebar scrolls down.
bool isVerticalDocument() const;
// Returns true if the document's writing mode is right-to-left or bottom-to-top.
bool isFlippedDocument() const;
void setFrameTimingRequestsDirty(bool isDirty) { m_frameTimingRequestsDirty = isDirty; }
bool frameTimingRequestsDirty() { return m_frameTimingRequestsDirty; }
// Returns true if this frame should not render or schedule visual updates.
bool shouldThrottleRendering() const;
// Returns true if this frame could potentially skip rendering and avoid
// scheduling visual updates.
bool canThrottleRendering() const;
bool isHiddenForThrottling() const { return m_hiddenForThrottling; }
// Paint properties for SPv2 Only.
void setPreTranslation(PassRefPtr<TransformPaintPropertyNode> preTranslation) { m_preTranslation = preTranslation; }
const TransformPaintPropertyNode* preTranslation() const { return m_preTranslation.get(); }
void setScrollTranslation(PassRefPtr<TransformPaintPropertyNode> scrollTranslation) { m_scrollTranslation = scrollTranslation; }
const TransformPaintPropertyNode* scrollTranslation() const { return m_scrollTranslation.get(); }
void setContentClip(PassRefPtr<ClipPaintPropertyNode> contentClip) { m_contentClip = contentClip; }
const ClipPaintPropertyNode* contentClip() const { return m_contentClip.get(); }
// TODO(ojan): Merge this with IntersectionObserver once it lands.
IntRect computeVisibleArea();
protected:
// Scroll the content via the compositor.
bool scrollContentsFastPath(const IntSize& scrollDelta);
// Scroll the content by invalidating everything.
void scrollContentsSlowPath(const IntRect& updateRect);
// These functions are used to create/destroy scrollbars.
void setHasHorizontalScrollbar(bool);
void setHasVerticalScrollbar(bool);
ScrollBehavior scrollBehaviorStyle() const override;
void scrollContentsIfNeeded();
void setScrollOrigin(const IntPoint&, bool updatePositionAtAll, bool updatePositionSynchronously);
enum ComputeScrollbarExistenceOption {
FirstPass,
Incremental
};
void computeScrollbarExistence(bool& newHasHorizontalScrollbar, bool& newHasVerticalScrollbar, const IntSize& docSize, ComputeScrollbarExistenceOption = FirstPass) const;
void updateScrollbarGeometry();
IntRect adjustScrollbarRectForResizer(const IntRect&, Scrollbar&);
// Called to update the scrollbars to accurately reflect the state of the view.
void updateScrollbars(const DoubleSize& desiredOffset);
class InUpdateScrollbarsScope {
STACK_ALLOCATED();
public:
explicit InUpdateScrollbarsScope(FrameView* view)
: m_scope(view->m_inUpdateScrollbars, true)
{ }
private:
TemporaryChange<bool> m_scope;
};
// Only for LayoutPart to traverse into sub frames during paint invalidation.
void invalidateTreeIfNeeded(PaintInvalidationState&);
private:
explicit FrameView(LocalFrame*);
void setScrollOffset(const IntPoint&, ScrollType) override;
void setScrollOffset(const DoublePoint&, ScrollType) override;
enum LifeCycleUpdateOption {
OnlyUpToLayoutClean,
OnlyUpToCompositingCleanPlusScrolling,
AllPhases,
};
void updateLifecyclePhasesInternal(LifeCycleUpdateOption);
void invalidateTreeIfNeededRecursive();
void scrollContentsIfNeededRecursive();
void updateStyleAndLayoutIfNeededRecursive();
void updatePaintProperties();
void synchronizedPaint();
void synchronizedPaintRecursively(GraphicsLayer*);
void pushPaintArtifactToCompositor();
void reset();
void init();
void clearLayoutSubtreeRootsAndMarkContainingBlocks();
// Called when our frame rect changes (or the rect/scroll position of an ancestor changes).
void frameRectsChanged() override;
bool contentsInCompositedLayer() const;
void calculateScrollbarModesFromOverflowStyle(const ComputedStyle*, ScrollbarMode& hMode, ScrollbarMode& vMode);
void updateCounters();
void forceLayoutParentViewIfNeeded();
void performPreLayoutTasks();
void performLayout(bool inSubtreeLayout);
void scheduleOrPerformPostLayoutTasks();
void performPostLayoutTasks();
DocumentLifecycle& lifecycle() const;
void contentsResized() override;
void scrollbarExistenceDidChange();
// Override Widget methods to do point conversion via layoutObjects, in order to
// take transforms into account.
IntRect convertToContainingWidget(const IntRect&) const override;
IntRect convertFromContainingWidget(const IntRect&) const override;
IntPoint convertToContainingWidget(const IntPoint&) const override;
IntPoint convertFromContainingWidget(const IntPoint&) const override;
void updateWidgetGeometriesIfNeeded();
bool wasViewportResized();
void sendResizeEventIfNeeded();
void updateScrollableAreaSet();
void scheduleUpdateWidgetsIfNecessary();
void updateWidgetsTimerFired(Timer<FrameView>*);
bool updateWidgets();
bool processUrlFragmentHelper(const String&, UrlFragmentBehavior);
void maintainScrollPositionAtAnchor(Node*);
void scrollToAnchor();
void scrollPositionChanged();
void didScrollTimerFired(Timer<FrameView>*);
void updateLayersAndCompositingAfterScrollIfNeeded();
static bool computeCompositedSelection(LocalFrame&, CompositedSelection&);
void updateCompositedSelectionIfNeeded();
// Returns true if the FrameView's own scrollbars overlay its content when visible.
bool hasOverlayScrollbars() const;
// Returns true if the frame should use custom scrollbars. If true, one of
// either |customScrollbarElement| or |customScrollbarFrame| will be set to
// the element or frame which owns the scrollbar with the other set to null.
bool shouldUseCustomScrollbars(Element*& customScrollbarElement, LocalFrame*& customScrollbarFrame) const;
// Returns true if a scrollbar needs to go from native -> custom or vice versa.
bool needsScrollbarReconstruction() const;
bool shouldIgnoreOverflowHidden() const;
void updateScrollCorner();
AXObjectCache* axObjectCache() const;
void removeFromAXObjectCache();
void setLayoutSizeInternal(const IntSize&);
bool adjustScrollbarExistence(ComputeScrollbarExistenceOption = FirstPass);
void adjustScrollbarOpacity();
void setScrollOffsetFromUpdateScrollbars(const DoubleSize&);
bool visualViewportSuppliesScrollbars() const;
IntRect rectToCopyOnScroll() const;
bool isFrameViewScrollbar(const Widget* child) const { return horizontalScrollbar() == child || verticalScrollbar() == child; }
ScrollingCoordinator* scrollingCoordinator();
void prepareLayoutAnalyzer();
PassRefPtr<TracedValue> analyzerCounters();
// LayoutObject for the viewport-defining element (see Document::viewportDefiningElement).
LayoutObject* viewportLayoutObject();
void collectAnnotatedRegions(LayoutObject&, Vector<AnnotatedRegionValue>&) const;
typedef WTF::HashMap <const GraphicsLayer*, Vector<std::pair<int64_t, WebRect>>> GraphicsLayerFrameTimingRequests;
void updateFrameTimingRequestsIfNeeded();
void collectFrameTimingRequests(GraphicsLayerFrameTimingRequests&);
void collectFrameTimingRequestsRecursive(GraphicsLayerFrameTimingRequests&);
template <typename Function> void forAllNonThrottledFrameViews(Function);
void setNeedsUpdateViewportIntersection();
void updateViewportIntersectionsForSubtree(LifeCycleUpdateOption);
void updateViewportIntersectionIfNeeded();
void notifyRenderThrottlingObservers();
// PaintInvalidationCapableScrollableArea
LayoutBox& boxForScrollControlPaintInvalidation() const override;
LayoutScrollbarPart* resizer() const override { return nullptr; }
LayoutSize m_size;
typedef HashSet<RefPtr<LayoutEmbeddedObject>> EmbeddedObjectSet;
EmbeddedObjectSet m_partUpdateSet;
// FIXME: These are just "children" of the FrameView and should be RefPtrWillBeMember<Widget> instead.
HashSet<RefPtr<LayoutPart>> m_parts;
// The RefPtr cycle between LocalFrame and FrameView is broken
// when a LocalFrame is detached by LocalFrame::detach().
// It clears the LocalFrame's m_view reference via setView(nullptr).
//
// For Oilpan, Member reference cycles pose no problem, but
// LocalFrame's FrameView is also cleared by that setView(), so as to
// keep the observable lifespan of LocalFrame::view() identical.
RefPtrWillBeMember<LocalFrame> m_frame;
WebDisplayMode m_displayMode;
bool m_doFullPaintInvalidation;
bool m_canHaveScrollbars;
bool m_hasPendingLayout;
LayoutSubtreeRootList m_layoutSubtreeRootList;
bool m_layoutSchedulingEnabled;
bool m_inSynchronousPostLayout;
int m_layoutCount;
unsigned m_nestedLayoutCount;
Timer<FrameView> m_postLayoutTasksTimer;
Timer<FrameView> m_updateWidgetsTimer;
OwnPtr<CancellableTaskFactory> m_renderThrottlingObserverNotificationFactory;
bool m_firstLayout;
bool m_isTransparent;
Color m_baseBackgroundColor;
IntSize m_lastViewportSize;
float m_lastZoomFactor;
AtomicString m_mediaType;
AtomicString m_mediaTypeWhenNotPrinting;
bool m_safeToPropagateScrollToParent;
bool m_isTrackingPaintInvalidations; // Used for testing.
RefPtrWillBeMember<Node> m_nodeToDraw;
// TODO(wangxianzhu): Use document cycle state for spv2 and synchronzied painting.
mutable bool m_isPainting;
unsigned m_visuallyNonEmptyCharacterCount;
unsigned m_visuallyNonEmptyPixelCount;
bool m_isVisuallyNonEmpty;
RefPtrWillBeMember<Node> m_scrollAnchor;
// layoutObject to hold our custom scroll corner.
LayoutScrollbarPart* m_scrollCorner;
OwnPtrWillBeMember<ScrollableAreaSet> m_scrollableAreas;
OwnPtrWillBeMember<ScrollableAreaSet> m_animatingScrollableAreas;
OwnPtr<ResizerAreaSet> m_resizerAreas;
OwnPtr<ViewportConstrainedObjectSet> m_viewportConstrainedObjects;
ViewportConstrainedObjectSet m_backgroundAttachmentFixedObjects;
OwnPtrWillBeMember<FrameViewAutoSizeInfo> m_autoSizeInfo;
IntSize m_inputEventsOffsetForEmulation;
float m_inputEventsScaleFactorForEmulation;
IntSize m_layoutSize;
bool m_layoutSizeFixedToFrameSize;
Timer<FrameView> m_didScrollTimer;
Vector<IntRect> m_tickmarks;
float m_topControlsViewportAdjustment;
bool m_needsUpdateWidgetGeometries;
bool m_needsUpdateViewportIntersection;
bool m_needsUpdateViewportIntersectionInSubtree;
#if ENABLE(ASSERT)
// Verified when finalizing.
bool m_hasBeenDisposed;
#endif
RefPtrWillBeMember<Scrollbar> m_horizontalScrollbar;
RefPtrWillBeMember<Scrollbar> m_verticalScrollbar;
ScrollbarMode m_horizontalScrollbarMode;
ScrollbarMode m_verticalScrollbarMode;
bool m_horizontalScrollbarLock;
bool m_verticalScrollbarLock;
ChildrenWidgetSet m_children;
DoubleSize m_pendingScrollDelta;
DoublePoint m_scrollPosition;
IntSize m_contentsSize;
int m_scrollbarsAvoidingResizer;
bool m_scrollbarsSuppressed;
bool m_inUpdateScrollbars;
OwnPtr<LayoutAnalyzer> m_analyzer;
// Mark if something has changed in the mapping from Frame to GraphicsLayer
// and the Frame Timing regions should be recalculated.
bool m_frameTimingRequestsDirty;
// Exists only on root frame.
// TODO(bokan): crbug.com/484188. We should specialize FrameView for the
// main frame.
OwnPtrWillBeMember<ScrollableArea> m_viewportScrollableArea;
// This frame's bounds in the root frame's content coordinates, clipped
// recursively through every ancestor view.
IntRect m_viewportIntersection;
bool m_viewportIntersectionValid;
// The following members control rendering pipeline throttling for this
// frame. They are only updated in response to intersection observer
// notifications, i.e., not in the middle of the lifecycle.
bool m_hiddenForThrottling;
bool m_crossOriginForThrottling;
// Paint properties for SPv2 Only.
// The hierarchy of transform subtree created by a FrameView.
// [ preTranslation ] The offset from Widget::frameRect. Establishes viewport.
// +---[ scrollTranslation ] Frame scrolling.
// TODO(trchen): This is going away in favor of Settings::rootLayerScrolls.
RefPtr<TransformPaintPropertyNode> m_preTranslation;
RefPtr<TransformPaintPropertyNode> m_scrollTranslation;
// The content clip clips the document (= LayoutView) but not the scrollbars.
// TODO(trchen): Going away in favor of Settings::rootLayerScrolls too.
RefPtr<ClipPaintPropertyNode> m_contentClip;
bool m_isUpdatingAllLifecyclePhases;
};
inline void FrameView::incrementVisuallyNonEmptyCharacterCount(unsigned count)
{
if (m_isVisuallyNonEmpty)
return;
m_visuallyNonEmptyCharacterCount += count;
// Use a threshold value to prevent very small amounts of visible content from triggering didMeaningfulLayout.
// The first few hundred characters rarely contain the interesting content of the page.
static const unsigned visualCharacterThreshold = 200;
if (m_visuallyNonEmptyCharacterCount > visualCharacterThreshold)
setIsVisuallyNonEmpty();
}
inline void FrameView::incrementVisuallyNonEmptyPixelCount(const IntSize& size)
{
if (m_isVisuallyNonEmpty)
return;
m_visuallyNonEmptyPixelCount += size.width() * size.height();
// Use a threshold value to prevent very small amounts of visible content from triggering didMeaningfulLayout.
static const unsigned visualPixelThreshold = 32 * 32;
if (m_visuallyNonEmptyPixelCount > visualPixelThreshold)
setIsVisuallyNonEmpty();
}
DEFINE_TYPE_CASTS(FrameView, Widget, widget, widget->isFrameView(), widget.isFrameView());
} // namespace blink
#endif // FrameView_h