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 "ui/keyboard/keyboard_controller.h" 6 7 #include "base/bind.h" 8 #include "base/command_line.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/message_loop/message_loop.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 #include "ui/aura/client/focus_client.h" 13 #include "ui/aura/layout_manager.h" 14 #include "ui/aura/test/aura_test_helper.h" 15 #include "ui/aura/test/event_generator.h" 16 #include "ui/aura/test/test_window_delegate.h" 17 #include "ui/aura/window.h" 18 #include "ui/aura/window_event_dispatcher.h" 19 #include "ui/base/ime/dummy_text_input_client.h" 20 #include "ui/base/ime/input_method.h" 21 #include "ui/base/ime/input_method_factory.h" 22 #include "ui/base/ime/text_input_client.h" 23 #include "ui/base/ime/text_input_focus_manager.h" 24 #include "ui/base/ui_base_switches_util.h" 25 #include "ui/compositor/compositor.h" 26 #include "ui/compositor/layer_type.h" 27 #include "ui/compositor/scoped_animation_duration_scale_mode.h" 28 #include "ui/compositor/test/context_factories_for_test.h" 29 #include "ui/compositor/test/layer_animator_test_controller.h" 30 #include "ui/gfx/geometry/rect.h" 31 #include "ui/keyboard/keyboard_controller_observer.h" 32 #include "ui/keyboard/keyboard_controller_proxy.h" 33 #include "ui/keyboard/keyboard_switches.h" 34 #include "ui/keyboard/keyboard_util.h" 35 #include "ui/wm/core/default_activation_client.h" 36 37 namespace keyboard { 38 namespace { 39 40 // Steps a layer animation until it is completed. Animations must be enabled. 41 void RunAnimationForLayer(ui::Layer* layer) { 42 // Animations must be enabled for stepping to work. 43 ASSERT_NE(ui::ScopedAnimationDurationScaleMode::duration_scale_mode(), 44 ui::ScopedAnimationDurationScaleMode::ZERO_DURATION); 45 46 ui::LayerAnimatorTestController controller(layer->GetAnimator()); 47 // Multiple steps are required to complete complex animations. 48 // TODO(vollick): This should not be necessary. crbug.com/154017 49 while (controller.animator()->is_animating()) { 50 controller.StartThreadedAnimationsIfNeeded(); 51 base::TimeTicks step_time = controller.animator()->last_step_time(); 52 controller.animator()->Step(step_time + 53 base::TimeDelta::FromMilliseconds(1000)); 54 } 55 } 56 57 // An event handler that focuses a window when it is clicked/touched on. This is 58 // used to match the focus manger behaviour in ash and views. 59 class TestFocusController : public ui::EventHandler { 60 public: 61 explicit TestFocusController(aura::Window* root) 62 : root_(root) { 63 root_->AddPreTargetHandler(this); 64 } 65 66 virtual ~TestFocusController() { 67 root_->RemovePreTargetHandler(this); 68 } 69 70 private: 71 // Overridden from ui::EventHandler: 72 virtual void OnEvent(ui::Event* event) OVERRIDE { 73 aura::Window* target = static_cast<aura::Window*>(event->target()); 74 if (event->type() == ui::ET_MOUSE_PRESSED || 75 event->type() == ui::ET_TOUCH_PRESSED) { 76 aura::client::GetFocusClient(target)->FocusWindow(target); 77 } 78 } 79 80 aura::Window* root_; 81 DISALLOW_COPY_AND_ASSIGN(TestFocusController); 82 }; 83 84 class TestKeyboardControllerProxy : public KeyboardControllerProxy { 85 public: 86 TestKeyboardControllerProxy() 87 : input_method_( 88 ui::CreateInputMethod(NULL, gfx::kNullAcceleratedWidget)) {} 89 90 virtual ~TestKeyboardControllerProxy() { 91 // Destroy the window before the delegate. 92 window_.reset(); 93 } 94 95 // Overridden from KeyboardControllerProxy: 96 virtual bool HasKeyboardWindow() const OVERRIDE { return window_; } 97 virtual aura::Window* GetKeyboardWindow() OVERRIDE { 98 if (!window_) { 99 window_.reset(new aura::Window(&delegate_)); 100 window_->Init(aura::WINDOW_LAYER_NOT_DRAWN); 101 window_->set_owned_by_parent(false); 102 } 103 return window_.get(); 104 } 105 virtual content::BrowserContext* GetBrowserContext() OVERRIDE { return NULL; } 106 virtual ui::InputMethod* GetInputMethod() OVERRIDE { 107 return input_method_.get(); 108 } 109 virtual void RequestAudioInput(content::WebContents* web_contents, 110 const content::MediaStreamRequest& request, 111 const content::MediaResponseCallback& callback) OVERRIDE { return; } 112 virtual void LoadSystemKeyboard() OVERRIDE {}; 113 virtual void ReloadKeyboardIfNeeded() OVERRIDE {}; 114 115 private: 116 scoped_ptr<aura::Window> window_; 117 aura::test::TestWindowDelegate delegate_; 118 scoped_ptr<ui::InputMethod> input_method_; 119 120 DISALLOW_COPY_AND_ASSIGN(TestKeyboardControllerProxy); 121 }; 122 123 // Keeps a count of all the events a window receives. 124 class EventObserver : public ui::EventHandler { 125 public: 126 EventObserver() {} 127 virtual ~EventObserver() {} 128 129 int GetEventCount(ui::EventType type) { 130 return event_counts_[type]; 131 } 132 133 private: 134 // Overridden from ui::EventHandler: 135 virtual void OnEvent(ui::Event* event) OVERRIDE { 136 ui::EventHandler::OnEvent(event); 137 event_counts_[event->type()]++; 138 } 139 140 std::map<ui::EventType, int> event_counts_; 141 DISALLOW_COPY_AND_ASSIGN(EventObserver); 142 }; 143 144 class KeyboardContainerObserver : public aura::WindowObserver { 145 public: 146 explicit KeyboardContainerObserver(aura::Window* window) : window_(window) { 147 window_->AddObserver(this); 148 } 149 virtual ~KeyboardContainerObserver() { 150 window_->RemoveObserver(this); 151 } 152 153 private: 154 virtual void OnWindowVisibilityChanged(aura::Window* window, 155 bool visible) OVERRIDE { 156 if (!visible) 157 base::MessageLoop::current()->Quit(); 158 } 159 160 aura::Window* window_; 161 162 DISALLOW_COPY_AND_ASSIGN(KeyboardContainerObserver); 163 }; 164 165 } // namespace 166 167 class KeyboardControllerTest : public testing::Test { 168 public: 169 KeyboardControllerTest() {} 170 virtual ~KeyboardControllerTest() {} 171 172 virtual void SetUp() OVERRIDE { 173 // The ContextFactory must exist before any Compositors are created. 174 bool enable_pixel_output = false; 175 ui::ContextFactory* context_factory = 176 ui::InitializeContextFactoryForTests(enable_pixel_output); 177 178 aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_)); 179 aura_test_helper_->SetUp(context_factory); 180 new wm::DefaultActivationClient(aura_test_helper_->root_window()); 181 ui::SetUpInputMethodFactoryForTesting(); 182 if (::switches::IsTextInputFocusManagerEnabled()) 183 ui::TextInputFocusManager::GetInstance()->FocusTextInputClient(NULL); 184 focus_controller_.reset(new TestFocusController(root_window())); 185 proxy_ = new TestKeyboardControllerProxy(); 186 controller_.reset(new KeyboardController(proxy_)); 187 } 188 189 virtual void TearDown() OVERRIDE { 190 controller_.reset(); 191 focus_controller_.reset(); 192 if (::switches::IsTextInputFocusManagerEnabled()) 193 ui::TextInputFocusManager::GetInstance()->FocusTextInputClient(NULL); 194 aura_test_helper_->TearDown(); 195 ui::TerminateContextFactoryForTests(); 196 } 197 198 aura::Window* root_window() { return aura_test_helper_->root_window(); } 199 KeyboardControllerProxy* proxy() { return proxy_; } 200 KeyboardController* controller() { return controller_.get(); } 201 202 void ShowKeyboard() { 203 test_text_input_client_.reset( 204 new ui::DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT)); 205 SetFocus(test_text_input_client_.get()); 206 } 207 208 protected: 209 void SetFocus(ui::TextInputClient* client) { 210 ui::InputMethod* input_method = proxy()->GetInputMethod(); 211 if (::switches::IsTextInputFocusManagerEnabled()) { 212 ui::TextInputFocusManager::GetInstance()->FocusTextInputClient(client); 213 input_method->OnTextInputTypeChanged(client); 214 } else { 215 input_method->SetFocusedTextInputClient(client); 216 } 217 if (client && client->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE) { 218 input_method->ShowImeIfNeeded(); 219 if (proxy_->GetKeyboardWindow()->bounds().height() == 0) { 220 // Set initial bounds for test keyboard window. 221 proxy_->GetKeyboardWindow()->SetBounds( 222 KeyboardBoundsFromWindowBounds( 223 controller()->GetContainerWindow()->bounds(), 100)); 224 } 225 } 226 } 227 228 bool WillHideKeyboard() { 229 return controller_->WillHideKeyboard(); 230 } 231 232 base::MessageLoopForUI message_loop_; 233 scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_; 234 scoped_ptr<TestFocusController> focus_controller_; 235 236 private: 237 KeyboardControllerProxy* proxy_; 238 scoped_ptr<KeyboardController> controller_; 239 scoped_ptr<ui::TextInputClient> test_text_input_client_; 240 DISALLOW_COPY_AND_ASSIGN(KeyboardControllerTest); 241 }; 242 243 TEST_F(KeyboardControllerTest, KeyboardSize) { 244 aura::Window* container(controller()->GetContainerWindow()); 245 aura::Window* keyboard(proxy()->GetKeyboardWindow()); 246 container->SetBounds(gfx::Rect(0, 0, 200, 100)); 247 248 container->AddChild(keyboard); 249 const gfx::Rect& before_bounds = keyboard->bounds(); 250 // The initial keyboard should be positioned at the bottom of container and 251 // has 0 height. 252 ASSERT_EQ(gfx::Rect(0, 100, 200, 0), before_bounds); 253 254 gfx::Rect new_bounds( 255 before_bounds.x(), before_bounds.y() - 50, 256 before_bounds.width(), 50); 257 258 keyboard->SetBounds(new_bounds); 259 ASSERT_EQ(new_bounds, keyboard->bounds()); 260 261 // Mock a screen rotation. 262 container->SetBounds(gfx::Rect(0, 0, 100, 200)); 263 // The above call should resize keyboard to new width while keeping the old 264 // height. 265 ASSERT_EQ(gfx::Rect(0, 150, 100, 50), keyboard->bounds()); 266 } 267 268 // Tests that tapping/clicking inside the keyboard does not give it focus. 269 TEST_F(KeyboardControllerTest, ClickDoesNotFocusKeyboard) { 270 const gfx::Rect& root_bounds = root_window()->bounds(); 271 aura::test::EventCountDelegate delegate; 272 scoped_ptr<aura::Window> window(new aura::Window(&delegate)); 273 window->Init(aura::WINDOW_LAYER_NOT_DRAWN); 274 window->SetBounds(root_bounds); 275 root_window()->AddChild(window.get()); 276 window->Show(); 277 window->Focus(); 278 279 aura::Window* keyboard_container(controller()->GetContainerWindow()); 280 keyboard_container->SetBounds(root_bounds); 281 282 root_window()->AddChild(keyboard_container); 283 keyboard_container->Show(); 284 285 ShowKeyboard(); 286 287 EXPECT_TRUE(window->IsVisible()); 288 EXPECT_TRUE(keyboard_container->IsVisible()); 289 EXPECT_TRUE(window->HasFocus()); 290 EXPECT_FALSE(keyboard_container->HasFocus()); 291 292 // Click on the keyboard. Make sure the keyboard receives the event, but does 293 // not get focus. 294 EventObserver observer; 295 keyboard_container->AddPreTargetHandler(&observer); 296 297 aura::test::EventGenerator generator(root_window()); 298 generator.MoveMouseTo(proxy()->GetKeyboardWindow()->bounds().CenterPoint()); 299 generator.ClickLeftButton(); 300 EXPECT_TRUE(window->HasFocus()); 301 EXPECT_FALSE(keyboard_container->HasFocus()); 302 EXPECT_EQ("0 0", delegate.GetMouseButtonCountsAndReset()); 303 EXPECT_EQ(1, observer.GetEventCount(ui::ET_MOUSE_PRESSED)); 304 EXPECT_EQ(1, observer.GetEventCount(ui::ET_MOUSE_RELEASED)); 305 306 // Click outside of the keyboard. It should reach the window behind. 307 generator.MoveMouseTo(gfx::Point()); 308 generator.ClickLeftButton(); 309 EXPECT_EQ("1 1", delegate.GetMouseButtonCountsAndReset()); 310 keyboard_container->RemovePreTargetHandler(&observer); 311 } 312 313 TEST_F(KeyboardControllerTest, EventHitTestingInContainer) { 314 const gfx::Rect& root_bounds = root_window()->bounds(); 315 aura::test::EventCountDelegate delegate; 316 scoped_ptr<aura::Window> window(new aura::Window(&delegate)); 317 window->Init(aura::WINDOW_LAYER_NOT_DRAWN); 318 window->SetBounds(root_bounds); 319 root_window()->AddChild(window.get()); 320 window->Show(); 321 window->Focus(); 322 323 aura::Window* keyboard_container(controller()->GetContainerWindow()); 324 keyboard_container->SetBounds(root_bounds); 325 326 root_window()->AddChild(keyboard_container); 327 keyboard_container->Show(); 328 329 ShowKeyboard(); 330 331 EXPECT_TRUE(window->IsVisible()); 332 EXPECT_TRUE(keyboard_container->IsVisible()); 333 EXPECT_TRUE(window->HasFocus()); 334 EXPECT_FALSE(keyboard_container->HasFocus()); 335 336 // Make sure hit testing works correctly while the keyboard is visible. 337 aura::Window* keyboard_window = proxy()->GetKeyboardWindow(); 338 ui::EventTarget* root = root_window(); 339 ui::EventTargeter* targeter = root->GetEventTargeter(); 340 gfx::Point location = keyboard_window->bounds().CenterPoint(); 341 ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, location, location, ui::EF_NONE, 342 ui::EF_NONE); 343 EXPECT_EQ(keyboard_window, targeter->FindTargetForEvent(root, &mouse1)); 344 345 location.set_y(keyboard_window->bounds().y() - 5); 346 ui::MouseEvent mouse2(ui::ET_MOUSE_MOVED, location, location, ui::EF_NONE, 347 ui::EF_NONE); 348 EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root, &mouse2)); 349 } 350 351 TEST_F(KeyboardControllerTest, KeyboardWindowCreation) { 352 const gfx::Rect& root_bounds = root_window()->bounds(); 353 aura::test::EventCountDelegate delegate; 354 scoped_ptr<aura::Window> window(new aura::Window(&delegate)); 355 window->Init(aura::WINDOW_LAYER_NOT_DRAWN); 356 window->SetBounds(root_bounds); 357 root_window()->AddChild(window.get()); 358 window->Show(); 359 window->Focus(); 360 361 aura::Window* keyboard_container(controller()->GetContainerWindow()); 362 keyboard_container->SetBounds(root_bounds); 363 364 root_window()->AddChild(keyboard_container); 365 keyboard_container->Show(); 366 367 EXPECT_FALSE(proxy()->HasKeyboardWindow()); 368 369 ui::EventTarget* root = root_window(); 370 ui::EventTargeter* targeter = root->GetEventTargeter(); 371 gfx::Point location(root_window()->bounds().width() / 2, 372 root_window()->bounds().height() - 10); 373 ui::MouseEvent mouse( 374 ui::ET_MOUSE_MOVED, location, location, ui::EF_NONE, ui::EF_NONE); 375 EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root, &mouse)); 376 EXPECT_FALSE(proxy()->HasKeyboardWindow()); 377 378 EXPECT_EQ( 379 controller()->GetContainerWindow(), 380 controller()->GetContainerWindow()->GetEventHandlerForPoint(location)); 381 EXPECT_FALSE(proxy()->HasKeyboardWindow()); 382 } 383 384 TEST_F(KeyboardControllerTest, VisibilityChangeWithTextInputTypeChange) { 385 const gfx::Rect& root_bounds = root_window()->bounds(); 386 387 ui::DummyTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT); 388 ui::DummyTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT); 389 ui::DummyTextInputClient input_client_2(ui::TEXT_INPUT_TYPE_TEXT); 390 ui::DummyTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE); 391 ui::DummyTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE); 392 393 aura::Window* keyboard_container(controller()->GetContainerWindow()); 394 scoped_ptr<KeyboardContainerObserver> keyboard_container_observer( 395 new KeyboardContainerObserver(keyboard_container)); 396 keyboard_container->SetBounds(root_bounds); 397 root_window()->AddChild(keyboard_container); 398 399 SetFocus(&input_client_0); 400 401 EXPECT_TRUE(keyboard_container->IsVisible()); 402 403 SetFocus(&no_input_client_0); 404 // Keyboard should not immediately hide itself. It is delayed to avoid layout 405 // flicker when the focus of input field quickly change. 406 EXPECT_TRUE(keyboard_container->IsVisible()); 407 EXPECT_TRUE(WillHideKeyboard()); 408 // Wait for hide keyboard to finish. 409 base::MessageLoop::current()->Run(); 410 EXPECT_FALSE(keyboard_container->IsVisible()); 411 412 SetFocus(&input_client_1); 413 EXPECT_TRUE(keyboard_container->IsVisible()); 414 415 // Schedule to hide keyboard. 416 SetFocus(&no_input_client_1); 417 EXPECT_TRUE(WillHideKeyboard()); 418 // Cancel keyboard hide. 419 SetFocus(&input_client_2); 420 421 EXPECT_FALSE(WillHideKeyboard()); 422 EXPECT_TRUE(keyboard_container->IsVisible()); 423 } 424 425 TEST_F(KeyboardControllerTest, AlwaysVisibleWhenLocked) { 426 const gfx::Rect& root_bounds = root_window()->bounds(); 427 428 ui::DummyTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT); 429 ui::DummyTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT); 430 ui::DummyTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE); 431 ui::DummyTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE); 432 433 aura::Window* keyboard_container(controller()->GetContainerWindow()); 434 scoped_ptr<KeyboardContainerObserver> keyboard_container_observer( 435 new KeyboardContainerObserver(keyboard_container)); 436 keyboard_container->SetBounds(root_bounds); 437 root_window()->AddChild(keyboard_container); 438 439 SetFocus(&input_client_0); 440 441 EXPECT_TRUE(keyboard_container->IsVisible()); 442 443 // Lock keyboard. 444 controller()->set_lock_keyboard(true); 445 446 SetFocus(&no_input_client_0); 447 // Keyboard should not try to hide itself as it is locked. 448 EXPECT_TRUE(keyboard_container->IsVisible()); 449 EXPECT_FALSE(WillHideKeyboard()); 450 451 SetFocus(&input_client_1); 452 EXPECT_TRUE(keyboard_container->IsVisible()); 453 454 // Unlock keyboard. 455 controller()->set_lock_keyboard(false); 456 457 // Keyboard should hide when focus on no input client. 458 SetFocus(&no_input_client_1); 459 EXPECT_TRUE(WillHideKeyboard()); 460 461 // Wait for hide keyboard to finish. 462 base::MessageLoop::current()->Run(); 463 EXPECT_FALSE(keyboard_container->IsVisible()); 464 } 465 466 class KeyboardControllerAnimationTest : public KeyboardControllerTest, 467 public KeyboardControllerObserver { 468 public: 469 KeyboardControllerAnimationTest() {} 470 virtual ~KeyboardControllerAnimationTest() {} 471 472 virtual void SetUp() OVERRIDE { 473 // We cannot short-circuit animations for this test. 474 ui::ScopedAnimationDurationScaleMode normal_duration_mode( 475 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); 476 477 KeyboardControllerTest::SetUp(); 478 479 const gfx::Rect& root_bounds = root_window()->bounds(); 480 keyboard_container()->SetBounds(root_bounds); 481 root_window()->AddChild(keyboard_container()); 482 controller()->AddObserver(this); 483 } 484 485 virtual void TearDown() OVERRIDE { 486 controller()->RemoveObserver(this); 487 KeyboardControllerTest::TearDown(); 488 } 489 490 protected: 491 // KeyboardControllerObserver overrides 492 virtual void OnKeyboardBoundsChanging(const gfx::Rect& new_bounds) OVERRIDE { 493 notified_bounds_ = new_bounds; 494 } 495 496 const gfx::Rect& notified_bounds() { return notified_bounds_; } 497 498 aura::Window* keyboard_container() { 499 return controller()->GetContainerWindow(); 500 } 501 502 aura::Window* keyboard_window() { 503 return proxy()->GetKeyboardWindow(); 504 } 505 506 private: 507 gfx::Rect notified_bounds_; 508 509 DISALLOW_COPY_AND_ASSIGN(KeyboardControllerAnimationTest); 510 }; 511 512 // Tests virtual keyboard has correct show and hide animation. 513 TEST_F(KeyboardControllerAnimationTest, ContainerAnimation) { 514 ui::Layer* layer = keyboard_container()->layer(); 515 ShowKeyboard(); 516 517 // Keyboard container and window should immediately become visible before 518 // animation starts. 519 EXPECT_TRUE(keyboard_container()->IsVisible()); 520 EXPECT_TRUE(keyboard_window()->IsVisible()); 521 float show_start_opacity = layer->opacity(); 522 gfx::Transform transform; 523 transform.Translate(0, keyboard_window()->bounds().height()); 524 EXPECT_EQ(transform, layer->transform()); 525 EXPECT_EQ(gfx::Rect(), notified_bounds()); 526 527 RunAnimationForLayer(layer); 528 EXPECT_TRUE(keyboard_container()->IsVisible()); 529 EXPECT_TRUE(keyboard_window()->IsVisible()); 530 float show_end_opacity = layer->opacity(); 531 EXPECT_LT(show_start_opacity, show_end_opacity); 532 EXPECT_EQ(gfx::Transform(), layer->transform()); 533 // KeyboardController should notify the bounds of keyboard window to its 534 // observers after show animation finished. 535 EXPECT_EQ(keyboard_window()->bounds(), notified_bounds()); 536 537 // Directly hide keyboard without delay. 538 controller()->HideKeyboard(KeyboardController::HIDE_REASON_AUTOMATIC); 539 EXPECT_TRUE(keyboard_container()->IsVisible()); 540 EXPECT_TRUE(keyboard_container()->layer()->visible()); 541 EXPECT_TRUE(keyboard_window()->IsVisible()); 542 float hide_start_opacity = layer->opacity(); 543 // KeyboardController should notify the bounds of keyboard window to its 544 // observers before hide animation starts. 545 EXPECT_EQ(gfx::Rect(), notified_bounds()); 546 547 RunAnimationForLayer(layer); 548 EXPECT_FALSE(keyboard_container()->IsVisible()); 549 EXPECT_FALSE(keyboard_container()->layer()->visible()); 550 EXPECT_FALSE(keyboard_window()->IsVisible()); 551 float hide_end_opacity = layer->opacity(); 552 EXPECT_GT(hide_start_opacity, hide_end_opacity); 553 EXPECT_EQ(transform, layer->transform()); 554 EXPECT_EQ(gfx::Rect(), notified_bounds()); 555 } 556 557 // Show keyboard during keyboard hide animation should abort the hide animation 558 // and the keyboard should animate in. 559 // Test for crbug.com/333284. 560 TEST_F(KeyboardControllerAnimationTest, ContainerShowWhileHide) { 561 ui::Layer* layer = keyboard_container()->layer(); 562 ShowKeyboard(); 563 RunAnimationForLayer(layer); 564 565 controller()->HideKeyboard(KeyboardController::HIDE_REASON_AUTOMATIC); 566 // Before hide animation finishes, show keyboard again. 567 ShowKeyboard(); 568 RunAnimationForLayer(layer); 569 EXPECT_TRUE(keyboard_container()->IsVisible()); 570 EXPECT_TRUE(keyboard_window()->IsVisible()); 571 EXPECT_EQ(1.0, layer->opacity()); 572 EXPECT_EQ(gfx::Transform(), layer->transform()); 573 } 574 575 class KeyboardControllerUsabilityTest : public KeyboardControllerTest { 576 public: 577 KeyboardControllerUsabilityTest() {} 578 virtual ~KeyboardControllerUsabilityTest() {} 579 580 virtual void SetUp() OVERRIDE { 581 CommandLine::ForCurrentProcess()->AppendSwitch( 582 switches::kKeyboardUsabilityExperiment); 583 KeyboardControllerTest::SetUp(); 584 } 585 586 private: 587 DISALLOW_COPY_AND_ASSIGN(KeyboardControllerUsabilityTest); 588 }; 589 590 TEST_F(KeyboardControllerUsabilityTest, KeyboardAlwaysVisibleInUsabilityTest) { 591 const gfx::Rect& root_bounds = root_window()->bounds(); 592 593 ui::DummyTextInputClient input_client(ui::TEXT_INPUT_TYPE_TEXT); 594 ui::DummyTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE); 595 596 aura::Window* keyboard_container(controller()->GetContainerWindow()); 597 keyboard_container->SetBounds(root_bounds); 598 root_window()->AddChild(keyboard_container); 599 600 SetFocus(&input_client); 601 EXPECT_TRUE(keyboard_container->IsVisible()); 602 603 SetFocus(&no_input_client); 604 // Keyboard should not hide itself after lost focus. 605 EXPECT_TRUE(keyboard_container->IsVisible()); 606 EXPECT_FALSE(WillHideKeyboard()); 607 } 608 609 } // namespace keyboard 610