// Copyright 2014 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 "ui/android/overscroll_refresh.h" #include "base/logging.h" namespace ui { namespace { // Experimentally determined constant used to allow activation even if touch // release results in a small upward fling (quite common during a slow scroll). const float kMinFlingVelocityForActivation = -500.f; } // namespace OverscrollRefresh::OverscrollRefresh(OverscrollRefreshHandler* handler) : scrolled_to_top_(true), overflow_y_hidden_(false), scroll_consumption_state_(DISABLED), handler_(handler) { DCHECK(handler); } OverscrollRefresh::~OverscrollRefresh() { } void OverscrollRefresh::Reset() { scroll_consumption_state_ = DISABLED; handler_->PullReset(); } void OverscrollRefresh::OnScrollBegin() { ReleaseWithoutActivation(); if (scrolled_to_top_ && !overflow_y_hidden_) scroll_consumption_state_ = AWAITING_SCROLL_UPDATE_ACK; } void OverscrollRefresh::OnScrollEnd(const gfx::Vector2dF& scroll_velocity) { bool allow_activation = scroll_velocity.y() > kMinFlingVelocityForActivation; Release(allow_activation); } void OverscrollRefresh::OnScrollUpdateAck(bool was_consumed) { if (scroll_consumption_state_ != AWAITING_SCROLL_UPDATE_ACK) return; if (was_consumed) { scroll_consumption_state_ = DISABLED; return; } scroll_consumption_state_ = handler_->PullStart() ? ENABLED : DISABLED; } bool OverscrollRefresh::WillHandleScrollUpdate( const gfx::Vector2dF& scroll_delta) { switch (scroll_consumption_state_) { case DISABLED: return false; case AWAITING_SCROLL_UPDATE_ACK: // If the initial scroll motion is downward, never allow activation. if (scroll_delta.y() <= 0) scroll_consumption_state_ = DISABLED; return false; case ENABLED: handler_->PullUpdate(scroll_delta.y()); return true; } NOTREACHED() << "Invalid overscroll state: " << scroll_consumption_state_; return false; } void OverscrollRefresh::ReleaseWithoutActivation() { bool allow_activation = false; Release(allow_activation); } bool OverscrollRefresh::IsActive() const { return scroll_consumption_state_ == ENABLED; } bool OverscrollRefresh::IsAwaitingScrollUpdateAck() const { return scroll_consumption_state_ == AWAITING_SCROLL_UPDATE_ACK; } void OverscrollRefresh::OnFrameUpdated( const gfx::Vector2dF& content_scroll_offset, bool root_overflow_y_hidden) { scrolled_to_top_ = content_scroll_offset.y() == 0; overflow_y_hidden_ = root_overflow_y_hidden; } void OverscrollRefresh::Release(bool allow_refresh) { if (scroll_consumption_state_ == ENABLED) handler_->PullRelease(allow_refresh); scroll_consumption_state_ = DISABLED; } } // namespace ui