Revert "Merged all Chromoting Host code into remoting_core.dll (Windows)."
[chromium-blink-merge.git] / cc / top_controls_manager.cc
blobc75797dae2791232b71b9dbe2dbfe0ce9b1b481f
1 // Copyright 2013 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.
5 #include "cc/top_controls_manager.h"
7 #include <algorithm>
9 #include "base/logging.h"
10 #include "base/time.h"
11 #include "cc/keyframed_animation_curve.h"
12 #include "cc/layer_tree_impl.h"
13 #include "cc/timing_function.h"
14 #include "cc/top_controls_manager_client.h"
15 #include "ui/gfx/transform.h"
16 #include "ui/gfx/vector2d_f.h"
18 namespace cc {
19 namespace {
20 // These constants were chosen empirically for their visually pleasant behavior.
21 // Contact tedchoc@chromium.org for questions about changing these values.
22 const float kShowHideThreshold = 0.5f;
23 const int64 kShowHideMaxDurationMs = 175;
26 // static
27 scoped_ptr<TopControlsManager> TopControlsManager::Create(
28 TopControlsManagerClient* client, float top_controls_height) {
29 return make_scoped_ptr(new TopControlsManager(client, top_controls_height));
32 TopControlsManager::TopControlsManager(TopControlsManagerClient* client,
33 float top_controls_height)
34 : client_(client),
35 animation_direction_(NO_ANIMATION),
36 is_overlay_mode_(false),
37 in_scroll_gesture_(false),
38 top_controls_height_(top_controls_height),
39 controls_top_offset_(0),
40 content_top_offset_(top_controls_height),
41 previous_root_scroll_offset_(0.f),
42 scroll_start_offset_(0.f) {
43 CHECK(client_);
46 TopControlsManager::~TopControlsManager() {
49 void TopControlsManager::UpdateDrawPositions() {
50 if (!client_->haveRootScrollLayer())
51 return;
53 // If the scroll position has changed underneath us (i.e. a javascript
54 // scroll), then simulate a scroll that covers the delta.
55 float scroll_total_y = RootScrollLayerTotalScrollY();
56 if (!in_scroll_gesture_
57 && scroll_total_y != previous_root_scroll_offset_) {
58 ScrollBy(gfx::Vector2dF(0, scroll_total_y - previous_root_scroll_offset_));
59 StartAnimationIfNecessary();
60 previous_root_scroll_offset_ = RootScrollLayerTotalScrollY();
64 void TopControlsManager::ScrollBegin() {
65 ResetAnimations();
66 in_scroll_gesture_ = true;
67 scroll_start_offset_ = RootScrollLayerTotalScrollY() + controls_top_offset_;
70 gfx::Vector2dF TopControlsManager::ScrollBy(
71 const gfx::Vector2dF pending_delta) {
72 if (pending_delta.y() == 0)
73 return pending_delta;
75 float scroll_total_y = RootScrollLayerTotalScrollY();
76 if (in_scroll_gesture_ &&
77 ((pending_delta.y() > 0 && scroll_total_y < scroll_start_offset_) ||
78 (pending_delta.y() < 0 &&
79 scroll_total_y > scroll_start_offset_ + top_controls_height_))) {
80 return pending_delta;
83 ResetAnimations();
84 return ScrollInternal(pending_delta);
87 gfx::Vector2dF TopControlsManager::ScrollInternal(
88 const gfx::Vector2dF pending_delta) {
89 float scroll_total_y = RootScrollLayerTotalScrollY();
90 float scroll_delta_y = pending_delta.y();
92 float previous_controls_offset = controls_top_offset_;
93 float previous_content_offset = content_top_offset_;
94 bool previous_was_overlay = is_overlay_mode_;
96 controls_top_offset_ -= scroll_delta_y;
97 controls_top_offset_ = std::min(
98 std::max(controls_top_offset_, -top_controls_height_), 0.f);
100 if (scroll_total_y > 0 || (scroll_total_y == 0
101 && content_top_offset_ < scroll_delta_y)) {
102 is_overlay_mode_ = true;
104 // The first case is where the page applies a scroll (javascript) and is
105 // being re-adjusted in a call to UpdateDrawPositions. Instead of slamming
106 // the controls to the top, we adjust by the scroll delta until we reach
107 // zero as we expect.
108 if (scroll_total_y > 0 && content_top_offset_ != 0)
109 content_top_offset_ -= scroll_delta_y;
110 else
111 content_top_offset_ = 0;
112 } else if (scroll_total_y <= 0 && (scroll_delta_y < 0
113 || (scroll_delta_y > 0 && content_top_offset_ > 0))) {
114 is_overlay_mode_ = false;
115 content_top_offset_ -= scroll_delta_y;
117 content_top_offset_ = std::max(
118 std::min(content_top_offset_,
119 controls_top_offset_ + top_controls_height_), 0.f);
121 gfx::Vector2dF applied_delta;
122 if (!previous_was_overlay)
123 applied_delta.set_y(previous_content_offset - content_top_offset_);
125 if (is_overlay_mode_ != previous_was_overlay
126 || previous_controls_offset != controls_top_offset_
127 || previous_content_offset != content_top_offset_) {
128 client_->setNeedsRedraw();
129 client_->setActiveTreeNeedsUpdateDrawProperties();
132 return pending_delta - applied_delta;
135 void TopControlsManager::ScrollEnd() {
136 StartAnimationIfNecessary();
137 previous_root_scroll_offset_ = RootScrollLayerTotalScrollY();
138 in_scroll_gesture_ = false;
141 void TopControlsManager::Animate(base::TimeTicks monotonic_time) {
142 if (!top_controls_animation_ || !client_->haveRootScrollLayer())
143 return;
145 double time = (monotonic_time - base::TimeTicks()).InMillisecondsF();
146 float new_offset = top_controls_animation_->getValue(time);
147 gfx::Vector2dF scroll_vector(0.f, -(new_offset - controls_top_offset_));
148 ScrollInternal(scroll_vector);
149 client_->setNeedsRedraw();
151 if (IsAnimationCompleteAtTime(monotonic_time))
152 ResetAnimations();
155 void TopControlsManager::ResetAnimations() {
156 if (top_controls_animation_)
157 top_controls_animation_.reset();
159 animation_direction_ = NO_ANIMATION;
162 float TopControlsManager::RootScrollLayerTotalScrollY() {
163 return client_->rootScrollLayerTotalScrollY();
166 void TopControlsManager::SetupAnimation(AnimationDirection direction) {
167 top_controls_animation_ = KeyframedFloatAnimationCurve::create();
168 double start_time =
169 (base::TimeTicks::Now() - base::TimeTicks()).InMillisecondsF();
170 top_controls_animation_->addKeyframe(
171 FloatKeyframe::create(start_time, controls_top_offset_,
172 scoped_ptr<TimingFunction>()));
173 float max_ending_offset =
174 (direction == SHOWING_CONTROLS ? 1 : -1) * top_controls_height_;
175 top_controls_animation_->addKeyframe(
176 FloatKeyframe::create(start_time + kShowHideMaxDurationMs,
177 controls_top_offset_ + max_ending_offset,
178 EaseTimingFunction::create()));
179 animation_direction_ = direction;
182 void TopControlsManager::StartAnimationIfNecessary() {
183 float scroll_total_y = RootScrollLayerTotalScrollY();
185 if (controls_top_offset_ != 0
186 && controls_top_offset_ != -top_controls_height_) {
187 AnimationDirection show_controls =
188 controls_top_offset_ >= -(top_controls_height_ * kShowHideThreshold) ?
189 SHOWING_CONTROLS : HIDING_CONTROLS;
190 if (!top_controls_animation_ || animation_direction_ != show_controls) {
191 SetupAnimation(show_controls);
192 client_->setNeedsRedraw();
197 bool TopControlsManager::IsAnimationCompleteAtTime(base::TimeTicks time) {
198 if (!top_controls_animation_)
199 return true;
201 double time_ms = (time - base::TimeTicks()).InMillisecondsF();
202 float new_offset = top_controls_animation_->getValue(time_ms);
204 if ((animation_direction_ == SHOWING_CONTROLS && new_offset >= 0) ||
205 (animation_direction_ == HIDING_CONTROLS
206 && new_offset <= -top_controls_height_)) {
207 return true;
209 return false;
212 } // namespace cc