Commit 77932377 authored by estade's avatar estade Committed by Commit bot

Update WM shadow transitions.

When changing from one shadow type to another, cross fade the two.

BUG=608852

Review-Url: https://codereview.chromium.org/2562143002
Cr-Commit-Position: refs/heads/master@{#437956}
parent b171ff9c
...@@ -15,10 +15,6 @@ namespace wm { ...@@ -15,10 +15,6 @@ namespace wm {
namespace { namespace {
// The opacity used for active shadow when animating between
// inactive/active shadow.
const float kInactiveShadowAnimationOpacity = 0.2f;
// Rounded corners are overdrawn on top of the window's content layer, // Rounded corners are overdrawn on top of the window's content layer,
// we need to exclude them from the occlusion area. // we need to exclude them from the occlusion area.
const int kRoundedCornerRadius = 2; const int kRoundedCornerRadius = 2;
...@@ -73,18 +69,16 @@ Shadow::~Shadow() {} ...@@ -73,18 +69,16 @@ Shadow::~Shadow() {}
void Shadow::Init(Style style) { void Shadow::Init(Style style) {
style_ = style; style_ = style;
layer_.reset(new ui::Layer(ui::LAYER_NOT_DRAWN)); layer_.reset(new ui::Layer(ui::LAYER_NOT_DRAWN));
shadow_layer_.reset(new ui::Layer(ui::LAYER_NINE_PATCH)); RecreateShadowLayer();
layer()->Add(shadow_layer_.get());
UpdateImagesForStyle();
shadow_layer_->set_name("Shadow");
shadow_layer_->SetVisible(true);
shadow_layer_->SetFillsBoundsOpaquely(false);
} }
void Shadow::SetContentBounds(const gfx::Rect& content_bounds) { void Shadow::SetContentBounds(const gfx::Rect& content_bounds) {
// When the window moves but doesn't change size, this is a no-op. (The
// origin stays the same in this case.)
if (content_bounds == content_bounds_)
return;
content_bounds_ = content_bounds; content_bounds_ = content_bounds;
UpdateLayerBounds(); UpdateLayerBounds();
} }
...@@ -93,64 +87,49 @@ void Shadow::SetStyle(Style style) { ...@@ -93,64 +87,49 @@ void Shadow::SetStyle(Style style) {
if (style_ == style) if (style_ == style)
return; return;
Style old_style = style_;
style_ = style; style_ = style;
// Stop waiting for any as yet unfinished implicit animations. // Stop waiting for any as yet unfinished implicit animations.
StopObservingImplicitAnimations(); StopObservingImplicitAnimations();
// If we're switching to or from the small style, don't bother with // The old shadow layer is the new fading out layer.
// animations. DCHECK(shadow_layer_);
if (style == STYLE_SMALL || old_style == STYLE_SMALL) { fading_layer_ = std::move(shadow_layer_);
UpdateImagesForStyle(); RecreateShadowLayer();
// Make sure the shadow is fully opaque. shadow_layer_->SetOpacity(0.f);
shadow_layer_->SetOpacity(1.0f);
return;
}
// If we're becoming active, switch images now. Because the inactive image {
// has a very low opacity the switch isn't noticeable and this approach // Observe the fade out animation so we can clean up the layer when done.
// allows us to use only a single set of shadow images at a time. ui::ScopedLayerAnimationSettings settings(fading_layer_->GetAnimator());
if (style == STYLE_ACTIVE) { settings.AddObserver(this);
UpdateImagesForStyle(); settings.SetTransitionDuration(
// Opacity was baked into inactive image, start opacity low to match. base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs));
shadow_layer_->SetOpacity(kInactiveShadowAnimationOpacity); fading_layer_->SetOpacity(0.f);
} }
{ {
// Property sets within this scope will be implicitly animated. // We don't care to observe this one.
ui::ScopedLayerAnimationSettings settings(shadow_layer_->GetAnimator()); ui::ScopedLayerAnimationSettings settings(shadow_layer_->GetAnimator());
settings.AddObserver(this);
settings.SetTransitionDuration( settings.SetTransitionDuration(
base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs)); base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs));
switch (style_) { shadow_layer_->SetOpacity(1.f);
case STYLE_ACTIVE:
// Animate the active shadow from kInactiveShadowAnimationOpacity to
// 1.0f.
shadow_layer_->SetOpacity(1.0f);
break;
case STYLE_INACTIVE:
// The opacity will be reset to 1.0f when animation is completed.
shadow_layer_->SetOpacity(kInactiveShadowAnimationOpacity);
break;
default:
NOTREACHED() << "Unhandled style " << style_;
break;
}
} }
} }
void Shadow::OnImplicitAnimationsCompleted() { void Shadow::OnImplicitAnimationsCompleted() {
// If we just finished going inactive, switch images. This doesn't cause fading_layer_.reset();
// a visual pop because the inactive image opacity is so low. // The size needed for layer() may be smaller now that |fading_layer_| is
if (style_ == STYLE_INACTIVE) { // removed.
UpdateImagesForStyle(); UpdateLayerBounds();
// Opacity is baked into inactive image, so set fully opaque.
shadow_layer_->SetOpacity(1.0f);
}
} }
void Shadow::UpdateImagesForStyle() { void Shadow::RecreateShadowLayer() {
shadow_layer_.reset(new ui::Layer(ui::LAYER_NINE_PATCH));
shadow_layer_->set_name("Shadow");
shadow_layer_->SetVisible(true);
shadow_layer_->SetFillsBoundsOpaquely(false);
layer()->Add(shadow_layer_.get());
const ShadowDetails& details = GetDetailsForElevation(ElevationForStyle()); const ShadowDetails& details = GetDetailsForElevation(ElevationForStyle());
shadow_layer_->UpdateNinePatchLayerImage(details.ninebox_image); shadow_layer_->UpdateNinePatchLayerImage(details.ninebox_image);
// The ninebox grid is defined in terms of the image size. The shadow blurs in // The ninebox grid is defined in terms of the image size. The shadow blurs in
...@@ -170,15 +149,37 @@ void Shadow::UpdateLayerBounds() { ...@@ -170,15 +149,37 @@ void Shadow::UpdateLayerBounds() {
// Shadow margins are negative, so this expands outwards from // Shadow margins are negative, so this expands outwards from
// |content_bounds_|. // |content_bounds_|.
const gfx::Insets margins = gfx::ShadowValue::GetMargin(details.values); const gfx::Insets margins = gfx::ShadowValue::GetMargin(details.values);
gfx::Rect layer_bounds = content_bounds_; gfx::Rect new_layer_bounds = content_bounds_;
layer_bounds.Inset(margins); new_layer_bounds.Inset(margins);
layer()->SetBounds(layer_bounds); gfx::Rect shadow_layer_bounds(new_layer_bounds.size());
const gfx::Rect shadow_layer_bounds(layer_bounds.size());
// When there's an old shadow fading out, the bounds of layer() have to be
// big enough to encompass both shadows.
if (fading_layer_) {
const gfx::Rect old_layer_bounds = layer()->bounds();
gfx::Rect combined_layer_bounds = old_layer_bounds;
combined_layer_bounds.Union(new_layer_bounds);
layer()->SetBounds(combined_layer_bounds);
// If this is reached via SetContentBounds, we might hypothetically need
// to change the size of the fading layer, but the fade is so fast it's
// not really an issue.
gfx::Rect fading_layer_bounds(fading_layer_->bounds());
fading_layer_bounds.Offset(old_layer_bounds.origin() -
combined_layer_bounds.origin());
fading_layer_->SetBounds(fading_layer_bounds);
shadow_layer_bounds.Offset(new_layer_bounds.origin() -
combined_layer_bounds.origin());
} else {
layer()->SetBounds(new_layer_bounds);
}
shadow_layer_->SetBounds(shadow_layer_bounds); shadow_layer_->SetBounds(shadow_layer_bounds);
// Occlude the region inside the bounding box. Occlusion uses shadow layer // Occlude the region inside the bounding box. Occlusion uses shadow layer
// space. See nine_patch_layer.h for more context on what's going on here. // space. See nine_patch_layer.h for more context on what's going on here.
gfx::Rect occlusion_bounds = shadow_layer_bounds; gfx::Rect occlusion_bounds(shadow_layer_bounds.size());
occlusion_bounds.Inset(-margins + gfx::Insets(kRoundedCornerRadius)); occlusion_bounds.Inset(-margins + gfx::Insets(kRoundedCornerRadius));
shadow_layer_->UpdateNinePatchOcclusion(occlusion_bounds); shadow_layer_->UpdateNinePatchOcclusion(occlusion_bounds);
......
...@@ -62,8 +62,8 @@ class WM_EXPORT Shadow : public ui::ImplicitAnimationObserver { ...@@ -62,8 +62,8 @@ class WM_EXPORT Shadow : public ui::ImplicitAnimationObserver {
void OnImplicitAnimationsCompleted() override; void OnImplicitAnimationsCompleted() override;
private: private:
// Updates the shadow images to the current |style_|. // Updates the shadow layer and its image to the current |style_|.
void UpdateImagesForStyle(); void RecreateShadowLayer();
// Updates the shadow layer bounds based on the inteior inset and the current // Updates the shadow layer bounds based on the inteior inset and the current
// |content_bounds_|. // |content_bounds_|.
...@@ -84,6 +84,10 @@ class WM_EXPORT Shadow : public ui::ImplicitAnimationObserver { ...@@ -84,6 +84,10 @@ class WM_EXPORT Shadow : public ui::ImplicitAnimationObserver {
// The actual shadow layer corresponding to a cc::NinePatchLayer. // The actual shadow layer corresponding to a cc::NinePatchLayer.
std::unique_ptr<ui::Layer> shadow_layer_; std::unique_ptr<ui::Layer> shadow_layer_;
// When the style changes, the old shadow cross-fades with the new one.
// When non-null, this is an old |shadow_layer_| that's being animated out.
std::unique_ptr<ui::Layer> fading_layer_;
// Bounds of the content that the shadow encloses. // Bounds of the content that the shadow encloses.
gfx::Rect content_bounds_; gfx::Rect content_bounds_;
......
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