blob: 728e964d6840b6bc2c9763457c517e513d4a0560 [file] [log] [blame]
// 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.
#include "third_party/blink/renderer/core/page/scrolling/scroll_state.h"
#include <memory>
#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_state_init.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
namespace blink {
namespace {
Node* NodeForId(DOMNodeId node_id) {
Node* node = DOMNodeIds::NodeForId(node_id);
DCHECK(node);
return node;
}
} // namespace
ScrollState* ScrollState::Create(ScrollStateInit* init) {
std::unique_ptr<ScrollStateData> scroll_state_data =
std::make_unique<ScrollStateData>();
scroll_state_data->delta_x = init->deltaX();
scroll_state_data->delta_y = init->deltaY();
scroll_state_data->delta_x_hint = init->deltaXHint();
scroll_state_data->delta_y_hint = init->deltaYHint();
scroll_state_data->position_x = init->positionX();
scroll_state_data->position_y = init->positionY();
scroll_state_data->velocity_x = init->velocityX();
scroll_state_data->velocity_y = init->velocityY();
scroll_state_data->is_beginning = init->isBeginning();
scroll_state_data->is_in_inertial_phase = init->isInInertialPhase();
scroll_state_data->is_ending = init->isEnding();
scroll_state_data->from_user_input = init->fromUserInput();
scroll_state_data->is_direct_manipulation = init->isDirectManipulation();
scroll_state_data->delta_granularity =
static_cast<ScrollGranularity>(init->deltaGranularity());
ScrollState* scroll_state =
MakeGarbageCollected<ScrollState>(std::move(scroll_state_data));
return scroll_state;
}
ScrollState::ScrollState(std::unique_ptr<ScrollStateData> data)
: data_(std::move(data)) {}
void ScrollState::consumeDelta(double x,
double y,
ExceptionState& exception_state) {
if ((data_->delta_x > 0 && 0 > x) || (data_->delta_x < 0 && 0 < x) ||
(data_->delta_y > 0 && 0 > y) || (data_->delta_y < 0 && 0 < y)) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidModificationError,
"Can't increase delta using consumeDelta");
return;
}
if (fabs(x) > fabs(data_->delta_x) || fabs(y) > fabs(data_->delta_y)) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidModificationError,
"Can't change direction of delta using consumeDelta");
return;
}
ConsumeDeltaNative(x, y);
}
void ScrollState::distributeToScrollChainDescendant() {
if (!scroll_chain_.IsEmpty()) {
DOMNodeId descendant_id = scroll_chain_.TakeFirst();
NodeForId(descendant_id)->CallDistributeScroll(*this);
}
}
void ScrollState::ConsumeDeltaNative(double x, double y) {
data_->delta_x -= x;
data_->delta_y -= y;
if (x)
data_->caused_scroll_x = true;
if (y)
data_->caused_scroll_y = true;
if (x || y)
data_->delta_consumed_for_scroll_sequence = true;
}
Node* ScrollState::CurrentNativeScrollingNode() {
if (data_->current_native_scrolling_element() == CompositorElementId()) {
node_.Clear();
return nullptr;
}
return node_;
}
void ScrollState::SetCurrentNativeScrollingNode(Node* node) {
node_ = node;
data_->set_current_native_scrolling_element(
CompositorElementIdFromDOMNodeId(DOMNodeIds::IdForNode(node)));
}
} // namespace blink