1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_PAINT_PROPERTY_NODE_H_
6 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_PAINT_PROPERTY_NODE_H_
7 
8 #include <algorithm>
9 #include "base/optional.h"
10 #include "cc/input/main_thread_scrolling_reason.h"
11 #include "cc/input/overscroll_behavior.h"
12 #include "cc/input/scroll_snap_data.h"
13 #include "third_party/blink/renderer/platform/geometry/float_point.h"
14 #include "third_party/blink/renderer/platform/geometry/float_size.h"
15 #include "third_party/blink/renderer/platform/geometry/int_rect.h"
16 #include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
17 #include "third_party/blink/renderer/platform/graphics/paint/paint_property_node.h"
18 #include "third_party/blink/renderer/platform/platform_export.h"
19 
20 namespace blink {
21 
22 using MainThreadScrollingReasons = uint32_t;
23 
24 // A scroll node contains auxiliary scrolling information which includes how far
25 // an area can be scrolled, main thread scrolling reasons, etc. Scroll nodes
26 // are referenced by TransformPaintPropertyNodes that are used for the scroll
27 // offset translation, though scroll offset translation can exist without a
28 // scroll node (e.g., overflow: hidden).
29 //
30 // Main thread scrolling reasons force scroll updates to go to the main thread
31 // and can have dependencies on other nodes. For example, all parents of a
32 // scroll node with background attachment fixed set should also have it set.
33 //
34 // The scroll tree differs from the other trees because it does not affect
35 // geometry directly.
36 class PLATFORM_EXPORT ScrollPaintPropertyNode
37     : public PaintPropertyNode<ScrollPaintPropertyNode> {
38  public:
39   // To make it less verbose and more readable to construct and update a node,
40   // a struct with default values is used to represent the state.
41   struct State {
42     IntRect container_rect;
43     IntSize contents_size;
44     bool user_scrollable_horizontal = false;
45     bool user_scrollable_vertical = false;
46 
47     // This bit tells the compositor whether the inner viewport should be
48     // scrolled using the full viewport mechanism (overscroll, top control
49     // movement, inner+outer panning, etc.). This can differ depending on
50     // whether the page has a non-default root scroller and is used to affect
51     // scroll chaining from fixed elements. See discussion on
52     // https://crbug.com/977954 for details.
53     bool prevent_viewport_scrolling_from_inner = false;
54 
55     bool max_scroll_offset_affected_by_page_scale = false;
56     MainThreadScrollingReasons main_thread_scrolling_reasons =
57         cc::MainThreadScrollingReason::kNotScrollingOnMain;
58     // The scrolling element id is stored directly on the scroll node and not
59     // on the associated TransformPaintPropertyNode used for scroll offset.
60     CompositorElementId compositor_element_id;
61     cc::OverscrollBehavior overscroll_behavior = cc::OverscrollBehavior(
62         cc::OverscrollBehavior::kOverscrollBehaviorTypeAuto);
63     base::Optional<cc::SnapContainerData> snap_container_data;
64 
ComputeChangeState65     PaintPropertyChangeType ComputeChange(const State& other) const {
66       if (container_rect != other.container_rect ||
67           contents_size != other.contents_size ||
68           user_scrollable_horizontal != other.user_scrollable_horizontal ||
69           user_scrollable_vertical != other.user_scrollable_vertical ||
70           prevent_viewport_scrolling_from_inner !=
71               other.prevent_viewport_scrolling_from_inner ||
72           max_scroll_offset_affected_by_page_scale !=
73               other.max_scroll_offset_affected_by_page_scale ||
74           main_thread_scrolling_reasons !=
75               other.main_thread_scrolling_reasons ||
76           compositor_element_id != other.compositor_element_id ||
77           overscroll_behavior != other.overscroll_behavior ||
78           snap_container_data != other.snap_container_data) {
79         return PaintPropertyChangeType::kChangedOnlyValues;
80       }
81       return PaintPropertyChangeType::kUnchanged;
82     }
83   };
84 
85   // This node is really a sentinel, and does not represent a real scroll.
86   static const ScrollPaintPropertyNode& Root();
87 
Create(const ScrollPaintPropertyNode & parent,State && state)88   static scoped_refptr<ScrollPaintPropertyNode> Create(
89       const ScrollPaintPropertyNode& parent,
90       State&& state) {
91     return base::AdoptRef(
92         new ScrollPaintPropertyNode(&parent, std::move(state)));
93   }
CreateAlias(const ScrollPaintPropertyNode &)94   static scoped_refptr<ScrollPaintPropertyNode> CreateAlias(
95       const ScrollPaintPropertyNode&) {
96     // ScrollPaintPropertyNodes cannot be aliases.
97     NOTREACHED();
98     return nullptr;
99   }
100 
101   // The empty AnimationState struct is to meet the requirement of
102   // ObjectPaintProperties.
103   struct AnimationState {};
104   PaintPropertyChangeType Update(const ScrollPaintPropertyNode& parent,
105                                  State&& state,
106                                  const AnimationState& = AnimationState()) {
107     auto parent_changed = SetParent(&parent);
108     auto state_changed = state_.ComputeChange(state);
109     if (state_changed != PaintPropertyChangeType::kUnchanged) {
110       state_ = std::move(state);
111       Validate();
112       AddChanged(state_changed);
113     }
114     return std::max(parent_changed, state_changed);
115   }
116 
OverscrollBehaviorX()117   cc::OverscrollBehavior::OverscrollBehaviorType OverscrollBehaviorX() const {
118     return state_.overscroll_behavior.x;
119   }
120 
OverscrollBehaviorY()121   cc::OverscrollBehavior::OverscrollBehaviorType OverscrollBehaviorY() const {
122     return state_.overscroll_behavior.y;
123   }
124 
GetSnapContainerData()125   base::Optional<cc::SnapContainerData> GetSnapContainerData() const {
126     return state_.snap_container_data;
127   }
128 
129   // Rect of the container area that the contents scrolls in, in the space of
130   // the parent of the associated transform node (ScrollTranslation).
131   // It doesn't include non-overlay scrollbars. Overlay scrollbars do not affect
132   // the rect.
ContainerRect()133   const IntRect& ContainerRect() const { return state_.container_rect; }
134 
135   // Size of the contents that is scrolled within the container rect.
ContentsSize()136   const IntSize& ContentsSize() const { return state_.contents_size; }
137 
UserScrollableHorizontal()138   bool UserScrollableHorizontal() const {
139     return state_.user_scrollable_horizontal;
140   }
UserScrollableVertical()141   bool UserScrollableVertical() const {
142     return state_.user_scrollable_vertical;
143   }
PreventViewportScrollingFromInner()144   bool PreventViewportScrollingFromInner() const {
145     return state_.prevent_viewport_scrolling_from_inner;
146   }
MaxScrollOffsetAffectedByPageScale()147   bool MaxScrollOffsetAffectedByPageScale() const {
148     return state_.max_scroll_offset_affected_by_page_scale;
149   }
150 
151   // Return reason bitfield with values from cc::MainThreadScrollingReason.
GetMainThreadScrollingReasons()152   MainThreadScrollingReasons GetMainThreadScrollingReasons() const {
153     return state_.main_thread_scrolling_reasons;
154   }
155 
156   // Main thread scrolling reason for the threaded scrolling disabled setting.
ThreadedScrollingDisabled()157   bool ThreadedScrollingDisabled() const {
158     return state_.main_thread_scrolling_reasons &
159            cc::MainThreadScrollingReason::kThreadedScrollingDisabled;
160   }
161 
162   // Main thread scrolling reason for background attachment fixed descendants.
HasBackgroundAttachmentFixedDescendants()163   bool HasBackgroundAttachmentFixedDescendants() const {
164     return state_.main_thread_scrolling_reasons &
165            cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects;
166   }
167 
GetCompositorElementId()168   const CompositorElementId& GetCompositorElementId() const {
169     return state_.compositor_element_id;
170   }
171 
172   std::unique_ptr<JSONObject> ToJSON() const;
173 
174  private:
ScrollPaintPropertyNode(const ScrollPaintPropertyNode * parent,State && state)175   ScrollPaintPropertyNode(const ScrollPaintPropertyNode* parent, State&& state)
176       : PaintPropertyNode(parent), state_(std::move(state)) {
177     Validate();
178   }
179 
Validate()180   void Validate() const {
181 #if DCHECK_IS_ON()
182     DCHECK(!state_.compositor_element_id ||
183            NamespaceFromCompositorElementId(state_.compositor_element_id) ==
184                CompositorElementIdNamespace::kScroll);
185 #endif
186   }
187 
188   State state_;
189 };
190 
191 }  // namespace blink
192 
193 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_PAINT_PROPERTY_NODE_H_
194