Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Side by Side Diff: cc/input/scrollbar_animation_controller.cc

Issue 2692243005: Merge Compositor's ScrollbarAnimationControllers into single class (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/input/scrollbar_animation_controller.h" 5 #include "cc/input/scrollbar_animation_controller.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/time/time.h" 9 #include "base/time/time.h"
10 #include "cc/trees/layer_tree_impl.h" 10 #include "cc/trees/layer_tree_impl.h"
11 11
12 namespace cc { 12 namespace cc {
13 13
14 std::unique_ptr<ScrollbarAnimationController>
15 ScrollbarAnimationController::CreateScrollbarAnimationControllerLinearFade(
16 int scroll_layer_id,
17 ScrollbarAnimationControllerClient* client,
18 base::TimeDelta delay_before_starting,
19 base::TimeDelta resize_delay_before_starting,
20 base::TimeDelta fade_duration) {
21 return base::WrapUnique(new ScrollbarAnimationController(
22 scroll_layer_id, client, delay_before_starting,
23 resize_delay_before_starting, fade_duration));
24 }
25
26 std::unique_ptr<ScrollbarAnimationController>
27 ScrollbarAnimationController::CreateScrollbarAnimationControllerThinning(
28 int scroll_layer_id,
29 ScrollbarAnimationControllerClient* client,
30 base::TimeDelta delay_before_starting,
31 base::TimeDelta resize_delay_before_starting,
32 base::TimeDelta fade_duration,
33 base::TimeDelta thinning_duration) {
34 return base::WrapUnique(new ScrollbarAnimationController(
35 scroll_layer_id, client, delay_before_starting,
36 resize_delay_before_starting, fade_duration, thinning_duration));
37 }
38
14 ScrollbarAnimationController::ScrollbarAnimationController( 39 ScrollbarAnimationController::ScrollbarAnimationController(
15 int scroll_layer_id, 40 int scroll_layer_id,
16 ScrollbarAnimationControllerClient* client, 41 ScrollbarAnimationControllerClient* client,
17 base::TimeDelta delay_before_starting, 42 base::TimeDelta delay_before_starting,
18 base::TimeDelta resize_delay_before_starting) 43 base::TimeDelta resize_delay_before_starting,
44 base::TimeDelta fade_duration)
19 : client_(client), 45 : client_(client),
20 delay_before_starting_(delay_before_starting), 46 delay_before_starting_(delay_before_starting),
21 resize_delay_before_starting_(resize_delay_before_starting), 47 resize_delay_before_starting_(resize_delay_before_starting),
22 is_animating_(false), 48 is_animating_(false),
23 scroll_layer_id_(scroll_layer_id), 49 scroll_layer_id_(scroll_layer_id),
24 currently_scrolling_(false), 50 currently_scrolling_(false),
25 scroll_gesture_has_scrolled_(false), 51 scroll_gesture_has_scrolled_(false),
52 opacity_(0.0f),
53 fade_duration_(fade_duration),
54 need_thinning_animation_(false),
26 weak_factory_(this) { 55 weak_factory_(this) {
56 ApplyOpacityToScrollbars(0.0f);
57 }
58
59 ScrollbarAnimationController::ScrollbarAnimationController(
60 int scroll_layer_id,
61 ScrollbarAnimationControllerClient* client,
62 base::TimeDelta delay_before_starting,
63 base::TimeDelta resize_delay_before_starting,
64 base::TimeDelta fade_duration,
65 base::TimeDelta thinning_duration)
66 : ScrollbarAnimationController(scroll_layer_id,
67 client,
68 delay_before_starting,
69 resize_delay_before_starting,
70 fade_duration) {
71 need_thinning_animation_ = true;
72 vertical_controller_ = SingleScrollbarAnimationControllerThinning::Create(
73 scroll_layer_id, ScrollbarOrientation::VERTICAL, client,
74 thinning_duration);
75 horizontal_controller_ = SingleScrollbarAnimationControllerThinning::Create(
76 scroll_layer_id, ScrollbarOrientation::HORIZONTAL, client,
77 thinning_duration);
27 } 78 }
28 79
29 ScrollbarAnimationController::~ScrollbarAnimationController() {} 80 ScrollbarAnimationController::~ScrollbarAnimationController() {}
30 81
82 ScrollbarSet ScrollbarAnimationController::Scrollbars() const {
83 return client_->ScrollbarsFor(scroll_layer_id_);
84 }
85
31 SingleScrollbarAnimationControllerThinning& 86 SingleScrollbarAnimationControllerThinning&
32 ScrollbarAnimationController::GetScrollbarAnimationController( 87 ScrollbarAnimationController::GetScrollbarAnimationController(
33 ScrollbarOrientation orientation) const { 88 ScrollbarOrientation orientation) const {
34 DCHECK(NeedThinningAnimation()); 89 DCHECK(need_thinning_animation_);
35 if (orientation == ScrollbarOrientation::VERTICAL) 90 if (orientation == ScrollbarOrientation::VERTICAL)
36 return *(vertical_controller_.get()); 91 return *(vertical_controller_.get());
37 else 92 else
38 return *(horizontal_controller_.get()); 93 return *(horizontal_controller_.get());
39 } 94 }
40 95
96 void ScrollbarAnimationController::StartAnimation() {
97 delayed_scrollbar_fade_.Cancel();
98 is_animating_ = true;
99 last_awaken_time_ = base::TimeTicks();
100 client_->SetNeedsAnimateForScrollbarAnimation();
101 }
102
103 void ScrollbarAnimationController::StopAnimation() {
104 delayed_scrollbar_fade_.Cancel();
105 is_animating_ = false;
106 }
107
108 void ScrollbarAnimationController::PostDelayedAnimationTask(bool on_resize) {
109 base::TimeDelta delay =
110 on_resize ? resize_delay_before_starting_ : delay_before_starting_;
111 delayed_scrollbar_fade_.Reset(
112 base::Bind(&ScrollbarAnimationController::StartAnimation,
113 weak_factory_.GetWeakPtr()));
114 client_->PostDelayedScrollbarAnimationTask(delayed_scrollbar_fade_.callback(),
115 delay);
116 }
117
41 bool ScrollbarAnimationController::Animate(base::TimeTicks now) { 118 bool ScrollbarAnimationController::Animate(base::TimeTicks now) {
42 bool animated = false; 119 bool animated = false;
43 120
44 if (is_animating_) { 121 if (is_animating_) {
45 if (last_awaken_time_.is_null()) 122 if (last_awaken_time_.is_null())
46 last_awaken_time_ = now; 123 last_awaken_time_ = now;
47 124
48 float progress = AnimationProgressAtTime(now); 125 float progress = AnimationProgressAtTime(now);
49 RunAnimationFrame(progress); 126 RunAnimationFrame(progress);
50 127
51 if (is_animating_) 128 if (is_animating_)
52 client_->SetNeedsAnimateForScrollbarAnimation(); 129 client_->SetNeedsAnimateForScrollbarAnimation();
53 animated = true; 130 animated = true;
54 } 131 }
55 132
56 if (NeedThinningAnimation()) { 133 if (need_thinning_animation_) {
57 animated |= vertical_controller_->Animate(now); 134 animated |= vertical_controller_->Animate(now);
58 animated |= horizontal_controller_->Animate(now); 135 animated |= horizontal_controller_->Animate(now);
59 } 136 }
60 137
61 return animated; 138 return animated;
62 } 139 }
63 140
64 bool ScrollbarAnimationController::ScrollbarsHidden() const {
65 return false;
66 }
67
68 bool ScrollbarAnimationController::NeedThinningAnimation() const {
69 return false;
70 }
71
72 float ScrollbarAnimationController::AnimationProgressAtTime( 141 float ScrollbarAnimationController::AnimationProgressAtTime(
73 base::TimeTicks now) { 142 base::TimeTicks now) {
74 base::TimeDelta delta = now - last_awaken_time_; 143 base::TimeDelta delta = now - last_awaken_time_;
75 float progress = delta.InSecondsF() / Duration().InSecondsF(); 144 float progress = delta.InSecondsF() / fade_duration_.InSecondsF();
76 return std::max(std::min(progress, 1.f), 0.f); 145 return std::max(std::min(progress, 1.f), 0.f);
77 } 146 }
78 147
79 void ScrollbarAnimationController::DidScrollBegin() { 148 void ScrollbarAnimationController::DidScrollBegin() {
80 currently_scrolling_ = true; 149 currently_scrolling_ = true;
81 } 150 }
82 151
152 void ScrollbarAnimationController::RunAnimationFrame(float progress) {
153 ApplyOpacityToScrollbars(1.f - progress);
154 client_->SetNeedsRedrawForScrollbarAnimation();
155 if (progress == 1.f)
156 StopAnimation();
157 }
158
83 void ScrollbarAnimationController::DidScrollUpdate(bool on_resize) { 159 void ScrollbarAnimationController::DidScrollUpdate(bool on_resize) {
160 if (need_thinning_animation_ && Captured())
161 return;
162
84 StopAnimation(); 163 StopAnimation();
85 164
86 // As an optimization, we avoid spamming fade delay tasks during active fast 165 // As an optimization, we avoid spamming fade delay tasks during active fast
87 // scrolls. But if we're not within one, we need to post every scroll update. 166 // scrolls. But if we're not within one, we need to post every scroll update.
88 if (!currently_scrolling_) 167 if (!currently_scrolling_) {
89 PostDelayedAnimationTask(on_resize); 168 // We don't fade out scrollbar if they need thinning animation and mouse is
90 else 169 // near.
170 if (!need_thinning_animation_ || !mouse_is_near_any_scrollbar())
171 PostDelayedAnimationTask(on_resize);
172 } else {
91 scroll_gesture_has_scrolled_ = true; 173 scroll_gesture_has_scrolled_ = true;
174 }
175
176 ApplyOpacityToScrollbars(1);
177
178 if (need_thinning_animation_) {
179 vertical_controller_->UpdateThumbThicknessScale();
180 horizontal_controller_->UpdateThumbThicknessScale();
181 }
92 } 182 }
93 183
94 void ScrollbarAnimationController::DidScrollEnd() { 184 void ScrollbarAnimationController::DidScrollEnd() {
95 if (scroll_gesture_has_scrolled_) { 185 bool has_scrolled = scroll_gesture_has_scrolled_;
96 PostDelayedAnimationTask(false); 186 scroll_gesture_has_scrolled_ = false;
97 scroll_gesture_has_scrolled_ = false;
98 }
99 187
100 currently_scrolling_ = false; 188 currently_scrolling_ = false;
189
190 // We don't fade out scrollbar if they need thinning animation and mouse is
191 // near.
192 if (need_thinning_animation_ && mouse_is_near_any_scrollbar())
193 return;
194
195 if (has_scrolled)
196 PostDelayedAnimationTask(false);
101 } 197 }
102 198
103 void ScrollbarAnimationController::DidMouseDown() { 199 void ScrollbarAnimationController::DidMouseDown() {
104 if (!NeedThinningAnimation() || ScrollbarsHidden()) 200 if (!need_thinning_animation_ || ScrollbarsHidden())
105 return; 201 return;
106 202
107 vertical_controller_->DidMouseDown(); 203 vertical_controller_->DidMouseDown();
108 horizontal_controller_->DidMouseDown(); 204 horizontal_controller_->DidMouseDown();
109 } 205 }
110 206
111 void ScrollbarAnimationController::DidMouseUp() { 207 void ScrollbarAnimationController::DidMouseUp() {
112 if (!NeedThinningAnimation()) 208 if (!need_thinning_animation_)
113 return; 209 return;
114 210
115 vertical_controller_->DidMouseUp(); 211 vertical_controller_->DidMouseUp();
116 horizontal_controller_->DidMouseUp(); 212 horizontal_controller_->DidMouseUp();
117 213
118 if (!mouse_is_near_any_scrollbar()) 214 if (!mouse_is_near_any_scrollbar())
119 PostDelayedAnimationTask(false); 215 PostDelayedAnimationTask(false);
120 } 216 }
121 217
122 void ScrollbarAnimationController::DidMouseLeave() { 218 void ScrollbarAnimationController::DidMouseLeave() {
123 if (!NeedThinningAnimation()) 219 if (!need_thinning_animation_)
124 return; 220 return;
125 221
126 vertical_controller_->DidMouseLeave(); 222 vertical_controller_->DidMouseLeave();
127 horizontal_controller_->DidMouseLeave(); 223 horizontal_controller_->DidMouseLeave();
128 224
129 if (ScrollbarsHidden() || Captured()) 225 if (ScrollbarsHidden() || Captured())
130 return; 226 return;
131 227
132 PostDelayedAnimationTask(false); 228 PostDelayedAnimationTask(false);
133 } 229 }
134 230
135 void ScrollbarAnimationController::DidMouseMoveNear( 231 void ScrollbarAnimationController::DidMouseMoveNear(
136 ScrollbarOrientation orientation, 232 ScrollbarOrientation orientation,
137 float distance) { 233 float distance) {
138 if (!NeedThinningAnimation()) 234 if (!need_thinning_animation_)
139 return; 235 return;
140 236
141 GetScrollbarAnimationController(orientation).DidMouseMoveNear(distance); 237 GetScrollbarAnimationController(orientation).DidMouseMoveNear(distance);
142 238
143 if (ScrollbarsHidden() || Captured()) 239 if (ScrollbarsHidden() || Captured())
144 return; 240 return;
145 241
146 if (mouse_is_near_any_scrollbar()) { 242 if (mouse_is_near_any_scrollbar()) {
147 ApplyOpacityToScrollbars(1); 243 ApplyOpacityToScrollbars(1);
148 StopAnimation(); 244 StopAnimation();
149 } else if (!animating_fade()) { 245 } else if (!is_animating_) {
150 PostDelayedAnimationTask(false); 246 PostDelayedAnimationTask(false);
151 } 247 }
152 } 248 }
153 249
154 bool ScrollbarAnimationController::mouse_is_over_scrollbar( 250 bool ScrollbarAnimationController::mouse_is_over_scrollbar(
155 ScrollbarOrientation orientation) const { 251 ScrollbarOrientation orientation) const {
156 DCHECK(NeedThinningAnimation()); 252 DCHECK(need_thinning_animation_);
157 return GetScrollbarAnimationController(orientation).mouse_is_over_scrollbar(); 253 return GetScrollbarAnimationController(orientation).mouse_is_over_scrollbar();
158 } 254 }
159 255
160 bool ScrollbarAnimationController::mouse_is_near_scrollbar( 256 bool ScrollbarAnimationController::mouse_is_near_scrollbar(
161 ScrollbarOrientation orientation) const { 257 ScrollbarOrientation orientation) const {
162 DCHECK(NeedThinningAnimation()); 258 DCHECK(need_thinning_animation_);
163 return GetScrollbarAnimationController(orientation).mouse_is_near_scrollbar(); 259 return GetScrollbarAnimationController(orientation).mouse_is_near_scrollbar();
164 } 260 }
165 261
166 bool ScrollbarAnimationController::mouse_is_near_any_scrollbar() const { 262 bool ScrollbarAnimationController::mouse_is_near_any_scrollbar() const {
167 DCHECK(NeedThinningAnimation()); 263 DCHECK(need_thinning_animation_);
168 return vertical_controller_->mouse_is_near_scrollbar() || 264 return vertical_controller_->mouse_is_near_scrollbar() ||
169 horizontal_controller_->mouse_is_near_scrollbar(); 265 horizontal_controller_->mouse_is_near_scrollbar();
170 } 266 }
171 267
172 bool ScrollbarAnimationController::Captured() const { 268 bool ScrollbarAnimationController::ScrollbarsHidden() const {
173 DCHECK(NeedThinningAnimation()); 269 return opacity_ == 0.0f;
174 return vertical_controller_->captured() || horizontal_controller_->captured();
175 } 270 }
176 271
177 void ScrollbarAnimationController::PostDelayedAnimationTask(bool on_resize) { 272 bool ScrollbarAnimationController::Captured() const {
178 base::TimeDelta delay = 273 DCHECK(need_thinning_animation_);
179 on_resize ? resize_delay_before_starting_ : delay_before_starting_; 274 return vertical_controller_->captured() || horizontal_controller_->captured();
180 delayed_scrollbar_fade_.Reset(
181 base::Bind(&ScrollbarAnimationController::StartAnimation,
182 weak_factory_.GetWeakPtr()));
183 client_->PostDelayedScrollbarAnimationTask(delayed_scrollbar_fade_.callback(),
184 delay);
185 }
186
187 void ScrollbarAnimationController::StartAnimation() {
188 delayed_scrollbar_fade_.Cancel();
189 is_animating_ = true;
190 last_awaken_time_ = base::TimeTicks();
191 client_->SetNeedsAnimateForScrollbarAnimation();
192 }
193
194 void ScrollbarAnimationController::StopAnimation() {
195 delayed_scrollbar_fade_.Cancel();
196 is_animating_ = false;
197 }
198
199 ScrollbarSet ScrollbarAnimationController::Scrollbars() const {
200 return client_->ScrollbarsFor(scroll_layer_id_);
201 } 275 }
202 276
203 void ScrollbarAnimationController::set_mouse_move_distance_for_test( 277 void ScrollbarAnimationController::set_mouse_move_distance_for_test(
weiliangc 2017/02/15 19:41:15 Since set_moust_move_distance_for_test is availabl
chaopeng 2017/02/15 19:59:50 This is the entry for layer_tree_host_impl_unittes
weiliangc 2017/02/15 20:06:08 I see three use cases there, none of which seems l
204 float distance) { 278 float distance) {
205 vertical_controller_->set_mouse_move_distance_for_test(distance); 279 vertical_controller_->set_mouse_move_distance_for_test(distance);
206 horizontal_controller_->set_mouse_move_distance_for_test(distance); 280 horizontal_controller_->set_mouse_move_distance_for_test(distance);
207 } 281 }
208 282
283 void ScrollbarAnimationController::ApplyOpacityToScrollbars(float opacity) {
284 for (ScrollbarLayerImplBase* scrollbar : Scrollbars()) {
285 if (!scrollbar->is_overlay_scrollbar())
286 continue;
287 float effective_opacity = scrollbar->CanScrollOrientation() ? opacity : 0;
288 PropertyTrees* property_trees =
289 scrollbar->layer_tree_impl()->property_trees();
290 // If this method is called during LayerImpl::PushPropertiesTo, we may not
291 // yet have valid layer_id_to_effect_node_index entries as property trees
292 // are pushed after layers during activation. We can skip updating opacity
293 // in that case as we are only registering a scrollbar and because opacity
294 // will be overwritten anyway when property trees are pushed.
295 if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT,
296 scrollbar->id())) {
297 property_trees->effect_tree.OnOpacityAnimated(
298 effective_opacity,
299 property_trees->layer_id_to_effect_node_index[scrollbar->id()],
300 scrollbar->layer_tree_impl());
301 }
302 }
303
304 bool previouslyVisible = opacity_ > 0.0f;
305 bool currentlyVisible = opacity > 0.0f;
306
307 opacity_ = opacity;
308
309 if (previouslyVisible != currentlyVisible)
310 client_->DidChangeScrollbarVisibility();
311 }
312
209 } // namespace cc 313 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698