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 ScrollPaintPropertyNode> { 39 public: 40 // To make it less verbose and more readable to construct and update a node, 41 // a struct with default values is used to represent the state. 42 struct State { 43 IntRect container_rect; 44 IntSize contents_size; 45 bool user_scrollable_horizontal = false; 46 bool user_scrollable_vertical = false; 47 48 // This bit tells the compositor whether the inner viewport should be 49 // scrolled using the full viewport mechanism (overscroll, top control 50 // movement, inner+outer panning, etc.). This can differ depending on 51 // whether the page has a non-default root scroller and is used to affect 52 // scroll chaining from fixed elements. See discussion on 53 // https://crbug.com/977954 for details. 54 bool prevent_viewport_scrolling_from_inner = false; 55 56 bool max_scroll_offset_affected_by_page_scale = false; 57 MainThreadScrollingReasons main_thread_scrolling_reasons = 58 cc::MainThreadScrollingReason::kNotScrollingOnMain; 59 // The scrolling element id is stored directly on the scroll node and not 60 // on the associated TransformPaintPropertyNode used for scroll offset. 61 CompositorElementId compositor_element_id; 62 cc::OverscrollBehavior overscroll_behavior = 63 cc::OverscrollBehavior(cc::OverscrollBehavior::Type::kAuto); 64 base::Optional<cc::SnapContainerData> snap_container_data; 65 ComputeChangeState66 PaintPropertyChangeType ComputeChange(const State& other) const { 67 if (container_rect != other.container_rect || 68 contents_size != other.contents_size || 69 user_scrollable_horizontal != other.user_scrollable_horizontal || 70 user_scrollable_vertical != other.user_scrollable_vertical || 71 prevent_viewport_scrolling_from_inner != 72 other.prevent_viewport_scrolling_from_inner || 73 max_scroll_offset_affected_by_page_scale != 74 other.max_scroll_offset_affected_by_page_scale || 75 main_thread_scrolling_reasons != 76 other.main_thread_scrolling_reasons || 77 compositor_element_id != other.compositor_element_id || 78 overscroll_behavior != other.overscroll_behavior || 79 snap_container_data != other.snap_container_data) { 80 return PaintPropertyChangeType::kChangedOnlyValues; 81 } 82 return PaintPropertyChangeType::kUnchanged; 83 } 84 }; 85 86 // This node is really a sentinel, and does not represent a real scroll. 87 static const ScrollPaintPropertyNode& Root(); 88 Create(const ScrollPaintPropertyNode & parent,State && state)89 static scoped_refptr<ScrollPaintPropertyNode> Create( 90 const ScrollPaintPropertyNode& parent, 91 State&& state) { 92 return base::AdoptRef( 93 new ScrollPaintPropertyNode(&parent, std::move(state))); 94 } CreateAlias(const ScrollPaintPropertyNode &)95 static scoped_refptr<ScrollPaintPropertyNode> CreateAlias( 96 const ScrollPaintPropertyNode&) { 97 // ScrollPaintPropertyNodes cannot be aliases. 98 NOTREACHED(); 99 return nullptr; 100 } 101 102 // The empty AnimationState struct is to meet the requirement of 103 // ObjectPaintProperties. 104 struct AnimationState {}; 105 PaintPropertyChangeType Update(const ScrollPaintPropertyNode& parent, 106 State&& state, 107 const AnimationState& = AnimationState()) { 108 auto parent_changed = SetParent(parent); 109 auto state_changed = state_.ComputeChange(state); 110 if (state_changed != PaintPropertyChangeType::kUnchanged) { 111 state_ = std::move(state); 112 Validate(); 113 AddChanged(state_changed); 114 } 115 return std::max(parent_changed, state_changed); 116 } 117 118 const ScrollPaintPropertyNode& Unalias() const = delete; 119 OverscrollBehaviorX()120 cc::OverscrollBehavior::Type OverscrollBehaviorX() const { 121 return state_.overscroll_behavior.x; 122 } 123 OverscrollBehaviorY()124 cc::OverscrollBehavior::Type OverscrollBehaviorY() const { 125 return state_.overscroll_behavior.y; 126 } 127 GetSnapContainerData()128 base::Optional<cc::SnapContainerData> GetSnapContainerData() const { 129 return state_.snap_container_data; 130 } 131 132 // Rect of the container area that the contents scrolls in, in the space of 133 // the parent of the associated transform node (ScrollTranslation). 134 // It doesn't include non-overlay scrollbars. Overlay scrollbars do not affect 135 // the rect. ContainerRect()136 const IntRect& ContainerRect() const { return state_.container_rect; } 137 138 // Size of the contents that is scrolled within the container rect. ContentsSize()139 const IntSize& ContentsSize() const { return state_.contents_size; } 140 UserScrollableHorizontal()141 bool UserScrollableHorizontal() const { 142 return state_.user_scrollable_horizontal; 143 } UserScrollableVertical()144 bool UserScrollableVertical() const { 145 return state_.user_scrollable_vertical; 146 } PreventViewportScrollingFromInner()147 bool PreventViewportScrollingFromInner() const { 148 return state_.prevent_viewport_scrolling_from_inner; 149 } MaxScrollOffsetAffectedByPageScale()150 bool MaxScrollOffsetAffectedByPageScale() const { 151 return state_.max_scroll_offset_affected_by_page_scale; 152 } 153 154 // Return reason bitfield with values from cc::MainThreadScrollingReason. GetMainThreadScrollingReasons()155 MainThreadScrollingReasons GetMainThreadScrollingReasons() const { 156 return state_.main_thread_scrolling_reasons; 157 } 158 159 // Main thread scrolling reason for the threaded scrolling disabled setting. ThreadedScrollingDisabled()160 bool ThreadedScrollingDisabled() const { 161 return state_.main_thread_scrolling_reasons & 162 cc::MainThreadScrollingReason::kThreadedScrollingDisabled; 163 } 164 165 // Main thread scrolling reason for background attachment fixed descendants. HasBackgroundAttachmentFixedDescendants()166 bool HasBackgroundAttachmentFixedDescendants() const { 167 return state_.main_thread_scrolling_reasons & 168 cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; 169 } 170 GetCompositorElementId()171 const CompositorElementId& GetCompositorElementId() const { 172 return state_.compositor_element_id; 173 } 174 175 std::unique_ptr<JSONObject> ToJSON() const; 176 177 private: ScrollPaintPropertyNode(const ScrollPaintPropertyNode * parent,State && state)178 ScrollPaintPropertyNode(const ScrollPaintPropertyNode* parent, State&& state) 179 : PaintPropertyNode(parent), state_(std::move(state)) { 180 Validate(); 181 } 182 183 using PaintPropertyNode::SetParent; 184 Validate()185 void Validate() const { 186 #if DCHECK_IS_ON() 187 DCHECK(!state_.compositor_element_id || 188 NamespaceFromCompositorElementId(state_.compositor_element_id) == 189 CompositorElementIdNamespace::kScroll); 190 #endif 191 } 192 193 State state_; 194 }; 195 196 } // namespace blink 197 198 #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_PAINT_PROPERTY_NODE_H_ 199