Commit 2c65720a authored by Alice Boxhall's avatar Alice Boxhall Committed by Commit Bot

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

This reverts commit 0dce55ff.

Reason for revert: This has caused a crash in many CrOS tests: https://ci.chromium.org/p/chromium/builders/ci/linux-chromeos-dbg/20119

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: Ib9ae60694fb461dda354fea4fd52e4e01186a6a7
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2335811
> Reviewed-by: Scott Violet <sky@chromium.org>
> Commit-Queue: Mitsuru Oshima <oshima@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#800827}

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

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

Bug: 1073685
Change-Id: I093849df58f25a46a021f923daab1ab1faa1efee
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2371383Reviewed-by: default avatarAlice Boxhall <aboxhall@chromium.org>
Commit-Queue: Alice Boxhall <aboxhall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#800896}
parent 7218ff0a
This diff is collapsed.
...@@ -291,7 +291,13 @@ void HeaderView::PaintHeaderContent(gfx::Canvas* canvas) { ...@@ -291,7 +291,13 @@ void HeaderView::PaintHeaderContent(gfx::Canvas* canvas) {
if (!should_paint_ || !target_widget_) if (!should_paint_ || !target_widget_)
return; return;
frame_header_->PaintHeader(canvas); bool paint_as_active =
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,7 +410,8 @@ NonClientFrameViewAsh::GetFrameCaptionButtonContainerViewForTest() { ...@@ -410,7 +410,8 @@ NonClientFrameViewAsh::GetFrameCaptionButtonContainerViewForTest() {
} }
void NonClientFrameViewAsh::PaintAsActiveChanged() { void NonClientFrameViewAsh::PaintAsActiveChanged() {
header_view_->GetFrameHeader()->SetPaintAsActive(ShouldPaintAsActive()); // The icons differ between active and inactive.
header_view_->SchedulePaint();
frame_->non_client_view()->Layout(); frame_->non_client_view()->Layout();
} }
......
...@@ -228,7 +228,6 @@ void FrameCaptionButtonContainerView::SetPaintAsActive(bool paint_as_active) { ...@@ -228,7 +228,6 @@ 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,10 +25,6 @@ using views::Widget; ...@@ -25,10 +25,6 @@ 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,
...@@ -57,6 +53,36 @@ void TileRoundRect(gfx::Canvas* canvas, ...@@ -57,6 +53,36 @@ 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:
...@@ -64,7 +90,9 @@ DefaultFrameHeader::DefaultFrameHeader( ...@@ -64,7 +90,9 @@ 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);
} }
...@@ -86,19 +114,18 @@ void DefaultFrameHeader::UpdateFrameColors() { ...@@ -86,19 +114,18 @@ void DefaultFrameHeader::UpdateFrameColors() {
target_window->GetProperty(kFrameInactiveColorKey); target_window->GetProperty(kFrameInactiveColorKey);
bool updated = false; bool updated = false;
// Update the frame if the frame color for the current active state chagnes. if (active_frame_color_.target_color() != active_frame_color) {
if (active_frame_color_ != active_frame_color) { active_frame_color_.SetTargetColor(active_frame_color);
active_frame_color_ = active_frame_color; updated = true;
updated = mode() == Mode::MODE_ACTIVE;
} }
if (inactive_frame_color_ != inactive_frame_color) { if (inactive_frame_color_.target_color() != inactive_frame_color) {
inactive_frame_color_ = inactive_frame_color; inactive_frame_color_.SetTargetColor(inactive_frame_color);
updated |= mode() == Mode::MODE_INACTIVE; updated = true;
} }
if (updated) { if (updated) {
UpdateCaptionButtonColors(); UpdateCaptionButtonColors();
StartTransitionAnimation(kFrameColorChangeAnimationDuration); view()->SchedulePaint();
} }
} }
...@@ -112,8 +139,10 @@ void DefaultFrameHeader::DoPaintHeader(gfx::Canvas* canvas) { ...@@ -112,8 +139,10 @@ void DefaultFrameHeader::DoPaintHeader(gfx::Canvas* canvas) {
: 0; : 0;
cc::PaintFlags flags; cc::PaintFlags flags;
flags.setColor(mode() == Mode::MODE_ACTIVE ? active_frame_color_ flags.setColor(color_utils::AlphaBlend(
: inactive_frame_color_); active_frame_color_.GetCurrentColor(),
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();
...@@ -157,11 +186,17 @@ aura::Window* DefaultFrameHeader::GetTargetWindow() { ...@@ -157,11 +186,17 @@ aura::Window* DefaultFrameHeader::GetTargetWindow() {
} }
SkColor DefaultFrameHeader::GetCurrentFrameColor() const { SkColor DefaultFrameHeader::GetCurrentFrameColor() const {
return mode() == MODE_ACTIVE ? active_frame_color_ : inactive_frame_color_; return mode() == MODE_ACTIVE ? active_frame_color_.target_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_; return active_frame_color_.GetCurrentColor();
} }
} // namespace ash } // namespace ash
...@@ -26,8 +26,12 @@ class ASH_PUBLIC_EXPORT DefaultFrameHeader : public FrameHeader { ...@@ -26,8 +26,12 @@ 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() { return active_frame_color_; } SkColor active_frame_color_for_testing() {
SkColor inactive_frame_color_for_testing() { return inactive_frame_color_; } return active_frame_color_.target_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);
...@@ -47,10 +51,33 @@ class ASH_PUBLIC_EXPORT DefaultFrameHeader : public FrameHeader { ...@@ -47,10 +51,33 @@ 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();
SkColor active_frame_color_ = kDefaultFrameColor; // A utility class to animate color value.
SkColor inactive_frame_color_ = kDefaultFrameColor; class ColorAnimator {
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,9 +11,6 @@ ...@@ -11,9 +11,6 @@
#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"
...@@ -32,9 +29,6 @@ namespace ash { ...@@ -32,9 +29,6 @@ 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
...@@ -67,6 +61,29 @@ gfx::Rect GetAvailableTitleBounds(const views::View* left_view, ...@@ -67,6 +61,29 @@ 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
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -90,105 +107,29 @@ int FrameHeader::GetMinimumHeaderWidth() const { ...@@ -90,105 +107,29 @@ int FrameHeader::GetMinimumHeaderWidth() const {
caption_button_container_->GetMinimumSize().width(); caption_button_container_->GetMinimumSize().width();
} }
// An invisible view that drives the frame's animation. This holds the animating void FrameHeader::PaintHeader(gfx::Canvas* canvas, Mode mode) {
// layer as a layer beneath this view so that it's behind all other child layers Mode old_mode = mode_;
// of the window to avoid hiding their contents. mode_ = mode;
class FrameHeader::FrameAnimatorView : public views::View,
public views::ViewObserver, if (mode_ != old_mode) {
public ui::ImplicitAnimationObserver { UpdateCaptionButtonColors();
public:
FrameAnimatorView(FrameHeader* frame_header, views::View* parent) if (!initial_paint_ && CanAnimateActivation(target_widget_)) {
: frame_header_(frame_header) { activation_animation_.SetSlideDuration(
SetPaintToLayer(ui::LAYER_NOT_DRAWN); base::TimeDelta::FromMilliseconds(200));
parent->AddChildViewAt(this, 0); if (mode_ == MODE_ACTIVE)
parent->AddObserver(this); activation_animation_.Show();
} else
FrameAnimatorView(const FrameAnimatorView&) = delete; activation_animation_.Hide();
FrameAnimatorView& operator=(const FrameAnimatorView&) = delete; } else {
~FrameAnimatorView() override { if (mode_ == MODE_ACTIVE)
StopAnimation(); activation_animation_.Reset(1);
if (parent()) else
parent()->RemoveObserver(this); activation_animation_.Reset(0);
}
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(View* observed_view, View* child) override {
// Stop animation if the child view order has changed during animation.
StopAnimation();
}
void OnViewIsDeleting(View* observed_view) override {
// Stop animation if the parent is being detroyed.
StopAnimation();
observed_view->RemoveObserver(this);
}
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_;
std::unique_ptr<ui::LayerTreeOwner> layer_owner_;
};
void FrameHeader::PaintHeader(gfx::Canvas* canvas) {
painted_ = true;
DoPaintHeader(canvas); DoPaintHeader(canvas);
} }
...@@ -216,18 +157,6 @@ void FrameHeader::SchedulePaintForTitle() { ...@@ -216,18 +157,6 @@ 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);
...@@ -269,15 +198,23 @@ void FrameHeader::SetFrameTextOverride( ...@@ -269,15 +198,23 @@ 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)
: target_widget_(target_widget), view_(view) { : views::AnimationDelegateViews(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() {
...@@ -332,18 +269,6 @@ void FrameHeader::SetCaptionButtonContainer( ...@@ -332,18 +269,6 @@ 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,12 +7,11 @@ ...@@ -7,12 +7,11 @@
#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/compositor/layer_animation_observer.h" #include "ui/gfx/animation/slide_animation.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 {
...@@ -30,13 +29,13 @@ namespace ash { ...@@ -30,13 +29,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 { class ASH_PUBLIC_EXPORT FrameHeader : public views::AnimationDelegateViews {
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);
virtual ~FrameHeader(); ~FrameHeader() override;
const base::string16& frame_text_override() const { const base::string16& frame_text_override() const {
return frame_text_override_; return frame_text_override_;
...@@ -46,7 +45,7 @@ class ASH_PUBLIC_EXPORT FrameHeader { ...@@ -46,7 +45,7 @@ class ASH_PUBLIC_EXPORT FrameHeader {
int GetMinimumHeaderWidth() const; int GetMinimumHeaderWidth() const;
// Paints the header. // Paints the header.
void PaintHeader(gfx::Canvas* canvas); void PaintHeader(gfx::Canvas* canvas, Mode mode);
// Performs layout for the header. // Performs layout for the header.
void LayoutHeader(); void LayoutHeader();
...@@ -82,6 +81,9 @@ class ASH_PUBLIC_EXPORT FrameHeader { ...@@ -82,6 +81,9 @@ class ASH_PUBLIC_EXPORT FrameHeader {
// 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_; }
...@@ -110,20 +112,19 @@ class ASH_PUBLIC_EXPORT FrameHeader { ...@@ -110,20 +112,19 @@ class ASH_PUBLIC_EXPORT FrameHeader {
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();
...@@ -138,19 +139,20 @@ class ASH_PUBLIC_EXPORT FrameHeader { ...@@ -138,19 +139,20 @@ class ASH_PUBLIC_EXPORT FrameHeader {
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,31 +34,39 @@ void PaintThemedFrame(gfx::Canvas* canvas, ...@@ -34,31 +34,39 @@ 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. // When no images are used, just draw a color, with the animation |alpha|
// applied.
if (frame_image.isNull() && frame_overlay_image.isNull()) { if (frame_image.isNull() && frame_overlay_image.isNull()) {
canvas->DrawColor(opaque_background_color); // We use kPlus blending mode so that between the active and inactive
// 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. // to draw all 2-3 components into a single layer then apply the alpha to them
// together.
const bool blending_required = const bool blending_required =
!frame_image.isNull() && !frame_overlay_image.isNull(); alpha < 0xFF || (!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. // behind them. Here the |alpha| will be applied to the background color by
// 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,
...@@ -81,6 +89,7 @@ void PaintFrameImagesInRoundRect(gfx::Canvas* canvas, ...@@ -81,6 +89,7 @@ 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,
...@@ -100,7 +109,7 @@ void PaintFrameImagesInRoundRect(gfx::Canvas* canvas, ...@@ -100,7 +109,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); bounds, image_inset_x, image_inset_y, alpha);
} }
} // namespace } // namespace
...@@ -138,7 +147,8 @@ int BrowserFrameHeaderAsh::GetThemeBackgroundXInset() { ...@@ -138,7 +147,8 @@ int BrowserFrameHeaderAsh::GetThemeBackgroundXInset() {
// BrowserFrameHeaderAsh, protected: // BrowserFrameHeaderAsh, protected:
void BrowserFrameHeaderAsh::DoPaintHeader(gfx::Canvas* canvas) { void BrowserFrameHeaderAsh::DoPaintHeader(gfx::Canvas* canvas) {
PaintFrameImages(canvas); PaintFrameImages(canvas, false /* active */);
PaintFrameImages(canvas, true /* active */);
PaintTitleBar(canvas); PaintTitleBar(canvas);
} }
...@@ -168,8 +178,13 @@ void BrowserFrameHeaderAsh::UpdateFrameColors() { ...@@ -168,8 +178,13 @@ void BrowserFrameHeaderAsh::UpdateFrameColors() {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// BrowserFrameHeaderAsh, private: // BrowserFrameHeaderAsh, private:
void BrowserFrameHeaderAsh::PaintFrameImages(gfx::Canvas* canvas) { void BrowserFrameHeaderAsh::PaintFrameImages(gfx::Canvas* canvas, bool active) {
const bool active = mode() == Mode::MODE_ACTIVE; int alpha = activation_animation().CurrentValueBetween(0, 0xFF);
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);
...@@ -186,5 +201,5 @@ void BrowserFrameHeaderAsh::PaintFrameImages(gfx::Canvas* canvas) { ...@@ -186,5 +201,5 @@ void BrowserFrameHeaderAsh::PaintFrameImages(gfx::Canvas* canvas) {
appearance_provider_->GetFrameHeaderColor(active), appearance_provider_->GetFrameHeaderColor(active),
GetPaintedBounds(), GetThemeBackgroundXInset(), GetPaintedBounds(), GetThemeBackgroundXInset(),
appearance_provider_->GetFrameHeaderImageYInset(), appearance_provider_->GetFrameHeaderImageYInset(),
corner_radius); alpha, corner_radius);
} }
...@@ -49,8 +49,9 @@ class BrowserFrameHeaderAsh : public ash::FrameHeader { ...@@ -49,8 +49,9 @@ class BrowserFrameHeaderAsh : public ash::FrameHeader {
SkColor GetCurrentFrameColor() const override; SkColor GetCurrentFrameColor() const override;
private: private:
// Paints the frame image. // Paints the frame image for the |active| state based on the current value of
void PaintFrameImages(gfx::Canvas* canvas); // the activation animation.
void PaintFrameImages(gfx::Canvas* canvas, bool active);
AppearanceProvider* appearance_provider_ = nullptr; AppearanceProvider* appearance_provider_ = nullptr;
......
...@@ -326,8 +326,11 @@ void BrowserNonClientFrameViewAsh::OnPaint(gfx::Canvas* canvas) { ...@@ -326,8 +326,11 @@ 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); frame_header_->PaintHeader(canvas, header_mode);
} }
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