+class KeyboardControllerAnimationTest : public KeyboardControllerTest,
+ public KeyboardControllerObserver {
+ public:
+ KeyboardControllerAnimationTest() {}
+ virtual ~KeyboardControllerAnimationTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ // We cannot short-circuit animations for this test.
+ ui::ScopedAnimationDurationScaleMode normal_duration_mode(
+ ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
+
+ KeyboardControllerTest::SetUp();
+
+ const gfx::Rect& root_bounds = root_window()->bounds();
+ keyboard_container()->SetBounds(root_bounds);
+ root_window()->AddChild(keyboard_container());
+ controller()->AddObserver(this);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ controller()->RemoveObserver(this);
+ KeyboardControllerTest::TearDown();
+ }
+
+ protected:
+ // KeyboardControllerObserver overrides
+ virtual void OnKeyboardBoundsChanging(const gfx::Rect& new_bounds) OVERRIDE {
+ notified_bounds_ = new_bounds;
+ }
+
+ const gfx::Rect& notified_bounds() { return notified_bounds_; }
+
+ aura::Window* keyboard_container() {
+ return controller()->GetContainerWindow();
+ }
+
+ aura::Window* keyboard_window() {
+ return proxy()->GetKeyboardWindow();
+ }
+
+ private:
+ gfx::Rect notified_bounds_;
+
+ DISALLOW_COPY_AND_ASSIGN(KeyboardControllerAnimationTest);
+};
+
+// Tests virtual keyboard has correct show and hide animation.
+TEST_F(KeyboardControllerAnimationTest, ContainerAnimation) {
+ ui::Layer* layer = keyboard_container()->layer();
+ ShowKeyboard();
+
+ // Keyboard container and window should immediately become visible before
+ // animation starts.
+ EXPECT_TRUE(keyboard_container()->IsVisible());
+ EXPECT_TRUE(keyboard_window()->IsVisible());
+ float show_start_opacity = layer->opacity();
+ gfx::Transform transform;
+ transform.Translate(0, keyboard_window()->bounds().height());
+ EXPECT_EQ(transform, layer->transform());
+ EXPECT_EQ(gfx::Rect(), notified_bounds());
+
+ RunAnimationForLayer(layer);
+ EXPECT_TRUE(keyboard_container()->IsVisible());
+ EXPECT_TRUE(keyboard_window()->IsVisible());
+ float show_end_opacity = layer->opacity();
+ EXPECT_LT(show_start_opacity, show_end_opacity);
+ EXPECT_EQ(gfx::Transform(), layer->transform());
+ // KeyboardController should notify the bounds of keyboard window to its
+ // observers after show animation finished.
+ EXPECT_EQ(keyboard_window()->bounds(), notified_bounds());
+
+ // Directly hide keyboard without delay.
+ controller()->HideKeyboard(KeyboardController::HIDE_REASON_AUTOMATIC);
+ EXPECT_TRUE(keyboard_container()->IsVisible());
+ EXPECT_TRUE(keyboard_container()->layer()->visible());
+ EXPECT_TRUE(keyboard_window()->IsVisible());
+ float hide_start_opacity = layer->opacity();
+ // KeyboardController should notify the bounds of keyboard window to its
+ // observers before hide animation starts.
+ EXPECT_EQ(gfx::Rect(), notified_bounds());
+
+ RunAnimationForLayer(layer);
+ EXPECT_FALSE(keyboard_container()->IsVisible());
+ EXPECT_FALSE(keyboard_container()->layer()->visible());
+ EXPECT_FALSE(keyboard_window()->IsVisible());
+ float hide_end_opacity = layer->opacity();
+ EXPECT_GT(hide_start_opacity, hide_end_opacity);
+ EXPECT_EQ(transform, layer->transform());
+ EXPECT_EQ(gfx::Rect(), notified_bounds());
+}
+
+// Show keyboard during keyboard hide animation should abort the hide animation
+// and the keyboard should animate in.
+// Test for crbug.com/333284.
+TEST_F(KeyboardControllerAnimationTest, ContainerShowWhileHide) {
+ ui::Layer* layer = keyboard_container()->layer();
+ ShowKeyboard();
+ RunAnimationForLayer(layer);
+
+ controller()->HideKeyboard(KeyboardController::HIDE_REASON_AUTOMATIC);
+ // Before hide animation finishes, show keyboard again.
+ ShowKeyboard();
+ RunAnimationForLayer(layer);
+ EXPECT_TRUE(keyboard_container()->IsVisible());
+ EXPECT_TRUE(keyboard_window()->IsVisible());
+ EXPECT_EQ(1.0, layer->opacity());
+ EXPECT_EQ(gfx::Transform(), layer->transform());
+}
+