Commit e0f71136 authored by bryeung@chromium.org's avatar bryeung@chromium.org

Delayed loading of the virtual keyboard.

Don't create the virtual keyboard until it is first shown.  This helps
prevent some start-up races.

Also clean-up some of the object ownership between KeyboardController
and KeyboardLayoutManager.  Each pointer exists in only one or the
other object now.

BUG=none

Review URL: https://codereview.chromium.org/13932030

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@194580 0039d316-1c4b-4281-b951-d872f2087c98
parent a8126e8c
...@@ -512,6 +512,7 @@ void RootWindowController::InitKeyboard() { ...@@ -512,6 +512,7 @@ void RootWindowController::InitKeyboard() {
aura::Window* keyboard_container = aura::Window* keyboard_container =
keyboard_controller_->GetContainerWindow(); keyboard_controller_->GetContainerWindow();
parent->AddChild(keyboard_container); parent->AddChild(keyboard_container);
keyboard_container->SetBounds(parent->bounds());
} }
} }
......
...@@ -78,6 +78,10 @@ void TextInputTestHelper::OnTextInputTypeChanged( ...@@ -78,6 +78,10 @@ void TextInputTestHelper::OnTextInputTypeChanged(
MessageLoop::current()->Quit(); MessageLoop::current()->Quit();
} }
void TextInputTestHelper::OnInputMethodDestroyed(
const ui::InputMethod* input_method) {
}
void TextInputTestHelper::OnFocus() { void TextInputTestHelper::OnFocus() {
focus_state_ = true; focus_state_ = true;
if (waiting_type_ == WAIT_ON_FOCUS) if (waiting_type_ == WAIT_ON_FOCUS)
......
...@@ -78,6 +78,8 @@ class TextInputTestHelper : public ui::MockInputMethod::Observer { ...@@ -78,6 +78,8 @@ class TextInputTestHelper : public ui::MockInputMethod::Observer {
virtual void OnCaretBoundsChanged(const ui::TextInputClient* client) OVERRIDE; virtual void OnCaretBoundsChanged(const ui::TextInputClient* client) OVERRIDE;
virtual void OnTextInputStateChanged( virtual void OnTextInputStateChanged(
const ui::TextInputClient* client) OVERRIDE; const ui::TextInputClient* client) OVERRIDE;
virtual void OnInputMethodDestroyed(
const ui::InputMethod* input_method) OVERRIDE;
// Represents waiting type of text input event. // Represents waiting type of text input event.
WaitImeEventType waiting_type_; WaitImeEventType waiting_type_;
......
...@@ -18,6 +18,9 @@ InputMethodBase::InputMethodBase() ...@@ -18,6 +18,9 @@ InputMethodBase::InputMethodBase()
} }
InputMethodBase::~InputMethodBase() { InputMethodBase::~InputMethodBase() {
FOR_EACH_OBSERVER(InputMethodObserver,
observer_list_,
OnInputMethodDestroyed(this));
} }
void InputMethodBase::SetDelegate(internal::InputMethodDelegate* delegate) { void InputMethodBase::SetDelegate(internal::InputMethodDelegate* delegate) {
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
namespace ui { namespace ui {
class InputMethod;
class TextInputClient; class TextInputClient;
class UI_EXPORT InputMethodObserver { class UI_EXPORT InputMethodObserver {
...@@ -19,6 +20,9 @@ class UI_EXPORT InputMethodObserver { ...@@ -19,6 +20,9 @@ class UI_EXPORT InputMethodObserver {
// - the TextInputClient is changed (e.g. by a change of focus) // - the TextInputClient is changed (e.g. by a change of focus)
// - the TextInputType of the TextInputClient changes // - the TextInputType of the TextInputClient changes
virtual void OnTextInputStateChanged(const TextInputClient* client) = 0; virtual void OnTextInputStateChanged(const TextInputClient* client) = 0;
// Called when the observed InputMethod is being destroyed.
virtual void OnInputMethodDestroyed(const InputMethod* input_method) = 0;
}; };
} // namespace ui } // namespace ui
......
...@@ -34,6 +34,7 @@ class UI_EXPORT MockInputMethod : NON_EXPORTED_BASE(public InputMethod) { ...@@ -34,6 +34,7 @@ class UI_EXPORT MockInputMethod : NON_EXPORTED_BASE(public InputMethod) {
// InputMethodObserver overrides // InputMethodObserver overrides
virtual void OnTextInputStateChanged(const TextInputClient* client) = 0; virtual void OnTextInputStateChanged(const TextInputClient* client) = 0;
virtual void OnInputMethodDestroyed(const InputMethod* input_method) = 0;
}; };
explicit MockInputMethod(internal::InputMethodDelegate* delegate); explicit MockInputMethod(internal::InputMethodDelegate* delegate);
virtual ~MockInputMethod(); virtual ~MockInputMethod();
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include "ui/aura/window_delegate.h" #include "ui/aura/window_delegate.h"
#include "ui/base/hit_test.h" #include "ui/base/hit_test.h"
#include "ui/base/ime/input_method.h" #include "ui/base/ime/input_method.h"
#include "ui/base/ime/input_method_base.h"
#include "ui/base/ime/text_input_client.h" #include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/text_input_type.h" #include "ui/base/ime/text_input_type.h"
#include "ui/gfx/path.h" #include "ui/gfx/path.h"
...@@ -28,38 +27,6 @@ gfx::Rect KeyboardBoundsFromWindowBounds(const gfx::Rect& window_bounds) { ...@@ -28,38 +27,6 @@ gfx::Rect KeyboardBoundsFromWindowBounds(const gfx::Rect& window_bounds) {
window_bounds.height() * kKeyboardHeightRatio); window_bounds.height() * kKeyboardHeightRatio);
} }
// LayoutManager for the virtual keyboard container. Manages a single window
// (the virtual keyboard) and keeps it positioned at the bottom of the
// container window.
class KeyboardLayoutManager : public aura::LayoutManager {
public:
KeyboardLayoutManager(aura::Window* owner, aura::Window* keyboard)
: owner_(owner), keyboard_(keyboard) {}
// Overridden from aura::LayoutManager
virtual void OnWindowResized() OVERRIDE {
SetChildBoundsDirect(keyboard_,
KeyboardBoundsFromWindowBounds(owner_->bounds()));
}
virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
CHECK(child == keyboard_);
}
virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
virtual void OnChildWindowVisibilityChanged(aura::Window* child,
bool visible) OVERRIDE {}
virtual void SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) OVERRIDE {
// Drop these: the size should only be set in OnWindowResized.
}
private:
aura::Window* owner_;
aura::Window* keyboard_;
DISALLOW_COPY_AND_ASSIGN(KeyboardLayoutManager);
};
// The KeyboardWindowDelegate makes sure the keyboard-window does not get focus. // The KeyboardWindowDelegate makes sure the keyboard-window does not get focus.
// This is necessary to make sure that the synthetic key-events reach the target // This is necessary to make sure that the synthetic key-events reach the target
// window. // window.
...@@ -110,16 +77,57 @@ class KeyboardWindowDelegate : public aura::WindowDelegate { ...@@ -110,16 +77,57 @@ class KeyboardWindowDelegate : public aura::WindowDelegate {
namespace keyboard { namespace keyboard {
// LayoutManager for the virtual keyboard container. Manages a single window
// (the virtual keyboard) and keeps it positioned at the bottom of the
// owner window.
class KeyboardLayoutManager : public aura::LayoutManager {
public:
KeyboardLayoutManager(aura::Window* container)
: container_(container), keyboard_(NULL) {
CHECK(container_);
}
// Overridden from aura::LayoutManager
virtual void OnWindowResized() OVERRIDE {
if (!keyboard_)
return;
SetChildBoundsDirect(keyboard_,
KeyboardBoundsFromWindowBounds(container_->bounds()));
}
virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
DCHECK(!keyboard_);
keyboard_ = child;
}
virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
virtual void OnChildWindowVisibilityChanged(aura::Window* child,
bool visible) OVERRIDE {}
virtual void SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) OVERRIDE {
// Drop these: the size should only be set in OnWindowResized.
}
private:
aura::Window* container_;
aura::Window* keyboard_;
DISALLOW_COPY_AND_ASSIGN(KeyboardLayoutManager);
};
KeyboardController::KeyboardController(KeyboardControllerProxy* proxy) KeyboardController::KeyboardController(KeyboardControllerProxy* proxy)
: proxy_(proxy), container_(NULL) { : proxy_(proxy),
container_(NULL),
input_method_(NULL) {
CHECK(proxy); CHECK(proxy);
proxy_->GetInputMethod()->AddObserver(this); input_method_ = proxy_->GetInputMethod();
input_method_->AddObserver(this);
} }
KeyboardController::~KeyboardController() { KeyboardController::~KeyboardController() {
if (container_) if (container_)
container_->RemoveObserver(this); container_->RemoveObserver(this);
proxy_->GetInputMethod()->RemoveObserver(this); if (input_method_)
input_method_->RemoveObserver(this);
} }
aura::Window* KeyboardController::GetContainerWindow() { aura::Window* KeyboardController::GetContainerWindow() {
...@@ -128,17 +136,21 @@ aura::Window* KeyboardController::GetContainerWindow() { ...@@ -128,17 +136,21 @@ aura::Window* KeyboardController::GetContainerWindow() {
container_->SetName("KeyboardContainer"); container_->SetName("KeyboardContainer");
container_->Init(ui::LAYER_NOT_DRAWN); container_->Init(ui::LAYER_NOT_DRAWN);
container_->AddObserver(this); container_->AddObserver(this);
container_->SetLayoutManager(new KeyboardLayoutManager(container_));
aura::Window* keyboard = proxy_->GetKeyboardWindow();
keyboard->Show();
container_->SetLayoutManager(
new KeyboardLayoutManager(container_, keyboard));
container_->AddChild(keyboard);
} }
return container_; return container_;
} }
void KeyboardController::OnWindowParentChanged(aura::Window* window,
aura::Window* parent) {
OnTextInputStateChanged(proxy_->GetInputMethod()->GetTextInputClient());
}
void KeyboardController::OnWindowDestroying(aura::Window* window) {
DCHECK_EQ(container_, window);
container_ = NULL;
}
void KeyboardController::OnTextInputStateChanged( void KeyboardController::OnTextInputStateChanged(
const ui::TextInputClient* client) { const ui::TextInputClient* client) {
if (!container_) if (!container_)
...@@ -147,23 +159,24 @@ void KeyboardController::OnTextInputStateChanged( ...@@ -147,23 +159,24 @@ void KeyboardController::OnTextInputStateChanged(
if (!client || client->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) { if (!client || client->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) {
container_->Hide(); container_->Hide();
} else { } else {
if (container_->children().empty()) {
aura::Window* keyboard = proxy_->GetKeyboardWindow();
keyboard->Show();
container_->AddChild(keyboard);
container_->layout_manager()->OnWindowResized();
}
container_->parent()->StackChildAtTop(container_); container_->parent()->StackChildAtTop(container_);
container_->Show(); container_->Show();
} }
// TODO(bryeung): whenever the TextInputClient changes we need to notify the // TODO(bryeung): whenever the TextInputClient changes we need to notify the
// keyboard (with the TextInputType) so that it can reset it's state (e.g. // keyboard (with the TextInputType) so that it can reset it's state (e.g.
// abandon compositions in progress) // abandon compositions in progress)
} }
void KeyboardController::OnWindowParentChanged(aura::Window* window, void KeyboardController::OnInputMethodDestroyed(
aura::Window* parent) { const ui::InputMethod* input_method) {
OnTextInputStateChanged(proxy_->GetInputMethod()->GetTextInputClient()); DCHECK_EQ(input_method_, input_method);
} input_method_ = NULL;
void KeyboardController::OnWindowDestroying(aura::Window* window) {
DCHECK_EQ(container_, window);
container_ = NULL;
} }
} // namespace keyboard } // namespace keyboard
...@@ -16,15 +16,17 @@ class Window; ...@@ -16,15 +16,17 @@ class Window;
} }
namespace ui { namespace ui {
class InputMethod;
class TextInputClient; class TextInputClient;
} }
namespace keyboard { namespace keyboard {
class KeyboardControllerProxy; class KeyboardControllerProxy;
class KeyboardLayoutManager;
// Provides control of the virtual keyboard, including providing a container, // Provides control of the virtual keyboard, including providing a container
// managing object lifetimes and controlling visibility. // and controlling visibility.
class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver, class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
public aura::WindowObserver { public aura::WindowObserver {
public: public:
...@@ -36,18 +38,24 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver, ...@@ -36,18 +38,24 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
// It is the responsibility of the caller to Show() the returned window. // It is the responsibility of the caller to Show() the returned window.
aura::Window* GetContainerWindow(); aura::Window* GetContainerWindow();
// InputMethodObserver overrides
virtual void OnTextInputStateChanged(
const ui::TextInputClient* client) OVERRIDE;
private: private:
// For access to Observer methods for simulation.
friend class KeyboardControllerTest;
// aura::WindowObserver overrides // aura::WindowObserver overrides
virtual void OnWindowParentChanged(aura::Window* window, virtual void OnWindowParentChanged(aura::Window* window,
aura::Window* parent) OVERRIDE; aura::Window* parent) OVERRIDE;
virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
// InputMethodObserver overrides
virtual void OnTextInputStateChanged(
const ui::TextInputClient* client) OVERRIDE;
virtual void OnInputMethodDestroyed(
const ui::InputMethod* input_method) OVERRIDE;
scoped_ptr<KeyboardControllerProxy> proxy_; scoped_ptr<KeyboardControllerProxy> proxy_;
aura::Window* container_; aura::Window* container_;
ui::InputMethod* input_method_;
DISALLOW_COPY_AND_ASSIGN(KeyboardController); DISALLOW_COPY_AND_ASSIGN(KeyboardController);
}; };
......
...@@ -49,33 +49,6 @@ class TestFocusController : public ui::EventHandler { ...@@ -49,33 +49,6 @@ class TestFocusController : public ui::EventHandler {
DISALLOW_COPY_AND_ASSIGN(TestFocusController); DISALLOW_COPY_AND_ASSIGN(TestFocusController);
}; };
class KeyboardControllerTest : public testing::Test {
public:
KeyboardControllerTest() {}
virtual ~KeyboardControllerTest() {}
virtual void SetUp() OVERRIDE {
aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
aura_test_helper_->SetUp();
ui::SetUpInputMethodFactoryForTesting();
focus_controller_.reset(new TestFocusController(root_window()));
}
virtual void TearDown() OVERRIDE {
aura_test_helper_->TearDown();
}
aura::RootWindow* root_window() { return aura_test_helper_->root_window(); }
protected:
base::MessageLoopForUI message_loop_;
scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
scoped_ptr<TestFocusController> focus_controller_;
private:
DISALLOW_COPY_AND_ASSIGN(KeyboardControllerTest);
};
class TestKeyboardControllerProxy : public KeyboardControllerProxy { class TestKeyboardControllerProxy : public KeyboardControllerProxy {
public: public:
TestKeyboardControllerProxy() TestKeyboardControllerProxy()
...@@ -176,6 +149,38 @@ class TestTextInputClient : public ui::TextInputClient { ...@@ -176,6 +149,38 @@ class TestTextInputClient : public ui::TextInputClient {
} // namespace } // namespace
class KeyboardControllerTest : public testing::Test {
public:
KeyboardControllerTest() {}
virtual ~KeyboardControllerTest() {}
virtual void SetUp() OVERRIDE {
aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
aura_test_helper_->SetUp();
ui::SetUpInputMethodFactoryForTesting();
focus_controller_.reset(new TestFocusController(root_window()));
}
virtual void TearDown() OVERRIDE {
aura_test_helper_->TearDown();
}
aura::RootWindow* root_window() { return aura_test_helper_->root_window(); }
void ShowKeyboard(KeyboardController* controller) {
TestTextInputClient test_text_input_client(ui::TEXT_INPUT_TYPE_TEXT);
controller->OnTextInputStateChanged(&test_text_input_client);
}
protected:
base::MessageLoopForUI message_loop_;
scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
scoped_ptr<TestFocusController> focus_controller_;
private:
DISALLOW_COPY_AND_ASSIGN(KeyboardControllerTest);
};
TEST_F(KeyboardControllerTest, KeyboardSize) { TEST_F(KeyboardControllerTest, KeyboardSize) {
KeyboardControllerProxy* proxy = new TestKeyboardControllerProxy(); KeyboardControllerProxy* proxy = new TestKeyboardControllerProxy();
KeyboardController controller(proxy); KeyboardController controller(proxy);
...@@ -214,7 +219,8 @@ TEST_F(KeyboardControllerTest, ClickDoesNotFocusKeyboard) { ...@@ -214,7 +219,8 @@ TEST_F(KeyboardControllerTest, ClickDoesNotFocusKeyboard) {
root_window()->AddChild(keyboard_container.get()); root_window()->AddChild(keyboard_container.get());
keyboard_container->Show(); keyboard_container->Show();
root_window()->StackChildAtTop(keyboard_container.get()); ShowKeyboard(&controller);
EXPECT_TRUE(window->IsVisible()); EXPECT_TRUE(window->IsVisible());
EXPECT_TRUE(keyboard_container->IsVisible()); EXPECT_TRUE(keyboard_container->IsVisible());
EXPECT_TRUE(window->HasFocus()); EXPECT_TRUE(window->HasFocus());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment