| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_ROOT_FRAME_VIEWPORT_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_ROOT_FRAME_VIEWPORT_H_ |
| |
| #include "base/single_thread_task_runner.h" |
| #include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink-forward.h" |
| #include "third_party/blink/renderer/core/core_export.h" |
| #include "third_party/blink/renderer/core/scroll/scrollable_area.h" |
| #include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" |
| #include "third_party/blink/renderer/platform/wtf/casting.h" |
| |
| namespace blink { |
| |
| class LocalFrameView; |
| struct PhysicalRect; |
| |
| // ScrollableArea for the root frame's viewport. This class ties together the |
| // concepts of layout and visual viewports, used in pinch-to-zoom. This class |
| // takes two ScrollableAreas, one for the visual viewport and one for the |
| // layout viewport, and delegates and composes the ScrollableArea API as needed |
| // between them. For most scrolling APIs, this class will split the scroll up |
| // between the two viewports in accord with the pinch-zoom semantics. For other |
| // APIs that don't make sense on the combined viewport, the call is delegated to |
| // the layout viewport. Thus, we could say this class is a decorator on the |
| // LocalFrameView scrollable area that adds pinch-zoom semantics to scrolling. |
| class CORE_EXPORT RootFrameViewport final |
| : public GarbageCollected<RootFrameViewport>, |
| public ScrollableArea { |
| public: |
| RootFrameViewport(ScrollableArea& visual_viewport, |
| ScrollableArea& layout_viewport); |
| |
| void Trace(Visitor*) const override; |
| |
| void SetLayoutViewport(ScrollableArea&); |
| ScrollableArea& LayoutViewport() const; |
| |
| // Convert from the root content document's coordinate space, into the |
| // coordinate space of the layout viewport's content. In the normal case, |
| // this will be a no-op since the root LocalFrameView is the layout viewport |
| // and so the root content is the layout viewport's content but if the page |
| // sets a custom root scroller via document.rootScroller, another element |
| // may be the layout viewport. |
| PhysicalRect RootContentsToLayoutViewportContents( |
| LocalFrameView& root_frame_view, |
| const PhysicalRect&) const; |
| |
| void RestoreToAnchor(const ScrollOffset&); |
| |
| // Callback whenever the visual viewport changes scroll position or scale. |
| void DidUpdateVisualViewport(); |
| |
| // ScrollableArea Implementation |
| bool IsRootFrameViewport() const override { return true; } |
| void SetScrollOffset(const ScrollOffset&, |
| mojom::blink::ScrollType, |
| mojom::blink::ScrollBehavior, |
| ScrollCallback on_finish) override; |
| PhysicalRect ScrollIntoView( |
| const PhysicalRect&, |
| const mojom::blink::ScrollIntoViewParamsPtr&) override; |
| IntRect VisibleContentRect( |
| IncludeScrollbarsInRect = kExcludeScrollbars) const override; |
| PhysicalRect VisibleScrollSnapportRect( |
| IncludeScrollbarsInRect = kExcludeScrollbars) const override; |
| bool ShouldUseIntegerScrollOffset() const override; |
| bool IsThrottled() const override { |
| // RootFrameViewport is always in the main frame, so the frame does not get |
| // throttled. |
| return false; |
| } |
| bool IsActive() const override; |
| int ScrollSize(ScrollbarOrientation) const override; |
| bool IsScrollCornerVisible() const override; |
| IntRect ScrollCornerRect() const override; |
| void UpdateScrollOffset(const ScrollOffset&, |
| mojom::blink::ScrollType) override; |
| IntSize ScrollOffsetInt() const override; |
| ScrollOffset GetScrollOffset() const override; |
| IntSize MinimumScrollOffsetInt() const override; |
| IntSize MaximumScrollOffsetInt() const override; |
| ScrollOffset MaximumScrollOffset() const override; |
| IntSize ClampScrollOffset(const IntSize&) const override; |
| ScrollOffset ClampScrollOffset(const ScrollOffset&) const override; |
| IntSize ContentsSize() const override; |
| bool ShouldScrollOnMainThread() const override; |
| bool ScrollbarsCanBeActive() const override; |
| bool UserInputScrollable(ScrollbarOrientation) const override; |
| bool ShouldPlaceVerticalScrollbarOnLeft() const override; |
| void ScrollControlWasSetNeedsPaintInvalidation() override; |
| cc::Layer* LayerForScrolling() const override; |
| cc::Layer* LayerForHorizontalScrollbar() const override; |
| cc::Layer* LayerForVerticalScrollbar() const override; |
| cc::Layer* LayerForScrollCorner() const override; |
| int HorizontalScrollbarHeight(OverlayScrollbarClipBehavior = |
| kIgnoreOverlayScrollbarSize) const override; |
| int VerticalScrollbarWidth(OverlayScrollbarClipBehavior = |
| kIgnoreOverlayScrollbarSize) const override; |
| ScrollResult UserScroll(ScrollGranularity, |
| const FloatSize&, |
| ScrollableArea::ScrollCallback on_finish) override; |
| CompositorElementId GetScrollElementId() const override; |
| CompositorElementId GetScrollbarElementId( |
| ScrollbarOrientation orientation) override; |
| bool ScrollAnimatorEnabled() const override; |
| ChromeClient* GetChromeClient() const override; |
| SmoothScrollSequencer* GetSmoothScrollSequencer() const override; |
| void ServiceScrollAnimations(double) override; |
| void UpdateCompositorScrollAnimations() override; |
| void CancelProgrammaticScrollAnimation() override; |
| mojom::blink::ScrollBehavior ScrollBehaviorStyle() const override; |
| ColorScheme UsedColorScheme() const override; |
| void ClearScrollableArea() override; |
| LayoutBox* GetLayoutBox() const override; |
| FloatQuad LocalToVisibleContentQuad(const FloatQuad&, |
| const LayoutObject*, |
| unsigned = 0) const final; |
| scoped_refptr<base::SingleThreadTaskRunner> GetTimerTaskRunner() const final; |
| ScrollbarTheme& GetPageScrollbarTheme() const override; |
| |
| // RootFrameViewport delegates these scroll-snap methods to its layout |
| // viewport. |
| const cc::SnapContainerData* GetSnapContainerData() const override; |
| void SetSnapContainerData(base::Optional<cc::SnapContainerData>) override; |
| bool SetTargetSnapAreaElementIds(cc::TargetSnapAreaElementIds) override; |
| bool SnapContainerDataNeedsUpdate() const override; |
| void SetSnapContainerDataNeedsUpdate(bool) override; |
| bool NeedsResnap() const override; |
| void SetNeedsResnap(bool) override; |
| base::Optional<FloatPoint> GetSnapPositionAndSetTarget( |
| const cc::SnapSelectionStrategy& strategy) override; |
| |
| void SetPendingHistoryRestoreScrollOffset( |
| const HistoryItem::ViewState& view_state, |
| bool should_restore_scroll) override { |
| pending_view_state_ = view_state; |
| should_restore_scroll_ = should_restore_scroll; |
| } |
| |
| void ApplyPendingHistoryRestoreScrollOffset() override; |
| |
| bool HasPendingHistoryRestoreScrollOffset() override { |
| return !!pending_view_state_; |
| } |
| |
| private: |
| FRIEND_TEST_ALL_PREFIXES(RootFrameViewportTest, DistributeScrollOrder); |
| |
| enum ViewportToScrollFirst { kVisualViewport, kLayoutViewport }; |
| |
| ScrollOffset ScrollOffsetFromScrollAnimators() const; |
| |
| void DistributeScrollBetweenViewports( |
| const ScrollOffset&, |
| mojom::blink::ScrollType, |
| mojom::blink::ScrollBehavior, |
| ViewportToScrollFirst, |
| ScrollCallback on_finish = ScrollCallback()); |
| |
| // If either of the layout or visual viewports are scrolled explicitly (i.e. |
| // not through this class), their updated offset will not be reflected in this |
| // class' animator so use this method to pull updated values when necessary. |
| void UpdateScrollAnimator(); |
| |
| ScrollableArea& GetVisualViewport() const { |
| DCHECK(visual_viewport_); |
| return *visual_viewport_; |
| } |
| |
| ScrollOffset ClampToUserScrollableOffset(const ScrollOffset&) const; |
| |
| Member<ScrollableArea> visual_viewport_; |
| Member<ScrollableArea> layout_viewport_; |
| base::Optional<HistoryItem::ViewState> pending_view_state_; |
| bool should_restore_scroll_; |
| }; |
| |
| template <> |
| struct DowncastTraits<RootFrameViewport> { |
| static bool AllowFrom(const ScrollableArea& scrollable_area) { |
| return scrollable_area.IsRootFrameViewport(); |
| } |
| }; |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_ROOT_FRAME_VIEWPORT_H_ |