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

Reland "Chrome OS: Use layer animation browser window frame activation animation."

This reverts commit 20aca0dd.

Reason for revert: The issue has been resoved in crrev.com/c/2384070

Original change's description:
> Revert "Chrome OS: Use layer animation browser window frame activation animation."
> 
> This reverts commit 3a2299e5.
> 
> Reason for revert: Suspected breaking https://ci.chromium.org/p/chromium/builders/ci/Linux%20Chromium%20OS%20ASan%20LSan%20Tests%20%281%29/38374 and https://ci.chromium.org/p/chromium/builders/ci/linux-chromeos-dbg/20193
> 
> Original change's description:
> > Chrome OS: Use layer animation browser window frame activation animation.
> > 
> > This is a revised version of original attempt crrev.comc/c/2166804.
> > Instead of creating a new layers, this clone and animate the window's layer,
> > but makes sure that the animating layer is at the bottom of other layers
> > within the window.
> > 
> > * It adds a invisible view with a layer
> >   at the bottom of the non_client_view (no frame w/o this, so we can exclude such case).
> > * Adds the animating layer as a child of this view, with
> >   "SetMasksToBounds(false)" so that it will not be clipped during animation.
> > * Once animation is done, this animating, old layer will be removed.
> > 
> > Bug: 1073685
> > Test: covered by unittests.
> > Change-Id: Ib5ae6a218d200394c54932e5b559217fcc7f89e1
> > Fixed: 2
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2375686
> > Reviewed-by: Scott Violet <sky@chromium.org>
> > Commit-Queue: Mitsuru Oshima <oshima@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#802386}
> 
> TBR=sky@chromium.org,oshima@chromium.org
> 
> Change-Id: I10600b9bc69818257f66fb5c1ae86f7fd1119c75
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: 1073685
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2381217
> Reviewed-by: Melissa Zhang <melzhang@chromium.org>
> Commit-Queue: Melissa Zhang <melzhang@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#802539}

