Commit 923f6277 authored by Peter Boström's avatar Peter Boström Committed by Commit Bot

Rewrite tab animation to use TimeTicks

Avoids having additional high-frequency post tasking for no-op tasks in
the background.

To keep track of when to stop animating without an AnimationEnded
callback, we keep track of the last-drawn animation state. This also has
the side effect of allowing us to avoid repainting the loading-progress
bar if would paint the same pixels we drew last time. This should avoid
a lot of repaints for slow-loading sites.

This also ends up fixing backwards-jumping indicators. Probably because
the logic for clamping the loading-progress timer got easier.

Bug: chromium:907044, chromium:905020, chromium:905452
Change-Id: Ic83748bad83115ef2283c881a89ed65e3d3938ab
Reviewed-on: https://chromium-review.googlesource.com/c/1346831Reviewed-by: default avatarSidney San Martín <sdy@chromium.org>
Commit-Queue: Peter Boström <pbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#611234}
parent bc5163ce
This diff is collapsed.
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/ui/tabs/tab_network_state.h" #include "chrome/browser/ui/tabs/tab_network_state.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/animation/linear_animation.h"
#include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia.h"
#include "ui/gfx/paint_throbber.h" #include "ui/gfx/paint_throbber.h"
#include "ui/views/view.h" #include "ui/views/view.h"
...@@ -25,7 +23,7 @@ struct TabRendererData; ...@@ -25,7 +23,7 @@ struct TabRendererData;
// the width is TabIcon::GetIdealWidth(), and the height goes down to the // the width is TabIcon::GetIdealWidth(), and the height goes down to the
// bottom of the enclosing view (this is so the crashed tab can animate out of // bottom of the enclosing view (this is so the crashed tab can animate out of
// the bottom). // the bottom).
class TabIcon : public views::View, public gfx::AnimationDelegate { class TabIcon : public views::View {
public: public:
// Attention indicator types (use as a bitmask). There is only one visual // Attention indicator types (use as a bitmask). There is only one visual
// representation, but the state of each of these is tracked separately and // representation, but the state of each of these is tracked separately and
...@@ -67,13 +65,20 @@ class TabIcon : public views::View, public gfx::AnimationDelegate { ...@@ -67,13 +65,20 @@ class TabIcon : public views::View, public gfx::AnimationDelegate {
friend CrashAnimation; friend CrashAnimation;
friend class TabTest; friend class TabTest;
// State used to draw the tab-loading animation. Also used to store the
// last-painted state to know to redraw the final frame as the animation
// finishes.
struct LoadingAnimationState {
base::TimeDelta elapsed_time;
double loading_progress;
SkAlpha loading_progress_alpha;
SkAlpha favicon_alpha;
};
// views::View: // views::View:
void OnPaint(gfx::Canvas* canvas) override; void OnPaint(gfx::Canvas* canvas) override;
void OnThemeChanged() override; void OnThemeChanged() override;
// gfx::AnimationDelegate:
void AnimationEnded(const gfx::Animation* animation) override;
// Paints the attention indicator and |favicon_| at the given location. // Paints the attention indicator and |favicon_| at the given location.
void PaintAttentionIndicatorAndIcon(gfx::Canvas* canvas, void PaintAttentionIndicatorAndIcon(gfx::Canvas* canvas,
const gfx::ImageSkia& icon, const gfx::ImageSkia& icon,
...@@ -89,6 +94,15 @@ class TabIcon : public views::View, public gfx::AnimationDelegate { ...@@ -89,6 +94,15 @@ class TabIcon : public views::View, public gfx::AnimationDelegate {
// current tab state. // current tab state.
void PaintLoadingAnimation(gfx::Canvas* canvas, const gfx::Rect& bounds); void PaintLoadingAnimation(gfx::Canvas* canvas, const gfx::Rect& bounds);
void UpdateLoadingAnimationState();
LoadingAnimationState GetLoadingAnimationState() const;
void RewindLoadingProgressTimerIfNecessary(double progress);
// Returns false if painting the loading animation would paint the same thing
// that's already painted.
bool LoadingAnimationNeedsRepaint() const;
// Gets either the crashed icon or favicon to be rendered for the tab. // Gets either the crashed icon or favicon to be rendered for the tab.
const gfx::ImageSkia& GetIconToPaint(); const gfx::ImageSkia& GetIconToPaint();
...@@ -118,6 +132,8 @@ class TabIcon : public views::View, public gfx::AnimationDelegate { ...@@ -118,6 +132,8 @@ class TabIcon : public views::View, public gfx::AnimationDelegate {
gfx::ImageSkia ThemeImage(const gfx::ImageSkia& source); gfx::ImageSkia ThemeImage(const gfx::ImageSkia& source);
const base::TickClock* clock_;
gfx::ImageSkia favicon_; gfx::ImageSkia favicon_;
TabNetworkState network_state_ = TabNetworkState::kNone; TabNetworkState network_state_ = TabNetworkState::kNone;
bool is_crashed_ = false; bool is_crashed_ = false;
...@@ -128,7 +144,8 @@ class TabIcon : public views::View, public gfx::AnimationDelegate { ...@@ -128,7 +144,8 @@ class TabIcon : public views::View, public gfx::AnimationDelegate {
bool inhibit_loading_animation_ = false; bool inhibit_loading_animation_ = false;
// The point in time when the tab icon was first painted in the loading state. // The point in time when the tab icon was first painted in the loading state.
base::TimeTicks loading_start_time_; // TODO(pbos): Remove after |kNewTabLoadingAnimation| launches.
base::TimeTicks old_animation_loading_start_time_;
// Paint state for the loading animation after the most recent waiting paint. // Paint state for the loading animation after the most recent waiting paint.
// TODO(pbos): After |kNewTabLoadingAnimation| launches, remove the need for // TODO(pbos): After |kNewTabLoadingAnimation| launches, remove the need for
...@@ -152,12 +169,15 @@ class TabIcon : public views::View, public gfx::AnimationDelegate { ...@@ -152,12 +169,15 @@ class TabIcon : public views::View, public gfx::AnimationDelegate {
double hiding_fraction_ = 0.0; double hiding_fraction_ = 0.0;
// Loading progress used for drawing the progress indicator. // Loading progress used for drawing the progress indicator.
double loading_progress_ = 1.0; double target_loading_progress_ = 1.0;
gfx::LinearAnimation loading_progress_timer_;
LoadingAnimationState animation_state_;
base::Optional<base::TimeTicks> loading_progress_timer_;
// Fade-in animation for the favicon. Starts when a favicon loads or the tab // Fade-in animation for the favicon. Starts when a favicon loads or the tab
// is no longer loading. The latter case will fade into a placeholder icon. // is no longer loading. The latter case will fade into a placeholder icon.
gfx::LinearAnimation favicon_fade_in_animation_; base::Optional<base::TimeTicks> favicon_fade_in_animation_;
// Crash animation (in place of favicon). Lazily created since most of the // Crash animation (in place of favicon). Lazily created since most of the
// time it will be unneeded. // time it will be unneeded.
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/test/simple_test_tick_clock.h"
#include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/layout_constants.h"
#include "chrome/browser/ui/tabs/tab_utils.h" #include "chrome/browser/ui/tabs/tab_utils.h"
#include "chrome/browser/ui/views/tabs/alert_indicator.h" #include "chrome/browser/ui/views/tabs/alert_indicator.h"
...@@ -305,18 +306,17 @@ class TabTest : public ChromeViewsTestBase { ...@@ -305,18 +306,17 @@ class TabTest : public ChromeViewsTestBase {
fade_animation->Stop(); fade_animation->Stop();
} }
static void FinishRunningLoadingAnimations(TabIcon* icon) { void SetupFakeClock(TabIcon* icon) { icon->clock_ = &fake_clock_; }
for (auto* animation :
{&icon->loading_progress_timer_, &icon->favicon_fade_in_animation_}) { void FinishRunningLoadingAnimations(TabIcon* icon) {
if (!animation->is_animating()) // Forward the clock enough for any running animations to finish.
continue; DCHECK(icon->clock_ == &fake_clock_);
animation->Stop(); fake_clock_.Advance(base::TimeDelta::FromMilliseconds(2000));
animation->SetCurrentValue(1.0); icon->UpdateLoadingAnimationState();
}
} }
static float GetLoadingProgress(TabIcon* icon) { static float GetLoadingProgress(TabIcon* icon) {
return icon->loading_progress_; return icon->target_loading_progress_;
} }
protected: protected:
...@@ -337,6 +337,7 @@ class TabTest : public ChromeViewsTestBase { ...@@ -337,6 +337,7 @@ class TabTest : public ChromeViewsTestBase {
} }
std::string original_locale_; std::string original_locale_;
base::SimpleTestTickClock fake_clock_;
}; };
class AlertIndicatorTest : public ChromeViewsTestBase { class AlertIndicatorTest : public ChromeViewsTestBase {
...@@ -585,6 +586,7 @@ TEST_F(TabTest, LayeredThrobber) { ...@@ -585,6 +586,7 @@ TEST_F(TabTest, LayeredThrobber) {
tab.SizeToPreferredSize(); tab.SizeToPreferredSize();
TabIcon* icon = GetTabIcon(tab); TabIcon* icon = GetTabIcon(tab);
SetupFakeClock(icon);
TabRendererData data; TabRendererData data;
data.url = GURL("http://example.com"); data.url = GURL("http://example.com");
EXPECT_FALSE(icon->ShowingLoadingAnimation()); EXPECT_FALSE(icon->ShowingLoadingAnimation());
......
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