Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: ui/wm/core/shadow.cc

Issue 2562143002: Update WM shadow transitions. (Closed)
Patch Set: review feedback Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/wm/core/shadow.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/wm/core/shadow.h" 5 #include "ui/wm/core/shadow.h"
6 6
7 #include "base/lazy_instance.h" 7 #include "base/lazy_instance.h"
8 #include "ui/base/resource/resource_bundle.h" 8 #include "ui/base/resource/resource_bundle.h"
9 #include "ui/compositor/layer.h" 9 #include "ui/compositor/layer.h"
10 #include "ui/compositor/scoped_layer_animation_settings.h" 10 #include "ui/compositor/scoped_layer_animation_settings.h"
11 #include "ui/gfx/geometry/insets.h" 11 #include "ui/gfx/geometry/insets.h"
12 #include "ui/gfx/image/image_skia_operations.h" 12 #include "ui/gfx/image/image_skia_operations.h"
13 13
14 namespace wm { 14 namespace wm {
15 15
16 namespace { 16 namespace {
17 17
18 // The opacity used for active shadow when animating between
19 // inactive/active shadow.
20 const float kInactiveShadowAnimationOpacity = 0.2f;
21
22 // Rounded corners are overdrawn on top of the window's content layer, 18 // Rounded corners are overdrawn on top of the window's content layer,
23 // we need to exclude them from the occlusion area. 19 // we need to exclude them from the occlusion area.
24 const int kRoundedCornerRadius = 2; 20 const int kRoundedCornerRadius = 2;
25 21
26 // Duration for opacity animation in milliseconds. 22 // Duration for opacity animation in milliseconds.
27 const int kShadowAnimationDurationMs = 100; 23 const int kShadowAnimationDurationMs = 100;
28 24
29 struct ShadowDetails { 25 struct ShadowDetails {
30 // Description of the shadows. 26 // Description of the shadows.
31 gfx::ShadowValues values; 27 gfx::ShadowValues values;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 } 62 }
67 63
68 } // namespace 64 } // namespace
69 65
70 Shadow::Shadow() {} 66 Shadow::Shadow() {}
71 67
72 Shadow::~Shadow() {} 68 Shadow::~Shadow() {}
73 69
74 void Shadow::Init(Style style) { 70 void Shadow::Init(Style style) {
75 style_ = style; 71 style_ = style;
76
77 layer_.reset(new ui::Layer(ui::LAYER_NOT_DRAWN)); 72 layer_.reset(new ui::Layer(ui::LAYER_NOT_DRAWN));
78 shadow_layer_.reset(new ui::Layer(ui::LAYER_NINE_PATCH)); 73 RecreateShadowLayer();
79 layer()->Add(shadow_layer_.get());
80
81 UpdateImagesForStyle();
82 shadow_layer_->set_name("Shadow");
83 shadow_layer_->SetVisible(true);
84 shadow_layer_->SetFillsBoundsOpaquely(false);
85 } 74 }
86 75
87 void Shadow::SetContentBounds(const gfx::Rect& content_bounds) { 76 void Shadow::SetContentBounds(const gfx::Rect& content_bounds) {
77 // When the window moves but doesn't change size, this is a no-op. (The
78 // origin stays the same in this case.)
79 if (content_bounds == content_bounds_)
80 return;
81
88 content_bounds_ = content_bounds; 82 content_bounds_ = content_bounds;
89 UpdateLayerBounds(); 83 UpdateLayerBounds();
90 } 84 }
91 85
92 void Shadow::SetStyle(Style style) { 86 void Shadow::SetStyle(Style style) {
93 if (style_ == style) 87 if (style_ == style)
94 return; 88 return;
95 89
96 Style old_style = style_;
97 style_ = style; 90 style_ = style;
98 91
99 // Stop waiting for any as yet unfinished implicit animations. 92 // Stop waiting for any as yet unfinished implicit animations.
100 StopObservingImplicitAnimations(); 93 StopObservingImplicitAnimations();
101 94
102 // If we're switching to or from the small style, don't bother with 95 // The old shadow layer is the new fading out layer.
103 // animations. 96 DCHECK(shadow_layer_);
104 if (style == STYLE_SMALL || old_style == STYLE_SMALL) { 97 fading_layer_ = std::move(shadow_layer_);
105 UpdateImagesForStyle(); 98 RecreateShadowLayer();
106 // Make sure the shadow is fully opaque. 99 shadow_layer_->SetOpacity(0.f);
107 shadow_layer_->SetOpacity(1.0f);
108 return;
109 }
110 100
111 // If we're becoming active, switch images now. Because the inactive image 101 {
112 // has a very low opacity the switch isn't noticeable and this approach 102 // Observe the fade out animation so we can clean up the layer when done.
113 // allows us to use only a single set of shadow images at a time. 103 ui::ScopedLayerAnimationSettings settings(fading_layer_->GetAnimator());
114 if (style == STYLE_ACTIVE) { 104 settings.AddObserver(this);
115 UpdateImagesForStyle(); 105 settings.SetTransitionDuration(
116 // Opacity was baked into inactive image, start opacity low to match. 106 base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs));
117 shadow_layer_->SetOpacity(kInactiveShadowAnimationOpacity); 107 fading_layer_->SetOpacity(0.f);
118 } 108 }
119 109
120 { 110 {
121 // Property sets within this scope will be implicitly animated. 111 // We don't care to observe this one.
122 ui::ScopedLayerAnimationSettings settings(shadow_layer_->GetAnimator()); 112 ui::ScopedLayerAnimationSettings settings(shadow_layer_->GetAnimator());
123 settings.AddObserver(this);
124 settings.SetTransitionDuration( 113 settings.SetTransitionDuration(
125 base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs)); 114 base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs));
126 switch (style_) { 115 shadow_layer_->SetOpacity(1.f);
127 case STYLE_ACTIVE:
128 // Animate the active shadow from kInactiveShadowAnimationOpacity to
129 // 1.0f.
130 shadow_layer_->SetOpacity(1.0f);
131 break;
132 case STYLE_INACTIVE:
133 // The opacity will be reset to 1.0f when animation is completed.
134 shadow_layer_->SetOpacity(kInactiveShadowAnimationOpacity);
135 break;
136 default:
137 NOTREACHED() << "Unhandled style " << style_;
138 break;
139 }
140 } 116 }
141 } 117 }
142 118
143 void Shadow::OnImplicitAnimationsCompleted() { 119 void Shadow::OnImplicitAnimationsCompleted() {
144 // If we just finished going inactive, switch images. This doesn't cause 120 fading_layer_.reset();
145 // a visual pop because the inactive image opacity is so low. 121 // The size needed for layer() may be smaller now that |fading_layer_| is
146 if (style_ == STYLE_INACTIVE) { 122 // removed.
147 UpdateImagesForStyle(); 123 UpdateLayerBounds();
148 // Opacity is baked into inactive image, so set fully opaque.
149 shadow_layer_->SetOpacity(1.0f);
150 }
151 } 124 }
152 125
153 void Shadow::UpdateImagesForStyle() { 126 void Shadow::RecreateShadowLayer() {
127 shadow_layer_.reset(new ui::Layer(ui::LAYER_NINE_PATCH));
128 shadow_layer_->set_name("Shadow");
129 shadow_layer_->SetVisible(true);
130 shadow_layer_->SetFillsBoundsOpaquely(false);
131 layer()->Add(shadow_layer_.get());
132
154 const ShadowDetails& details = GetDetailsForElevation(ElevationForStyle()); 133 const ShadowDetails& details = GetDetailsForElevation(ElevationForStyle());
155 shadow_layer_->UpdateNinePatchLayerImage(details.ninebox_image); 134 shadow_layer_->UpdateNinePatchLayerImage(details.ninebox_image);
156 // The ninebox grid is defined in terms of the image size. The shadow blurs in 135 // The ninebox grid is defined in terms of the image size. The shadow blurs in
157 // both inward and outward directions from the edge of the contents, so the 136 // both inward and outward directions from the edge of the contents, so the
158 // aperture goes further inside the image than the shadow margins (which 137 // aperture goes further inside the image than the shadow margins (which
159 // represent exterior blur). 138 // represent exterior blur).
160 gfx::Rect aperture(details.ninebox_image.size()); 139 gfx::Rect aperture(details.ninebox_image.size());
161 gfx::Insets blur_region = gfx::ShadowValue::GetBlurRegion(details.values) + 140 gfx::Insets blur_region = gfx::ShadowValue::GetBlurRegion(details.values) +
162 gfx::Insets(kRoundedCornerRadius); 141 gfx::Insets(kRoundedCornerRadius);
163 aperture.Inset(blur_region); 142 aperture.Inset(blur_region);
164 shadow_layer_->UpdateNinePatchLayerAperture(aperture); 143 shadow_layer_->UpdateNinePatchLayerAperture(aperture);
165 UpdateLayerBounds(); 144 UpdateLayerBounds();
166 } 145 }
167 146
168 void Shadow::UpdateLayerBounds() { 147 void Shadow::UpdateLayerBounds() {
169 const ShadowDetails& details = GetDetailsForElevation(ElevationForStyle()); 148 const ShadowDetails& details = GetDetailsForElevation(ElevationForStyle());
170 // Shadow margins are negative, so this expands outwards from 149 // Shadow margins are negative, so this expands outwards from
171 // |content_bounds_|. 150 // |content_bounds_|.
172 const gfx::Insets margins = gfx::ShadowValue::GetMargin(details.values); 151 const gfx::Insets margins = gfx::ShadowValue::GetMargin(details.values);
173 gfx::Rect layer_bounds = content_bounds_; 152 gfx::Rect new_layer_bounds = content_bounds_;
174 layer_bounds.Inset(margins); 153 new_layer_bounds.Inset(margins);
175 layer()->SetBounds(layer_bounds); 154 gfx::Rect shadow_layer_bounds(new_layer_bounds.size());
176 const gfx::Rect shadow_layer_bounds(layer_bounds.size()); 155
156 // When there's an old shadow fading out, the bounds of layer() have to be
157 // big enough to encompass both shadows.
158 if (fading_layer_) {
159 const gfx::Rect old_layer_bounds = layer()->bounds();
160 gfx::Rect combined_layer_bounds = old_layer_bounds;
161 combined_layer_bounds.Union(new_layer_bounds);
162 layer()->SetBounds(combined_layer_bounds);
163
164 // If this is reached via SetContentBounds, we might hypothetically need
165 // to change the size of the fading layer, but the fade is so fast it's
166 // not really an issue.
167 gfx::Rect fading_layer_bounds(fading_layer_->bounds());
168 fading_layer_bounds.Offset(old_layer_bounds.origin() -
169 combined_layer_bounds.origin());
170 fading_layer_->SetBounds(fading_layer_bounds);
171
172 shadow_layer_bounds.Offset(new_layer_bounds.origin() -
173 combined_layer_bounds.origin());
174 } else {
175 layer()->SetBounds(new_layer_bounds);
176 }
177
177 shadow_layer_->SetBounds(shadow_layer_bounds); 178 shadow_layer_->SetBounds(shadow_layer_bounds);
178 179
179 // Occlude the region inside the bounding box. Occlusion uses shadow layer 180 // Occlude the region inside the bounding box. Occlusion uses shadow layer
180 // space. See nine_patch_layer.h for more context on what's going on here. 181 // space. See nine_patch_layer.h for more context on what's going on here.
181 gfx::Rect occlusion_bounds = shadow_layer_bounds; 182 gfx::Rect occlusion_bounds(shadow_layer_bounds.size());
182 occlusion_bounds.Inset(-margins + gfx::Insets(kRoundedCornerRadius)); 183 occlusion_bounds.Inset(-margins + gfx::Insets(kRoundedCornerRadius));
183 shadow_layer_->UpdateNinePatchOcclusion(occlusion_bounds); 184 shadow_layer_->UpdateNinePatchOcclusion(occlusion_bounds);
184 185
185 // The border is more or less the same inset as the aperture, but can be no 186 // The border is more or less the same inset as the aperture, but can be no
186 // larger than the shadow layer. When the shadow layer is too small, shrink 187 // larger than the shadow layer. When the shadow layer is too small, shrink
187 // the dimensions proportionally. 188 // the dimensions proportionally.
188 gfx::Insets blur_region = gfx::ShadowValue::GetBlurRegion(details.values) + 189 gfx::Insets blur_region = gfx::ShadowValue::GetBlurRegion(details.values) +
189 gfx::Insets(kRoundedCornerRadius); 190 gfx::Insets(kRoundedCornerRadius);
190 int border_w = std::min(blur_region.width(), shadow_layer_bounds.width()); 191 int border_w = std::min(blur_region.width(), shadow_layer_bounds.width());
191 int border_x = border_w * blur_region.left() / blur_region.width(); 192 int border_x = border_w * blur_region.left() / blur_region.width();
(...skipping 10 matching lines...) Expand all
202 case STYLE_INACTIVE: 203 case STYLE_INACTIVE:
203 return 8; 204 return 8;
204 case STYLE_SMALL: 205 case STYLE_SMALL:
205 return 6; 206 return 6;
206 } 207 }
207 NOTREACHED(); 208 NOTREACHED();
208 return 0; 209 return 0;
209 } 210 }
210 211
211 } // namespace wm 212 } // namespace wm
OLDNEW
« no previous file with comments | « ui/wm/core/shadow.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698