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

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

Issue 2728803002: Handles users rotating screen too early (Closed)
Patch Set: Created 3 years, 9 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
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
(...skipping 16 matching lines...) Expand all
27 #include "ui/gfx/animation/tween.h" 27 #include "ui/gfx/animation/tween.h"
28 #include "ui/gfx/geometry/point.h" 28 #include "ui/gfx/geometry/point.h"
29 #include "ui/gfx/geometry/rect.h" 29 #include "ui/gfx/geometry/rect.h"
30 #include "ui/gfx/geometry/rect_f.h" 30 #include "ui/gfx/geometry/rect_f.h"
31 #include "ui/gfx/transform.h" 31 #include "ui/gfx/transform.h"
32 #include "ui/gfx/transform_util.h" 32 #include "ui/gfx/transform_util.h"
33 #include "ui/wm/core/window_util.h" 33 #include "ui/wm/core/window_util.h"
34 34
35 namespace ash { 35 namespace ash {
36 36
37 // struct ScreenRotationAnimator::RotationRequest {
bruthig 2017/03/02 18:25:45 Did you mean to remove this?
wutao 2017/03/03 02:45:52 Done.
38 // base::WeakPtr<ScreenRotationAnimator> animator;
39 // int64_t display_id;
40 // display::Display::Rotation initial_rotation;
41 // display::Display::Rotation new_rotation;
42 // display::Display::RotationSource source;
43 //};
44
45 ScreenRotationAnimator::ScreenRotationAnimatorObserver::
46 ScreenRotationAnimatorObserver() {}
47 ScreenRotationAnimator::ScreenRotationAnimatorObserver::
48 ~ScreenRotationAnimatorObserver() {}
49
50 void ScreenRotationAnimator::ScreenRotationAnimatorObserver::
51 OnEndedOrAbortedAnimation(base::WeakPtr<ScreenRotationAnimator> animator) {}
52
37 namespace { 53 namespace {
38 54
39 // The number of degrees that the rotation animations animate through. 55 // The number of degrees that the rotation animations animate through.
40 const int kRotationDegrees = 20; 56 const int kRotationDegrees = 20;
41 57
42 // The time it takes for the rotation animations to run. 58 // The time it takes for the rotation animations to run.
43 const int kRotationDurationInMs = 250; 59 const int kRotationDurationInMs = 250;
44 60
45 // Gets the current display rotation for the display with the specified 61 // The rotation directions
46 // |display_id|. 62 const int kCountClockWiseRotation = 1;
47 display::Display::Rotation GetCurrentRotation(int64_t display_id) { 63 const int kClockWiseRotation = -1;
48 return Shell::GetInstance() 64
49 ->display_manager() 65 int GetRotationFactor(display::Display::Rotation initial_rotation,
50 ->GetDisplayInfo(display_id) 66 display::Display::Rotation new_rotation) {
51 .GetActiveRotation(); 67 return (initial_rotation + 3) % 4 == new_rotation ? kCountClockWiseRotation
68 : kClockWiseRotation;
52 } 69 }
53 70
54 // Returns true if the rotation between |initial_rotation| and |new_rotation| is 71 // Returns true if the rotation between |initial_rotation| and |new_rotation| is
55 // 180 degrees. 72 // 180 degrees.
56 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, 73 bool Is180DegreeFlip(display::Display::Rotation initial_rotation,
57 display::Display::Rotation new_rotation) { 74 display::Display::Rotation new_rotation) {
58 return (initial_rotation + 2) % 4 == new_rotation; 75 return (initial_rotation + 2) % 4 == new_rotation;
59 } 76 }
60 77
78 // Returns the initial degrees the old layer animation to begin with.
79 int GetInitialDegrees(display::Display::Rotation initial_rotation,
80 display::Display::Rotation new_rotation) {
81 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90);
82 }
83
84 aura::Window* GetRootWindow(int64_t display_id) {
85 return Shell::GetInstance()
86 ->window_tree_host_manager()
87 ->GetRootWindowForDisplayId(display_id);
88 }
89
61 // A LayerAnimationObserver that will destroy the contained LayerTreeOwner when 90 // A LayerAnimationObserver that will destroy the contained LayerTreeOwner when
62 // notified that a layer animation has ended or was aborted. 91 // notified that a layer animation has ended or was aborted.
63 class LayerCleanupObserver : public ui::LayerAnimationObserver { 92 class LayerCleanupObserver : public ui::LayerAnimationObserver {
64 public: 93 public:
65 explicit LayerCleanupObserver( 94 explicit LayerCleanupObserver(
66 std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner); 95 std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner,
96 base::WeakPtr<ScreenRotationAnimator> animator);
67 ~LayerCleanupObserver() override; 97 ~LayerCleanupObserver() override;
68 98
69 // Get the root layer of the owned layer tree. 99 // Get the root layer of the owned layer tree.
70 ui::Layer* GetRootLayer(); 100 ui::Layer* GetRootLayer();
71 101
72 // ui::LayerAnimationObserver: 102 // ui::LayerAnimationObserver:
73 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override; 103 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override;
74 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override; 104 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override;
75 void OnLayerAnimationScheduled( 105 void OnLayerAnimationScheduled(
76 ui::LayerAnimationSequence* sequence) override {} 106 ui::LayerAnimationSequence* sequence) override {}
77 107
78 protected: 108 protected:
79 // ui::LayerAnimationObserver: 109 // ui::LayerAnimationObserver:
80 bool RequiresNotificationWhenAnimatorDestroyed() const override { 110 bool RequiresNotificationWhenAnimatorDestroyed() const override {
81 return true; 111 return true;
82 } 112 }
83 void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override; 113 void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override;
84 void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override; 114 void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override;
85 115
86 private: 116 private:
87 // Aborts the active animations of the layer, and recurses upon its child 117 // Aborts the active animations of the layer, and recurses upon its child
88 // layers. 118 // layers.
89 void AbortAnimations(ui::Layer* layer); 119 void AbortAnimations(ui::Layer* layer);
90 120
91 // The owned layer tree. 121 base::WeakPtr<ScreenRotationAnimator> animator_;
92 std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner_;
93 122
94 // The LayerAnimationSequence that |this| has been attached to. Defaults to 123 // The LayerAnimationSequence that |this| has been attached to. Defaults to
95 // nullptr. 124 // nullptr.
96 ui::LayerAnimationSequence* sequence_; 125 ui::LayerAnimationSequence* sequence_;
97 126
98 DISALLOW_COPY_AND_ASSIGN(LayerCleanupObserver); 127 DISALLOW_COPY_AND_ASSIGN(LayerCleanupObserver);
99 }; 128 };
100 129
101 LayerCleanupObserver::LayerCleanupObserver( 130 LayerCleanupObserver::LayerCleanupObserver(
102 std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner) 131 std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner,
103 : layer_tree_owner_(std::move(layer_tree_owner)), sequence_(nullptr) {} 132 base::WeakPtr<ScreenRotationAnimator> animator)
133 : animator_(animator), sequence_(nullptr) {
134 animator_->set_old_layer_tree_owner(layer_tree_owner.release());
135 }
104 136
105 LayerCleanupObserver::~LayerCleanupObserver() { 137 LayerCleanupObserver::~LayerCleanupObserver() {
106 // We must eplicitly detach from |sequence_| because we return true from 138 // We must eplicitly detach from |sequence_| because we return true from
107 // RequiresNotificationWhenAnimatorDestroyed. 139 // RequiresNotificationWhenAnimatorDestroyed.
108 if (sequence_) 140 if (sequence_)
109 sequence_->RemoveObserver(this); 141 sequence_->RemoveObserver(this);
110 AbortAnimations(layer_tree_owner_->root());
111 } 142 }
112 143
113 ui::Layer* LayerCleanupObserver::GetRootLayer() { 144 ui::Layer* LayerCleanupObserver::GetRootLayer() {
114 return layer_tree_owner_->root(); 145 if (animator_ && animator_->old_layer_tree_owner())
146 return animator_->old_layer_tree_owner()->root();
147 else {
148 NOTREACHED();
149 return nullptr;
150 }
115 } 151 }
116 152
117 void LayerCleanupObserver::OnLayerAnimationEnded( 153 void LayerCleanupObserver::OnLayerAnimationEnded(
118 ui::LayerAnimationSequence* sequence) { 154 ui::LayerAnimationSequence* sequence) {
155 if (animator_ && animator_->observer()) {
156 animator_->reset_old_layer_tree_owner();
157 animator_->observer()->OnEndedOrAbortedAnimation(animator_);
158 }
159
119 delete this; 160 delete this;
120 } 161 }
121 162
122 void LayerCleanupObserver::OnLayerAnimationAborted( 163 void LayerCleanupObserver::OnLayerAnimationAborted(
123 ui::LayerAnimationSequence* sequence) { 164 ui::LayerAnimationSequence* sequence) {
165 if (animator_ && animator_->observer()) {
166 AbortAnimations(animator_->old_layer_tree_owner()->root());
167 animator_->reset_old_layer_tree_owner();
168 animator_->observer()->OnEndedOrAbortedAnimation(animator_);
169 }
170
124 delete this; 171 delete this;
125 } 172 }
126 173
127 void LayerCleanupObserver::OnAttachedToSequence( 174 void LayerCleanupObserver::OnAttachedToSequence(
128 ui::LayerAnimationSequence* sequence) { 175 ui::LayerAnimationSequence* sequence) {
129 sequence_ = sequence; 176 sequence_ = sequence;
130 } 177 }
131 178
132 void LayerCleanupObserver::OnDetachedFromSequence( 179 void LayerCleanupObserver::OnDetachedFromSequence(
133 ui::LayerAnimationSequence* sequence) { 180 ui::LayerAnimationSequence* sequence) {
134 DCHECK_EQ(sequence, sequence_); 181 DCHECK_EQ(sequence, sequence_);
135 sequence_ = nullptr; 182 sequence_ = nullptr;
136 } 183 }
137 184
138 void LayerCleanupObserver::AbortAnimations(ui::Layer* layer) { 185 void LayerCleanupObserver::AbortAnimations(ui::Layer* layer) {
139 for (ui::Layer* child_layer : layer->children()) 186 for (ui::Layer* child_layer : layer->children())
140 AbortAnimations(child_layer); 187 AbortAnimations(child_layer);
141 layer->GetAnimator()->AbortAllAnimations(); 188 layer->GetAnimator()->AbortAllAnimations();
142 } 189 }
143 190
144 // Set the screen orientation for the given |display_id| to |new_rotation| and 191 // Set the screen orientation for the given |display_id| to |new_rotation| and
145 // animate the change. The animation will rotate the initial orientation's 192 // animate the change. The animation will rotate the initial orientation's
146 // layer towards the new orientation through |rotation_degrees| while fading 193 // layer towards the new orientation through |rotation_degrees| while fading
147 // out, and the new orientation's layer will be rotated in to the 194 // out, and the new orientation's layer will be rotated in to the
148 // |new_orientation| through |rotation_degrees| arc. 195 // |new_orientation| through |rotation_degrees| arc.
149 void RotateScreen(int64_t display_id, 196 void RotateScreen(
150 display::Display::Rotation new_rotation, 197 const ScreenRotationAnimator::ScreenRotationRequest rotation_request) {
151 display::Display::RotationSource source) { 198 rotation_request.animator->set_is_animating(true);
152 aura::Window* root_window = Shell::GetInstance()
153 ->window_tree_host_manager()
154 ->GetRootWindowForDisplayId(display_id);
155 199
156 const display::Display::Rotation initial_orientation = 200 aura::Window* root_window =
157 GetCurrentRotation(display_id); 201 GetRootWindow(rotation_request.animator->display_id());
158 202
159 const gfx::Rect original_screen_bounds = root_window->GetTargetBounds(); 203 const gfx::Rect original_screen_bounds = root_window->GetTargetBounds();
160 // 180 degree rotations should animate clock-wise. 204 // 180 degree rotations should animate clock-wise.
161 const int rotation_factor = 205 const int rotation_factor = GetRotationFactor(
162 (initial_orientation + 3) % 4 == new_rotation ? 1 : -1; 206 rotation_request.initial_rotation, rotation_request.new_rotation);
163 207
164 const int old_layer_initial_rotation_degrees = 208 const int old_layer_initial_rotation_degrees = GetInitialDegrees(
165 (Is180DegreeFlip(initial_orientation, new_rotation) ? 180 : 90); 209 rotation_request.initial_rotation, rotation_request.new_rotation);
166 210
167 const base::TimeDelta duration = 211 const base::TimeDelta duration =
168 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); 212 base::TimeDelta::FromMilliseconds(kRotationDurationInMs);
169 213
170 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; 214 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN;
171 215
172 std::unique_ptr<ui::LayerTreeOwner> old_layer_tree = 216 std::unique_ptr<ui::LayerTreeOwner> old_layer_tree =
173 ::wm::RecreateLayers(root_window); 217 ::wm::RecreateLayers(root_window);
218 old_layer_tree->root()->set_name("old_layer_tree");
174 219
175 // Add the cloned layer tree in to the root, so it will be rendered. 220 // Add the cloned layer tree in to the root, so it will be rendered.
176 root_window->layer()->Add(old_layer_tree->root()); 221 root_window->layer()->Add(old_layer_tree->root());
177 root_window->layer()->StackAtTop(old_layer_tree->root()); 222 root_window->layer()->StackAtTop(old_layer_tree->root());
178 223
179 std::unique_ptr<LayerCleanupObserver> layer_cleanup_observer( 224 std::unique_ptr<LayerCleanupObserver> layer_cleanup_observer(
180 new LayerCleanupObserver(std::move(old_layer_tree))); 225 new LayerCleanupObserver(std::move(old_layer_tree),
226 rotation_request.animator->WeakPtr()));
181 227
182 Shell::GetInstance()->display_manager()->SetDisplayRotation( 228 Shell::GetInstance()->display_manager()->SetDisplayRotation(
183 display_id, new_rotation, source); 229 rotation_request.animator->display_id(), rotation_request.new_rotation,
230 rotation_request.source);
184 231
185 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds(); 232 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds();
186 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, 233 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
187 rotated_screen_bounds.height() / 2); 234 rotated_screen_bounds.height() / 2);
188 235
189 // We must animate each non-cloned child layer individually because the cloned 236 // We must animate each non-cloned child layer individually because the cloned
190 // layer was added as a child to |root_window|'s layer so that it will be 237 // layer was added as a child to |root_window|'s layer so that it will be
191 // rendered. 238 // rendered.
192 // TODO(bruthig): Add a NOT_DRAWN layer in between the root_window's layer and 239 // TODO(bruthig): Add a NOT_DRAWN layer in between the root_window's layer and
193 // its current children so that we only need to initiate two 240 // its current children so that we only need to initiate two
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 base::MakeUnique<ui::LayerAnimationSequence>(std::move(screen_rotation)); 286 base::MakeUnique<ui::LayerAnimationSequence>(std::move(screen_rotation));
240 // Add an observer so that the cloned layers can be cleaned up with the 287 // Add an observer so that the cloned layers can be cleaned up with the
241 // animation completes/aborts. 288 // animation completes/aborts.
242 animation_sequence->AddObserver(layer_cleanup_observer.release()); 289 animation_sequence->AddObserver(layer_cleanup_observer.release());
243 animator->StartAnimation(animation_sequence.release()); 290 animator->StartAnimation(animation_sequence.release());
244 } 291 }
245 292
246 } // namespace 293 } // namespace
247 294
248 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) 295 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id)
249 : display_id_(display_id) {} 296 : display_id_(display_id),
297 is_animating_(false),
298 observer_(nullptr),
299 weak_factory_(this) {}
250 300
251 ScreenRotationAnimator::~ScreenRotationAnimator() {} 301 ScreenRotationAnimator::~ScreenRotationAnimator() {}
252 302
253 bool ScreenRotationAnimator::CanAnimate() const { 303 // Gets the current display rotation.
304 display::Display::Rotation ScreenRotationAnimator::GetCurrentRotation() const {
254 return Shell::GetInstance() 305 return Shell::GetInstance()
255 ->display_manager() 306 ->display_manager()
256 ->GetDisplayForId(display_id_) 307 ->GetDisplayInfo(display_id_)
257 .is_valid(); 308 .GetActiveRotation();
309 }
310
311 int64_t ScreenRotationAnimator::display_id() const {
312 return display_id_;
313 }
314
315 bool ScreenRotationAnimator::is_animating() const {
316 return is_animating_;
317 }
318
319 void ScreenRotationAnimator::set_is_animating(bool rotating) {
320 is_animating_ = rotating;
321 }
322
323 ScreenRotationAnimator::ScreenRotationAnimatorObserver*
324 ScreenRotationAnimator::observer() const {
325 return observer_;
326 }
327
328 void ScreenRotationAnimator::SetObserver(
329 ScreenRotationAnimatorObserver* observer) {
330 observer_ = observer;
331 }
332
333 void ScreenRotationAnimator::RemoveObserver() {
334 if (observer_)
335 observer_ = nullptr;
336 }
337
338 ui::LayerTreeOwner* ScreenRotationAnimator::old_layer_tree_owner() const {
339 return old_layer_tree_owner_.get();
340 }
341
342 void ScreenRotationAnimator::reset_old_layer_tree_owner() {
343 old_layer_tree_owner_.reset();
344 }
345
346 void ScreenRotationAnimator::set_old_layer_tree_owner(
347 ui::LayerTreeOwner* layer_tree_owner) {
348 old_layer_tree_owner_.reset(layer_tree_owner);
349 }
350
351 ScreenRotationAnimator::ScreenRotationRequest*
352 ScreenRotationAnimator::last_pending_request() const {
353 return last_pending_request_.get();
354 }
355
356 void ScreenRotationAnimator::reset_last_pending_request() {
357 last_pending_request_.reset();
358 }
359
360 base::WeakPtr<ScreenRotationAnimator> ScreenRotationAnimator::WeakPtr() {
361 return weak_factory_.GetWeakPtr();
258 } 362 }
259 363
260 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, 364 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation,
261 display::Display::RotationSource source) { 365 display::Display::RotationSource source) {
262 const display::Display::Rotation current_rotation = 366 std::unique_ptr<ScreenRotationRequest> rotation_request =
263 GetCurrentRotation(display_id_); 367 base::MakeUnique<ScreenRotationRequest>();
368 rotation_request->animator = this;
369 rotation_request->display_id = display_id_;
370 rotation_request->initial_rotation = GetCurrentRotation();
371 rotation_request->new_rotation = new_rotation;
372 rotation_request->source = source;
264 373
265 if (current_rotation == new_rotation) 374 if (is_animating()) {
266 return; 375 last_pending_request_.reset(rotation_request.release());
267 376
268 RotateScreen(display_id_, new_rotation, source); 377 aura::Window* root_window = GetRootWindow(display_id_);
378 for (ui::Layer* child_layer : root_window->layer()->children()) {
379 if (old_layer_tree_owner_ && child_layer == old_layer_tree_owner_->root())
380 continue;
381
382 child_layer->GetAnimator()->StopAnimating();
383 }
384
385 if (old_layer_tree_owner_) {
386 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
387 }
388 } else {
389 RotateScreen(*rotation_request);
390 rotation_request.reset();
391 }
269 } 392 }
270 393
271 } // namespace ash 394 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698