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

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

Powered by Google App Engine
This is Rietveld 408576698