Limit display of the virtual keyboard to state changes triggered from a user gesture.
[chromium-blink-merge.git] / ui / views / ime / input_method_bridge.cc
blob5fc7fde3d77e7a0f36850ac2d3e1ad85b6e6c06c
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/views/ime/input_method_bridge.h"
7 #include "ui/base/ime/input_method.h"
8 #include "ui/base/ime/input_method_observer.h"
9 #include "ui/events/event.h"
10 #include "ui/gfx/rect.h"
11 #include "ui/views/view.h"
12 #include "ui/views/widget/widget.h"
14 namespace views {
16 // InputMethodBridge::HostObserver class ---------------------------------------
18 // An observer class for observing the host input method. When the host input
19 // method is destroyed, it will null out the |host_| field on the
20 // InputMethodBridge object.
21 class InputMethodBridge::HostObserver : public ui::InputMethodObserver {
22 public:
23 explicit HostObserver(InputMethodBridge* bridge);
24 virtual ~HostObserver();
26 virtual void OnTextInputTypeChanged(
27 const ui::TextInputClient* client) OVERRIDE {}
28 virtual void OnFocus() OVERRIDE {}
29 virtual void OnBlur() OVERRIDE {}
30 virtual void OnCaretBoundsChanged(
31 const ui::TextInputClient* client) OVERRIDE {}
32 virtual void OnTextInputStateChanged(
33 const ui::TextInputClient* client) OVERRIDE {}
34 virtual void OnInputMethodDestroyed(
35 const ui::InputMethod* input_method) OVERRIDE;
36 virtual void OnShowImeIfNeeded() OVERRIDE {}
38 private:
39 InputMethodBridge* bridge_;
41 DISALLOW_COPY_AND_ASSIGN(HostObserver);
44 InputMethodBridge::HostObserver::HostObserver(InputMethodBridge* bridge)
45 : bridge_(bridge) {
46 bridge_->host_->AddObserver(this);
49 InputMethodBridge::HostObserver::~HostObserver() {
50 if (bridge_->host_)
51 bridge_->host_->RemoveObserver(this);
54 void InputMethodBridge::HostObserver::OnInputMethodDestroyed(
55 const ui::InputMethod* input_method) {
56 DCHECK_EQ(bridge_->host_, input_method);
57 bridge_->host_->RemoveObserver(this);
58 bridge_->host_ = NULL;
61 // InputMethodBridge class -----------------------------------------------------
63 InputMethodBridge::InputMethodBridge(internal::InputMethodDelegate* delegate,
64 ui::InputMethod* host,
65 bool shared_input_method)
66 : host_(host),
67 shared_input_method_(shared_input_method) {
68 DCHECK(host_);
69 SetDelegate(delegate);
71 host_observer_.reset(new HostObserver(this));
74 InputMethodBridge::~InputMethodBridge() {
75 // By the time we get here it's very likely |widget_|'s NativeWidget has been
76 // destroyed. This means any calls to |widget_| that go to the NativeWidget,
77 // such as IsActive(), will crash. SetFocusedTextInputClient() may callback to
78 // this and go into |widget_|. NULL out |widget_| so we don't attempt to use
79 // it.
80 DetachFromWidget();
82 // Host input method might have been destroyed at this point.
83 if (host_)
84 host_->DetachTextInputClient(this);
87 void InputMethodBridge::OnFocus() {
88 DCHECK(host_);
90 // Direct the shared IME to send TextInputClient messages to |this| object.
91 if (shared_input_method_ || !host_->GetTextInputClient())
92 host_->SetFocusedTextInputClient(this);
94 // TODO(yusukes): We don't need to call OnTextInputTypeChanged() once we move
95 // text input type tracker code to ui::InputMethodBase.
96 if (GetFocusedView()) {
97 OnTextInputTypeChanged(GetFocusedView());
98 OnCaretBoundsChanged(GetFocusedView());
102 void InputMethodBridge::OnBlur() {
103 DCHECK(host_);
105 if (HasCompositionText()) {
106 ConfirmCompositionText();
107 host_->CancelComposition(this);
110 if (host_->GetTextInputClient() == this)
111 host_->SetFocusedTextInputClient(NULL);
114 bool InputMethodBridge::OnUntranslatedIMEMessage(const base::NativeEvent& event,
115 NativeEventResult* result) {
116 DCHECK(host_);
118 return host_->OnUntranslatedIMEMessage(event, result);
121 void InputMethodBridge::DispatchKeyEvent(const ui::KeyEvent& key) {
122 DCHECK(key.type() == ui::ET_KEY_PRESSED || key.type() == ui::ET_KEY_RELEASED);
124 // We can just dispatch the event here since the |key| is already processed by
125 // the system-wide IME.
126 DispatchKeyEventPostIME(key);
129 void InputMethodBridge::OnTextInputTypeChanged(View* view) {
130 DCHECK(host_);
132 if (IsViewFocused(view))
133 host_->OnTextInputTypeChanged(this);
134 InputMethodBase::OnTextInputTypeChanged(view);
137 void InputMethodBridge::OnCaretBoundsChanged(View* view) {
138 DCHECK(host_);
140 if (IsViewFocused(view) && !IsTextInputTypeNone())
141 host_->OnCaretBoundsChanged(this);
144 void InputMethodBridge::CancelComposition(View* view) {
145 DCHECK(host_);
147 if (IsViewFocused(view))
148 host_->CancelComposition(this);
151 void InputMethodBridge::OnInputLocaleChanged() {
152 DCHECK(host_);
154 host_->OnInputLocaleChanged();
157 std::string InputMethodBridge::GetInputLocale() {
158 DCHECK(host_);
160 return host_->GetInputLocale();
163 bool InputMethodBridge::IsActive() {
164 DCHECK(host_);
166 return host_->IsActive();
169 bool InputMethodBridge::IsCandidatePopupOpen() const {
170 DCHECK(host_);
172 return host_->IsCandidatePopupOpen();
175 void InputMethodBridge::ShowImeIfNeeded() {
176 DCHECK(host_);
177 host_->ShowImeIfNeeded();
180 // Overridden from TextInputClient. Forward an event from the system-wide IME
181 // to the text input |client|, which is e.g. views::Textfield.
182 void InputMethodBridge::SetCompositionText(
183 const ui::CompositionText& composition) {
184 TextInputClient* client = GetTextInputClient();
185 if (client)
186 client->SetCompositionText(composition);
189 void InputMethodBridge::ConfirmCompositionText() {
190 TextInputClient* client = GetTextInputClient();
191 if (client)
192 client->ConfirmCompositionText();
195 void InputMethodBridge::ClearCompositionText() {
196 TextInputClient* client = GetTextInputClient();
197 if (client)
198 client->ClearCompositionText();
201 void InputMethodBridge::InsertText(const base::string16& text) {
202 TextInputClient* client = GetTextInputClient();
203 if (client)
204 client->InsertText(text);
207 void InputMethodBridge::InsertChar(base::char16 ch, int flags) {
208 TextInputClient* client = GetTextInputClient();
209 if (client)
210 client->InsertChar(ch, flags);
213 gfx::NativeWindow InputMethodBridge::GetAttachedWindow() const {
214 TextInputClient* client = GetTextInputClient();
215 return client ?
216 client->GetAttachedWindow() : static_cast<gfx::NativeWindow>(NULL);
219 ui::TextInputType InputMethodBridge::GetTextInputType() const {
220 TextInputClient* client = GetTextInputClient();
221 return client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE;
224 ui::TextInputMode InputMethodBridge::GetTextInputMode() const {
225 TextInputClient* client = GetTextInputClient();
226 return client ? client->GetTextInputMode() : ui::TEXT_INPUT_MODE_DEFAULT;
229 bool InputMethodBridge::CanComposeInline() const {
230 TextInputClient* client = GetTextInputClient();
231 return client ? client->CanComposeInline() : true;
234 gfx::Rect InputMethodBridge::GetCaretBounds() const {
235 TextInputClient* client = GetTextInputClient();
236 if (!client)
237 return gfx::Rect();
239 return client->GetCaretBounds();
242 bool InputMethodBridge::GetCompositionCharacterBounds(uint32 index,
243 gfx::Rect* rect) const {
244 DCHECK(rect);
245 TextInputClient* client = GetTextInputClient();
246 if (!client)
247 return false;
249 return client->GetCompositionCharacterBounds(index, rect);
252 bool InputMethodBridge::HasCompositionText() const {
253 TextInputClient* client = GetTextInputClient();
254 return client ? client->HasCompositionText() : false;
257 bool InputMethodBridge::GetTextRange(gfx::Range* range) const {
258 TextInputClient* client = GetTextInputClient();
259 return client ? client->GetTextRange(range) : false;
262 bool InputMethodBridge::GetCompositionTextRange(gfx::Range* range) const {
263 TextInputClient* client = GetTextInputClient();
264 return client ? client->GetCompositionTextRange(range) : false;
267 bool InputMethodBridge::GetSelectionRange(gfx::Range* range) const {
268 TextInputClient* client = GetTextInputClient();
269 return client ? client->GetSelectionRange(range) : false;
272 bool InputMethodBridge::SetSelectionRange(const gfx::Range& range) {
273 TextInputClient* client = GetTextInputClient();
274 return client ? client->SetSelectionRange(range) : false;
277 bool InputMethodBridge::DeleteRange(const gfx::Range& range) {
278 TextInputClient* client = GetTextInputClient();
279 return client ? client->DeleteRange(range) : false;
282 bool InputMethodBridge::GetTextFromRange(const gfx::Range& range,
283 base::string16* text) const {
284 TextInputClient* client = GetTextInputClient();
285 return client ? client->GetTextFromRange(range, text) : false;
288 void InputMethodBridge::OnInputMethodChanged() {
289 TextInputClient* client = GetTextInputClient();
290 if (client)
291 client->OnInputMethodChanged();
294 bool InputMethodBridge::ChangeTextDirectionAndLayoutAlignment(
295 base::i18n::TextDirection direction) {
296 TextInputClient* client = GetTextInputClient();
297 return client ?
298 client->ChangeTextDirectionAndLayoutAlignment(direction) : false;
301 void InputMethodBridge::ExtendSelectionAndDelete(size_t before, size_t after) {
302 TextInputClient* client = GetTextInputClient();
303 if (client)
304 client->ExtendSelectionAndDelete(before, after);
307 void InputMethodBridge::EnsureCaretInRect(const gfx::Rect& rect) {
308 TextInputClient* client = GetTextInputClient();
309 if (client)
310 client->EnsureCaretInRect(rect);
313 void InputMethodBridge::OnCandidateWindowShown() {
316 void InputMethodBridge::OnCandidateWindowUpdated() {
319 void InputMethodBridge::OnCandidateWindowHidden() {
322 // Overridden from FocusChangeListener.
323 void InputMethodBridge::OnWillChangeFocus(View* focused_before, View* focused) {
324 if (HasCompositionText()) {
325 ConfirmCompositionText();
326 CancelComposition(focused_before);
330 void InputMethodBridge::OnDidChangeFocus(View* focused_before, View* focused) {
331 DCHECK_EQ(GetFocusedView(), focused);
332 OnTextInputTypeChanged(focused);
333 OnCaretBoundsChanged(focused);
336 ui::InputMethod* InputMethodBridge::GetHostInputMethod() const {
337 return host_;
341 } // namespace views