| /* |
| * Copyright (C) 2011, 2015 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #pragma once |
| |
| #include "EventTrackingRegions.h" |
| #include "LayoutRect.h" |
| #include "PlatformWheelEvent.h" |
| #include "ScrollSnapOffsetsInfo.h" |
| #include "ScrollTypes.h" |
| #include "ScrollingCoordinatorTypes.h" |
| #include <variant> |
| #include <wtf/Forward.h> |
| #include <wtf/ThreadSafeRefCounted.h> |
| #include <wtf/Threading.h> |
| #include <wtf/TypeCasts.h> |
| |
| namespace WTF { |
| class TextStream; |
| } |
| |
| namespace WebCore { |
| |
| class AbsolutePositionConstraints; |
| class Document; |
| class Frame; |
| class FrameView; |
| class GraphicsLayer; |
| class Page; |
| class Region; |
| class RenderObject; |
| class RenderLayer; |
| class ScrollableArea; |
| class ViewportConstraints; |
| |
| using FramesPerSecond = unsigned; |
| using PlatformDisplayID = uint32_t; |
| |
| class ScrollingCoordinator : public ThreadSafeRefCounted<ScrollingCoordinator> { |
| WTF_MAKE_FAST_ALLOCATED; |
| public: |
| static Ref<ScrollingCoordinator> create(Page*); |
| virtual ~ScrollingCoordinator(); |
| |
| WEBCORE_EXPORT virtual void pageDestroyed(); |
| |
| virtual bool isAsyncScrollingCoordinator() const { return false; } |
| virtual bool isRemoteScrollingCoordinator() const { return false; } |
| |
| // Return whether this scrolling coordinator handles scrolling for the given frame view. |
| WEBCORE_EXPORT virtual bool coordinatesScrollingForFrameView(const FrameView&) const; |
| |
| // Return whether this scrolling coordinator handles scrolling for the given overflow scroll layer. |
| WEBCORE_EXPORT virtual bool coordinatesScrollingForOverflowLayer(const RenderLayer&) const; |
| |
| // Returns the ScrollingNodeID of the innermost scrolling node that scrolls the renderer. |
| WEBCORE_EXPORT virtual ScrollingNodeID scrollableContainerNodeID(const RenderObject&) const; |
| |
| // Should be called whenever the given frame view has been laid out. |
| virtual void frameViewLayoutUpdated(FrameView&) { } |
| |
| using LayoutViewportOriginOrOverrideRect = std::variant<std::optional<FloatPoint>, std::optional<FloatRect>>; |
| virtual void reconcileScrollingState(FrameView&, const FloatPoint&, const LayoutViewportOriginOrOverrideRect&, ScrollType, ViewportRectStability, ScrollingLayerPositionAction) { } |
| |
| // Should be called whenever the set of fixed objects changes. |
| void frameViewFixedObjectsDidChange(FrameView&); |
| |
| // Should be called whenever the FrameView's visual viewport changed. |
| virtual void frameViewVisualViewportChanged(FrameView&) { } |
| |
| // Called whenever the non-fast scrollable region changes for reasons other than layout. |
| virtual void frameViewEventTrackingRegionsChanged(FrameView&) { } |
| |
| // Should be called whenever the root layer for the given frame view changes. |
| virtual void frameViewRootLayerDidChange(FrameView&); |
| |
| virtual void frameViewWillBeDetached(FrameView&) { } |
| |
| // Traverses the scrolling tree, setting layer positions to represent the current scrolled state. |
| virtual void applyScrollingTreeLayerPositions() { } |
| |
| virtual void didScheduleRenderingUpdate() { } |
| virtual void willStartRenderingUpdate() { } |
| virtual void didCompleteRenderingUpdate() { } |
| |
| virtual void willStartPlatformRenderingUpdate() { } |
| virtual void didCompletePlatformRenderingUpdate() { } |
| |
| #if ENABLE(KINETIC_SCROLLING) |
| // Dispatched by the scrolling tree during handleWheelEvent. This is required as long as scrollbars are painted on the main thread. |
| virtual void handleWheelEventPhase(ScrollingNodeID, PlatformWheelEventPhase) { } |
| #endif |
| |
| // Force all scroll layer position updates to happen on the main thread. |
| WEBCORE_EXPORT void setForceSynchronousScrollLayerPositionUpdates(bool); |
| |
| // These virtual functions are currently unique to the threaded scrolling architecture. |
| virtual void commitTreeStateIfNeeded() { } |
| |
| virtual bool requestScrollPositionUpdate(ScrollableArea&, const ScrollPosition&, ScrollType = ScrollType::Programmatic, ScrollClamping = ScrollClamping::Clamped) { return false; } |
| virtual bool requestAnimatedScrollToPosition(ScrollableArea&, const ScrollPosition&, ScrollClamping) { return false; } |
| virtual void stopAnimatedScroll(ScrollableArea&) { } |
| |
| virtual bool handleWheelEventForScrolling(const PlatformWheelEvent&, ScrollingNodeID, std::optional<WheelScrollGestureState>) { return false; } |
| virtual void wheelEventWasProcessedByMainThread(const PlatformWheelEvent&, std::optional<WheelScrollGestureState>) { } |
| |
| // Create an unparented node. |
| virtual ScrollingNodeID createNode(ScrollingNodeType, ScrollingNodeID newNodeID) { return newNodeID; } |
| // Parent a node in the scrolling tree. This may return a new nodeID if the node type changed. parentID = 0 sets the root node. |
| virtual ScrollingNodeID insertNode(ScrollingNodeType, ScrollingNodeID newNodeID, ScrollingNodeID /*parentID*/, size_t /*childIndex*/ = notFound) { return newNodeID; } |
| // Node will be unparented, but not destroyed. It's the client's responsibility to either re-parent or destroy this node. |
| virtual void unparentNode(ScrollingNodeID) { } |
| // Node will be destroyed, and its children left unparented. |
| virtual void unparentChildrenAndDestroyNode(ScrollingNodeID) { } |
| // Node will be unparented, and it and its children destroyed. |
| virtual void detachAndDestroySubtree(ScrollingNodeID) { } |
| // Destroy the tree, including both parented and unparented nodes. |
| virtual void clearAllNodes() { } |
| |
| virtual ScrollingNodeID parentOfNode(ScrollingNodeID) const { return 0; } |
| virtual Vector<ScrollingNodeID> childrenOfNode(ScrollingNodeID) const { return { }; } |
| |
| virtual void scrollBySimulatingWheelEventForTesting(ScrollingNodeID, FloatSize) { } |
| |
| struct NodeLayers { |
| GraphicsLayer* layer { nullptr }; |
| GraphicsLayer* scrollContainerLayer { nullptr }; |
| GraphicsLayer* scrolledContentsLayer { nullptr }; |
| GraphicsLayer* counterScrollingLayer { nullptr }; |
| GraphicsLayer* insetClipLayer { nullptr }; |
| GraphicsLayer* rootContentsLayer { nullptr }; |
| GraphicsLayer* horizontalScrollbarLayer { nullptr }; |
| GraphicsLayer* verticalScrollbarLayer { nullptr }; |
| }; |
| virtual void setNodeLayers(ScrollingNodeID, const NodeLayers&) { } |
| |
| virtual void setScrollingNodeScrollableAreaGeometry(ScrollingNodeID, ScrollableArea&) { } |
| virtual void setFrameScrollingNodeState(ScrollingNodeID, const FrameView&) { } |
| virtual void setViewportConstraintedNodeConstraints(ScrollingNodeID, const ViewportConstraints&) { } |
| virtual void setPositionedNodeConstraints(ScrollingNodeID, const AbsolutePositionConstraints&) { } |
| virtual void setRelatedOverflowScrollingNodes(ScrollingNodeID, Vector<ScrollingNodeID>&&) { } |
| virtual void setSynchronousScrollingReasons(ScrollingNodeID, OptionSet<SynchronousScrollingReason>) { } |
| virtual OptionSet<SynchronousScrollingReason> synchronousScrollingReasons(ScrollingNodeID) const { return { }; }; |
| bool hasSynchronousScrollingReasons(ScrollingNodeID nodeID) const { return !!synchronousScrollingReasons(nodeID); } |
| |
| virtual void reconcileViewportConstrainedLayerPositions(ScrollingNodeID, const LayoutRect&, ScrollingLayerPositionAction) { } |
| virtual String scrollingStateTreeAsText(OptionSet<ScrollingStateTreeAsTextBehavior> = { }) const; |
| virtual String scrollingTreeAsText(OptionSet<ScrollingStateTreeAsTextBehavior> = { }) const; |
| virtual bool isRubberBandInProgress(ScrollingNodeID) const { return false; } |
| virtual bool isUserScrollInProgress(ScrollingNodeID) const { return false; } |
| virtual bool isScrollSnapInProgress(ScrollingNodeID) const { return false; } |
| virtual void updateScrollSnapPropertiesWithFrameView(const FrameView&) { } |
| virtual void setScrollPinningBehavior(ScrollPinningBehavior) { } |
| virtual bool hasSubscrollers() const { return false; } |
| |
| // Generated a unique id for scrolling nodes. |
| ScrollingNodeID uniqueScrollingNodeID(); |
| |
| bool shouldUpdateScrollLayerPositionSynchronously(const FrameView&) const; |
| |
| virtual void willDestroyScrollableArea(ScrollableArea&) { } |
| virtual void scrollableAreaScrollbarLayerDidChange(ScrollableArea&, ScrollbarOrientation) { } |
| |
| virtual void windowScreenDidChange(PlatformDisplayID, std::optional<FramesPerSecond> /* nominalFramesPerSecond */) { } |
| |
| static String synchronousScrollingReasonsAsText(OptionSet<SynchronousScrollingReason>); |
| String synchronousScrollingReasonsAsText() const; |
| |
| EventTrackingRegions absoluteEventTrackingRegions() const; |
| virtual void updateIsMonitoringWheelEventsForFrameView(const FrameView&) { } |
| |
| virtual void startMonitoringWheelEvents(bool /* clearLatchingState */) { } |
| virtual void stopMonitoringWheelEvents() { } |
| |
| protected: |
| explicit ScrollingCoordinator(Page*); |
| |
| GraphicsLayer* scrollContainerLayerForFrameView(FrameView&); |
| GraphicsLayer* scrolledContentsLayerForFrameView(FrameView&); |
| GraphicsLayer* counterScrollingLayerForFrameView(FrameView&); |
| GraphicsLayer* insetClipLayerForFrameView(FrameView&); |
| GraphicsLayer* rootContentsLayerForFrameView(FrameView&); |
| GraphicsLayer* contentShadowLayerForFrameView(FrameView&); |
| GraphicsLayer* headerLayerForFrameView(FrameView&); |
| GraphicsLayer* footerLayerForFrameView(FrameView&); |
| |
| virtual void willCommitTree() { } |
| |
| Page* m_page; // FIXME: ideally this would be a reference but it gets nulled on async teardown. |
| |
| private: |
| virtual bool hasVisibleSlowRepaintViewportConstrainedObjects(const FrameView&) const; |
| |
| void updateSynchronousScrollingReasons(FrameView&); |
| void updateSynchronousScrollingReasonsForAllFrames(); |
| |
| EventTrackingRegions absoluteEventTrackingRegionsForFrame(const Frame&) const; |
| |
| bool m_forceSynchronousScrollLayerPositionUpdates { false }; |
| }; |
| |
| WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollableAreaParameters); |
| WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollingNodeType); |
| WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollingLayerPositionAction); |
| WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ViewportRectStability); |
| |
| } // namespace WebCore |
| |
| #define SPECIALIZE_TYPE_TRAITS_SCROLLING_COORDINATOR(ToValueTypeName, predicate) \ |
| SPECIALIZE_TYPE_TRAITS_BEGIN(ToValueTypeName) \ |
| static bool isType(const WebCore::ScrollingCoordinator& value) { return value.predicate; } \ |
| SPECIALIZE_TYPE_TRAITS_END() |