Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(513)

Side by Side Diff: ui/base/ime/input_method_ibus.cc

Issue 8576005: IME (input method editor) support for Aura, part 3 of 3: Use ui::InputMethod in ash. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase, review Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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_ibus.h" 5 #include "ui/base/ime/input_method_ibus.h"
6 6
7 #include <ibus.h> 7 #include <ibus.h>
8 #if defined(TOUCH_UI) 8
9 #if defined(USE_AURA)
10 // Aura for Linux/ChromeOS, with and without TOUCH_UI.
11 #include <X11/X.h>
9 #include <X11/Xlib.h> 12 #include <X11/Xlib.h>
10 #include <X11/Xutil.h> 13 #include <X11/Xutil.h>
14 #else
15 // TODO(yusukes): Support non-Aura platforms like TOUCH_UI without Aura.
16 #error not supported yet
11 #endif 17 #endif
12 18
13 #include <algorithm> 19 #include <algorithm>
14 #include <cstring> 20 #include <cstring>
15 #include <set> 21 #include <set>
16 #include <vector> 22 #include <vector>
17 23
24 #include "base/command_line.h"
18 #include "base/basictypes.h" 25 #include "base/basictypes.h"
19 #include "base/command_line.h"
20 #include "base/i18n/char_iterator.h" 26 #include "base/i18n/char_iterator.h"
21 #include "base/logging.h" 27 #include "base/logging.h"
22 #include "base/string_util.h" 28 #include "base/string_util.h"
23 #include "base/third_party/icu/icu_utf.h" 29 #include "base/third_party/icu/icu_utf.h"
24 #include "base/utf_string_conversions.h" 30 #include "base/utf_string_conversions.h"
31 #include "ui/base/events.h"
32 #include "ui/base/ime/text_input_client.h"
25 #include "ui/base/keycodes/keyboard_codes.h" 33 #include "ui/base/keycodes/keyboard_codes.h"
26 #include "ui/gfx/point.h"
27 #include "ui/gfx/rect.h" 34 #include "ui/gfx/rect.h"
28 #include "views/events/event.h"
29 #include "views/widget/widget.h"
30 35
31 #if defined(USE_AURA) || defined(TOUCH_UI) 36 #if defined(USE_AURA)
37 #include "ui/aura/desktop.h"
38 #include "ui/aura/event.h"
32 #include "ui/base/keycodes/keyboard_code_conversion_x.h" 39 #include "ui/base/keycodes/keyboard_code_conversion_x.h"
33 #elif defined(TOOLKIT_USES_GTK)
34 #include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
35 #endif 40 #endif
36 41
37 namespace { 42 namespace {
38 43
39 // A global flag to switch the InputMethod implementation to InputMethodIBus 44 #if defined(USE_AURA)
40 bool inputmethod_ibus_enabled = false; 45 aura::KeyEvent* GetKeyEvent(gfx::NativeEvent native_key_event) {
46 DCHECK(native_key_event && (native_key_event->type() == ui::ET_KEY_PRESSED ||
47 native_key_event->type() == ui::ET_KEY_RELEASED));
48 return static_cast<aura::KeyEvent*>(native_key_event);
49 }
50 #endif
51
52 ui::KeyboardCode GetCode(gfx::NativeEvent native_key_event) {
53 #if defined(USE_AURA)
54 return GetKeyEvent(native_key_event)->key_code();
55 #else
56 NOTIMPLEMENTED();
57 return ui::VKEY_UNKNOWN;
58 #endif
59 }
41 60
42 // Converts ibus key state flags to event flags. 61 // Converts ibus key state flags to event flags.
43 int EventFlagsFromIBusState(guint32 state) { 62 int EventFlagsFromIBusState(guint32 state) {
44 return (state & IBUS_LOCK_MASK ? ui::EF_CAPS_LOCK_DOWN : 0) | 63 return (state & IBUS_LOCK_MASK ? ui::EF_CAPS_LOCK_DOWN : 0) |
45 (state & IBUS_CONTROL_MASK ? ui::EF_CONTROL_DOWN : 0) | 64 (state & IBUS_CONTROL_MASK ? ui::EF_CONTROL_DOWN : 0) |
46 (state & IBUS_SHIFT_MASK ? ui::EF_SHIFT_DOWN : 0) | 65 (state & IBUS_SHIFT_MASK ? ui::EF_SHIFT_DOWN : 0) |
47 (state & IBUS_MOD1_MASK ? ui::EF_ALT_DOWN : 0) | 66 (state & IBUS_MOD1_MASK ? ui::EF_ALT_DOWN : 0) |
48 (state & IBUS_BUTTON1_MASK ? ui::EF_LEFT_BUTTON_DOWN : 0) | 67 (state & IBUS_BUTTON1_MASK ? ui::EF_LEFT_BUTTON_DOWN : 0) |
49 (state & IBUS_BUTTON2_MASK ? ui::EF_MIDDLE_BUTTON_DOWN : 0) | 68 (state & IBUS_BUTTON2_MASK ? ui::EF_MIDDLE_BUTTON_DOWN : 0) |
50 (state & IBUS_BUTTON3_MASK ? ui::EF_RIGHT_BUTTON_DOWN : 0); 69 (state & IBUS_BUTTON3_MASK ? ui::EF_RIGHT_BUTTON_DOWN : 0);
51 } 70 }
52 71
53 // Converts event flags to ibus key state flags. 72 // Converts event flags to ibus key state flags.
54 guint32 IBusStateFromEventFlags(int flags) { 73 guint32 IBusStateFromEventFlags(int flags) {
55 return (flags & ui::EF_CAPS_LOCK_DOWN ? IBUS_LOCK_MASK : 0) | 74 return (flags & ui::EF_CAPS_LOCK_DOWN ? IBUS_LOCK_MASK : 0) |
56 (flags & ui::EF_CONTROL_DOWN ? IBUS_CONTROL_MASK : 0) | 75 (flags & ui::EF_CONTROL_DOWN ? IBUS_CONTROL_MASK : 0) |
57 (flags & ui::EF_SHIFT_DOWN ? IBUS_SHIFT_MASK : 0) | 76 (flags & ui::EF_SHIFT_DOWN ? IBUS_SHIFT_MASK : 0) |
58 (flags & ui::EF_ALT_DOWN ? IBUS_MOD1_MASK : 0) | 77 (flags & ui::EF_ALT_DOWN ? IBUS_MOD1_MASK : 0) |
59 (flags & ui::EF_LEFT_BUTTON_DOWN ? IBUS_BUTTON1_MASK : 0) | 78 (flags & ui::EF_LEFT_BUTTON_DOWN ? IBUS_BUTTON1_MASK : 0) |
60 (flags & ui::EF_MIDDLE_BUTTON_DOWN ? IBUS_BUTTON2_MASK : 0) | 79 (flags & ui::EF_MIDDLE_BUTTON_DOWN ? IBUS_BUTTON2_MASK : 0) |
61 (flags & ui::EF_RIGHT_BUTTON_DOWN ? IBUS_BUTTON3_MASK : 0); 80 (flags & ui::EF_RIGHT_BUTTON_DOWN ? IBUS_BUTTON3_MASK : 0);
62 } 81 }
63 82
64 void IBusKeyEventFromViewsKeyEvent(const views::KeyEvent& key, 83 void IBusKeyEventFromNativeKeyEvent(gfx::NativeEvent native_key_event,
65 guint32* ibus_keyval, 84 guint32* ibus_keyval,
66 guint32* ibus_keycode, 85 guint32* ibus_keycode,
67 guint32* ibus_state) { 86 guint32* ibus_state) {
68 #if defined(USE_AURA) 87 #if defined(USE_AURA)
69 // TODO(yusukes): Handle native_event()? 88 aura::KeyEvent* key = GetKeyEvent(native_key_event);
70 *ibus_keyval = ui::XKeysymForWindowsKeyCode( 89 if (key->native_event()) {
71 key.key_code(), key.IsShiftDown() ^ key.IsCapsLockDown()); 90 XKeyEvent* x_key = reinterpret_cast<XKeyEvent*>(key->native_event());
72 *ibus_keycode = 0;
73 #elif defined(TOUCH_UI)
74 if (key.native_event()) {
75 XKeyEvent* x_key = reinterpret_cast<XKeyEvent*>(key.native_event());
76 // Yes, ibus uses X11 keysym. We cannot use XLookupKeysym(), which doesn't 91 // Yes, ibus uses X11 keysym. We cannot use XLookupKeysym(), which doesn't
77 // translate Shift and CapsLock states. 92 // translate Shift and CapsLock states.
78 KeySym keysym = NoSymbol; 93 KeySym keysym = NoSymbol;
79 ::XLookupString(x_key, NULL, 0, &keysym, NULL); 94 ::XLookupString(x_key, NULL, 0, &keysym, NULL);
80 *ibus_keyval = keysym; 95 *ibus_keyval = keysym;
81 *ibus_keycode = x_key->keycode; 96 *ibus_keycode = x_key->keycode;
82 } else { 97 } else {
83 *ibus_keyval = ui::XKeysymForWindowsKeyCode( 98 *ibus_keyval = ui::XKeysymForWindowsKeyCode(
84 key.key_code(), key.IsShiftDown() ^ key.IsCapsLockDown()); 99 key->key_code(), key->IsShiftDown() ^ key->IsCapsLockDown());
85 *ibus_keycode = 0; 100 *ibus_keycode = 0;
86 } 101 }
87 #elif defined(TOOLKIT_USES_GTK) 102
88 if (key.gdk_event()) { 103 *ibus_state = IBusStateFromEventFlags(key->flags());
89 GdkEventKey* gdk_key = reinterpret_cast<GdkEventKey*>(key.gdk_event()); 104 if (key->type() == ui::ET_KEY_RELEASED)
90 *ibus_keyval = gdk_key->keyval; 105 *ibus_state |= IBUS_RELEASE_MASK;
91 *ibus_keycode = gdk_key->hardware_keycode; 106 #else
92 } else { 107 NOTIMPLEMENTED();
93 *ibus_keyval = ui::GdkKeyCodeForWindowsKeyCode( 108 *ibus_keyval = *ibus_keycode = *ibus_state = 0;
94 key.key_code(), key.IsShiftDown() ^ key.IsCapsLockDown());
95 *ibus_keycode = 0;
96 }
97 #endif 109 #endif
98
99 *ibus_state = IBusStateFromEventFlags(key.flags());
100 if (key.type() == ui::ET_KEY_RELEASED)
101 *ibus_state |= IBUS_RELEASE_MASK;
102 } 110 }
103 111
104 void ExtractCompositionTextFromIBusPreedit(IBusText* text, 112 void ExtractCompositionTextFromIBusPreedit(IBusText* text,
105 guint cursor_position, 113 guint cursor_position,
106 ui::CompositionText* composition) { 114 ui::CompositionText* composition) {
107 composition->Clear(); 115 composition->Clear();
108 composition->text = UTF8ToUTF16(text->text); 116 composition->text = UTF8ToUTF16(text->text);
109 117
110 if (composition->text.empty()) 118 if (composition->text.empty())
111 return; 119 return;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 } 175 }
168 } 176 }
169 177
170 // Use a black thin underline by default. 178 // Use a black thin underline by default.
171 if (composition->underlines.empty()) { 179 if (composition->underlines.empty()) {
172 composition->underlines.push_back(ui::CompositionUnderline( 180 composition->underlines.push_back(ui::CompositionUnderline(
173 0, length, SK_ColorBLACK, false /* thick */)); 181 0, length, SK_ColorBLACK, false /* thick */));
174 } 182 }
175 } 183 }
176 184
177 // A switch to enable InputMethodIBus
178 const char kEnableInputMethodIBusSwitch[] = "enable-inputmethod-ibus";
179
180 } // namespace 185 } // namespace
181 186
182 namespace views { 187 namespace ui {
183 188
184 // InputMethodIBus::PendingKeyEvent implementation ---------------------------- 189 // InputMethodIBus::PendingKeyEvent implementation ------------------------
185 class InputMethodIBus::PendingKeyEvent { 190 class InputMethodIBus::PendingKeyEvent {
186 public: 191 public:
187 PendingKeyEvent(InputMethodIBus* input_method, const KeyEvent& key, 192 PendingKeyEvent(InputMethodIBus* input_method,
193 gfx::NativeEvent native_key_event,
188 guint32 ibus_keyval); 194 guint32 ibus_keyval);
189 ~PendingKeyEvent(); 195 ~PendingKeyEvent();
190 196
191 // Abandon this pending key event. Its result will just be discarded. 197 // Abandon this pending key event. Its result will just be discarded.
192 void abandon() { input_method_ = NULL; } 198 void Abandon() { input_method_ = NULL; }
193 199
194 InputMethodIBus* input_method() const { return input_method_; } 200 InputMethodIBus* input_method() const { return input_method_; }
195 201
196 // Process this pending key event after we receive its result from the input 202 // Process this pending key event after we receive its result from the input
197 // method. It just call through InputMethodIBus::ProcessKeyEventPostIME(). 203 // method. It just call through InputMethodIBus::ProcessKeyEventPostIME().
198 void ProcessPostIME(bool handled); 204 void ProcessPostIME(bool handled);
199 205
200 private: 206 private:
201 InputMethodIBus* input_method_; 207 InputMethodIBus* input_method_;
202 208
203 // Complete information of a views::KeyEvent. Sadly, views::KeyEvent doesn't 209 #if defined(USE_AURA)
204 // support copy. 210 // Complete information of an aura::KeyEvent which doesn't support copy.
205 ui::EventType type_; 211 EventType type_;
206 int flags_; 212 int flags_;
207 ui::KeyboardCode key_code_; 213 KeyboardCode key_code_;
208 uint16 character_; 214 uint16 character_;
209 uint16 unmodified_character_; 215 uint16 unmodified_character_;
210 216
211 guint32 ibus_keyval_; 217 // corresponding XEvent data of an aura::KeyEvent. It's a plain struct so we
212
213 #if defined(TOUCH_UI)
214 // corresponding XEvent data of a views::KeyEvent. It's a plain struct so we
215 // can do bitwise copy. 218 // can do bitwise copy.
216 XKeyEvent x_event_; 219 XKeyEvent x_event_;
217 #endif 220 #endif
218 221
222 const guint32 ibus_keyval_;
223
219 DISALLOW_COPY_AND_ASSIGN(PendingKeyEvent); 224 DISALLOW_COPY_AND_ASSIGN(PendingKeyEvent);
220 }; 225 };
221 226
222 InputMethodIBus::PendingKeyEvent::PendingKeyEvent(InputMethodIBus* input_method, 227 InputMethodIBus::PendingKeyEvent::PendingKeyEvent(
223 const KeyEvent& key, 228 InputMethodIBus* input_method,
224 guint32 ibus_keyval) 229 gfx::NativeEvent native_key_event,
230 guint32 ibus_keyval)
225 : input_method_(input_method), 231 : input_method_(input_method),
226 type_(key.type()), 232 #if defined(USE_AURA)
227 flags_(key.flags()), 233 type_(native_key_event->type()),
228 key_code_(key.key_code()), 234 flags_(native_key_event->flags()),
229 character_(key.GetCharacter()), 235 key_code_(GetKeyEvent(native_key_event)->key_code()),
230 unmodified_character_(key.GetUnmodifiedCharacter()), 236 character_(GetKeyEvent(native_key_event)->GetCharacter()),
237 unmodified_character_(
238 GetKeyEvent(native_key_event)->GetUnmodifiedCharacter()),
239 #endif
231 ibus_keyval_(ibus_keyval) { 240 ibus_keyval_(ibus_keyval) {
232 DCHECK(input_method_); 241 DCHECK(input_method_);
233 242
234 #if defined(TOUCH_UI) 243 #if defined(USE_AURA)
235 if (key.native_event()) 244 if (native_key_event->native_event())
236 x_event_ = *reinterpret_cast<XKeyEvent*>(key.native_event()); 245 x_event_ = *reinterpret_cast<XKeyEvent*>(native_key_event->native_event());
237 else 246 else
238 memset(&x_event_, 0, sizeof(x_event_)); 247 memset(&x_event_, 0, sizeof(x_event_));
248 #else
249 NOTIMPLEMENTED();
239 #endif 250 #endif
240 } 251 }
241 252
242 InputMethodIBus::PendingKeyEvent::~PendingKeyEvent() { 253 InputMethodIBus::PendingKeyEvent::~PendingKeyEvent() {
243 if (input_method_) 254 if (input_method_)
244 input_method_->FinishPendingKeyEvent(this); 255 input_method_->FinishPendingKeyEvent(this);
245 } 256 }
246 257
247 void InputMethodIBus::PendingKeyEvent::ProcessPostIME(bool handled) { 258 void InputMethodIBus::PendingKeyEvent::ProcessPostIME(bool handled) {
248 if (!input_method_) 259 if (!input_method_)
249 return; 260 return;
250 261
251 #if defined(TOUCH_UI) 262 #if defined(USE_AURA)
252 if (x_event_.type == KeyPress || x_event_.type == KeyRelease) { 263 if (x_event_.type == KeyPress || x_event_.type == KeyRelease) {
253 KeyEvent key(reinterpret_cast<XEvent*>(&x_event_)); 264 aura::KeyEvent key(
254 input_method_->ProcessKeyEventPostIME(key, ibus_keyval_, handled); 265 reinterpret_cast<XEvent*>(&x_event_), false /* is_char */);
266 input_method_->ProcessKeyEventPostIME(&key, ibus_keyval_, handled);
255 return; 267 return;
256 } 268 }
257 #endif 269 aura::KeyEvent key(type_, key_code_, flags_);
258 KeyEvent key(type_, key_code_, flags_); 270 if (key_code_ == VKEY_UNKNOWN) {
259 if (key_code_ == ui::VKEY_UNKNOWN) {
260 key.set_character(character_); 271 key.set_character(character_);
261 key.set_unmodified_character(unmodified_character_); 272 key.set_unmodified_character(unmodified_character_);
262 } 273 }
263 input_method_->ProcessKeyEventPostIME(key, ibus_keyval_, handled); 274 input_method_->ProcessKeyEventPostIME(&key, ibus_keyval_, handled);
275 #else
276 NOTIMPLEMENTED();
277 #endif
264 } 278 }
265 279
266 // InputMethodIBus::PendingCreateICRequest implementation --------------------- 280 // InputMethodIBus::PendingCreateICRequest implementation -----------------
267 class InputMethodIBus::PendingCreateICRequest { 281 class InputMethodIBus::PendingCreateICRequest {
268 public: 282 public:
269 PendingCreateICRequest(InputMethodIBus* input_method, 283 PendingCreateICRequest(InputMethodIBus* input_method,
270 PendingCreateICRequest** request_ptr); 284 PendingCreateICRequest** request_ptr);
271 ~PendingCreateICRequest(); 285 ~PendingCreateICRequest();
272 286
273 // Abandon this pending key event. Its result will just be discarded. 287 // Abandon this pending key event. Its result will just be discarded.
274 void abandon() { 288 void Abandon() {
275 input_method_ = NULL; 289 input_method_ = NULL;
276 request_ptr_ = NULL; 290 request_ptr_ = NULL;
277 } 291 }
278 292
279 // Stores the result input context to |input_method_|, or abandon it if 293 // Stores the result input context to |input_method_|, or abandon it if
280 // |input_method_| is NULL. 294 // |input_method_| is NULL.
281 void StoreOrAbandonInputContext(IBusInputContext* ic); 295 void StoreOrAbandonInputContext(IBusInputContext* ic);
282 296
283 private: 297 private:
284 InputMethodIBus* input_method_; 298 InputMethodIBus* input_method_;
(...skipping 19 matching lines...) Expand all
304 if (input_method_) { 318 if (input_method_) {
305 input_method_->SetContext(ic); 319 input_method_->SetContext(ic);
306 } else { 320 } else {
307 // ibus_proxy_destroy() will not really release the object, we still need 321 // ibus_proxy_destroy() will not really release the object, we still need
308 // to call g_object_unref() explicitly. 322 // to call g_object_unref() explicitly.
309 ibus_proxy_destroy(reinterpret_cast<IBusProxy *>(ic)); 323 ibus_proxy_destroy(reinterpret_cast<IBusProxy *>(ic));
310 g_object_unref(ic); 324 g_object_unref(ic);
311 } 325 }
312 } 326 }
313 327
314 // InputMethodIBus implementation --------------------------------------------- 328 // InputMethodIBus implementation -----------------------------------------
315 InputMethodIBus::InputMethodIBus(internal::InputMethodDelegate* delegate) 329 InputMethodIBus::InputMethodIBus(
330 internal::InputMethodDelegate* delegate)
316 : context_(NULL), 331 : context_(NULL),
317 pending_create_ic_request_(NULL), 332 pending_create_ic_request_(NULL),
318 context_focused_(false), 333 context_focused_(false),
319 composing_text_(false), 334 composing_text_(false),
320 composition_changed_(false), 335 composition_changed_(false),
321 suppress_next_result_(false) { 336 suppress_next_result_(false) {
322 set_delegate(delegate); 337 set_delegate(delegate);
323 } 338 }
324 339
325 InputMethodIBus::~InputMethodIBus() { 340 InputMethodIBus::~InputMethodIBus() {
326 AbandonAllPendingKeyEvents(); 341 AbandonAllPendingKeyEvents();
327 DestroyContext(); 342 DestroyContext();
328 343
329 // Disconnect bus signals 344 // Disconnect bus signals
330 g_signal_handlers_disconnect_by_func( 345 g_signal_handlers_disconnect_by_func(
331 GetIBus(), reinterpret_cast<gpointer>(OnIBusConnectedThunk), this); 346 GetIBus(), reinterpret_cast<gpointer>(OnIBusConnectedThunk), this);
332 g_signal_handlers_disconnect_by_func( 347 g_signal_handlers_disconnect_by_func(
333 GetIBus(), reinterpret_cast<gpointer>(OnIBusDisconnectedThunk), this); 348 GetIBus(), reinterpret_cast<gpointer>(OnIBusDisconnectedThunk), this);
334 } 349 }
335 350
336 void InputMethodIBus::OnFocus() { 351 void InputMethodIBus::Init() {
337 DCHECK(!widget_focused());
338 InputMethodBase::OnFocus();
339 UpdateContextFocusState();
340 }
341
342 void InputMethodIBus::OnBlur() {
343 DCHECK(widget_focused());
344 ConfirmCompositionText();
345 InputMethodBase::OnBlur();
346 UpdateContextFocusState();
347 }
348
349 void InputMethodIBus::Init(Widget* widget) {
350 // Initializes the connection to ibus daemon. It may happen asynchronously, 352 // Initializes the connection to ibus daemon. It may happen asynchronously,
351 // and as soon as the connection is established, the |context_| will be 353 // and as soon as the connection is established, the |context_| will be
352 // created automatically. 354 // created automatically.
353 IBusBus* bus = GetIBus(); 355 IBusBus* bus = GetIBus();
354 356
355 // connect bus signals 357 // connect bus signals
356 g_signal_connect(bus, "connected", 358 g_signal_connect(bus, "connected",
357 G_CALLBACK(OnIBusConnectedThunk), this); 359 G_CALLBACK(OnIBusConnectedThunk), this);
358 g_signal_connect(bus, "disconnected", 360 g_signal_connect(bus, "disconnected",
359 G_CALLBACK(OnIBusDisconnectedThunk), this); 361 G_CALLBACK(OnIBusDisconnectedThunk), this);
360 362
361 // Creates the |context_| if the connection is already established. In such 363 // Creates the |context_| if the connection is already established. In such
362 // case, we will not get "connected" signal. 364 // case, we will not get "connected" signal.
363 if (ibus_bus_is_connected(bus)) 365 if (ibus_bus_is_connected(bus))
364 CreateContext(); 366 CreateContext();
365
366 InputMethodBase::Init(widget);
367 } 367 }
368 368
369 void InputMethodIBus::DispatchKeyEvent(const KeyEvent& key) { 369 void InputMethodIBus::DispatchKeyEvent(gfx::NativeEvent native_key_event) {
370 DCHECK(key.type() == ui::ET_KEY_PRESSED || key.type() == ui::ET_KEY_RELEASED); 370 DCHECK(native_key_event && (native_key_event->type() == ET_KEY_PRESSED ||
371 DCHECK(widget_focused()); 371 native_key_event->type() == ET_KEY_RELEASED));
372 372
373 guint32 ibus_keyval = 0; 373 guint32 ibus_keyval = 0;
374 guint32 ibus_keycode = 0; 374 guint32 ibus_keycode = 0;
375 guint32 ibus_state = 0; 375 guint32 ibus_state = 0;
376 IBusKeyEventFromViewsKeyEvent(key, &ibus_keyval, &ibus_keycode, &ibus_state); 376 IBusKeyEventFromNativeKeyEvent(
377 native_key_event, &ibus_keyval, &ibus_keycode, &ibus_state);
377 378
378 // If |context_| is not usable, then we can only dispatch the key event as is. 379 // If |context_| is not usable, then we can only dispatch the key event as is.
379 // We also dispatch the key event directly if the current text input type is 380 // We also dispatch the key event directly if the current text input type is
380 // ui::TEXT_INPUT_TYPE_PASSWORD, to bypass the input method. 381 // TEXT_INPUT_TYPE_PASSWORD, to bypass the input method.
381 // Note: We need to send the key event to ibus even if the |context_| is not 382 // Note: We need to send the key event to ibus even if the |context_| is not
382 // enabled, so that ibus can have a chance to enable the |context_|. 383 // enabled, so that ibus can have a chance to enable the |context_|.
383 if (!context_focused_ || 384 if (!context_focused_ ||
384 GetTextInputType() == ui::TEXT_INPUT_TYPE_PASSWORD) { 385 GetTextInputType() == TEXT_INPUT_TYPE_PASSWORD) {
385 if (key.type() == ui::ET_KEY_PRESSED) 386 if (native_key_event->type() == ET_KEY_PRESSED)
386 ProcessUnfilteredKeyPressEvent(key, ibus_keyval); 387 ProcessUnfilteredKeyPressEvent(native_key_event, ibus_keyval);
387 else 388 else
388 DispatchKeyEventPostIME(key); 389 DispatchKeyEventPostIME(native_key_event);
389 return; 390 return;
390 } 391 }
391 392
392 PendingKeyEvent* pending_key = new PendingKeyEvent(this, key, ibus_keyval); 393 PendingKeyEvent* pending_key =
394 new PendingKeyEvent(this, native_key_event, ibus_keyval);
393 pending_key_events_.insert(pending_key); 395 pending_key_events_.insert(pending_key);
394 396
395 // Note: 397 // Note:
396 // 1. We currently set timeout to -1, because ibus doesn't have a mechanism to 398 // 1. We currently set timeout to -1, because ibus doesn't have a mechanism to
397 // associate input method results to corresponding key event, thus there is 399 // associate input method results to corresponding key event, thus there is
398 // actually no way to abandon results generated by a specific key event. So we 400 // actually no way to abandon results generated by a specific key event. So we
399 // actually cannot abandon a specific key event and its result but accept 401 // actually cannot abandon a specific key event and its result but accept
400 // following key events and their results. So a timeout to abandon a key event 402 // following key events and their results. So a timeout to abandon a key event
401 // will not work. 403 // will not work.
402 // 2. We set GCancellable to NULL, because the operation of cancelling a async 404 // 2. We set GCancellable to NULL, because the operation of cancelling a async
(...skipping 10 matching lines...) Expand all
413 context_, 415 context_,
414 ibus_keyval, ibus_keycode, ibus_state, -1, NULL, 416 ibus_keyval, ibus_keycode, ibus_state, -1, NULL,
415 reinterpret_cast<GAsyncReadyCallback>(ProcessKeyEventDone), 417 reinterpret_cast<GAsyncReadyCallback>(ProcessKeyEventDone),
416 pending_key); 418 pending_key);
417 419
418 // We don't want to suppress the result generated by this key event, but it 420 // We don't want to suppress the result generated by this key event, but it
419 // may cause problem. See comment in ResetContext() method. 421 // may cause problem. See comment in ResetContext() method.
420 suppress_next_result_ = false; 422 suppress_next_result_ = false;
421 } 423 }
422 424
423 void InputMethodIBus::OnTextInputTypeChanged(View* view) { 425 void InputMethodIBus::OnTextInputTypeChanged(gfx::NativeWindow window) {
424 if (context_ && IsViewFocused(view)) { 426 if (context_ && IsWindowFocused(window)) {
425 ResetContext(); 427 ResetContext();
426 UpdateContextFocusState(); 428 UpdateContextFocusState();
427 } 429 }
428 InputMethodBase::OnTextInputTypeChanged(view); 430 InputMethodBase::OnTextInputTypeChanged(window);
429 } 431 }
430 432
431 void InputMethodIBus::OnCaretBoundsChanged(View* view) { 433 void InputMethodIBus::OnCaretBoundsChanged(gfx::NativeWindow window) {
432 if (!context_focused_ || !IsViewFocused(view)) 434 if (!context_focused_ || !IsWindowFocused(window))
433 return; 435 return;
434 436
435 // The current text input type should not be NONE if |context_| is focused. 437 // The current text input type should not be NONE if |context_| is focused.
436 DCHECK(!IsTextInputTypeNone()); 438 DCHECK(!IsTextInputTypeNone());
437 439
438 gfx::Rect rect = GetTextInputClient()->GetCaretBounds(); 440 const gfx::Rect rect = text_input_client()->GetCaretBounds();
439 gfx::Point origin = rect.origin(); 441 gfx::Point origin = rect.origin();
440 gfx::Point end = gfx::Point(rect.right(), rect.bottom()); 442 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
441 443
442 // We need to convert the origin and end points separately, in case the View 444 #if defined(USE_AURA)
443 // is scaled. 445 aura::Desktop* desktop = aura::Desktop::GetInstance();
444 View::ConvertPointToScreen(view, &origin); 446 aura::Window::ConvertPointToWindow(window, desktop, &origin);
445 View::ConvertPointToScreen(view, &end); 447 aura::Window::ConvertPointToWindow(window, desktop, &end);
448 #else
449 NOTIMPLEMENTED();
450 #endif
446 451
447 // This function runs asynchronously. 452 // This function runs asynchronously.
448 ibus_input_context_set_cursor_location( 453 ibus_input_context_set_cursor_location(
449 context_, origin.x(), origin.y(), 454 context_, origin.x(), origin.y(),
450 end.x() - origin.x(), end.y() - origin.y()); 455 end.x() - origin.x(), end.y() - origin.y());
451 } 456 }
452 457
453 void InputMethodIBus::CancelComposition(View* view) { 458 void InputMethodIBus::CancelComposition(gfx::NativeWindow window) {
454 if (context_focused_ && IsViewFocused(view)) 459 if (context_focused_ && IsWindowFocused(window))
455 ResetContext(); 460 ResetContext();
456 } 461 }
457 462
458 std::string InputMethodIBus::GetInputLocale() { 463 std::string InputMethodIBus::GetInputLocale() {
459 // Not supported. 464 // Not supported.
460 return std::string(""); 465 return "";
461 } 466 }
462 467
463 base::i18n::TextDirection InputMethodIBus::GetInputTextDirection() { 468 base::i18n::TextDirection InputMethodIBus::GetInputTextDirection() {
464 // Not supported. 469 // Not supported.
465 return base::i18n::UNKNOWN_DIRECTION; 470 return base::i18n::UNKNOWN_DIRECTION;
466 } 471 }
467 472
468 bool InputMethodIBus::IsActive() { 473 bool InputMethodIBus::IsActive() {
469 return true; 474 return true;
470 } 475 }
471 476
472 // static
473 bool InputMethodIBus::IsInputMethodIBusEnabled() {
474 #if defined(TOUCH_UI)
475 return true;
476 #else
477 return inputmethod_ibus_enabled ||
478 CommandLine::ForCurrentProcess()->HasSwitch(
479 kEnableInputMethodIBusSwitch);
480 #endif
481 }
482
483 // static
484 void InputMethodIBus::SetEnableInputMethodIBus(bool enabled) {
485 inputmethod_ibus_enabled = enabled;
486 }
487
488 void InputMethodIBus::OnWillChangeFocus(View* focused_before, View* focused) {
489 ConfirmCompositionText();
490 }
491
492 void InputMethodIBus::OnDidChangeFocus(View* focused_before, View* focused) {
493 UpdateContextFocusState();
494
495 // Force to update caret bounds, in case the View thinks that the caret
496 // bounds has not changed.
497 if (context_focused_)
498 OnCaretBoundsChanged(GetFocusedView());
499 }
500
501 void InputMethodIBus::CreateContext() { 477 void InputMethodIBus::CreateContext() {
502 DCHECK(!context_); 478 DCHECK(!context_);
503 DCHECK(GetIBus()); 479 DCHECK(GetIBus());
504 DCHECK(ibus_bus_is_connected(GetIBus())); 480 DCHECK(ibus_bus_is_connected(GetIBus()));
505 DCHECK(!pending_create_ic_request_); 481 DCHECK(!pending_create_ic_request_);
506 482
507 // Creates the input context asynchronously. 483 // Creates the input context asynchronously.
508 pending_create_ic_request_ = new PendingCreateICRequest( 484 pending_create_ic_request_ = new PendingCreateICRequest(
509 this, &pending_create_ic_request_); 485 this, &pending_create_ic_request_);
510 ibus_bus_create_input_context_async( 486 ibus_bus_create_input_context_async(
(...skipping 26 matching lines...) Expand all
537 ibus_input_context_set_capabilities(ic, caps); 513 ibus_input_context_set_capabilities(ic, caps);
538 514
539 UpdateContextFocusState(); 515 UpdateContextFocusState();
540 OnInputMethodChanged(); 516 OnInputMethodChanged();
541 } 517 }
542 518
543 void InputMethodIBus::DestroyContext() { 519 void InputMethodIBus::DestroyContext() {
544 if (pending_create_ic_request_) { 520 if (pending_create_ic_request_) {
545 DCHECK(!context_); 521 DCHECK(!context_);
546 // |pending_create_ic_request_| will be deleted in CreateInputContextDone(). 522 // |pending_create_ic_request_| will be deleted in CreateInputContextDone().
547 pending_create_ic_request_->abandon(); 523 pending_create_ic_request_->Abandon();
548 pending_create_ic_request_ = NULL; 524 pending_create_ic_request_ = NULL;
549 } else if (context_) { 525 } else if (context_) {
550 // ibus_proxy_destroy() will not really release the resource of |context_| 526 // ibus_proxy_destroy() will not really release the resource of |context_|
551 // object. We still need to handle "destroy" signal and call 527 // object. We still need to handle "destroy" signal and call
552 // g_object_unref() there. 528 // g_object_unref() there.
553 ibus_proxy_destroy(reinterpret_cast<IBusProxy *>(context_)); 529 ibus_proxy_destroy(reinterpret_cast<IBusProxy *>(context_));
554 DCHECK(!context_); 530 DCHECK(!context_);
555 } 531 }
556 } 532 }
557 533
558 void InputMethodIBus::ConfirmCompositionText() { 534 void InputMethodIBus::ConfirmCompositionText() {
559 ui::TextInputClient* client = GetTextInputClient(); 535 TextInputClient* client = text_input_client();
560 if (client && client->HasCompositionText()) 536 if (client && client->HasCompositionText())
561 client->ConfirmCompositionText(); 537 client->ConfirmCompositionText();
562 538
563 ResetContext(); 539 ResetContext();
564 } 540 }
565 541
566 void InputMethodIBus::ResetContext() { 542 void InputMethodIBus::ResetContext() {
567 if (!context_focused_ || !GetTextInputClient()) 543 if (!context_focused_ || !text_input_client())
568 return; 544 return;
569 545
570 DCHECK(widget_focused());
571 DCHECK(GetFocusedView());
572
573 // Because ibus runs in asynchronous mode, the input method may still send us 546 // Because ibus runs in asynchronous mode, the input method may still send us
574 // results after sending out the reset request, so we use a flag to discard 547 // results after sending out the reset request, so we use a flag to discard
575 // all results generated by previous key events. But because ibus does not 548 // all results generated by previous key events. But because ibus does not
576 // have a mechanism to identify each key event and corresponding results, this 549 // have a mechanism to identify each key event and corresponding results, this
577 // approach will not work for some corner cases. For example if the user types 550 // approach will not work for some corner cases. For example if the user types
578 // very fast, then the next key event may come in before the |context_| is 551 // very fast, then the next key event may come in before the |context_| is
579 // really reset. Then we actually cannot know whether or not the next 552 // really reset. Then we actually cannot know whether or not the next
580 // result should be discard. 553 // result should be discard.
581 suppress_next_result_ = true; 554 suppress_next_result_ = true;
582 555
(...skipping 18 matching lines...) Expand all
601 574
602 void InputMethodIBus::UpdateContextFocusState() { 575 void InputMethodIBus::UpdateContextFocusState() {
603 if (!context_) { 576 if (!context_) {
604 context_focused_ = false; 577 context_focused_ = false;
605 return; 578 return;
606 } 579 }
607 580
608 const bool old_context_focused = context_focused_; 581 const bool old_context_focused = context_focused_;
609 // Use switch here in case we are going to add more text input types. 582 // Use switch here in case we are going to add more text input types.
610 switch (GetTextInputType()) { 583 switch (GetTextInputType()) {
611 case ui::TEXT_INPUT_TYPE_NONE: 584 case TEXT_INPUT_TYPE_NONE:
612 case ui::TEXT_INPUT_TYPE_PASSWORD: 585 case TEXT_INPUT_TYPE_PASSWORD:
613 context_focused_ = false; 586 context_focused_ = false;
614 break; 587 break;
615 default: 588 default:
616 context_focused_ = true; 589 context_focused_ = true;
617 break; 590 break;
618 } 591 }
619 592
620 // We only focus in |context_| when the focus is in a normal textfield. 593 // We only focus in |context_| when the focus is in a normal textfield.
621 // ibus_input_context_focus_{in|out}() run asynchronously. 594 // ibus_input_context_focus_{in|out}() run asynchronously.
622 if (old_context_focused && !context_focused_) 595 if (old_context_focused && !context_focused_)
623 ibus_input_context_focus_out(context_); 596 ibus_input_context_focus_out(context_);
624 else if (!old_context_focused && context_focused_) 597 else if (!old_context_focused && context_focused_)
625 ibus_input_context_focus_in(context_); 598 ibus_input_context_focus_in(context_);
626 } 599 }
627 600
628 void InputMethodIBus::ProcessKeyEventPostIME(const KeyEvent& key, 601 void InputMethodIBus::ProcessKeyEventPostIME(gfx::NativeEvent native_key_event,
629 guint32 ibus_keyval, 602 guint32 ibus_keyval,
630 bool handled) { 603 bool handled) {
604 TextInputClient* client = text_input_client();
605
631 // If we get here without a focused text input client, then it means the key 606 // If we get here without a focused text input client, then it means the key
632 // event is sent to the global ibus input context. 607 // event is sent to the fake ibus input context.
633 if (!GetTextInputClient()) { 608 // TODO(yusukes): Can we remove this check? We no longer use the fake context.
634 DispatchKeyEventPostIME(key); 609 if (!client) {
610 DispatchKeyEventPostIME(native_key_event);
635 return; 611 return;
636 } 612 }
637 613
638 const View* old_focused_view = GetFocusedView(); 614 if (native_key_event->type() == ET_KEY_PRESSED && handled)
639 615 ProcessFilteredKeyPressEvent(native_key_event);
640 // Same reason as above DCHECK.
641 DCHECK(old_focused_view);
642
643 if (key.type() == ui::ET_KEY_PRESSED && handled)
644 ProcessFilteredKeyPressEvent(key);
645 616
646 // In case the focus was changed by the key event. The |context_| should have 617 // In case the focus was changed by the key event. The |context_| should have
647 // been reset when the focused view changed. 618 // been reset when the focused window changed.
648 if (old_focused_view != GetFocusedView()) 619 if (client != text_input_client())
649 return; 620 return;
650 621
651 if (HasInputMethodResult()) 622 if (HasInputMethodResult())
652 ProcessInputMethodResult(key, handled); 623 ProcessInputMethodResult(native_key_event, handled);
653 624
654 // In case the focus was changed when sending input method results to the 625 // In case the focus was changed when sending input method results to the
655 // focused View. 626 // focused window.
656 if (old_focused_view != GetFocusedView()) 627 if (client != text_input_client())
657 return; 628 return;
658 629
659 if (key.type() == ui::ET_KEY_PRESSED && !handled) 630 if (native_key_event->type() == ET_KEY_PRESSED && !handled)
660 ProcessUnfilteredKeyPressEvent(key, ibus_keyval); 631 ProcessUnfilteredKeyPressEvent(native_key_event, ibus_keyval);
661 else if (key.type() == ui::ET_KEY_RELEASED) 632 else if (native_key_event->type() == ET_KEY_RELEASED)
662 DispatchKeyEventPostIME(key); 633 DispatchKeyEventPostIME(native_key_event);
663 } 634 }
664 635
665 void InputMethodIBus::ProcessFilteredKeyPressEvent(const KeyEvent& key) { 636 void InputMethodIBus::ProcessFilteredKeyPressEvent(
637 gfx::NativeEvent native_key_event) {
666 if (NeedInsertChar()) { 638 if (NeedInsertChar()) {
667 DispatchKeyEventPostIME(key); 639 DispatchKeyEventPostIME(native_key_event);
668 } else { 640 } else {
669 KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, key.flags()); 641 #if defined(USE_AURA)
670 DispatchKeyEventPostIME(key); 642 aura::KeyEvent aura_key(
643 ET_KEY_PRESSED, VKEY_PROCESSKEY, native_key_event->flags());
644 DispatchKeyEventPostIME(&aura_key);
645 #else
646 NOTIMPLEMENTED();
647 #endif
671 } 648 }
672 } 649 }
673 650
674 void InputMethodIBus::ProcessUnfilteredKeyPressEvent(const KeyEvent& key, 651 void InputMethodIBus::ProcessUnfilteredKeyPressEvent(
675 guint32 ibus_keyval) { 652 gfx::NativeEvent native_key_event, guint32 ibus_keyval) {
676 const View* old_focused_view = GetFocusedView(); 653 TextInputClient* client = text_input_client();
677 DispatchKeyEventPostIME(key); 654 DispatchKeyEventPostIME(native_key_event);
678 655
679 // We shouldn't dispatch the character anymore if the key event caused focus 656 // We shouldn't dispatch the character anymore if the key event dispatch
680 // change. 657 // caused focus change. For example, in the following scenario,
681 if (old_focused_view != GetFocusedView()) 658 // 1. visit a web page which has a <textarea>.
659 // 2. click Omnibox.
660 // 3. enable Korean IME, press A, then press Tab to move the focus to the web
661 // page.
662 // We should return here not to send the Tab key event to RWHV.
663 if (client != text_input_client())
682 return; 664 return;
683 665
684 // Process compose and dead keys 666 // Process compose and dead keys
685 if (character_composer_.FilterKeyPress(ibus_keyval)) { 667 if (character_composer_.FilterKeyPress(ibus_keyval)) {
686 string16 composed = character_composer_.composed_character(); 668 string16 composed = character_composer_.composed_character();
687 if (!composed.empty()) { 669 if (!composed.empty()) {
688 ui::TextInputClient* client = GetTextInputClient(); 670 client = text_input_client();
689 if (client) 671 if (client)
690 client->InsertText(composed); 672 client->InsertText(composed);
691 } 673 }
692 return; 674 return;
693 } 675 }
676
694 // If a key event was not filtered by |context_| and |character_composer_|, 677 // If a key event was not filtered by |context_| and |character_composer_|,
695 // then it means the key event didn't generate any result text. So we need 678 // then it means the key event didn't generate any result text. So we need
696 // to send corresponding character to the focused text input client. 679 // to send corresponding character to the focused text input client.
680 client = text_input_client();
681 const aura::KeyEvent* aura_key_event = GetKeyEvent(native_key_event);
682 const KeyboardCode code = aura_key_event->key_code();
683 const char16 ch = aura_key_event->GetCharacter();
697 684
698 ui::TextInputClient* client = GetTextInputClient(); 685 if (client && InputMethod::ShouldSendCharEventForKeyboardCode(code) && ch)
699 char16 ch = key.GetCharacter(); 686 client->InsertChar(ch, native_key_event->flags());
700 if (ch && client)
701 client->InsertChar(ch, key.flags());
702 } 687 }
703 688
704 void InputMethodIBus::ProcessInputMethodResult(const KeyEvent& key, 689 void InputMethodIBus::ProcessInputMethodResult(
705 bool handled) { 690 gfx::NativeEvent native_key_event, bool handled) {
706 ui::TextInputClient* client = GetTextInputClient(); 691 TextInputClient* client = text_input_client();
707 DCHECK(client); 692 DCHECK(client);
708 693
709 if (result_text_.length()) { 694 if (result_text_.length()) {
710 if (handled && NeedInsertChar()) { 695 if (handled && NeedInsertChar()) {
711 for (string16::const_iterator i = result_text_.begin(); 696 for (string16::const_iterator i = result_text_.begin();
712 i != result_text_.end(); ++i) { 697 i != result_text_.end(); ++i) {
713 client->InsertChar(*i, key.flags()); 698 client->InsertChar(*i, native_key_event->flags());
714 } 699 }
715 } else { 700 } else {
716 client->InsertText(result_text_); 701 client->InsertText(result_text_);
717 composing_text_ = false; 702 composing_text_ = false;
718 } 703 }
719 } 704 }
720 705
721 if (composition_changed_ && !IsTextInputTypeNone()) { 706 if (composition_changed_ && !IsTextInputTypeNone()) {
722 if (composition_.text.length()) { 707 if (composition_.text.length()) {
723 composing_text_ = true; 708 composing_text_ = true;
724 client->SetCompositionText(composition_); 709 client->SetCompositionText(composition_);
725 } else if (result_text_.empty()) { 710 } else if (result_text_.empty()) {
726 client->ClearCompositionText(); 711 client->ClearCompositionText();
727 } 712 }
728 } 713 }
729 714
730 // We should not clear composition text here, as it may belong to the next 715 // We should not clear composition text here, as it may belong to the next
731 // composition session. 716 // composition session.
732 result_text_.clear(); 717 result_text_.clear();
733 composition_changed_ = false; 718 composition_changed_ = false;
734 } 719 }
735 720
736 bool InputMethodIBus::NeedInsertChar() const { 721 bool InputMethodIBus::NeedInsertChar() const {
737 return GetTextInputClient() && 722 return text_input_client() &&
738 (IsTextInputTypeNone() || 723 (IsTextInputTypeNone() ||
739 (!composing_text_ && result_text_.length() == 1)); 724 (!composing_text_ && result_text_.length() == 1));
740 } 725 }
741 726
742 bool InputMethodIBus::HasInputMethodResult() const { 727 bool InputMethodIBus::HasInputMethodResult() const {
743 return result_text_.length() || composition_changed_; 728 return result_text_.length() || composition_changed_;
744 } 729 }
745 730
746 void InputMethodIBus::SendFakeProcessKeyEvent(bool pressed) const { 731 void InputMethodIBus::SendFakeProcessKeyEvent(bool pressed) const {
747 KeyEvent key(pressed ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED, 732 #if defined(USE_AURA)
748 ui::VKEY_PROCESSKEY, 0); 733 aura::KeyEvent key(pressed ? ET_KEY_PRESSED : ET_KEY_RELEASED,
749 DispatchKeyEventPostIME(key); 734 VKEY_PROCESSKEY, 0);
735 DispatchKeyEventPostIME(&key);
736 #else
737 NOTIMPLEMENTED();
738 #endif
750 } 739 }
751 740
752 void InputMethodIBus::FinishPendingKeyEvent(PendingKeyEvent* pending_key) { 741 void InputMethodIBus::FinishPendingKeyEvent(PendingKeyEvent* pending_key) {
753 DCHECK(pending_key_events_.count(pending_key)); 742 DCHECK(pending_key_events_.count(pending_key));
754 743
755 // |pending_key| will be deleted in ProcessKeyEventDone(). 744 // |pending_key| will be deleted in ProcessKeyEventDone().
756 pending_key_events_.erase(pending_key); 745 pending_key_events_.erase(pending_key);
757 } 746 }
758 747
759 void InputMethodIBus::AbandonAllPendingKeyEvents() { 748 void InputMethodIBus::AbandonAllPendingKeyEvents() {
760 for (std::set<PendingKeyEvent*>::iterator i = pending_key_events_.begin(); 749 for (std::set<PendingKeyEvent*>::iterator i = pending_key_events_.begin();
761 i != pending_key_events_.end(); ++i) { 750 i != pending_key_events_.end(); ++i) {
762 // The object will be deleted in ProcessKeyEventDone(). 751 // The object will be deleted in ProcessKeyEventDone().
763 (*i)->abandon(); 752 (*i)->Abandon();
764 } 753 }
765 pending_key_events_.clear(); 754 pending_key_events_.clear();
766 } 755 }
767 756
768 void InputMethodIBus::OnCommitText(IBusInputContext* context, IBusText* text) { 757 void InputMethodIBus::OnCommitText(
758 IBusInputContext* context, IBusText* text) {
769 DCHECK_EQ(context_, context); 759 DCHECK_EQ(context_, context);
770 if (suppress_next_result_ || !text || !text->text) 760 if (suppress_next_result_ || !text || !text->text)
771 return; 761 return;
772 762
773 // We need to receive input method result even if the text input type is 763 // We need to receive input method result even if the text input type is
774 // ui::TEXT_INPUT_TYPE_NONE, to make sure we can always send correct 764 // TEXT_INPUT_TYPE_NONE, to make sure we can always send correct
775 // character for each key event to the focused text input client. 765 // character for each key event to the focused text input client.
776 if (!GetTextInputClient()) 766 if (!text_input_client())
777 return; 767 return;
778 768
779 string16 utf16_text(UTF8ToUTF16(text->text)); 769 string16 utf16_text(UTF8ToUTF16(text->text));
780 770
781 // Append the text to the buffer, because commit signal might be fired 771 // Append the text to the buffer, because commit signal might be fired
782 // multiple times when processing a key event. 772 // multiple times when processing a key event.
783 result_text_.append(utf16_text); 773 result_text_.append(utf16_text);
784 774
785 // If we are not handling key event, do not bother sending text result if the 775 // If we are not handling key event, do not bother sending text result if the
786 // focused text input client does not support text input. 776 // focused text input client does not support text input.
787 if (pending_key_events_.empty() && !IsTextInputTypeNone()) { 777 if (pending_key_events_.empty() && !IsTextInputTypeNone()) {
788 SendFakeProcessKeyEvent(true); 778 SendFakeProcessKeyEvent(true);
789 GetTextInputClient()->InsertText(utf16_text); 779 text_input_client()->InsertText(utf16_text);
790 SendFakeProcessKeyEvent(false); 780 SendFakeProcessKeyEvent(false);
791 result_text_.clear(); 781 result_text_.clear();
792 } 782 }
793 } 783 }
794 784
795 void InputMethodIBus::OnForwardKeyEvent(IBusInputContext* context, 785 void InputMethodIBus::OnForwardKeyEvent(IBusInputContext* context,
796 guint keyval, 786 guint keyval,
797 guint keycode, 787 guint keycode,
798 guint state) { 788 guint state) {
799 DCHECK_EQ(context_, context); 789 DCHECK_EQ(context_, context);
800 790
801 ui::KeyboardCode key_code = ui::VKEY_UNKNOWN; 791 KeyboardCode key_code = VKEY_UNKNOWN;
802 #if defined(USE_AURA) || defined(TOUCH_UI) 792 #if defined(USE_AURA)
803 key_code = ui::KeyboardCodeFromXKeysym(keyval); 793 key_code = KeyboardCodeFromXKeysym(keyval);
804 #elif defined(TOOLKIT_USES_GTK) 794 #else
805 key_code = ui::WindowsKeyCodeForGdkKeyCode(keyval); 795 NOTIMPLEMENTED();
806 #endif 796 #endif
807 797
808 if (!key_code) 798 if (!key_code)
809 return; 799 return;
810 800
811 KeyEvent key(state & IBUS_RELEASE_MASK ? 801 #if defined(USE_AURA)
812 ui::ET_KEY_RELEASED : ui::ET_KEY_PRESSED, 802 aura::KeyEvent key(state & IBUS_RELEASE_MASK ?
813 key_code, EventFlagsFromIBusState(state)); 803 ET_KEY_RELEASED : ET_KEY_PRESSED,
804 key_code, EventFlagsFromIBusState(state));
814 805
815 // It is not clear when the input method will forward us a fake key event. 806 // It is not clear when the input method will forward us a fake key event.
816 // If there is a pending key event, then we may already received some input 807 // If there is a pending key event, then we may already received some input
817 // method results, so we dispatch this fake key event directly rather than 808 // method results, so we dispatch this fake key event directly rather than
818 // calling ProcessKeyEventPostIME(), which will clear pending input method 809 // calling ProcessKeyEventPostIME(), which will clear pending input method
819 // results. 810 // results.
820 if (key.type() == ui::ET_KEY_PRESSED) 811 if (key.type() == ET_KEY_PRESSED)
821 ProcessUnfilteredKeyPressEvent(key, keyval); 812 ProcessUnfilteredKeyPressEvent(&key, keyval);
822 else 813 else
823 DispatchKeyEventPostIME(key); 814 DispatchKeyEventPostIME(&key);
815 #else
816 NOTIMPLEMENTED();
817 #endif
824 } 818 }
825 819
826 void InputMethodIBus::OnShowPreeditText(IBusInputContext* context) { 820 void InputMethodIBus::OnShowPreeditText(IBusInputContext* context) {
827 DCHECK_EQ(context_, context); 821 DCHECK_EQ(context_, context);
828 if (suppress_next_result_ || IsTextInputTypeNone()) 822 if (suppress_next_result_ || IsTextInputTypeNone())
829 return; 823 return;
830 824
831 composing_text_ = true; 825 composing_text_ = true;
832 } 826 }
833 827
(...skipping 22 matching lines...) Expand all
856 composition_changed_ = true; 850 composition_changed_ = true;
857 851
858 // In case OnShowPreeditText() is not called. 852 // In case OnShowPreeditText() is not called.
859 if (composition_.text.length()) 853 if (composition_.text.length())
860 composing_text_ = true; 854 composing_text_ = true;
861 855
862 // If we receive a composition text without pending key event, then we need to 856 // If we receive a composition text without pending key event, then we need to
863 // send it to the focused text input client directly. 857 // send it to the focused text input client directly.
864 if (pending_key_events_.empty()) { 858 if (pending_key_events_.empty()) {
865 SendFakeProcessKeyEvent(true); 859 SendFakeProcessKeyEvent(true);
866 GetTextInputClient()->SetCompositionText(composition_); 860 text_input_client()->SetCompositionText(composition_);
867 SendFakeProcessKeyEvent(false); 861 SendFakeProcessKeyEvent(false);
868 composition_changed_ = false; 862 composition_changed_ = false;
869 composition_.Clear(); 863 composition_.Clear();
870 } 864 }
871 } 865 }
872 866
873 void InputMethodIBus::OnHidePreeditText(IBusInputContext* context) { 867 void InputMethodIBus::OnHidePreeditText(IBusInputContext* context) {
874 DCHECK_EQ(context_, context); 868 DCHECK_EQ(context_, context);
875 if (composition_.text.empty() || IsTextInputTypeNone()) 869 if (composition_.text.empty() || IsTextInputTypeNone())
876 return; 870 return;
877 871
878 // Intentionally leaves |composing_text_| unchanged. 872 // Intentionally leaves |composing_text_| unchanged.
879 composition_changed_ = true; 873 composition_changed_ = true;
880 composition_.Clear(); 874 composition_.Clear();
881 875
882 if (pending_key_events_.empty()) { 876 if (pending_key_events_.empty()) {
883 ui::TextInputClient* client = GetTextInputClient(); 877 TextInputClient* client = text_input_client();
884 if (client && client->HasCompositionText()) 878 if (client && client->HasCompositionText())
885 client->ClearCompositionText(); 879 client->ClearCompositionText();
886 composition_changed_ = false; 880 composition_changed_ = false;
887 } 881 }
888 } 882 }
889 883
890 void InputMethodIBus::OnDestroy(IBusInputContext* context) { 884 void InputMethodIBus::OnDestroy(IBusInputContext* context) {
891 DCHECK_EQ(context_, context); 885 DCHECK_EQ(context_, context);
892 g_object_unref(context_); 886 g_object_unref(context_);
893 context_ = NULL; 887 context_ = NULL;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
951 PendingCreateICRequest* data) { 945 PendingCreateICRequest* data) {
952 DCHECK_EQ(GetIBus(), bus); 946 DCHECK_EQ(GetIBus(), bus);
953 DCHECK(data); 947 DCHECK(data);
954 IBusInputContext* ic = 948 IBusInputContext* ic =
955 ibus_bus_create_input_context_async_finish(bus, res, NULL); 949 ibus_bus_create_input_context_async_finish(bus, res, NULL);
956 if (ic) 950 if (ic)
957 data->StoreOrAbandonInputContext(ic); 951 data->StoreOrAbandonInputContext(ic);
958 delete data; 952 delete data;
959 } 953 }
960 954
961 } // namespace views 955 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698