Chromium Code Reviews| 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* owner) : owner_(owner), keyboard_(NULL) { | |
| 86 CHECK(owner_); | |
| 87 } | |
| 88 | |
| 89 aura::Window* owner() { return owner_; } | |
| 90 | |
| 91 void AddKeyboard(aura::Window* keyboard) { | |
| 92 keyboard->Show(); | |
| 93 owner_->AddChild(keyboard); | |
| 94 OnWindowResized(); | |
| 95 } | |
| 96 | |
| 97 bool HasKeyboard() { return keyboard_ != NULL; } | |
| 98 | |
| 99 void ShowKeyboard() { | |
| 100 owner_->parent()->StackChildAtTop(owner_); | |
| 101 owner_->Show(); | |
| 102 } | |
| 103 | |
| 104 void HideKeyboard() { | |
| 105 owner_->Hide(); | |
| 106 } | |
| 107 | |
| 108 // Overridden from aura::LayoutManager | |
| 109 virtual void OnWindowResized() OVERRIDE { | |
| 110 if (!keyboard_) | |
| 111 return; | |
| 112 SetChildBoundsDirect(keyboard_, | |
| 113 KeyboardBoundsFromWindowBounds(owner_->bounds())); | |
| 114 } | |
| 115 virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE { | |
| 116 DCHECK(!keyboard_); | |
| 117 keyboard_ = child; | |
| 118 } | |
| 119 virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {} | |
| 120 virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {} | |
| 121 virtual void OnChildWindowVisibilityChanged(aura::Window* child, | |
| 122 bool visible) OVERRIDE {} | |
| 123 virtual void SetChildBounds(aura::Window* child, | |
| 124 const gfx::Rect& requested_bounds) OVERRIDE { | |
| 125 // Drop these: the size should only be set in OnWindowResized. | |
| 126 } | |
| 127 | |
| 128 private: | |
| 129 aura::Window* owner_; | |
| 130 aura::Window* keyboard_; | |
| 131 | |
| 132 DISALLOW_COPY_AND_ASSIGN(KeyboardLayoutManager); | |
| 133 }; | |
| 134 | |
| 113 KeyboardController::KeyboardController(KeyboardControllerProxy* proxy) | 135 KeyboardController::KeyboardController(KeyboardControllerProxy* proxy) |
| 114 : proxy_(proxy), container_(NULL) { | 136 : proxy_(proxy), layout_manager_(NULL), input_method_(NULL) { |
| 115 CHECK(proxy); | 137 CHECK(proxy); |
| 116 proxy_->GetInputMethod()->AddObserver(this); | 138 input_method_ = proxy_->GetInputMethod(); |
| 139 input_method_->AddObserver(this); | |
|
sadrul
2013/04/15 03:48:44
I don't think having |input_method_| is useful her
bryeung
2013/04/15 15:02:22
Fetching the InputMethod from the Window propertie
| |
| 117 } | 140 } |
| 118 | 141 |
| 119 KeyboardController::~KeyboardController() { | 142 KeyboardController::~KeyboardController() { |
| 120 if (container_) | 143 input_method_->RemoveObserver(this); |
| 121 container_->RemoveObserver(this); | |
| 122 proxy_->GetInputMethod()->RemoveObserver(this); | |
| 123 } | 144 } |
| 124 | 145 |
| 125 aura::Window* KeyboardController::GetContainerWindow() { | 146 aura::Window* KeyboardController::GetContainerWindow() { |
| 126 if (!container_) { | 147 if (!layout_manager_) { |
| 127 container_ = new aura::Window(new KeyboardWindowDelegate()); | 148 aura::Window* container = new aura::Window(new KeyboardWindowDelegate()); |
| 128 container_->SetName("KeyboardContainer"); | 149 container->SetName("KeyboardContainer"); |
| 129 container_->Init(ui::LAYER_NOT_DRAWN); | 150 container->Init(ui::LAYER_NOT_DRAWN); |
| 130 container_->AddObserver(this); | 151 container->AddObserver(this); |
| 131 | 152 |
| 132 aura::Window* keyboard = proxy_->GetKeyboardWindow(); | 153 layout_manager_ = new KeyboardLayoutManager(container); |
| 133 keyboard->Show(); | 154 container->SetLayoutManager(layout_manager_); |
| 134 | |
| 135 container_->SetLayoutManager( | |
| 136 new KeyboardLayoutManager(container_, keyboard)); | |
| 137 container_->AddChild(keyboard); | |
| 138 } | 155 } |
| 139 return container_; | 156 return layout_manager_->owner(); |
|
sadrul
2013/04/15 03:48:44
I think having the |container_| in the KC is easie
bryeung
2013/04/15 15:02:22
Okay. I didn't like having two different referenc
| |
| 140 } | 157 } |
| 141 | 158 |
| 142 void KeyboardController::OnTextInputStateChanged( | 159 void KeyboardController::OnTextInputStateChanged( |
| 143 const ui::TextInputClient* client) { | 160 const ui::TextInputClient* client) { |
| 144 if (!container_) | 161 if (!layout_manager_) |
| 145 return; | 162 return; |
| 146 | 163 |
| 147 if (!client || client->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) { | 164 if (!client || client->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) { |
| 148 container_->Hide(); | 165 layout_manager_->HideKeyboard(); |
| 149 } else { | 166 } else { |
| 150 container_->parent()->StackChildAtTop(container_); | 167 if (!layout_manager_->HasKeyboard()) |
|
sadrul
2013/04/15 03:48:44
Could you have just checked that container_->child
bryeung
2013/04/15 15:02:22
Done.
| |
| 151 container_->Show(); | 168 layout_manager_->AddKeyboard(proxy_->GetKeyboardWindow()); |
| 169 layout_manager_->ShowKeyboard(); | |
| 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::OnWindowParentChanged(aura::Window* window, |
| 160 aura::Window* parent) { | 177 aura::Window* parent) { |
| 161 OnTextInputStateChanged(proxy_->GetInputMethod()->GetTextInputClient()); | 178 OnTextInputStateChanged(proxy_->GetInputMethod()->GetTextInputClient()); |
| 162 } | 179 } |
| 163 | 180 |
| 164 void KeyboardController::OnWindowDestroying(aura::Window* window) { | 181 void KeyboardController::OnWindowDestroying(aura::Window* window) { |
| 165 DCHECK_EQ(container_, window); | 182 DCHECK(layout_manager_); |
| 166 container_ = NULL; | 183 DCHECK_EQ(layout_manager_->owner(), window); |
| 184 layout_manager_->owner()->RemoveObserver(this); | |
| 167 } | 185 } |
| 168 | 186 |
| 169 } // namespace keyboard | 187 } // namespace keyboard |
| OLD | NEW |