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/base/ime/input_method_ibus.h" | 5 #include "ui/base/ime/input_method_ibus.h" |
6 | 6 |
7 #include <X11/X.h> | 7 #include <X11/X.h> |
8 #include <X11/Xlib.h> | 8 #include <X11/Xlib.h> |
9 #include <X11/Xutil.h> | 9 #include <X11/Xutil.h> |
10 #undef FocusIn | 10 #undef FocusIn |
11 #undef FocusOut | 11 #undef FocusOut |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
14 #include <cstring> | 14 #include <cstring> |
15 #include <set> | 15 #include <set> |
16 #include <vector> | 16 #include <vector> |
17 | 17 |
18 #include "base/basictypes.h" | 18 #include "base/basictypes.h" |
19 #include "base/bind.h" | 19 #include "base/bind.h" |
20 #include "base/i18n/char_iterator.h" | 20 #include "base/i18n/char_iterator.h" |
21 #include "base/logging.h" | 21 #include "base/logging.h" |
22 #include "base/string_util.h" | 22 #include "base/string_util.h" |
23 #include "base/third_party/icu/icu_utf.h" | 23 #include "base/third_party/icu/icu_utf.h" |
24 #include "base/utf_string_conversions.h" | 24 #include "base/utf_string_conversions.h" |
25 #include "chromeos/dbus/dbus_thread_manager.h" | 25 #include "chromeos/dbus/dbus_thread_manager.h" |
| 26 #include "chromeos/dbus/ibus/ibus_client.h" |
26 #include "chromeos/dbus/ibus/ibus_input_context_client.h" | 27 #include "chromeos/dbus/ibus/ibus_input_context_client.h" |
27 #include "chromeos/dbus/ibus/ibus_text.h" | 28 #include "chromeos/dbus/ibus/ibus_text.h" |
28 #include "ui/base/events.h" | 29 #include "ui/base/events.h" |
29 #include "ui/base/ime/ibus_client_impl.h" | 30 #include "ui/base/ime/ibus_client.h" |
30 #include "ui/base/ime/text_input_client.h" | 31 #include "ui/base/ime/text_input_client.h" |
31 #include "ui/base/keycodes/keyboard_code_conversion.h" | 32 #include "ui/base/keycodes/keyboard_code_conversion.h" |
32 #include "ui/base/keycodes/keyboard_code_conversion_x.h" | 33 #include "ui/base/keycodes/keyboard_code_conversion_x.h" |
33 #include "ui/base/keycodes/keyboard_codes.h" | 34 #include "ui/base/keycodes/keyboard_codes.h" |
34 #include "ui/gfx/rect.h" | 35 #include "ui/gfx/rect.h" |
35 | 36 |
36 namespace { | 37 namespace { |
37 | 38 |
38 const int kIBusReleaseMask = 1 << 30; | 39 const int kIBusReleaseMask = 1 << 30; |
| 40 const char kClientName[] = "chrome"; |
| 41 |
| 42 // Following capability mask is introduced from |
| 43 // http://ibus.googlecode.com/svn/docs/ibus-1.4/ibus-ibustypes.html#IBusCapabili
te |
| 44 const uint32 kIBusCapabilityPreeditText = 1U; |
| 45 const uint32 kIBusCapabilityFocus = 8U; |
39 | 46 |
40 XKeyEvent* GetKeyEvent(XEvent* event) { | 47 XKeyEvent* GetKeyEvent(XEvent* event) { |
41 DCHECK(event && (event->type == KeyPress || event->type == KeyRelease)); | 48 DCHECK(event && (event->type == KeyPress || event->type == KeyRelease)); |
42 return &event->xkey; | 49 return &event->xkey; |
43 } | 50 } |
44 | 51 |
45 // Converts X (and ibus) flags to event flags. | 52 // Converts X (and ibus) flags to event flags. |
46 int EventFlagsFromXFlags(unsigned int flags) { | 53 int EventFlagsFromXFlags(unsigned int flags) { |
47 return (flags & LockMask ? ui::EF_CAPS_LOCK_DOWN : 0) | | 54 return (flags & LockMask ? ui::EF_CAPS_LOCK_DOWN : 0) | |
48 (flags & ControlMask ? ui::EF_CONTROL_DOWN : 0) | | 55 (flags & ControlMask ? ui::EF_CONTROL_DOWN : 0) | |
(...skipping 21 matching lines...) Expand all Loading... |
70 // translate Shift and CapsLock states. | 77 // translate Shift and CapsLock states. |
71 KeySym keysym = NoSymbol; | 78 KeySym keysym = NoSymbol; |
72 ::XLookupString(x_key, NULL, 0, &keysym, NULL); | 79 ::XLookupString(x_key, NULL, 0, &keysym, NULL); |
73 *ibus_keyval = keysym; | 80 *ibus_keyval = keysym; |
74 *ibus_keycode = x_key->keycode; | 81 *ibus_keycode = x_key->keycode; |
75 *ibus_state = IBusStateFromXFlags(x_key->state); | 82 *ibus_state = IBusStateFromXFlags(x_key->state); |
76 if (native_event->type == KeyRelease) | 83 if (native_event->type == KeyRelease) |
77 *ibus_state |= kIBusReleaseMask; | 84 *ibus_state |= kIBusReleaseMask; |
78 } | 85 } |
79 | 86 |
| 87 chromeos::IBusInputContextClient* GetInputContextClient() { |
| 88 return chromeos::DBusThreadManager::Get()->GetIBusInputContextClient(); |
| 89 } |
| 90 |
80 } // namespace | 91 } // namespace |
81 | 92 |
82 namespace ui { | 93 namespace ui { |
83 | 94 |
84 // InputMethodIBus::PendingKeyEventImpl implementation ------------------------ | 95 // A class to hold all data related to a key event being processed by the input |
85 class InputMethodIBus::PendingKeyEventImpl | 96 // method but still has no result back yet. |
86 : public internal::IBusClient::PendingKeyEvent { | 97 class InputMethodIBus::PendingKeyEvent { |
87 public: | 98 public: |
88 PendingKeyEventImpl(InputMethodIBus* input_method, | 99 PendingKeyEvent(InputMethodIBus* input_method, |
89 const base::NativeEvent& native_event, | 100 const base::NativeEvent& native_event, |
90 uint32 ibus_keyval); | 101 uint32 ibus_keyval); |
91 virtual ~PendingKeyEventImpl(); | 102 virtual ~PendingKeyEvent(); |
92 | 103 |
93 // internal::IBusClient::PendingKeyEvent overrides: | 104 // Process this pending key event after we receive its result from the input |
94 virtual void ProcessPostIME(bool handled) OVERRIDE; | 105 // method. It just call through InputMethodIBus::ProcessKeyEventPostIME(). |
| 106 void ProcessPostIME(bool handled); |
95 | 107 |
96 // Abandon this pending key event. Its result will just be discarded. | 108 // Abandon this pending key event. Its result will just be discarded. |
97 void Abandon() { input_method_ = NULL; } | 109 void Abandon() { input_method_ = NULL; } |
98 | 110 |
99 InputMethodIBus* input_method() const { return input_method_; } | 111 InputMethodIBus* input_method() const { return input_method_; } |
100 | 112 |
101 private: | 113 private: |
102 InputMethodIBus* input_method_; | 114 InputMethodIBus* input_method_; |
103 | 115 |
104 // TODO(yusukes): To support a fabricated key event (which is typically from | 116 // TODO(yusukes): To support a fabricated key event (which is typically from |
105 // a virtual keyboard), we might have to copy event type, event flags, key | 117 // a virtual keyboard), we might have to copy event type, event flags, key |
106 // code, 'character_', and 'unmodified_character_'. See views::InputMethodIBus | 118 // code, 'character_', and 'unmodified_character_'. See views::InputMethodIBus |
107 // for details. | 119 // for details. |
108 | 120 |
109 // corresponding XEvent data of a key event. It's a plain struct so we can do | 121 // corresponding XEvent data of a key event. It's a plain struct so we can do |
110 // bitwise copy. | 122 // bitwise copy. |
111 XKeyEvent x_event_; | 123 XKeyEvent x_event_; |
112 | 124 |
113 const uint32 ibus_keyval_; | 125 const uint32 ibus_keyval_; |
114 | 126 |
115 DISALLOW_COPY_AND_ASSIGN(PendingKeyEventImpl); | 127 DISALLOW_COPY_AND_ASSIGN(PendingKeyEvent); |
116 }; | 128 }; |
117 | 129 |
118 InputMethodIBus::PendingKeyEventImpl::PendingKeyEventImpl( | 130 InputMethodIBus::PendingKeyEvent::PendingKeyEvent( |
119 InputMethodIBus* input_method, | 131 InputMethodIBus* input_method, |
120 const base::NativeEvent& native_event, | 132 const base::NativeEvent& native_event, |
121 uint32 ibus_keyval) | 133 uint32 ibus_keyval) |
122 : input_method_(input_method), | 134 : input_method_(input_method), |
123 ibus_keyval_(ibus_keyval) { | 135 ibus_keyval_(ibus_keyval) { |
124 DCHECK(input_method_); | 136 DCHECK(input_method_); |
125 | 137 |
126 // TODO(yusukes): Support non-native event (from e.g. a virtual keyboard). | 138 // TODO(yusukes): Support non-native event (from e.g. a virtual keyboard). |
127 DCHECK(native_event); | 139 DCHECK(native_event); |
128 x_event_ = *GetKeyEvent(native_event); | 140 x_event_ = *GetKeyEvent(native_event); |
129 } | 141 } |
130 | 142 |
131 InputMethodIBus::PendingKeyEventImpl::~PendingKeyEventImpl() { | 143 InputMethodIBus::PendingKeyEvent::~PendingKeyEvent() { |
132 if (input_method_) | 144 if (input_method_) |
133 input_method_->FinishPendingKeyEvent(this); | 145 input_method_->FinishPendingKeyEvent(this); |
134 } | 146 } |
135 | 147 |
136 void InputMethodIBus::PendingKeyEventImpl::ProcessPostIME(bool handled) { | 148 void InputMethodIBus::PendingKeyEvent::ProcessPostIME(bool handled) { |
137 if (!input_method_) | 149 if (!input_method_) |
138 return; | 150 return; |
139 | 151 |
140 if (x_event_.type == KeyPress || x_event_.type == KeyRelease) { | 152 if (x_event_.type == KeyPress || x_event_.type == KeyRelease) { |
141 input_method_->ProcessKeyEventPostIME(reinterpret_cast<XEvent*>(&x_event_), | 153 input_method_->ProcessKeyEventPostIME(reinterpret_cast<XEvent*>(&x_event_), |
142 ibus_keyval_, | 154 ibus_keyval_, |
143 handled); | 155 handled); |
144 return; | 156 return; |
145 } | 157 } |
146 | 158 |
147 // TODO(yusukes): Support non-native event (from e.g. a virtual keyboard). | 159 // TODO(yusukes): Support non-native event (from e.g. a virtual keyboard). |
148 // See views::InputMethodIBus for details. Never forget to set 'character_' | 160 // See views::InputMethodIBus for details. Never forget to set 'character_' |
149 // and 'unmodified_character_' to support i18n VKs like a French VK! | 161 // and 'unmodified_character_' to support i18n VKs like a French VK! |
150 } | 162 } |
151 | 163 |
152 // InputMethodIBus::PendingCreateICRequestImpl implementation ----------------- | 164 // A class to hold information of a pending request for creating an ibus input |
153 class InputMethodIBus::PendingCreateICRequestImpl | 165 // context. |
154 : public internal::IBusClient::PendingCreateICRequest { | 166 class InputMethodIBus::PendingCreateICRequest { |
155 public: | 167 public: |
156 PendingCreateICRequestImpl(InputMethodIBus* input_method, | 168 PendingCreateICRequest(InputMethodIBus* input_method, |
157 internal::IBusClient* ibus_client, | 169 PendingCreateICRequest** request_ptr); |
158 PendingCreateICRequestImpl** request_ptr); | 170 virtual ~PendingCreateICRequest(); |
159 virtual ~PendingCreateICRequestImpl(); | |
160 | 171 |
161 // internal::IBusClient::PendingCreateICRequest overrides: | 172 // Set up signal handlers, or destroy object proxy if the input context is |
162 virtual void InitOrAbandonInputContext() OVERRIDE; | 173 // already abandoned. |
163 virtual void OnCreateInputContextFailed() OVERRIDE; | 174 void InitOrAbandonInputContext(); |
| 175 |
| 176 // Called if the create input context method call is failed. |
| 177 void OnCreateInputContextFailed(); |
164 | 178 |
165 // Abandon this pending key event. Its result will just be discarded. | 179 // Abandon this pending key event. Its result will just be discarded. |
166 void Abandon() { | 180 void Abandon() { |
167 input_method_ = NULL; | 181 input_method_ = NULL; |
168 request_ptr_ = NULL; | 182 request_ptr_ = NULL; |
169 // Do not reset |ibus_client_| here. | 183 // Do not reset |ibus_client_| here. |
170 } | 184 } |
171 | 185 |
172 private: | 186 private: |
173 InputMethodIBus* input_method_; | 187 InputMethodIBus* input_method_; |
174 internal::IBusClient* ibus_client_; | 188 PendingCreateICRequest** request_ptr_; |
175 PendingCreateICRequestImpl** request_ptr_; | |
176 | 189 |
177 DISALLOW_COPY_AND_ASSIGN(PendingCreateICRequestImpl); | 190 DISALLOW_COPY_AND_ASSIGN(PendingCreateICRequest); |
178 }; | 191 }; |
179 | 192 |
180 InputMethodIBus::PendingCreateICRequestImpl::PendingCreateICRequestImpl( | 193 InputMethodIBus::PendingCreateICRequest::PendingCreateICRequest( |
181 InputMethodIBus* input_method, | 194 InputMethodIBus* input_method, |
182 internal::IBusClient* ibus_client, | 195 PendingCreateICRequest** request_ptr) |
183 PendingCreateICRequestImpl** request_ptr) | |
184 : input_method_(input_method), | 196 : input_method_(input_method), |
185 ibus_client_(ibus_client), | |
186 request_ptr_(request_ptr) { | 197 request_ptr_(request_ptr) { |
187 } | 198 } |
188 | 199 |
189 InputMethodIBus::PendingCreateICRequestImpl::~PendingCreateICRequestImpl() { | 200 InputMethodIBus::PendingCreateICRequest::~PendingCreateICRequest() { |
190 if (request_ptr_) { | 201 if (request_ptr_) { |
191 DCHECK_EQ(*request_ptr_, this); | 202 DCHECK_EQ(*request_ptr_, this); |
192 *request_ptr_ = NULL; | 203 *request_ptr_ = NULL; |
193 } | 204 } |
194 } | 205 } |
195 | 206 |
196 void InputMethodIBus::PendingCreateICRequestImpl::OnCreateInputContextFailed() { | 207 void InputMethodIBus::PendingCreateICRequest::OnCreateInputContextFailed() { |
197 // TODO(nona): If the connection between Chrome and ibus-daemon terminates | 208 // TODO(nona): If the connection between Chrome and ibus-daemon terminates |
198 // for some reason, the create ic request will fail. We might want to call | 209 // for some reason, the create ic request will fail. We might want to call |
199 // ibus_client_->CreateContext() again after some delay. | 210 // ibus_client_->CreateContext() again after some delay. |
200 } | 211 } |
201 | 212 |
202 void InputMethodIBus::PendingCreateICRequestImpl::InitOrAbandonInputContext() { | 213 void InputMethodIBus::PendingCreateICRequest::InitOrAbandonInputContext() { |
203 if (input_method_) { | 214 if (input_method_) { |
204 DCHECK(ibus_client_->IsContextReady()); | 215 DCHECK(input_method_->IsContextReady()); |
205 input_method_->SetUpSignalHandlers(); | 216 input_method_->SetUpSignalHandlers(); |
206 } else { | 217 } else { |
207 ibus_client_->DestroyProxy(); | 218 GetInputContextClient()->ResetObjectProxy(); |
208 DCHECK(!ibus_client_->IsContextReady()); | |
209 } | 219 } |
210 } | 220 } |
211 | 221 |
212 // InputMethodIBus implementation ----------------------------------------- | 222 // InputMethodIBus implementation ----------------------------------------- |
213 InputMethodIBus::InputMethodIBus( | 223 InputMethodIBus::InputMethodIBus( |
214 internal::InputMethodDelegate* delegate) | 224 internal::InputMethodDelegate* delegate) |
215 : | 225 : ibus_client_(new internal::IBusClient), |
216 ibus_client_(new internal::IBusClientImpl), | |
217 pending_create_ic_request_(NULL), | 226 pending_create_ic_request_(NULL), |
218 context_focused_(false), | 227 context_focused_(false), |
219 composing_text_(false), | 228 composing_text_(false), |
220 composition_changed_(false), | 229 composition_changed_(false), |
221 suppress_next_result_(false), | 230 suppress_next_result_(false), |
222 weak_ptr_factory_(this) { | 231 weak_ptr_factory_(this) { |
223 SetDelegate(delegate); | 232 SetDelegate(delegate); |
224 } | 233 } |
225 | 234 |
226 InputMethodIBus::~InputMethodIBus() { | 235 InputMethodIBus::~InputMethodIBus() { |
227 AbandonAllPendingKeyEvents(); | 236 AbandonAllPendingKeyEvents(); |
228 if (ibus_client_->IsContextReady()) | 237 if (IsContextReady()) |
229 DestroyContext(); | 238 DestroyContext(); |
230 } | 239 } |
231 | 240 |
232 void InputMethodIBus::set_ibus_client( | 241 void InputMethodIBus::set_ibus_client( |
233 scoped_ptr<internal::IBusClient> new_client) { | 242 scoped_ptr<internal::IBusClient> new_client) { |
234 ibus_client_.swap(new_client); | 243 ibus_client_.swap(new_client); |
235 } | 244 } |
236 | 245 |
237 internal::IBusClient* InputMethodIBus::ibus_client() const { | 246 internal::IBusClient* InputMethodIBus::ibus_client() const { |
238 return ibus_client_.get(); | 247 return ibus_client_.get(); |
239 } | 248 } |
240 | 249 |
241 void InputMethodIBus::OnFocus() { | 250 void InputMethodIBus::OnFocus() { |
242 InputMethodBase::OnFocus(); | 251 InputMethodBase::OnFocus(); |
243 UpdateContextFocusState(); | 252 UpdateContextFocusState(); |
244 } | 253 } |
245 | 254 |
246 void InputMethodIBus::OnBlur() { | 255 void InputMethodIBus::OnBlur() { |
247 ConfirmCompositionText(); | 256 ConfirmCompositionText(); |
248 InputMethodBase::OnBlur(); | 257 InputMethodBase::OnBlur(); |
249 UpdateContextFocusState(); | 258 UpdateContextFocusState(); |
250 } | 259 } |
251 | 260 |
252 void InputMethodIBus::Init(bool focused) { | 261 void InputMethodIBus::Init(bool focused) { |
253 // Initializes the connection to ibus daemon. It may happen asynchronously, | 262 // Initializes the connection to ibus daemon. It may happen asynchronously, |
254 // and as soon as the connection is established, the |context_| will be | 263 // and as soon as the connection is established, the |context_| will be |
255 // created automatically. | 264 // created automatically. |
256 | 265 |
257 // Create the input context if the connection is already established. | 266 // Create the input context if the connection is already established. |
258 if (ibus_client_->IsConnected()) | 267 if (IsConnected()) |
259 CreateContext(); | 268 CreateContext(); |
260 | 269 |
261 InputMethodBase::Init(focused); | 270 InputMethodBase::Init(focused); |
262 } | 271 } |
263 | 272 |
264 // static | 273 // static |
265 void InputMethodIBus::ProcessKeyEventDone( | 274 void InputMethodIBus::ProcessKeyEventDone( |
266 PendingKeyEventImpl* pending_key_event, bool is_handled) { | 275 PendingKeyEvent* pending_key_event, bool is_handled) { |
267 DCHECK(pending_key_event); | 276 DCHECK(pending_key_event); |
268 pending_key_event->ProcessPostIME(is_handled); | 277 pending_key_event->ProcessPostIME(is_handled); |
269 delete pending_key_event; | 278 delete pending_key_event; |
270 } | 279 } |
271 | 280 |
272 void InputMethodIBus::DispatchKeyEvent(const base::NativeEvent& native_event) { | 281 void InputMethodIBus::DispatchKeyEvent(const base::NativeEvent& native_event) { |
273 DCHECK(native_event && (native_event->type == KeyPress || | 282 DCHECK(native_event && (native_event->type == KeyPress || |
274 native_event->type == KeyRelease)); | 283 native_event->type == KeyRelease)); |
275 DCHECK(system_toplevel_window_focused()); | 284 DCHECK(system_toplevel_window_focused()); |
276 | 285 |
(...skipping 12 matching lines...) Expand all Loading... |
289 GetTextInputType() == TEXT_INPUT_TYPE_PASSWORD || | 298 GetTextInputType() == TEXT_INPUT_TYPE_PASSWORD || |
290 ibus_client_->GetInputMethodType() == | 299 ibus_client_->GetInputMethodType() == |
291 internal::IBusClient::INPUT_METHOD_XKB_LAYOUT) { | 300 internal::IBusClient::INPUT_METHOD_XKB_LAYOUT) { |
292 if (native_event->type == KeyPress) | 301 if (native_event->type == KeyPress) |
293 ProcessUnfilteredKeyPressEvent(native_event, ibus_keyval); | 302 ProcessUnfilteredKeyPressEvent(native_event, ibus_keyval); |
294 else | 303 else |
295 DispatchKeyEventPostIME(native_event); | 304 DispatchKeyEventPostIME(native_event); |
296 return; | 305 return; |
297 } | 306 } |
298 | 307 |
299 PendingKeyEventImpl* pending_key = | 308 PendingKeyEvent* pending_key = |
300 new PendingKeyEventImpl(this, native_event, ibus_keyval); | 309 new PendingKeyEvent(this, native_event, ibus_keyval); |
301 pending_key_events_.insert(pending_key); | 310 pending_key_events_.insert(pending_key); |
302 | 311 |
303 ibus_client_->SendKeyEvent(ibus_keyval, | 312 GetInputContextClient()->ProcessKeyEvent( |
304 ibus_keycode, | 313 ibus_keyval, |
305 ibus_state, | 314 ibus_keycode, |
306 base::Bind(&InputMethodIBus::ProcessKeyEventDone, | 315 ibus_state, base::Bind(&InputMethodIBus::ProcessKeyEventDone, |
307 base::Unretained(pending_key))); | 316 base::Unretained(pending_key))); |
308 | 317 |
309 // We don't want to suppress the result generated by this key event, but it | 318 // We don't want to suppress the result generated by this key event, but it |
310 // may cause problem. See comment in ResetContext() method. | 319 // may cause problem. See comment in ResetContext() method. |
311 suppress_next_result_ = false; | 320 suppress_next_result_ = false; |
312 } | 321 } |
313 | 322 |
314 void InputMethodIBus::OnTextInputTypeChanged(const TextInputClient* client) { | 323 void InputMethodIBus::OnTextInputTypeChanged(const TextInputClient* client) { |
315 if (ibus_client_->IsContextReady() && IsTextInputClientFocused(client)) { | 324 if (IsContextReady() && IsTextInputClientFocused(client)) { |
316 ResetContext(); | 325 ResetContext(); |
317 UpdateContextFocusState(); | 326 UpdateContextFocusState(); |
318 } | 327 } |
319 InputMethodBase::OnTextInputTypeChanged(client); | 328 InputMethodBase::OnTextInputTypeChanged(client); |
320 } | 329 } |
321 | 330 |
322 void InputMethodIBus::OnCaretBoundsChanged(const TextInputClient* client) { | 331 void InputMethodIBus::OnCaretBoundsChanged(const TextInputClient* client) { |
323 if (!context_focused_ || !IsTextInputClientFocused(client)) | 332 if (!context_focused_ || !IsTextInputClientFocused(client)) |
324 return; | 333 return; |
325 | 334 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 // focus and after it acquires focus again are the same. | 377 // focus and after it acquires focus again are the same. |
369 OnTextInputTypeChanged(focused); | 378 OnTextInputTypeChanged(focused); |
370 | 379 |
371 UpdateContextFocusState(); | 380 UpdateContextFocusState(); |
372 // Force to update caret bounds, in case the client thinks that the caret | 381 // Force to update caret bounds, in case the client thinks that the caret |
373 // bounds has not changed. | 382 // bounds has not changed. |
374 OnCaretBoundsChanged(focused); | 383 OnCaretBoundsChanged(focused); |
375 } | 384 } |
376 | 385 |
377 void InputMethodIBus::CreateContext() { | 386 void InputMethodIBus::CreateContext() { |
378 DCHECK(ibus_client_->IsConnected()); | 387 DCHECK(IsConnected()); |
379 DCHECK(!pending_create_ic_request_); | 388 DCHECK(!pending_create_ic_request_); |
380 | 389 |
| 390 pending_create_ic_request_ = new PendingCreateICRequest( |
| 391 this, &pending_create_ic_request_); |
| 392 |
381 // Creates the input context asynchronously. | 393 // Creates the input context asynchronously. |
382 pending_create_ic_request_ = new PendingCreateICRequestImpl( | 394 chromeos::DBusThreadManager::Get()->GetIBusClient()->CreateInputContext( |
383 this, ibus_client_.get(), &pending_create_ic_request_); | 395 kClientName, |
384 ibus_client_->CreateContext(pending_create_ic_request_); | 396 base::Bind(&InputMethodIBus::CreateInputContextDone, |
| 397 weak_ptr_factory_.GetWeakPtr(), |
| 398 base::Unretained(pending_create_ic_request_)), |
| 399 base::Bind(&InputMethodIBus::CreateInputContextFail, |
| 400 weak_ptr_factory_.GetWeakPtr(), |
| 401 base::Unretained(pending_create_ic_request_))); |
385 } | 402 } |
386 | 403 |
387 void InputMethodIBus::SetUpSignalHandlers() { | 404 void InputMethodIBus::SetUpSignalHandlers() { |
388 DCHECK(ibus_client_->IsContextReady()); | 405 DCHECK(IsContextReady()); |
389 | 406 |
390 // connect input context signals | 407 // connect input context signals |
391 chromeos::IBusInputContextClient* input_context_client = | 408 chromeos::IBusInputContextClient* input_context_client = |
392 chromeos::DBusThreadManager::Get()->GetIBusInputContextClient(); | 409 chromeos::DBusThreadManager::Get()->GetIBusInputContextClient(); |
393 input_context_client->SetCommitTextHandler( | 410 input_context_client->SetCommitTextHandler( |
394 base::Bind(&InputMethodIBus::OnCommitText, | 411 base::Bind(&InputMethodIBus::OnCommitText, |
395 weak_ptr_factory_.GetWeakPtr())); | 412 weak_ptr_factory_.GetWeakPtr())); |
396 | 413 |
397 input_context_client->SetForwardKeyEventHandler( | 414 input_context_client->SetForwardKeyEventHandler( |
398 base::Bind(&InputMethodIBus::OnForwardKeyEvent, | 415 base::Bind(&InputMethodIBus::OnForwardKeyEvent, |
399 weak_ptr_factory_.GetWeakPtr())); | 416 weak_ptr_factory_.GetWeakPtr())); |
400 | 417 |
401 input_context_client->SetUpdatePreeditTextHandler( | 418 input_context_client->SetUpdatePreeditTextHandler( |
402 base::Bind(&InputMethodIBus::OnUpdatePreeditText, | 419 base::Bind(&InputMethodIBus::OnUpdatePreeditText, |
403 weak_ptr_factory_.GetWeakPtr())); | 420 weak_ptr_factory_.GetWeakPtr())); |
404 | 421 |
405 input_context_client->SetShowPreeditTextHandler( | 422 input_context_client->SetShowPreeditTextHandler( |
406 base::Bind(&InputMethodIBus::OnShowPreeditText, | 423 base::Bind(&InputMethodIBus::OnShowPreeditText, |
407 weak_ptr_factory_.GetWeakPtr())); | 424 weak_ptr_factory_.GetWeakPtr())); |
408 | 425 |
409 input_context_client->SetHidePreeditTextHandler( | 426 input_context_client->SetHidePreeditTextHandler( |
410 base::Bind(&InputMethodIBus::OnHidePreeditText, | 427 base::Bind(&InputMethodIBus::OnHidePreeditText, |
411 weak_ptr_factory_.GetWeakPtr())); | 428 weak_ptr_factory_.GetWeakPtr())); |
412 | 429 |
413 ibus_client_->SetCapabilities(internal::IBusClient::INLINE_COMPOSITION); | 430 GetInputContextClient()->SetCapabilities( |
| 431 kIBusCapabilityPreeditText | kIBusCapabilityFocus); |
414 | 432 |
415 UpdateContextFocusState(); | 433 UpdateContextFocusState(); |
416 // Since ibus-daemon is launched in an on-demand basis on Chrome OS, RWHVA (or | 434 // Since ibus-daemon is launched in an on-demand basis on Chrome OS, RWHVA (or |
417 // equivalents) might call OnCaretBoundsChanged() before the daemon starts. To | 435 // equivalents) might call OnCaretBoundsChanged() before the daemon starts. To |
418 // save the case, call OnCaretBoundsChanged() here. | 436 // save the case, call OnCaretBoundsChanged() here. |
419 OnCaretBoundsChanged(GetTextInputClient()); | 437 OnCaretBoundsChanged(GetTextInputClient()); |
420 OnInputMethodChanged(); | 438 OnInputMethodChanged(); |
421 } | 439 } |
422 | 440 |
423 void InputMethodIBus::DestroyContext() { | 441 void InputMethodIBus::DestroyContext() { |
424 if (pending_create_ic_request_) { | 442 if (pending_create_ic_request_) { |
425 DCHECK(!ibus_client_->IsContextReady()); | 443 DCHECK(!IsContextReady()); |
426 // |pending_create_ic_request_| will be deleted in CreateInputContextDone(). | 444 // |pending_create_ic_request_| will be deleted in CreateInputContextDone(). |
427 pending_create_ic_request_->Abandon(); | 445 pending_create_ic_request_->Abandon(); |
428 pending_create_ic_request_ = NULL; | 446 pending_create_ic_request_ = NULL; |
429 return; | 447 return; |
430 } | 448 } |
431 const chromeos::IBusInputContextClient* input_context = | 449 const chromeos::IBusInputContextClient* input_context = |
432 chromeos::DBusThreadManager::Get()->GetIBusInputContextClient(); | 450 chromeos::DBusThreadManager::Get()->GetIBusInputContextClient(); |
433 if (input_context && input_context->IsObjectProxyReady()) { | 451 if (input_context && input_context->IsObjectProxyReady()) { |
434 // We can't use IsContextReady here because we want to destroy object proxy | 452 // We can't use IsContextReady here because we want to destroy object proxy |
435 // regardless of connection. The IsContextReady contains connection check. | 453 // regardless of connection. The IsContextReady contains connection check. |
436 ResetInputContext(); | 454 ResetInputContext(); |
437 DCHECK(!ibus_client_->IsContextReady()); | 455 DCHECK(!IsContextReady()); |
438 } | 456 } |
439 } | 457 } |
440 | 458 |
441 void InputMethodIBus::ConfirmCompositionText() { | 459 void InputMethodIBus::ConfirmCompositionText() { |
442 TextInputClient* client = GetTextInputClient(); | 460 TextInputClient* client = GetTextInputClient(); |
443 if (client && client->HasCompositionText()) | 461 if (client && client->HasCompositionText()) |
444 client->ConfirmCompositionText(); | 462 client->ConfirmCompositionText(); |
445 | 463 |
446 ResetContext(); | 464 ResetContext(); |
447 } | 465 } |
(...skipping 21 matching lines...) Expand all Loading... |
469 | 487 |
470 // We need to abandon all pending key events, but as above comment says, there | 488 // We need to abandon all pending key events, but as above comment says, there |
471 // is no reliable way to abandon all results generated by these abandoned key | 489 // is no reliable way to abandon all results generated by these abandoned key |
472 // events. | 490 // events. |
473 AbandonAllPendingKeyEvents(); | 491 AbandonAllPendingKeyEvents(); |
474 | 492 |
475 // This function runs asynchronously. | 493 // This function runs asynchronously. |
476 // Note: some input method engines may not support reset method, such as | 494 // Note: some input method engines may not support reset method, such as |
477 // ibus-anthy. But as we control all input method engines by ourselves, we can | 495 // ibus-anthy. But as we control all input method engines by ourselves, we can |
478 // make sure that all of the engines we are using support it correctly. | 496 // make sure that all of the engines we are using support it correctly. |
479 ibus_client_->Reset(); | 497 GetInputContextClient()->Reset(); |
480 | 498 |
481 character_composer_.Reset(); | 499 character_composer_.Reset(); |
482 } | 500 } |
483 | 501 |
484 void InputMethodIBus::UpdateContextFocusState() { | 502 void InputMethodIBus::UpdateContextFocusState() { |
485 if (!ibus_client_->IsContextReady()) { | 503 if (!IsContextReady()) { |
486 context_focused_ = false; | 504 context_focused_ = false; |
487 return; | 505 return; |
488 } | 506 } |
489 | 507 |
490 const bool old_context_focused = context_focused_; | 508 const bool old_context_focused = context_focused_; |
491 // Use switch here in case we are going to add more text input types. | 509 // Use switch here in case we are going to add more text input types. |
492 switch (GetTextInputType()) { | 510 switch (GetTextInputType()) { |
493 case TEXT_INPUT_TYPE_NONE: | 511 case TEXT_INPUT_TYPE_NONE: |
494 case TEXT_INPUT_TYPE_PASSWORD: | 512 case TEXT_INPUT_TYPE_PASSWORD: |
495 context_focused_ = false; | 513 context_focused_ = false; |
496 break; | 514 break; |
497 default: | 515 default: |
498 context_focused_ = true; | 516 context_focused_ = true; |
499 break; | 517 break; |
500 } | 518 } |
501 | 519 |
502 // We only focus in |context_| when the focus is in a normal textfield. | 520 // We only focus in |context_| when the focus is in a normal textfield. |
503 // ibus_input_context_focus_{in|out}() run asynchronously. | 521 // ibus_input_context_focus_{in|out}() run asynchronously. |
504 if (old_context_focused && !context_focused_) | 522 if (old_context_focused && !context_focused_) |
505 ibus_client_->FocusOut(); | 523 GetInputContextClient()->FocusOut(); |
506 else if (!old_context_focused && context_focused_) | 524 else if (!old_context_focused && context_focused_) |
507 ibus_client_->FocusIn(); | 525 GetInputContextClient()->FocusIn(); |
508 | 526 |
509 if (context_focused_) { | 527 if (context_focused_) { |
510 internal::IBusClient::InlineCompositionCapability capability = | 528 uint32 capability = kIBusCapabilityFocus; |
511 CanComposeInline() ? internal::IBusClient::INLINE_COMPOSITION | 529 if (CanComposeInline()) |
512 : internal::IBusClient::OFF_THE_SPOT_COMPOSITION; | 530 capability |= kIBusCapabilityPreeditText; |
513 ibus_client_->SetCapabilities(capability); | 531 GetInputContextClient()->SetCapabilities(capability); |
514 } | 532 } |
515 } | 533 } |
516 | 534 |
517 void InputMethodIBus::ProcessKeyEventPostIME( | 535 void InputMethodIBus::ProcessKeyEventPostIME( |
518 const base::NativeEvent& native_event, | 536 const base::NativeEvent& native_event, |
519 uint32 ibus_keyval, | 537 uint32 ibus_keyval, |
520 bool handled) { | 538 bool handled) { |
521 TextInputClient* client = GetTextInputClient(); | 539 TextInputClient* client = GetTextInputClient(); |
522 | 540 |
523 if (!client) { | 541 if (!client) { |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 bool InputMethodIBus::HasInputMethodResult() const { | 718 bool InputMethodIBus::HasInputMethodResult() const { |
701 return result_text_.length() || composition_changed_; | 719 return result_text_.length() || composition_changed_; |
702 } | 720 } |
703 | 721 |
704 void InputMethodIBus::SendFakeProcessKeyEvent(bool pressed) const { | 722 void InputMethodIBus::SendFakeProcessKeyEvent(bool pressed) const { |
705 DispatchFabricatedKeyEventPostIME(pressed ? ET_KEY_PRESSED : ET_KEY_RELEASED, | 723 DispatchFabricatedKeyEventPostIME(pressed ? ET_KEY_PRESSED : ET_KEY_RELEASED, |
706 VKEY_PROCESSKEY, | 724 VKEY_PROCESSKEY, |
707 0); | 725 0); |
708 } | 726 } |
709 | 727 |
710 void InputMethodIBus::FinishPendingKeyEvent(PendingKeyEventImpl* pending_key) { | 728 void InputMethodIBus::FinishPendingKeyEvent(PendingKeyEvent* pending_key) { |
711 DCHECK(pending_key_events_.count(pending_key)); | 729 DCHECK(pending_key_events_.count(pending_key)); |
712 | 730 |
713 // |pending_key| will be deleted in ProcessKeyEventDone(). | 731 // |pending_key| will be deleted in ProcessKeyEventDone(). |
714 pending_key_events_.erase(pending_key); | 732 pending_key_events_.erase(pending_key); |
715 } | 733 } |
716 | 734 |
717 void InputMethodIBus::AbandonAllPendingKeyEvents() { | 735 void InputMethodIBus::AbandonAllPendingKeyEvents() { |
718 std::set<PendingKeyEventImpl*>::iterator i; | 736 std::set<PendingKeyEvent*>::iterator i; |
719 for (i = pending_key_events_.begin(); i != pending_key_events_.end(); ++i) { | 737 for (i = pending_key_events_.begin(); i != pending_key_events_.end(); ++i) { |
720 // The object will be deleted in ProcessKeyEventDone(). | 738 // The object will be deleted in ProcessKeyEventDone(). |
721 (*i)->Abandon(); | 739 (*i)->Abandon(); |
722 } | 740 } |
723 pending_key_events_.clear(); | 741 pending_key_events_.clear(); |
724 } | 742 } |
725 | 743 |
726 void InputMethodIBus::OnCommitText(const chromeos::ibus::IBusText& text) { | 744 void InputMethodIBus::OnCommitText(const chromeos::ibus::IBusText& text) { |
727 if (suppress_next_result_ || text.text().empty()) | 745 if (suppress_next_result_ || text.text().empty()) |
728 return; | 746 return; |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
838 } | 856 } |
839 } | 857 } |
840 | 858 |
841 void InputMethodIBus::ResetInputContext() { | 859 void InputMethodIBus::ResetInputContext() { |
842 context_focused_ = false; | 860 context_focused_ = false; |
843 | 861 |
844 ConfirmCompositionText(); | 862 ConfirmCompositionText(); |
845 | 863 |
846 // We are dead, so we need to ask the client to stop relying on us. | 864 // We are dead, so we need to ask the client to stop relying on us. |
847 OnInputMethodChanged(); | 865 OnInputMethodChanged(); |
848 ibus_client_->DestroyProxy(); | 866 GetInputContextClient()->ResetObjectProxy(); |
| 867 } |
| 868 |
| 869 void InputMethodIBus::CreateInputContextDone( |
| 870 PendingCreateICRequest* ic_request, |
| 871 const dbus::ObjectPath& object_path) { |
| 872 chromeos::DBusThreadManager::Get()->GetIBusInputContextClient() |
| 873 ->Initialize(chromeos::DBusThreadManager::Get()->GetIBusBus(), |
| 874 object_path); |
| 875 ic_request->InitOrAbandonInputContext(); |
| 876 delete ic_request; |
| 877 } |
| 878 |
| 879 void InputMethodIBus::CreateInputContextFail( |
| 880 PendingCreateICRequest* ic_request) { |
| 881 ic_request->OnCreateInputContextFailed(); |
| 882 delete ic_request; |
| 883 } |
| 884 |
| 885 bool InputMethodIBus::IsConnected() { |
| 886 return chromeos::DBusThreadManager::Get()->GetIBusBus() != NULL; |
| 887 } |
| 888 |
| 889 bool InputMethodIBus::IsContextReady() { |
| 890 if (!IsConnected()) |
| 891 return false; |
| 892 if (!GetInputContextClient()) |
| 893 return false; |
| 894 return GetInputContextClient()->IsObjectProxyReady(); |
849 } | 895 } |
850 | 896 |
851 void InputMethodIBus::OnConnected() { | 897 void InputMethodIBus::OnConnected() { |
852 DCHECK(ibus_client_->IsConnected()); | 898 DCHECK(IsConnected()); |
853 // If already input context is initialized, do nothing. | 899 // If already input context is initialized, do nothing. |
854 if (ibus_client_->IsContextReady()) | 900 if (IsContextReady()) |
855 return; | 901 return; |
856 | 902 |
857 DestroyContext(); | 903 DestroyContext(); |
858 CreateContext(); | 904 CreateContext(); |
859 } | 905 } |
860 | 906 |
861 void InputMethodIBus::OnDisconnected() { | 907 void InputMethodIBus::OnDisconnected() { |
862 DestroyContext(); | 908 DestroyContext(); |
863 } | 909 } |
864 | 910 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
941 } | 987 } |
942 | 988 |
943 // Use a black thin underline by default. | 989 // Use a black thin underline by default. |
944 if (out_composition->underlines.empty()) { | 990 if (out_composition->underlines.empty()) { |
945 out_composition->underlines.push_back(CompositionUnderline( | 991 out_composition->underlines.push_back(CompositionUnderline( |
946 0, length, SK_ColorBLACK, false /* thick */)); | 992 0, length, SK_ColorBLACK, false /* thick */)); |
947 } | 993 } |
948 } | 994 } |
949 | 995 |
950 } // namespace ui | 996 } // namespace ui |
OLD | NEW |