| 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 "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "ui/aura/layout_manager.h" | 9 #include "ui/aura/layout_manager.h" |
| 10 #include "ui/aura/window.h" | 10 #include "ui/aura/window.h" |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 input_method_(NULL), | 171 input_method_(NULL), |
| 172 keyboard_visible_(false), | 172 keyboard_visible_(false), |
| 173 lock_keyboard_(false), | 173 lock_keyboard_(false), |
| 174 weak_factory_(this) { | 174 weak_factory_(this) { |
| 175 CHECK(proxy); | 175 CHECK(proxy); |
| 176 input_method_ = proxy_->GetInputMethod(); | 176 input_method_ = proxy_->GetInputMethod(); |
| 177 input_method_->AddObserver(this); | 177 input_method_->AddObserver(this); |
| 178 } | 178 } |
| 179 | 179 |
| 180 KeyboardController::~KeyboardController() { | 180 KeyboardController::~KeyboardController() { |
| 181 if (container_) { | 181 if (container_) |
| 182 container_->RemoveObserver(this); | 182 container_->RemoveObserver(this); |
| 183 // Remove the keyboard window from the children because the keyboard window | |
| 184 // is owned by proxy and it should be destroyed by proxy. | |
| 185 if (container_->Contains(proxy_->GetKeyboardWindow())) | |
| 186 container_->RemoveChild(proxy_->GetKeyboardWindow()); | |
| 187 } | |
| 188 if (input_method_) | 183 if (input_method_) |
| 189 input_method_->RemoveObserver(this); | 184 input_method_->RemoveObserver(this); |
| 190 } | 185 } |
| 191 | 186 |
| 192 aura::Window* KeyboardController::GetContainerWindow() { | 187 aura::Window* KeyboardController::GetContainerWindow() { |
| 193 if (!container_.get()) { | 188 if (!container_.get()) { |
| 194 container_.reset(new aura::Window( | 189 container_.reset(new aura::Window( |
| 195 new KeyboardWindowDelegate(proxy_.get()))); | 190 new KeyboardWindowDelegate(proxy_.get()))); |
| 196 container_->set_event_targeter(scoped_ptr<ui::EventTargeter>( | 191 container_->set_event_targeter(scoped_ptr<ui::EventTargeter>( |
| 197 new KeyboardContainerTargeter(container_.get(), proxy_.get()))); | 192 new KeyboardContainerTargeter(container_.get(), proxy_.get()))); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 | 237 |
| 243 void KeyboardController::SetOverrideContentUrl(const GURL& url) { | 238 void KeyboardController::SetOverrideContentUrl(const GURL& url) { |
| 244 proxy_->SetOverrideContentUrl(url); | 239 proxy_->SetOverrideContentUrl(url); |
| 245 } | 240 } |
| 246 | 241 |
| 247 void KeyboardController::OnTextInputStateChanged( | 242 void KeyboardController::OnTextInputStateChanged( |
| 248 const ui::TextInputClient* client) { | 243 const ui::TextInputClient* client) { |
| 249 if (!container_.get()) | 244 if (!container_.get()) |
| 250 return; | 245 return; |
| 251 | 246 |
| 252 bool was_showing = keyboard_visible_; | 247 if (IsKeyboardUsabilityExperimentEnabled()) { |
| 253 bool should_show = was_showing; | 248 OnShowImeIfNeeded(); |
| 249 return; |
| 250 } |
| 251 |
| 254 ui::TextInputType type = | 252 ui::TextInputType type = |
| 255 client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE; | 253 client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE; |
| 256 if (type == ui::TEXT_INPUT_TYPE_NONE && | 254 if (type == ui::TEXT_INPUT_TYPE_NONE && !lock_keyboard_) { |
| 257 !IsKeyboardUsabilityExperimentEnabled() && | 255 if (keyboard_visible_) { |
| 258 !lock_keyboard_) { | |
| 259 should_show = false; | |
| 260 } else { | |
| 261 if (container_->children().empty()) { | |
| 262 keyboard::MarkKeyboardLoadStarted(); | |
| 263 aura::Window* keyboard = proxy_->GetKeyboardWindow(); | |
| 264 keyboard->Show(); | |
| 265 container_->AddChild(keyboard); | |
| 266 } | |
| 267 if (type != ui::TEXT_INPUT_TYPE_NONE) | |
| 268 proxy_->SetUpdateInputType(type); | |
| 269 container_->parent()->StackChildAtTop(container_.get()); | |
| 270 should_show = true; | |
| 271 } | |
| 272 | |
| 273 if (was_showing != should_show) { | |
| 274 if (should_show) { | |
| 275 keyboard_visible_ = true; | |
| 276 | |
| 277 // If the controller is in the process of hiding the keyboard, do not log | |
| 278 // the stat here since the keyboard will not actually be shown. | |
| 279 if (!WillHideKeyboard()) | |
| 280 keyboard::LogKeyboardControlEvent(keyboard::KEYBOARD_CONTROL_SHOW); | |
| 281 | |
| 282 weak_factory_.InvalidateWeakPtrs(); | |
| 283 // If |container_| has hide animation, its visibility is set to false when | |
| 284 // hide animation finished. So even if the container is visible at this | |
| 285 // point, it may in the process of hiding. We still need to show keyboard | |
| 286 // container in this case. | |
| 287 if (container_->IsVisible() && | |
| 288 !container_->layer()->GetAnimator()->is_animating()) { | |
| 289 return; | |
| 290 } | |
| 291 | |
| 292 NotifyKeyboardBoundsChanging(container_->children()[0]->bounds()); | |
| 293 | |
| 294 proxy_->ShowKeyboardContainer(container_.get()); | |
| 295 } else { | |
| 296 // Set the visibility state here so that any queries for visibility | 256 // Set the visibility state here so that any queries for visibility |
| 297 // before the timer fires returns the correct future value. | 257 // before the timer fires returns the correct future value. |
| 298 keyboard_visible_ = false; | 258 keyboard_visible_ = false; |
| 299 base::MessageLoop::current()->PostDelayedTask( | 259 base::MessageLoop::current()->PostDelayedTask( |
| 300 FROM_HERE, | 260 FROM_HERE, |
| 301 base::Bind(&KeyboardController::HideKeyboard, | 261 base::Bind(&KeyboardController::HideKeyboard, |
| 302 weak_factory_.GetWeakPtr(), HIDE_REASON_AUTOMATIC), | 262 weak_factory_.GetWeakPtr(), HIDE_REASON_AUTOMATIC), |
| 303 base::TimeDelta::FromMilliseconds(kHideKeyboardDelayMs)); | 263 base::TimeDelta::FromMilliseconds(kHideKeyboardDelayMs)); |
| 304 } | 264 } |
| 265 } else { |
| 266 // Abort a pending keyboard hide. |
| 267 if (WillHideKeyboard()) { |
| 268 weak_factory_.InvalidateWeakPtrs(); |
| 269 keyboard_visible_ = true; |
| 270 } |
| 271 proxy_->SetUpdateInputType(type); |
| 272 // Do not explicitly show the Virtual keyboard unless it is in the process |
| 273 // of hiding. Instead, the virtual keyboard is shown in response to a user |
| 274 // gesture (mouse or touch) that is received while an element has input |
| 275 // focus. Showing the keyboard requires an explicit call to |
| 276 // OnShowImeIfNeeded. |
| 305 } | 277 } |
| 306 // TODO(bryeung): whenever the TextInputClient changes we need to notify the | 278 // TODO(bryeung): whenever the TextInputClient changes we need to notify the |
| 307 // keyboard (with the TextInputType) so that it can reset it's state (e.g. | 279 // keyboard (with the TextInputType) so that it can reset it's state (e.g. |
| 308 // abandon compositions in progress) | 280 // abandon compositions in progress) |
| 309 } | 281 } |
| 310 | 282 |
| 311 void KeyboardController::OnInputMethodDestroyed( | 283 void KeyboardController::OnInputMethodDestroyed( |
| 312 const ui::InputMethod* input_method) { | 284 const ui::InputMethod* input_method) { |
| 313 DCHECK_EQ(input_method_, input_method); | 285 DCHECK_EQ(input_method_, input_method); |
| 314 input_method_ = NULL; | 286 input_method_ = NULL; |
| 315 } | 287 } |
| 316 | 288 |
| 289 void KeyboardController::OnShowImeIfNeeded() { |
| 290 if (!container_.get()) |
| 291 return; |
| 292 |
| 293 if (container_->children().empty()) { |
| 294 keyboard::MarkKeyboardLoadStarted(); |
| 295 aura::Window* keyboard = proxy_->GetKeyboardWindow(); |
| 296 keyboard->Show(); |
| 297 container_->AddChild(keyboard); |
| 298 keyboard->set_owned_by_parent(false); |
| 299 } |
| 300 if (keyboard_visible_) |
| 301 return; |
| 302 |
| 303 keyboard_visible_ = true; |
| 304 |
| 305 // If the controller is in the process of hiding the keyboard, do not log |
| 306 // the stat here since the keyboard will not actually be shown. |
| 307 if (!WillHideKeyboard()) |
| 308 keyboard::LogKeyboardControlEvent(keyboard::KEYBOARD_CONTROL_SHOW); |
| 309 |
| 310 weak_factory_.InvalidateWeakPtrs(); |
| 311 |
| 312 // If |container_| has hide animation, its visibility is set to false when |
| 313 // hide animation finished. So even if the container is visible at this |
| 314 // point, it may in the process of hiding. We still need to show keyboard |
| 315 // container in this case. |
| 316 if (container_->IsVisible() && |
| 317 !container_->layer()->GetAnimator()->is_animating()) { |
| 318 return; |
| 319 } |
| 320 |
| 321 NotifyKeyboardBoundsChanging(container_->children()[0]->bounds()); |
| 322 |
| 323 proxy_->ShowKeyboardContainer(container_.get()); |
| 324 } |
| 325 |
| 317 bool KeyboardController::WillHideKeyboard() const { | 326 bool KeyboardController::WillHideKeyboard() const { |
| 318 return weak_factory_.HasWeakPtrs(); | 327 return weak_factory_.HasWeakPtrs(); |
| 319 } | 328 } |
| 320 | 329 |
| 321 } // namespace keyboard | 330 } // namespace keyboard |
| OLD | NEW |