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

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

Issue 2728803002: Handles users rotating screen too early (Closed)
Patch Set: Rebased, reset is_rotating in layerCleanupObserver etc. 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 ScreenRotationAnimator::ScreenRotationAnimatorObserver::
38 ScreenRotationAnimatorObserver() {}
39 ScreenRotationAnimator::ScreenRotationAnimatorObserver::
bruthig 2017/03/08 22:35:59 nit: newline between c'tor and d'tor.
wutao 2017/03/09 22:09:19 Done.
40 ~ScreenRotationAnimatorObserver() {}
41
42 void ScreenRotationAnimator::ScreenRotationAnimatorObserver::
43 OnEndedOrAbortedAnimation(ScreenRotationAnimator* animator) {}
44
37 namespace { 45 namespace {
38 46
39 // The number of degrees that the rotation animations animate through. 47 // The number of degrees that the rotation animations animate through.
40 const int kRotationDegrees = 20; 48 const int kRotationDegrees = 20;
41 49
42 // The time it takes for the rotation animations to run. 50 // The time it takes for the rotation animations to run.
43 const int kRotationDurationInMs = 250; 51 const int kRotationDurationInMs = 250;
44 52
45 // Gets the current display rotation for the display with the specified 53 // The rotation directions
46 // |display_id|. 54 const int kCounterClockWiseRotation = 1;
47 display::Display::Rotation GetCurrentRotation(int64_t display_id) { 55 const int kClockWiseRotation = -1;
48 return Shell::GetInstance() 56
49 ->display_manager() 57 int GetRotationFactor(display::Display::Rotation initial_rotation,
50 ->GetDisplayInfo(display_id) 58 display::Display::Rotation new_rotation) {
51 .GetActiveRotation(); 59 return (initial_rotation + 3) % 4 == new_rotation ? kCounterClockWiseRotation
60 : kClockWiseRotation;
52 } 61 }
53 62
54 // Returns true if the rotation between |initial_rotation| and |new_rotation| is 63 // Returns true if the rotation between |initial_rotation| and |new_rotation| is
55 // 180 degrees. 64 // 180 degrees.
56 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, 65 bool Is180DegreeFlip(display::Display::Rotation initial_rotation,
57 display::Display::Rotation new_rotation) { 66 display::Display::Rotation new_rotation) {
58 return (initial_rotation + 2) % 4 == new_rotation; 67 return (initial_rotation + 2) % 4 == new_rotation;
59 } 68 }
60 69
70 // Returns the initial degrees the old layer animation to begin with.
71 int GetInitialDegrees(display::Display::Rotation initial_rotation,
72 display::Display::Rotation new_rotation) {
73 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90);
74 }
75
76 aura::Window* GetRootWindow(int64_t display_id) {
77 return Shell::GetInstance()
78 ->window_tree_host_manager()
79 ->GetRootWindowForDisplayId(display_id);
80 }
81
61 // A LayerAnimationObserver that will destroy the contained LayerTreeOwner when 82 // A LayerAnimationObserver that will destroy the contained LayerTreeOwner when
62 // notified that a layer animation has ended or was aborted. 83 // notified that a layer animation has ended or was aborted.
63 class LayerCleanupObserver : public ui::LayerAnimationObserver { 84 class LayerCleanupObserver : public ui::LayerAnimationObserver {
64 public: 85 public:
65 explicit LayerCleanupObserver( 86 explicit LayerCleanupObserver(
bruthig 2017/03/08 22:35:59 You should drop 'explicit' now that you have more
wutao 2017/03/09 22:09:19 Done.
66 std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner); 87 std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner,
88 ScreenRotationAnimator* animator);
67 ~LayerCleanupObserver() override; 89 ~LayerCleanupObserver() override;
68 90
69 // Get the root layer of the owned layer tree. 91 // Get the root layer of the owned layer tree.
70 ui::Layer* GetRootLayer(); 92 ui::Layer* GetRootLayer();
71 93
72 // ui::LayerAnimationObserver: 94 // ui::LayerAnimationObserver:
73 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override; 95 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override;
74 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override; 96 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override;
75 void OnLayerAnimationScheduled( 97 void OnLayerAnimationScheduled(
76 ui::LayerAnimationSequence* sequence) override {} 98 ui::LayerAnimationSequence* sequence) override {}
77 99
78 protected: 100 protected:
79 // ui::LayerAnimationObserver: 101 // ui::LayerAnimationObserver:
80 bool RequiresNotificationWhenAnimatorDestroyed() const override { 102 bool RequiresNotificationWhenAnimatorDestroyed() const override {
81 return true; 103 return true;
82 } 104 }
83 void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override; 105 void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override;
84 void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override; 106 void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override;
85 107
86 private: 108 private:
87 // Aborts the active animations of the layer, and recurses upon its child 109 // Aborts the active animations of the layer, and recurses upon its child
88 // layers. 110 // layers.
89 void AbortAnimations(ui::Layer* layer); 111 void AbortAnimations(ui::Layer* layer);
90 112
91 // The owned layer tree. 113 ScreenRotationAnimator* animator_;
92 std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner_;
93 114
94 // The LayerAnimationSequence that |this| has been attached to. Defaults to 115 // The LayerAnimationSequence that |this| has been attached to. Defaults to
95 // nullptr. 116 // nullptr.
96 ui::LayerAnimationSequence* sequence_; 117 ui::LayerAnimationSequence* sequence_;
97 118
98 DISALLOW_COPY_AND_ASSIGN(LayerCleanupObserver); 119 DISALLOW_COPY_AND_ASSIGN(LayerCleanupObserver);
99 }; 120 };
100 121
101 LayerCleanupObserver::LayerCleanupObserver( 122 LayerCleanupObserver::LayerCleanupObserver(
102 std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner) 123 std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner,
103 : layer_tree_owner_(std::move(layer_tree_owner)), sequence_(nullptr) {} 124 ScreenRotationAnimator* animator)
125 : animator_(animator), sequence_(nullptr) {
126 animator_->set_old_layer_tree_owner(layer_tree_owner.release());
127 }
104 128
105 LayerCleanupObserver::~LayerCleanupObserver() { 129 LayerCleanupObserver::~LayerCleanupObserver() {
106 // We must eplicitly detach from |sequence_| because we return true from 130 // We must eplicitly detach from |sequence_| because we return true from
107 // RequiresNotificationWhenAnimatorDestroyed. 131 // RequiresNotificationWhenAnimatorDestroyed.
108 if (sequence_) 132 if (sequence_)
109 sequence_->RemoveObserver(this); 133 sequence_->RemoveObserver(this);
110 AbortAnimations(layer_tree_owner_->root());
111 } 134 }
112 135
113 ui::Layer* LayerCleanupObserver::GetRootLayer() { 136 ui::Layer* LayerCleanupObserver::GetRootLayer() {
114 return layer_tree_owner_->root(); 137 if (animator_ && animator_->old_layer_tree_owner())
138 return animator_->old_layer_tree_owner()->root();
139 else {
140 NOTREACHED();
141 return nullptr;
142 }
115 } 143 }
116 144
117 void LayerCleanupObserver::OnLayerAnimationEnded( 145 void LayerCleanupObserver::OnLayerAnimationEnded(
118 ui::LayerAnimationSequence* sequence) { 146 ui::LayerAnimationSequence* sequence) {
147 if (animator_) {
bruthig 2017/03/08 22:35:59 Double check but I believe |this| may outlive the
wutao 2017/03/09 22:09:19 At second thought, when ~ScreenRotationAnimator()
148 animator_->set_is_rotating(false);
149 animator_->reset_old_layer_tree_owner();
150 if (animator_->observer())
151 animator_->observer()->OnEndedOrAbortedAnimation(animator_);
152 }
153
119 delete this; 154 delete this;
120 } 155 }
121 156
122 void LayerCleanupObserver::OnLayerAnimationAborted( 157 void LayerCleanupObserver::OnLayerAnimationAborted(
123 ui::LayerAnimationSequence* sequence) { 158 ui::LayerAnimationSequence* sequence) {
159 if (animator_) {
160 if (animator_->old_layer_tree_owner())
161 AbortAnimations(animator_->old_layer_tree_owner()->root());
162 animator_->set_is_rotating(false);
163 animator_->reset_old_layer_tree_owner();
164 if (animator_->observer())
165 animator_->observer()->OnEndedOrAbortedAnimation(animator_);
166 }
167
124 delete this; 168 delete this;
125 } 169 }
126 170
127 void LayerCleanupObserver::OnAttachedToSequence( 171 void LayerCleanupObserver::OnAttachedToSequence(
128 ui::LayerAnimationSequence* sequence) { 172 ui::LayerAnimationSequence* sequence) {
129 sequence_ = sequence; 173 sequence_ = sequence;
130 } 174 }
131 175
132 void LayerCleanupObserver::OnDetachedFromSequence( 176 void LayerCleanupObserver::OnDetachedFromSequence(
133 ui::LayerAnimationSequence* sequence) { 177 ui::LayerAnimationSequence* sequence) {
134 DCHECK_EQ(sequence, sequence_); 178 DCHECK_EQ(sequence, sequence_);
135 sequence_ = nullptr; 179 sequence_ = nullptr;
136 } 180 }
137 181
138 void LayerCleanupObserver::AbortAnimations(ui::Layer* layer) { 182 void LayerCleanupObserver::AbortAnimations(ui::Layer* layer) {
139 for (ui::Layer* child_layer : layer->children()) 183 for (ui::Layer* child_layer : layer->children())
140 AbortAnimations(child_layer); 184 AbortAnimations(child_layer);
141 layer->GetAnimator()->AbortAllAnimations(); 185 layer->GetAnimator()->AbortAllAnimations();
142 } 186 }
143 187
144 // Set the screen orientation for the given |display_id| to |new_rotation| and 188 // 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 189 // animate the change. The animation will rotate the initial orientation's
146 // layer towards the new orientation through |rotation_degrees| while fading 190 // layer towards the new orientation through |rotation_degrees| while fading
147 // out, and the new orientation's layer will be rotated in to the 191 // out, and the new orientation's layer will be rotated in to the
148 // |new_orientation| through |rotation_degrees| arc. 192 // |new_orientation| through |rotation_degrees| arc.
149 void RotateScreen(int64_t display_id, 193 void RotateScreen(
150 display::Display::Rotation new_rotation, 194 const ScreenRotationAnimator::ScreenRotationRequest& rotation_request) {
151 display::Display::RotationSource source) { 195 rotation_request.animator->set_is_rotating(true);
152 aura::Window* root_window = Shell::GetInstance()
153 ->window_tree_host_manager()
154 ->GetRootWindowForDisplayId(display_id);
155 196
156 const display::Display::Rotation initial_orientation = 197 aura::Window* root_window = GetRootWindow(rotation_request.display_id);
157 GetCurrentRotation(display_id);
158 198
159 const gfx::Rect original_screen_bounds = root_window->GetTargetBounds(); 199 const gfx::Rect original_screen_bounds = root_window->GetTargetBounds();
160 // 180 degree rotations should animate clock-wise. 200 // 180 degree rotations should animate clock-wise.
161 const int rotation_factor = 201 const int rotation_factor = GetRotationFactor(
162 (initial_orientation + 3) % 4 == new_rotation ? 1 : -1; 202 rotation_request.initial_rotation, rotation_request.new_rotation);
163 203
164 const int old_layer_initial_rotation_degrees = 204 const int old_layer_initial_rotation_degrees = GetInitialDegrees(
165 (Is180DegreeFlip(initial_orientation, new_rotation) ? 180 : 90); 205 rotation_request.initial_rotation, rotation_request.new_rotation);
166 206
167 const base::TimeDelta duration = 207 const base::TimeDelta duration =
168 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); 208 base::TimeDelta::FromMilliseconds(kRotationDurationInMs);
169 209
170 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; 210 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN;
171 211
172 std::unique_ptr<ui::LayerTreeOwner> old_layer_tree = 212 std::unique_ptr<ui::LayerTreeOwner> old_layer_tree =
173 ::wm::RecreateLayers(root_window); 213 ::wm::RecreateLayers(root_window);
214 old_layer_tree->root()->set_name("old_layer_tree");
bruthig 2017/03/08 22:35:59 "old_layer_tree" will be pretty ambiguous to someo
wutao 2017/03/09 22:09:19 Done.
174 215
175 // Add the cloned layer tree in to the root, so it will be rendered. 216 // Add the cloned layer tree in to the root, so it will be rendered.
176 root_window->layer()->Add(old_layer_tree->root()); 217 root_window->layer()->Add(old_layer_tree->root());
177 root_window->layer()->StackAtTop(old_layer_tree->root()); 218 root_window->layer()->StackAtTop(old_layer_tree->root());
178 219
179 std::unique_ptr<LayerCleanupObserver> layer_cleanup_observer( 220 std::unique_ptr<LayerCleanupObserver> layer_cleanup_observer(
180 new LayerCleanupObserver(std::move(old_layer_tree))); 221 new LayerCleanupObserver(std::move(old_layer_tree),
bruthig 2017/03/08 22:35:59 Is there any reason that the ScreenRotationAnimato
wutao 2017/03/09 22:09:19 No. Only reason is that I plan to remove LayerClea
222 rotation_request.animator));
181 223
182 Shell::GetInstance()->display_manager()->SetDisplayRotation( 224 Shell::GetInstance()->display_manager()->SetDisplayRotation(
183 display_id, new_rotation, source); 225 rotation_request.display_id, rotation_request.new_rotation,
226 rotation_request.source);
184 227
185 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds(); 228 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds();
186 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, 229 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
187 rotated_screen_bounds.height() / 2); 230 rotated_screen_bounds.height() / 2);
188 231
189 // We must animate each non-cloned child layer individually because the cloned 232 // 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 233 // layer was added as a child to |root_window|'s layer so that it will be
191 // rendered. 234 // rendered.
192 // TODO(bruthig): Add a NOT_DRAWN layer in between the root_window's layer and 235 // 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 236 // 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)); 282 base::MakeUnique<ui::LayerAnimationSequence>(std::move(screen_rotation));
240 // Add an observer so that the cloned layers can be cleaned up with the 283 // Add an observer so that the cloned layers can be cleaned up with the
241 // animation completes/aborts. 284 // animation completes/aborts.
242 animation_sequence->AddObserver(layer_cleanup_observer.release()); 285 animation_sequence->AddObserver(layer_cleanup_observer.release());
243 animator->StartAnimation(animation_sequence.release()); 286 animator->StartAnimation(animation_sequence.release());
244 } 287 }
245 288
246 } // namespace 289 } // namespace
247 290
248 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) 291 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id)
249 : display_id_(display_id) {} 292 : display_id_(display_id), is_rotating_(false), observer_(nullptr) {}
250 293
251 ScreenRotationAnimator::~ScreenRotationAnimator() {} 294 ScreenRotationAnimator::~ScreenRotationAnimator() {}
252 295
253 bool ScreenRotationAnimator::CanAnimate() const {
254 return Shell::GetInstance()
255 ->display_manager()
256 ->GetDisplayForId(display_id_)
257 .is_valid();
258 }
259
260 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, 296 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation,
261 display::Display::RotationSource source) { 297 display::Display::RotationSource source) {
262 const display::Display::Rotation current_rotation = 298 const display::Display::Rotation initial_rotation =
263 GetCurrentRotation(display_id_); 299 Shell::GetInstance()
300 ->display_manager()
301 ->GetDisplayInfo(display_id_)
302 .GetActiveRotation();
264 303
265 if (current_rotation == new_rotation) 304 if (initial_rotation == new_rotation)
266 return; 305 return;
267 306
268 RotateScreen(display_id_, new_rotation, source); 307 std::unique_ptr<ScreenRotationRequest> rotation_request =
308 base::MakeUnique<ScreenRotationRequest>();
309 rotation_request->animator = this;
310 rotation_request->display_id = display_id_;
311 rotation_request->initial_rotation = initial_rotation;
312 rotation_request->new_rotation = new_rotation;
313 rotation_request->source = source;
314
315 if (is_rotating()) {
316 last_pending_request_.reset(rotation_request.release());
bruthig 2017/03/08 22:35:59 nit: For readability, consider wrapping this code
wutao 2017/03/09 22:09:19 Done.
317
318 aura::Window* root_window = GetRootWindow(display_id_);
319 for (ui::Layer* child_layer : root_window->layer()->children()) {
320 if (old_layer_tree_owner_ && child_layer == old_layer_tree_owner_->root())
321 continue;
322
323 child_layer->GetAnimator()->StopAnimating();
324 }
325
326 if (old_layer_tree_owner_) {
327 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
328 }
329 } else {
330 last_pending_request_.reset();
331 RotateScreen(*rotation_request);
332 rotation_request.reset();
333 }
269 } 334 }
270 335
271 } // namespace ash 336 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698