Compute can_use_lcd_text using property trees.
[chromium-blink-merge.git] / cc / input / top_controls_manager.cc
blob1a961b50e9393697598bf83738dbe3684c56d1e4
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/input/top_controls_manager.h"
7 #include <algorithm>
9 #include "base/logging.h"
10 #include "cc/animation/keyframed_animation_curve.h"
11 #include "cc/animation/timing_function.h"
12 #include "cc/input/top_controls_manager_client.h"
13 #include "cc/output/begin_frame_args.h"
14 #include "cc/trees/layer_tree_impl.h"
15 #include "ui/gfx/geometry/vector2d_f.h"
16 #include "ui/gfx/transform.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 int64 kShowHideMaxDurationMs = 200;
25 // static
26 scoped_ptr<TopControlsManager> TopControlsManager::Create(
27 TopControlsManagerClient* client,
28 float top_controls_show_threshold,
29 float top_controls_hide_threshold) {
30 return make_scoped_ptr(new TopControlsManager(client,
31 top_controls_show_threshold,
32 top_controls_hide_threshold));
35 TopControlsManager::TopControlsManager(TopControlsManagerClient* client,
36 float top_controls_show_threshold,
37 float top_controls_hide_threshold)
38 : client_(client),
39 animation_direction_(NO_ANIMATION),
40 permitted_state_(BOTH),
41 accumulated_scroll_delta_(0.f),
42 baseline_content_offset_(0.f),
43 top_controls_show_threshold_(top_controls_hide_threshold),
44 top_controls_hide_threshold_(top_controls_show_threshold),
45 pinch_gesture_active_(false) {
46 CHECK(client_);
49 TopControlsManager::~TopControlsManager() {
52 float TopControlsManager::ControlsTopOffset() const {
53 return ContentTopOffset() - TopControlsHeight();
56 float TopControlsManager::ContentTopOffset() const {
57 return TopControlsShownRatio() * TopControlsHeight();
60 float TopControlsManager::TopControlsShownRatio() const {
61 return client_->CurrentTopControlsShownRatio();
64 float TopControlsManager::TopControlsHeight() const {
65 return client_->TopControlsHeight();
68 void TopControlsManager::UpdateTopControlsState(TopControlsState constraints,
69 TopControlsState current,
70 bool animate) {
71 DCHECK(!(constraints == SHOWN && current == HIDDEN));
72 DCHECK(!(constraints == HIDDEN && current == SHOWN));
74 permitted_state_ = constraints;
76 // Don't do anything if it doesn't matter which state the controls are in.
77 if (constraints == BOTH && current == BOTH)
78 return;
80 // Don't do anything if there is no change in offset.
81 float final_shown_ratio = 1.f;
82 if (constraints == HIDDEN || current == HIDDEN)
83 final_shown_ratio = 0.f;
84 if (final_shown_ratio == TopControlsShownRatio())
85 return;
87 if (animate) {
88 SetupAnimation(final_shown_ratio ? SHOWING_CONTROLS : HIDING_CONTROLS);
89 } else {
90 ResetAnimations();
91 client_->SetCurrentTopControlsShownRatio(final_shown_ratio);
95 void TopControlsManager::ScrollBegin() {
96 DCHECK(!pinch_gesture_active_);
97 ResetAnimations();
98 ResetBaseline();
101 gfx::Vector2dF TopControlsManager::ScrollBy(
102 const gfx::Vector2dF& pending_delta) {
103 if (!TopControlsHeight())
104 return pending_delta;
106 if (pinch_gesture_active_)
107 return pending_delta;
109 if (permitted_state_ == SHOWN && pending_delta.y() > 0)
110 return pending_delta;
111 else if (permitted_state_ == HIDDEN && pending_delta.y() < 0)
112 return pending_delta;
114 accumulated_scroll_delta_ += pending_delta.y();
116 float old_offset = ContentTopOffset();
117 client_->SetCurrentTopControlsShownRatio(
118 (baseline_content_offset_ - accumulated_scroll_delta_) /
119 TopControlsHeight());
121 // If the controls are fully visible, treat the current position as the
122 // new baseline even if the gesture didn't end.
123 if (TopControlsShownRatio() == 1.f)
124 ResetBaseline();
126 ResetAnimations();
128 gfx::Vector2dF applied_delta(0.f, old_offset - ContentTopOffset());
129 return pending_delta - applied_delta;
132 void TopControlsManager::ScrollEnd() {
133 DCHECK(!pinch_gesture_active_);
134 StartAnimationIfNecessary();
137 void TopControlsManager::PinchBegin() {
138 DCHECK(!pinch_gesture_active_);
139 pinch_gesture_active_ = true;
140 StartAnimationIfNecessary();
143 void TopControlsManager::PinchEnd() {
144 DCHECK(pinch_gesture_active_);
145 // Pinch{Begin,End} will always occur within the scope of Scroll{Begin,End},
146 // so return to a state expected by the remaining scroll sequence.
147 pinch_gesture_active_ = false;
148 ScrollBegin();
151 void TopControlsManager::MainThreadHasStoppedFlinging() {
152 StartAnimationIfNecessary();
155 gfx::Vector2dF TopControlsManager::Animate(base::TimeTicks monotonic_time) {
156 if (!top_controls_animation_ || !client_->HaveRootScrollLayer())
157 return gfx::Vector2dF();
159 base::TimeDelta time = monotonic_time - base::TimeTicks();
161 float old_offset = ContentTopOffset();
162 client_->SetCurrentTopControlsShownRatio(
163 top_controls_animation_->GetValue(time));
165 if (IsAnimationCompleteAtTime(monotonic_time))
166 ResetAnimations();
168 gfx::Vector2dF scroll_delta(0.f, ContentTopOffset() - old_offset);
169 return scroll_delta;
172 void TopControlsManager::ResetAnimations() {
173 top_controls_animation_ = nullptr;
174 animation_direction_ = NO_ANIMATION;
177 void TopControlsManager::SetupAnimation(AnimationDirection direction) {
178 DCHECK_NE(NO_ANIMATION, direction);
179 DCHECK_IMPLIES(direction == HIDING_CONTROLS, TopControlsShownRatio() > 0.f);
180 DCHECK_IMPLIES(direction == SHOWING_CONTROLS, TopControlsShownRatio() < 1.f);
182 if (top_controls_animation_ && animation_direction_ == direction)
183 return;
185 if (!TopControlsHeight()) {
186 client_->SetCurrentTopControlsShownRatio(
187 direction == HIDING_CONTROLS ? 0.f : 1.f);
188 return;
191 top_controls_animation_ = KeyframedFloatAnimationCurve::Create();
192 base::TimeDelta start_time = base::TimeTicks::Now() - base::TimeTicks();
193 top_controls_animation_->AddKeyframe(
194 FloatKeyframe::Create(start_time, TopControlsShownRatio(), nullptr));
195 float max_ending_ratio = (direction == SHOWING_CONTROLS ? 1 : -1);
196 top_controls_animation_->AddKeyframe(FloatKeyframe::Create(
197 start_time + base::TimeDelta::FromMilliseconds(kShowHideMaxDurationMs),
198 TopControlsShownRatio() + max_ending_ratio,
199 EaseTimingFunction::Create()));
200 animation_direction_ = direction;
201 client_->DidChangeTopControlsPosition();
204 void TopControlsManager::StartAnimationIfNecessary() {
205 if (TopControlsShownRatio() == 0.f || TopControlsShownRatio() == 1.f)
206 return;
208 if (TopControlsShownRatio() >= 1.f - top_controls_hide_threshold_) {
209 // If we're showing so much that the hide threshold won't trigger, show.
210 SetupAnimation(SHOWING_CONTROLS);
211 } else if (TopControlsShownRatio() <= top_controls_show_threshold_) {
212 // If we're showing so little that the show threshold won't trigger, hide.
213 SetupAnimation(HIDING_CONTROLS);
214 } else {
215 // If we could be either showing or hiding, we determine which one to
216 // do based on whether or not the total scroll delta was moving up or
217 // down.
218 SetupAnimation(accumulated_scroll_delta_ <= 0.f ? SHOWING_CONTROLS
219 : HIDING_CONTROLS);
223 bool TopControlsManager::IsAnimationCompleteAtTime(base::TimeTicks time) {
224 if (!top_controls_animation_)
225 return true;
227 base::TimeDelta animation_time = time - base::TimeTicks();
228 float new_ratio = top_controls_animation_->GetValue(animation_time);
230 if ((animation_direction_ == SHOWING_CONTROLS && new_ratio >= 1.f) ||
231 (animation_direction_ == HIDING_CONTROLS && new_ratio <= 0.f)) {
232 return true;
234 return false;
237 void TopControlsManager::ResetBaseline() {
238 accumulated_scroll_delta_ = 0.f;
239 baseline_content_offset_ = ContentTopOffset();
242 } // namespace cc