OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/views/ime/input_method_bridge.h" | 5 #include "ui/views/ime/input_method_bridge.h" |
6 | 6 |
7 #include "ui/base/events/event.h" | 7 #include "ui/base/events/event.h" |
8 #include "ui/base/ime/input_method.h" | 8 #include "ui/base/ime/input_method.h" |
9 #include "ui/gfx/rect.h" | 9 #include "ui/base/ime/text_input_client.h" |
10 #include "ui/views/view.h" | |
11 #include "ui/views/widget/widget.h" | |
12 | 10 |
13 namespace views { | 11 namespace views { |
14 | 12 |
15 InputMethodBridge::InputMethodBridge(internal::InputMethodDelegate* delegate, | 13 InputMethodBridge::InputMethodBridge(internal::InputMethodDelegate* delegate, |
16 ui::InputMethod* host, | 14 ui::InputMethod* host, |
17 bool shared_input_method) | 15 bool shared_input_method) |
18 : host_(host), | 16 : host_(host), |
19 shared_input_method_(shared_input_method), | 17 shared_input_method_(shared_input_method), |
20 context_focused_(false) { | 18 context_focused_(false) { |
21 DCHECK(host_); | 19 DCHECK(host_); |
22 SetDelegate(delegate); | 20 SetDelegate(delegate); |
23 } | 21 } |
24 | 22 |
25 InputMethodBridge::~InputMethodBridge() { | 23 InputMethodBridge::~InputMethodBridge() { |
26 // By the time we get here it's very likely |widget_|'s NativeWidget has been | 24 // By the time we get here it's very likely |widget_|'s NativeWidget has been |
27 // destroyed. This means any calls to |widget_| that go to the NativeWidget, | 25 // destroyed. This means any calls to |widget_| that go to the NativeWidget, |
28 // such as IsActive(), will crash. SetFocusedTextInputClient() may callback to | 26 // such as IsActive(), will crash. SetFocusedTextInputClient() may callback to |
29 // this and go into |widget_|. NULL out |widget_| so we don't attempt to use | 27 // this and go into |widget_|. NULL out |widget_| so we don't attempt to use |
30 // it. | 28 // it. |
31 DetachFromWidget(); | 29 DetachFromWidget(); |
32 if (host_->GetTextInputClient() == this) | |
33 host_->SetFocusedTextInputClient(NULL); | |
34 } | |
35 | |
36 void InputMethodBridge::OnFocus() { | |
37 // Direct the shared IME to send TextInputClient messages to |this| object. | |
38 if (shared_input_method_ || !host_->GetTextInputClient()) | |
39 host_->SetFocusedTextInputClient(this); | |
40 | |
41 // TODO(yusukes): We don't need to call OnTextInputTypeChanged() once we move | |
42 // text input type tracker code to ui::InputMethodBase. | |
43 if (GetFocusedView()) | |
44 OnTextInputTypeChanged(GetFocusedView()); | |
45 } | |
46 | |
47 void InputMethodBridge::OnBlur() { | |
48 if (HasCompositionText()) { | |
49 ConfirmCompositionText(); | |
50 host_->CancelComposition(this); | |
51 } | |
52 | |
53 if (host_->GetTextInputClient() == this) | |
54 host_->SetFocusedTextInputClient(NULL); | |
55 } | 30 } |
56 | 31 |
57 bool InputMethodBridge::OnUntranslatedIMEMessage(const base::NativeEvent& event, | 32 bool InputMethodBridge::OnUntranslatedIMEMessage(const base::NativeEvent& event, |
58 NativeEventResult* result) { | 33 NativeEventResult* result) { |
59 return host_->OnUntranslatedIMEMessage(event, result); | 34 return host_->OnUntranslatedIMEMessage(event, result); |
60 } | 35 } |
61 | 36 |
62 void InputMethodBridge::DispatchKeyEvent(const ui::KeyEvent& key) { | 37 void InputMethodBridge::DispatchKeyEvent(const ui::KeyEvent& key) { |
63 DCHECK(key.type() == ui::ET_KEY_PRESSED || key.type() == ui::ET_KEY_RELEASED); | 38 DCHECK(key.type() == ui::ET_KEY_PRESSED || key.type() == ui::ET_KEY_RELEASED); |
64 | 39 |
65 // We can just dispatch the event here since the |key| is already processed by | 40 // We can just dispatch the event here since the |key| is already processed by |
66 // the system-wide IME. | 41 // the system-wide IME. |
67 DispatchKeyEventPostIME(key); | 42 DispatchKeyEventPostIME(key); |
68 } | 43 } |
69 | 44 |
70 void InputMethodBridge::OnTextInputTypeChanged(View* view) { | 45 void InputMethodBridge::OnTextInputTypeChanged(View* view) { |
71 if (IsViewFocused(view)) | 46 if (IsViewFocused(view)) |
72 host_->OnTextInputTypeChanged(this); | 47 host_->OnTextInputTypeChanged(GetTextInputClient()); |
73 InputMethodBase::OnTextInputTypeChanged(view); | |
74 } | 48 } |
75 | 49 |
76 void InputMethodBridge::OnCaretBoundsChanged(View* view) { | 50 void InputMethodBridge::OnCaretBoundsChanged(View* view) { |
77 if (IsViewFocused(view) && !IsTextInputTypeNone()) | 51 if (IsViewFocused(view) && !IsTextInputTypeNone()) |
78 host_->OnCaretBoundsChanged(this); | 52 host_->OnCaretBoundsChanged(GetTextInputClient()); |
79 } | 53 } |
80 | 54 |
81 void InputMethodBridge::CancelComposition(View* view) { | 55 void InputMethodBridge::CancelComposition(View* view) { |
82 if (IsViewFocused(view)) | 56 if (IsViewFocused(view)) |
83 host_->CancelComposition(this); | 57 host_->CancelComposition(GetTextInputClient()); |
84 } | 58 } |
85 | 59 |
86 void InputMethodBridge::OnInputLocaleChanged() { | 60 void InputMethodBridge::OnInputLocaleChanged() { |
87 return host_->OnInputLocaleChanged(); | 61 return host_->OnInputLocaleChanged(); |
88 } | 62 } |
89 | 63 |
90 std::string InputMethodBridge::GetInputLocale() { | 64 std::string InputMethodBridge::GetInputLocale() { |
91 return host_->GetInputLocale(); | 65 return host_->GetInputLocale(); |
92 } | 66 } |
93 | 67 |
94 base::i18n::TextDirection InputMethodBridge::GetInputTextDirection() { | 68 base::i18n::TextDirection InputMethodBridge::GetInputTextDirection() { |
95 return host_->GetInputTextDirection(); | 69 return host_->GetInputTextDirection(); |
96 } | 70 } |
97 | 71 |
98 bool InputMethodBridge::IsActive() { | 72 bool InputMethodBridge::IsActive() { |
99 return host_->IsActive(); | 73 return host_->IsActive(); |
100 } | 74 } |
101 | 75 |
102 bool InputMethodBridge::IsCandidatePopupOpen() const { | 76 bool InputMethodBridge::IsCandidatePopupOpen() const { |
103 return host_->IsCandidatePopupOpen(); | 77 return host_->IsCandidatePopupOpen(); |
104 } | 78 } |
105 | 79 |
106 // Overridden from TextInputClient. Forward an event from the system-wide IME | |
107 // to the text input |client|, which is e.g. views::NativeTextfieldViews. | |
108 void InputMethodBridge::SetCompositionText( | |
109 const ui::CompositionText& composition) { | |
110 TextInputClient* client = GetTextInputClient(); | |
111 if (client) | |
112 client->SetCompositionText(composition); | |
113 } | |
114 | |
115 void InputMethodBridge::ConfirmCompositionText() { | |
116 TextInputClient* client = GetTextInputClient(); | |
117 if (client) | |
118 client->ConfirmCompositionText(); | |
119 } | |
120 | |
121 void InputMethodBridge::ClearCompositionText() { | |
122 TextInputClient* client = GetTextInputClient(); | |
123 if (client) | |
124 client->ClearCompositionText(); | |
125 } | |
126 | |
127 void InputMethodBridge::InsertText(const string16& text) { | |
128 TextInputClient* client = GetTextInputClient(); | |
129 if (client) | |
130 client->InsertText(text); | |
131 } | |
132 | |
133 void InputMethodBridge::InsertChar(char16 ch, int flags) { | |
134 TextInputClient* client = GetTextInputClient(); | |
135 if (client) | |
136 client->InsertChar(ch, flags); | |
137 } | |
138 | |
139 gfx::NativeWindow InputMethodBridge::GetAttachedWindow() const { | |
140 TextInputClient* client = GetTextInputClient(); | |
141 return client ? | |
142 client->GetAttachedWindow() : static_cast<gfx::NativeWindow>(NULL); | |
143 } | |
144 | |
145 ui::TextInputType InputMethodBridge::GetTextInputType() const { | |
146 TextInputClient* client = GetTextInputClient(); | |
147 return client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE; | |
148 } | |
149 | |
150 ui::TextInputMode InputMethodBridge::GetTextInputMode() const { | |
151 TextInputClient* client = GetTextInputClient(); | |
152 return client ? client->GetTextInputMode() : ui::TEXT_INPUT_MODE_DEFAULT; | |
153 } | |
154 | |
155 bool InputMethodBridge::CanComposeInline() const { | |
156 TextInputClient* client = GetTextInputClient(); | |
157 return client ? client->CanComposeInline() : true; | |
158 } | |
159 | |
160 gfx::Rect InputMethodBridge::GetCaretBounds() { | |
161 TextInputClient* client = GetTextInputClient(); | |
162 if (!client) | |
163 return gfx::Rect(); | |
164 | |
165 return client->GetCaretBounds(); | |
166 } | |
167 | |
168 bool InputMethodBridge::GetCompositionCharacterBounds(uint32 index, | |
169 gfx::Rect* rect) { | |
170 DCHECK(rect); | |
171 TextInputClient* client = GetTextInputClient(); | |
172 if (!client) | |
173 return false; | |
174 | |
175 return client->GetCompositionCharacterBounds(index, rect); | |
176 } | |
177 | |
178 bool InputMethodBridge::HasCompositionText() { | |
179 TextInputClient* client = GetTextInputClient(); | |
180 return client ? client->HasCompositionText() : false; | |
181 } | |
182 | |
183 bool InputMethodBridge::GetTextRange(ui::Range* range) { | |
184 TextInputClient* client = GetTextInputClient(); | |
185 return client ? client->GetTextRange(range) : false; | |
186 } | |
187 | |
188 bool InputMethodBridge::GetCompositionTextRange(ui::Range* range) { | |
189 TextInputClient* client = GetTextInputClient(); | |
190 return client ? client->GetCompositionTextRange(range) : false; | |
191 } | |
192 | |
193 bool InputMethodBridge::GetSelectionRange(ui::Range* range) { | |
194 TextInputClient* client = GetTextInputClient(); | |
195 return client ? client->GetSelectionRange(range) : false; | |
196 } | |
197 | |
198 bool InputMethodBridge::SetSelectionRange(const ui::Range& range) { | |
199 TextInputClient* client = GetTextInputClient(); | |
200 return client ? client->SetSelectionRange(range) : false; | |
201 } | |
202 | |
203 bool InputMethodBridge::DeleteRange(const ui::Range& range) { | |
204 TextInputClient* client = GetTextInputClient(); | |
205 return client ? client->DeleteRange(range) : false; | |
206 } | |
207 | |
208 bool InputMethodBridge::GetTextFromRange( | |
209 const ui::Range& range, string16* text) { | |
210 TextInputClient* client = GetTextInputClient(); | |
211 return client ? client->GetTextFromRange(range, text) : false; | |
212 } | |
213 | |
214 void InputMethodBridge::OnInputMethodChanged() { | |
215 TextInputClient* client = GetTextInputClient(); | |
216 if (client) | |
217 client->OnInputMethodChanged(); | |
218 } | |
219 | |
220 bool InputMethodBridge::ChangeTextDirectionAndLayoutAlignment( | |
221 base::i18n::TextDirection direction) { | |
222 TextInputClient* client = GetTextInputClient(); | |
223 return client ? | |
224 client->ChangeTextDirectionAndLayoutAlignment(direction) : false; | |
225 } | |
226 | |
227 void InputMethodBridge::ExtendSelectionAndDelete(size_t before, size_t after) { | |
228 TextInputClient* client = GetTextInputClient(); | |
229 if (client) | |
230 client->ExtendSelectionAndDelete(before, after); | |
231 } | |
232 | |
233 void InputMethodBridge::EnsureCaretInRect(const gfx::Rect& rect) { | |
234 TextInputClient* client = GetTextInputClient(); | |
235 if (client) | |
236 client->EnsureCaretInRect(rect); | |
237 } | |
238 | |
239 // Overridden from FocusChangeListener. | |
240 void InputMethodBridge::OnWillChangeFocus(View* focused_before, View* focused) { | 80 void InputMethodBridge::OnWillChangeFocus(View* focused_before, View* focused) { |
241 if (HasCompositionText()) { | 81 if (GetTextInputClient() && GetTextInputClient()->HasCompositionText()) { |
242 ConfirmCompositionText(); | 82 GetTextInputClient()->ConfirmCompositionText(); |
243 CancelComposition(focused_before); | 83 CancelComposition(focused_before); |
244 } | 84 } |
245 } | 85 } |
246 | 86 |
247 void InputMethodBridge::OnDidChangeFocus(View* focused_before, View* focused) { | 87 void InputMethodBridge::OnDidChangeFocus(View* focused_before, View* focused) { |
248 DCHECK_EQ(GetFocusedView(), focused); | 88 DCHECK_EQ(GetFocusedView(), focused); |
| 89 host_->SetFocusedTextInputClient(GetTextInputClient()); |
249 OnTextInputTypeChanged(focused); | 90 OnTextInputTypeChanged(focused); |
250 OnCaretBoundsChanged(focused); | 91 OnCaretBoundsChanged(focused); |
251 } | 92 } |
252 | 93 |
253 ui::InputMethod* InputMethodBridge::GetHostInputMethod() const { | 94 ui::InputMethod* InputMethodBridge::GetHostInputMethod() const { |
254 return host_; | 95 return host_; |
255 } | 96 } |
256 | 97 |
257 | 98 |
258 } // namespace views | 99 } // namespace views |
OLD | NEW |