Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / views / ime / input_method_bridge.cc
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.
4
5 #include "ui/views/ime/input_method_bridge.h"
6
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"
13
14 namespace views {
15
16 // InputMethodBridge::HostObserver class ---------------------------------------
17
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   ~HostObserver() override;
25
26   void OnTextInputTypeChanged(const ui::TextInputClient* client) override {}
27   void OnFocus() override {}
28   void OnBlur() override {}
29   void OnCaretBoundsChanged(const ui::TextInputClient* client) override {}
30   void OnTextInputStateChanged(const ui::TextInputClient* client) override {}
31   void OnInputMethodDestroyed(const ui::InputMethod* input_method) override;
32   void OnShowImeIfNeeded() override {}
33
34  private:
35   InputMethodBridge* bridge_;
36
37   DISALLOW_COPY_AND_ASSIGN(HostObserver);
38 };
39
40 InputMethodBridge::HostObserver::HostObserver(InputMethodBridge* bridge)
41     : bridge_(bridge) {
42   bridge_->host_->AddObserver(this);
43 }
44
45 InputMethodBridge::HostObserver::~HostObserver() {
46   if (bridge_->host_)
47     bridge_->host_->RemoveObserver(this);
48 }
49
50 void InputMethodBridge::HostObserver::OnInputMethodDestroyed(
51     const ui::InputMethod* input_method) {
52   DCHECK_EQ(bridge_->host_, input_method);
53   bridge_->host_->RemoveObserver(this);
54   bridge_->host_ = NULL;
55 }
56
57 // InputMethodBridge class -----------------------------------------------------
58
59 InputMethodBridge::InputMethodBridge(internal::InputMethodDelegate* delegate,
60                                      ui::InputMethod* host,
61                                      bool shared_input_method)
62     : host_(host),
63       shared_input_method_(shared_input_method) {
64   DCHECK(host_);
65   SetDelegate(delegate);
66
67   host_observer_.reset(new HostObserver(this));
68 }
69
70 InputMethodBridge::~InputMethodBridge() {
71   // By the time we get here it's very likely |widget_|'s NativeWidget has been
72   // destroyed. This means any calls to |widget_| that go to the NativeWidget,
73   // such as IsActive(), will crash. SetFocusedTextInputClient() may callback to
74   // this and go into |widget_|. NULL out |widget_| so we don't attempt to use
75   // it.
76   DetachFromWidget();
77
78   // Host input method might have been destroyed at this point.
79   if (host_)
80     host_->DetachTextInputClient(this);
81 }
82
83 void InputMethodBridge::OnFocus() {
84   DCHECK(host_);
85
86   // Direct the shared IME to send TextInputClient messages to |this| object.
87   if (shared_input_method_ || !host_->GetTextInputClient())
88     host_->SetFocusedTextInputClient(this);
89
90   // TODO(yusukes): We don't need to call OnTextInputTypeChanged() once we move
91   // text input type tracker code to ui::InputMethodBase.
92   if (GetFocusedView()) {
93     OnTextInputTypeChanged(GetFocusedView());
94     OnCaretBoundsChanged(GetFocusedView());
95   }
96 }
97
98 void InputMethodBridge::OnBlur() {
99   DCHECK(host_);
100
101   if (HasCompositionText()) {
102     ConfirmCompositionText();
103     host_->CancelComposition(this);
104   }
105
106   if (host_->GetTextInputClient() == this)
107     host_->SetFocusedTextInputClient(NULL);
108 }
109
110 bool InputMethodBridge::OnUntranslatedIMEMessage(const base::NativeEvent& event,
111                                                  NativeEventResult* result) {
112   DCHECK(host_);
113
114   return host_->OnUntranslatedIMEMessage(event, result);
115 }
116
117 void InputMethodBridge::DispatchKeyEvent(const ui::KeyEvent& key) {
118   DCHECK(key.type() == ui::ET_KEY_PRESSED || key.type() == ui::ET_KEY_RELEASED);
119
120   // We can just dispatch the event here since the |key| is already processed by
121   // the system-wide IME.
122   DispatchKeyEventPostIME(key);
123 }
124
125 void InputMethodBridge::OnTextInputTypeChanged(View* view) {
126   DCHECK(host_);
127
128   if (IsViewFocused(view))
129     host_->OnTextInputTypeChanged(this);
130   InputMethodBase::OnTextInputTypeChanged(view);
131 }
132
133 void InputMethodBridge::OnCaretBoundsChanged(View* view) {
134   DCHECK(host_);
135
136   if (IsViewFocused(view) && !IsTextInputTypeNone())
137     host_->OnCaretBoundsChanged(this);
138 }
139
140 void InputMethodBridge::CancelComposition(View* view) {
141   DCHECK(host_);
142
143   if (IsViewFocused(view))
144     host_->CancelComposition(this);
145 }
146
147 void InputMethodBridge::OnInputLocaleChanged() {
148   DCHECK(host_);
149
150   host_->OnInputLocaleChanged();
151 }
152
153 std::string InputMethodBridge::GetInputLocale() {
154   DCHECK(host_);
155
156   return host_->GetInputLocale();
157 }
158
159 bool InputMethodBridge::IsActive() {
160   DCHECK(host_);
161
162   return host_->IsActive();
163 }
164
165 bool InputMethodBridge::IsCandidatePopupOpen() const {
166   DCHECK(host_);
167
168   return host_->IsCandidatePopupOpen();
169 }
170
171 void InputMethodBridge::ShowImeIfNeeded() {
172   DCHECK(host_);
173   host_->ShowImeIfNeeded();
174 }
175
176 // Overridden from TextInputClient. Forward an event from the system-wide IME
177 // to the text input |client|, which is e.g. views::Textfield.
178 void InputMethodBridge::SetCompositionText(
179     const ui::CompositionText& composition) {
180   TextInputClient* client = GetTextInputClient();
181   if (client)
182     client->SetCompositionText(composition);
183 }
184
185 void InputMethodBridge::ConfirmCompositionText() {
186   TextInputClient* client = GetTextInputClient();
187   if (client)
188     client->ConfirmCompositionText();
189 }
190
191 void InputMethodBridge::ClearCompositionText() {
192   TextInputClient* client = GetTextInputClient();
193   if (client)
194     client->ClearCompositionText();
195 }
196
197 void InputMethodBridge::InsertText(const base::string16& text) {
198   TextInputClient* client = GetTextInputClient();
199   if (client)
200     client->InsertText(text);
201 }
202
203 void InputMethodBridge::InsertChar(base::char16 ch, int flags) {
204   TextInputClient* client = GetTextInputClient();
205   if (client)
206     client->InsertChar(ch, flags);
207 }
208
209 gfx::NativeWindow InputMethodBridge::GetAttachedWindow() const {
210   TextInputClient* client = GetTextInputClient();
211   return client ?
212       client->GetAttachedWindow() : static_cast<gfx::NativeWindow>(NULL);
213 }
214
215 ui::TextInputType InputMethodBridge::GetTextInputType() const {
216   TextInputClient* client = GetTextInputClient();
217   return client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE;
218 }
219
220 ui::TextInputMode InputMethodBridge::GetTextInputMode() const {
221   TextInputClient* client = GetTextInputClient();
222   return client ? client->GetTextInputMode() : ui::TEXT_INPUT_MODE_DEFAULT;
223 }
224
225 int InputMethodBridge::GetTextInputFlags() const {
226   TextInputClient* client = GetTextInputClient();
227   return client ? client->GetTextInputFlags() : 0;
228 }
229
230 bool InputMethodBridge::CanComposeInline() const {
231   TextInputClient* client = GetTextInputClient();
232   return client ? client->CanComposeInline() : true;
233 }
234
235 gfx::Rect InputMethodBridge::GetCaretBounds() const {
236   TextInputClient* client = GetTextInputClient();
237   if (!client)
238     return gfx::Rect();
239
240   return client->GetCaretBounds();
241 }
242
243 bool InputMethodBridge::GetCompositionCharacterBounds(uint32 index,
244                                                       gfx::Rect* rect) const {
245   DCHECK(rect);
246   TextInputClient* client = GetTextInputClient();
247   if (!client)
248     return false;
249
250   return client->GetCompositionCharacterBounds(index, rect);
251 }
252
253 bool InputMethodBridge::HasCompositionText() const {
254   TextInputClient* client = GetTextInputClient();
255   return client ? client->HasCompositionText() : false;
256 }
257
258 bool InputMethodBridge::GetTextRange(gfx::Range* range) const {
259   TextInputClient* client = GetTextInputClient();
260   return client ?  client->GetTextRange(range) : false;
261 }
262
263 bool InputMethodBridge::GetCompositionTextRange(gfx::Range* range) const {
264   TextInputClient* client = GetTextInputClient();
265   return client ? client->GetCompositionTextRange(range) : false;
266 }
267
268 bool InputMethodBridge::GetSelectionRange(gfx::Range* range) const {
269   TextInputClient* client = GetTextInputClient();
270   return client ? client->GetSelectionRange(range) : false;
271 }
272
273 bool InputMethodBridge::SetSelectionRange(const gfx::Range& range) {
274   TextInputClient* client = GetTextInputClient();
275   return client ? client->SetSelectionRange(range) : false;
276 }
277
278 bool InputMethodBridge::DeleteRange(const gfx::Range& range) {
279   TextInputClient* client = GetTextInputClient();
280   return client ? client->DeleteRange(range) : false;
281 }
282
283 bool InputMethodBridge::GetTextFromRange(const gfx::Range& range,
284                                          base::string16* text) const {
285   TextInputClient* client = GetTextInputClient();
286   return client ? client->GetTextFromRange(range, text) : false;
287 }
288
289 void InputMethodBridge::OnInputMethodChanged() {
290   TextInputClient* client = GetTextInputClient();
291   if (client)
292     client->OnInputMethodChanged();
293 }
294
295 bool InputMethodBridge::ChangeTextDirectionAndLayoutAlignment(
296     base::i18n::TextDirection direction) {
297   TextInputClient* client = GetTextInputClient();
298   return client ?
299       client->ChangeTextDirectionAndLayoutAlignment(direction) : false;
300 }
301
302 void InputMethodBridge::ExtendSelectionAndDelete(size_t before, size_t after) {
303   TextInputClient* client = GetTextInputClient();
304   if (client)
305     client->ExtendSelectionAndDelete(before, after);
306 }
307
308 void InputMethodBridge::EnsureCaretInRect(const gfx::Rect& rect) {
309   TextInputClient* client = GetTextInputClient();
310   if (client)
311     client->EnsureCaretInRect(rect);
312 }
313
314 void InputMethodBridge::OnCandidateWindowShown() {
315 }
316
317 void InputMethodBridge::OnCandidateWindowUpdated() {
318 }
319
320 void InputMethodBridge::OnCandidateWindowHidden() {
321 }
322
323 bool InputMethodBridge::IsEditingCommandEnabled(int command_id) {
324   return false;
325 }
326
327 void InputMethodBridge::ExecuteEditingCommand(int command_id) {
328 }
329
330 // Overridden from FocusChangeListener.
331 void InputMethodBridge::OnWillChangeFocus(View* focused_before, View* focused) {
332   if (HasCompositionText()) {
333     ConfirmCompositionText();
334     CancelComposition(focused_before);
335   }
336 }
337
338 void InputMethodBridge::OnDidChangeFocus(View* focused_before, View* focused) {
339   DCHECK_EQ(GetFocusedView(), focused);
340   OnTextInputTypeChanged(focused);
341   OnCaretBoundsChanged(focused);
342 }
343
344 ui::InputMethod* InputMethodBridge::GetHostInputMethod() const {
345   return host_;
346 }
347
348
349 }  // namespace views