1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/keyboard/keyboard_controller.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/layout_manager.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/window.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/window_delegate.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/hit_test.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/ime/input_method.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/ime/text_input_client.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/ime/text_input_type.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/path.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/rect.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/skia_util.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/keyboard/keyboard_controller_observer.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/keyboard/keyboard_controller_proxy.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)gfx::Rect KeyboardBoundsFromWindowBounds(const gfx::Rect& window_bounds) {
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const float kKeyboardHeightRatio = 0.3f;
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return gfx::Rect(
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      window_bounds.x(),
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      window_bounds.y() + window_bounds.height() * (1 - kKeyboardHeightRatio),
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      window_bounds.width(),
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      window_bounds.height() * kKeyboardHeightRatio);
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The KeyboardWindowDelegate makes sure the keyboard-window does not get focus.
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This is necessary to make sure that the synthetic key-events reach the target
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// window.
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The delegate deletes itself when the window is destroyed.
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class KeyboardWindowDelegate : public aura::WindowDelegate {
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  KeyboardWindowDelegate() {}
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~KeyboardWindowDelegate() {}
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Overridden from aura::WindowDelegate:
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual gfx::Size GetMinimumSize() const OVERRIDE { return gfx::Size(); }
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual gfx::Size GetMaximumSize() const OVERRIDE { return gfx::Size(); }
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               const gfx::Rect& new_bounds) OVERRIDE {
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bounds_ = new_bounds;
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return gfx::kNullCursor;
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE {
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return HTNOWHERE;
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool ShouldDescendIntoChildForEventHandling(
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      aura::Window* child,
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const gfx::Point& location) OVERRIDE {
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool CanFocus() OVERRIDE { return false; }
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnCaptureLost() OVERRIDE {}
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {}
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {}
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnWindowDestroying() OVERRIDE {}
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnWindowDestroyed() OVERRIDE { delete this; }
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {}
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool HasHitTestMask() const OVERRIDE { return true; }
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Rect keyboard_bounds = KeyboardBoundsFromWindowBounds(bounds_);
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    mask->addRect(RectToSkRect(keyboard_bounds));
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE { return NULL; }
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Rect bounds_;
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(KeyboardWindowDelegate);
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace keyboard {
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// LayoutManager for the virtual keyboard container.  Manages a single window
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// (the virtual keyboard) and keeps it positioned at the bottom of the
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// owner window.
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class KeyboardLayoutManager : public aura::LayoutManager {
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  KeyboardLayoutManager(aura::Window* container)
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : container_(container), keyboard_(NULL) {
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK(container_);
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Overridden from aura::LayoutManager
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnWindowResized() OVERRIDE {
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!keyboard_)
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetChildBoundsDirect(keyboard_,
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         KeyboardBoundsFromWindowBounds(container_->bounds()));
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(!keyboard_);
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    keyboard_ = child;
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnChildWindowVisibilityChanged(aura::Window* child,
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              bool visible) OVERRIDE {}
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void SetChildBounds(aura::Window* child,
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              const gfx::Rect& requested_bounds) OVERRIDE {
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Drop these: the size should only be set in OnWindowResized.
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::Window* container_;
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::Window* keyboard_;
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(KeyboardLayoutManager);
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)KeyboardController::KeyboardController(KeyboardControllerProxy* proxy)
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : proxy_(proxy),
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      container_(NULL),
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      input_method_(NULL) {
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(proxy);
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  input_method_ = proxy_->GetInputMethod();
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  input_method_->AddObserver(this);
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)KeyboardController::~KeyboardController() {
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (container_)
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    container_->RemoveObserver(this);
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (input_method_)
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    input_method_->RemoveObserver(this);
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)aura::Window* KeyboardController::GetContainerWindow() {
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!container_) {
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    container_ = new aura::Window(new KeyboardWindowDelegate());
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    container_->SetName("KeyboardContainer");
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    container_->Init(ui::LAYER_NOT_DRAWN);
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    container_->AddObserver(this);
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    container_->SetLayoutManager(new KeyboardLayoutManager(container_));
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return container_;
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void KeyboardController::AddObserver(KeyboardControllerObserver* observer) {
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  observer_list_.AddObserver(observer);
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void KeyboardController::RemoveObserver(KeyboardControllerObserver* observer) {
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  observer_list_.RemoveObserver(observer);
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void KeyboardController::OnWindowHierarchyChanged(
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const HierarchyChangeParams& params) {
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (params.new_parent && params.target == container_)
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    OnTextInputStateChanged(proxy_->GetInputMethod()->GetTextInputClient());
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void KeyboardController::OnWindowDestroying(aura::Window* window) {
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(container_, window);
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  container_ = NULL;
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void KeyboardController::OnTextInputStateChanged(
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ui::TextInputClient* client) {
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!container_)
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool was_showing = container_->IsVisible();
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool should_show = was_showing;
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!client || client->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) {
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    should_show = false;
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (container_->children().empty()) {
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      aura::Window* keyboard = proxy_->GetKeyboardWindow();
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      keyboard->Show();
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      container_->AddChild(keyboard);
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      container_->layout_manager()->OnWindowResized();
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    container_->parent()->StackChildAtTop(container_);
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    should_show = true;
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (was_showing != should_show) {
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Rect new_bounds(
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        should_show ? container_->children()[0]->bounds() : gfx::Rect());
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FOR_EACH_OBSERVER(
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        KeyboardControllerObserver,
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        observer_list_,
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        OnKeyboardBoundsChanging(new_bounds));
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (should_show)
194b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      proxy_->ShowKeyboardContainer(container_);
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    else
196b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      proxy_->HideKeyboardContainer(container_);
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(bryeung): whenever the TextInputClient changes we need to notify the
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // keyboard (with the TextInputType) so that it can reset it's state (e.g.
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // abandon compositions in progress)
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void KeyboardController::OnInputMethodDestroyed(
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ui::InputMethod* input_method) {
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(input_method_, input_method);
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  input_method_ = NULL;
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace keyboard
211