Chromium Code Reviews| Index: ui/wm/core/shadow.cc |
| diff --git a/ui/wm/core/shadow.cc b/ui/wm/core/shadow.cc |
| index 1eb0ac6b4e3523c4890354f1efa88f77fc89bc21..1f7a299b29820e95810ddffb96efc3220be74769 100644 |
| --- a/ui/wm/core/shadow.cc |
| +++ b/ui/wm/core/shadow.cc |
| @@ -5,9 +5,10 @@ |
| #include "ui/wm/core/shadow.h" |
| #include "grit/ui_resources.h" |
| +#include "third_party/skia/include/core/SkBitmap.h" |
| #include "ui/base/resource/resource_bundle.h" |
| +#include "ui/compositor/layer.h" |
| #include "ui/compositor/scoped_layer_animation_settings.h" |
| -#include "ui/wm/core/image_grid.h" |
| namespace { |
| @@ -16,10 +17,17 @@ const float kActiveShadowOpacity = 1.0f; |
| const float kInactiveShadowOpacity = 0.2f; |
| const float kSmallShadowOpacity = 1.0f; |
| +// Shadow aperture for different styles. |
| +// Note that this may be greater than interior inset to allow shadows with |
| +// curved corners that extend inwards beyond a window's borders. |
| +const int kActiveInteriorAperture = 134; |
| +const int kInactiveInteriorAperture = 134; |
| +const int kSmallInteriorAperture = 9; |
| + |
| // Interior inset for different styles. |
| -const int kActiveInteriorInset = 0; |
| -const int kInactiveInteriorInset = 0; |
| -const int kSmallInteriorInset = 5; |
| +const int kActiveInteriorInset = 64; |
| +const int kInactiveInteriorInset = 64; |
| +const int kSmallInteriorInset = 4; |
| // Duration for opacity animation in milliseconds. |
| const int kShadowAnimationDurationMs = 100; |
| @@ -36,6 +44,18 @@ float GetOpacityForStyle(wm::Shadow::Style style) { |
| return 1.0f; |
| } |
| +int GetShadowApertureForStyle(wm::Shadow::Style style) { |
| + switch (style) { |
| + case wm::Shadow::STYLE_ACTIVE: |
| + return kActiveInteriorAperture; |
| + case wm::Shadow::STYLE_INACTIVE: |
| + return kInactiveInteriorAperture; |
| + case wm::Shadow::STYLE_SMALL: |
| + return kSmallInteriorAperture; |
| + } |
| + return 0; |
| +} |
| + |
| int GetInteriorInsetForStyle(wm::Shadow::Style style) { |
| switch (style) { |
| case wm::Shadow::STYLE_ACTIVE: |
| @@ -60,19 +80,18 @@ Shadow::~Shadow() { |
| void Shadow::Init(Style style) { |
| style_ = style; |
| - image_grid_.reset(new ImageGrid); |
| + |
| + layer_.reset(new ui::Layer()); |
| + layer()->SetShowNinePatch(); |
| UpdateImagesForStyle(); |
| - image_grid_->layer()->set_name("Shadow"); |
| - image_grid_->layer()->SetOpacity(GetOpacityForStyle(style_)); |
| + layer()->set_name("Shadow"); |
| + layer()->SetVisible(true); |
| + layer()->SetOpacity(GetOpacityForStyle(style_)); |
| } |
| void Shadow::SetContentBounds(const gfx::Rect& content_bounds) { |
| content_bounds_ = content_bounds; |
| - UpdateImageGridBounds(); |
| -} |
| - |
| -ui::Layer* Shadow::layer() const { |
| - return image_grid_->layer(); |
| + UpdateImageBounds(); |
| } |
| void Shadow::SetStyle(Style style) { |
| @@ -89,7 +108,7 @@ void Shadow::SetStyle(Style style) { |
| // animations. |
| if (style == STYLE_SMALL || old_style == STYLE_SMALL) { |
| UpdateImagesForStyle(); |
| - image_grid_->layer()->SetOpacity(GetOpacityForStyle(style)); |
| + layer()->SetOpacity(GetOpacityForStyle(style)); |
| return; |
| } |
| @@ -99,7 +118,7 @@ void Shadow::SetStyle(Style style) { |
| if (style == STYLE_ACTIVE) { |
| UpdateImagesForStyle(); |
| // Opacity was baked into inactive image, start opacity low to match. |
| - image_grid_->layer()->SetOpacity(kInactiveShadowOpacity); |
| + layer()->SetOpacity(kInactiveShadowOpacity); |
| } |
| { |
| @@ -110,10 +129,10 @@ void Shadow::SetStyle(Style style) { |
| base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs)); |
| switch (style_) { |
| case STYLE_ACTIVE: |
| - image_grid_->layer()->SetOpacity(kActiveShadowOpacity); |
| + layer()->SetOpacity(kActiveShadowOpacity); |
| break; |
| case STYLE_INACTIVE: |
| - image_grid_->layer()->SetOpacity(kInactiveShadowOpacity); |
| + layer()->SetOpacity(kInactiveShadowOpacity); |
| break; |
| default: |
| NOTREACHED() << "Unhandled style " << style_; |
| @@ -128,66 +147,54 @@ void Shadow::OnImplicitAnimationsCompleted() { |
| if (style_ == STYLE_INACTIVE) { |
| UpdateImagesForStyle(); |
| // Opacity is baked into inactive image, so set fully opaque. |
| - image_grid_->layer()->SetOpacity(1.0f); |
| + layer()->SetOpacity(1.0f); |
| } |
| } |
| void Shadow::UpdateImagesForStyle() { |
| ResourceBundle& res = ResourceBundle::GetSharedInstance(); |
| + gfx::Image image; |
| switch (style_) { |
| case STYLE_ACTIVE: |
| - image_grid_->SetImages( |
| - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_TOP_LEFT), |
|
sky
2014/07/14 15:30:06
This is the more common style used in chrome. See
hshi1
2014/07/14 21:23:37
While I agree of the advantage of separate images,
oshima
2014/07/14 22:02:32
I actually prefer single image and would like nine
|
| - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_TOP), |
| - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_TOP_RIGHT), |
| - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_LEFT), |
| - NULL, |
| - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_RIGHT), |
| - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_BOTTOM_LEFT), |
| - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_BOTTOM), |
| - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_BOTTOM_RIGHT)); |
| + image = res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE); |
| break; |
| case STYLE_INACTIVE: |
| - image_grid_->SetImages( |
| - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_TOP_LEFT), |
| - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_TOP), |
| - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_TOP_RIGHT), |
| - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_LEFT), |
| - NULL, |
| - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_RIGHT), |
| - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_BOTTOM_LEFT), |
| - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_BOTTOM), |
| - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_BOTTOM_RIGHT)); |
| + image = res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE); |
| break; |
| case STYLE_SMALL: |
| - image_grid_->SetImages( |
| - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_LEFT), |
| - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP), |
| - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_RIGHT), |
| - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_LEFT), |
| - NULL, |
| - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_RIGHT), |
| - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_LEFT), |
| - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM), |
| - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_RIGHT)); |
| + image = res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL); |
| break; |
| default: |
| NOTREACHED() << "Unhandled style " << style_; |
| break; |
| } |
| + // Calculate shadow aperture and border for style. |
| + int shadow_aperture = GetShadowApertureForStyle(style_); |
| + gfx::Rect aperture(shadow_aperture, |
| + shadow_aperture, |
| + image.Width() - shadow_aperture * 2, |
| + image.Height() - shadow_aperture * 2); |
| + gfx::Rect border(shadow_aperture, |
| + shadow_aperture, |
| + shadow_aperture * 2, |
| + shadow_aperture * 2); |
| + |
| + // Update nine-patch layer image with aperture and border. |
| + layer()->UpdateNinePatchBitmap(image.AsBitmap(), aperture, border); |
| + |
| // Update interior inset for style. |
| interior_inset_ = GetInteriorInsetForStyle(style_); |
| // Image sizes may have changed. |
| - UpdateImageGridBounds(); |
| + UpdateImageBounds(); |
| } |
| -void Shadow::UpdateImageGridBounds() { |
| +void Shadow::UpdateImageBounds() { |
| // Update bounds based on content bounds and image sizes. |
| - gfx::Rect image_grid_bounds = content_bounds_; |
| - image_grid_bounds.Inset(interior_inset_, interior_inset_); |
| - image_grid_->SetContentBounds(image_grid_bounds); |
| + gfx::Rect image_bounds = content_bounds_; |
| + image_bounds.Inset(-interior_inset_, -interior_inset_); |
| + layer()->SetBounds(image_bounds); |
| } |
| } // namespace wm |