window_slider_unittest.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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/event_generator.h" 12#include "ui/aura/test/test_window_delegate.h" 13#include "ui/aura/window.h" 14#include "ui/base/hit_test.h" 15#include "ui/compositor/scoped_animation_duration_scale_mode.h" 16#include "ui/compositor/scoped_layer_animation_settings.h" 17#include "ui/compositor/test/layer_animator_test_controller.h" 18#include "ui/events/event_processor.h" 19#include "ui/events/event_utils.h" 20#include "ui/gfx/frame_time.h" 21 22namespace content { 23 24void 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 34void 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 48void 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 64void 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. 71class 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 84class 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() 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. 173class 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. 192class 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() OVERRIDE { 202 WindowSliderDelegateTest::OnWindowSlideCompleted(); 203 delete owner_; 204 } 205 206 aura::Window* owner_; 207 DISALLOW_COPY_AND_ASSIGN(WindowSliderDeleteOwnerOnComplete); 208}; 209 210typedef aura::test::AuraTestBase WindowSliderTest; 211 212TEST_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 aura::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. 293TEST_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(ui::ET_KEY_PRESSED, 304 ui::VKEY_A, 305 0, 306 true), 307 NULL 308 }; 309 310 new WindowSlider(&slider_delegate, root_window(), window.get()); 311 for (int i = 0; events[i]; ++i) { 312 // Generate a horizontal overscroll. 313 aura::test::EventGenerator generator(root_window()); 314 generator.GestureScrollSequenceWithCallback( 315 gfx::Point(10, 10), 316 gfx::Point(80, 10), 317 base::TimeDelta::FromMilliseconds(10), 318 1, 319 base::Bind(&DispatchEventDuringScrollCallback, 320 root_window()->GetHost()->event_processor(), 321 base::Owned(events[i]))); 322 EXPECT_TRUE(slider_delegate.created_back_layer()); 323 EXPECT_TRUE(slider_delegate.slide_aborted()); 324 EXPECT_FALSE(slider_delegate.created_front_layer()); 325 EXPECT_FALSE(slider_delegate.slide_completing()); 326 EXPECT_FALSE(slider_delegate.slide_completed()); 327 EXPECT_FALSE(slider_delegate.slider_destroyed()); 328 slider_delegate.Reset(); 329 } 330 window.reset(); 331 EXPECT_TRUE(slider_delegate.slider_destroyed()); 332} 333 334// Tests that the window slide can continue after it is interrupted by another 335// event if the user continues scrolling. 336TEST_F(WindowSliderTest, WindowSlideInterruptedThenContinues) { 337 scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL)); 338 window->SetBounds(gfx::Rect(0, 0, 400, 400)); 339 WindowSliderDelegateTest slider_delegate; 340 341 ui::ScopedAnimationDurationScaleMode normal_duration_( 342 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); 343 ui::LayerAnimator* animator = window->layer()->GetAnimator(); 344 gfx::AnimationContainerElement* element = animator; 345 animator->set_disable_timer_for_test(true); 346 ui::LayerAnimatorTestController test_controller(animator); 347 348 WindowSlider* slider = 349 new WindowSlider(&slider_delegate, root_window(), window.get()); 350 351 ui::MouseEvent interrupt_event(ui::ET_MOUSE_MOVED, 352 gfx::Point(55, 10), 353 gfx::Point(55, 10), 354 0, 0); 355 356 aura::test::EventGenerator generator(root_window()); 357 358 // Start the scroll sequence. Scroll forward so that |window|'s layer is the 359 // one animating. 360 const int kTouchId = 5; 361 ui::TouchEvent press(ui::ET_TOUCH_PRESSED, 362 gfx::Point(10, 10), 363 kTouchId, 364 ui::EventTimeForNow()); 365 generator.Dispatch(&press); 366 367 // First scroll event of the sequence. 368 ui::TouchEvent move1(ui::ET_TOUCH_MOVED, 369 gfx::Point(100, 10), 370 kTouchId, 371 ui::EventTimeForNow()); 372 generator.Dispatch(&move1); 373 EXPECT_TRUE(slider->IsSlideInProgress()); 374 EXPECT_FALSE(animator->is_animating()); 375 // Dispatch the event after the first scroll and confirm it interrupts the 376 // scroll and starts the "reset slide" animation. 377 generator.Dispatch(&interrupt_event); 378 EXPECT_TRUE(slider->IsSlideInProgress()); 379 EXPECT_TRUE(animator->is_animating()); 380 EXPECT_TRUE(slider_delegate.created_back_layer()); 381 // slide_aborted() should be false because the 'reset slide' animation 382 // hasn't completed yet. 383 EXPECT_FALSE(slider_delegate.slide_aborted()); 384 EXPECT_FALSE(slider_delegate.created_front_layer()); 385 EXPECT_FALSE(slider_delegate.slide_completing()); 386 EXPECT_FALSE(slider_delegate.slide_completed()); 387 EXPECT_FALSE(slider_delegate.slider_destroyed()); 388 slider_delegate.Reset(); 389 390 // Second scroll event of the sequence. 391 ui::TouchEvent move2(ui::ET_TOUCH_MOVED, 392 gfx::Point(200, 10), 393 kTouchId, 394 ui::EventTimeForNow()); 395 generator.Dispatch(&move2); 396 // The second scroll should instantly cause the animation to complete. 397 EXPECT_FALSE(animator->is_animating()); 398 EXPECT_FALSE(slider_delegate.created_back_layer()); 399 // The ResetScroll() animation was completed, so now slide_aborted() 400 // should be true. 401 EXPECT_TRUE(slider_delegate.slide_aborted()); 402 403 // Third scroll event of the sequence. 404 ui::TouchEvent move3(ui::ET_TOUCH_MOVED, 405 gfx::Point(300, 10), 406 kTouchId, 407 ui::EventTimeForNow()); 408 generator.Dispatch(&move3); 409 // The third scroll should re-start the sliding. 410 EXPECT_TRUE(slider->IsSlideInProgress()); 411 EXPECT_TRUE(slider_delegate.created_back_layer()); 412 413 // Generate the release event, finishing the scroll sequence. 414 ui::TouchEvent release(ui::ET_TOUCH_RELEASED, 415 gfx::Point(300, 10), 416 kTouchId, 417 ui::EventTimeForNow()); 418 generator.Dispatch(&release); 419 // When the scroll gesture ends, the slide animation should start. 420 EXPECT_TRUE(slider->IsSlideInProgress()); 421 EXPECT_TRUE(animator->is_animating()); 422 EXPECT_TRUE(slider_delegate.slide_completing()); 423 EXPECT_FALSE(slider_delegate.created_front_layer()); 424 EXPECT_FALSE(slider_delegate.slide_completed()); 425 EXPECT_FALSE(slider_delegate.slider_destroyed()); 426 427 // Progress the animator to complete the slide animation. 428 ui::ScopedLayerAnimationSettings settings(animator); 429 base::TimeDelta duration = settings.GetTransitionDuration(); 430 test_controller.StartThreadedAnimationsIfNeeded(); 431 element->Step(gfx::FrameTime::Now() + duration); 432 433 EXPECT_TRUE(slider_delegate.slide_completed()); 434 EXPECT_FALSE(slider_delegate.slider_destroyed()); 435 436 window.reset(); 437 EXPECT_TRUE(slider_delegate.slider_destroyed()); 438} 439 440// Tests that the slide works correctly when the owner of the window changes 441// during the duration of the slide. 442TEST_F(WindowSliderTest, OwnerWindowChangesDuringWindowSlide) { 443 scoped_ptr<aura::Window> parent(CreateNormalWindow(0, root_window(), NULL)); 444 445 NoEventWindowDelegate window_delegate; 446 window_delegate.set_window_component(HTNOWHERE); 447 scoped_ptr<aura::Window> window(CreateNormalWindow(1, parent.get(), 448 &window_delegate)); 449 450 WindowSliderDelegateTest slider_delegate; 451 scoped_ptr<WindowSlider> slider( 452 new WindowSlider(&slider_delegate, parent.get(), window.get())); 453 454 // Generate a horizontal scroll, and change the owner in the middle of the 455 // scroll. 456 aura::test::EventGenerator generator(root_window()); 457 aura::Window* old_window = window.get(); 458 generator.GestureScrollSequenceWithCallback( 459 gfx::Point(10, 10), 460 gfx::Point(80, 10), 461 base::TimeDelta::FromMilliseconds(10), 462 1, 463 base::Bind(&ChangeSliderOwnerDuringScrollCallback, 464 base::Unretained(&window), 465 slider.get())); 466 aura::Window* new_window = window.get(); 467 EXPECT_NE(old_window, new_window); 468 469 EXPECT_TRUE(slider_delegate.created_back_layer()); 470 EXPECT_TRUE(slider_delegate.slide_completing()); 471 EXPECT_TRUE(slider_delegate.slide_completed()); 472 EXPECT_FALSE(slider_delegate.created_front_layer()); 473 EXPECT_FALSE(slider_delegate.slide_aborted()); 474 EXPECT_FALSE(slider_delegate.slider_destroyed()); 475} 476 477// If the delegate doesn't create the layer to show while sliding, WindowSlider 478// shouldn't start the slide or change delegate's state in any way in response 479// to user input. 480TEST_F(WindowSliderTest, NoSlideWhenLayerCantBeCreated) { 481 scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL)); 482 window->SetBounds(gfx::Rect(0, 0, 400, 400)); 483 WindowSliderDelegateTest slider_delegate; 484 slider_delegate.SetCanCreateLayer(false); 485 WindowSlider* slider = 486 new WindowSlider(&slider_delegate, root_window(), window.get()); 487 488 aura::test::EventGenerator generator(root_window()); 489 490 // No slide in progress should be reported during scroll since the layer 491 // wasn't created. 492 generator.GestureScrollSequenceWithCallback( 493 gfx::Point(10, 10), 494 gfx::Point(180, 10), 495 base::TimeDelta::FromMilliseconds(10), 496 1, 497 base::Bind(&ConfirmNoSlideDuringScrollCallback, slider)); 498 499 EXPECT_FALSE(slider_delegate.created_back_layer()); 500 EXPECT_FALSE(slider_delegate.slide_completing()); 501 EXPECT_FALSE(slider_delegate.slide_completed()); 502 EXPECT_FALSE(slider_delegate.created_front_layer()); 503 EXPECT_FALSE(slider_delegate.slide_aborted()); 504 EXPECT_FALSE(slider_delegate.slider_destroyed()); 505 window->SetTransform(gfx::Transform()); 506 507 slider_delegate.SetCanCreateLayer(true); 508 generator.GestureScrollSequenceWithCallback( 509 gfx::Point(10, 10), 510 gfx::Point(180, 10), 511 base::TimeDelta::FromMilliseconds(10), 512 10, 513 base::Bind(&ConfirmSlideDuringScrollCallback, slider)); 514 EXPECT_TRUE(slider_delegate.created_back_layer()); 515 EXPECT_TRUE(slider_delegate.slide_completing()); 516 EXPECT_TRUE(slider_delegate.slide_completed()); 517 EXPECT_FALSE(slider_delegate.created_front_layer()); 518 EXPECT_FALSE(slider_delegate.slide_aborted()); 519 EXPECT_FALSE(slider_delegate.slider_destroyed()); 520 521 window.reset(); 522 EXPECT_TRUE(slider_delegate.slider_destroyed()); 523} 524 525// Tests that the owner window can be destroyed from |OnWindowSliderDestroyed()| 526// delegate callback without causing a crash. 527TEST_F(WindowSliderTest, OwnerIsDestroyedOnSliderDestroy) { 528 size_t child_windows = root_window()->children().size(); 529 aura::Window* window = CreateNormalWindow(0, root_window(), NULL); 530 window->SetBounds(gfx::Rect(0, 0, 400, 400)); 531 EXPECT_EQ(child_windows + 1, root_window()->children().size()); 532 533 WindowSliderDeleteOwnerOnDestroy slider_delegate(window); 534 aura::test::EventGenerator generator(root_window()); 535 536 // Generate a horizontal overscroll. 537 scoped_ptr<WindowSlider> slider( 538 new WindowSlider(&slider_delegate, root_window(), window)); 539 generator.GestureScrollSequence(gfx::Point(10, 10), 540 gfx::Point(180, 10), 541 base::TimeDelta::FromMilliseconds(10), 542 10); 543 EXPECT_TRUE(slider_delegate.created_back_layer()); 544 EXPECT_TRUE(slider_delegate.slide_completing()); 545 EXPECT_TRUE(slider_delegate.slide_completed()); 546 EXPECT_FALSE(slider_delegate.created_front_layer()); 547 EXPECT_FALSE(slider_delegate.slide_aborted()); 548 EXPECT_FALSE(slider_delegate.slider_destroyed()); 549 550 slider.reset(); 551 // Destroying the slider would have destroyed |window| too. So |window| should 552 // not need to be destroyed here. 553 EXPECT_EQ(child_windows, root_window()->children().size()); 554} 555 556// Tests that the owner window can be destroyed from |OnWindowSlideComplete()| 557// delegate callback without causing a crash. 558TEST_F(WindowSliderTest, OwnerIsDestroyedOnSlideComplete) { 559 size_t child_windows = root_window()->children().size(); 560 aura::Window* window = CreateNormalWindow(0, root_window(), NULL); 561 window->SetBounds(gfx::Rect(0, 0, 400, 400)); 562 EXPECT_EQ(child_windows + 1, root_window()->children().size()); 563 564 WindowSliderDeleteOwnerOnComplete slider_delegate(window); 565 aura::test::EventGenerator generator(root_window()); 566 567 // Generate a horizontal overscroll. 568 new WindowSlider(&slider_delegate, root_window(), window); 569 generator.GestureScrollSequence(gfx::Point(10, 10), 570 gfx::Point(180, 10), 571 base::TimeDelta::FromMilliseconds(10), 572 10); 573 EXPECT_TRUE(slider_delegate.created_back_layer()); 574 EXPECT_TRUE(slider_delegate.slide_completing()); 575 EXPECT_TRUE(slider_delegate.slide_completed()); 576 EXPECT_FALSE(slider_delegate.created_front_layer()); 577 EXPECT_FALSE(slider_delegate.slide_aborted()); 578 EXPECT_TRUE(slider_delegate.slider_destroyed()); 579 580 // Destroying the slider would have destroyed |window| too. So |window| should 581 // not need to be destroyed here. 582 EXPECT_EQ(child_windows, root_window()->children().size()); 583} 584 585// Test the scenario when two swipe gesture occur quickly one after another so 586// that the second swipe occurs while the transition animation triggered by the 587// first swipe is in progress. 588// The second swipe is supposed to instantly complete the animation caused by 589// the first swipe, ask the delegate to create a new layer, and animate it. 590TEST_F(WindowSliderTest, SwipeDuringSwipeAnimation) { 591 scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL)); 592 window->SetBounds(gfx::Rect(0, 0, 400, 400)); 593 WindowSliderDelegateTest slider_delegate; 594 new WindowSlider(&slider_delegate, root_window(), window.get()); 595 596 ui::ScopedAnimationDurationScaleMode normal_duration_( 597 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); 598 ui::LayerAnimator* animator = window->layer()->GetAnimator(); 599 gfx::AnimationContainerElement* element = animator; 600 animator->set_disable_timer_for_test(true); 601 ui::LayerAnimatorTestController test_controller(animator); 602 603 aura::test::EventGenerator generator(root_window()); 604 605 // Swipe forward so that |window|'s layer is the one animating. 606 generator.GestureScrollSequence( 607 gfx::Point(10, 10), 608 gfx::Point(180, 10), 609 base::TimeDelta::FromMilliseconds(10), 610 2); 611 EXPECT_TRUE(slider_delegate.created_back_layer()); 612 EXPECT_FALSE(slider_delegate.slide_aborted()); 613 EXPECT_FALSE(slider_delegate.created_front_layer()); 614 EXPECT_TRUE(slider_delegate.slide_completing()); 615 EXPECT_FALSE(slider_delegate.slide_completed()); 616 EXPECT_FALSE(slider_delegate.slider_destroyed()); 617 ui::ScopedLayerAnimationSettings settings(animator); 618 base::TimeDelta duration = settings.GetTransitionDuration(); 619 test_controller.StartThreadedAnimationsIfNeeded(); 620 base::TimeTicks start_time1 = gfx::FrameTime::Now(); 621 622 element->Step(start_time1 + duration/2); 623 EXPECT_FALSE(slider_delegate.slide_completed()); 624 slider_delegate.Reset(); 625 // Generate another horizontal swipe while the animation from the previous 626 // swipe is in progress. 627 generator.GestureScrollSequence( 628 gfx::Point(10, 10), 629 gfx::Point(180, 10), 630 base::TimeDelta::FromMilliseconds(10), 631 2); 632 // Performing the second swipe should instantly complete the slide started 633 // by the first swipe and create a new layer. 634 EXPECT_TRUE(slider_delegate.created_back_layer()); 635 EXPECT_FALSE(slider_delegate.slide_aborted()); 636 EXPECT_FALSE(slider_delegate.created_front_layer()); 637 EXPECT_TRUE(slider_delegate.slide_completing()); 638 EXPECT_TRUE(slider_delegate.slide_completed()); 639 EXPECT_FALSE(slider_delegate.slider_destroyed()); 640 test_controller.StartThreadedAnimationsIfNeeded(); 641 base::TimeTicks start_time2 = gfx::FrameTime::Now(); 642 slider_delegate.Reset(); 643 element->Step(start_time2 + duration); 644 // The animation for the second slide should now be completed. 645 EXPECT_TRUE(slider_delegate.slide_completed()); 646 slider_delegate.Reset(); 647 648 window.reset(); 649 EXPECT_TRUE(slider_delegate.slider_destroyed()); 650} 651 652} // namespace content 653