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