| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/keyboard/keyboard_controller.h" | 5 #include "ui/keyboard/keyboard_controller.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
| 13 #include "base/run_loop.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
| 14 #include "ui/aura/client/focus_client.h" | 15 #include "ui/aura/client/focus_client.h" |
| 15 #include "ui/aura/layout_manager.h" | 16 #include "ui/aura/layout_manager.h" |
| 16 #include "ui/aura/test/aura_test_helper.h" | 17 #include "ui/aura/test/aura_test_helper.h" |
| 17 #include "ui/aura/test/test_window_delegate.h" | 18 #include "ui/aura/test/test_window_delegate.h" |
| 18 #include "ui/aura/window.h" | 19 #include "ui/aura/window.h" |
| 19 #include "ui/aura/window_event_dispatcher.h" | 20 #include "ui/aura/window_event_dispatcher.h" |
| 20 #include "ui/base/ime/dummy_text_input_client.h" | 21 #include "ui/base/ime/dummy_text_input_client.h" |
| 21 #include "ui/base/ime/input_method.h" | 22 #include "ui/base/ime/input_method.h" |
| 22 #include "ui/base/ime/input_method_factory.h" | 23 #include "ui/base/ime/input_method_factory.h" |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 ui::EventHandler::OnEvent(event); | 140 ui::EventHandler::OnEvent(event); |
| 140 event_counts_[event->type()]++; | 141 event_counts_[event->type()]++; |
| 141 } | 142 } |
| 142 | 143 |
| 143 std::map<ui::EventType, int> event_counts_; | 144 std::map<ui::EventType, int> event_counts_; |
| 144 DISALLOW_COPY_AND_ASSIGN(EventObserver); | 145 DISALLOW_COPY_AND_ASSIGN(EventObserver); |
| 145 }; | 146 }; |
| 146 | 147 |
| 147 class KeyboardContainerObserver : public aura::WindowObserver { | 148 class KeyboardContainerObserver : public aura::WindowObserver { |
| 148 public: | 149 public: |
| 149 explicit KeyboardContainerObserver(aura::Window* window) : window_(window) { | 150 explicit KeyboardContainerObserver(aura::Window* window, |
| 151 base::RunLoop* run_loop) |
| 152 : window_(window), run_loop_(run_loop) { |
| 150 window_->AddObserver(this); | 153 window_->AddObserver(this); |
| 151 } | 154 } |
| 152 ~KeyboardContainerObserver() override { window_->RemoveObserver(this); } | 155 ~KeyboardContainerObserver() override { window_->RemoveObserver(this); } |
| 153 | 156 |
| 154 private: | 157 private: |
| 155 void OnWindowVisibilityChanged(aura::Window* window, bool visible) override { | 158 void OnWindowVisibilityChanged(aura::Window* window, bool visible) override { |
| 156 if (!visible) | 159 if (!visible) |
| 157 base::MessageLoop::current()->QuitWhenIdle(); | 160 run_loop_->QuitWhenIdle(); |
| 158 } | 161 } |
| 159 | 162 |
| 160 aura::Window* window_; | 163 aura::Window* window_; |
| 164 base::RunLoop* const run_loop_; |
| 161 | 165 |
| 162 DISALLOW_COPY_AND_ASSIGN(KeyboardContainerObserver); | 166 DISALLOW_COPY_AND_ASSIGN(KeyboardContainerObserver); |
| 163 }; | 167 }; |
| 164 | 168 |
| 165 } // namespace | 169 } // namespace |
| 166 | 170 |
| 167 class KeyboardControllerTest : public testing::Test, | 171 class KeyboardControllerTest : public testing::Test, |
| 168 public KeyboardControllerObserver { | 172 public KeyboardControllerObserver { |
| 169 public: | 173 public: |
| 170 KeyboardControllerTest() : number_of_calls_(0), ui_(nullptr) {} | 174 KeyboardControllerTest() : number_of_calls_(0), ui_(nullptr) {} |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 } | 361 } |
| 358 | 362 |
| 359 TEST_F(KeyboardControllerTest, VisibilityChangeWithTextInputTypeChange) { | 363 TEST_F(KeyboardControllerTest, VisibilityChangeWithTextInputTypeChange) { |
| 360 keyboard::SetAccessibilityKeyboardEnabled(true); | 364 keyboard::SetAccessibilityKeyboardEnabled(true); |
| 361 ui::DummyTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT); | 365 ui::DummyTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT); |
| 362 ui::DummyTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT); | 366 ui::DummyTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT); |
| 363 ui::DummyTextInputClient input_client_2(ui::TEXT_INPUT_TYPE_TEXT); | 367 ui::DummyTextInputClient input_client_2(ui::TEXT_INPUT_TYPE_TEXT); |
| 364 ui::DummyTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE); | 368 ui::DummyTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE); |
| 365 ui::DummyTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE); | 369 ui::DummyTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE); |
| 366 | 370 |
| 371 base::RunLoop run_loop; |
| 367 aura::Window* keyboard_container(controller()->GetContainerWindow()); | 372 aura::Window* keyboard_container(controller()->GetContainerWindow()); |
| 368 std::unique_ptr<KeyboardContainerObserver> keyboard_container_observer( | 373 std::unique_ptr<KeyboardContainerObserver> keyboard_container_observer( |
| 369 new KeyboardContainerObserver(keyboard_container)); | 374 new KeyboardContainerObserver(keyboard_container, &run_loop)); |
| 370 root_window()->AddChild(keyboard_container); | 375 root_window()->AddChild(keyboard_container); |
| 371 | 376 |
| 372 SetFocus(&input_client_0); | 377 SetFocus(&input_client_0); |
| 373 | 378 |
| 374 EXPECT_TRUE(keyboard_container->IsVisible()); | 379 EXPECT_TRUE(keyboard_container->IsVisible()); |
| 375 | 380 |
| 376 SetFocus(&no_input_client_0); | 381 SetFocus(&no_input_client_0); |
| 377 // Keyboard should not immediately hide itself. It is delayed to avoid layout | 382 // Keyboard should not immediately hide itself. It is delayed to avoid layout |
| 378 // flicker when the focus of input field quickly change. | 383 // flicker when the focus of input field quickly change. |
| 379 EXPECT_TRUE(keyboard_container->IsVisible()); | 384 EXPECT_TRUE(keyboard_container->IsVisible()); |
| 380 EXPECT_TRUE(WillHideKeyboard()); | 385 EXPECT_TRUE(WillHideKeyboard()); |
| 381 // Wait for hide keyboard to finish. | 386 // Wait for hide keyboard to finish. |
| 382 base::MessageLoop::current()->Run(); | 387 run_loop.Run(); |
| 383 EXPECT_FALSE(keyboard_container->IsVisible()); | 388 EXPECT_FALSE(keyboard_container->IsVisible()); |
| 384 | 389 |
| 385 SetFocus(&input_client_1); | 390 SetFocus(&input_client_1); |
| 386 EXPECT_TRUE(keyboard_container->IsVisible()); | 391 EXPECT_TRUE(keyboard_container->IsVisible()); |
| 387 | 392 |
| 388 // Schedule to hide keyboard. | 393 // Schedule to hide keyboard. |
| 389 SetFocus(&no_input_client_1); | 394 SetFocus(&no_input_client_1); |
| 390 EXPECT_TRUE(WillHideKeyboard()); | 395 EXPECT_TRUE(WillHideKeyboard()); |
| 391 // Cancel keyboard hide. | 396 // Cancel keyboard hide. |
| 392 SetFocus(&input_client_2); | 397 SetFocus(&input_client_2); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 420 EXPECT_TRUE(ShouldEnableInsets(ui()->GetKeyboardWindow())); | 425 EXPECT_TRUE(ShouldEnableInsets(ui()->GetKeyboardWindow())); |
| 421 } | 426 } |
| 422 | 427 |
| 423 // Verify switch to FLOATING mode will reset the overscroll or resize and when | 428 // Verify switch to FLOATING mode will reset the overscroll or resize and when |
| 424 // in FLOATING mode, overscroll or resize wont be triggered. | 429 // in FLOATING mode, overscroll or resize wont be triggered. |
| 425 TEST_F(KeyboardControllerTest, FloatingKeyboardDontOverscrollOrResize) { | 430 TEST_F(KeyboardControllerTest, FloatingKeyboardDontOverscrollOrResize) { |
| 426 keyboard::SetAccessibilityKeyboardEnabled(true); | 431 keyboard::SetAccessibilityKeyboardEnabled(true); |
| 427 ui::DummyTextInputClient input_client(ui::TEXT_INPUT_TYPE_TEXT); | 432 ui::DummyTextInputClient input_client(ui::TEXT_INPUT_TYPE_TEXT); |
| 428 ui::DummyTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE); | 433 ui::DummyTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE); |
| 429 | 434 |
| 435 base::RunLoop run_loop; |
| 430 aura::Window* container(controller()->GetContainerWindow()); | 436 aura::Window* container(controller()->GetContainerWindow()); |
| 431 root_window()->AddChild(container); | 437 root_window()->AddChild(container); |
| 432 std::unique_ptr<KeyboardContainerObserver> keyboard_container_observer( | 438 std::unique_ptr<KeyboardContainerObserver> keyboard_container_observer( |
| 433 new KeyboardContainerObserver(container)); | 439 new KeyboardContainerObserver(container, &run_loop)); |
| 434 gfx::Rect screen_bounds = root_window()->bounds(); | 440 gfx::Rect screen_bounds = root_window()->bounds(); |
| 435 keyboard::SetTouchKeyboardEnabled(true); | 441 keyboard::SetTouchKeyboardEnabled(true); |
| 436 | 442 |
| 437 SetFocus(&input_client); | 443 SetFocus(&input_client); |
| 438 gfx::Rect expected_bounds( | 444 gfx::Rect expected_bounds( |
| 439 0, screen_bounds.height() - kDefaultVirtualKeyboardHeight, | 445 0, screen_bounds.height() - kDefaultVirtualKeyboardHeight, |
| 440 screen_bounds.width(), kDefaultVirtualKeyboardHeight); | 446 screen_bounds.width(), kDefaultVirtualKeyboardHeight); |
| 441 // Verify overscroll or resize is in effect. | 447 // Verify overscroll or resize is in effect. |
| 442 EXPECT_EQ(expected_bounds, notified_bounds()); | 448 EXPECT_EQ(expected_bounds, notified_bounds()); |
| 443 EXPECT_EQ(1, number_of_calls()); | 449 EXPECT_EQ(1, number_of_calls()); |
| 444 | 450 |
| 445 controller()->SetKeyboardMode(FLOATING); | 451 controller()->SetKeyboardMode(FLOATING); |
| 446 // Switch to FLOATING should clear overscroll or resize. | 452 // Switch to FLOATING should clear overscroll or resize. |
| 447 EXPECT_EQ(gfx::Rect(), notified_bounds()); | 453 EXPECT_EQ(gfx::Rect(), notified_bounds()); |
| 448 EXPECT_EQ(2, number_of_calls()); | 454 EXPECT_EQ(2, number_of_calls()); |
| 449 SetFocus(&no_input_client); | 455 SetFocus(&no_input_client); |
| 450 base::MessageLoop::current()->Run(); | 456 run_loop.Run(); |
| 451 EXPECT_EQ(gfx::Rect(), notified_bounds()); | 457 EXPECT_EQ(gfx::Rect(), notified_bounds()); |
| 452 EXPECT_EQ(3, number_of_calls()); | 458 EXPECT_EQ(3, number_of_calls()); |
| 453 SetFocus(&input_client); | 459 SetFocus(&input_client); |
| 454 // In FLOATING mode, no overscroll or resize should be triggered. | 460 // In FLOATING mode, no overscroll or resize should be triggered. |
| 455 EXPECT_EQ(3, number_of_calls()); | 461 EXPECT_EQ(3, number_of_calls()); |
| 456 EXPECT_EQ(gfx::Rect(), controller()->current_keyboard_bounds()); | 462 EXPECT_EQ(gfx::Rect(), controller()->current_keyboard_bounds()); |
| 457 keyboard::SetAccessibilityKeyboardEnabled(false); | 463 keyboard::SetAccessibilityKeyboardEnabled(false); |
| 458 } | 464 } |
| 459 | 465 |
| 460 // Verify switch to FULL_WIDTH mode will move virtual keyboard to the right | 466 // Verify switch to FULL_WIDTH mode will move virtual keyboard to the right |
| (...skipping 19 matching lines...) Expand all Loading... |
| 480 EXPECT_EQ(expected_bounds, controller()->current_keyboard_bounds()); | 486 EXPECT_EQ(expected_bounds, controller()->current_keyboard_bounds()); |
| 481 } | 487 } |
| 482 | 488 |
| 483 TEST_F(KeyboardControllerTest, AlwaysVisibleWhenLocked) { | 489 TEST_F(KeyboardControllerTest, AlwaysVisibleWhenLocked) { |
| 484 keyboard::SetAccessibilityKeyboardEnabled(true); | 490 keyboard::SetAccessibilityKeyboardEnabled(true); |
| 485 ui::DummyTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT); | 491 ui::DummyTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT); |
| 486 ui::DummyTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT); | 492 ui::DummyTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT); |
| 487 ui::DummyTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE); | 493 ui::DummyTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE); |
| 488 ui::DummyTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE); | 494 ui::DummyTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE); |
| 489 | 495 |
| 496 base::RunLoop run_loop; |
| 490 aura::Window* keyboard_container(controller()->GetContainerWindow()); | 497 aura::Window* keyboard_container(controller()->GetContainerWindow()); |
| 491 std::unique_ptr<KeyboardContainerObserver> keyboard_container_observer( | 498 std::unique_ptr<KeyboardContainerObserver> keyboard_container_observer( |
| 492 new KeyboardContainerObserver(keyboard_container)); | 499 new KeyboardContainerObserver(keyboard_container, &run_loop)); |
| 493 root_window()->AddChild(keyboard_container); | 500 root_window()->AddChild(keyboard_container); |
| 494 | 501 |
| 495 SetFocus(&input_client_0); | 502 SetFocus(&input_client_0); |
| 496 | 503 |
| 497 EXPECT_TRUE(keyboard_container->IsVisible()); | 504 EXPECT_TRUE(keyboard_container->IsVisible()); |
| 498 | 505 |
| 499 // Lock keyboard. | 506 // Lock keyboard. |
| 500 controller()->set_lock_keyboard(true); | 507 controller()->set_lock_keyboard(true); |
| 501 | 508 |
| 502 SetFocus(&no_input_client_0); | 509 SetFocus(&no_input_client_0); |
| 503 // Keyboard should not try to hide itself as it is locked. | 510 // Keyboard should not try to hide itself as it is locked. |
| 504 EXPECT_TRUE(keyboard_container->IsVisible()); | 511 EXPECT_TRUE(keyboard_container->IsVisible()); |
| 505 EXPECT_FALSE(WillHideKeyboard()); | 512 EXPECT_FALSE(WillHideKeyboard()); |
| 506 | 513 |
| 507 SetFocus(&input_client_1); | 514 SetFocus(&input_client_1); |
| 508 EXPECT_TRUE(keyboard_container->IsVisible()); | 515 EXPECT_TRUE(keyboard_container->IsVisible()); |
| 509 | 516 |
| 510 // Unlock keyboard. | 517 // Unlock keyboard. |
| 511 controller()->set_lock_keyboard(false); | 518 controller()->set_lock_keyboard(false); |
| 512 | 519 |
| 513 // Keyboard should hide when focus on no input client. | 520 // Keyboard should hide when focus on no input client. |
| 514 SetFocus(&no_input_client_1); | 521 SetFocus(&no_input_client_1); |
| 515 EXPECT_TRUE(WillHideKeyboard()); | 522 EXPECT_TRUE(WillHideKeyboard()); |
| 516 | 523 |
| 517 // Wait for hide keyboard to finish. | 524 // Wait for hide keyboard to finish. |
| 518 base::MessageLoop::current()->Run(); | 525 run_loop.Run(); |
| 519 EXPECT_FALSE(keyboard_container->IsVisible()); | 526 EXPECT_FALSE(keyboard_container->IsVisible()); |
| 520 keyboard::SetAccessibilityKeyboardEnabled(false); | 527 keyboard::SetAccessibilityKeyboardEnabled(false); |
| 521 } | 528 } |
| 522 | 529 |
| 523 class KeyboardControllerAnimationTest : public KeyboardControllerTest { | 530 class KeyboardControllerAnimationTest : public KeyboardControllerTest { |
| 524 public: | 531 public: |
| 525 KeyboardControllerAnimationTest() {} | 532 KeyboardControllerAnimationTest() {} |
| 526 ~KeyboardControllerAnimationTest() override {} | 533 ~KeyboardControllerAnimationTest() override {} |
| 527 | 534 |
| 528 void SetUp() override { | 535 void SetUp() override { |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 gfx::Rect new_bounds(0, 0, 1280, 800); | 658 gfx::Rect new_bounds(0, 0, 1280, 800); |
| 652 ASSERT_NE(new_bounds, root_window()->bounds()); | 659 ASSERT_NE(new_bounds, root_window()->bounds()); |
| 653 EXPECT_EQ(1, number_of_calls()); | 660 EXPECT_EQ(1, number_of_calls()); |
| 654 root_window()->SetBounds(new_bounds); | 661 root_window()->SetBounds(new_bounds); |
| 655 EXPECT_EQ(2, number_of_calls()); | 662 EXPECT_EQ(2, number_of_calls()); |
| 656 MockRotateScreen(); | 663 MockRotateScreen(); |
| 657 EXPECT_EQ(3, number_of_calls()); | 664 EXPECT_EQ(3, number_of_calls()); |
| 658 } | 665 } |
| 659 | 666 |
| 660 } // namespace keyboard | 667 } // namespace keyboard |
| OLD | NEW |