Commit 19a2837f authored by Robert Liao's avatar Robert Liao Committed by Commit Bot

Lazily Obtain the Compositor

If we set |compositor_| during AddedToWidget() and not call Play(), the
compositor could shutdown and we would never clear |compositor_| since
we're not registered as an AnimationObserver and will miss
OnCompositingShuttingDown().

BUG=899112

Change-Id: If1dbe4ae9db80d55d3d5db6d939da6008bf97160
Reviewed-on: https://chromium-review.googlesource.com/c/1300694
Commit-Queue: Robert Liao <robliao@chromium.org>
Reviewed-by: default avatarMichael Wasserman <msw@chromium.org>
Reviewed-by: default avatarMalay Keshav <malaykeshav@chromium.org>
Cr-Commit-Position: refs/heads/master@{#603253}
parent b26f9161
...@@ -52,13 +52,7 @@ void AnimatedImageView::Play() { ...@@ -52,13 +52,7 @@ void AnimatedImageView::Play() {
state_ = State::kPlaying; state_ = State::kPlaying;
// We cannot play the animation unless we have a valid compositor. SetCompositorFromWidget();
if (!compositor_)
return;
// Ensure the class is added as an observer to receive clock ticks.
if (!compositor_->HasAnimationObserver(this))
compositor_->AddAnimationObserver(this);
animated_image_->Start(); animated_image_->Start();
} }
...@@ -68,8 +62,7 @@ void AnimatedImageView::Stop() { ...@@ -68,8 +62,7 @@ void AnimatedImageView::Stop() {
return; return;
DCHECK(animated_image_); DCHECK(animated_image_);
if (compositor_) ClearCurrentCompositor();
compositor_->RemoveAnimationObserver(this);
animated_image_->Stop(); animated_image_->Stop();
state_ = State::kStopped; state_ = State::kStopped;
...@@ -102,27 +95,21 @@ const char* AnimatedImageView::GetClassName() const { ...@@ -102,27 +95,21 @@ const char* AnimatedImageView::GetClassName() const {
} }
void AnimatedImageView::NativeViewHierarchyChanged() { void AnimatedImageView::NativeViewHierarchyChanged() {
// When switching a window from one display to another, the compositor
// associated with the widget changes.
AddedToWidget();
}
void AnimatedImageView::AddedToWidget() {
ui::Compositor* compositor = GetWidget()->GetCompositor(); ui::Compositor* compositor = GetWidget()->GetCompositor();
DCHECK(compositor); DCHECK(compositor);
if (compositor_ != compositor) { if (compositor_ != compositor) {
if (compositor_ && compositor_->HasAnimationObserver(this)) ClearCurrentCompositor();
compositor_->RemoveAnimationObserver(this);
compositor_ = compositor; // Restore the Play() state with the new compositor.
if (state_ == State::kPlaying)
SetCompositorFromWidget();
} }
} }
void AnimatedImageView::RemovedFromWidget() { void AnimatedImageView::RemovedFromWidget() {
if (compositor_) { if (compositor_) {
Stop(); Stop();
if (compositor_->HasAnimationObserver(this)) ClearCurrentCompositor();
compositor_->RemoveAnimationObserver(this);
compositor_ = nullptr;
} }
} }
...@@ -134,6 +121,22 @@ void AnimatedImageView::OnAnimationStep(base::TimeTicks timestamp) { ...@@ -134,6 +121,22 @@ void AnimatedImageView::OnAnimationStep(base::TimeTicks timestamp) {
void AnimatedImageView::OnCompositingShuttingDown(ui::Compositor* compositor) { void AnimatedImageView::OnCompositingShuttingDown(ui::Compositor* compositor) {
if (compositor_ == compositor) { if (compositor_ == compositor) {
Stop(); Stop();
ClearCurrentCompositor();
}
}
void AnimatedImageView::SetCompositorFromWidget() {
DCHECK(!compositor_);
auto* widget = GetWidget();
DCHECK(widget);
compositor_ = widget->GetCompositor();
DCHECK(!compositor_->HasAnimationObserver(this));
compositor_->AddAnimationObserver(this);
}
void AnimatedImageView::ClearCurrentCompositor() {
if (compositor_) {
DCHECK(compositor_->HasAnimationObserver(this));
compositor_->RemoveAnimationObserver(this); compositor_->RemoveAnimationObserver(this);
compositor_ = nullptr; compositor_ = nullptr;
} }
......
...@@ -48,7 +48,8 @@ class VIEWS_EXPORT AnimatedImageView : public ImageViewBase, ...@@ -48,7 +48,8 @@ class VIEWS_EXPORT AnimatedImageView : public ImageViewBase,
void SetAnimatedImage( void SetAnimatedImage(
std::unique_ptr<gfx::SkiaVectorAnimation> animated_image); std::unique_ptr<gfx::SkiaVectorAnimation> animated_image);
// Plays the animation in loop. // Plays the animation in loop and must only be called when this view has
// access to a widget.
void Play(); void Play();
// Stops any animation and resets it to the start frame. // Stops any animation and resets it to the start frame.
...@@ -61,13 +62,15 @@ class VIEWS_EXPORT AnimatedImageView : public ImageViewBase, ...@@ -61,13 +62,15 @@ class VIEWS_EXPORT AnimatedImageView : public ImageViewBase,
void OnPaint(gfx::Canvas* canvas) override; void OnPaint(gfx::Canvas* canvas) override;
const char* GetClassName() const override; const char* GetClassName() const override;
void NativeViewHierarchyChanged() override; void NativeViewHierarchyChanged() override;
void AddedToWidget() override;
void RemovedFromWidget() override; void RemovedFromWidget() override;
// Overridden from ui::CompositorAnimationObserver: // Overridden from ui::CompositorAnimationObserver:
void OnAnimationStep(base::TimeTicks timestamp) override; void OnAnimationStep(base::TimeTicks timestamp) override;
void OnCompositingShuttingDown(ui::Compositor* compositor) override; void OnCompositingShuttingDown(ui::Compositor* compositor) override;
void SetCompositorFromWidget();
void ClearCurrentCompositor();
// Overridden from ImageViewBase: // Overridden from ImageViewBase:
gfx::Size GetImageSize() const override; gfx::Size GetImageSize() const override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment