Commit ffba1d48 authored by Mitsuru Oshima's avatar Mitsuru Oshima Committed by Commit Bot

Obtain compositor from widget in CompositorAnimationRunner

* It observes widget's destruction instead of observing
 compositor's in CompositorChecker. This allow CAR to continue running
 even if the widget's compositor changes.
* Re-enable on chromeos

Bug: 1019536
Test: Covered by unittests.
Change-Id: Ia3a3201408b93d70b98339e79b7e9ffd6db22e56
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1890493Reviewed-by: default avatarAllen Bauer <kylixrd@chromium.org>
Reviewed-by: default avatarAlan Cutter <alancutter@chromium.org>
Commit-Queue: Mitsuru Oshima <oshima@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712641}
parent 5a11f028
...@@ -55,12 +55,6 @@ void AnimationDelegateViews::AnimationContainerShuttingDown( ...@@ -55,12 +55,6 @@ void AnimationDelegateViews::AnimationContainerShuttingDown(
} }
void AnimationDelegateViews::UpdateAnimationRunner() { void AnimationDelegateViews::UpdateAnimationRunner() {
#if defined(OS_CHROMEOS)
// TODO(crbug.com/969788): Re-enable this function with better ui::Compositor
// switching support.
return;
#endif // defined(OS_CHROMEOS)
if (!container_) if (!container_)
return; return;
...@@ -74,8 +68,8 @@ void AnimationDelegateViews::UpdateAnimationRunner() { ...@@ -74,8 +68,8 @@ void AnimationDelegateViews::UpdateAnimationRunner() {
if (container_->has_custom_animation_runner()) if (container_->has_custom_animation_runner())
return; return;
container_->SetAnimationRunner(std::make_unique<CompositorAnimationRunner>( container_->SetAnimationRunner(
view_->GetWidget()->GetCompositor())); std::make_unique<CompositorAnimationRunner>(view_->GetWidget()));
} }
} // namespace views } // namespace views
...@@ -4,37 +4,22 @@ ...@@ -4,37 +4,22 @@
#include "ui/views/animation/compositor_animation_runner.h" #include "ui/views/animation/compositor_animation_runner.h"
namespace views { #include "ui/views/widget/widget.h"
////////////////////////////////////////////////////////////////////////////////
// CompositorAnimationRunner::CompositorChecker
//
CompositorAnimationRunner::CompositorChecker::CompositorChecker(
CompositorAnimationRunner* runner)
: runner_(runner) {
scoped_observer_.Add(runner_->compositor_);
}
CompositorAnimationRunner::CompositorChecker::~CompositorChecker() = default; namespace views {
void CompositorAnimationRunner::CompositorChecker::OnCompositingShuttingDown(
ui::Compositor* compositor) {
runner_->OnCompositingShuttingDown(compositor);
DCHECK(!compositor->HasAnimationObserver(runner_));
scoped_observer_.Remove(compositor);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// CompositorAnimationRunner // CompositorAnimationRunner
// //
CompositorAnimationRunner::CompositorAnimationRunner(ui::Compositor* compositor) CompositorAnimationRunner::CompositorAnimationRunner(Widget* widget)
: compositor_(compositor) { : widget_(widget) {
DCHECK(compositor_); widget_->AddObserver(this);
} }
CompositorAnimationRunner::~CompositorAnimationRunner() { CompositorAnimationRunner::~CompositorAnimationRunner() {
// Make sure we're not observing |compositor_|. // Make sure we're not observing |compositor_|.
Stop(); if (widget_)
OnWidgetDestroying(widget_);
DCHECK(!compositor_ || !compositor_->HasAnimationObserver(this)); DCHECK(!compositor_ || !compositor_->HasAnimationObserver(this));
} }
...@@ -43,6 +28,7 @@ void CompositorAnimationRunner::Stop() { ...@@ -43,6 +28,7 @@ void CompositorAnimationRunner::Stop() {
compositor_->RemoveAnimationObserver(this); compositor_->RemoveAnimationObserver(this);
min_interval_ = base::TimeDelta::Max(); min_interval_ = base::TimeDelta::Max();
compositor_ = nullptr;
} }
void CompositorAnimationRunner::OnAnimationStep(base::TimeTicks timestamp) { void CompositorAnimationRunner::OnAnimationStep(base::TimeTicks timestamp) {
...@@ -56,13 +42,30 @@ void CompositorAnimationRunner::OnAnimationStep(base::TimeTicks timestamp) { ...@@ -56,13 +42,30 @@ void CompositorAnimationRunner::OnAnimationStep(base::TimeTicks timestamp) {
void CompositorAnimationRunner::OnCompositingShuttingDown( void CompositorAnimationRunner::OnCompositingShuttingDown(
ui::Compositor* compositor) { ui::Compositor* compositor) {
Stop(); Stop();
compositor_ = nullptr; }
void CompositorAnimationRunner::OnWidgetDestroying(Widget* widget) {
Stop();
widget_->RemoveObserver(this);
widget_ = nullptr;
} }
void CompositorAnimationRunner::OnStart(base::TimeDelta min_interval, void CompositorAnimationRunner::OnStart(base::TimeDelta min_interval,
base::TimeDelta elapsed) { base::TimeDelta elapsed) {
if (!compositor_) if (!widget_)
return;
ui::Compositor* current_compositor = widget_->GetCompositor();
if (!current_compositor) {
Stop();
return; return;
}
if (current_compositor != compositor_) {
if (compositor_ && compositor_->HasAnimationObserver(this))
compositor_->RemoveAnimationObserver(this);
compositor_ = current_compositor;
}
last_tick_ = base::TimeTicks::Now() - elapsed; last_tick_ = base::TimeTicks::Now() - elapsed;
min_interval_ = min_interval; min_interval_ = min_interval;
......
...@@ -11,14 +11,19 @@ ...@@ -11,14 +11,19 @@
#include "ui/compositor/compositor_animation_observer.h" #include "ui/compositor/compositor_animation_observer.h"
#include "ui/compositor/compositor_observer.h" #include "ui/compositor/compositor_observer.h"
#include "ui/gfx/animation/animation_container.h" #include "ui/gfx/animation/animation_container.h"
#include "ui/views/widget/widget_observer.h"
namespace views { namespace views {
class Widget;
// An animation runner based on ui::Compositor. // An animation runner based on ui::Compositor.
class CompositorAnimationRunner : public gfx::AnimationRunner, class CompositorAnimationRunner : public gfx::AnimationRunner,
public ui::CompositorAnimationObserver { public ui::CompositorAnimationObserver,
public WidgetObserver {
public: public:
explicit CompositorAnimationRunner(ui::Compositor* compositor); explicit CompositorAnimationRunner(Widget* widget);
CompositorAnimationRunner(CompositorAnimationRunner&) = delete;
CompositorAnimationRunner& operator=(CompositorAnimationRunner&) = delete;
~CompositorAnimationRunner() override; ~CompositorAnimationRunner() override;
// gfx::AnimationRunner: // gfx::AnimationRunner:
...@@ -28,37 +33,25 @@ class CompositorAnimationRunner : public gfx::AnimationRunner, ...@@ -28,37 +33,25 @@ class CompositorAnimationRunner : public gfx::AnimationRunner,
void OnAnimationStep(base::TimeTicks timestamp) override; void OnAnimationStep(base::TimeTicks timestamp) override;
void OnCompositingShuttingDown(ui::Compositor* compositor) override; void OnCompositingShuttingDown(ui::Compositor* compositor) override;
// WidgetObserver:
void OnWidgetDestroying(Widget* widget) override;
protected: protected:
// gfx::AnimationRunner: // gfx::AnimationRunner:
void OnStart(base::TimeDelta min_interval, base::TimeDelta elapsed) override; void OnStart(base::TimeDelta min_interval, base::TimeDelta elapsed) override;
private: private:
// This observes Compositor's destruction and helps CompositorAnimationRunner // When |widget_| is nullptr, it means the widget has been destroyed and
// to stop animation. we need this because CompositorAnimationRunner observes // |compositor_| must also be nullptr.
// the Compositor only when it's animating. Widget* widget_;
class CompositorChecker : public ui::CompositorObserver {
public:
explicit CompositorChecker(CompositorAnimationRunner* runner);
CompositorChecker(const CompositorChecker& other) = delete;
CompositorChecker& operator=(const CompositorChecker& other) = delete;
~CompositorChecker() override;
// ui::CompositorObserver:
void OnCompositingShuttingDown(ui::Compositor* compositor) override;
private: // When |compositor_| is nullptr, it means either the animation is not
CompositorAnimationRunner* runner_; // running, or the compositor or |widget_| associated with the compositor_ has
ScopedObserver<ui::Compositor, ui::CompositorObserver> scoped_observer_{ // been destroyed during animation.
this}; ui::Compositor* compositor_ = nullptr;
};
// When |compositor_| is nullptr, it means compositor has been shut down.
ui::Compositor* compositor_;
base::TimeDelta min_interval_ = base::TimeDelta::Max(); base::TimeDelta min_interval_ = base::TimeDelta::Max();
base::TimeTicks last_tick_; base::TimeTicks last_tick_;
CompositorChecker checker_{this};
}; };
} // namespace views } // namespace views
......
...@@ -12,22 +12,16 @@ ...@@ -12,22 +12,16 @@
namespace views { namespace views {
namespace test { namespace test {
namespace {
constexpr base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(100);
}
using CompositorAnimationRunnerTest = WidgetTest; using CompositorAnimationRunnerTest = WidgetTest;
// TODO(crbug.com/969788): Re-enable CompositorAnimationRunner with better TEST_F(CompositorAnimationRunnerTest, BasicCoverageTest) {
// ui::Compositor switching support.
#if defined(OS_CHROMEOS)
#define MAYBE_BasicCoverageTest DISABLED_BasicCoverageTest
#else
#define MAYBE_BasicCoverageTest BasicCoverageTest
#endif
TEST_F(CompositorAnimationRunnerTest, MAYBE_BasicCoverageTest) {
WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget()); WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget());
widget->Show(); widget->Show();
constexpr base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(100);
AnimationDelegateViews delegate(widget->GetContentsView()); AnimationDelegateViews delegate(widget->GetContentsView());
gfx::LinearAnimation animation( gfx::LinearAnimation animation(
kDuration, gfx::LinearAnimation::kDefaultFrameRate, &delegate); kDuration, gfx::LinearAnimation::kDefaultFrameRate, &delegate);
...@@ -50,5 +44,67 @@ TEST_F(CompositorAnimationRunnerTest, MAYBE_BasicCoverageTest) { ...@@ -50,5 +44,67 @@ TEST_F(CompositorAnimationRunnerTest, MAYBE_BasicCoverageTest) {
run_loop.Run(); run_loop.Run();
} }
// No DesktopAura on ChromeOS.
// Each widget on MACOSX has its own ui::Compositor.
#if !defined(OS_CHROMEOS) && !(OS_MACOSX)
using CompositorAnimationRunnerDesktopTest = DesktopWidgetTest;
TEST_F(CompositorAnimationRunnerDesktopTest, SwitchCompositor) {
WidgetAutoclosePtr widget1(CreateTopLevelNativeWidget());
widget1->Show();
WidgetAutoclosePtr widget2(CreateTopLevelNativeWidget());
widget2->Show();
ASSERT_NE(widget1->GetCompositor(), widget2->GetCompositor());
Widget* child = CreateChildNativeWidgetWithParent(widget1.get());
child->Show();
AnimationDelegateViews delegate(child->GetContentsView());
gfx::LinearAnimation animation(
kDuration, gfx::LinearAnimation::kDefaultFrameRate, &delegate);
base::RepeatingTimer interval_timer;
animation.Start();
EXPECT_TRUE(animation.is_animating());
EXPECT_TRUE(delegate.container()->has_custom_animation_runner());
{
base::RunLoop run_loop;
interval_timer.Start(FROM_HERE, kDuration,
base::BindLambdaForTesting([&]() {
if (animation.is_animating())
return;
interval_timer.Stop();
run_loop.Quit();
}));
run_loop.Run();
}
EXPECT_FALSE(animation.is_animating());
Widget::ReparentNativeView(child->GetNativeView(), widget2->GetNativeView());
widget1.reset();
animation.Start();
EXPECT_TRUE(animation.is_animating());
EXPECT_TRUE(delegate.container()->has_custom_animation_runner());
{
base::RunLoop run_loop;
interval_timer.Start(FROM_HERE, kDuration,
base::BindLambdaForTesting([&]() {
if (animation.is_animating())
return;
interval_timer.Stop();
run_loop.Quit();
}));
run_loop.Run();
}
}
#endif
} // namespace test } // namespace test
} // namespace views } // namespace views
...@@ -76,8 +76,7 @@ InstallableInkDrop::InstallableInkDrop(View* view) ...@@ -76,8 +76,7 @@ InstallableInkDrop::InstallableInkDrop(View* view)
// Using CompositorAnimationRunner keeps our animation updates in sync with // Using CompositorAnimationRunner keeps our animation updates in sync with
// compositor frames and avoids jank. // compositor frames and avoids jank.
animation_container_->SetAnimationRunner( animation_container_->SetAnimationRunner(
std::make_unique<CompositorAnimationRunner>( std::make_unique<CompositorAnimationRunner>(view_->GetWidget()));
view_->GetWidget()->GetCompositor()));
} }
} }
......
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