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