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