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 "ui/aura/layout_manager.h" | 7 #include "ui/aura/layout_manager.h" |
8 #include "ui/aura/window.h" | 8 #include "ui/aura/window.h" |
9 #include "ui/aura/window_delegate.h" | 9 #include "ui/aura/window_delegate.h" |
10 #include "ui/base/hit_test.h" | 10 #include "ui/base/hit_test.h" |
11 #include "ui/base/ime/input_method.h" | 11 #include "ui/base/ime/input_method.h" |
12 #include "ui/base/ime/input_method_base.h" | |
13 #include "ui/base/ime/text_input_client.h" | 12 #include "ui/base/ime/text_input_client.h" |
14 #include "ui/base/ime/text_input_type.h" | 13 #include "ui/base/ime/text_input_type.h" |
15 #include "ui/gfx/path.h" | 14 #include "ui/gfx/path.h" |
16 #include "ui/gfx/rect.h" | 15 #include "ui/gfx/rect.h" |
17 #include "ui/gfx/skia_util.h" | 16 #include "ui/gfx/skia_util.h" |
18 #include "ui/keyboard/keyboard_controller_proxy.h" | 17 #include "ui/keyboard/keyboard_controller_proxy.h" |
19 | 18 |
20 namespace { | 19 namespace { |
21 | 20 |
22 gfx::Rect KeyboardBoundsFromWindowBounds(const gfx::Rect& window_bounds) { | 21 gfx::Rect KeyboardBoundsFromWindowBounds(const gfx::Rect& window_bounds) { |
23 const float kKeyboardHeightRatio = 0.3f; | 22 const float kKeyboardHeightRatio = 0.3f; |
24 return gfx::Rect( | 23 return gfx::Rect( |
25 window_bounds.x(), | 24 window_bounds.x(), |
26 window_bounds.y() + window_bounds.height() * (1 - kKeyboardHeightRatio), | 25 window_bounds.y() + window_bounds.height() * (1 - kKeyboardHeightRatio), |
27 window_bounds.width(), | 26 window_bounds.width(), |
28 window_bounds.height() * kKeyboardHeightRatio); | 27 window_bounds.height() * kKeyboardHeightRatio); |
29 } | 28 } |
30 | 29 |
31 // LayoutManager for the virtual keyboard container. Manages a single window | |
32 // (the virtual keyboard) and keeps it positioned at the bottom of the | |
33 // container window. | |
34 class KeyboardLayoutManager : public aura::LayoutManager { | |
35 public: | |
36 KeyboardLayoutManager(aura::Window* owner, aura::Window* keyboard) | |
37 : owner_(owner), keyboard_(keyboard) {} | |
38 | |
39 // Overridden from aura::LayoutManager | |
40 virtual void OnWindowResized() OVERRIDE { | |
41 SetChildBoundsDirect(keyboard_, | |
42 KeyboardBoundsFromWindowBounds(owner_->bounds())); | |
43 } | |
44 virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE { | |
45 CHECK(child == keyboard_); | |
46 } | |
47 virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {} | |
48 virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {} | |
49 virtual void OnChildWindowVisibilityChanged(aura::Window* child, | |
50 bool visible) OVERRIDE {} | |
51 virtual void SetChildBounds(aura::Window* child, | |
52 const gfx::Rect& requested_bounds) OVERRIDE { | |
53 // Drop these: the size should only be set in OnWindowResized. | |
54 } | |
55 | |
56 private: | |
57 aura::Window* owner_; | |
58 aura::Window* keyboard_; | |
59 | |
60 DISALLOW_COPY_AND_ASSIGN(KeyboardLayoutManager); | |
61 }; | |
62 | |
63 // The KeyboardWindowDelegate makes sure the keyboard-window does not get focus. | 30 // The KeyboardWindowDelegate makes sure the keyboard-window does not get focus. |
64 // This is necessary to make sure that the synthetic key-events reach the target | 31 // This is necessary to make sure that the synthetic key-events reach the target |
65 // window. | 32 // window. |
66 // The delegate deletes itself when the window is destroyed. | 33 // The delegate deletes itself when the window is destroyed. |
67 class KeyboardWindowDelegate : public aura::WindowDelegate { | 34 class KeyboardWindowDelegate : public aura::WindowDelegate { |
68 public: | 35 public: |
69 KeyboardWindowDelegate() {} | 36 KeyboardWindowDelegate() {} |
70 virtual ~KeyboardWindowDelegate() {} | 37 virtual ~KeyboardWindowDelegate() {} |
71 | 38 |
72 private: | 39 private: |
(...skipping 30 matching lines...) Expand all Loading... |
103 virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE { return NULL; } | 70 virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE { return NULL; } |
104 | 71 |
105 gfx::Rect bounds_; | 72 gfx::Rect bounds_; |
106 DISALLOW_COPY_AND_ASSIGN(KeyboardWindowDelegate); | 73 DISALLOW_COPY_AND_ASSIGN(KeyboardWindowDelegate); |
107 }; | 74 }; |
108 | 75 |
109 } // namespace | 76 } // namespace |
110 | 77 |
111 namespace keyboard { | 78 namespace keyboard { |
112 | 79 |
| 80 // LayoutManager for the virtual keyboard container. Manages a single window |
| 81 // (the virtual keyboard) and keeps it positioned at the bottom of the |
| 82 // owner window. |
| 83 class KeyboardLayoutManager : public aura::LayoutManager { |
| 84 public: |
| 85 KeyboardLayoutManager(aura::Window* container) |
| 86 : container_(container), keyboard_(NULL) { |
| 87 CHECK(container_); |
| 88 } |
| 89 |
| 90 // Overridden from aura::LayoutManager |
| 91 virtual void OnWindowResized() OVERRIDE { |
| 92 if (!keyboard_) |
| 93 return; |
| 94 SetChildBoundsDirect(keyboard_, |
| 95 KeyboardBoundsFromWindowBounds(container_->bounds())); |
| 96 } |
| 97 virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE { |
| 98 DCHECK(!keyboard_); |
| 99 keyboard_ = child; |
| 100 } |
| 101 virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {} |
| 102 virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {} |
| 103 virtual void OnChildWindowVisibilityChanged(aura::Window* child, |
| 104 bool visible) OVERRIDE {} |
| 105 virtual void SetChildBounds(aura::Window* child, |
| 106 const gfx::Rect& requested_bounds) OVERRIDE { |
| 107 // Drop these: the size should only be set in OnWindowResized. |
| 108 } |
| 109 |
| 110 private: |
| 111 aura::Window* container_; |
| 112 aura::Window* keyboard_; |
| 113 |
| 114 DISALLOW_COPY_AND_ASSIGN(KeyboardLayoutManager); |
| 115 }; |
| 116 |
113 KeyboardController::KeyboardController(KeyboardControllerProxy* proxy) | 117 KeyboardController::KeyboardController(KeyboardControllerProxy* proxy) |
114 : proxy_(proxy), container_(NULL) { | 118 : proxy_(proxy), |
| 119 container_(NULL), |
| 120 input_method_(NULL) { |
115 CHECK(proxy); | 121 CHECK(proxy); |
116 proxy_->GetInputMethod()->AddObserver(this); | 122 input_method_ = proxy_->GetInputMethod(); |
| 123 input_method_->AddObserver(this); |
117 } | 124 } |
118 | 125 |
119 KeyboardController::~KeyboardController() { | 126 KeyboardController::~KeyboardController() { |
120 if (container_) | 127 if (container_) |
121 container_->RemoveObserver(this); | 128 container_->RemoveObserver(this); |
122 proxy_->GetInputMethod()->RemoveObserver(this); | 129 if (input_method_) |
| 130 input_method_->RemoveObserver(this); |
123 } | 131 } |
124 | 132 |
125 aura::Window* KeyboardController::GetContainerWindow() { | 133 aura::Window* KeyboardController::GetContainerWindow() { |
126 if (!container_) { | 134 if (!container_) { |
127 container_ = new aura::Window(new KeyboardWindowDelegate()); | 135 container_ = new aura::Window(new KeyboardWindowDelegate()); |
128 container_->SetName("KeyboardContainer"); | 136 container_->SetName("KeyboardContainer"); |
129 container_->Init(ui::LAYER_NOT_DRAWN); | 137 container_->Init(ui::LAYER_NOT_DRAWN); |
130 container_->AddObserver(this); | 138 container_->AddObserver(this); |
131 | 139 container_->SetLayoutManager(new KeyboardLayoutManager(container_)); |
132 aura::Window* keyboard = proxy_->GetKeyboardWindow(); | |
133 keyboard->Show(); | |
134 | |
135 container_->SetLayoutManager( | |
136 new KeyboardLayoutManager(container_, keyboard)); | |
137 container_->AddChild(keyboard); | |
138 } | 140 } |
139 return container_; | 141 return container_; |
140 } | 142 } |
141 | 143 |
| 144 void KeyboardController::OnWindowParentChanged(aura::Window* window, |
| 145 aura::Window* parent) { |
| 146 OnTextInputStateChanged(proxy_->GetInputMethod()->GetTextInputClient()); |
| 147 } |
| 148 |
| 149 void KeyboardController::OnWindowDestroying(aura::Window* window) { |
| 150 DCHECK_EQ(container_, window); |
| 151 container_ = NULL; |
| 152 } |
| 153 |
142 void KeyboardController::OnTextInputStateChanged( | 154 void KeyboardController::OnTextInputStateChanged( |
143 const ui::TextInputClient* client) { | 155 const ui::TextInputClient* client) { |
144 if (!container_) | 156 if (!container_) |
145 return; | 157 return; |
146 | 158 |
147 if (!client || client->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) { | 159 if (!client || client->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) { |
148 container_->Hide(); | 160 container_->Hide(); |
149 } else { | 161 } else { |
| 162 if (container_->children().empty()) { |
| 163 aura::Window* keyboard = proxy_->GetKeyboardWindow(); |
| 164 keyboard->Show(); |
| 165 container_->AddChild(keyboard); |
| 166 container_->layout_manager()->OnWindowResized(); |
| 167 } |
150 container_->parent()->StackChildAtTop(container_); | 168 container_->parent()->StackChildAtTop(container_); |
151 container_->Show(); | 169 container_->Show(); |
152 } | 170 } |
153 | |
154 // TODO(bryeung): whenever the TextInputClient changes we need to notify the | 171 // TODO(bryeung): whenever the TextInputClient changes we need to notify the |
155 // keyboard (with the TextInputType) so that it can reset it's state (e.g. | 172 // keyboard (with the TextInputType) so that it can reset it's state (e.g. |
156 // abandon compositions in progress) | 173 // abandon compositions in progress) |
157 } | 174 } |
158 | 175 |
159 void KeyboardController::OnWindowParentChanged(aura::Window* window, | 176 void KeyboardController::OnInputMethodDestroyed( |
160 aura::Window* parent) { | 177 const ui::InputMethod* input_method) { |
161 OnTextInputStateChanged(proxy_->GetInputMethod()->GetTextInputClient()); | 178 DCHECK_EQ(input_method_, input_method); |
162 } | 179 input_method_ = NULL; |
163 | |
164 void KeyboardController::OnWindowDestroying(aura::Window* window) { | |
165 DCHECK_EQ(container_, window); | |
166 container_ = NULL; | |
167 } | 180 } |
168 | 181 |
169 } // namespace keyboard | 182 } // namespace keyboard |
OLD | NEW |