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