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

Side by Side Diff: ash/rotator/screen_rotation_animator.cc

Issue 2790583004: Add second copy request after screen rotation to flatten the layers in animation. (Closed)
Patch Set: Created 3 years, 8 months 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 | « ash/rotator/screen_rotation_animator.h ('k') | chrome/browser/about_flags.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "ash/rotator/screen_rotation_animator.h" 5 #include "ash/rotator/screen_rotation_animator.h"
6 6
7 #include <string> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
11 #include "ash/common/ash_switches.h"
11 #include "ash/display/window_tree_host_manager.h" 12 #include "ash/display/window_tree_host_manager.h"
12 #include "ash/rotator/screen_rotation_animation.h" 13 #include "ash/rotator/screen_rotation_animation.h"
13 #include "ash/rotator/screen_rotation_animator_observer.h" 14 #include "ash/rotator/screen_rotation_animator_observer.h"
14 #include "ash/shell.h" 15 #include "ash/shell.h"
15 #include "base/command_line.h" 16 #include "base/command_line.h"
16 #include "base/memory/ptr_util.h" 17 #include "base/memory/ptr_util.h"
17 #include "base/metrics/histogram_macros.h" 18 #include "base/metrics/histogram_macros.h"
18 #include "base/time/time.h" 19 #include "base/time/time.h"
20 #include "cc/output/copy_output_request.h"
21 #include "cc/output/copy_output_result.h"
19 #include "ui/aura/window.h" 22 #include "ui/aura/window.h"
23 #include "ui/compositor/callback_layer_animation_observer.h"
20 #include "ui/compositor/layer.h" 24 #include "ui/compositor/layer.h"
21 #include "ui/compositor/layer_animation_element.h" 25 #include "ui/compositor/layer_animation_element.h"
22 #include "ui/compositor/layer_animation_observer.h" 26 #include "ui/compositor/layer_animation_observer.h"
23 #include "ui/compositor/layer_animation_sequence.h" 27 #include "ui/compositor/layer_animation_sequence.h"
24 #include "ui/compositor/layer_animator.h" 28 #include "ui/compositor/layer_animator.h"
25 #include "ui/compositor/layer_owner.h" 29 #include "ui/compositor/layer_owner.h"
26 #include "ui/compositor/layer_tree_owner.h" 30 #include "ui/compositor/layer_tree_owner.h"
27 #include "ui/display/display.h" 31 #include "ui/display/display.h"
28 #include "ui/display/manager/display_manager.h" 32 #include "ui/display/manager/display_manager.h"
29 #include "ui/display/manager/managed_display_info.h" 33 #include "ui/display/manager/managed_display_info.h"
(...skipping 12 matching lines...) Expand all
42 // The number of degrees that the rotation animations animate through. 46 // The number of degrees that the rotation animations animate through.
43 const int kRotationDegrees = 20; 47 const int kRotationDegrees = 20;
44 48
45 // The time it takes for the rotation animations to run. 49 // The time it takes for the rotation animations to run.
46 const int kRotationDurationInMs = 250; 50 const int kRotationDurationInMs = 250;
47 51
48 // The rotation factors. 52 // The rotation factors.
49 const int kCounterClockWiseRotationFactor = 1; 53 const int kCounterClockWiseRotationFactor = 1;
50 const int kClockWiseRotationFactor = -1; 54 const int kClockWiseRotationFactor = -1;
51 55
52 // Aborts the active animations of the layer, and recurses upon its child 56 // The delegate root layer name.
53 // layers. 57 const std::string kDelegateRootLayerName = "DelegateRootLayer";
54 void AbortAnimations(ui::Layer* layer) { 58 // The old root layer name.
55 for (ui::Layer* child_layer : layer->children()) 59 const std::string kOldRootLayerName = "ScreenRotationAnimator:old_layer_tree";
56 AbortAnimations(child_layer); 60 // The new root layer name.
57 layer->GetAnimator()->AbortAllAnimations(); 61 const std::string kNewRootLayerName = "ScreenRotationAnimator:new_layer_tree";
58 }
59 62
60 display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) { 63 display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) {
61 return Shell::GetInstance() 64 return Shell::GetInstance()
62 ->display_manager() 65 ->display_manager()
63 ->GetDisplayInfo(display_id) 66 ->GetDisplayInfo(display_id)
64 .GetActiveRotation(); 67 .GetActiveRotation();
65 } 68 }
66 69
67 bool IsDisplayIdValid(int64_t display_id) { 70 bool IsDisplayIdValid(int64_t display_id) {
68 return Shell::GetInstance()->display_manager()->IsDisplayIdValid(display_id); 71 return Shell::GetInstance()->display_manager()->IsDisplayIdValid(display_id);
69 } 72 }
70 73
71 // 180 degree rotations should animate clock-wise. 74 // 180 degree rotations should animate clock-wise.
72 int GetRotationFactor(display::Display::Rotation initial_rotation, 75 int GetRotationFactor(display::Display::Rotation initial_rotation,
73 display::Display::Rotation new_rotation) { 76 display::Display::Rotation new_rotation) {
74 return (initial_rotation + 3) % 4 == new_rotation 77 return (initial_rotation + 3) % 4 == new_rotation
75 ? kCounterClockWiseRotationFactor 78 ? kCounterClockWiseRotationFactor
76 : kClockWiseRotationFactor; 79 : kClockWiseRotationFactor;
77 } 80 }
78 81
79 aura::Window* GetRootWindow(int64_t display_id) { 82 aura::Window* GetRootWindow(int64_t display_id) {
80 return Shell::GetInstance() 83 return Shell::GetInstance()
81 ->window_tree_host_manager() 84 ->window_tree_host_manager()
82 ->GetRootWindowForDisplayId(display_id); 85 ->GetRootWindowForDisplayId(display_id);
83 } 86 }
84 87
88 ui::Layer* GetChildLayerByName(ui::Layer* parent, const std::string& name) {
89 for (ui::Layer* child_layer : parent->children()) {
90 if (child_layer->name() == name)
91 return child_layer;
92 }
93 NOTREACHED();
94 return nullptr;
95 }
96
85 // Returns true if the rotation between |initial_rotation| and |new_rotation| is 97 // Returns true if the rotation between |initial_rotation| and |new_rotation| is
86 // 180 degrees. 98 // 180 degrees.
87 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, 99 bool Is180DegreeFlip(display::Display::Rotation initial_rotation,
88 display::Display::Rotation new_rotation) { 100 display::Display::Rotation new_rotation) {
89 return (initial_rotation + 2) % 4 == new_rotation; 101 return (initial_rotation + 2) % 4 == new_rotation;
90 } 102 }
91 103
92 // Returns the initial degrees the old layer animation to begin with. 104 // Returns the initial degrees the old layer animation to begin with.
93 int GetInitialDegrees(display::Display::Rotation initial_rotation, 105 int GetInitialDegrees(display::Display::Rotation initial_rotation,
94 display::Display::Rotation new_rotation) { 106 display::Display::Rotation new_rotation) {
95 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); 107 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90);
96 } 108 }
97 109
98 // A LayerAnimationObserver that will destroy the contained LayerTreeOwner
99 // when notified that a layer animation has ended or was aborted.
100 class LayerCleanupObserver : public ui::LayerAnimationObserver {
101 public:
102 // Takes WeakPtr of ScreenRotationAnimator. |this| may outlive the |animator_|
103 // instance and the |animator_| isn't detaching itself as an observer when
104 // being destroyed. However, ideally, when |animator_| is destroying,
105 // deleting |old_layer_tree_owner_| will trigger OnLayerAnimationAborted and
106 // delete |this| before |animator_| deleted.
107 explicit LayerCleanupObserver(base::WeakPtr<ScreenRotationAnimator> animator);
108 ~LayerCleanupObserver() override;
109
110 // ui::LayerAnimationObserver:
111 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override;
112 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override;
113 void OnLayerAnimationScheduled(
114 ui::LayerAnimationSequence* sequence) override {}
115
116 protected:
117 // ui::LayerAnimationObserver:
118 bool RequiresNotificationWhenAnimatorDestroyed() const override {
119 return true;
120 }
121 void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override;
122 void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override;
123
124 private:
125 base::WeakPtr<ScreenRotationAnimator> animator_;
126
127 // The LayerAnimationSequence that |this| has been attached to. Defaults to
128 // nullptr.
129 ui::LayerAnimationSequence* sequence_;
130
131 DISALLOW_COPY_AND_ASSIGN(LayerCleanupObserver);
132 };
133
134 LayerCleanupObserver::LayerCleanupObserver(
135 base::WeakPtr<ScreenRotationAnimator> animator)
136 : animator_(animator), sequence_(nullptr) {}
137
138 LayerCleanupObserver::~LayerCleanupObserver() {
139 // We must eplicitly detach from |sequence_| because we return true from
140 // RequiresNotificationWhenAnimatorDestroyed.
141 if (sequence_)
142 sequence_->RemoveObserver(this);
143 }
144
145 void LayerCleanupObserver::OnLayerAnimationEnded(
146 ui::LayerAnimationSequence* sequence) {
147 if (animator_)
148 animator_->ProcessAnimationQueue();
149
150 delete this;
151 }
152
153 void LayerCleanupObserver::OnLayerAnimationAborted(
154 ui::LayerAnimationSequence* sequence) {
155 if (animator_)
156 animator_->ProcessAnimationQueue();
157
158 delete this;
159 }
160
161 void LayerCleanupObserver::OnAttachedToSequence(
162 ui::LayerAnimationSequence* sequence) {
163 sequence_ = sequence;
164 }
165
166 void LayerCleanupObserver::OnDetachedFromSequence(
167 ui::LayerAnimationSequence* sequence) {
168 DCHECK_EQ(sequence, sequence_);
169 sequence_ = nullptr;
170 }
171
172 class ScreenRotationAnimationMetricsReporter 110 class ScreenRotationAnimationMetricsReporter
173 : public ui::AnimationMetricsReporter { 111 : public ui::AnimationMetricsReporter {
174 public: 112 public:
175 ScreenRotationAnimationMetricsReporter() {} 113 ScreenRotationAnimationMetricsReporter() {}
176 ~ScreenRotationAnimationMetricsReporter() override {} 114 ~ScreenRotationAnimationMetricsReporter() override {}
177 115
178 void Report(int value) override { 116 void Report(int value) override {
179 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); 117 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value);
180 } 118 }
181 119
182 private: 120 private:
183 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); 121 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter);
184 }; 122 };
185 123
124 void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) {
125 // Add the cloned layer tree in to the root, so it will be rendered.
126 root_window->layer()->Add(layer);
127 root_window->layer()->StackAtTop(layer);
128 }
129
130 bool AnimationEndedCallback(
131 base::WeakPtr<ScreenRotationAnimator> animator,
132 const ui::CallbackLayerAnimationObserver& observer) {
133 if (animator)
134 animator->ProcessAnimationQueue();
135 return true;
136 }
137
138 // Round near zero value to zero.
139 void RoundNearZero(gfx::Transform* transform) {
140 const float kEpsilon = 0.001f;
141 SkMatrix44& matrix = transform->matrix();
142 for (int x = 0; x < 4; ++x) {
143 for (int y = 0; y < 4; ++y) {
144 if (std::abs(SkMScalarToFloat(matrix.get(x, y))) < kEpsilon)
145 matrix.set(x, y, SkFloatToMScalar(0.0f));
146 }
147 }
148 }
149
150 void TransformLayerToOldRotation(
151 ui::Layer* layer,
152 const int64_t display_id,
153 const display::Display::Rotation& new_rotation,
154 const display::Display::Rotation& old_rotation) {
155 const display::Display display =
156 Shell::GetInstance()->display_manager()->GetDisplayForId(display_id);
157
158 const int rotation_changed = ((new_rotation - old_rotation) + 4) % 4;
159 float one_pixel = 1.0f / display.device_scale_factor();
160 gfx::Transform transform;
161 switch (rotation_changed) {
162 case 0:
163 break;
164 case 1:
165 transform.Rotate(270);
166 transform.Translate(-display.bounds().height() + one_pixel, 0);
167 break;
168 case 2:
169 transform.Rotate(180);
170 transform.Translate(-display.bounds().width() + one_pixel,
171 -display.bounds().height() + one_pixel);
172 break;
173 case 3:
174 transform.Rotate(90);
175 transform.Translate(0, -display.bounds().width() + one_pixel);
176 break;
177 }
178
179 RoundNearZero(&transform);
180 layer->SetTransform(transform);
181 }
182
186 } // namespace 183 } // namespace
187 184
188 struct ScreenRotationAnimator::ScreenRotationRequest { 185 struct ScreenRotationAnimator::ScreenRotationRequest {
189 ScreenRotationRequest(display::Display::Rotation to_rotation, 186 ScreenRotationRequest(const display::Display::Rotation& from_rotation,
190 display::Display::RotationSource from_source) 187 const display::Display::Rotation& to_rotation,
191 : new_rotation(to_rotation), source(from_source) {} 188 const display::Display::RotationSource& from_source)
189 : old_rotation(from_rotation),
190 new_rotation(to_rotation),
191 source(from_source) {}
192 display::Display::Rotation old_rotation;
192 display::Display::Rotation new_rotation; 193 display::Display::Rotation new_rotation;
193 display::Display::RotationSource source; 194 display::Display::RotationSource source;
194 }; 195 };
195 196
196 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) 197 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id)
197 : display_id_(display_id), 198 : display_id_(display_id),
198 is_rotating_(false), 199 is_rotating_(false),
199 metrics_reporter_( 200 metrics_reporter_(
200 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), 201 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()),
201 disable_animation_timers_for_test_(false), 202 disable_animation_timers_for_test_(false),
202 weak_factory_(this) {} 203 weak_factory_(this) {}
203 204
204 ScreenRotationAnimator::~ScreenRotationAnimator() { 205 ScreenRotationAnimator::~ScreenRotationAnimator() {
205 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from 206 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from
206 // calling a method on the |animator_|. 207 // calling a method on the |animator_|.
207 weak_factory_.InvalidateWeakPtrs(); 208 weak_factory_.InvalidateWeakPtrs();
208 209
209 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in 210 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in
210 // order to make sure |metrics_reporter_| outlives the attached animation 211 // order to make sure |metrics_reporter_| outlives the attached animation
211 // sequence. 212 // sequence.
212 old_layer_tree_owner_.reset(); 213 old_layer_tree_owner_.reset();
213 metrics_reporter_.reset(); 214 metrics_reporter_.reset();
214 } 215 }
215 216
217 void ScreenRotationAnimator::StartRotationAnimation(
218 std::unique_ptr<ScreenRotationRequest> rotation_request) {
219 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
220 switches::kAshEnableSmoothScreenRotation)) {
221 const cc::CopyOutputRequest::CopyOutputRequestCallback callback =
222 base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation,
223 weak_factory_.GetWeakPtr(), base::Passed(&rotation_request));
224 RequestCopyRootLayerByName(kDelegateRootLayerName, callback);
225 } else {
226 StartSlowAnimation(std::move(rotation_request));
227 }
228 }
229
230 void ScreenRotationAnimator::SetRotation(
231 const display::Display::Rotation& new_rotation,
232 const display::Display::Rotation& old_rotation,
233 const display::Display::RotationSource& source) {
234 Shell::GetInstance()->display_manager()->SetDisplayRotation(
235 display_id_, new_rotation, source);
236 TransformLayerToOldRotation(old_layer_tree_owner_->root(), display_id_,
237 new_rotation, old_rotation);
238 }
239
240 void ScreenRotationAnimator::StartSlowAnimation(
241 std::unique_ptr<ScreenRotationRequest> rotation_request) {
242 CreateOldLayerTree();
243 SetRotation(rotation_request->new_rotation, rotation_request->old_rotation,
244 rotation_request->source);
245 AnimateRotation(std::move(rotation_request));
246 }
247
248 void ScreenRotationAnimator::RequestCopyRootLayerByName(
249 const std::string& layer_name,
250 const cc::CopyOutputRequest::CopyOutputRequestCallback& callback) {
251 std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
252 cc::CopyOutputRequest::CreateRequest(callback);
253 ui::Layer* layer =
254 GetChildLayerByName(GetRootWindow(display_id_)->layer(), layer_name);
255 gfx::Rect rect(layer->size());
256 copy_output_request->set_area(rect);
257 layer->RequestCopyOfOutput(std::move(copy_output_request));
258 }
259
260 void ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation(
261 std::unique_ptr<ScreenRotationRequest> rotation_request,
262 std::unique_ptr<cc::CopyOutputResult> result) {
263 // If copy request does not succeed or canceled, fall back to recreate layers
264 // solution.
265 if (result->IsEmpty() || result->size().IsEmpty() || !result->HasTexture()) {
danakj 2017/03/31 19:32:30 I don't think you need to check size() or HasTextu
wutao 2017/04/07 06:59:11 Acknowledged.
266 StartSlowAnimation(std::move(rotation_request));
267 } else {
268 old_layer_tree_owner_ = CopyLayerTree(kOldRootLayerName, std::move(result));
269
270 SetRotation(rotation_request->new_rotation, rotation_request->old_rotation,
271 rotation_request->source);
272
273 const cc::CopyOutputRequest::CopyOutputRequestCallback callback =
274 base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedAfterRotation,
275 weak_factory_.GetWeakPtr(), base::Passed(&rotation_request));
276 RequestCopyRootLayerByName(kDelegateRootLayerName, callback);
danakj 2017/03/31 19:32:30 Why not do both of these copies at the same time i
wutao 2017/04/07 06:59:11 Talked offline, The two requests are on the same l
277 }
278 }
279
280 void ScreenRotationAnimator::OnRootLayerCopiedAfterRotation(
281 std::unique_ptr<ScreenRotationRequest> rotation_request,
282 std::unique_ptr<cc::CopyOutputResult> result) {
283 if (!result->IsEmpty() && !result->size().IsEmpty() && result->HasTexture())
danakj 2017/03/31 19:32:30 same about size and HasTexture
wutao 2017/04/07 06:59:11 Acknowledged.
284 new_layer_tree_owner_ = CopyLayerTree(kNewRootLayerName, std::move(result));
285 AnimateRotation(std::move(rotation_request));
286 }
287
288 void ScreenRotationAnimator::CreateOldLayerTree() {
289 aura::Window* root_window = GetRootWindow(display_id_);
290 old_layer_tree_owner_ = ::wm::RecreateLayers(root_window);
291 old_layer_tree_owner_->root()->set_name(kOldRootLayerName);
292 AddLayerAtTopOfWindowLayers(root_window, old_layer_tree_owner_->root());
293 }
294
295 std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree(
296 const std::string& layer_name,
297 std::unique_ptr<cc::CopyOutputResult> result) {
298 cc::TextureMailbox texture_mailbox;
299 std::unique_ptr<cc::SingleReleaseCallback> release_callback;
300 result->TakeTexture(&texture_mailbox, &release_callback);
301 DCHECK(texture_mailbox.IsTexture());
302
303 aura::Window* root_window = GetRootWindow(display_id_);
304 gfx::Rect rect(root_window->layer()->size());
305 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>();
306 copy_layer->SetBounds(rect);
307 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback),
308 rect.size());
309
310 copy_layer->set_name(layer_name);
311 AddLayerAtTopOfWindowLayers(root_window, copy_layer.get());
312 return base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer));
313 }
314
216 void ScreenRotationAnimator::AnimateRotation( 315 void ScreenRotationAnimator::AnimateRotation(
217 std::unique_ptr<ScreenRotationRequest> rotation_request) { 316 std::unique_ptr<ScreenRotationRequest> rotation_request) {
218 aura::Window* root_window = GetRootWindow(display_id_); 317 const int rotation_factor = GetRotationFactor(rotation_request->old_rotation,
219 318 rotation_request->new_rotation);
220 const gfx::Rect original_screen_bounds = root_window->GetTargetBounds();
221
222 const int rotation_factor = GetRotationFactor(
223 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation);
224
225 const int old_layer_initial_rotation_degrees = GetInitialDegrees( 319 const int old_layer_initial_rotation_degrees = GetInitialDegrees(
226 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); 320 rotation_request->old_rotation, rotation_request->new_rotation);
227
228 const base::TimeDelta duration = 321 const base::TimeDelta duration =
229 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); 322 base::TimeDelta::FromMilliseconds(kRotationDurationInMs);
230
231 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; 323 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN;
232 324 aura::Window* root_window = GetRootWindow(display_id_);
233 std::unique_ptr<ui::LayerTreeOwner> old_layer_tree =
234 ::wm::RecreateLayers(root_window);
235 old_layer_tree->root()->set_name("ScreenRotationAnimator:old_layer_tree");
236
237 // Add the cloned layer tree in to the root, so it will be rendered.
238 root_window->layer()->Add(old_layer_tree->root());
239 root_window->layer()->StackAtTop(old_layer_tree->root());
240
241 old_layer_tree_owner_ = std::move(old_layer_tree);
242 std::unique_ptr<LayerCleanupObserver> old_layer_cleanup_observer(
243 new LayerCleanupObserver(weak_factory_.GetWeakPtr()));
244
245 Shell::GetInstance()->display_manager()->SetDisplayRotation(
246 display_id_, rotation_request->new_rotation, rotation_request->source);
247
248 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds(); 325 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds();
249 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, 326 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
250 rotated_screen_bounds.height() / 2); 327 rotated_screen_bounds.height() / 2);
251 328
252 ui::Layer* old_root_layer = old_layer_tree_owner_->root(); 329 // Make the current layers invisible.
253 // We must animate each non-cloned child layer individually because the cloned 330 if (new_layer_tree_owner_) {
254 // layer was added as a child to |root_window|'s layer so that it will be 331 GetChildLayerByName(root_window->layer(), kDelegateRootLayerName)
255 // rendered. 332 ->SetOpacity(0.0f);
256 // TODO(bruthig): Add a NOT_DRAWN layer in between the root_window's layer and
257 // its current children so that we only need to initiate two
258 // LayerAnimationSequences. One for the new layers and one for the old layer.
259 for (ui::Layer* child_layer : root_window->layer()->children()) {
260 // Skip the cloned layer because it has a different animation.
261 if (child_layer == old_root_layer)
262 continue;
263
264 std::unique_ptr<ScreenRotationAnimation> screen_rotation =
265 base::MakeUnique<ScreenRotationAnimation>(
266 child_layer, kRotationDegrees * rotation_factor,
267 0 /* end_degrees */, child_layer->opacity(),
268 1.0f /* target_opacity */, pivot, duration, tween_type);
269
270 ui::LayerAnimator* animator = child_layer->GetAnimator();
271 animator->set_preemption_strategy(
272 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
273 std::unique_ptr<ui::LayerAnimationSequence> animation_sequence =
274 base::MakeUnique<ui::LayerAnimationSequence>(
275 std::move(screen_rotation));
276 animator->StartAnimation(animation_sequence.release());
277 } 333 }
278 334
335 // Add an observer so that the copied layers can be cleaned up with the
336 // animation completes/aborts.
337 ui::CallbackLayerAnimationObserver* observer =
338 new ui::CallbackLayerAnimationObserver(
339 base::Bind(&AnimationEndedCallback, weak_factory_.GetWeakPtr()));
340
341 ui::Layer* new_root_layer;
342 if (new_layer_tree_owner_ &&
343 base::CommandLine::ForCurrentProcess()->HasSwitch(
344 switches::kAshEnableSmoothScreenRotation)) {
345 new_root_layer = new_layer_tree_owner_->root();
346 } else {
347 new_root_layer =
348 GetChildLayerByName(root_window->layer(), kDelegateRootLayerName);
349 }
350
351 std::unique_ptr<ScreenRotationAnimation> current_layer_screen_rotation =
352 base::MakeUnique<ScreenRotationAnimation>(
353 new_root_layer, kRotationDegrees * rotation_factor,
354 0 /* end_degrees */, 0.0f,
355 new_root_layer->opacity() /* target_opacity */, pivot, duration,
356 tween_type);
357
358 ui::LayerAnimator* current_layer_animator = new_root_layer->GetAnimator();
359 current_layer_animator->set_preemption_strategy(
360 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
361 std::unique_ptr<ui::LayerAnimationSequence> current_layer_animation_sequence =
362 base::MakeUnique<ui::LayerAnimationSequence>(
363 std::move(current_layer_screen_rotation));
364
365 ui::Layer* old_root_layer = old_layer_tree_owner_->root();
366 const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds();
279 // The old layer will also be transformed into the new orientation. We will 367 // The old layer will also be transformed into the new orientation. We will
280 // translate it so that the old layer's center point aligns with the new 368 // translate it so that the old layer's center point aligns with the new
281 // orientation's center point and use that center point as the pivot for the 369 // orientation's center point and use that center point as the pivot for the
282 // rotation animation. 370 // rotation animation.
283 gfx::Transform translate_transform; 371 gfx::Transform translate_transform;
284 translate_transform.Translate( 372 translate_transform.Translate(
285 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2, 373 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2,
286 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); 374 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2);
287 old_root_layer->SetTransform(translate_transform); 375 old_root_layer->SetTransform(translate_transform);
288 376
289 std::unique_ptr<ScreenRotationAnimation> screen_rotation = 377 std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation =
290 base::MakeUnique<ScreenRotationAnimation>( 378 base::MakeUnique<ScreenRotationAnimation>(
291 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, 379 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor,
292 (old_layer_initial_rotation_degrees - kRotationDegrees) * 380 (old_layer_initial_rotation_degrees - kRotationDegrees) *
293 rotation_factor, 381 rotation_factor,
294 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, 382 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration,
295 tween_type); 383 tween_type);
296 384
297 ui::LayerAnimator* animator = old_root_layer->GetAnimator(); 385 ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator();
298 animator->set_preemption_strategy( 386 old_layer_animator->set_preemption_strategy(
299 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); 387 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
300 std::unique_ptr<ui::LayerAnimationSequence> animation_sequence = 388 std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence =
301 base::MakeUnique<ui::LayerAnimationSequence>(std::move(screen_rotation)); 389 base::MakeUnique<ui::LayerAnimationSequence>(
302 // Add an observer so that the cloned layers can be cleaned up with the 390 std::move(old_layer_screen_rotation));
303 // animation completes/aborts. 391
304 animation_sequence->AddObserver(old_layer_cleanup_observer.release());
305 // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to
306 // control the animation.
307 if (disable_animation_timers_for_test_) 392 if (disable_animation_timers_for_test_)
308 animator->set_disable_timer_for_test(true); 393 old_layer_animator->set_disable_timer_for_test(true);
309 animation_sequence->SetAnimationMetricsReporter(metrics_reporter_.get()); 394 old_layer_animation_sequence->SetAnimationMetricsReporter(
310 animator->StartAnimation(animation_sequence.release()); 395 metrics_reporter_.get());
311 396
397 current_layer_animator->AddObserver(observer);
398 old_layer_animator->AddObserver(observer);
399 current_layer_animator->StartAnimation(
400 current_layer_animation_sequence.release());
401 old_layer_animator->StartAnimation(old_layer_animation_sequence.release());
402 observer->SetActive();
312 rotation_request.reset(); 403 rotation_request.reset();
313 } 404 }
314 405
315 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, 406 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation,
316 display::Display::RotationSource source) { 407 display::Display::RotationSource source) {
317 if (GetCurrentScreenRotation(display_id_) == new_rotation) 408 const display::Display::Rotation current_rotation =
409 GetCurrentScreenRotation(display_id_);
410 if (current_rotation == new_rotation)
318 return; 411 return;
319 412
320 std::unique_ptr<ScreenRotationRequest> rotation_request = 413 std::unique_ptr<ScreenRotationRequest> rotation_request =
321 base::MakeUnique<ScreenRotationRequest>(new_rotation, source); 414 base::MakeUnique<ScreenRotationRequest>(current_rotation, new_rotation,
415 source);
322 416
323 if (is_rotating_) { 417 if (is_rotating_) {
324 last_pending_request_ = std::move(rotation_request); 418 last_pending_request_ = std::move(rotation_request);
325 // The pending request will be processed when the 419 // The pending request will be processed when the
326 // OnLayerAnimation(Ended|Aborted) methods should be called after 420 // OnLayerAnimation(Ended|Aborted) methods should be called after
327 // StopAnimating(). 421 // StopAnimating().
328 StopAnimating(); 422 StopAnimating();
329 } else { 423 } else {
330 is_rotating_ = true; 424 is_rotating_ = true;
331 AnimateRotation(std::move(rotation_request)); 425 StartRotationAnimation(std::move(rotation_request));
332 } 426 }
333 } 427 }
334 428
335 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver( 429 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver(
336 ScreenRotationAnimatorObserver* observer) { 430 ScreenRotationAnimatorObserver* observer) {
337 screen_rotation_animator_observers_.AddObserver(observer); 431 screen_rotation_animator_observers_.AddObserver(observer);
338 } 432 }
339 433
340 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( 434 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver(
341 ScreenRotationAnimatorObserver* observer) { 435 ScreenRotationAnimatorObserver* observer) {
342 screen_rotation_animator_observers_.RemoveObserver(observer); 436 screen_rotation_animator_observers_.RemoveObserver(observer);
343 } 437 }
344 438
345 void ScreenRotationAnimator::ProcessAnimationQueue() { 439 void ScreenRotationAnimator::ProcessAnimationQueue() {
346 is_rotating_ = false; 440 is_rotating_ = false;
441 StopAnimating();
347 old_layer_tree_owner_.reset(); 442 old_layer_tree_owner_.reset();
443 new_layer_tree_owner_.reset();
348 if (last_pending_request_ && IsDisplayIdValid(display_id_)) { 444 if (last_pending_request_ && IsDisplayIdValid(display_id_)) {
349 std::unique_ptr<ScreenRotationRequest> rotation_request = 445 std::unique_ptr<ScreenRotationRequest> rotation_request =
350 std::move(last_pending_request_); 446 std::move(last_pending_request_);
351 Rotate(rotation_request->new_rotation, rotation_request->source); 447 Rotate(rotation_request->new_rotation, rotation_request->source);
352 rotation_request.reset(); 448 rotation_request.reset();
353 return; 449 return;
354 } 450 }
355 451
356 for (auto& observer : screen_rotation_animator_observers_) 452 for (auto& observer : screen_rotation_animator_observers_)
357 observer.OnScreenRotationAnimationFinished(this); 453 observer.OnScreenRotationAnimationFinished(this);
358 } 454 }
359 455
360 void ScreenRotationAnimator::set_disable_animation_timers_for_test( 456 void ScreenRotationAnimator::set_disable_animation_timers_for_test(
361 bool disable_timers) { 457 bool disable_timers) {
362 disable_animation_timers_for_test_ = disable_timers; 458 disable_animation_timers_for_test_ = disable_timers;
363 } 459 }
364 460
365 void ScreenRotationAnimator::StopAnimating() { 461 void ScreenRotationAnimator::StopAnimating() {
366 aura::Window* root_window = GetRootWindow(display_id_); 462 GetChildLayerByName(GetRootWindow(display_id_)->layer(),
367 for (ui::Layer* child_layer : root_window->layer()->children()) { 463 kDelegateRootLayerName)
368 if (child_layer == old_layer_tree_owner_->root()) 464 ->SetOpacity(1.0f);
369 continue;
370
371 child_layer->GetAnimator()->StopAnimating();
372 }
373
374 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); 465 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
466 // |new_layer_tree_owner_| could be nullptr if the second copy request failed
467 // or canceled.
468 if (new_layer_tree_owner_)
469 new_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
375 } 470 }
376 471
377 } // namespace ash 472 } // namespace ash
OLDNEW
« no previous file with comments | « ash/rotator/screen_rotation_animator.h ('k') | chrome/browser/about_flags.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698