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

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

Issue 2562143002: Update WM shadow transitions. (Closed)
Patch Set: 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));
79 layer()->Add(shadow_layer_.get());
80
81 UpdateImagesForStyle(); 73 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 UpdateImagesForStyle();
James Cook 2016/12/09 23:56:43 Maybe this should be renamed to RecreateLayerForSt
Evan Stade 2016/12/10 00:07:02 Done.
106 // Make sure the shadow is fully opaque. 99 shadow_layer_->SetOpacity(0.0);
James Cook 2016/12/09 23:56:43 nit: SetOpacity takes a float, I prefer 0.f or 0.0
Evan Stade 2016/12/10 00:07:02 Done.
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.0);
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.0);
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 UpdateLayerBounds();
James Cook 2016/12/09 23:56:43 nit: might be nice to comment why this is necessar
Evan Stade 2016/12/10 00:07:02 Done.
146 if (style_ == STYLE_INACTIVE) {
147 UpdateImagesForStyle();
148 // Opacity is baked into inactive image, so set fully opaque.
149 shadow_layer_->SetOpacity(1.0f);
150 }
151 } 122 }
152 123
153 void Shadow::UpdateImagesForStyle() { 124 void Shadow::UpdateImagesForStyle() {
125 shadow_layer_.reset(new ui::Layer(ui::LAYER_NINE_PATCH));
126 shadow_layer_->set_name("Shadow");
127 shadow_layer_->SetVisible(true);
128 shadow_layer_->SetFillsBoundsOpaquely(false);
129 layer()->Add(shadow_layer_.get());
130
154 const ShadowDetails& details = GetDetailsForElevation(ElevationForStyle()); 131 const ShadowDetails& details = GetDetailsForElevation(ElevationForStyle());
155 shadow_layer_->UpdateNinePatchLayerImage(details.ninebox_image); 132 shadow_layer_->UpdateNinePatchLayerImage(details.ninebox_image);
156 // The ninebox grid is defined in terms of the image size. The shadow blurs in 133 // 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 134 // 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 135 // aperture goes further inside the image than the shadow margins (which
159 // represent exterior blur). 136 // represent exterior blur).
160 gfx::Rect aperture(details.ninebox_image.size()); 137 gfx::Rect aperture(details.ninebox_image.size());
161 gfx::Insets blur_region = gfx::ShadowValue::GetBlurRegion(details.values) + 138 gfx::Insets blur_region = gfx::ShadowValue::GetBlurRegion(details.values) +
162 gfx::Insets(kRoundedCornerRadius); 139 gfx::Insets(kRoundedCornerRadius);
163 aperture.Inset(blur_region); 140 aperture.Inset(blur_region);
164 shadow_layer_->UpdateNinePatchLayerAperture(aperture); 141 shadow_layer_->UpdateNinePatchLayerAperture(aperture);
165 UpdateLayerBounds(); 142 UpdateLayerBounds();
166 } 143 }
167 144
168 void Shadow::UpdateLayerBounds() { 145 void Shadow::UpdateLayerBounds() {
169 const ShadowDetails& details = GetDetailsForElevation(ElevationForStyle()); 146 const ShadowDetails& details = GetDetailsForElevation(ElevationForStyle());
170 // Shadow margins are negative, so this expands outwards from 147 // Shadow margins are negative, so this expands outwards from
171 // |content_bounds_|. 148 // |content_bounds_|.
172 const gfx::Insets margins = gfx::ShadowValue::GetMargin(details.values); 149 const gfx::Insets margins = gfx::ShadowValue::GetMargin(details.values);
173 gfx::Rect layer_bounds = content_bounds_; 150 gfx::Rect new_layer_bounds = content_bounds_;
James Cook 2016/12/09 23:56:43 Thanks for renaming this. |new_layer_bounds| is cl
Evan Stade 2016/12/10 00:07:02 pleasure is mine
174 layer_bounds.Inset(margins); 151 new_layer_bounds.Inset(margins);
175 layer()->SetBounds(layer_bounds); 152 gfx::Rect shadow_layer_bounds(new_layer_bounds.size());
176 const gfx::Rect shadow_layer_bounds(layer_bounds.size()); 153
154 // When there's an old shadow fading out, the bounds of layer() have to be
155 // big enough to encompass both shadows.
156 if (fading_layer_) {
157 const gfx::Rect old_layer_bounds = layer()->bounds();
158 gfx::Rect combined_layer_bounds = old_layer_bounds;
159 combined_layer_bounds.Union(new_layer_bounds);
160 layer()->SetBounds(combined_layer_bounds);
161
162 // If this is reached via SetContentBounds, we might hypothetically need
163 // to change the size of the fading layer, but the fade is so fast it's
164 // not really an issue.
165 gfx::Rect fading_layer_bounds(fading_layer_->bounds());
166 fading_layer_bounds.Offset(old_layer_bounds.origin() -
167 combined_layer_bounds.origin());
168 fading_layer_->SetBounds(fading_layer_bounds);
169
170 shadow_layer_bounds.Offset(new_layer_bounds.origin() -
171 combined_layer_bounds.origin());
172 } else {
173 layer()->SetBounds(new_layer_bounds);
174 }
175
177 shadow_layer_->SetBounds(shadow_layer_bounds); 176 shadow_layer_->SetBounds(shadow_layer_bounds);
178 177
179 // Occlude the region inside the bounding box. Occlusion uses shadow layer 178 // 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. 179 // space. See nine_patch_layer.h for more context on what's going on here.
181 gfx::Rect occlusion_bounds = shadow_layer_bounds; 180 gfx::Rect occlusion_bounds(shadow_layer_bounds.size());
182 occlusion_bounds.Inset(-margins + gfx::Insets(kRoundedCornerRadius)); 181 occlusion_bounds.Inset(-margins + gfx::Insets(kRoundedCornerRadius));
183 shadow_layer_->UpdateNinePatchOcclusion(occlusion_bounds); 182 shadow_layer_->UpdateNinePatchOcclusion(occlusion_bounds);
184 183
185 // The border is more or less the same inset as the aperture, but can be no 184 // 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 185 // larger than the shadow layer. When the shadow layer is too small, shrink
187 // the dimensions proportionally. 186 // the dimensions proportionally.
188 gfx::Insets blur_region = gfx::ShadowValue::GetBlurRegion(details.values) + 187 gfx::Insets blur_region = gfx::ShadowValue::GetBlurRegion(details.values) +
189 gfx::Insets(kRoundedCornerRadius); 188 gfx::Insets(kRoundedCornerRadius);
190 int border_w = std::min(blur_region.width(), shadow_layer_bounds.width()); 189 int border_w = std::min(blur_region.width(), shadow_layer_bounds.width());
191 int border_x = border_w * blur_region.left() / blur_region.width(); 190 int border_x = border_w * blur_region.left() / blur_region.width();
(...skipping 10 matching lines...) Expand all
202 case STYLE_INACTIVE: 201 case STYLE_INACTIVE:
203 return 8; 202 return 8;
204 case STYLE_SMALL: 203 case STYLE_SMALL:
205 return 6; 204 return 6;
206 } 205 }
207 NOTREACHED(); 206 NOTREACHED();
208 return 0; 207 return 0;
209 } 208 }
210 209
211 } // namespace wm 210 } // 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