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 @@
#include "base/macros.h"
#include "base/time/time.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/paint_throbber.h"
#include "ui/views/view.h"
......@@ -25,7 +23,7 @@ struct TabRendererData;
// 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
// the bottom).
class TabIcon : public views::View, public gfx::AnimationDelegate {
class TabIcon : public views::View {
public:
// Attention indicator types (use as a bitmask). There is only one visual
// representation, but the state of each of these is tracked separately and
......@@ -67,13 +65,20 @@ class TabIcon : public views::View, public gfx::AnimationDelegate {
friend CrashAnimation;
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:
void OnPaint(gfx::Canvas* canvas) override;
void OnThemeChanged() override;
// gfx::AnimationDelegate:
void AnimationEnded(const gfx::Animation* animation) override;
// Paints the attention indicator and |favicon_| at the given location.
void PaintAttentionIndicatorAndIcon(gfx::Canvas* canvas,
const gfx::ImageSkia& icon,
......@@ -89,6 +94,15 @@ class TabIcon : public views::View, public gfx::AnimationDelegate {
// current tab state.
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.
const gfx::ImageSkia& GetIconToPaint();
......@@ -118,6 +132,8 @@ class TabIcon : public views::View, public gfx::AnimationDelegate {
gfx::ImageSkia ThemeImage(const gfx::ImageSkia& source);
const base::TickClock* clock_;
gfx::ImageSkia favicon_;
TabNetworkState network_state_ = TabNetworkState::kNone;
bool is_crashed_ = false;
......@@ -128,7 +144,8 @@ class TabIcon : public views::View, public gfx::AnimationDelegate {
bool inhibit_loading_animation_ = false;
// 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.
// TODO(pbos): After |kNewTabLoadingAnimation| launches, remove the need for
......@@ -152,12 +169,15 @@ class TabIcon : public views::View, public gfx::AnimationDelegate {
double hiding_fraction_ = 0.0;
// Loading progress used for drawing the progress indicator.
double loading_progress_ = 1.0;
gfx::LinearAnimation loading_progress_timer_;
double target_loading_progress_ = 1.0;
LoadingAnimationState animation_state_;
base::Optional<base::TimeTicks> loading_progress_timer_;
// 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.
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
// time it will be unneeded.
......
......@@ -10,6 +10,7 @@
#include "base/macros.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/tabs/tab_utils.h"
#include "chrome/browser/ui/views/tabs/alert_indicator.h"
......@@ -305,18 +306,17 @@ class TabTest : public ChromeViewsTestBase {
fade_animation->Stop();
}
static void FinishRunningLoadingAnimations(TabIcon* icon) {
for (auto* animation :
{&icon->loading_progress_timer_, &icon->favicon_fade_in_animation_}) {
if (!animation->is_animating())
continue;
animation->Stop();
animation->SetCurrentValue(1.0);
}
void SetupFakeClock(TabIcon* icon) { icon->clock_ = &fake_clock_; }
void FinishRunningLoadingAnimations(TabIcon* icon) {
// Forward the clock enough for any running animations to finish.
DCHECK(icon->clock_ == &fake_clock_);
fake_clock_.Advance(base::TimeDelta::FromMilliseconds(2000));
icon->UpdateLoadingAnimationState();
}
static float GetLoadingProgress(TabIcon* icon) {
return icon->loading_progress_;
return icon->target_loading_progress_;
}
protected:
......@@ -337,6 +337,7 @@ class TabTest : public ChromeViewsTestBase {
}
std::string original_locale_;
base::SimpleTestTickClock fake_clock_;
};
class AlertIndicatorTest : public ChromeViewsTestBase {
......@@ -585,6 +586,7 @@ TEST_F(TabTest, LayeredThrobber) {
tab.SizeToPreferredSize();
TabIcon* icon = GetTabIcon(tab);
SetupFakeClock(icon);
TabRendererData data;
data.url = GURL("http://example.com");
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