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

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

Issue 2554913002: Prevent overlay scrollbars expand or hover together (Closed)
Patch Set: 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 { 13 namespace {
14 const float kIdleThicknessScale = 0.4f;
15 const float kDefaultMouseMoveDistanceToTriggerAnimation = 25.f; 14 const float kDefaultMouseMoveDistanceToTriggerAnimation = 25.f;
16 } 15 }
17 16
18 namespace cc { 17 namespace cc {
19 18
20 std::unique_ptr<ScrollbarAnimationControllerThinning> 19 using std::for_each;
20
21 unique_ptr<ScrollbarAnimationControllerThinning>
21 ScrollbarAnimationControllerThinning::Create( 22 ScrollbarAnimationControllerThinning::Create(
22 int scroll_layer_id, 23 int scroll_layer_id,
23 ScrollbarAnimationControllerClient* client, 24 ScrollbarAnimationControllerClient* client,
24 base::TimeDelta delay_before_starting, 25 base::TimeDelta delay_before_starting,
25 base::TimeDelta resize_delay_before_starting, 26 base::TimeDelta resize_delay_before_starting,
26 base::TimeDelta fade_duration, 27 base::TimeDelta fade_duration,
27 base::TimeDelta thinning_duration) { 28 base::TimeDelta thinning_duration) {
28 return base::WrapUnique(new ScrollbarAnimationControllerThinning( 29 return base::WrapUnique(new ScrollbarAnimationControllerThinning(
29 scroll_layer_id, client, delay_before_starting, 30 scroll_layer_id, client, delay_before_starting,
30 resize_delay_before_starting, fade_duration, thinning_duration)); 31 resize_delay_before_starting, fade_duration, thinning_duration));
31 } 32 }
32 33
33 ScrollbarAnimationControllerThinning::ScrollbarAnimationControllerThinning( 34 ScrollbarAnimationControllerThinning::ScrollbarAnimationControllerThinning(
34 int scroll_layer_id, 35 int scroll_layer_id,
35 ScrollbarAnimationControllerClient* client, 36 ScrollbarAnimationControllerClient* client,
36 base::TimeDelta delay_before_starting, 37 base::TimeDelta delay_before_starting,
37 base::TimeDelta resize_delay_before_starting, 38 base::TimeDelta resize_delay_before_starting,
38 base::TimeDelta fade_duration, 39 base::TimeDelta fade_duration,
39 base::TimeDelta thinning_duration) 40 base::TimeDelta thinning_duration)
40 : ScrollbarAnimationController(scroll_layer_id, 41 : ScrollbarAnimationController(scroll_layer_id,
41 client, 42 client,
42 delay_before_starting, 43 delay_before_starting,
43 resize_delay_before_starting), 44 resize_delay_before_starting) {
44 opacity_(0.0f), 45 scrollbar_controllers.push_back(
45 captured_(false), 46 SingleScrollbarAnimationControllerThinning::Create(
46 mouse_is_over_scrollbar_(false), 47 scroll_layer_id, ScrollbarOrientation::VERTICAL, client,
47 mouse_is_near_scrollbar_(false), 48 delay_before_starting, resize_delay_before_starting, fade_duration,
48 thickness_change_(NONE), 49 thinning_duration));
49 mouse_move_distance_to_trigger_animation_( 50 scrollbar_controllers.push_back(
50 kDefaultMouseMoveDistanceToTriggerAnimation), 51 SingleScrollbarAnimationControllerThinning::Create(
51 fade_duration_(fade_duration), 52 scroll_layer_id, ScrollbarOrientation::HORIZONTAL, client,
52 thinning_duration_(thinning_duration), 53 delay_before_starting, resize_delay_before_starting, fade_duration,
53 current_animating_property_(OPACITY) { 54 thinning_duration));
54 ApplyOpacity(0.f);
55 ApplyThumbThicknessScale(kIdleThicknessScale);
56 } 55 }
57 56
58 ScrollbarAnimationControllerThinning::~ScrollbarAnimationControllerThinning() {} 57 ScrollbarAnimationControllerThinning::~ScrollbarAnimationControllerThinning() {}
59 58
60 void ScrollbarAnimationControllerThinning::RunAnimationFrame(float progress) { 59 void ScrollbarAnimationControllerThinning::GetScrollbarAnimationController(
61 if (captured_) 60 ScrollbarOrientation orientation,
62 return; 61 SingleScrollbarAnimationControllerThinning* scrollbar_controller) const {
62 for (auto itr = scrollbar_controllers.begin();
63 itr != scrollbar_controllers.end(); itr++) {
64 if ((*itr)->orientation() == orientation) {
65 scrollbar_controller = itr->get();
66 }
67 }
68 DCHECK(scrollbar_controller);
69 }
63 70
64 if (current_animating_property_ == OPACITY) 71 bool ScrollbarAnimationControllerThinning::mouse_is_over_scrollbar(
65 ApplyOpacity(1.f - progress); 72 ScrollbarOrientation orientation) const {
66 else 73 SingleScrollbarAnimationControllerThinning* scrollbar_controller_ptr =
67 ApplyThumbThicknessScale(ThumbThicknessScaleAt(progress)); 74 nullptr;
75 GetScrollbarAnimationController(orientation, scrollbar_controller_ptr);
76 return scrollbar_controller_ptr->mouse_is_over_scrollbar();
77 }
68 78
69 client_->SetNeedsRedrawForScrollbarAnimation(); 79 bool ScrollbarAnimationControllerThinning::mouse_is_near_scrollbar(
70 if (progress == 1.f) { 80 ScrollbarOrientation orientation) const {
71 StopAnimation(); 81 SingleScrollbarAnimationControllerThinning* scrollbar_controller_ptr =
72 if (current_animating_property_ == THICKNESS) { 82 nullptr;
73 thickness_change_ = NONE; 83 GetScrollbarAnimationController(orientation, scrollbar_controller_ptr);
74 SetCurrentAnimatingProperty(OPACITY); 84 return scrollbar_controller_ptr->mouse_is_near_scrollbar();
75 PostDelayedAnimationTask(false); 85 }
76 } 86
87 bool ScrollbarAnimationControllerThinning::ScrollbarsHidden() const {
88 return scrollbar_controllers[0]->ScrollbarsHidden();
89 }
90
91 void ScrollbarAnimationControllerThinning::set_mouse_move_distance_for_test(
92 float distance) {
93 for (auto itr = scrollbar_controllers.begin();
94 itr != scrollbar_controllers.end(); itr++) {
95 (*itr)->set_mouse_move_distance_for_test(distance);
77 } 96 }
78 } 97 }
79 98
99 bool ScrollbarAnimationControllerThinning::Animate(base::TimeTicks now) {
100 bool result = false;
101 for (auto itr = scrollbar_controllers.begin();
102 itr != scrollbar_controllers.end(); itr++) {
103 result |= (*itr)->Animate(now);
104 }
105
106 return result;
107 }
108
109 void ScrollbarAnimationControllerThinning::RunAnimationFrame(float progress) {
110 // do nothing
111 }
112
80 const base::TimeDelta& ScrollbarAnimationControllerThinning::Duration() { 113 const base::TimeDelta& ScrollbarAnimationControllerThinning::Duration() {
81 if (current_animating_property_ == OPACITY) 114 // should not call
82 return fade_duration_; 115 return scrollbar_controllers[0]->Duration();
83 else
84 return thinning_duration_;
85 } 116 }
86 117
87 void ScrollbarAnimationControllerThinning::DidMouseDown() { 118 void ScrollbarAnimationControllerThinning::DidMouseDown() {
88 if (!mouse_is_over_scrollbar_ || opacity_ == 0.0f) 119 for_each(
89 return; 120 scrollbar_controllers.begin(), scrollbar_controllers.end(),
90 121 [](unique_ptr<SingleScrollbarAnimationControllerThinning>&
91 StopAnimation(); 122 scrollbar_controller) { scrollbar_controller->DidMouseDown(); });
92 captured_ = true;
93 ApplyOpacity(1.f);
94 ApplyThumbThicknessScale(1.f);
95 } 123 }
96 124
97 void ScrollbarAnimationControllerThinning::DidMouseUp() { 125 void ScrollbarAnimationControllerThinning::DidMouseUp() {
98 if (!captured_ || opacity_ == 0.0f) 126 for_each(
99 return; 127 scrollbar_controllers.begin(), scrollbar_controllers.end(),
100 128 [](unique_ptr<SingleScrollbarAnimationControllerThinning>&
101 captured_ = false; 129 scrollbar_controller) { scrollbar_controller->DidMouseUp(); });
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 } 130 }
113 131
114 void ScrollbarAnimationControllerThinning::DidMouseLeave() { 132 void ScrollbarAnimationControllerThinning::DidMouseLeave() {
115 if (!mouse_is_over_scrollbar_ && !mouse_is_near_scrollbar_) 133 for_each(
116 return; 134 scrollbar_controllers.begin(), scrollbar_controllers.end(),
117 135 [](unique_ptr<SingleScrollbarAnimationControllerThinning>&
118 mouse_is_over_scrollbar_ = false; 136 scrollbar_controller) { scrollbar_controller->DidMouseLeave(); });
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 } 137 }
128 138
129 void ScrollbarAnimationControllerThinning::DidScrollUpdate(bool on_resize) { 139 void ScrollbarAnimationControllerThinning::DidScrollUpdate(bool on_resize) {
130 if (captured_) 140 for_each(scrollbar_controllers.begin(), scrollbar_controllers.end(),
131 return; 141 [&on_resize](unique_ptr<SingleScrollbarAnimationControllerThinning>&
132 142 scrollbar_controller) {
133 ScrollbarAnimationController::DidScrollUpdate(on_resize); 143 scrollbar_controller->DidScrollUpdate(on_resize);
134 ApplyOpacity(1.f); 144 });
135 ApplyThumbThicknessScale(mouse_is_near_scrollbar_ ? 1.f
136 : kIdleThicknessScale);
137 SetCurrentAnimatingProperty(OPACITY);
138 } 145 }
139 146
140 void ScrollbarAnimationControllerThinning::DidMouseMoveNear(float distance) { 147 void ScrollbarAnimationControllerThinning::DidMouseMoveNear(
141 bool mouse_is_over_scrollbar = distance == 0.0f; 148 vector<DistanceToScrollbar> distances) {
142 bool mouse_is_near_scrollbar = 149 for_each(scrollbar_controllers.begin(), scrollbar_controllers.end(),
143 distance < mouse_move_distance_to_trigger_animation_; 150 [&distances](unique_ptr<SingleScrollbarAnimationControllerThinning>&
144 151 scrollbar_controller) {
145 if (captured_ || opacity_ == 0.0f) { 152 scrollbar_controller->DidMouseMoveNear(distances);
146 mouse_is_near_scrollbar_ = mouse_is_near_scrollbar; 153 });
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 } 154 }
251 155
252 } // namespace cc 156 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698