window_slider_unittest.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten// Use of this source code is governed by a BSD-style license that can be
3c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten// found in the LICENSE file.
4c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten
5c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten#include "content/browser/web_contents/aura/window_slider.h"
6c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten
7c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten#include "base/bind.h"
8c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten#include "base/time/time.h"
9c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten#include "testing/gtest/include/gtest/gtest.h"
10c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten#include "ui/aura/test/aura_test_base.h"
11c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten#include "ui/aura/test/test_window_delegate.h"
12c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten#include "ui/aura/window.h"
13c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten#include "ui/base/hit_test.h"
14c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten#include "ui/compositor/scoped_animation_duration_scale_mode.h"
15c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten#include "ui/compositor/scoped_layer_animation_settings.h"
16c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten#include "ui/compositor/test/layer_animator_test_controller.h"
17c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten#include "ui/events/event_processor.h"
18c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten#include "ui/events/event_utils.h"
19c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten#include "ui/events/test/event_generator.h"
207126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include "ui/gfx/frame_time.h"
21c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten
22be2218961ac506ba9c2be0dddb2f74debd283bb8Glenn Kastennamespace content {
23c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten
24c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kastenvoid DispatchEventDuringScrollCallback(ui::EventProcessor* dispatcher,
25c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten                                       ui::Event* event,
26c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten                                       ui::EventType type,
27c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten                                       const gfx::Vector2dF& delta) {
28c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  if (type != ui::ET_GESTURE_SCROLL_UPDATE)
29c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten    return;
30c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  ui::EventDispatchDetails details = dispatcher->OnEventFromSource(event);
31c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  CHECK(!details.dispatcher_destroyed);
32c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten}
33c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten
34c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kastenvoid ChangeSliderOwnerDuringScrollCallback(scoped_ptr<aura::Window>* window,
35c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten                                           WindowSlider* slider,
36c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten                                           ui::EventType type,
37c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten                                           const gfx::Vector2dF& delta) {
387126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  if (type != ui::ET_GESTURE_SCROLL_UPDATE)
39c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten    return;
40c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  aura::Window* new_window = new aura::Window(NULL);
417126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  new_window->Init(aura::WINDOW_LAYER_TEXTURED);
427126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  new_window->Show();
437126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  slider->ChangeOwner(new_window);
447126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  (*window)->parent()->AddChild(new_window);
457126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  window->reset(new_window);
467126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten}
477126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
4858432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kastenvoid ConfirmSlideDuringScrollCallback(WindowSlider* slider,
49c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten                                      ui::EventType type,
50c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten                                      const gfx::Vector2dF& delta) {
51c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  static float total_delta_x = 0;
52c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  if (type == ui::ET_GESTURE_SCROLL_BEGIN)
537126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    total_delta_x = 0;
547126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
55c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  if (type == ui::ET_GESTURE_SCROLL_UPDATE) {
56c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten    total_delta_x += delta.x();
57c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten    if (total_delta_x >= 70)
587126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten      EXPECT_TRUE(slider->IsSlideInProgress());
59c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  } else {
60c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten    EXPECT_FALSE(slider->IsSlideInProgress());
617126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  }
627126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten}
637126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
647126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenvoid ConfirmNoSlideDuringScrollCallback(WindowSlider* slider,
65c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten                                        ui::EventType type,
66c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten                                        const gfx::Vector2dF& delta) {
67c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  EXPECT_FALSE(slider->IsSlideInProgress());
6858432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten}
69c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten
707126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// The window delegate does not receive any events.
717126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenclass NoEventWindowDelegate : public aura::test::TestWindowDelegate {
72c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten public:
73c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  NoEventWindowDelegate() {
74c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  }
75c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  virtual ~NoEventWindowDelegate() {}
7658432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten
77c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten private:
78c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  // Overridden from aura::WindowDelegate:
79c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  virtual bool HasHitTestMask() const OVERRIDE { return true; }
80c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten
81c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  DISALLOW_COPY_AND_ASSIGN(NoEventWindowDelegate);
82c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten};
837126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
847126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenclass WindowSliderDelegateTest : public WindowSlider::Delegate {
857126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten public:
867126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  WindowSliderDelegateTest()
877126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten      : can_create_layer_(true),
887126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        created_back_layer_(false),
8958432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten        created_front_layer_(false),
907126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        slide_completing_(false),
917126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        slide_completed_(false),
927126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        slide_aborted_(false),
937126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        slider_destroyed_(false) {
947126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  }
957126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  virtual ~WindowSliderDelegateTest() {
967126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // Make sure slide_completed() gets called if slide_completing() was called.
977126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    CHECK(!slide_completing_ || slide_completed_);
987126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  }
9958432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten
1007126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  void Reset() {
1017126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    can_create_layer_ = true;
1027126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    created_back_layer_ = false;
1037126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    created_front_layer_ = false;
1047126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    slide_completing_ = false;
1057126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    slide_completed_ = false;
1067126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    slide_aborted_ = false;
1077126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    slider_destroyed_ = false;
1087126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  }
1097126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1107126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  void SetCanCreateLayer(bool can_create_layer) {
1117126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    can_create_layer_ = can_create_layer;
1127126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  }
1137126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1147126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  bool created_back_layer() const { return created_back_layer_; }
1157126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  bool created_front_layer() const { return created_front_layer_; }
1167126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  bool slide_completing() const { return slide_completing_; }
1177126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  bool slide_completed() const { return slide_completed_; }
1187126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  bool slide_aborted() const { return slide_aborted_; }
1197126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  bool slider_destroyed() const { return slider_destroyed_; }
1207126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1217126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten protected:
1227126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  ui::Layer* CreateLayerForTest() {
1237126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    CHECK(can_create_layer_);
1247126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    ui::Layer* layer = new ui::Layer(ui::LAYER_SOLID_COLOR);
1257126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    layer->SetColor(SK_ColorRED);
1267126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    return layer;
1277126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  }
1287126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1297126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  // Overridden from WindowSlider::Delegate:
1307126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  virtual ui::Layer* CreateBackLayer() OVERRIDE {
1317126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    if (!can_create_layer_)
1327126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten      return NULL;
1337126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    created_back_layer_ = true;
1347126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    return CreateLayerForTest();
1357126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  }
1367126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1377126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  virtual ui::Layer* CreateFrontLayer() OVERRIDE {
1387126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    if (!can_create_layer_)
13958432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten      return NULL;
1407126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    created_front_layer_ = true;
1417126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    return CreateLayerForTest();
1427126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  }
1437126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1447126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  virtual void OnWindowSlideCompleted(scoped_ptr<ui::Layer> layer) OVERRIDE {
1457126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    slide_completed_ = true;
1467126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  }
1477126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1487126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  virtual void OnWindowSlideCompleting() OVERRIDE {
1497126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    slide_completing_ = true;
1507126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  }
1517126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1527126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  virtual void OnWindowSlideAborted() OVERRIDE {
1537126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    slide_aborted_ = true;
1547126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  }
1557126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1567126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  virtual void OnWindowSliderDestroyed() OVERRIDE {
1577126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    slider_destroyed_ = true;
1587126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  }
1594076e5009bfe70bc06a78f5aafec77af6c03201dGlenn Kasten
1604076e5009bfe70bc06a78f5aafec77af6c03201dGlenn Kasten private:
161e047d27324083628b51bad0661a184f6cb96c56dGlenn Kasten  bool can_create_layer_;
1627126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  bool created_back_layer_;
1637126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  bool created_front_layer_;
1647126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  bool slide_completing_;
1657126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  bool slide_completed_;
1667126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  bool slide_aborted_;
1677126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  bool slider_destroyed_;
1687126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1697126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  DISALLOW_COPY_AND_ASSIGN(WindowSliderDelegateTest);
1707126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten};
1717126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1727126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// This delegate destroys the owner window when the slider is destroyed.
1737126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenclass WindowSliderDeleteOwnerOnDestroy : public WindowSliderDelegateTest {
1747126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten public:
1757126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  explicit WindowSliderDeleteOwnerOnDestroy(aura::Window* owner)
1767126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten      : owner_(owner) {
1777126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  }
1787126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten  virtual ~WindowSliderDeleteOwnerOnDestroy() {}
1797126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
180c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten private:
181c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten  // 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  ui::test::EventGenerator generator(root_window());
218
219  // Generate a horizontal overscroll.
220  WindowSlider* slider =
221      new WindowSlider(&slider_delegate, root_window(), window.get());
222  generator.GestureScrollSequenceWithCallback(
223      gfx::Point(10, 10),
224      gfx::Point(180, 10),
225      base::TimeDelta::FromMilliseconds(10),
226      10,
227      base::Bind(&ConfirmSlideDuringScrollCallback, slider));
228  EXPECT_TRUE(slider_delegate.created_back_layer());
229  EXPECT_TRUE(slider_delegate.slide_completing());
230  EXPECT_TRUE(slider_delegate.slide_completed());
231  EXPECT_FALSE(slider_delegate.created_front_layer());
232  EXPECT_FALSE(slider_delegate.slide_aborted());
233  EXPECT_FALSE(slider_delegate.slider_destroyed());
234  EXPECT_FALSE(slider->IsSlideInProgress());
235  slider_delegate.Reset();
236  window->SetTransform(gfx::Transform());
237
238  // Generate a horizontal overscroll in the reverse direction.
239  generator.GestureScrollSequenceWithCallback(
240      gfx::Point(180, 10),
241      gfx::Point(10, 10),
242      base::TimeDelta::FromMilliseconds(10),
243      10,
244      base::Bind(&ConfirmSlideDuringScrollCallback, slider));
245  EXPECT_TRUE(slider_delegate.created_front_layer());
246  EXPECT_TRUE(slider_delegate.slide_completing());
247  EXPECT_TRUE(slider_delegate.slide_completed());
248  EXPECT_FALSE(slider_delegate.created_back_layer());
249  EXPECT_FALSE(slider_delegate.slide_aborted());
250  EXPECT_FALSE(slider_delegate.slider_destroyed());
251  EXPECT_FALSE(slider->IsSlideInProgress());
252  slider_delegate.Reset();
253
254  // Generate a vertical overscroll.
255  generator.GestureScrollSequenceWithCallback(
256      gfx::Point(10, 10),
257      gfx::Point(10, 80),
258      base::TimeDelta::FromMilliseconds(10),
259      10,
260      base::Bind(&ConfirmNoSlideDuringScrollCallback, slider));
261  EXPECT_FALSE(slider_delegate.created_back_layer());
262  EXPECT_FALSE(slider_delegate.slide_completing());
263  EXPECT_FALSE(slider_delegate.slide_completed());
264  EXPECT_FALSE(slider_delegate.created_front_layer());
265  EXPECT_FALSE(slider_delegate.slide_aborted());
266  EXPECT_FALSE(slider->IsSlideInProgress());
267  slider_delegate.Reset();
268
269  // Generate a horizontal scroll that starts overscroll, but doesn't scroll
270  // enough to complete it.
271  generator.GestureScrollSequenceWithCallback(
272      gfx::Point(10, 10),
273      gfx::Point(80, 10),
274      base::TimeDelta::FromMilliseconds(10),
275      10,
276      base::Bind(&ConfirmSlideDuringScrollCallback, slider));
277  EXPECT_TRUE(slider_delegate.created_back_layer());
278  EXPECT_TRUE(slider_delegate.slide_aborted());
279  EXPECT_FALSE(slider_delegate.created_front_layer());
280  EXPECT_FALSE(slider_delegate.slide_completing());
281  EXPECT_FALSE(slider_delegate.slide_completed());
282  EXPECT_FALSE(slider_delegate.slider_destroyed());
283  EXPECT_FALSE(slider->IsSlideInProgress());
284  slider_delegate.Reset();
285
286  // Destroy the window. This should destroy the slider.
287  window.reset();
288  EXPECT_TRUE(slider_delegate.slider_destroyed());
289}
290
291// Tests that the window slide is interrupted when a different type of event
292// happens.
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('a', ui::VKEY_A, ui::EF_NONE),
304    NULL
305  };
306
307  new WindowSlider(&slider_delegate, root_window(), window.get());
308  for (int i = 0; events[i]; ++i) {
309    // Generate a horizontal overscroll.
310    ui::test::EventGenerator generator(root_window());
311    generator.GestureScrollSequenceWithCallback(
312        gfx::Point(10, 10),
313        gfx::Point(80, 10),
314        base::TimeDelta::FromMilliseconds(10),
315        1,
316        base::Bind(&DispatchEventDuringScrollCallback,
317                   root_window()->GetHost()->event_processor(),
318                   base::Owned(events[i])));
319    EXPECT_TRUE(slider_delegate.created_back_layer());
320    EXPECT_TRUE(slider_delegate.slide_aborted());
321    EXPECT_FALSE(slider_delegate.created_front_layer());
322    EXPECT_FALSE(slider_delegate.slide_completing());
323    EXPECT_FALSE(slider_delegate.slide_completed());
324    EXPECT_FALSE(slider_delegate.slider_destroyed());
325    slider_delegate.Reset();
326  }
327  window.reset();
328  EXPECT_TRUE(slider_delegate.slider_destroyed());
329}
330
331// Tests that the window slide can continue after it is interrupted by another
332// event if the user continues scrolling.
333TEST_F(WindowSliderTest, WindowSlideInterruptedThenContinues) {
334  scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL));
335  window->SetBounds(gfx::Rect(0, 0, 400, 400));
336  WindowSliderDelegateTest slider_delegate;
337
338  ui::ScopedAnimationDurationScaleMode normal_duration_(
339      ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
340  ui::LayerAnimator* animator = window->layer()->GetAnimator();
341  animator->set_disable_timer_for_test(true);
342  ui::LayerAnimatorTestController test_controller(animator);
343
344  WindowSlider* slider =
345      new WindowSlider(&slider_delegate, root_window(), window.get());
346
347  ui::MouseEvent interrupt_event(ui::ET_MOUSE_MOVED,
348                                 gfx::Point(55, 10),
349                                 gfx::Point(55, 10),
350                                 0, 0);
351
352  ui::test::EventGenerator generator(root_window());
353
354  // Start the scroll sequence. Scroll forward so that |window|'s layer is the
355  // one animating.
356  const int kTouchId = 5;
357  ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
358                       gfx::Point(10, 10),
359                       kTouchId,
360                       ui::EventTimeForNow());
361  generator.Dispatch(&press);
362
363  // First scroll event of the sequence.
364  ui::TouchEvent move1(ui::ET_TOUCH_MOVED,
365                       gfx::Point(100, 10),
366                       kTouchId,
367                       ui::EventTimeForNow());
368  generator.Dispatch(&move1);
369  EXPECT_TRUE(slider->IsSlideInProgress());
370  EXPECT_FALSE(animator->is_animating());
371  // Dispatch the event after the first scroll and confirm it interrupts the
372  // scroll and starts  the "reset slide" animation.
373  generator.Dispatch(&interrupt_event);
374  EXPECT_TRUE(slider->IsSlideInProgress());
375  EXPECT_TRUE(animator->is_animating());
376  EXPECT_TRUE(slider_delegate.created_back_layer());
377  // slide_aborted() should be false because the 'reset slide' animation
378  // hasn't completed yet.
379  EXPECT_FALSE(slider_delegate.slide_aborted());
380  EXPECT_FALSE(slider_delegate.created_front_layer());
381  EXPECT_FALSE(slider_delegate.slide_completing());
382  EXPECT_FALSE(slider_delegate.slide_completed());
383  EXPECT_FALSE(slider_delegate.slider_destroyed());
384  slider_delegate.Reset();
385
386  // Second scroll event of the sequence.
387  ui::TouchEvent move2(ui::ET_TOUCH_MOVED,
388                       gfx::Point(200, 10),
389                       kTouchId,
390                       ui::EventTimeForNow());
391  generator.Dispatch(&move2);
392  // The second scroll should instantly cause the animation to complete.
393  EXPECT_FALSE(animator->is_animating());
394  EXPECT_FALSE(slider_delegate.created_back_layer());
395  // The ResetScroll() animation was completed, so now slide_aborted()
396  // should be true.
397  EXPECT_TRUE(slider_delegate.slide_aborted());
398
399  // Third scroll event of the sequence.
400  ui::TouchEvent move3(ui::ET_TOUCH_MOVED,
401                       gfx::Point(300, 10),
402                       kTouchId,
403                       ui::EventTimeForNow());
404  generator.Dispatch(&move3);
405  // The third scroll should re-start the sliding.
406  EXPECT_TRUE(slider->IsSlideInProgress());
407  EXPECT_TRUE(slider_delegate.created_back_layer());
408
409  // Generate the release event, finishing the scroll sequence.
410  ui::TouchEvent release(ui::ET_TOUCH_RELEASED,
411                         gfx::Point(300, 10),
412                         kTouchId,
413                         ui::EventTimeForNow());
414  generator.Dispatch(&release);
415  // When the scroll gesture ends, the slide animation should start.
416  EXPECT_TRUE(slider->IsSlideInProgress());
417  EXPECT_TRUE(animator->is_animating());
418  EXPECT_TRUE(slider_delegate.slide_completing());
419  EXPECT_FALSE(slider_delegate.created_front_layer());
420  EXPECT_FALSE(slider_delegate.slide_completed());
421  EXPECT_FALSE(slider_delegate.slider_destroyed());
422
423  // Progress the animator to complete the slide animation.
424  ui::ScopedLayerAnimationSettings settings(animator);
425  base::TimeDelta duration = settings.GetTransitionDuration();
426  test_controller.StartThreadedAnimationsIfNeeded();
427  animator->Step(gfx::FrameTime::Now() + duration);
428
429  EXPECT_TRUE(slider_delegate.slide_completed());
430  EXPECT_FALSE(slider_delegate.slider_destroyed());
431
432  window.reset();
433  EXPECT_TRUE(slider_delegate.slider_destroyed());
434}
435
436// Tests that the slide works correctly when the owner of the window changes
437// during the duration of the slide.
438TEST_F(WindowSliderTest, OwnerWindowChangesDuringWindowSlide) {
439  scoped_ptr<aura::Window> parent(CreateNormalWindow(0, root_window(), NULL));
440
441  NoEventWindowDelegate window_delegate;
442  window_delegate.set_window_component(HTNOWHERE);
443  scoped_ptr<aura::Window> window(CreateNormalWindow(1, parent.get(),
444                                                     &window_delegate));
445
446  WindowSliderDelegateTest slider_delegate;
447  scoped_ptr<WindowSlider> slider(
448      new WindowSlider(&slider_delegate, parent.get(), window.get()));
449
450  // Generate a horizontal scroll, and change the owner in the middle of the
451  // scroll.
452  ui::test::EventGenerator generator(root_window());
453  aura::Window* old_window = window.get();
454  generator.GestureScrollSequenceWithCallback(
455      gfx::Point(10, 10),
456      gfx::Point(80, 10),
457      base::TimeDelta::FromMilliseconds(10),
458      1,
459      base::Bind(&ChangeSliderOwnerDuringScrollCallback,
460                 base::Unretained(&window),
461                 slider.get()));
462  aura::Window* new_window = window.get();
463  EXPECT_NE(old_window, new_window);
464
465  EXPECT_TRUE(slider_delegate.created_back_layer());
466  EXPECT_TRUE(slider_delegate.slide_completing());
467  EXPECT_TRUE(slider_delegate.slide_completed());
468  EXPECT_FALSE(slider_delegate.created_front_layer());
469  EXPECT_FALSE(slider_delegate.slide_aborted());
470  EXPECT_FALSE(slider_delegate.slider_destroyed());
471}
472
473// If the delegate doesn't create the layer to show while sliding, WindowSlider
474// shouldn't start the slide or change delegate's state in any way in response
475// to user input.
476TEST_F(WindowSliderTest, NoSlideWhenLayerCantBeCreated) {
477  scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL));
478  window->SetBounds(gfx::Rect(0, 0, 400, 400));
479  WindowSliderDelegateTest slider_delegate;
480  slider_delegate.SetCanCreateLayer(false);
481  WindowSlider* slider =
482      new WindowSlider(&slider_delegate, root_window(), window.get());
483
484  ui::test::EventGenerator generator(root_window());
485
486  // No slide in progress should be reported during scroll since the layer
487  // wasn't created.
488  generator.GestureScrollSequenceWithCallback(
489      gfx::Point(10, 10),
490      gfx::Point(180, 10),
491      base::TimeDelta::FromMilliseconds(10),
492      1,
493      base::Bind(&ConfirmNoSlideDuringScrollCallback, slider));
494
495  EXPECT_FALSE(slider_delegate.created_back_layer());
496  EXPECT_FALSE(slider_delegate.slide_completing());
497  EXPECT_FALSE(slider_delegate.slide_completed());
498  EXPECT_FALSE(slider_delegate.created_front_layer());
499  EXPECT_FALSE(slider_delegate.slide_aborted());
500  EXPECT_FALSE(slider_delegate.slider_destroyed());
501  window->SetTransform(gfx::Transform());
502
503  slider_delegate.SetCanCreateLayer(true);
504  generator.GestureScrollSequenceWithCallback(
505      gfx::Point(10, 10),
506      gfx::Point(180, 10),
507      base::TimeDelta::FromMilliseconds(10),
508      10,
509      base::Bind(&ConfirmSlideDuringScrollCallback, slider));
510  EXPECT_TRUE(slider_delegate.created_back_layer());
511  EXPECT_TRUE(slider_delegate.slide_completing());
512  EXPECT_TRUE(slider_delegate.slide_completed());
513  EXPECT_FALSE(slider_delegate.created_front_layer());
514  EXPECT_FALSE(slider_delegate.slide_aborted());
515  EXPECT_FALSE(slider_delegate.slider_destroyed());
516
517  window.reset();
518  EXPECT_TRUE(slider_delegate.slider_destroyed());
519}
520
521// Tests that the owner window can be destroyed from |OnWindowSliderDestroyed()|
522// delegate callback without causing a crash.
523TEST_F(WindowSliderTest, OwnerIsDestroyedOnSliderDestroy) {
524  size_t child_windows = root_window()->children().size();
525  aura::Window* window = CreateNormalWindow(0, root_window(), NULL);
526  window->SetBounds(gfx::Rect(0, 0, 400, 400));
527  EXPECT_EQ(child_windows + 1, root_window()->children().size());
528
529  WindowSliderDeleteOwnerOnDestroy slider_delegate(window);
530  ui::test::EventGenerator generator(root_window());
531
532  // Generate a horizontal overscroll.
533  scoped_ptr<WindowSlider> slider(
534      new WindowSlider(&slider_delegate, root_window(), window));
535  generator.GestureScrollSequence(gfx::Point(10, 10),
536                                  gfx::Point(180, 10),
537                                  base::TimeDelta::FromMilliseconds(10),
538                                  10);
539  EXPECT_TRUE(slider_delegate.created_back_layer());
540  EXPECT_TRUE(slider_delegate.slide_completing());
541  EXPECT_TRUE(slider_delegate.slide_completed());
542  EXPECT_FALSE(slider_delegate.created_front_layer());
543  EXPECT_FALSE(slider_delegate.slide_aborted());
544  EXPECT_FALSE(slider_delegate.slider_destroyed());
545
546  slider.reset();
547  // Destroying the slider would have destroyed |window| too. So |window| should
548  // not need to be destroyed here.
549  EXPECT_EQ(child_windows, root_window()->children().size());
550}
551
552// Tests that the owner window can be destroyed from |OnWindowSlideComplete()|
553// delegate callback without causing a crash.
554TEST_F(WindowSliderTest, OwnerIsDestroyedOnSlideComplete) {
555  size_t child_windows = root_window()->children().size();
556  aura::Window* window = CreateNormalWindow(0, root_window(), NULL);
557  window->SetBounds(gfx::Rect(0, 0, 400, 400));
558  EXPECT_EQ(child_windows + 1, root_window()->children().size());
559
560  WindowSliderDeleteOwnerOnComplete slider_delegate(window);
561  ui::test::EventGenerator generator(root_window());
562
563  // Generate a horizontal overscroll.
564  new WindowSlider(&slider_delegate, root_window(), window);
565  generator.GestureScrollSequence(gfx::Point(10, 10),
566                                  gfx::Point(180, 10),
567                                  base::TimeDelta::FromMilliseconds(10),
568                                  10);
569  EXPECT_TRUE(slider_delegate.created_back_layer());
570  EXPECT_TRUE(slider_delegate.slide_completing());
571  EXPECT_TRUE(slider_delegate.slide_completed());
572  EXPECT_FALSE(slider_delegate.created_front_layer());
573  EXPECT_FALSE(slider_delegate.slide_aborted());
574  EXPECT_TRUE(slider_delegate.slider_destroyed());
575
576  // Destroying the slider would have destroyed |window| too. So |window| should
577  // not need to be destroyed here.
578  EXPECT_EQ(child_windows, root_window()->children().size());
579}
580
581// Test the scenario when two swipe gesture occur quickly one after another so
582// that the second swipe occurs while the transition animation triggered by the
583// first swipe is in progress.
584// The second swipe is supposed to instantly complete the animation caused by
585// the first swipe, ask the delegate to create a new layer, and animate it.
586TEST_F(WindowSliderTest, SwipeDuringSwipeAnimation) {
587  scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL));
588  window->SetBounds(gfx::Rect(0, 0, 400, 400));
589  WindowSliderDelegateTest slider_delegate;
590  new WindowSlider(&slider_delegate, root_window(), window.get());
591
592  // This test uses explicit durations so needs a normal duration.
593  ui::ScopedAnimationDurationScaleMode normal_duration(
594      ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
595  ui::LayerAnimator* animator = window->layer()->GetAnimator();
596  animator->set_disable_timer_for_test(true);
597  ui::LayerAnimatorTestController test_controller(animator);
598
599  ui::test::EventGenerator generator(root_window());
600
601  // Swipe forward so that |window|'s layer is the one animating.
602  generator.GestureScrollSequence(
603      gfx::Point(10, 10),
604      gfx::Point(180, 10),
605      base::TimeDelta::FromMilliseconds(10),
606      2);
607  EXPECT_TRUE(slider_delegate.created_back_layer());
608  EXPECT_FALSE(slider_delegate.slide_aborted());
609  EXPECT_FALSE(slider_delegate.created_front_layer());
610  EXPECT_TRUE(slider_delegate.slide_completing());
611  EXPECT_FALSE(slider_delegate.slide_completed());
612  EXPECT_FALSE(slider_delegate.slider_destroyed());
613  ui::ScopedLayerAnimationSettings settings(animator);
614  base::TimeDelta duration = settings.GetTransitionDuration();
615  test_controller.StartThreadedAnimationsIfNeeded();
616  base::TimeTicks start_time1 =  gfx::FrameTime::Now();
617
618  animator->Step(start_time1 + duration / 2);
619  EXPECT_FALSE(slider_delegate.slide_completed());
620  slider_delegate.Reset();
621  // Generate another horizontal swipe while the animation from the previous
622  // swipe is in progress.
623  generator.GestureScrollSequence(
624      gfx::Point(10, 10),
625      gfx::Point(180, 10),
626      base::TimeDelta::FromMilliseconds(10),
627      2);
628  // Performing the second swipe should instantly complete the slide started
629  // by the first swipe and create a new layer.
630  EXPECT_TRUE(slider_delegate.created_back_layer());
631  EXPECT_FALSE(slider_delegate.slide_aborted());
632  EXPECT_FALSE(slider_delegate.created_front_layer());
633  EXPECT_TRUE(slider_delegate.slide_completing());
634  EXPECT_TRUE(slider_delegate.slide_completed());
635  EXPECT_FALSE(slider_delegate.slider_destroyed());
636  test_controller.StartThreadedAnimationsIfNeeded();
637  base::TimeTicks start_time2 =  gfx::FrameTime::Now();
638  slider_delegate.Reset();
639  animator->Step(start_time2 + duration);
640  // The animation for the second slide should now be completed.
641  EXPECT_TRUE(slider_delegate.slide_completed());
642  slider_delegate.Reset();
643
644  window.reset();
645  EXPECT_TRUE(slider_delegate.slider_destroyed());
646}
647
648}  // namespace content
649