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 |