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