Chromium Code Reviews| 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 |