OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "components/mus/ws/animation_runner.h" | |
6 | |
7 #include "base/strings/stringprintf.h" | |
8 #include "components/mus/public/interfaces/window_manager_constants.mojom.h" | |
9 #include "components/mus/ws/animation_runner_observer.h" | |
10 #include "components/mus/ws/scheduled_animation_group.h" | |
11 #include "components/mus/ws/server_window.h" | |
12 #include "components/mus/ws/test_server_window_delegate.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 | |
15 using base::TimeDelta; | |
16 | |
17 namespace mus { | |
18 using mojom::AnimationProperty; | |
19 using mojom::AnimationTweenType; | |
20 using mojom::AnimationElement; | |
21 using mojom::AnimationGroup; | |
22 using mojom::AnimationProperty; | |
23 using mojom::AnimationSequence; | |
24 using mojom::AnimationTweenType; | |
25 using mojom::AnimationValue; | |
26 using mojom::AnimationValuePtr; | |
27 | |
28 namespace ws { | |
29 namespace { | |
30 | |
31 class TestAnimationRunnerObserver : public AnimationRunnerObserver { | |
32 public: | |
33 TestAnimationRunnerObserver() {} | |
34 ~TestAnimationRunnerObserver() override {} | |
35 | |
36 std::vector<std::string>* changes() { return &changes_; } | |
37 std::vector<uint32_t>* change_ids() { return &change_ids_; } | |
38 | |
39 void clear_changes() { | |
40 changes_.clear(); | |
41 change_ids_.clear(); | |
42 } | |
43 | |
44 // AnimationRunnerDelgate: | |
45 void OnAnimationScheduled(uint32_t id) override { | |
46 change_ids_.push_back(id); | |
47 changes_.push_back("scheduled"); | |
48 } | |
49 void OnAnimationDone(uint32_t id) override { | |
50 change_ids_.push_back(id); | |
51 changes_.push_back("done"); | |
52 } | |
53 void OnAnimationInterrupted(uint32_t id) override { | |
54 change_ids_.push_back(id); | |
55 changes_.push_back("interrupted"); | |
56 } | |
57 void OnAnimationCanceled(uint32_t id) override { | |
58 change_ids_.push_back(id); | |
59 changes_.push_back("canceled"); | |
60 } | |
61 | |
62 private: | |
63 std::vector<uint32_t> change_ids_; | |
64 std::vector<std::string> changes_; | |
65 | |
66 DISALLOW_COPY_AND_ASSIGN(TestAnimationRunnerObserver); | |
67 }; | |
68 | |
69 // Creates an AnimationValuePtr from the specified float value. | |
70 AnimationValuePtr FloatAnimationValue(float float_value) { | |
71 AnimationValuePtr value(AnimationValue::New()); | |
72 value->float_value = float_value; | |
73 return value; | |
74 } | |
75 | |
76 // Creates an AnimationValuePtr from the specified transform. | |
77 AnimationValuePtr TransformAnimationValue(const gfx::Transform& transform) { | |
78 AnimationValuePtr value(AnimationValue::New()); | |
79 value->transform = transform; | |
80 return value; | |
81 } | |
82 | |
83 // Adds an AnimationElement to |group|s last sequence with the specified value. | |
84 void AddElement(AnimationGroup* group, | |
85 TimeDelta time, | |
86 AnimationValuePtr start_value, | |
87 AnimationValuePtr target_value, | |
88 AnimationProperty property, | |
89 AnimationTweenType tween_type) { | |
90 AnimationSequence& sequence = | |
91 *(group->sequences[group->sequences.size() - 1]); | |
92 sequence.elements.push_back(AnimationElement::New()); | |
93 AnimationElement& element = | |
94 *(sequence.elements[sequence.elements.size() - 1]); | |
95 element.property = property; | |
96 element.duration = time.InMicroseconds(); | |
97 element.tween_type = tween_type; | |
98 element.start_value = std::move(start_value); | |
99 element.target_value = std::move(target_value); | |
100 } | |
101 | |
102 void AddOpacityElement(AnimationGroup* group, | |
103 TimeDelta time, | |
104 AnimationValuePtr start_value, | |
105 AnimationValuePtr target_value) { | |
106 AddElement(group, time, std::move(start_value), std::move(target_value), | |
107 AnimationProperty::OPACITY, AnimationTweenType::LINEAR); | |
108 } | |
109 | |
110 void AddTransformElement(AnimationGroup* group, | |
111 TimeDelta time, | |
112 AnimationValuePtr start_value, | |
113 AnimationValuePtr target_value) { | |
114 AddElement(group, time, std::move(start_value), std::move(target_value), | |
115 AnimationProperty::TRANSFORM, AnimationTweenType::LINEAR); | |
116 } | |
117 | |
118 void AddPauseElement(AnimationGroup* group, TimeDelta time) { | |
119 AddElement(group, time, AnimationValuePtr(), AnimationValuePtr(), | |
120 AnimationProperty::NONE, AnimationTweenType::LINEAR); | |
121 } | |
122 | |
123 void InitGroupForWindow(AnimationGroup* group, | |
124 const WindowId& id, | |
125 int cycle_count) { | |
126 group->window_id = WindowIdToTransportId(id); | |
127 group->sequences.push_back(AnimationSequence::New()); | |
128 group->sequences[group->sequences.size() - 1]->cycle_count = cycle_count; | |
129 } | |
130 | |
131 } // namespace | |
132 | |
133 class AnimationRunnerTest : public testing::Test { | |
134 public: | |
135 AnimationRunnerTest() | |
136 : initial_time_(base::TimeTicks::Now()), runner_(initial_time_) { | |
137 runner_.AddObserver(&runner_observer_); | |
138 } | |
139 ~AnimationRunnerTest() override { runner_.RemoveObserver(&runner_observer_); } | |
140 | |
141 protected: | |
142 // Convenience to schedule an animation for a single window/group pair. | |
143 AnimationRunner::AnimationId ScheduleForSingleWindow( | |
144 ServerWindow* window, | |
145 const AnimationGroup* group, | |
146 base::TimeTicks now) { | |
147 std::vector<AnimationRunner::WindowAndAnimationPair> pairs; | |
148 pairs.push_back(std::make_pair(window, group)); | |
149 return runner_.Schedule(pairs, now); | |
150 } | |
151 | |
152 // If |id| is valid and there is only one window schedule against the | |
153 // animation it is returned; otherwise returns null. | |
154 ServerWindow* GetSingleWindowAnimating(AnimationRunner::AnimationId id) { | |
155 std::set<ServerWindow*> windows(runner_.GetWindowsAnimating(id)); | |
156 return windows.size() == 1 ? *windows.begin() : nullptr; | |
157 } | |
158 | |
159 const base::TimeTicks initial_time_; | |
160 TestAnimationRunnerObserver runner_observer_; | |
161 AnimationRunner runner_; | |
162 | |
163 private: | |
164 DISALLOW_COPY_AND_ASSIGN(AnimationRunnerTest); | |
165 }; | |
166 | |
167 // Opacity from 1 to .5 over 1000. | |
168 TEST_F(AnimationRunnerTest, SingleProperty) { | |
169 TestServerWindowDelegate window_delegate; | |
170 ServerWindow window(&window_delegate, WindowId()); | |
171 | |
172 AnimationGroup group; | |
173 InitGroupForWindow(&group, window.id(), 1); | |
174 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
175 AnimationValuePtr(), FloatAnimationValue(.5)); | |
176 | |
177 const uint32_t animation_id = | |
178 ScheduleForSingleWindow(&window, &group, initial_time_); | |
179 | |
180 ASSERT_EQ(1u, runner_observer_.changes()->size()); | |
181 EXPECT_EQ("scheduled", runner_observer_.changes()->at(0)); | |
182 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); | |
183 runner_observer_.clear_changes(); | |
184 | |
185 EXPECT_TRUE(runner_.HasAnimations()); | |
186 | |
187 // Opacity should still be 1 (the initial value). | |
188 EXPECT_EQ(1.f, window.opacity()); | |
189 | |
190 // Animate half way. | |
191 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); | |
192 | |
193 EXPECT_EQ(.75f, window.opacity()); | |
194 EXPECT_TRUE(runner_observer_.changes()->empty()); | |
195 | |
196 // Run well past the end. Value should progress to end and delegate should | |
197 // be notified. | |
198 runner_.Tick(initial_time_ + TimeDelta::FromSeconds(10)); | |
199 EXPECT_EQ(.5f, window.opacity()); | |
200 | |
201 ASSERT_EQ(1u, runner_observer_.changes()->size()); | |
202 EXPECT_EQ("done", runner_observer_.changes()->at(0)); | |
203 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); | |
204 | |
205 EXPECT_FALSE(runner_.HasAnimations()); | |
206 } | |
207 | |
208 // Opacity from 1 to .5, followed by transform from identity to 2x,3x. | |
209 TEST_F(AnimationRunnerTest, TwoPropertiesInSequence) { | |
210 TestServerWindowDelegate window_delegate; | |
211 ServerWindow window(&window_delegate, WindowId()); | |
212 | |
213 AnimationGroup group; | |
214 InitGroupForWindow(&group, window.id(), 1); | |
215 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
216 AnimationValuePtr(), FloatAnimationValue(.5f)); | |
217 | |
218 gfx::Transform done_transform; | |
219 done_transform.Scale(2, 4); | |
220 AddTransformElement(&group, TimeDelta::FromMicroseconds(2000), | |
221 AnimationValuePtr(), | |
222 TransformAnimationValue(done_transform)); | |
223 | |
224 const uint32_t animation_id = | |
225 ScheduleForSingleWindow(&window, &group, initial_time_); | |
226 runner_observer_.clear_changes(); | |
227 | |
228 // Nothing in the window should have changed yet. | |
229 EXPECT_EQ(1.f, window.opacity()); | |
230 EXPECT_TRUE(window.transform().IsIdentity()); | |
231 | |
232 // Animate half way from through opacity animation. | |
233 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); | |
234 | |
235 EXPECT_EQ(.75f, window.opacity()); | |
236 EXPECT_TRUE(window.transform().IsIdentity()); | |
237 | |
238 // Finish first element (opacity). | |
239 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1000)); | |
240 EXPECT_EQ(.5f, window.opacity()); | |
241 EXPECT_TRUE(window.transform().IsIdentity()); | |
242 | |
243 // Half way through second (transform). | |
244 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(2000)); | |
245 EXPECT_EQ(.5f, window.opacity()); | |
246 gfx::Transform half_way_transform; | |
247 half_way_transform.Scale(1.5, 2.5); | |
248 EXPECT_EQ(half_way_transform, window.transform()); | |
249 | |
250 EXPECT_TRUE(runner_observer_.changes()->empty()); | |
251 | |
252 // To end. | |
253 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(3500)); | |
254 EXPECT_EQ(.5f, window.opacity()); | |
255 EXPECT_EQ(done_transform, window.transform()); | |
256 | |
257 ASSERT_EQ(1u, runner_observer_.changes()->size()); | |
258 EXPECT_EQ("done", runner_observer_.changes()->at(0)); | |
259 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); | |
260 } | |
261 | |
262 // Opacity from .5 to 1 over 1000, transform to 2x,4x over 500. | |
263 TEST_F(AnimationRunnerTest, TwoPropertiesInParallel) { | |
264 TestServerWindowDelegate window_delegate; | |
265 ServerWindow window(&window_delegate, WindowId(1, 1)); | |
266 | |
267 AnimationGroup group; | |
268 InitGroupForWindow(&group, window.id(), 1); | |
269 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
270 FloatAnimationValue(.5f), FloatAnimationValue(1)); | |
271 | |
272 group.sequences.push_back(AnimationSequence::New()); | |
273 group.sequences[1]->cycle_count = 1; | |
274 gfx::Transform done_transform; | |
275 done_transform.Scale(2, 4); | |
276 AddTransformElement(&group, TimeDelta::FromMicroseconds(500), | |
277 AnimationValuePtr(), | |
278 TransformAnimationValue(done_transform)); | |
279 | |
280 const uint32_t animation_id = | |
281 ScheduleForSingleWindow(&window, &group, initial_time_); | |
282 | |
283 runner_observer_.clear_changes(); | |
284 | |
285 // Nothing in the window should have changed yet. | |
286 EXPECT_EQ(1.f, window.opacity()); | |
287 EXPECT_TRUE(window.transform().IsIdentity()); | |
288 | |
289 // Animate to 250, which is 1/4 way through opacity and half way through | |
290 // transform. | |
291 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(250)); | |
292 | |
293 EXPECT_EQ(.625f, window.opacity()); | |
294 gfx::Transform half_way_transform; | |
295 half_way_transform.Scale(1.5, 2.5); | |
296 EXPECT_EQ(half_way_transform, window.transform()); | |
297 | |
298 // Animate to 500, which is 1/2 way through opacity and transform done. | |
299 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); | |
300 EXPECT_EQ(.75f, window.opacity()); | |
301 EXPECT_EQ(done_transform, window.transform()); | |
302 | |
303 // Animate to 750, which is 3/4 way through opacity and transform done. | |
304 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(750)); | |
305 EXPECT_EQ(.875f, window.opacity()); | |
306 EXPECT_EQ(done_transform, window.transform()); | |
307 | |
308 EXPECT_TRUE(runner_observer_.changes()->empty()); | |
309 | |
310 // To end. | |
311 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(3500)); | |
312 EXPECT_EQ(1.f, window.opacity()); | |
313 EXPECT_EQ(done_transform, window.transform()); | |
314 | |
315 ASSERT_EQ(1u, runner_observer_.changes()->size()); | |
316 EXPECT_EQ("done", runner_observer_.changes()->at(0)); | |
317 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); | |
318 } | |
319 | |
320 // Opacity from .5 to 1 over 1000, pause for 500, 1 to .5 over 500, with a cycle | |
321 // count of 3. | |
322 TEST_F(AnimationRunnerTest, Cycles) { | |
323 TestServerWindowDelegate window_delegate; | |
324 ServerWindow window(&window_delegate, WindowId(1, 2)); | |
325 | |
326 window.SetOpacity(.5f); | |
327 | |
328 AnimationGroup group; | |
329 InitGroupForWindow(&group, window.id(), 3); | |
330 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
331 AnimationValuePtr(), FloatAnimationValue(1)); | |
332 AddPauseElement(&group, TimeDelta::FromMicroseconds(500)); | |
333 AddOpacityElement(&group, TimeDelta::FromMicroseconds(500), | |
334 AnimationValuePtr(), FloatAnimationValue(.5)); | |
335 | |
336 ScheduleForSingleWindow(&window, &group, initial_time_); | |
337 runner_observer_.clear_changes(); | |
338 | |
339 // Nothing in the window should have changed yet. | |
340 EXPECT_EQ(.5f, window.opacity()); | |
341 | |
342 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); | |
343 EXPECT_EQ(.75f, window.opacity()); | |
344 | |
345 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1250)); | |
346 EXPECT_EQ(1.f, window.opacity()); | |
347 | |
348 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1750)); | |
349 EXPECT_EQ(.75f, window.opacity()); | |
350 | |
351 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(2500)); | |
352 EXPECT_EQ(.75f, window.opacity()); | |
353 | |
354 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(3250)); | |
355 EXPECT_EQ(1.f, window.opacity()); | |
356 | |
357 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(3750)); | |
358 EXPECT_EQ(.75f, window.opacity()); | |
359 | |
360 // Animate to the end. | |
361 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(6500)); | |
362 EXPECT_EQ(.5f, window.opacity()); | |
363 | |
364 ASSERT_EQ(1u, runner_observer_.changes()->size()); | |
365 EXPECT_EQ("done", runner_observer_.changes()->at(0)); | |
366 } | |
367 | |
368 // Verifies scheduling the same window twice sends an interrupt. | |
369 TEST_F(AnimationRunnerTest, ScheduleTwice) { | |
370 TestServerWindowDelegate window_delegate; | |
371 ServerWindow window(&window_delegate, WindowId(1, 2)); | |
372 | |
373 AnimationGroup group; | |
374 InitGroupForWindow(&group, window.id(), 1); | |
375 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
376 AnimationValuePtr(), FloatAnimationValue(.5)); | |
377 | |
378 const uint32_t animation_id = | |
379 ScheduleForSingleWindow(&window, &group, initial_time_); | |
380 runner_observer_.clear_changes(); | |
381 | |
382 // Animate half way. | |
383 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); | |
384 | |
385 EXPECT_EQ(.75f, window.opacity()); | |
386 EXPECT_TRUE(runner_observer_.changes()->empty()); | |
387 | |
388 // Schedule again. We should get an interrupt, but opacity shouldn't change. | |
389 const uint32_t animation2_id = ScheduleForSingleWindow( | |
390 &window, &group, initial_time_ + TimeDelta::FromMicroseconds(500)); | |
391 | |
392 // Id should have changed. | |
393 EXPECT_NE(animation_id, animation2_id); | |
394 | |
395 EXPECT_FALSE(runner_.IsAnimating(animation_id)); | |
396 EXPECT_EQ(&window, GetSingleWindowAnimating(animation2_id)); | |
397 | |
398 EXPECT_EQ(.75f, window.opacity()); | |
399 EXPECT_EQ(2u, runner_observer_.changes()->size()); | |
400 EXPECT_EQ("interrupted", runner_observer_.changes()->at(0)); | |
401 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); | |
402 EXPECT_EQ("scheduled", runner_observer_.changes()->at(1)); | |
403 EXPECT_EQ(animation2_id, runner_observer_.change_ids()->at(1)); | |
404 runner_observer_.clear_changes(); | |
405 | |
406 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1000)); | |
407 EXPECT_EQ(.625f, window.opacity()); | |
408 EXPECT_TRUE(runner_observer_.changes()->empty()); | |
409 | |
410 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(2000)); | |
411 EXPECT_EQ(.5f, window.opacity()); | |
412 EXPECT_EQ(1u, runner_observer_.changes()->size()); | |
413 EXPECT_EQ("done", runner_observer_.changes()->at(0)); | |
414 EXPECT_EQ(animation2_id, runner_observer_.change_ids()->at(0)); | |
415 } | |
416 | |
417 // Verifies Remove() works. | |
418 TEST_F(AnimationRunnerTest, CancelAnimationForWindow) { | |
419 // Create an animation and advance it part way. | |
420 TestServerWindowDelegate window_delegate; | |
421 ServerWindow window(&window_delegate, WindowId()); | |
422 AnimationGroup group; | |
423 InitGroupForWindow(&group, window.id(), 1); | |
424 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
425 AnimationValuePtr(), FloatAnimationValue(.5)); | |
426 | |
427 const uint32_t animation_id = | |
428 ScheduleForSingleWindow(&window, &group, initial_time_); | |
429 runner_observer_.clear_changes(); | |
430 EXPECT_EQ(&window, GetSingleWindowAnimating(animation_id)); | |
431 | |
432 EXPECT_TRUE(runner_.HasAnimations()); | |
433 | |
434 // Animate half way. | |
435 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); | |
436 EXPECT_EQ(.75f, window.opacity()); | |
437 EXPECT_TRUE(runner_observer_.changes()->empty()); | |
438 | |
439 // Cancel the animation. | |
440 runner_.CancelAnimationForWindow(&window); | |
441 | |
442 EXPECT_FALSE(runner_.HasAnimations()); | |
443 EXPECT_EQ(nullptr, GetSingleWindowAnimating(animation_id)); | |
444 | |
445 EXPECT_EQ(.75f, window.opacity()); | |
446 | |
447 EXPECT_EQ(1u, runner_observer_.changes()->size()); | |
448 EXPECT_EQ("canceled", runner_observer_.changes()->at(0)); | |
449 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); | |
450 } | |
451 | |
452 // Verifies a tick with a very large delta and a sequence that repeats forever | |
453 // doesn't take a long time. | |
454 TEST_F(AnimationRunnerTest, InfiniteRepeatWithHugeGap) { | |
455 TestServerWindowDelegate window_delegate; | |
456 ServerWindow window(&window_delegate, WindowId(1, 2)); | |
457 | |
458 window.SetOpacity(.5f); | |
459 | |
460 AnimationGroup group; | |
461 InitGroupForWindow(&group, window.id(), 0); | |
462 AddOpacityElement(&group, TimeDelta::FromMicroseconds(500), | |
463 AnimationValuePtr(), FloatAnimationValue(1)); | |
464 AddOpacityElement(&group, TimeDelta::FromMicroseconds(500), | |
465 AnimationValuePtr(), FloatAnimationValue(.5)); | |
466 | |
467 ScheduleForSingleWindow(&window, &group, initial_time_); | |
468 runner_observer_.clear_changes(); | |
469 | |
470 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1000000000750)); | |
471 | |
472 EXPECT_EQ(.75f, window.opacity()); | |
473 | |
474 ASSERT_EQ(0u, runner_observer_.changes()->size()); | |
475 } | |
476 | |
477 // Verifies a second schedule sets any properties that are no longer animating | |
478 // to their final value. | |
479 TEST_F(AnimationRunnerTest, RescheduleSetsPropertiesToFinalValue) { | |
480 TestServerWindowDelegate window_delegate; | |
481 ServerWindow window(&window_delegate, WindowId()); | |
482 | |
483 AnimationGroup group; | |
484 InitGroupForWindow(&group, window.id(), 1); | |
485 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
486 AnimationValuePtr(), FloatAnimationValue(.5)); | |
487 | |
488 gfx::Transform done_transform; | |
489 done_transform.Scale(2, 4); | |
490 AddTransformElement(&group, TimeDelta::FromMicroseconds(500), | |
491 AnimationValuePtr(), | |
492 TransformAnimationValue(done_transform)); | |
493 | |
494 ScheduleForSingleWindow(&window, &group, initial_time_); | |
495 | |
496 // Schedule() again, this time without animating opacity. | |
497 group.sequences[0]->elements[0]->property = AnimationProperty::NONE; | |
498 ScheduleForSingleWindow(&window, &group, initial_time_); | |
499 | |
500 // Opacity should go to final value. | |
501 EXPECT_EQ(.5f, window.opacity()); | |
502 // Transform shouldn't have changed since newly scheduled animation also has | |
503 // transform in it. | |
504 EXPECT_TRUE(window.transform().IsIdentity()); | |
505 } | |
506 | |
507 // Opacity from 1 to .5 over 1000 of v1 and v2 transform to 2x,4x over 500. | |
508 TEST_F(AnimationRunnerTest, TwoWindows) { | |
509 TestServerWindowDelegate window_delegate; | |
510 ServerWindow window1(&window_delegate, WindowId()); | |
511 ServerWindow window2(&window_delegate, WindowId(1, 2)); | |
512 | |
513 AnimationGroup group1; | |
514 InitGroupForWindow(&group1, window1.id(), 1); | |
515 AddOpacityElement(&group1, TimeDelta::FromMicroseconds(1000), | |
516 AnimationValuePtr(), FloatAnimationValue(.5)); | |
517 | |
518 AnimationGroup group2; | |
519 InitGroupForWindow(&group2, window2.id(), 1); | |
520 gfx::Transform done_transform; | |
521 done_transform.Scale(2, 4); | |
522 AddTransformElement(&group2, TimeDelta::FromMicroseconds(500), | |
523 AnimationValuePtr(), | |
524 TransformAnimationValue(done_transform)); | |
525 | |
526 std::vector<AnimationRunner::WindowAndAnimationPair> pairs; | |
527 pairs.push_back(std::make_pair(&window1, &group1)); | |
528 pairs.push_back(std::make_pair(&window2, &group2)); | |
529 | |
530 const uint32_t animation_id = runner_.Schedule(pairs, initial_time_); | |
531 | |
532 ASSERT_EQ(1u, runner_observer_.changes()->size()); | |
533 EXPECT_EQ("scheduled", runner_observer_.changes()->at(0)); | |
534 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); | |
535 runner_observer_.clear_changes(); | |
536 | |
537 EXPECT_TRUE(runner_.HasAnimations()); | |
538 EXPECT_TRUE(runner_.IsAnimating(animation_id)); | |
539 | |
540 // Properties should be at the initial value. | |
541 EXPECT_EQ(1.f, window1.opacity()); | |
542 EXPECT_TRUE(window2.transform().IsIdentity()); | |
543 | |
544 // Animate 250ms in, which is quarter way for opacity and half way for | |
545 // transform. | |
546 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(250)); | |
547 EXPECT_EQ(.875f, window1.opacity()); | |
548 gfx::Transform half_way_transform; | |
549 half_way_transform.Scale(1.5, 2.5); | |
550 EXPECT_EQ(half_way_transform, window2.transform()); | |
551 std::set<ServerWindow*> windows_animating( | |
552 runner_.GetWindowsAnimating(animation_id)); | |
553 EXPECT_EQ(2u, windows_animating.size()); | |
554 EXPECT_EQ(1u, windows_animating.count(&window1)); | |
555 EXPECT_EQ(1u, windows_animating.count(&window2)); | |
556 | |
557 // Animate 750ms in, window1 should be done 3/4 done, and window2 done. | |
558 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(750)); | |
559 EXPECT_EQ(.625, window1.opacity()); | |
560 EXPECT_EQ(done_transform, window2.transform()); | |
561 windows_animating = runner_.GetWindowsAnimating(animation_id); | |
562 EXPECT_EQ(1u, windows_animating.size()); | |
563 EXPECT_EQ(1u, windows_animating.count(&window1)); | |
564 EXPECT_TRUE(runner_.HasAnimations()); | |
565 EXPECT_TRUE(runner_.IsAnimating(animation_id)); | |
566 | |
567 // Animate to end. | |
568 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1750)); | |
569 EXPECT_EQ(.5, window1.opacity()); | |
570 EXPECT_EQ(done_transform, window2.transform()); | |
571 windows_animating = runner_.GetWindowsAnimating(animation_id); | |
572 EXPECT_TRUE(windows_animating.empty()); | |
573 EXPECT_FALSE(runner_.HasAnimations()); | |
574 EXPECT_FALSE(runner_.IsAnimating(animation_id)); | |
575 } | |
576 | |
577 TEST_F(AnimationRunnerTest, Reschedule) { | |
578 TestServerWindowDelegate window_delegate; | |
579 ServerWindow window(&window_delegate, WindowId()); | |
580 | |
581 // Animation from 1-0 over 1ms and in parallel transform to 2x,4x over 1ms. | |
582 AnimationGroup group; | |
583 InitGroupForWindow(&group, window.id(), 1); | |
584 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), | |
585 AnimationValuePtr(), FloatAnimationValue(0)); | |
586 group.sequences.push_back(AnimationSequence::New()); | |
587 group.sequences[1]->cycle_count = 1; | |
588 gfx::Transform done_transform; | |
589 done_transform.Scale(2, 4); | |
590 AddTransformElement(&group, TimeDelta::FromMicroseconds(1000), | |
591 AnimationValuePtr(), | |
592 TransformAnimationValue(done_transform)); | |
593 const uint32_t animation_id1 = | |
594 ScheduleForSingleWindow(&window, &group, initial_time_); | |
595 | |
596 // Animate half way in. | |
597 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); | |
598 EXPECT_EQ(.5f, window.opacity()); | |
599 gfx::Transform half_way_transform; | |
600 half_way_transform.Scale(1.5, 2.5); | |
601 EXPECT_EQ(half_way_transform, window.transform()); | |
602 | |
603 runner_observer_.clear_changes(); | |
604 | |
605 // Schedule the same window animating opacity to 1. | |
606 AnimationGroup group2; | |
607 InitGroupForWindow(&group2, window.id(), 1); | |
608 AddOpacityElement(&group2, TimeDelta::FromMicroseconds(1000), | |
609 AnimationValuePtr(), FloatAnimationValue(1)); | |
610 const uint32_t animation_id2 = ScheduleForSingleWindow( | |
611 &window, &group2, initial_time_ + TimeDelta::FromMicroseconds(500)); | |
612 | |
613 // Opacity should remain at .5, but transform should go to end state. | |
614 EXPECT_EQ(.5f, window.opacity()); | |
615 EXPECT_EQ(done_transform, window.transform()); | |
616 | |
617 ASSERT_EQ(2u, runner_observer_.changes()->size()); | |
618 EXPECT_EQ("interrupted", runner_observer_.changes()->at(0)); | |
619 EXPECT_EQ(animation_id1, runner_observer_.change_ids()->at(0)); | |
620 EXPECT_EQ("scheduled", runner_observer_.changes()->at(1)); | |
621 EXPECT_EQ(animation_id2, runner_observer_.change_ids()->at(1)); | |
622 runner_observer_.clear_changes(); | |
623 | |
624 // Animate half way through new sequence. Opacity should be the only thing | |
625 // changing. | |
626 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1000)); | |
627 EXPECT_EQ(.75f, window.opacity()); | |
628 EXPECT_EQ(done_transform, window.transform()); | |
629 ASSERT_EQ(0u, runner_observer_.changes()->size()); | |
630 | |
631 // Animate to end. | |
632 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(2000)); | |
633 ASSERT_EQ(1u, runner_observer_.changes()->size()); | |
634 EXPECT_EQ("done", runner_observer_.changes()->at(0)); | |
635 EXPECT_EQ(animation_id2, runner_observer_.change_ids()->at(0)); | |
636 } | |
637 | |
638 } // ws | |
639 } // mus | |
OLD | NEW |