OLD | NEW |
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> | |
8 #include <utility> | |
9 #include <vector> | |
10 | |
11 #include "ash/common/ash_switches.h" | 7 #include "ash/common/ash_switches.h" |
12 #include "ash/display/window_tree_host_manager.h" | 8 #include "ash/display/window_tree_host_manager.h" |
| 9 #include "ash/public/cpp/shell_window_ids.h" |
13 #include "ash/rotator/screen_rotation_animation.h" | 10 #include "ash/rotator/screen_rotation_animation.h" |
14 #include "ash/rotator/screen_rotation_animator_observer.h" | 11 #include "ash/rotator/screen_rotation_animator_observer.h" |
15 #include "ash/shell.h" | 12 #include "ash/shell.h" |
| 13 #include "ash/utility/transformer_util.h" |
16 #include "base/command_line.h" | 14 #include "base/command_line.h" |
17 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
18 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
19 #include "base/time/time.h" | 17 #include "base/time/time.h" |
20 #include "cc/output/copy_output_request.h" | 18 #include "cc/output/copy_output_request.h" |
21 #include "cc/output/copy_output_result.h" | 19 #include "cc/output/copy_output_result.h" |
22 #include "ui/aura/window.h" | 20 #include "ui/aura/window.h" |
| 21 #include "ui/compositor/callback_layer_animation_observer.h" |
23 #include "ui/compositor/layer.h" | 22 #include "ui/compositor/layer.h" |
24 #include "ui/compositor/layer_animation_element.h" | 23 #include "ui/compositor/layer_animation_element.h" |
25 #include "ui/compositor/layer_animation_observer.h" | |
26 #include "ui/compositor/layer_animation_sequence.h" | 24 #include "ui/compositor/layer_animation_sequence.h" |
27 #include "ui/compositor/layer_animator.h" | 25 #include "ui/compositor/layer_animator.h" |
28 #include "ui/compositor/layer_owner.h" | 26 #include "ui/compositor/layer_owner.h" |
29 #include "ui/compositor/layer_tree_owner.h" | 27 #include "ui/compositor/layer_tree_owner.h" |
30 #include "ui/display/display.h" | 28 #include "ui/display/display.h" |
31 #include "ui/display/manager/display_manager.h" | 29 #include "ui/display/manager/display_manager.h" |
32 #include "ui/display/manager/managed_display_info.h" | 30 #include "ui/display/manager/managed_display_info.h" |
33 #include "ui/gfx/animation/tween.h" | 31 #include "ui/gfx/animation/tween.h" |
34 #include "ui/gfx/geometry/point.h" | 32 #include "ui/gfx/geometry/point.h" |
35 #include "ui/gfx/geometry/rect.h" | 33 #include "ui/gfx/geometry/rect.h" |
36 #include "ui/gfx/geometry/rect_f.h" | 34 #include "ui/gfx/geometry/rect_f.h" |
37 #include "ui/gfx/transform.h" | 35 #include "ui/gfx/transform.h" |
38 #include "ui/gfx/transform_util.h" | 36 #include "ui/gfx/transform_util.h" |
39 #include "ui/wm/core/window_util.h" | 37 #include "ui/wm/core/window_util.h" |
40 | 38 |
41 namespace ash { | 39 namespace ash { |
42 | 40 |
43 namespace { | 41 namespace { |
44 | 42 |
45 // The number of degrees that the rotation animations animate through. | 43 // The number of degrees that the rotation animations animate through. |
46 const int kRotationDegrees = 20; | 44 const int kRotationDegrees = 20; |
47 | 45 |
48 // The time it takes for the rotation animations to run. | 46 // The time it takes for the rotation animations to run. |
49 const int kRotationDurationInMs = 250; | 47 const int kRotationDurationInMs = 250; |
50 | 48 |
51 // The rotation factors. | 49 // The rotation factors. |
52 const int kCounterClockWiseRotationFactor = 1; | 50 const int kCounterClockWiseRotationFactor = 1; |
53 const int kClockWiseRotationFactor = -1; | 51 const int kClockWiseRotationFactor = -1; |
54 | 52 |
55 // Aborts the active animations of the layer, and recurses upon its child | |
56 // layers. | |
57 void AbortAnimations(ui::Layer* layer) { | |
58 for (ui::Layer* child_layer : layer->children()) | |
59 AbortAnimations(child_layer); | |
60 layer->GetAnimator()->AbortAllAnimations(); | |
61 } | |
62 | |
63 display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) { | 53 display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) { |
64 return Shell::Get() | 54 return Shell::Get() |
65 ->display_manager() | 55 ->display_manager() |
66 ->GetDisplayInfo(display_id) | 56 ->GetDisplayInfo(display_id) |
67 .GetActiveRotation(); | 57 .GetActiveRotation(); |
68 } | 58 } |
69 | 59 |
70 bool IsDisplayIdValid(int64_t display_id) { | 60 bool IsDisplayIdValid(int64_t display_id) { |
71 return Shell::Get()->display_manager()->IsDisplayIdValid(display_id); | 61 return Shell::Get()->display_manager()->IsDisplayIdValid(display_id); |
72 } | 62 } |
73 | 63 |
74 // 180 degree rotations should animate clock-wise. | 64 // 180 degree rotations should animate clock-wise. |
75 int GetRotationFactor(display::Display::Rotation initial_rotation, | 65 int GetRotationFactor(display::Display::Rotation initial_rotation, |
76 display::Display::Rotation new_rotation) { | 66 display::Display::Rotation new_rotation) { |
77 return (initial_rotation + 3) % 4 == new_rotation | 67 return (initial_rotation + 3) % 4 == new_rotation |
78 ? kCounterClockWiseRotationFactor | 68 ? kCounterClockWiseRotationFactor |
79 : kClockWiseRotationFactor; | 69 : kClockWiseRotationFactor; |
80 } | 70 } |
81 | 71 |
82 aura::Window* GetRootWindow(int64_t display_id) { | 72 aura::Window* GetRootWindow(int64_t display_id) { |
83 return Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId( | 73 return Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId( |
84 display_id); | 74 display_id); |
85 } | 75 } |
86 | 76 |
| 77 aura::Window* GetScreenRotationContainer(int64_t display_id) { |
| 78 return GetRootWindow(display_id) |
| 79 ->GetChildById(kShellWindowId_ScreenRotationContainer); |
| 80 } |
| 81 |
87 // Returns true if the rotation between |initial_rotation| and |new_rotation| is | 82 // Returns true if the rotation between |initial_rotation| and |new_rotation| is |
88 // 180 degrees. | 83 // 180 degrees. |
89 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, | 84 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, |
90 display::Display::Rotation new_rotation) { | 85 display::Display::Rotation new_rotation) { |
91 return (initial_rotation + 2) % 4 == new_rotation; | 86 return (initial_rotation + 2) % 4 == new_rotation; |
92 } | 87 } |
93 | 88 |
94 // Returns the initial degrees the old layer animation to begin with. | 89 // Returns the initial degrees the old layer animation to begin with. |
95 int GetInitialDegrees(display::Display::Rotation initial_rotation, | 90 int GetInitialDegrees(display::Display::Rotation initial_rotation, |
96 display::Display::Rotation new_rotation) { | 91 display::Display::Rotation new_rotation) { |
97 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); | 92 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); |
98 } | 93 } |
99 | 94 |
100 // A LayerAnimationObserver that will destroy the contained LayerTreeOwner | 95 void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) { |
101 // when notified that a layer animation has ended or was aborted. | 96 // Add the cloned/copied layer tree into the root, so it will be rendered. |
102 class LayerCleanupObserver : public ui::LayerAnimationObserver { | 97 root_window->layer()->Add(layer); |
103 public: | 98 root_window->layer()->StackAtTop(layer); |
104 // Takes WeakPtr of ScreenRotationAnimator. |this| may outlive the |animator_| | |
105 // instance and the |animator_| isn't detaching itself as an observer when | |
106 // being destroyed. However, ideally, when |animator_| is destroying, | |
107 // deleting |old_layer_tree_owner_| will trigger OnLayerAnimationAborted and | |
108 // delete |this| before |animator_| deleted. | |
109 explicit LayerCleanupObserver(base::WeakPtr<ScreenRotationAnimator> animator); | |
110 ~LayerCleanupObserver() override; | |
111 | |
112 // ui::LayerAnimationObserver: | |
113 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override; | |
114 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override; | |
115 void OnLayerAnimationScheduled( | |
116 ui::LayerAnimationSequence* sequence) override {} | |
117 | |
118 protected: | |
119 // ui::LayerAnimationObserver: | |
120 bool RequiresNotificationWhenAnimatorDestroyed() const override { | |
121 return true; | |
122 } | |
123 void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override; | |
124 void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override; | |
125 | |
126 private: | |
127 base::WeakPtr<ScreenRotationAnimator> animator_; | |
128 | |
129 // The LayerAnimationSequence that |this| has been attached to. Defaults to | |
130 // nullptr. | |
131 ui::LayerAnimationSequence* sequence_; | |
132 | |
133 DISALLOW_COPY_AND_ASSIGN(LayerCleanupObserver); | |
134 }; | |
135 | |
136 LayerCleanupObserver::LayerCleanupObserver( | |
137 base::WeakPtr<ScreenRotationAnimator> animator) | |
138 : animator_(animator), sequence_(nullptr) {} | |
139 | |
140 LayerCleanupObserver::~LayerCleanupObserver() { | |
141 // We must eplicitly detach from |sequence_| because we return true from | |
142 // RequiresNotificationWhenAnimatorDestroyed. | |
143 if (sequence_) | |
144 sequence_->RemoveObserver(this); | |
145 } | 99 } |
146 | 100 |
147 void LayerCleanupObserver::OnLayerAnimationEnded( | 101 // The Callback will be invoked when all animation sequences have |
148 ui::LayerAnimationSequence* sequence) { | 102 // finished. |observer| will be destroyed after invoking the Callback if it |
149 if (animator_) | 103 // returns true. |
150 animator_->ProcessAnimationQueue(); | 104 bool AnimationEndedCallback( |
151 | 105 base::WeakPtr<ScreenRotationAnimator> animator, |
152 delete this; | 106 const ui::CallbackLayerAnimationObserver& observer) { |
| 107 if (animator) |
| 108 animator->ProcessAnimationQueue(); |
| 109 return true; |
153 } | 110 } |
154 | 111 |
155 void LayerCleanupObserver::OnLayerAnimationAborted( | 112 // Creates a Transform for the old layer in screen rotation animation. |
156 ui::LayerAnimationSequence* sequence) { | 113 gfx::Transform CreateScreenRotationOldLayerTransformForDisplay( |
157 if (animator_) | 114 display::Display::Rotation new_rotation, |
158 animator_->ProcessAnimationQueue(); | 115 display::Display::Rotation old_rotation, |
159 | 116 const display::Display& display) { |
160 delete this; | 117 gfx::Transform inverse; |
161 } | 118 CHECK(CreateRotationTransform(old_rotation, new_rotation, display) |
162 | 119 .GetInverse(&inverse)); |
163 void LayerCleanupObserver::OnAttachedToSequence( | 120 return inverse; |
164 ui::LayerAnimationSequence* sequence) { | |
165 sequence_ = sequence; | |
166 } | |
167 | |
168 void LayerCleanupObserver::OnDetachedFromSequence( | |
169 ui::LayerAnimationSequence* sequence) { | |
170 DCHECK_EQ(sequence, sequence_); | |
171 sequence_ = nullptr; | |
172 } | 121 } |
173 | 122 |
174 class ScreenRotationAnimationMetricsReporter | 123 class ScreenRotationAnimationMetricsReporter |
175 : public ui::AnimationMetricsReporter { | 124 : public ui::AnimationMetricsReporter { |
176 public: | 125 public: |
177 ScreenRotationAnimationMetricsReporter() {} | 126 ScreenRotationAnimationMetricsReporter() {} |
178 ~ScreenRotationAnimationMetricsReporter() override {} | 127 ~ScreenRotationAnimationMetricsReporter() override {} |
179 | 128 |
180 void Report(int value) override { | 129 void Report(int value) override { |
181 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); | 130 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); |
182 } | 131 } |
183 | 132 |
184 private: | 133 private: |
185 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); | 134 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); |
186 }; | 135 }; |
187 | 136 |
188 } // namespace | 137 } // namespace |
189 | 138 |
190 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) | 139 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) |
191 : display_id_(display_id), | 140 : display_id_(display_id), |
192 is_rotating_(false), | 141 is_rotating_(false), |
193 metrics_reporter_( | 142 metrics_reporter_( |
194 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), | 143 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), |
195 disable_animation_timers_for_test_(false), | 144 disable_animation_timers_for_test_(false), |
| 145 has_switch_ash_enable_smooth_screen_rotation_(false), |
| 146 screen_rotation_container_layer_( |
| 147 GetScreenRotationContainer(display_id_)->layer()), |
| 148 root_window_(GetRootWindow(display_id_)), |
196 weak_factory_(this) {} | 149 weak_factory_(this) {} |
197 | 150 |
198 ScreenRotationAnimator::~ScreenRotationAnimator() { | 151 ScreenRotationAnimator::~ScreenRotationAnimator() { |
199 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from | 152 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from |
200 // calling a method on the |animator_|. | 153 // calling a method on the |animator_|. |
201 weak_factory_.InvalidateWeakPtrs(); | 154 weak_factory_.InvalidateWeakPtrs(); |
202 | 155 |
203 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in | 156 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in |
204 // order to make sure |metrics_reporter_| outlives the attached animation | 157 // order to make sure |metrics_reporter_| outlives the attached animation |
205 // sequence. | 158 // sequence. |
206 old_layer_tree_owner_.reset(); | 159 old_layer_tree_owner_.reset(); |
207 metrics_reporter_.reset(); | 160 metrics_reporter_.reset(); |
208 } | 161 } |
209 | 162 |
210 void ScreenRotationAnimator::StartRotationAnimation( | 163 void ScreenRotationAnimator::StartRotationAnimation( |
211 std::unique_ptr<ScreenRotationRequest> rotation_request) { | 164 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
212 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 165 if (has_switch_ash_enable_smooth_screen_rotation_) { |
213 switches::kAshEnableSmoothScreenRotation)) { | 166 std::unique_ptr<cc::CopyOutputRequest> copy_output_request = |
214 RequestCopyRootLayerAndAnimateRotation(std::move(rotation_request)); | 167 cc::CopyOutputRequest::CreateRequest( |
| 168 CreateAfterCopyCallbackBeforeRotation(std::move(rotation_request))); |
| 169 RequestCopyScreenRotationContainerLayer(std::move(copy_output_request)); |
215 } else { | 170 } else { |
216 CreateOldLayerTree(); | 171 StartSlowAnimation(std::move(rotation_request)); |
217 AnimateRotation(std::move(rotation_request)); | |
218 } | 172 } |
219 } | 173 } |
220 | 174 |
221 void ScreenRotationAnimator::RequestCopyRootLayerAndAnimateRotation( | 175 void ScreenRotationAnimator::StartSlowAnimation( |
222 std::unique_ptr<ScreenRotationRequest> rotation_request) { | 176 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
223 std::unique_ptr<cc::CopyOutputRequest> copy_output_request = | 177 CreateOldLayerTree(); |
224 cc::CopyOutputRequest::CreateRequest( | 178 SetRotation(rotation_request->new_rotation, rotation_request->old_rotation, |
225 CreateAfterCopyCallback(std::move(rotation_request))); | 179 rotation_request->source); |
226 ui::Layer* layer = GetRootWindow(display_id_)->layer(); | 180 AnimateRotation(std::move(rotation_request)); |
227 copy_output_request->set_area(gfx::Rect(layer->size())); | 181 } |
228 layer->RequestCopyOfOutput(std::move(copy_output_request)); | 182 |
| 183 void ScreenRotationAnimator::SetRotation( |
| 184 display::Display::Rotation new_rotation, |
| 185 display::Display::Rotation old_rotation, |
| 186 display::Display::RotationSource source) { |
| 187 Shell::Get()->display_manager()->SetDisplayRotation(display_id_, new_rotation, |
| 188 source); |
| 189 const display::Display display = |
| 190 Shell::Get()->display_manager()->GetDisplayForId(display_id_); |
| 191 old_layer_tree_owner_->root()->SetTransform( |
| 192 CreateScreenRotationOldLayerTransformForDisplay(new_rotation, |
| 193 old_rotation, display)); |
| 194 } |
| 195 |
| 196 void ScreenRotationAnimator::RequestCopyScreenRotationContainerLayer( |
| 197 std::unique_ptr<cc::CopyOutputRequest> copy_output_request) { |
| 198 copy_output_request->set_area( |
| 199 gfx::Rect(screen_rotation_container_layer_->size())); |
| 200 screen_rotation_container_layer_->RequestCopyOfOutput( |
| 201 std::move(copy_output_request)); |
229 } | 202 } |
230 | 203 |
231 ScreenRotationAnimator::CopyCallback | 204 ScreenRotationAnimator::CopyCallback |
232 ScreenRotationAnimator::CreateAfterCopyCallback( | 205 ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation( |
233 std::unique_ptr<ScreenRotationRequest> rotation_request) { | 206 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
234 return base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation, | 207 return base::Bind(&ScreenRotationAnimator:: |
| 208 OnScreenRotationContainerLayerCopiedBeforeRotation, |
235 weak_factory_.GetWeakPtr(), | 209 weak_factory_.GetWeakPtr(), |
236 base::Passed(&rotation_request)); | 210 base::Passed(&rotation_request)); |
237 } | 211 } |
238 | 212 |
239 void ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation( | 213 ScreenRotationAnimator::CopyCallback |
| 214 ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation( |
| 215 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
| 216 return base::Bind(&ScreenRotationAnimator:: |
| 217 OnScreenRotationContainerLayerCopiedAfterRotation, |
| 218 weak_factory_.GetWeakPtr(), |
| 219 base::Passed(&rotation_request)); |
| 220 } |
| 221 |
| 222 void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation( |
240 std::unique_ptr<ScreenRotationRequest> rotation_request, | 223 std::unique_ptr<ScreenRotationRequest> rotation_request, |
241 std::unique_ptr<cc::CopyOutputResult> result) { | 224 std::unique_ptr<cc::CopyOutputResult> result) { |
242 // If display was removed, should abort rotation. | 225 // In the following cases, abort rotation: |
243 if (!IsDisplayIdValid(display_id_)) { | 226 // 1) if the display was removed, |
| 227 // 2) the copy request has been canceled or failed. It would fail if, |
| 228 // for examples: a) The layer is removed from the compositor and destroye |
| 229 // before committing the request to the compositor. b) The compositor is |
| 230 // shutdown. |
| 231 if (!IsDisplayIdValid(display_id_) || result->IsEmpty()) { |
244 ProcessAnimationQueue(); | 232 ProcessAnimationQueue(); |
| 233 rotation_request.reset(); |
245 return; | 234 return; |
246 } | 235 } |
247 | 236 |
248 // Fall back to recreate layers solution when the copy request has been | 237 old_layer_tree_owner_ = CopyLayerTree(std::move(result)); |
249 // canceled or failed. It would fail if, for examples: a) The layer is removed | 238 SetRotation(rotation_request->new_rotation, rotation_request->old_rotation, |
250 // from the compositor and destroyed before committing the request to the | 239 rotation_request->source); |
251 // compositor. b) The compositor is shutdown. | 240 std::unique_ptr<cc::CopyOutputRequest> copy_output_request = |
252 if (result->IsEmpty()) | 241 cc::CopyOutputRequest::CreateRequest( |
253 CreateOldLayerTree(); | 242 CreateAfterCopyCallbackAfterRotation(std::move(rotation_request))); |
254 else | 243 RequestCopyScreenRotationContainerLayer(std::move(copy_output_request)); |
255 CopyOldLayerTree(std::move(result)); | 244 } |
| 245 |
| 246 void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation( |
| 247 std::unique_ptr<ScreenRotationRequest> rotation_request, |
| 248 std::unique_ptr<cc::CopyOutputResult> result) { |
| 249 // In the following cases, abort rotation: |
| 250 // 1) if the display was removed, |
| 251 // 2) the copy request has been canceled or failed. It would fail if, |
| 252 // for examples: a) The layer is removed from the compositor and destroye |
| 253 // before committing the request to the compositor. b) The compositor is |
| 254 // shutdown. |
| 255 if (!IsDisplayIdValid(display_id_) || result->IsEmpty()) { |
| 256 ProcessAnimationQueue(); |
| 257 rotation_request.reset(); |
| 258 return; |
| 259 } |
| 260 |
| 261 new_layer_tree_owner_ = CopyLayerTree(std::move(result)); |
256 AnimateRotation(std::move(rotation_request)); | 262 AnimateRotation(std::move(rotation_request)); |
257 } | 263 } |
258 | 264 |
259 void ScreenRotationAnimator::CreateOldLayerTree() { | 265 void ScreenRotationAnimator::CreateOldLayerTree() { |
260 old_layer_tree_owner_ = ::wm::RecreateLayers(GetRootWindow(display_id_)); | 266 old_layer_tree_owner_ = ::wm::RecreateLayers(root_window_); |
| 267 AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root()); |
261 } | 268 } |
262 | 269 |
263 void ScreenRotationAnimator::CopyOldLayerTree( | 270 std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree( |
264 std::unique_ptr<cc::CopyOutputResult> result) { | 271 std::unique_ptr<cc::CopyOutputResult> result) { |
265 cc::TextureMailbox texture_mailbox; | 272 cc::TextureMailbox texture_mailbox; |
266 std::unique_ptr<cc::SingleReleaseCallback> release_callback; | 273 std::unique_ptr<cc::SingleReleaseCallback> release_callback; |
267 result->TakeTexture(&texture_mailbox, &release_callback); | 274 result->TakeTexture(&texture_mailbox, &release_callback); |
268 DCHECK(texture_mailbox.IsTexture()); | 275 DCHECK(texture_mailbox.IsTexture()); |
269 | 276 |
270 aura::Window* root_window = GetRootWindow(display_id_); | 277 gfx::Rect rect(root_window_->layer()->size()); |
271 gfx::Rect rect(root_window->layer()->size()); | |
272 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>(); | 278 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>(); |
273 copy_layer->SetBounds(rect); | 279 copy_layer->SetBounds(rect); |
274 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback), | 280 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback), |
275 rect.size()); | 281 rect.size()); |
276 old_layer_tree_owner_ = | 282 |
277 base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer)); | 283 AddLayerAtTopOfWindowLayers(root_window_, copy_layer.get()); |
| 284 return base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer)); |
278 } | 285 } |
279 | 286 |
280 void ScreenRotationAnimator::AnimateRotation( | 287 void ScreenRotationAnimator::AnimateRotation( |
281 std::unique_ptr<ScreenRotationRequest> rotation_request) { | 288 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
282 aura::Window* root_window = GetRootWindow(display_id_); | 289 const int rotation_factor = GetRotationFactor(rotation_request->old_rotation, |
283 std::unique_ptr<LayerCleanupObserver> old_layer_cleanup_observer( | 290 rotation_request->new_rotation); |
284 new LayerCleanupObserver(weak_factory_.GetWeakPtr())); | |
285 ui::Layer* old_root_layer = old_layer_tree_owner_->root(); | |
286 old_root_layer->set_name("ScreenRotationAnimator:old_layer_tree"); | |
287 // Add the cloned layer tree in to the root, so it will be rendered. | |
288 root_window->layer()->Add(old_root_layer); | |
289 root_window->layer()->StackAtTop(old_root_layer); | |
290 | |
291 const gfx::Rect original_screen_bounds = root_window->GetTargetBounds(); | |
292 | |
293 const int rotation_factor = GetRotationFactor( | |
294 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); | |
295 | |
296 const int old_layer_initial_rotation_degrees = GetInitialDegrees( | 291 const int old_layer_initial_rotation_degrees = GetInitialDegrees( |
297 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); | 292 rotation_request->old_rotation, rotation_request->new_rotation); |
298 | |
299 const base::TimeDelta duration = | 293 const base::TimeDelta duration = |
300 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); | 294 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); |
301 | |
302 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; | 295 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; |
303 | 296 const gfx::Rect rotated_screen_bounds = root_window_->GetTargetBounds(); |
304 Shell::Get()->display_manager()->SetDisplayRotation( | |
305 display_id_, rotation_request->new_rotation, rotation_request->source); | |
306 | |
307 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds(); | |
308 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, | 297 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, |
309 rotated_screen_bounds.height() / 2); | 298 rotated_screen_bounds.height() / 2); |
310 | 299 |
311 // We must animate each non-cloned child layer individually because the cloned | 300 ui::Layer* new_root_layer; |
312 // layer was added as a child to |root_window|'s layer so that it will be | 301 if (new_layer_tree_owner_ && has_switch_ash_enable_smooth_screen_rotation_) { |
313 // rendered. | 302 // Make the current layers invisible if the copy request after rotation is |
314 // TODO(bruthig): Add a NOT_DRAWN layer in between the root_window's layer and | 303 // succeesful. |
315 // its current children so that we only need to initiate two | 304 screen_rotation_container_layer_->SetOpacity(0.0f); |
316 // LayerAnimationSequences. One for the new layers and one for the old layer. | 305 new_root_layer = new_layer_tree_owner_->root(); |
317 for (ui::Layer* child_layer : root_window->layer()->children()) { | 306 } else { |
318 // Skip the cloned layer because it has a different animation. | 307 new_root_layer = screen_rotation_container_layer_; |
319 if (child_layer == old_root_layer) | |
320 continue; | |
321 | |
322 std::unique_ptr<ScreenRotationAnimation> screen_rotation = | |
323 base::MakeUnique<ScreenRotationAnimation>( | |
324 child_layer, kRotationDegrees * rotation_factor, | |
325 0 /* end_degrees */, child_layer->opacity(), | |
326 1.0f /* target_opacity */, pivot, duration, tween_type); | |
327 | |
328 ui::LayerAnimator* animator = child_layer->GetAnimator(); | |
329 animator->set_preemption_strategy( | |
330 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); | |
331 std::unique_ptr<ui::LayerAnimationSequence> animation_sequence = | |
332 base::MakeUnique<ui::LayerAnimationSequence>( | |
333 std::move(screen_rotation)); | |
334 animator->StartAnimation(animation_sequence.release()); | |
335 } | 308 } |
336 | 309 |
| 310 std::unique_ptr<ScreenRotationAnimation> new_layer_screen_rotation = |
| 311 base::MakeUnique<ScreenRotationAnimation>( |
| 312 new_root_layer, kRotationDegrees * rotation_factor, |
| 313 0 /* end_degrees */, 0.0f, |
| 314 new_root_layer->opacity() /* target_opacity */, pivot, duration, |
| 315 tween_type); |
| 316 |
| 317 ui::LayerAnimator* new_layer_animator = new_root_layer->GetAnimator(); |
| 318 new_layer_animator->set_preemption_strategy( |
| 319 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
| 320 std::unique_ptr<ui::LayerAnimationSequence> new_layer_animation_sequence = |
| 321 base::MakeUnique<ui::LayerAnimationSequence>( |
| 322 std::move(new_layer_screen_rotation)); |
| 323 |
| 324 ui::Layer* old_root_layer = old_layer_tree_owner_->root(); |
| 325 const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds(); |
337 // The old layer will also be transformed into the new orientation. We will | 326 // The old layer will also be transformed into the new orientation. We will |
338 // translate it so that the old layer's center point aligns with the new | 327 // translate it so that the old layer's center point aligns with the new |
339 // orientation's center point and use that center point as the pivot for the | 328 // orientation's center point and use that center point as the pivot for the |
340 // rotation animation. | 329 // rotation animation. |
341 gfx::Transform translate_transform; | 330 gfx::Transform translate_transform; |
342 translate_transform.Translate( | 331 translate_transform.Translate( |
343 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2, | 332 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2, |
344 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); | 333 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); |
345 old_root_layer->SetTransform(translate_transform); | 334 old_root_layer->SetTransform(translate_transform); |
346 | 335 |
347 std::unique_ptr<ScreenRotationAnimation> screen_rotation = | 336 std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation = |
348 base::MakeUnique<ScreenRotationAnimation>( | 337 base::MakeUnique<ScreenRotationAnimation>( |
349 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, | 338 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, |
350 (old_layer_initial_rotation_degrees - kRotationDegrees) * | 339 (old_layer_initial_rotation_degrees - kRotationDegrees) * |
351 rotation_factor, | 340 rotation_factor, |
352 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, | 341 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, |
353 tween_type); | 342 tween_type); |
354 | 343 |
355 ui::LayerAnimator* animator = old_root_layer->GetAnimator(); | 344 ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator(); |
356 animator->set_preemption_strategy( | 345 old_layer_animator->set_preemption_strategy( |
357 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); | 346 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
358 std::unique_ptr<ui::LayerAnimationSequence> animation_sequence = | 347 std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence = |
359 base::MakeUnique<ui::LayerAnimationSequence>(std::move(screen_rotation)); | 348 base::MakeUnique<ui::LayerAnimationSequence>( |
360 // Add an observer so that the cloned layers can be cleaned up with the | 349 std::move(old_layer_screen_rotation)); |
361 // animation completes/aborts. | 350 |
362 animation_sequence->AddObserver(old_layer_cleanup_observer.release()); | |
363 // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to | 351 // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to |
364 // control the animation. | 352 // control the animation. |
365 if (disable_animation_timers_for_test_) | 353 if (disable_animation_timers_for_test_) { |
366 animator->set_disable_timer_for_test(true); | 354 if (new_layer_tree_owner_) |
367 animation_sequence->SetAnimationMetricsReporter(metrics_reporter_.get()); | 355 new_layer_animator->set_disable_timer_for_test(true); |
368 animator->StartAnimation(animation_sequence.release()); | 356 old_layer_animator->set_disable_timer_for_test(true); |
| 357 } |
| 358 old_layer_animation_sequence->SetAnimationMetricsReporter( |
| 359 metrics_reporter_.get()); |
| 360 |
| 361 // Add an observer so that the cloned/copied layers can be cleaned up with the |
| 362 // animation completes/aborts. |
| 363 ui::CallbackLayerAnimationObserver* observer = |
| 364 new ui::CallbackLayerAnimationObserver( |
| 365 base::Bind(&AnimationEndedCallback, weak_factory_.GetWeakPtr())); |
| 366 if (new_layer_tree_owner_) |
| 367 new_layer_animator->AddObserver(observer); |
| 368 new_layer_animator->StartAnimation(new_layer_animation_sequence.release()); |
| 369 old_layer_animator->AddObserver(observer); |
| 370 old_layer_animator->StartAnimation(old_layer_animation_sequence.release()); |
| 371 observer->SetActive(); |
369 | 372 |
370 rotation_request.reset(); | 373 rotation_request.reset(); |
371 } | 374 } |
372 | 375 |
373 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, | 376 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, |
374 display::Display::RotationSource source) { | 377 display::Display::RotationSource source) { |
375 if (GetCurrentScreenRotation(display_id_) == new_rotation) | 378 const display::Display::Rotation current_rotation = |
| 379 GetCurrentScreenRotation(display_id_); |
| 380 if (current_rotation == new_rotation) |
376 return; | 381 return; |
377 | 382 |
| 383 has_switch_ash_enable_smooth_screen_rotation_ = |
| 384 base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 385 switches::kAshEnableSmoothScreenRotation); |
| 386 |
378 std::unique_ptr<ScreenRotationRequest> rotation_request = | 387 std::unique_ptr<ScreenRotationRequest> rotation_request = |
379 base::MakeUnique<ScreenRotationRequest>(new_rotation, source); | 388 base::MakeUnique<ScreenRotationRequest>(current_rotation, new_rotation, |
| 389 source); |
380 | 390 |
381 if (is_rotating_) { | 391 if (is_rotating_) { |
382 last_pending_request_ = std::move(rotation_request); | 392 last_pending_request_ = std::move(rotation_request); |
383 // The pending request will be processed when the | 393 // The pending request will be processed when the |
384 // OnLayerAnimation(Ended|Aborted) methods should be called after | 394 // OnLayerAnimation(Ended|Aborted) methods should be called after |
385 // StopAnimating(). | 395 // StopAnimating(). |
386 StopAnimating(); | 396 StopAnimating(); |
387 } else { | 397 } else { |
388 is_rotating_ = true; | 398 is_rotating_ = true; |
389 StartRotationAnimation(std::move(rotation_request)); | 399 StartRotationAnimation(std::move(rotation_request)); |
390 } | 400 } |
391 } | 401 } |
392 | 402 |
393 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver( | 403 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver( |
394 ScreenRotationAnimatorObserver* observer) { | 404 ScreenRotationAnimatorObserver* observer) { |
395 screen_rotation_animator_observers_.AddObserver(observer); | 405 screen_rotation_animator_observers_.AddObserver(observer); |
396 } | 406 } |
397 | 407 |
398 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( | 408 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( |
399 ScreenRotationAnimatorObserver* observer) { | 409 ScreenRotationAnimatorObserver* observer) { |
400 screen_rotation_animator_observers_.RemoveObserver(observer); | 410 screen_rotation_animator_observers_.RemoveObserver(observer); |
401 } | 411 } |
402 | 412 |
403 void ScreenRotationAnimator::ProcessAnimationQueue() { | 413 void ScreenRotationAnimator::ProcessAnimationQueue() { |
404 is_rotating_ = false; | 414 is_rotating_ = false; |
| 415 if (IsDisplayIdValid(display_id_)) |
| 416 screen_rotation_container_layer_->SetOpacity(1.0f); |
405 old_layer_tree_owner_.reset(); | 417 old_layer_tree_owner_.reset(); |
| 418 new_layer_tree_owner_.reset(); |
406 if (last_pending_request_ && IsDisplayIdValid(display_id_)) { | 419 if (last_pending_request_ && IsDisplayIdValid(display_id_)) { |
407 std::unique_ptr<ScreenRotationRequest> rotation_request = | 420 std::unique_ptr<ScreenRotationRequest> rotation_request = |
408 std::move(last_pending_request_); | 421 std::move(last_pending_request_); |
409 Rotate(rotation_request->new_rotation, rotation_request->source); | 422 Rotate(rotation_request->new_rotation, rotation_request->source); |
410 rotation_request.reset(); | 423 rotation_request.reset(); |
411 return; | 424 return; |
412 } | 425 } |
413 | 426 |
414 for (auto& observer : screen_rotation_animator_observers_) | 427 for (auto& observer : screen_rotation_animator_observers_) |
415 observer.OnScreenRotationAnimationFinished(this); | 428 observer.OnScreenRotationAnimationFinished(this); |
416 } | 429 } |
417 | 430 |
418 void ScreenRotationAnimator::set_disable_animation_timers_for_test( | 431 void ScreenRotationAnimator::set_disable_animation_timers_for_test( |
419 bool disable_timers) { | 432 bool disable_timers) { |
420 disable_animation_timers_for_test_ = disable_timers; | 433 disable_animation_timers_for_test_ = disable_timers; |
421 } | 434 } |
422 | 435 |
423 void ScreenRotationAnimator::StopAnimating() { | 436 void ScreenRotationAnimator::StopAnimating() { |
424 aura::Window* root_window = GetRootWindow(display_id_); | 437 // |old_layer_tree_owner_| new_layer_tree_owner_| could be nullptr if another |
425 for (ui::Layer* child_layer : root_window->layer()->children()) { | 438 // the rotation request comes before the copy request finished. |
426 if (child_layer == old_layer_tree_owner_->root()) | 439 if (old_layer_tree_owner_) |
427 continue; | 440 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); |
428 | 441 if (new_layer_tree_owner_) { |
429 child_layer->GetAnimator()->StopAnimating(); | 442 new_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); |
430 } | 443 } |
431 | 444 if (IsDisplayIdValid(display_id_)) |
432 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); | 445 screen_rotation_container_layer_->SetOpacity(1.0f); |
433 } | 446 } |
434 | 447 |
435 } // namespace ash | 448 } // namespace ash |
OLD | NEW |