OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013 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 "content/browser/web_contents/aura/window_slider.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/time/time.h" | |
9 #include "testing/gtest/include/gtest/gtest.h" | |
10 #include "ui/aura/test/aura_test_base.h" | |
11 #include "ui/aura/test/test_window_delegate.h" | |
12 #include "ui/aura/window.h" | |
13 #include "ui/base/hit_test.h" | |
14 #include "ui/compositor/scoped_animation_duration_scale_mode.h" | |
15 #include "ui/compositor/scoped_layer_animation_settings.h" | |
16 #include "ui/compositor/test/layer_animator_test_controller.h" | |
17 #include "ui/events/event_processor.h" | |
18 #include "ui/events/event_utils.h" | |
19 #include "ui/events/test/event_generator.h" | |
20 #include "ui/gfx/frame_time.h" | |
21 | |
22 namespace content { | |
23 | |
24 void DispatchEventDuringScrollCallback(ui::EventProcessor* dispatcher, | |
25 ui::Event* event, | |
26 ui::EventType type, | |
27 const gfx::Vector2dF& delta) { | |
28 if (type != ui::ET_GESTURE_SCROLL_UPDATE) | |
29 return; | |
30 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(event); | |
31 CHECK(!details.dispatcher_destroyed); | |
32 } | |
33 | |
34 void ChangeSliderOwnerDuringScrollCallback(scoped_ptr<aura::Window>* window, | |
35 WindowSlider* slider, | |
36 ui::EventType type, | |
37 const gfx::Vector2dF& delta) { | |
38 if (type != ui::ET_GESTURE_SCROLL_UPDATE) | |
39 return; | |
40 aura::Window* new_window = new aura::Window(NULL); | |
41 new_window->Init(ui::LAYER_TEXTURED); | |
42 new_window->Show(); | |
43 slider->ChangeOwner(new_window); | |
44 (*window)->parent()->AddChild(new_window); | |
45 window->reset(new_window); | |
46 } | |
47 | |
48 void ConfirmSlideDuringScrollCallback(WindowSlider* slider, | |
49 ui::EventType type, | |
50 const gfx::Vector2dF& delta) { | |
51 static float total_delta_x = 0; | |
52 if (type == ui::ET_GESTURE_SCROLL_BEGIN) | |
53 total_delta_x = 0; | |
54 | |
55 if (type == ui::ET_GESTURE_SCROLL_UPDATE) { | |
56 total_delta_x += delta.x(); | |
57 if (total_delta_x >= 70) | |
58 EXPECT_TRUE(slider->IsSlideInProgress()); | |
59 } else { | |
60 EXPECT_FALSE(slider->IsSlideInProgress()); | |
61 } | |
62 } | |
63 | |
64 void ConfirmNoSlideDuringScrollCallback(WindowSlider* slider, | |
65 ui::EventType type, | |
66 const gfx::Vector2dF& delta) { | |
67 EXPECT_FALSE(slider->IsSlideInProgress()); | |
68 } | |
69 | |
70 // The window delegate does not receive any events. | |
71 class NoEventWindowDelegate : public aura::test::TestWindowDelegate { | |
72 public: | |
73 NoEventWindowDelegate() { | |
74 } | |
75 ~NoEventWindowDelegate() override {} | |
76 | |
77 private: | |
78 // Overridden from aura::WindowDelegate: | |
79 bool HasHitTestMask() const override { return true; } | |
80 | |
81 DISALLOW_COPY_AND_ASSIGN(NoEventWindowDelegate); | |
82 }; | |
83 | |
84 class WindowSliderDelegateTest : public WindowSlider::Delegate { | |
85 public: | |
86 WindowSliderDelegateTest() | |
87 : can_create_layer_(true), | |
88 created_back_layer_(false), | |
89 created_front_layer_(false), | |
90 slide_completing_(false), | |
91 slide_completed_(false), | |
92 slide_aborted_(false), | |
93 slider_destroyed_(false) { | |
94 } | |
95 ~WindowSliderDelegateTest() override { | |
96 // Make sure slide_completed() gets called if slide_completing() was called. | |
97 CHECK(!slide_completing_ || slide_completed_); | |
98 } | |
99 | |
100 void Reset() { | |
101 can_create_layer_ = true; | |
102 created_back_layer_ = false; | |
103 created_front_layer_ = false; | |
104 slide_completing_ = false; | |
105 slide_completed_ = false; | |
106 slide_aborted_ = false; | |
107 slider_destroyed_ = false; | |
108 } | |
109 | |
110 void SetCanCreateLayer(bool can_create_layer) { | |
111 can_create_layer_ = can_create_layer; | |
112 } | |
113 | |
114 bool created_back_layer() const { return created_back_layer_; } | |
115 bool created_front_layer() const { return created_front_layer_; } | |
116 bool slide_completing() const { return slide_completing_; } | |
117 bool slide_completed() const { return slide_completed_; } | |
118 bool slide_aborted() const { return slide_aborted_; } | |
119 bool slider_destroyed() const { return slider_destroyed_; } | |
120 | |
121 protected: | |
122 ui::Layer* CreateLayerForTest() { | |
123 CHECK(can_create_layer_); | |
124 ui::Layer* layer = new ui::Layer(ui::LAYER_SOLID_COLOR); | |
125 layer->SetColor(SK_ColorRED); | |
126 return layer; | |
127 } | |
128 | |
129 // Overridden from WindowSlider::Delegate: | |
130 ui::Layer* CreateBackLayer() override { | |
131 if (!can_create_layer_) | |
132 return NULL; | |
133 created_back_layer_ = true; | |
134 return CreateLayerForTest(); | |
135 } | |
136 | |
137 ui::Layer* CreateFrontLayer() override { | |
138 if (!can_create_layer_) | |
139 return NULL; | |
140 created_front_layer_ = true; | |
141 return CreateLayerForTest(); | |
142 } | |
143 | |
144 void OnWindowSlideCompleted(scoped_ptr<ui::Layer> layer) override { | |
145 slide_completed_ = true; | |
146 } | |
147 | |
148 void OnWindowSlideCompleting() override { slide_completing_ = true; } | |
149 | |
150 void OnWindowSlideAborted() override { slide_aborted_ = true; } | |
151 | |
152 void OnWindowSliderDestroyed() override { slider_destroyed_ = true; } | |
153 | |
154 private: | |
155 bool can_create_layer_; | |
156 bool created_back_layer_; | |
157 bool created_front_layer_; | |
158 bool slide_completing_; | |
159 bool slide_completed_; | |
160 bool slide_aborted_; | |
161 bool slider_destroyed_; | |
162 | |
163 DISALLOW_COPY_AND_ASSIGN(WindowSliderDelegateTest); | |
164 }; | |
165 | |
166 // This delegate destroys the owner window when the slider is destroyed. | |
167 class WindowSliderDeleteOwnerOnDestroy : public WindowSliderDelegateTest { | |
168 public: | |
169 explicit WindowSliderDeleteOwnerOnDestroy(aura::Window* owner) | |
170 : owner_(owner) { | |
171 } | |
172 ~WindowSliderDeleteOwnerOnDestroy() override {} | |
173 | |
174 private: | |
175 // Overridden from WindowSlider::Delegate: | |
176 void OnWindowSliderDestroyed() override { | |
177 WindowSliderDelegateTest::OnWindowSliderDestroyed(); | |
178 delete owner_; | |
179 } | |
180 | |
181 aura::Window* owner_; | |
182 DISALLOW_COPY_AND_ASSIGN(WindowSliderDeleteOwnerOnDestroy); | |
183 }; | |
184 | |
185 // This delegate destroyes the owner window when a slide is completed. | |
186 class WindowSliderDeleteOwnerOnComplete : public WindowSliderDelegateTest { | |
187 public: | |
188 explicit WindowSliderDeleteOwnerOnComplete(aura::Window* owner) | |
189 : owner_(owner) { | |
190 } | |
191 ~WindowSliderDeleteOwnerOnComplete() override {} | |
192 | |
193 private: | |
194 // Overridden from WindowSlider::Delegate: | |
195 void OnWindowSlideCompleted(scoped_ptr<ui::Layer> layer) override { | |
196 WindowSliderDelegateTest::OnWindowSlideCompleted(layer.Pass()); | |
197 delete owner_; | |
198 } | |
199 | |
200 aura::Window* owner_; | |
201 DISALLOW_COPY_AND_ASSIGN(WindowSliderDeleteOwnerOnComplete); | |
202 }; | |
203 | |
204 typedef aura::test::AuraTestBase WindowSliderTest; | |
205 | |
206 TEST_F(WindowSliderTest, WindowSlideUsingGesture) { | |
207 scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL)); | |
208 window->SetBounds(gfx::Rect(0, 0, 400, 400)); | |
209 WindowSliderDelegateTest slider_delegate; | |
210 | |
211 ui::test::EventGenerator generator(root_window()); | |
212 | |
213 // Generate a horizontal overscroll. | |
214 WindowSlider* slider = | |
215 new WindowSlider(&slider_delegate, root_window(), window.get()); | |
216 generator.GestureScrollSequenceWithCallback( | |
217 gfx::Point(10, 10), | |
218 gfx::Point(180, 10), | |
219 base::TimeDelta::FromMilliseconds(10), | |
220 10, | |
221 base::Bind(&ConfirmSlideDuringScrollCallback, slider)); | |
222 EXPECT_TRUE(slider_delegate.created_back_layer()); | |
223 EXPECT_TRUE(slider_delegate.slide_completing()); | |
224 EXPECT_TRUE(slider_delegate.slide_completed()); | |
225 EXPECT_FALSE(slider_delegate.created_front_layer()); | |
226 EXPECT_FALSE(slider_delegate.slide_aborted()); | |
227 EXPECT_FALSE(slider_delegate.slider_destroyed()); | |
228 EXPECT_FALSE(slider->IsSlideInProgress()); | |
229 slider_delegate.Reset(); | |
230 window->SetTransform(gfx::Transform()); | |
231 | |
232 // Generate a horizontal overscroll in the reverse direction. | |
233 generator.GestureScrollSequenceWithCallback( | |
234 gfx::Point(180, 10), | |
235 gfx::Point(10, 10), | |
236 base::TimeDelta::FromMilliseconds(10), | |
237 10, | |
238 base::Bind(&ConfirmSlideDuringScrollCallback, slider)); | |
239 EXPECT_TRUE(slider_delegate.created_front_layer()); | |
240 EXPECT_TRUE(slider_delegate.slide_completing()); | |
241 EXPECT_TRUE(slider_delegate.slide_completed()); | |
242 EXPECT_FALSE(slider_delegate.created_back_layer()); | |
243 EXPECT_FALSE(slider_delegate.slide_aborted()); | |
244 EXPECT_FALSE(slider_delegate.slider_destroyed()); | |
245 EXPECT_FALSE(slider->IsSlideInProgress()); | |
246 slider_delegate.Reset(); | |
247 | |
248 // Generate a vertical overscroll. | |
249 generator.GestureScrollSequenceWithCallback( | |
250 gfx::Point(10, 10), | |
251 gfx::Point(10, 80), | |
252 base::TimeDelta::FromMilliseconds(10), | |
253 10, | |
254 base::Bind(&ConfirmNoSlideDuringScrollCallback, slider)); | |
255 EXPECT_FALSE(slider_delegate.created_back_layer()); | |
256 EXPECT_FALSE(slider_delegate.slide_completing()); | |
257 EXPECT_FALSE(slider_delegate.slide_completed()); | |
258 EXPECT_FALSE(slider_delegate.created_front_layer()); | |
259 EXPECT_FALSE(slider_delegate.slide_aborted()); | |
260 EXPECT_FALSE(slider->IsSlideInProgress()); | |
261 slider_delegate.Reset(); | |
262 | |
263 // Generate a horizontal scroll that starts overscroll, but doesn't scroll | |
264 // enough to complete it. | |
265 generator.GestureScrollSequenceWithCallback( | |
266 gfx::Point(10, 10), | |
267 gfx::Point(80, 10), | |
268 base::TimeDelta::FromMilliseconds(10), | |
269 10, | |
270 base::Bind(&ConfirmSlideDuringScrollCallback, slider)); | |
271 EXPECT_TRUE(slider_delegate.created_back_layer()); | |
272 EXPECT_TRUE(slider_delegate.slide_aborted()); | |
273 EXPECT_FALSE(slider_delegate.created_front_layer()); | |
274 EXPECT_FALSE(slider_delegate.slide_completing()); | |
275 EXPECT_FALSE(slider_delegate.slide_completed()); | |
276 EXPECT_FALSE(slider_delegate.slider_destroyed()); | |
277 EXPECT_FALSE(slider->IsSlideInProgress()); | |
278 slider_delegate.Reset(); | |
279 | |
280 // Destroy the window. This should destroy the slider. | |
281 window.reset(); | |
282 EXPECT_TRUE(slider_delegate.slider_destroyed()); | |
283 } | |
284 | |
285 // Tests that the window slide is interrupted when a different type of event | |
286 // happens. | |
287 TEST_F(WindowSliderTest, WindowSlideIsCancelledOnEvent) { | |
288 scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL)); | |
289 window->SetBounds(gfx::Rect(0, 0, 400, 400)); | |
290 WindowSliderDelegateTest slider_delegate; | |
291 | |
292 ui::Event* events[] = { | |
293 new ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(55, 10), | |
294 gfx::Point(55, 10), ui::EventTimeForNow(), 0, 0), | |
295 new ui::KeyEvent('a', ui::VKEY_A, ui::EF_NONE), | |
296 nullptr | |
297 }; | |
298 | |
299 new WindowSlider(&slider_delegate, root_window(), window.get()); | |
300 for (int i = 0; events[i]; ++i) { | |
301 // Generate a horizontal overscroll. | |
302 ui::test::EventGenerator generator(root_window()); | |
303 generator.GestureScrollSequenceWithCallback( | |
304 gfx::Point(10, 10), | |
305 gfx::Point(80, 10), | |
306 base::TimeDelta::FromMilliseconds(10), | |
307 1, | |
308 base::Bind(&DispatchEventDuringScrollCallback, | |
309 root_window()->GetHost()->event_processor(), | |
310 base::Owned(events[i]))); | |
311 EXPECT_TRUE(slider_delegate.created_back_layer()); | |
312 EXPECT_TRUE(slider_delegate.slide_aborted()); | |
313 EXPECT_FALSE(slider_delegate.created_front_layer()); | |
314 EXPECT_FALSE(slider_delegate.slide_completing()); | |
315 EXPECT_FALSE(slider_delegate.slide_completed()); | |
316 EXPECT_FALSE(slider_delegate.slider_destroyed()); | |
317 slider_delegate.Reset(); | |
318 } | |
319 window.reset(); | |
320 EXPECT_TRUE(slider_delegate.slider_destroyed()); | |
321 } | |
322 | |
323 // Tests that the window slide can continue after it is interrupted by another | |
324 // event if the user continues scrolling. | |
325 TEST_F(WindowSliderTest, WindowSlideInterruptedThenContinues) { | |
326 scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL)); | |
327 window->SetBounds(gfx::Rect(0, 0, 400, 400)); | |
328 WindowSliderDelegateTest slider_delegate; | |
329 | |
330 ui::ScopedAnimationDurationScaleMode normal_duration_( | |
331 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); | |
332 ui::LayerAnimator* animator = window->layer()->GetAnimator(); | |
333 animator->set_disable_timer_for_test(true); | |
334 ui::LayerAnimatorTestController test_controller(animator); | |
335 | |
336 WindowSlider* slider = | |
337 new WindowSlider(&slider_delegate, root_window(), window.get()); | |
338 | |
339 ui::MouseEvent interrupt_event(ui::ET_MOUSE_MOVED, gfx::Point(55, 10), | |
340 gfx::Point(55, 10), ui::EventTimeForNow(), 0, | |
341 0); | |
342 | |
343 ui::test::EventGenerator generator(root_window()); | |
344 | |
345 // Start the scroll sequence. Scroll forward so that |window|'s layer is the | |
346 // one animating. | |
347 const int kTouchId = 5; | |
348 ui::TouchEvent press(ui::ET_TOUCH_PRESSED, | |
349 gfx::Point(10, 10), | |
350 kTouchId, | |
351 ui::EventTimeForNow()); | |
352 generator.Dispatch(&press); | |
353 | |
354 // First scroll event of the sequence. | |
355 ui::TouchEvent move1(ui::ET_TOUCH_MOVED, | |
356 gfx::Point(100, 10), | |
357 kTouchId, | |
358 ui::EventTimeForNow()); | |
359 generator.Dispatch(&move1); | |
360 EXPECT_TRUE(slider->IsSlideInProgress()); | |
361 EXPECT_FALSE(animator->is_animating()); | |
362 // Dispatch the event after the first scroll and confirm it interrupts the | |
363 // scroll and starts the "reset slide" animation. | |
364 generator.Dispatch(&interrupt_event); | |
365 EXPECT_TRUE(slider->IsSlideInProgress()); | |
366 EXPECT_TRUE(animator->is_animating()); | |
367 EXPECT_TRUE(slider_delegate.created_back_layer()); | |
368 // slide_aborted() should be false because the 'reset slide' animation | |
369 // hasn't completed yet. | |
370 EXPECT_FALSE(slider_delegate.slide_aborted()); | |
371 EXPECT_FALSE(slider_delegate.created_front_layer()); | |
372 EXPECT_FALSE(slider_delegate.slide_completing()); | |
373 EXPECT_FALSE(slider_delegate.slide_completed()); | |
374 EXPECT_FALSE(slider_delegate.slider_destroyed()); | |
375 slider_delegate.Reset(); | |
376 | |
377 // Second scroll event of the sequence. | |
378 ui::TouchEvent move2(ui::ET_TOUCH_MOVED, | |
379 gfx::Point(200, 10), | |
380 kTouchId, | |
381 ui::EventTimeForNow()); | |
382 generator.Dispatch(&move2); | |
383 // The second scroll should instantly cause the animation to complete. | |
384 EXPECT_FALSE(animator->is_animating()); | |
385 EXPECT_FALSE(slider_delegate.created_back_layer()); | |
386 // The ResetScroll() animation was completed, so now slide_aborted() | |
387 // should be true. | |
388 EXPECT_TRUE(slider_delegate.slide_aborted()); | |
389 | |
390 // Third scroll event of the sequence. | |
391 ui::TouchEvent move3(ui::ET_TOUCH_MOVED, | |
392 gfx::Point(300, 10), | |
393 kTouchId, | |
394 ui::EventTimeForNow()); | |
395 generator.Dispatch(&move3); | |
396 // The third scroll should re-start the sliding. | |
397 EXPECT_TRUE(slider->IsSlideInProgress()); | |
398 EXPECT_TRUE(slider_delegate.created_back_layer()); | |
399 | |
400 // Generate the release event, finishing the scroll sequence. | |
401 ui::TouchEvent release(ui::ET_TOUCH_RELEASED, | |
402 gfx::Point(300, 10), | |
403 kTouchId, | |
404 ui::EventTimeForNow()); | |
405 generator.Dispatch(&release); | |
406 // When the scroll gesture ends, the slide animation should start. | |
407 EXPECT_TRUE(slider->IsSlideInProgress()); | |
408 EXPECT_TRUE(animator->is_animating()); | |
409 EXPECT_TRUE(slider_delegate.slide_completing()); | |
410 EXPECT_FALSE(slider_delegate.created_front_layer()); | |
411 EXPECT_FALSE(slider_delegate.slide_completed()); | |
412 EXPECT_FALSE(slider_delegate.slider_destroyed()); | |
413 | |
414 // Progress the animator to complete the slide animation. | |
415 ui::ScopedLayerAnimationSettings settings(animator); | |
416 base::TimeDelta duration = settings.GetTransitionDuration(); | |
417 test_controller.StartThreadedAnimationsIfNeeded(); | |
418 animator->Step(gfx::FrameTime::Now() + duration); | |
419 | |
420 EXPECT_TRUE(slider_delegate.slide_completed()); | |
421 EXPECT_FALSE(slider_delegate.slider_destroyed()); | |
422 | |
423 window.reset(); | |
424 EXPECT_TRUE(slider_delegate.slider_destroyed()); | |
425 } | |
426 | |
427 // Tests that the slide works correctly when the owner of the window changes | |
428 // during the duration of the slide. | |
429 TEST_F(WindowSliderTest, OwnerWindowChangesDuringWindowSlide) { | |
430 scoped_ptr<aura::Window> parent(CreateNormalWindow(0, root_window(), NULL)); | |
431 | |
432 NoEventWindowDelegate window_delegate; | |
433 window_delegate.set_window_component(HTNOWHERE); | |
434 scoped_ptr<aura::Window> window(CreateNormalWindow(1, parent.get(), | |
435 &window_delegate)); | |
436 | |
437 WindowSliderDelegateTest slider_delegate; | |
438 scoped_ptr<WindowSlider> slider( | |
439 new WindowSlider(&slider_delegate, parent.get(), window.get())); | |
440 | |
441 // Generate a horizontal scroll, and change the owner in the middle of the | |
442 // scroll. | |
443 ui::test::EventGenerator generator(root_window()); | |
444 aura::Window* old_window = window.get(); | |
445 generator.GestureScrollSequenceWithCallback( | |
446 gfx::Point(10, 10), | |
447 gfx::Point(80, 10), | |
448 base::TimeDelta::FromMilliseconds(10), | |
449 1, | |
450 base::Bind(&ChangeSliderOwnerDuringScrollCallback, | |
451 base::Unretained(&window), | |
452 slider.get())); | |
453 aura::Window* new_window = window.get(); | |
454 EXPECT_NE(old_window, new_window); | |
455 | |
456 EXPECT_TRUE(slider_delegate.created_back_layer()); | |
457 EXPECT_TRUE(slider_delegate.slide_completing()); | |
458 EXPECT_TRUE(slider_delegate.slide_completed()); | |
459 EXPECT_FALSE(slider_delegate.created_front_layer()); | |
460 EXPECT_FALSE(slider_delegate.slide_aborted()); | |
461 EXPECT_FALSE(slider_delegate.slider_destroyed()); | |
462 } | |
463 | |
464 // If the delegate doesn't create the layer to show while sliding, WindowSlider | |
465 // shouldn't start the slide or change delegate's state in any way in response | |
466 // to user input. | |
467 TEST_F(WindowSliderTest, NoSlideWhenLayerCantBeCreated) { | |
468 scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL)); | |
469 window->SetBounds(gfx::Rect(0, 0, 400, 400)); | |
470 WindowSliderDelegateTest slider_delegate; | |
471 slider_delegate.SetCanCreateLayer(false); | |
472 WindowSlider* slider = | |
473 new WindowSlider(&slider_delegate, root_window(), window.get()); | |
474 | |
475 ui::test::EventGenerator generator(root_window()); | |
476 | |
477 // No slide in progress should be reported during scroll since the layer | |
478 // wasn't created. | |
479 generator.GestureScrollSequenceWithCallback( | |
480 gfx::Point(10, 10), | |
481 gfx::Point(180, 10), | |
482 base::TimeDelta::FromMilliseconds(10), | |
483 1, | |
484 base::Bind(&ConfirmNoSlideDuringScrollCallback, slider)); | |
485 | |
486 EXPECT_FALSE(slider_delegate.created_back_layer()); | |
487 EXPECT_FALSE(slider_delegate.slide_completing()); | |
488 EXPECT_FALSE(slider_delegate.slide_completed()); | |
489 EXPECT_FALSE(slider_delegate.created_front_layer()); | |
490 EXPECT_FALSE(slider_delegate.slide_aborted()); | |
491 EXPECT_FALSE(slider_delegate.slider_destroyed()); | |
492 window->SetTransform(gfx::Transform()); | |
493 | |
494 slider_delegate.SetCanCreateLayer(true); | |
495 generator.GestureScrollSequenceWithCallback( | |
496 gfx::Point(10, 10), | |
497 gfx::Point(180, 10), | |
498 base::TimeDelta::FromMilliseconds(10), | |
499 10, | |
500 base::Bind(&ConfirmSlideDuringScrollCallback, slider)); | |
501 EXPECT_TRUE(slider_delegate.created_back_layer()); | |
502 EXPECT_TRUE(slider_delegate.slide_completing()); | |
503 EXPECT_TRUE(slider_delegate.slide_completed()); | |
504 EXPECT_FALSE(slider_delegate.created_front_layer()); | |
505 EXPECT_FALSE(slider_delegate.slide_aborted()); | |
506 EXPECT_FALSE(slider_delegate.slider_destroyed()); | |
507 | |
508 window.reset(); | |
509 EXPECT_TRUE(slider_delegate.slider_destroyed()); | |
510 } | |
511 | |
512 // Tests that the owner window can be destroyed from |OnWindowSliderDestroyed()| | |
513 // delegate callback without causing a crash. | |
514 TEST_F(WindowSliderTest, OwnerIsDestroyedOnSliderDestroy) { | |
515 size_t child_windows = root_window()->children().size(); | |
516 aura::Window* window = CreateNormalWindow(0, root_window(), NULL); | |
517 window->SetBounds(gfx::Rect(0, 0, 400, 400)); | |
518 EXPECT_EQ(child_windows + 1, root_window()->children().size()); | |
519 | |
520 WindowSliderDeleteOwnerOnDestroy slider_delegate(window); | |
521 ui::test::EventGenerator generator(root_window()); | |
522 | |
523 // Generate a horizontal overscroll. | |
524 scoped_ptr<WindowSlider> slider( | |
525 new WindowSlider(&slider_delegate, root_window(), window)); | |
526 generator.GestureScrollSequence(gfx::Point(10, 10), | |
527 gfx::Point(180, 10), | |
528 base::TimeDelta::FromMilliseconds(10), | |
529 10); | |
530 EXPECT_TRUE(slider_delegate.created_back_layer()); | |
531 EXPECT_TRUE(slider_delegate.slide_completing()); | |
532 EXPECT_TRUE(slider_delegate.slide_completed()); | |
533 EXPECT_FALSE(slider_delegate.created_front_layer()); | |
534 EXPECT_FALSE(slider_delegate.slide_aborted()); | |
535 EXPECT_FALSE(slider_delegate.slider_destroyed()); | |
536 | |
537 slider.reset(); | |
538 // Destroying the slider would have destroyed |window| too. So |window| should | |
539 // not need to be destroyed here. | |
540 EXPECT_EQ(child_windows, root_window()->children().size()); | |
541 } | |
542 | |
543 // Tests that the owner window can be destroyed from |OnWindowSlideComplete()| | |
544 // delegate callback without causing a crash. | |
545 TEST_F(WindowSliderTest, OwnerIsDestroyedOnSlideComplete) { | |
546 size_t child_windows = root_window()->children().size(); | |
547 aura::Window* window = CreateNormalWindow(0, root_window(), NULL); | |
548 window->SetBounds(gfx::Rect(0, 0, 400, 400)); | |
549 EXPECT_EQ(child_windows + 1, root_window()->children().size()); | |
550 | |
551 WindowSliderDeleteOwnerOnComplete slider_delegate(window); | |
552 ui::test::EventGenerator generator(root_window()); | |
553 | |
554 // Generate a horizontal overscroll. | |
555 new WindowSlider(&slider_delegate, root_window(), window); | |
556 generator.GestureScrollSequence(gfx::Point(10, 10), | |
557 gfx::Point(180, 10), | |
558 base::TimeDelta::FromMilliseconds(10), | |
559 10); | |
560 EXPECT_TRUE(slider_delegate.created_back_layer()); | |
561 EXPECT_TRUE(slider_delegate.slide_completing()); | |
562 EXPECT_TRUE(slider_delegate.slide_completed()); | |
563 EXPECT_FALSE(slider_delegate.created_front_layer()); | |
564 EXPECT_FALSE(slider_delegate.slide_aborted()); | |
565 EXPECT_TRUE(slider_delegate.slider_destroyed()); | |
566 | |
567 // Destroying the slider would have destroyed |window| too. So |window| should | |
568 // not need to be destroyed here. | |
569 EXPECT_EQ(child_windows, root_window()->children().size()); | |
570 } | |
571 | |
572 // Test the scenario when two swipe gesture occur quickly one after another so | |
573 // that the second swipe occurs while the transition animation triggered by the | |
574 // first swipe is in progress. | |
575 // The second swipe is supposed to instantly complete the animation caused by | |
576 // the first swipe, ask the delegate to create a new layer, and animate it. | |
577 TEST_F(WindowSliderTest, SwipeDuringSwipeAnimation) { | |
578 scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL)); | |
579 window->SetBounds(gfx::Rect(0, 0, 400, 400)); | |
580 WindowSliderDelegateTest slider_delegate; | |
581 new WindowSlider(&slider_delegate, root_window(), window.get()); | |
582 | |
583 // This test uses explicit durations so needs a normal duration. | |
584 ui::ScopedAnimationDurationScaleMode normal_duration( | |
585 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); | |
586 ui::LayerAnimator* animator = window->layer()->GetAnimator(); | |
587 animator->set_disable_timer_for_test(true); | |
588 ui::LayerAnimatorTestController test_controller(animator); | |
589 | |
590 ui::test::EventGenerator generator(root_window()); | |
591 | |
592 // Swipe forward so that |window|'s layer is the one animating. | |
593 generator.GestureScrollSequence( | |
594 gfx::Point(10, 10), | |
595 gfx::Point(180, 10), | |
596 base::TimeDelta::FromMilliseconds(10), | |
597 2); | |
598 EXPECT_TRUE(slider_delegate.created_back_layer()); | |
599 EXPECT_FALSE(slider_delegate.slide_aborted()); | |
600 EXPECT_FALSE(slider_delegate.created_front_layer()); | |
601 EXPECT_TRUE(slider_delegate.slide_completing()); | |
602 EXPECT_FALSE(slider_delegate.slide_completed()); | |
603 EXPECT_FALSE(slider_delegate.slider_destroyed()); | |
604 ui::ScopedLayerAnimationSettings settings(animator); | |
605 base::TimeDelta duration = settings.GetTransitionDuration(); | |
606 test_controller.StartThreadedAnimationsIfNeeded(); | |
607 base::TimeTicks start_time1 = gfx::FrameTime::Now(); | |
608 | |
609 animator->Step(start_time1 + duration / 2); | |
610 EXPECT_FALSE(slider_delegate.slide_completed()); | |
611 slider_delegate.Reset(); | |
612 // Generate another horizontal swipe while the animation from the previous | |
613 // swipe is in progress. | |
614 generator.GestureScrollSequence( | |
615 gfx::Point(10, 10), | |
616 gfx::Point(180, 10), | |
617 base::TimeDelta::FromMilliseconds(10), | |
618 2); | |
619 // Performing the second swipe should instantly complete the slide started | |
620 // by the first swipe and create a new layer. | |
621 EXPECT_TRUE(slider_delegate.created_back_layer()); | |
622 EXPECT_FALSE(slider_delegate.slide_aborted()); | |
623 EXPECT_FALSE(slider_delegate.created_front_layer()); | |
624 EXPECT_TRUE(slider_delegate.slide_completing()); | |
625 EXPECT_TRUE(slider_delegate.slide_completed()); | |
626 EXPECT_FALSE(slider_delegate.slider_destroyed()); | |
627 test_controller.StartThreadedAnimationsIfNeeded(); | |
628 base::TimeTicks start_time2 = gfx::FrameTime::Now(); | |
629 slider_delegate.Reset(); | |
630 animator->Step(start_time2 + duration); | |
631 // The animation for the second slide should now be completed. | |
632 EXPECT_TRUE(slider_delegate.slide_completed()); | |
633 slider_delegate.Reset(); | |
634 | |
635 window.reset(); | |
636 EXPECT_TRUE(slider_delegate.slider_destroyed()); | |
637 } | |
638 | |
639 } // namespace content | |
OLD | NEW |