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

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

Issue 2554913002: Prevent overlay scrollbars expand or hover together (Closed)
Patch Set: add ScrollbarAnimationControllerThinningTest Created 4 years 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 2013 The Chromium Authors. All rights reserved. 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 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_thinning.h" 5 #include "cc/input/scrollbar_animation_controller_thinning.h"
6 6
7 #include "base/memory/ptr_util.h" 7 #include "base/memory/ptr_util.h"
8 #include "base/time/time.h" 8 #include "base/time/time.h"
9 #include "cc/layers/layer_impl.h" 9 #include "cc/layers/layer_impl.h"
10 #include "cc/layers/scrollbar_layer_impl_base.h" 10 #include "cc/layers/scrollbar_layer_impl_base.h"
11 #include "cc/trees/layer_tree_impl.h" 11 #include "cc/trees/layer_tree_impl.h"
12 12
13 namespace {
14 const float kIdleThicknessScale = 0.4f;
15 const float kDefaultMouseMoveDistanceToTriggerAnimation = 25.f;
16 }
17
18 namespace cc { 13 namespace cc {
19 14
20 std::unique_ptr<ScrollbarAnimationControllerThinning> 15 unique_ptr<ScrollbarAnimationControllerThinning>
21 ScrollbarAnimationControllerThinning::Create( 16 ScrollbarAnimationControllerThinning::Create(
22 int scroll_layer_id, 17 int scroll_layer_id,
23 ScrollbarAnimationControllerClient* client, 18 ScrollbarAnimationControllerClient* client,
24 base::TimeDelta delay_before_starting, 19 base::TimeDelta delay_before_starting,
25 base::TimeDelta resize_delay_before_starting, 20 base::TimeDelta resize_delay_before_starting,
26 base::TimeDelta fade_duration, 21 base::TimeDelta fade_duration,
27 base::TimeDelta thinning_duration) { 22 base::TimeDelta thinning_duration) {
28 return base::WrapUnique(new ScrollbarAnimationControllerThinning( 23 return base::WrapUnique(new ScrollbarAnimationControllerThinning(
29 scroll_layer_id, client, delay_before_starting, 24 scroll_layer_id, client, delay_before_starting,
30 resize_delay_before_starting, fade_duration, thinning_duration)); 25 resize_delay_before_starting, fade_duration, thinning_duration));
31 } 26 }
32 27
33 ScrollbarAnimationControllerThinning::ScrollbarAnimationControllerThinning( 28 ScrollbarAnimationControllerThinning::ScrollbarAnimationControllerThinning(
34 int scroll_layer_id, 29 int scroll_layer_id,
35 ScrollbarAnimationControllerClient* client, 30 ScrollbarAnimationControllerClient* client,
36 base::TimeDelta delay_before_starting, 31 base::TimeDelta delay_before_starting,
37 base::TimeDelta resize_delay_before_starting, 32 base::TimeDelta resize_delay_before_starting,
38 base::TimeDelta fade_duration, 33 base::TimeDelta fade_duration,
39 base::TimeDelta thinning_duration) 34 base::TimeDelta thinning_duration)
40 : ScrollbarAnimationController(scroll_layer_id, 35 : ScrollbarAnimationController(scroll_layer_id,
41 client, 36 client,
42 delay_before_starting, 37 delay_before_starting,
43 resize_delay_before_starting), 38 resize_delay_before_starting) {
44 opacity_(0.0f), 39 v_scrollbar_controller = SingleScrollbarAnimationControllerThinning::Create(
45 captured_(false), 40 scroll_layer_id, ScrollbarOrientation::VERTICAL, client,
46 mouse_is_over_scrollbar_(false), 41 delay_before_starting, resize_delay_before_starting, fade_duration,
47 mouse_is_near_scrollbar_(false), 42 thinning_duration);
48 thickness_change_(NONE), 43 h_scrollbar_controller = SingleScrollbarAnimationControllerThinning::Create(
49 mouse_move_distance_to_trigger_animation_( 44 scroll_layer_id, ScrollbarOrientation::HORIZONTAL, client,
50 kDefaultMouseMoveDistanceToTriggerAnimation), 45 delay_before_starting, resize_delay_before_starting, fade_duration,
51 fade_duration_(fade_duration), 46 thinning_duration);
52 thinning_duration_(thinning_duration),
53 current_animating_property_(OPACITY) {
54 ApplyOpacity(0.f);
55 ApplyThumbThicknessScale(kIdleThicknessScale);
56 } 47 }
57 48
58 ScrollbarAnimationControllerThinning::~ScrollbarAnimationControllerThinning() {} 49 ScrollbarAnimationControllerThinning::~ScrollbarAnimationControllerThinning() {}
59 50
51 SingleScrollbarAnimationControllerThinning*
bokan 2016/12/08 19:34:07 This should return a ref since we'll always have a
52 ScrollbarAnimationControllerThinning::GetScrollbarAnimationController(
53 ScrollbarOrientation orientation) const {
54 if (orientation == ScrollbarOrientation::VERTICAL)
55 return v_scrollbar_controller.get();
56 else
57 return h_scrollbar_controller.get();
58 }
59
60 bool ScrollbarAnimationControllerThinning::mouse_is_over_scrollbar(
61 ScrollbarOrientation orientation) const {
62 return GetScrollbarAnimationController(orientation)
63 ->mouse_is_over_scrollbar();
64 }
65
66 bool ScrollbarAnimationControllerThinning::mouse_is_near_scrollbar(
67 ScrollbarOrientation orientation) const {
68 return GetScrollbarAnimationController(orientation)
69 ->mouse_is_near_scrollbar();
70 }
71
72 bool ScrollbarAnimationControllerThinning::ScrollbarsHidden() const {
73 return v_scrollbar_controller->ScrollbarsHidden();
bokan 2016/12/08 19:34:07 Hidden state should be part of this class since sc
74 }
75
76 void ScrollbarAnimationControllerThinning::set_mouse_move_distance_for_test(
77 float distance) {
78 v_scrollbar_controller->set_mouse_move_distance_for_test(distance);
79 h_scrollbar_controller->set_mouse_move_distance_for_test(distance);
80 }
81
82 bool ScrollbarAnimationControllerThinning::Animate(base::TimeTicks now) {
83 bool result = v_scrollbar_controller->Animate(now);
84 result = h_scrollbar_controller->Animate(now) || result;
85 return result;
86 }
87
60 void ScrollbarAnimationControllerThinning::RunAnimationFrame(float progress) { 88 void ScrollbarAnimationControllerThinning::RunAnimationFrame(float progress) {
61 if (captured_) 89 // This method is deleted in ScrollbarAnimationControllerThinning
bokan 2016/12/08 19:34:07 It'd be more appropriate to say that we delegate r
62 return; 90 NOTREACHED();
63
64 if (current_animating_property_ == OPACITY)
65 ApplyOpacity(1.f - progress);
66 else
67 ApplyThumbThicknessScale(ThumbThicknessScaleAt(progress));
68
69 client_->SetNeedsRedrawForScrollbarAnimation();
70 if (progress == 1.f) {
71 StopAnimation();
72 if (current_animating_property_ == THICKNESS) {
73 thickness_change_ = NONE;
74 SetCurrentAnimatingProperty(OPACITY);
75 PostDelayedAnimationTask(false);
76 }
77 }
78 } 91 }
79 92
80 const base::TimeDelta& ScrollbarAnimationControllerThinning::Duration() { 93 const base::TimeDelta& ScrollbarAnimationControllerThinning::Duration() {
81 if (current_animating_property_ == OPACITY) 94 // This method is deleted in ScrollbarAnimationControllerThinning
82 return fade_duration_; 95 NOTREACHED();
83 else 96 return v_scrollbar_controller->Duration();
84 return thinning_duration_;
85 } 97 }
86 98
87 void ScrollbarAnimationControllerThinning::DidMouseDown() { 99 void ScrollbarAnimationControllerThinning::DidMouseDown() {
88 if (!mouse_is_over_scrollbar_ || opacity_ == 0.0f) 100 v_scrollbar_controller->DidMouseDown();
89 return; 101 h_scrollbar_controller->DidMouseDown();
90
91 StopAnimation();
92 captured_ = true;
93 ApplyOpacity(1.f);
94 ApplyThumbThicknessScale(1.f);
95 } 102 }
96 103
97 void ScrollbarAnimationControllerThinning::DidMouseUp() { 104 void ScrollbarAnimationControllerThinning::DidMouseUp() {
98 if (!captured_ || opacity_ == 0.0f) 105 v_scrollbar_controller->DidMouseUp();
99 return; 106 h_scrollbar_controller->DidMouseUp();
100
101 captured_ = false;
102 StopAnimation();
103
104 if (!mouse_is_near_scrollbar_) {
105 SetCurrentAnimatingProperty(THICKNESS);
106 thickness_change_ = DECREASE;
107 StartAnimation();
108 } else {
109 SetCurrentAnimatingProperty(OPACITY);
110 PostDelayedAnimationTask(false);
111 }
112 } 107 }
113 108
114 void ScrollbarAnimationControllerThinning::DidMouseLeave() { 109 void ScrollbarAnimationControllerThinning::DidMouseLeave() {
115 if (!mouse_is_over_scrollbar_ && !mouse_is_near_scrollbar_) 110 v_scrollbar_controller->DidMouseLeave();
116 return; 111 h_scrollbar_controller->DidMouseLeave();
117
118 mouse_is_over_scrollbar_ = false;
119 mouse_is_near_scrollbar_ = false;
120
121 if (captured_ || opacity_ == 0.0f)
122 return;
123
124 thickness_change_ = DECREASE;
125 SetCurrentAnimatingProperty(THICKNESS);
126 StartAnimation();
127 } 112 }
128 113
129 void ScrollbarAnimationControllerThinning::DidScrollUpdate(bool on_resize) { 114 void ScrollbarAnimationControllerThinning::DidScrollUpdate(bool on_resize) {
130 if (captured_) 115 v_scrollbar_controller->DidScrollUpdate(on_resize);
131 return; 116 h_scrollbar_controller->DidScrollUpdate(on_resize);
132
133 ScrollbarAnimationController::DidScrollUpdate(on_resize);
134 ApplyOpacity(1.f);
135 ApplyThumbThicknessScale(mouse_is_near_scrollbar_ ? 1.f
136 : kIdleThicknessScale);
137 SetCurrentAnimatingProperty(OPACITY);
138 } 117 }
139 118
140 void ScrollbarAnimationControllerThinning::DidMouseMoveNear(float distance) { 119 void ScrollbarAnimationControllerThinning::DidMouseMoveNear(
141 bool mouse_is_over_scrollbar = distance == 0.0f; 120 ScrollbarOrientation orientation,
142 bool mouse_is_near_scrollbar = 121 float distance) {
143 distance < mouse_move_distance_to_trigger_animation_; 122 GetScrollbarAnimationController(orientation)
144 123 ->DidMouseMoveNear(orientation, distance);
145 if (captured_ || opacity_ == 0.0f) {
146 mouse_is_near_scrollbar_ = mouse_is_near_scrollbar;
147 mouse_is_over_scrollbar_ = mouse_is_over_scrollbar;
148 return;
149 }
150
151 if (mouse_is_over_scrollbar == mouse_is_over_scrollbar_ &&
152 mouse_is_near_scrollbar == mouse_is_near_scrollbar_)
153 return;
154
155 if (mouse_is_over_scrollbar_ != mouse_is_over_scrollbar)
156 mouse_is_over_scrollbar_ = mouse_is_over_scrollbar;
157
158 if (mouse_is_near_scrollbar_ != mouse_is_near_scrollbar) {
159 mouse_is_near_scrollbar_ = mouse_is_near_scrollbar;
160 thickness_change_ = mouse_is_near_scrollbar_ ? INCREASE : DECREASE;
161 }
162
163 SetCurrentAnimatingProperty(THICKNESS);
164 StartAnimation();
165 }
166
167 bool ScrollbarAnimationControllerThinning::ScrollbarsHidden() const {
168 return opacity_ == 0.0f;
169 }
170
171 float ScrollbarAnimationControllerThinning::ThumbThicknessScaleAt(
172 float progress) {
173 if (thickness_change_ == NONE)
174 return mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale;
175 float factor = thickness_change_ == INCREASE ? progress : (1.f - progress);
176 return ((1.f - kIdleThicknessScale) * factor) + kIdleThicknessScale;
177 }
178
179 float ScrollbarAnimationControllerThinning::AdjustScale(
180 float new_value,
181 float current_value,
182 AnimationChange animation_change,
183 float min_value,
184 float max_value) {
185 float result;
186 if (animation_change == INCREASE && current_value > new_value)
187 result = current_value;
188 else if (animation_change == DECREASE && current_value < new_value)
189 result = current_value;
190 else
191 result = new_value;
192 if (result > max_value)
193 return max_value;
194 if (result < min_value)
195 return min_value;
196 return result;
197 }
198
199 void ScrollbarAnimationControllerThinning::ApplyOpacity(float opacity) {
200 for (ScrollbarLayerImplBase* scrollbar : Scrollbars()) {
201 if (!scrollbar->is_overlay_scrollbar())
202 continue;
203 float effective_opacity = scrollbar->CanScrollOrientation() ? opacity : 0;
204 PropertyTrees* property_trees =
205 scrollbar->layer_tree_impl()->property_trees();
206 // If this method is called during LayerImpl::PushPropertiesTo, we may not
207 // yet have valid effect_id_to_index_map entries as property trees are
208 // pushed after layers during activation. We can skip updating opacity in
209 // that case as we are only registering a scrollbar and because opacity will
210 // be overwritten anyway when property trees are pushed.
211 if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT,
212 scrollbar->id())) {
213 property_trees->effect_tree.OnOpacityAnimated(
214 effective_opacity,
215 property_trees->effect_id_to_index_map[scrollbar->id()],
216 scrollbar->layer_tree_impl());
217 }
218 }
219
220 bool previouslyVisible = opacity_ > 0.0f;
221 bool currentlyVisible = opacity > 0.0f;
222
223 opacity_ = opacity;
224
225 if (previouslyVisible != currentlyVisible)
226 client_->DidChangeScrollbarVisibility();
227 }
228
229 void ScrollbarAnimationControllerThinning::ApplyThumbThicknessScale(
230 float thumb_thickness_scale) {
231 for (ScrollbarLayerImplBase* scrollbar : Scrollbars()) {
232 if (!scrollbar->is_overlay_scrollbar())
233 continue;
234
235 scrollbar->SetThumbThicknessScaleFactor(AdjustScale(
236 thumb_thickness_scale, scrollbar->thumb_thickness_scale_factor(),
237 thickness_change_, kIdleThicknessScale, 1));
238 }
239 }
240
241 void ScrollbarAnimationControllerThinning::SetCurrentAnimatingProperty(
242 AnimatingProperty property) {
243 if (current_animating_property_ == property)
244 return;
245
246 StopAnimation();
247 current_animating_property_ = property;
248 if (current_animating_property_ == THICKNESS)
249 ApplyOpacity(1.f);
250 } 124 }
251 125
252 } // namespace cc 126 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698