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