TBR=sky@chromium.org,oshima@chromium.org,melzhang@chromium.org

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: 1073685
Change-Id: I38725fa15f79576db154db91f7ca384578f545b1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2385815Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Commit-Queue: Mitsuru Oshima <oshima@chromium.org>
Cr-Commit-Position: refs/heads/master@{#803143}
parent 04bea739
This diff is collapsed.
...@@ -291,13 +291,7 @@ void HeaderView::PaintHeaderContent(gfx::Canvas* canvas) { ...@@ -291,13 +291,7 @@ void HeaderView::PaintHeaderContent(gfx::Canvas* canvas) {
if (!should_paint_ || !target_widget_) if (!should_paint_ || !target_widget_)
return; return;
bool paint_as_active = frame_header_->PaintHeader(canvas);
target_widget_->non_client_view()->frame_view()->ShouldPaintAsActive();
frame_header_->SetPaintAsActive(paint_as_active);
FrameHeader::Mode header_mode =
paint_as_active ? FrameHeader::MODE_ACTIVE : FrameHeader::MODE_INACTIVE;
frame_header_->PaintHeader(canvas, header_mode);
} }
void HeaderView::UpdateBackButton() { void HeaderView::UpdateBackButton() {
......
...@@ -410,8 +410,7 @@ NonClientFrameViewAsh::GetFrameCaptionButtonContainerViewForTest() { ...@@ -410,8 +410,7 @@ NonClientFrameViewAsh::GetFrameCaptionButtonContainerViewForTest() {
} }
void NonClientFrameViewAsh::PaintAsActiveChanged() { void NonClientFrameViewAsh::PaintAsActiveChanged() {
// The icons differ between active and inactive. header_view_->GetFrameHeader()->SetPaintAsActive(ShouldPaintAsActive());
header_view_->SchedulePaint();
frame_->non_client_view()->Layout(); frame_->non_client_view()->Layout();
} }
......
...@@ -228,6 +228,7 @@ void FrameCaptionButtonContainerView::SetPaintAsActive(bool paint_as_active) { ...@@ -228,6 +228,7 @@ void FrameCaptionButtonContainerView::SetPaintAsActive(bool paint_as_active) {
minimize_button_->set_paint_as_active(paint_as_active); minimize_button_->set_paint_as_active(paint_as_active);
size_button_->set_paint_as_active(paint_as_active); size_button_->set_paint_as_active(paint_as_active);
close_button_->set_paint_as_active(paint_as_active); close_button_->set_paint_as_active(paint_as_active);
SchedulePaint();
} }
void FrameCaptionButtonContainerView::SetBackgroundColor( void FrameCaptionButtonContainerView::SetBackgroundColor(
......
...@@ -25,6 +25,10 @@ using views::Widget; ...@@ -25,6 +25,10 @@ using views::Widget;
namespace { namespace {
// Duration of animation scheduled when frame color is changed.
constexpr base::TimeDelta kFrameColorChangeAnimationDuration =
base::TimeDelta::FromMilliseconds(240);
// Tiles an image into an area, rounding the top corners. // Tiles an image into an area, rounding the top corners.
void TileRoundRect(gfx::Canvas* canvas, void TileRoundRect(gfx::Canvas* canvas,
const cc::PaintFlags& flags, const cc::PaintFlags& flags,
...@@ -53,36 +57,6 @@ void TileRoundRect(gfx::Canvas* canvas, ...@@ -53,36 +57,6 @@ void TileRoundRect(gfx::Canvas* canvas,
namespace ash { namespace ash {
DefaultFrameHeader::ColorAnimator::ColorAnimator(
gfx::AnimationDelegate* delegate)
: animation_(delegate) {
animation_.SetSlideDuration(base::TimeDelta::FromMilliseconds(240));
animation_.SetTweenType(gfx::Tween::EASE_IN);
animation_.Reset(1);
}
DefaultFrameHeader::ColorAnimator::ColorAnimator::~ColorAnimator() = default;
void DefaultFrameHeader::ColorAnimator::SetTargetColor(SkColor target) {
target_color_ = target;
start_color_ = current_color_;
if (current_color_ == kDefaultFrameColor) {
// Changing from default should be set immediately.
current_color_ = target_color_;
animation_.Reset(1);
} else {
animation_.Reset(0);
}
animation_.Show();
}
SkColor DefaultFrameHeader::ColorAnimator::GetCurrentColor() {
current_color_ =
color_utils::AlphaBlend(target_color_, start_color_,
static_cast<float>(animation_.GetCurrentValue()));
return current_color_;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// DefaultFrameHeader, public: // DefaultFrameHeader, public:
...@@ -90,9 +64,7 @@ DefaultFrameHeader::DefaultFrameHeader( ...@@ -90,9 +64,7 @@ DefaultFrameHeader::DefaultFrameHeader(
views::Widget* target_widget, views::Widget* target_widget,
views::View* header_view, views::View* header_view,
FrameCaptionButtonContainerView* caption_button_container) FrameCaptionButtonContainerView* caption_button_container)
: FrameHeader(target_widget, header_view), : FrameHeader(target_widget, header_view) {
active_frame_color_(this),
inactive_frame_color_(this) {
DCHECK(caption_button_container); DCHECK(caption_button_container);
SetCaptionButtonContainer(caption_button_container); SetCaptionButtonContainer(caption_button_container);
} }
...@@ -114,18 +86,19 @@ void DefaultFrameHeader::UpdateFrameColors() { ...@@ -114,18 +86,19 @@ void DefaultFrameHeader::UpdateFrameColors() {
target_window->GetProperty(kFrameInactiveColorKey); target_window->GetProperty(kFrameInactiveColorKey);
bool updated = false; bool updated = false;
if (active_frame_color_.target_color() != active_frame_color) { // Update the frame if the frame color for the current active state chagnes.
active_frame_color_.SetTargetColor(active_frame_color); if (active_frame_color_ != active_frame_color) {
updated = true; active_frame_color_ = active_frame_color;
updated = mode() == Mode::MODE_ACTIVE;
} }
if (inactive_frame_color_.target_color() != inactive_frame_color) { if (inactive_frame_color_ != inactive_frame_color) {
inactive_frame_color_.SetTargetColor(inactive_frame_color); inactive_frame_color_ = inactive_frame_color;
updated = true; updated |= mode() == Mode::MODE_INACTIVE;
} }
if (updated) { if (updated) {
UpdateCaptionButtonColors(); UpdateCaptionButtonColors();
view()->SchedulePaint(); StartTransitionAnimation(kFrameColorChangeAnimationDuration);
} }
} }
...@@ -139,10 +112,8 @@ void DefaultFrameHeader::DoPaintHeader(gfx::Canvas* canvas) { ...@@ -139,10 +112,8 @@ void DefaultFrameHeader::DoPaintHeader(gfx::Canvas* canvas) {
: 0; : 0;
cc::PaintFlags flags; cc::PaintFlags flags;
flags.setColor(color_utils::AlphaBlend( flags.setColor(mode() == Mode::MODE_ACTIVE ? active_frame_color_
active_frame_color_.GetCurrentColor(), : inactive_frame_color_);
inactive_frame_color_.GetCurrentColor(),
static_cast<float>(activation_animation().GetCurrentValue())));
flags.setAntiAlias(true); flags.setAntiAlias(true);
if (width_in_pixels_ > 0) { if (width_in_pixels_ > 0) {
canvas->Save(); canvas->Save();
...@@ -186,17 +157,11 @@ aura::Window* DefaultFrameHeader::GetTargetWindow() { ...@@ -186,17 +157,11 @@ aura::Window* DefaultFrameHeader::GetTargetWindow() {
} }
SkColor DefaultFrameHeader::GetCurrentFrameColor() const { SkColor DefaultFrameHeader::GetCurrentFrameColor() const {
return mode() == MODE_ACTIVE ? active_frame_color_.target_color() return mode() == MODE_ACTIVE ? active_frame_color_ : inactive_frame_color_;
: inactive_frame_color_.target_color();
}
gfx::SlideAnimation*
DefaultFrameHeader::GetAnimationForActiveFrameColorForTest() {
return active_frame_color_.animation();
} }
SkColor DefaultFrameHeader::GetActiveFrameColorForPaintForTest() { SkColor DefaultFrameHeader::GetActiveFrameColorForPaintForTest() {
return active_frame_color_.GetCurrentColor(); return active_frame_color_;
} }
} // namespace ash } // namespace ash
...@@ -26,12 +26,8 @@ class ASH_PUBLIC_EXPORT DefaultFrameHeader : public FrameHeader { ...@@ -26,12 +26,8 @@ class ASH_PUBLIC_EXPORT DefaultFrameHeader : public FrameHeader {
FrameCaptionButtonContainerView* caption_button_container); FrameCaptionButtonContainerView* caption_button_container);
~DefaultFrameHeader() override; ~DefaultFrameHeader() override;
SkColor active_frame_color_for_testing() { SkColor active_frame_color_for_testing() { return active_frame_color_; }
return active_frame_color_.target_color(); SkColor inactive_frame_color_for_testing() { return inactive_frame_color_; }
}
SkColor inactive_frame_color_for_testing() {
return inactive_frame_color_.target_color();
}
void SetWidthInPixels(int width_in_pixels); void SetWidthInPixels(int width_in_pixels);
...@@ -51,33 +47,10 @@ class ASH_PUBLIC_EXPORT DefaultFrameHeader : public FrameHeader { ...@@ -51,33 +47,10 @@ class ASH_PUBLIC_EXPORT DefaultFrameHeader : public FrameHeader {
// Returns the window of the target widget. // Returns the window of the target widget.
aura::Window* GetTargetWindow(); aura::Window* GetTargetWindow();
gfx::SlideAnimation* GetAnimationForActiveFrameColorForTest();
SkColor GetActiveFrameColorForPaintForTest(); SkColor GetActiveFrameColorForPaintForTest();
// A utility class to animate color value. SkColor active_frame_color_ = kDefaultFrameColor;
class ColorAnimator { SkColor inactive_frame_color_ = kDefaultFrameColor;
public:
explicit ColorAnimator(gfx::AnimationDelegate* delegate);
~ColorAnimator();
void SetTargetColor(SkColor target);
SkColor target_color() const { return target_color_; }
SkColor GetCurrentColor();
float get_value() const { return animation_.GetCurrentValue(); }
gfx::SlideAnimation* animation() { return &animation_; }
private:
gfx::SlideAnimation animation_;
SkColor start_color_ = kDefaultFrameColor;
SkColor target_color_ = kDefaultFrameColor;
SkColor current_color_ = kDefaultFrameColor;
DISALLOW_COPY_AND_ASSIGN(ColorAnimator);
};
ColorAnimator active_frame_color_;
ColorAnimator inactive_frame_color_;
int width_in_pixels_ = -1; int width_in_pixels_ = -1;
......
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
#include "ash/public/cpp/window_properties.h" #include "ash/public/cpp/window_properties.h"
#include "base/logging.h" // DCHECK #include "base/logging.h" // DCHECK
#include "ui/base/class_property.h" #include "ui/base/class_property.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_tree_owner.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h" #include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h" #include "ui/gfx/color_utils.h"
#include "ui/gfx/font_list.h" #include "ui/gfx/font_list.h"
...@@ -29,6 +32,9 @@ namespace ash { ...@@ -29,6 +32,9 @@ namespace ash {
namespace { namespace {
constexpr base::TimeDelta kFrameActivationAnimationDuration =
base::TimeDelta::FromMilliseconds(200);
DEFINE_UI_CLASS_PROPERTY_KEY(FrameHeader*, kFrameHeaderKey, nullptr) DEFINE_UI_CLASS_PROPERTY_KEY(FrameHeader*, kFrameHeaderKey, nullptr)
// Returns the available bounds for the header's title given the views to the // Returns the available bounds for the header's title given the views to the
...@@ -61,29 +67,6 @@ gfx::Rect GetAvailableTitleBounds(const views::View* left_view, ...@@ -61,29 +67,6 @@ gfx::Rect GetAvailableTitleBounds(const views::View* left_view,
return gfx::Rect(x, y, width, title_height); return gfx::Rect(x, y, width, title_height);
} }
// Returns true if the header for |widget| can animate to new visuals when the
// widget's activation changes. Returns false if the header should switch to
// new visuals instantaneously.
bool CanAnimateActivation(views::Widget* widget) {
// Do not animate the header if the parent (e.g. the active desk container) is
// already animating. All of the implementers of FrameHeader animate
// activation by continuously painting during the animation. This gives the
// parent's animation a slower frame rate.
// TODO(sky): Expose a better way to determine this rather than assuming the
// parent is a toplevel container.
aura::Window* window = widget->GetNativeWindow();
// TODO(sky): parent()->layer() is for mash until animations ported.
if (!window || !window->parent() || !window->parent()->layer())
return true;
ui::LayerAnimator* parent_layer_animator =
window->parent()->layer()->GetAnimator();
return !parent_layer_animator->IsAnimatingProperty(
ui::LayerAnimationElement::OPACITY) &&
!parent_layer_animator->IsAnimatingProperty(
ui::LayerAnimationElement::VISIBILITY);
}
} // namespace } // namespace
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -107,29 +90,102 @@ int FrameHeader::GetMinimumHeaderWidth() const { ...@@ -107,29 +90,102 @@ int FrameHeader::GetMinimumHeaderWidth() const {
caption_button_container_->GetMinimumSize().width(); caption_button_container_->GetMinimumSize().width();
} }
void FrameHeader::PaintHeader(gfx::Canvas* canvas, Mode mode) { // An invisible view that drives the frame's animation. This holds the animating
Mode old_mode = mode_; // layer as a layer beneath this view so that it's behind all other child layers
mode_ = mode; // of the window to avoid hiding their contents.
class FrameHeader::FrameAnimatorView : public views::View,
if (mode_ != old_mode) { public views::ViewObserver,
UpdateCaptionButtonColors(); public ui::ImplicitAnimationObserver {
public:
if (!initial_paint_ && CanAnimateActivation(target_widget_)) { FrameAnimatorView(FrameHeader* frame_header, views::View* parent)
activation_animation_.SetSlideDuration( : frame_header_(frame_header), parent_(parent) {
base::TimeDelta::FromMilliseconds(200)); SetPaintToLayer(ui::LAYER_NOT_DRAWN);
if (mode_ == MODE_ACTIVE) parent_->AddChildViewAt(this, 0);
activation_animation_.Show(); parent_->AddObserver(this);
else }
activation_animation_.Hide(); FrameAnimatorView(const FrameAnimatorView&) = delete;
} else { FrameAnimatorView& operator=(const FrameAnimatorView&) = delete;
if (mode_ == MODE_ACTIVE) ~FrameAnimatorView() override {
activation_animation_.Reset(1); StopAnimation();
else // A child view should always be removed first.
activation_animation_.Reset(0); parent_->RemoveObserver(this);
}
void StartAnimation(base::TimeDelta duration) {
StopAnimation();
aura::Window* window = frame_header_->target_widget()->GetNativeWindow();
// Make sure the this view is at the bottom of root view's children.
parent_->ReorderChildView(this, 0);
std::unique_ptr<ui::LayerTreeOwner> old_layer_owner =
std::make_unique<ui::LayerTreeOwner>(window->RecreateLayer());
ui::Layer* old_layer = old_layer_owner->root();
ui::Layer* new_layer = window->layer();
new_layer->SetName(old_layer->name());
old_layer->SetName(old_layer->name() + ":Old");
old_layer->SetTransform(gfx::Transform());
layer_owner_ = std::move(old_layer_owner);
AddLayerBeneathView(old_layer);
// The old layer is on top and should fade out.
old_layer->SetOpacity(1.f);
new_layer->SetOpacity(1.f);
{
ui::ScopedLayerAnimationSettings settings(old_layer->GetAnimator());
settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
settings.AddObserver(this);
settings.SetTransitionDuration(duration);
old_layer->SetOpacity(0.f);
settings.SetTweenType(gfx::Tween::EASE_OUT);
}
}
// views::Views:
const char* GetClassName() const override { return "FrameAnimatorView"; }
std::unique_ptr<ui::Layer> RecreateLayer() override {
// A layer may be recreated for another animation (maximize/restore).
// Just cancel the animation if that happens during animation.
StopAnimation();
return views::View::RecreateLayer();
}
// ViewObserver::
void OnChildViewReordered(views::View* observed_view,
views::View* child) override {
// Stop animation if the child view order has changed during animation.
StopAnimation();
}
void OnViewBoundsChanged(views::View* observed_view) override {
// Stop animation if the frame size changed during animation.
StopAnimation();
SetBoundsRect(parent_->GetLocalBounds());
}
// ui::ImplicitAnimationObserver overrides:
void OnImplicitAnimationsCompleted() override {
RemoveLayerBeneathView(layer_owner_->root());
layer_owner_ = nullptr;
}
private:
void StopAnimation() {
if (layer_owner_) {
layer_owner_->root()->GetAnimator()->StopAnimating();
layer_owner_ = nullptr;
} }
initial_paint_ = false;
} }
FrameHeader* frame_header_;
views::View* parent_;
std::unique_ptr<ui::LayerTreeOwner> layer_owner_;
};
void FrameHeader::PaintHeader(gfx::Canvas* canvas) {
painted_ = true;
DoPaintHeader(canvas); DoPaintHeader(canvas);
} }
...@@ -157,6 +213,18 @@ void FrameHeader::SchedulePaintForTitle() { ...@@ -157,6 +213,18 @@ void FrameHeader::SchedulePaintForTitle() {
} }
void FrameHeader::SetPaintAsActive(bool paint_as_active) { void FrameHeader::SetPaintAsActive(bool paint_as_active) {
// No need to animate if already active.
const bool already_active = (mode_ == Mode::MODE_ACTIVE);
if (already_active == paint_as_active)
return;
mode_ = paint_as_active ? MODE_ACTIVE : MODE_INACTIVE;
// The frame has no content yet to animatie.
if (painted_)
StartTransitionAnimation(kFrameActivationAnimationDuration);
caption_button_container_->SetPaintAsActive(paint_as_active); caption_button_container_->SetPaintAsActive(paint_as_active);
if (back_button_) if (back_button_)
back_button_->set_paint_as_active(paint_as_active); back_button_->set_paint_as_active(paint_as_active);
...@@ -198,23 +266,15 @@ void FrameHeader::SetFrameTextOverride( ...@@ -198,23 +266,15 @@ void FrameHeader::SetFrameTextOverride(
SchedulePaintForTitle(); SchedulePaintForTitle();
} }
///////////////////////////////////////////////////////////////////////////////
// gfx::AnimationDelegate overrides:
void FrameHeader::AnimationProgressed(const gfx::Animation* animation) {
view_->SchedulePaintInRect(GetPaintedBounds());
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// FrameHeader, protected: // FrameHeader, protected:
FrameHeader::FrameHeader(views::Widget* target_widget, views::View* view) FrameHeader::FrameHeader(views::Widget* target_widget, views::View* view)
: views::AnimationDelegateViews(view), : target_widget_(target_widget), view_(view) {
target_widget_(target_widget),
view_(view) {
DCHECK(target_widget); DCHECK(target_widget);
DCHECK(view); DCHECK(view);
UpdateFrameHeaderKey(); UpdateFrameHeaderKey();
frame_animator_ = new FrameAnimatorView(this, view);
} }
void FrameHeader::UpdateFrameHeaderKey() { void FrameHeader::UpdateFrameHeaderKey() {
...@@ -269,6 +329,18 @@ void FrameHeader::SetCaptionButtonContainer( ...@@ -269,6 +329,18 @@ void FrameHeader::SetCaptionButtonContainer(
LayoutHeaderInternal(); LayoutHeaderInternal();
} }
void FrameHeader::StartTransitionAnimation(base::TimeDelta duration) {
aura::Window* window = target_widget_->GetNativeWindow();
// Don't start another animation if the window is already animating
// such as maximize/restore/unminimize.
if (window->layer()->GetAnimator()->is_animating())
return;
frame_animator_->StartAnimation(duration);
frame_animator_->SchedulePaint();
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// FrameHeader, private: // FrameHeader, private:
......
...@@ -7,11 +7,12 @@ ...@@ -7,11 +7,12 @@
#include "ash/public/cpp/ash_public_export.h" #include "ash/public/cpp/ash_public_export.h"
#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h" #include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
#include "base/callback.h"
#include "base/optional.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
#include "ui/base/ui_base_types.h" #include "ui/base/ui_base_types.h"
#include "ui/gfx/animation/slide_animation.h" #include "ui/compositor/layer_animation_observer.h"
#include "ui/views/animation/animation_delegate_views.h"
#include "ui/views/window/frame_caption_button.h" #include "ui/views/window/frame_caption_button.h"
namespace gfx { namespace gfx {
...@@ -29,13 +30,13 @@ namespace ash { ...@@ -29,13 +30,13 @@ namespace ash {
class CaptionButtonModel; class CaptionButtonModel;
// Helper class for managing the window header. // Helper class for managing the window header.
class ASH_PUBLIC_EXPORT FrameHeader : public views::AnimationDelegateViews { class ASH_PUBLIC_EXPORT FrameHeader {
public: public:
enum Mode { MODE_ACTIVE, MODE_INACTIVE }; enum Mode { MODE_ACTIVE, MODE_INACTIVE };
static FrameHeader* Get(views::Widget* widget); static FrameHeader* Get(views::Widget* widget);
~FrameHeader() override; virtual ~FrameHeader();
const base::string16& frame_text_override() const { const base::string16& frame_text_override() const {
return frame_text_override_; return frame_text_override_;
...@@ -45,7 +46,7 @@ class ASH_PUBLIC_EXPORT FrameHeader : public views::AnimationDelegateViews { ...@@ -45,7 +46,7 @@ class ASH_PUBLIC_EXPORT FrameHeader : public views::AnimationDelegateViews {
int GetMinimumHeaderWidth() const; int GetMinimumHeaderWidth() const;
// Paints the header. // Paints the header.
void PaintHeader(gfx::Canvas* canvas, Mode mode); void PaintHeader(gfx::Canvas* canvas);
// Performs layout for the header. // Performs layout for the header.
void LayoutHeader(); void LayoutHeader();
...@@ -81,9 +82,6 @@ class ASH_PUBLIC_EXPORT FrameHeader : public views::AnimationDelegateViews { ...@@ -81,9 +82,6 @@ class ASH_PUBLIC_EXPORT FrameHeader : public views::AnimationDelegateViews {
// regardless of what ShouldShowWindowTitle() returns. // regardless of what ShouldShowWindowTitle() returns.
void SetFrameTextOverride(const base::string16& frame_text_override); void SetFrameTextOverride(const base::string16& frame_text_override);
// views::AnimationDelegateViews:
void AnimationProgressed(const gfx::Animation* animation) override;
void UpdateFrameHeaderKey(); void UpdateFrameHeaderKey();
views::View* view() { return view_; } views::View* view() { return view_; }
...@@ -112,19 +110,20 @@ class ASH_PUBLIC_EXPORT FrameHeader : public views::AnimationDelegateViews { ...@@ -112,19 +110,20 @@ class ASH_PUBLIC_EXPORT FrameHeader : public views::AnimationDelegateViews {
Mode mode() const { return mode_; } Mode mode() const { return mode_; }
const gfx::SlideAnimation& activation_animation() {
return activation_animation_;
}
virtual void DoPaintHeader(gfx::Canvas* canvas) = 0; virtual void DoPaintHeader(gfx::Canvas* canvas) = 0;
virtual views::CaptionButtonLayoutSize GetButtonLayoutSize() const = 0; virtual views::CaptionButtonLayoutSize GetButtonLayoutSize() const = 0;
virtual SkColor GetTitleColor() const = 0; virtual SkColor GetTitleColor() const = 0;
virtual SkColor GetCurrentFrameColor() const = 0; virtual SkColor GetCurrentFrameColor() const = 0;
// Starts fade transition animation with given duration.
void StartTransitionAnimation(base::TimeDelta duration);
private: private:
class FrameAnimatorView;
FRIEND_TEST_ALL_PREFIXES(DefaultFrameHeaderTest, BackButtonAlignment); FRIEND_TEST_ALL_PREFIXES(DefaultFrameHeaderTest, BackButtonAlignment);
FRIEND_TEST_ALL_PREFIXES(DefaultFrameHeaderTest, TitleIconAlignment); FRIEND_TEST_ALL_PREFIXES(DefaultFrameHeaderTest, TitleIconAlignment);
FRIEND_TEST_ALL_PREFIXES(DefaultFrameHeaderTest, FrameColors); FRIEND_TEST_ALL_PREFIXES(DefaultFrameHeaderTest, FrameColors);
friend class FramePaintWaiter;
void LayoutHeaderInternal(); void LayoutHeaderInternal();
...@@ -139,20 +138,19 @@ class ASH_PUBLIC_EXPORT FrameHeader : public views::AnimationDelegateViews { ...@@ -139,20 +138,19 @@ class ASH_PUBLIC_EXPORT FrameHeader : public views::AnimationDelegateViews {
views::FrameCaptionButton* back_button_ = nullptr; // May remain nullptr. views::FrameCaptionButton* back_button_ = nullptr; // May remain nullptr.
views::View* left_header_view_ = nullptr; // May remain nullptr. views::View* left_header_view_ = nullptr; // May remain nullptr.
FrameCaptionButtonContainerView* caption_button_container_ = nullptr; FrameCaptionButtonContainerView* caption_button_container_ = nullptr;
FrameAnimatorView* frame_animator_ = nullptr; // owned by view tree.
// The height of the header to paint. // The height of the header to paint.
int painted_height_ = 0; int painted_height_ = 0;
// Used to skip animation when the frame hasn't painted yet.
bool painted_ = false;
// Whether the header should be painted as active. // Whether the header should be painted as active.
Mode mode_ = MODE_INACTIVE; Mode mode_ = MODE_INACTIVE;
// Whether the header is painted for the first time.
bool initial_paint_ = true;
base::string16 frame_text_override_; base::string16 frame_text_override_;
gfx::SlideAnimation activation_animation_{this};
DISALLOW_COPY_AND_ASSIGN(FrameHeader); DISALLOW_COPY_AND_ASSIGN(FrameHeader);
}; };
......
...@@ -34,39 +34,31 @@ void PaintThemedFrame(gfx::Canvas* canvas, ...@@ -34,39 +34,31 @@ void PaintThemedFrame(gfx::Canvas* canvas,
SkColor background_color, SkColor background_color,
const gfx::Rect& bounds, const gfx::Rect& bounds,
int image_inset_x, int image_inset_x,
int image_inset_y, int image_inset_y) {
int alpha) {
SkColor opaque_background_color = SkColor opaque_background_color =
SkColorSetA(background_color, SK_AlphaOPAQUE); SkColorSetA(background_color, SK_AlphaOPAQUE);
// When no images are used, just draw a color, with the animation |alpha| // When no images are used, just draw a color.
// applied.
if (frame_image.isNull() && frame_overlay_image.isNull()) { if (frame_image.isNull() && frame_overlay_image.isNull()) {
// We use kPlus blending mode so that between the active and inactive canvas->DrawColor(opaque_background_color);
// background colors, the result is 255 alpha (i.e. opaque).
canvas->DrawColor(SkColorSetA(opaque_background_color, alpha),
SkBlendMode::kPlus);
return; return;
} }
// This handles the case where blending is required between one or more images // This handles the case where blending is required between one or more images
// and the background color. In this case we use a SaveLayerWithFlags() call // and the background color. In this case we use a SaveLayerWithFlags() call
// to draw all 2-3 components into a single layer then apply the alpha to them // to draw all 2-3 components into a single layer.
// together.
const bool blending_required = const bool blending_required =
alpha < 0xFF || (!frame_image.isNull() && !frame_overlay_image.isNull()); !frame_image.isNull() && !frame_overlay_image.isNull();
if (blending_required) { if (blending_required) {
cc::PaintFlags flags; cc::PaintFlags flags;
// We use kPlus blending mode so that between the active and inactive // We use kPlus blending mode so that between the active and inactive
// background colors, the result is 255 alpha (i.e. opaque). // background colors, the result is 255 alpha (i.e. opaque).
flags.setBlendMode(SkBlendMode::kPlus); flags.setBlendMode(SkBlendMode::kPlus);
flags.setAlpha(alpha);
canvas->SaveLayerWithFlags(flags); canvas->SaveLayerWithFlags(flags);
} }
// Images can be transparent and we expect the background color to be present // Images can be transparent and we expect the background color to be present
// behind them. Here the |alpha| will be applied to the background color by // behind them.
// the SaveLayer call, so use |opaque_background_color|.
canvas->DrawColor(opaque_background_color); canvas->DrawColor(opaque_background_color);
if (!frame_image.isNull()) { if (!frame_image.isNull()) {
canvas->TileImageInt(frame_image, image_inset_x, image_inset_y, 0, 0, canvas->TileImageInt(frame_image, image_inset_x, image_inset_y, 0, 0,
...@@ -89,7 +81,6 @@ void PaintFrameImagesInRoundRect(gfx::Canvas* canvas, ...@@ -89,7 +81,6 @@ void PaintFrameImagesInRoundRect(gfx::Canvas* canvas,
const gfx::Rect& bounds, const gfx::Rect& bounds,
int image_inset_x, int image_inset_x,
int image_inset_y, int image_inset_y,
int alpha,
int corner_radius) { int corner_radius) {
const SkScalar sk_corner_radius = SkIntToScalar(corner_radius); const SkScalar sk_corner_radius = SkIntToScalar(corner_radius);
const SkScalar radii[8] = {sk_corner_radius, const SkScalar radii[8] = {sk_corner_radius,
...@@ -109,7 +100,7 @@ void PaintFrameImagesInRoundRect(gfx::Canvas* canvas, ...@@ -109,7 +100,7 @@ void PaintFrameImagesInRoundRect(gfx::Canvas* canvas,
canvas->ClipPath(frame_path, antialias); canvas->ClipPath(frame_path, antialias);
PaintThemedFrame(canvas, frame_image, frame_overlay_image, background_color, PaintThemedFrame(canvas, frame_image, frame_overlay_image, background_color,
bounds, image_inset_x, image_inset_y, alpha); bounds, image_inset_x, image_inset_y);
} }
} // namespace } // namespace
...@@ -147,8 +138,7 @@ int BrowserFrameHeaderAsh::GetThemeBackgroundXInset() { ...@@ -147,8 +138,7 @@ int BrowserFrameHeaderAsh::GetThemeBackgroundXInset() {
// BrowserFrameHeaderAsh, protected: // BrowserFrameHeaderAsh, protected:
void BrowserFrameHeaderAsh::DoPaintHeader(gfx::Canvas* canvas) { void BrowserFrameHeaderAsh::DoPaintHeader(gfx::Canvas* canvas) {
PaintFrameImages(canvas, false /* active */); PaintFrameImages(canvas);
PaintFrameImages(canvas, true /* active */);
PaintTitleBar(canvas); PaintTitleBar(canvas);
} }
...@@ -178,13 +168,8 @@ void BrowserFrameHeaderAsh::UpdateFrameColors() { ...@@ -178,13 +168,8 @@ void BrowserFrameHeaderAsh::UpdateFrameColors() {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// BrowserFrameHeaderAsh, private: // BrowserFrameHeaderAsh, private:
void BrowserFrameHeaderAsh::PaintFrameImages(gfx::Canvas* canvas, bool active) { void BrowserFrameHeaderAsh::PaintFrameImages(gfx::Canvas* canvas) {
int alpha = activation_animation().CurrentValueBetween(0, 0xFF); const bool active = mode() == Mode::MODE_ACTIVE;
if (!active)
alpha = 0xFF - alpha;
if (alpha == 0)
return;
gfx::ImageSkia frame_image = gfx::ImageSkia frame_image =
appearance_provider_->GetFrameHeaderImage(active); appearance_provider_->GetFrameHeaderImage(active);
...@@ -201,5 +186,5 @@ void BrowserFrameHeaderAsh::PaintFrameImages(gfx::Canvas* canvas, bool active) { ...@@ -201,5 +186,5 @@ void BrowserFrameHeaderAsh::PaintFrameImages(gfx::Canvas* canvas, bool active) {
appearance_provider_->GetFrameHeaderColor(active), appearance_provider_->GetFrameHeaderColor(active),
GetPaintedBounds(), GetThemeBackgroundXInset(), GetPaintedBounds(), GetThemeBackgroundXInset(),
appearance_provider_->GetFrameHeaderImageYInset(), appearance_provider_->GetFrameHeaderImageYInset(),
alpha, corner_radius); corner_radius);
} }
...@@ -49,9 +49,8 @@ class BrowserFrameHeaderAsh : public ash::FrameHeader { ...@@ -49,9 +49,8 @@ class BrowserFrameHeaderAsh : public ash::FrameHeader {
SkColor GetCurrentFrameColor() const override; SkColor GetCurrentFrameColor() const override;
private: private:
// Paints the frame image for the |active| state based on the current value of // Paints the frame image.
// the activation animation. void PaintFrameImages(gfx::Canvas* canvas);
void PaintFrameImages(gfx::Canvas* canvas, bool active);
AppearanceProvider* appearance_provider_ = nullptr; AppearanceProvider* appearance_provider_ = nullptr;
......
...@@ -326,11 +326,8 @@ void BrowserNonClientFrameViewAsh::OnPaint(gfx::Canvas* canvas) { ...@@ -326,11 +326,8 @@ void BrowserNonClientFrameViewAsh::OnPaint(gfx::Canvas* canvas) {
if (!ShouldPaint()) if (!ShouldPaint())
return; return;
const ash::FrameHeader::Mode header_mode =
ShouldPaintAsActive() ? ash::FrameHeader::MODE_ACTIVE
: ash::FrameHeader::MODE_INACTIVE;
if (frame_header_) if (frame_header_)
frame_header_->PaintHeader(canvas, header_mode); frame_header_->PaintHeader(canvas);
} }
void BrowserNonClientFrameViewAsh::Layout() { void BrowserNonClientFrameViewAsh::Layout() {
......
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