OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2015 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. | |
4 | |
5 #include "content/browser/web_contents/aura/overscroll_window_animation.h" | |
6 | |
7 #include "base/auto_reset.h" | |
8 #include "content/browser/web_contents/aura/overscroll_window_delegate.h" | |
9 #include "content/browser/web_contents/aura/shadow_layer_delegate.h" | |
10 #include "content/browser/web_contents/web_contents_impl.h" | |
11 #include "content/browser/web_contents/web_contents_view_aura.h" | |
12 #include "content/public/browser/render_widget_host_view.h" | |
13 #include "ui/aura/window.h" | |
14 #include "ui/compositor/layer_animation_observer.h" | |
15 #include "ui/compositor/scoped_layer_animation_settings.h" | |
16 | |
17 namespace content { | |
18 | |
19 namespace { | |
20 | |
21 // Responsible for fading out and deleting the layer of the overlay window. | |
22 class OverlayDismissAnimator : public ui::LayerAnimationObserver { | |
23 public: | |
24 // Takes ownership of the layer. | |
25 explicit OverlayDismissAnimator(scoped_ptr<ui::Layer> layer) | |
26 : layer_(layer.Pass()) { | |
27 CHECK(layer_.get()); | |
28 } | |
29 | |
30 // Starts the fadeout animation on the layer. When the animation finishes, | |
31 // the object deletes itself along with the layer. | |
32 void Animate() { | |
33 DCHECK(layer_.get()); | |
34 ui::LayerAnimator* animator = layer_->GetAnimator(); | |
35 // This makes SetOpacity() animate with default duration (which could be | |
36 // zero, e.g. when running tests). | |
37 ui::ScopedLayerAnimationSettings settings(animator); | |
38 animator->AddObserver(this); | |
39 LOG(ERROR) << "Setting opacity to 0"; | |
40 layer_->SetOpacity(0); | |
41 } | |
42 | |
43 // Overridden from ui::LayerAnimationObserver | |
44 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override { | |
45 LOG(ERROR) << "Deleting dismiss layer"; | |
46 delete this; | |
47 } | |
48 | |
49 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override { | |
50 LOG(ERROR) << "Animation aborted!!!"; | |
51 delete this; | |
52 } | |
53 | |
54 void OnLayerAnimationScheduled( | |
55 ui::LayerAnimationSequence* sequence) override {} | |
56 | |
57 private: | |
58 ~OverlayDismissAnimator() override {} | |
59 | |
60 scoped_ptr<ui::Layer> layer_; | |
61 | |
62 DISALLOW_COPY_AND_ASSIGN(OverlayDismissAnimator); | |
63 }; | |
64 | |
65 } // namespace | |
66 | |
67 OverscrollWindowAnimation::OverscrollWindowAnimation( | |
68 WebContentsImpl* web_contents, | |
69 OverscrollNavigationOverlay* ono, | |
70 aura::Window* web_contents_window) | |
71 : web_contents_(web_contents), | |
72 ono_(ono), | |
73 direction_(OverscrollNavigationOverlay::NONE), | |
74 web_contents_window_(web_contents_window), | |
75 slide_layer_(nullptr), | |
76 fade_out_(false), | |
77 animation_cancelled_(false), | |
78 gesture_completed_(false) { | |
79 } | |
80 | |
81 OverscrollWindowAnimation::~OverscrollWindowAnimation() { | |
82 LOG(ERROR) << "OWA destructor"; | |
83 } | |
84 | |
85 void OverscrollWindowAnimation::CancelAnimation() { | |
86 LOG(ERROR) << "Cancelling animation"; | |
87 animation_cancelled_ = true; | |
88 fade_out_ = false; | |
89 gesture_completed_ = true; | |
90 aura::Window* animate_window = GetWindowToAnimateForOverscroll(); | |
91 if (!animate_window) | |
92 return; | |
93 ui::ScopedLayerAnimationSettings settings( | |
94 animate_window->layer()->GetAnimator()); | |
95 settings.SetPreemptionStrategy( | |
96 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | |
97 settings.SetTweenType(gfx::Tween::EASE_OUT); | |
98 settings.AddObserver(this); | |
99 animate_window->SetTransform(gfx::Transform()); | |
100 direction_ = OverscrollNavigationOverlay::NONE; | |
101 } | |
102 | |
103 // We should be able to delete this function. | |
104 void OverscrollWindowAnimation::AbortAllAnimations() { | |
105 aura::Window* target = GetWindowToAnimateForOverscroll(); | |
106 if (target) | |
107 target->layer()->GetAnimator()->AbortAllAnimations(); | |
108 } | |
109 | |
110 void OverscrollWindowAnimation::DismissOverlay() { | |
111 LOG(ERROR) << "Dismissing overlay"; | |
112 if (gesture_completed_) { | |
113 FadeOutOverscrollWindow(); | |
114 return; | |
115 } | |
116 fade_out_ = true; | |
117 } | |
118 | |
119 void OverscrollWindowAnimation::OnImplicitAnimationsCompleted() { | |
120 LOG(ERROR) << "On implicit animations completed"; | |
121 if (!overscroll_window_) { | |
122 LOG(ERROR) << "Overscroll window already destroyed, returning"; | |
123 return; | |
124 } | |
125 gesture_completed_ = true; | |
126 aura::Window* contents = web_contents_->GetContentNativeView(); | |
127 contents->parent()->StackChildBelow(contents, overscroll_window_.get()); | |
mfomitchev
2015/02/13 22:08:48
Similar to the previous comments - this logic shou
| |
128 contents->SetTransform(gfx::Transform()); | |
129 if (fade_out_) { | |
130 LOG(ERROR) << "With fade_out_ == true"; | |
131 FadeOutOverscrollWindow(); | |
132 return; | |
133 } | |
134 if (animation_cancelled_) { | |
135 LOG(ERROR) << "With animation_cancelled_ == true"; | |
136 overscroll_window_.reset(); | |
137 overscroll_shadow_.reset(); | |
138 } | |
139 } | |
140 | |
141 gfx::Vector2dF OverscrollWindowAnimation::GetTranslationForOverscroll( | |
142 float delta_x) { | |
143 const float bounds_width = | |
144 static_cast<float>(web_contents_window_->bounds().width()); | |
145 if (direction_ == OverscrollNavigationOverlay::FORWARD) | |
146 return gfx::Vector2dF(std::max(-bounds_width, delta_x), 0); | |
147 else | |
148 return gfx::Vector2dF(std::min(bounds_width, delta_x), 0); | |
149 } | |
150 | |
151 gfx::Rect OverscrollWindowAnimation::GetVisibleBounds() const { | |
152 return web_contents_window_->bounds(); | |
153 } | |
154 | |
155 bool OverscrollWindowAnimation::OnOverscrollUpdate(float delta_x, | |
156 float delta_y) { | |
157 if (direction_ == OverscrollNavigationOverlay::NONE) | |
158 return false; | |
159 LOG(ERROR) << "OWA: OnOverscrollUpdate"; | |
160 gfx::Vector2dF translate = GetTranslationForOverscroll(delta_x); | |
161 if (translate.IsZero()) | |
162 return false; | |
163 | |
164 gfx::Transform transform; | |
165 transform.Translate(translate.x(), translate.y()); | |
166 aura::Window* animate_window = GetWindowToAnimateForOverscroll(); | |
167 if (animate_window) { | |
168 animate_window->SetTransform(transform); | |
169 return true; | |
170 } | |
171 return false; | |
172 } | |
173 | |
174 void OverscrollWindowAnimation::OnOverscrollModeChange( | |
175 OverscrollMode old_mode, | |
176 OverscrollMode new_mode) { | |
177 LOG(ERROR) << "OWA: OnOverscrollModeChange"; | |
178 animation_cancelled_ = false; | |
179 AbortAllAnimations(); | |
180 | |
181 direction_ = | |
182 ono_->GetNavigationDirection(web_contents_->GetController(), new_mode); | |
183 // TODO(nsatragno): in this case, show a feedback animation. | |
184 if (direction_ == OverscrollNavigationOverlay::NONE) { | |
185 if (overscroll_window_) | |
186 CancelAnimation(); | |
187 return; | |
188 } | |
189 if (overscroll_window_) { | |
190 LOG(ERROR) << "OWA: SHOULD CREATE LAYER"; | |
191 AddNewLayer(); | |
192 return; | |
193 } | |
194 | |
195 StartAnimating(); | |
196 } | |
197 | |
198 void OverscrollWindowAnimation::StartAnimating() { | |
199 LOG(ERROR) << "OWA: StartAnimating"; | |
200 gesture_completed_ = false; | |
201 OverscrollWindowDelegate* overscroll_delegate = new OverscrollWindowDelegate( | |
mfomitchev
2015/02/13 22:08:48
I am not sure this setup code belongs in OWA eithe
| |
202 this, ono_->GetImageForDirection(direction_)); | |
203 overscroll_window_.reset(new aura::Window(overscroll_delegate)); | |
204 overscroll_window_->SetType(ui::wm::WINDOW_TYPE_CONTROL); | |
205 overscroll_window_->SetTransparent(true); | |
206 overscroll_window_->Init(aura::WINDOW_LAYER_TEXTURED); | |
207 overscroll_window_->layer()->SetMasksToBounds(false); | |
208 overscroll_window_->SetName("OverscrollOverlay"); | |
209 | |
210 aura::Window* animate_window = GetWindowToAnimateForOverscroll(); | |
211 web_contents_window_->AddChild(overscroll_window_.get()); | |
212 | |
213 if (animate_window == overscroll_window_) { | |
214 LOG(ERROR) << "animate_window == overscroll_window_"; | |
215 web_contents_window_->StackChildAbove( | |
216 overscroll_window_.get(), web_contents_->GetContentNativeView()); | |
217 } else { | |
218 LOG(ERROR) << "animate_window != overscroll_window_"; | |
219 web_contents_window_->StackChildBelow( | |
220 overscroll_window_.get(), web_contents_->GetContentNativeView()); | |
221 } | |
222 | |
223 overscroll_window_->SetBounds(GetStarterBounds()); | |
224 overscroll_window_->Show(); | |
225 | |
226 if (!animate_window) | |
227 LOG(ERROR) << "ERROR: ANIMATE_WINDOW_ IS NULL"; | |
228 | |
229 overscroll_shadow_.reset(new ShadowLayerDelegate(animate_window->layer())); | |
230 } | |
231 | |
232 void OverscrollWindowAnimation::AddNewLayer() { | |
233 slide_layer_ = ono_->CreateLayerForDirection(direction_); | |
234 ui::Layer* parent = overscroll_window_->layer()->parent(); | |
mfomitchev
2015/02/13 22:08:48
Same here
| |
235 parent->Add(slide_layer_.get()); | |
236 // TODO stack apropriately. | |
237 if (direction_ == OverscrollNavigationOverlay::FORWARD) | |
238 parent->StackAbove(slide_layer_.get(), overscroll_window_->layer()); | |
239 else | |
240 parent->StackBelow(slide_layer_.get(), overscroll_window_->layer()); | |
241 slide_layer_->SetBounds(GetStarterBounds()); | |
242 } | |
243 | |
244 void OverscrollWindowAnimation::FadeOutOverscrollWindow() { | |
245 fade_out_ = false; | |
246 LOG(ERROR) << "FadeOutOverscrollWindow"; | |
247 if (!overscroll_window_) | |
248 return; | |
249 aura::Window* contents = web_contents_->GetContentNativeView(); | |
250 contents->layer()->SetLayerBrightness(1.f); | |
251 { | |
252 ui::ScopedLayerAnimationSettings settings(contents->layer()->GetAnimator()); | |
253 settings.SetPreemptionStrategy( | |
254 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | |
255 settings.SetTweenType(gfx::Tween::EASE_OUT); | |
256 contents->layer()->SetLayerBrightness(0.f); | |
257 } | |
258 scoped_ptr<ui::Layer> dismiss_layer = overscroll_window_->AcquireLayer(); | |
259 overscroll_window_.reset(); | |
260 (new OverlayDismissAnimator(dismiss_layer.Pass()))->Animate(); | |
261 // TODO delete shadow when the dismiss animation finishes? | |
262 overscroll_shadow_.reset(); | |
263 } | |
264 | |
265 gfx::Rect OverscrollWindowAnimation::GetStarterBounds() const { | |
266 gfx::Rect bounds = gfx::Rect(web_contents_window_->bounds().size()); | |
267 if (direction_ == OverscrollNavigationOverlay::FORWARD) { | |
268 // The overlay will be sliding in from the right edge towards the left in | |
269 // non-RTL, or sliding in from the left edge towards the right in RTL. | |
270 // So position the overlay window accordingly. | |
271 bounds.Offset(base::i18n::IsRTL() ? -bounds.width() : bounds.width(), 0); | |
272 } | |
273 return bounds; | |
274 } | |
275 | |
276 void OverscrollWindowAnimation::OnOverscrollComplete( | |
277 OverscrollMode overscroll_mode) { | |
278 LOG(ERROR) << "OWA: OnOverscrollComplete"; | |
279 aura::Window* target = GetWindowToAnimateForOverscroll(); | |
280 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator()); | |
281 settings.SetPreemptionStrategy( | |
282 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | |
283 settings.SetTweenType(gfx::Tween::EASE_OUT); | |
284 settings.AddObserver(this); | |
285 gfx::Transform transform; | |
286 int content_width = | |
287 web_contents_->GetRenderWidgetHostView()->GetViewBounds().width(); | |
288 float translate_x = static_cast<float>( | |
289 direction_ == OverscrollNavigationOverlay::FORWARD ? -content_width | |
290 : content_width); | |
291 transform.Translate(translate_x, 0); | |
292 target->SetTransform(transform); | |
293 direction_ = OverscrollNavigationOverlay::NONE; | |
294 } | |
295 | |
296 aura::Window* OverscrollWindowAnimation::GetWindowToAnimateForOverscroll() | |
297 const { | |
298 return direction_ == OverscrollNavigationOverlay::FORWARD | |
299 ? overscroll_window_.get() | |
300 : web_contents_->GetContentNativeView(); | |
301 } | |
302 | |
303 } // namespace content | |
OLD | NEW |