blob: 09635066481489638ee48b74e36d9c698feff117 [file] [log] [blame]
// Copyright 2016 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_PLATFORM_GRAPHICS_PAINT_SCROLL_PAINT_PROPERTY_NODE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_PAINT_PROPERTY_NODE_H_
#include <algorithm>
#include "base/optional.h"
#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/input/overscroll_behavior.h"
#include "cc/input/scroll_snap_data.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_property_node.h"
#include "third_party/blink/renderer/platform/platform_export.h"
namespace blink {
using MainThreadScrollingReasons = uint32_t;
// A scroll node contains auxiliary scrolling information which includes how far
// an area can be scrolled, main thread scrolling reasons, etc. Scroll nodes
// are referenced by TransformPaintPropertyNodes that are used for the scroll
// offset translation, though scroll offset translation can exist without a
// scroll node (e.g., overflow: hidden).
//
// Main thread scrolling reasons force scroll updates to go to the main thread
// and can have dependencies on other nodes. For example, all parents of a
// scroll node with background attachment fixed set should also have it set.
//
// The scroll tree differs from the other trees because it does not affect
// geometry directly.
class PLATFORM_EXPORT ScrollPaintPropertyNode
: public PaintPropertyNode<ScrollPaintPropertyNode,
ScrollPaintPropertyNode> {
public:
// To make it less verbose and more readable to construct and update a node,
// a struct with default values is used to represent the state.
struct State {
IntRect container_rect;
IntSize contents_size;
bool user_scrollable_horizontal = false;
bool user_scrollable_vertical = false;
// This bit tells the compositor whether the inner viewport should be
// scrolled using the full viewport mechanism (overscroll, top control
// movement, inner+outer panning, etc.). This can differ depending on
// whether the page has a non-default root scroller and is used to affect
// scroll chaining from fixed elements. See discussion on
// https://crbug.com/977954 for details.
bool prevent_viewport_scrolling_from_inner = false;
bool max_scroll_offset_affected_by_page_scale = false;
MainThreadScrollingReasons main_thread_scrolling_reasons =
cc::MainThreadScrollingReason::kNotScrollingOnMain;
// The scrolling element id is stored directly on the scroll node and not
// on the associated TransformPaintPropertyNode used for scroll offset.
CompositorElementId compositor_element_id;
cc::OverscrollBehavior overscroll_behavior =
cc::OverscrollBehavior(cc::OverscrollBehavior::Type::kAuto);
base::Optional<cc::SnapContainerData> snap_container_data;
PaintPropertyChangeType ComputeChange(const State& other) const {
if (container_rect != other.container_rect ||
contents_size != other.contents_size ||
user_scrollable_horizontal != other.user_scrollable_horizontal ||
user_scrollable_vertical != other.user_scrollable_vertical ||
prevent_viewport_scrolling_from_inner !=
other.prevent_viewport_scrolling_from_inner ||
max_scroll_offset_affected_by_page_scale !=
other.max_scroll_offset_affected_by_page_scale ||
main_thread_scrolling_reasons !=
other.main_thread_scrolling_reasons ||
compositor_element_id != other.compositor_element_id ||
overscroll_behavior != other.overscroll_behavior ||
snap_container_data != other.snap_container_data) {
return PaintPropertyChangeType::kChangedOnlyValues;
}
return PaintPropertyChangeType::kUnchanged;
}
};
// This node is really a sentinel, and does not represent a real scroll.
static const ScrollPaintPropertyNode& Root();
static scoped_refptr<ScrollPaintPropertyNode> Create(
const ScrollPaintPropertyNode& parent,
State&& state) {
return base::AdoptRef(
new ScrollPaintPropertyNode(&parent, std::move(state)));
}
static scoped_refptr<ScrollPaintPropertyNode> CreateAlias(
const ScrollPaintPropertyNode&) {
// ScrollPaintPropertyNodes cannot be aliases.
NOTREACHED();
return nullptr;
}
// The empty AnimationState struct is to meet the requirement of
// ObjectPaintProperties.
struct AnimationState {};
PaintPropertyChangeType Update(const ScrollPaintPropertyNode& parent,
State&& state,
const AnimationState& = AnimationState()) {
auto parent_changed = SetParent(parent);
auto state_changed = state_.ComputeChange(state);
if (state_changed != PaintPropertyChangeType::kUnchanged) {
state_ = std::move(state);
Validate();
AddChanged(state_changed);
}
return std::max(parent_changed, state_changed);
}
const ScrollPaintPropertyNode& Unalias() const = delete;
cc::OverscrollBehavior::Type OverscrollBehaviorX() const {
return state_.overscroll_behavior.x;
}
cc::OverscrollBehavior::Type OverscrollBehaviorY() const {
return state_.overscroll_behavior.y;
}
base::Optional<cc::SnapContainerData> GetSnapContainerData() const {
return state_.snap_container_data;
}
// Rect of the container area that the contents scrolls in, in the space of
// the parent of the associated transform node (ScrollTranslation).
// It doesn't include non-overlay scrollbars. Overlay scrollbars do not affect
// the rect.
const IntRect& ContainerRect() const { return state_.container_rect; }
// Size of the contents that is scrolled within the container rect.
const IntSize& ContentsSize() const { return state_.contents_size; }
bool UserScrollableHorizontal() const {
return state_.user_scrollable_horizontal;
}
bool UserScrollableVertical() const {
return state_.user_scrollable_vertical;
}
bool PreventViewportScrollingFromInner() const {
return state_.prevent_viewport_scrolling_from_inner;
}
bool MaxScrollOffsetAffectedByPageScale() const {
return state_.max_scroll_offset_affected_by_page_scale;
}
// Return reason bitfield with values from cc::MainThreadScrollingReason.
MainThreadScrollingReasons GetMainThreadScrollingReasons() const {
return state_.main_thread_scrolling_reasons;
}
// Main thread scrolling reason for the threaded scrolling disabled setting.
bool ThreadedScrollingDisabled() const {
return state_.main_thread_scrolling_reasons &
cc::MainThreadScrollingReason::kThreadedScrollingDisabled;
}
// Main thread scrolling reason for background attachment fixed descendants.
bool HasBackgroundAttachmentFixedDescendants() const {
return state_.main_thread_scrolling_reasons &
cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects;
}
const CompositorElementId& GetCompositorElementId() const {
return state_.compositor_element_id;
}
std::unique_ptr<JSONObject> ToJSON() const;
private:
ScrollPaintPropertyNode(const ScrollPaintPropertyNode* parent, State&& state)
: PaintPropertyNode(parent), state_(std::move(state)) {
Validate();
}
using PaintPropertyNode::SetParent;
void Validate() const {
#if DCHECK_IS_ON()
DCHECK(!state_.compositor_element_id ||
NamespaceFromCompositorElementId(state_.compositor_element_id) ==
CompositorElementIdNamespace::kScroll);
#endif
}
State state_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_PAINT_PROPERTY_NODE_H_