| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/base/ime/input_method_ibus.h" | 5 #include "ui/base/ime/input_method_ibus.h" |
| 6 | 6 |
| 7 #include <X11/X.h> | 7 #include <X11/X.h> |
| 8 #include <X11/Xlib.h> | 8 #include <X11/Xlib.h> |
| 9 #include <X11/Xutil.h> | 9 #include <X11/Xutil.h> |
| 10 #undef FocusIn | 10 #undef FocusIn |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 // http://ibus.googlecode.com/svn/docs/ibus-1.4/ibus-ibustypes.html#IBusCapabili
te | 46 // http://ibus.googlecode.com/svn/docs/ibus-1.4/ibus-ibustypes.html#IBusCapabili
te |
| 47 const uint32 kIBusCapabilityPreeditText = 1U; | 47 const uint32 kIBusCapabilityPreeditText = 1U; |
| 48 const uint32 kIBusCapabilityFocus = 8U; | 48 const uint32 kIBusCapabilityFocus = 8U; |
| 49 const uint32 kIBusCapabilitySurroundingText = 32U; | 49 const uint32 kIBusCapabilitySurroundingText = 32U; |
| 50 | 50 |
| 51 XKeyEvent* GetKeyEvent(XEvent* event) { | 51 XKeyEvent* GetKeyEvent(XEvent* event) { |
| 52 DCHECK(event && (event->type == KeyPress || event->type == KeyRelease)); | 52 DCHECK(event && (event->type == KeyPress || event->type == KeyRelease)); |
| 53 return &event->xkey; | 53 return &event->xkey; |
| 54 } | 54 } |
| 55 | 55 |
| 56 // Converts X (and ibus) flags to event flags. | 56 // Converts X (and ibus) state to event flags. |
| 57 int EventFlagsFromXFlags(unsigned int flags) { | 57 int EventFlagsFromXState(unsigned int state) { |
| 58 return (flags & LockMask ? ui::EF_CAPS_LOCK_DOWN : 0) | | 58 return (state & LockMask ? ui::EF_CAPS_LOCK_DOWN : 0) | |
| 59 (flags & ControlMask ? ui::EF_CONTROL_DOWN : 0) | | 59 (state & ControlMask ? ui::EF_CONTROL_DOWN : 0) | |
| 60 (flags & ShiftMask ? ui::EF_SHIFT_DOWN : 0) | | 60 (state & ShiftMask ? ui::EF_SHIFT_DOWN : 0) | |
| 61 (flags & Mod1Mask ? ui::EF_ALT_DOWN : 0) | | 61 (state & Mod1Mask ? ui::EF_ALT_DOWN : 0) | |
| 62 (flags & Button1Mask ? ui::EF_LEFT_MOUSE_BUTTON : 0) | | 62 (state & Button1Mask ? ui::EF_LEFT_MOUSE_BUTTON : 0) | |
| 63 (flags & Button2Mask ? ui::EF_MIDDLE_MOUSE_BUTTON : 0) | | 63 (state & Button2Mask ? ui::EF_MIDDLE_MOUSE_BUTTON : 0) | |
| 64 (flags & Button3Mask ? ui::EF_RIGHT_MOUSE_BUTTON : 0); | 64 (state & Button3Mask ? ui::EF_RIGHT_MOUSE_BUTTON : 0); |
| 65 } | 65 } |
| 66 | 66 |
| 67 // Converts X flags to ibus key state flags. | 67 // Converts X state to ibus key and button state. |
| 68 uint32 IBusStateFromXFlags(unsigned int flags) { | 68 uint32 IBusStateFromXState(unsigned int state) { |
| 69 return (flags & (LockMask | ControlMask | ShiftMask | Mod1Mask | | 69 return (state & (LockMask | ControlMask | ShiftMask | Mod1Mask | |
| 70 Button1Mask | Button2Mask | Button3Mask)); | 70 Button1Mask | Button2Mask | Button3Mask)); |
| 71 } | 71 } |
| 72 | 72 |
| 73 chromeos::IBusInputContextClient* GetInputContextClient() { | 73 chromeos::IBusInputContextClient* GetInputContextClient() { |
| 74 return chromeos::DBusThreadManager::Get()->GetIBusInputContextClient(); | 74 return chromeos::DBusThreadManager::Get()->GetIBusInputContextClient(); |
| 75 } | 75 } |
| 76 | 76 |
| 77 // Converts gfx::Rect to ibus::Rect. | 77 // Converts gfx::Rect to ibus::Rect. |
| 78 chromeos::ibus::Rect GfxRectToIBusRect(const gfx::Rect& rect) { | 78 chromeos::ibus::Rect GfxRectToIBusRect(const gfx::Rect& rect) { |
| 79 return chromeos::ibus::Rect(rect.x(), rect.y(), rect.width(), rect.height()); | 79 return chromeos::ibus::Rect(rect.x(), rect.y(), rect.width(), rect.height()); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 | 133 |
| 134 // Create the input context if the connection is already established. | 134 // Create the input context if the connection is already established. |
| 135 if (IsConnected()) | 135 if (IsConnected()) |
| 136 CreateContext(); | 136 CreateContext(); |
| 137 | 137 |
| 138 InputMethodBase::Init(focused); | 138 InputMethodBase::Init(focused); |
| 139 } | 139 } |
| 140 | 140 |
| 141 void InputMethodIBus::ProcessKeyEventDone(uint32 id, | 141 void InputMethodIBus::ProcessKeyEventDone(uint32 id, |
| 142 XEvent* event, | 142 XEvent* event, |
| 143 uint32 keyval, | 143 uint32 ibus_keyval, |
| 144 uint32 ibus_keycode, |
| 145 uint32 ibus_state, |
| 144 bool is_handled) { | 146 bool is_handled) { |
| 145 DCHECK(event); | 147 DCHECK(event); |
| 146 std::set<uint32>::iterator it = pending_key_events_.find(id); | 148 std::set<uint32>::iterator it = pending_key_events_.find(id); |
| 147 | 149 |
| 148 if (it == pending_key_events_.end()) | 150 if (it == pending_key_events_.end()) |
| 149 return; // Abandoned key event. | 151 return; // Abandoned key event. |
| 150 if (event->type == KeyPress || event->type == KeyRelease) | 152 if (event->type == KeyPress || event->type == KeyRelease) |
| 151 ProcessKeyEventPostIME(event, keyval, is_handled); | 153 ProcessKeyEventPostIME(event, ibus_keyval, ibus_keycode, ibus_state, |
| 154 is_handled); |
| 152 | 155 |
| 153 // Do not use |it| for erasing, ProcessKeyEventPostIME may change the | 156 // Do not use |it| for erasing, ProcessKeyEventPostIME may change the |
| 154 // |pending_key_events_|. | 157 // |pending_key_events_|. |
| 155 pending_key_events_.erase(id); | 158 pending_key_events_.erase(id); |
| 156 } | 159 } |
| 157 | 160 |
| 158 bool InputMethodIBus::DispatchKeyEvent(const base::NativeEvent& native_event) { | 161 bool InputMethodIBus::DispatchKeyEvent(const base::NativeEvent& native_event) { |
| 159 DCHECK(native_event && (native_event->type == KeyPress || | 162 DCHECK(native_event && (native_event->type == KeyPress || |
| 160 native_event->type == KeyRelease)); | 163 native_event->type == KeyRelease)); |
| 161 DCHECK(system_toplevel_window_focused()); | 164 DCHECK(system_toplevel_window_focused()); |
| 162 | 165 |
| 163 uint32 ibus_keyval = 0; | 166 uint32 ibus_keyval = 0; |
| 164 uint32 ibus_keycode = 0; | 167 uint32 ibus_keycode = 0; |
| 165 uint32 ibus_state = 0; | 168 uint32 ibus_state = 0; |
| 166 IBusKeyEventFromNativeKeyEvent( | 169 IBusKeyEventFromNativeKeyEvent( |
| 167 native_event, &ibus_keyval, &ibus_keycode, &ibus_state); | 170 native_event, |
| 171 &ibus_keyval, &ibus_keycode, &ibus_state); |
| 168 | 172 |
| 169 // If |context_| is not usable, then we can only dispatch the key event as is. | 173 // If |context_| is not usable, then we can only dispatch the key event as is. |
| 170 // We also dispatch the key event directly if the current text input type is | 174 // We also dispatch the key event directly if the current text input type is |
| 171 // TEXT_INPUT_TYPE_PASSWORD, to bypass the input method. | 175 // TEXT_INPUT_TYPE_PASSWORD, to bypass the input method. |
| 172 // Note: We need to send the key event to ibus even if the |context_| is not | 176 // Note: We need to send the key event to ibus even if the |context_| is not |
| 173 // enabled, so that ibus can have a chance to enable the |context_|. | 177 // enabled, so that ibus can have a chance to enable the |context_|. |
| 174 if (!context_focused_ || | 178 if (!context_focused_ || |
| 175 GetTextInputType() == TEXT_INPUT_TYPE_PASSWORD || | 179 GetTextInputType() == TEXT_INPUT_TYPE_PASSWORD || |
| 176 !GetInputContextClient() || | 180 !GetInputContextClient() || |
| 177 GetInputContextClient()->IsXKBLayout()) { | 181 GetInputContextClient()->IsXKBLayout()) { |
| 178 if (native_event->type == KeyPress) | 182 if (native_event->type == KeyPress) |
| 179 ProcessUnfilteredKeyPressEvent(native_event, ibus_keyval); | 183 ProcessUnfilteredKeyPressEvent(native_event, |
| 184 ibus_keyval, ibus_keycode, ibus_state); |
| 180 else | 185 else |
| 181 DispatchKeyEventPostIME(native_event); | 186 DispatchKeyEventPostIME(native_event); |
| 182 return true; | 187 return true; |
| 183 } | 188 } |
| 184 | 189 |
| 185 pending_key_events_.insert(current_keyevent_id_); | 190 pending_key_events_.insert(current_keyevent_id_); |
| 186 | 191 |
| 187 // Since |native_event| might be treated as XEvent whose size is bigger than | 192 // Since |native_event| might be treated as XEvent whose size is bigger than |
| 188 // XKeyEvent e.g. in CopyNativeEvent() in ui/base/events/event.cc, allocating | 193 // XKeyEvent e.g. in CopyNativeEvent() in ui/base/events/event.cc, allocating |
| 189 // |event| as XKeyEvent and casting it to XEvent is unsafe. crbug.com/151884 | 194 // |event| as XKeyEvent and casting it to XEvent is unsafe. crbug.com/151884 |
| 190 XEvent* event = new XEvent; | 195 XEvent* event = new XEvent; |
| 191 *event = *native_event; | 196 *event = *native_event; |
| 192 const chromeos::IBusInputContextClient::ProcessKeyEventCallback callback = | 197 const chromeos::IBusInputContextClient::ProcessKeyEventCallback callback = |
| 193 base::Bind(&InputMethodIBus::ProcessKeyEventDone, | 198 base::Bind(&InputMethodIBus::ProcessKeyEventDone, |
| 194 weak_ptr_factory_.GetWeakPtr(), | 199 weak_ptr_factory_.GetWeakPtr(), |
| 195 current_keyevent_id_, | 200 current_keyevent_id_, |
| 196 base::Owned(event), // Pass the ownership of |event|. | 201 base::Owned(event), // Pass the ownership of |event|. |
| 197 ibus_keyval); | 202 ibus_keyval, |
| 203 ibus_keycode, |
| 204 ibus_state); |
| 198 | 205 |
| 199 GetInputContextClient()->ProcessKeyEvent(ibus_keyval, | 206 GetInputContextClient()->ProcessKeyEvent(ibus_keyval, |
| 200 ibus_keycode, | 207 ibus_keycode, |
| 201 ibus_state, | 208 ibus_state, |
| 202 callback, | 209 callback, |
| 203 base::Bind(callback, false)); | 210 base::Bind(callback, false)); |
| 204 ++current_keyevent_id_; | 211 ++current_keyevent_id_; |
| 205 | 212 |
| 206 // We don't want to suppress the result generated by this key event, but it | 213 // We don't want to suppress the result generated by this key event, but it |
| 207 // may cause problem. See comment in ResetContext() method. | 214 // may cause problem. See comment in ResetContext() method. |
| 208 suppress_next_result_ = false; | 215 suppress_next_result_ = false; |
| 209 return true; | 216 return true; |
| 210 } | 217 } |
| 211 | 218 |
| 212 bool InputMethodIBus::DispatchFabricatedKeyEvent(const ui::KeyEvent& event) { | 219 bool InputMethodIBus::DispatchFabricatedKeyEvent(const ui::KeyEvent& event) { |
| 213 // TODO(bryeung): The fabricated events should also pass through IME. | 220 // TODO(bryeung): The fabricated events should also pass through IME. |
| 214 if (event.type() == ET_KEY_PRESSED) { | 221 if (event.type() == ET_KEY_PRESSED) { |
| 215 ProcessUnfilteredFabricatedKeyPressEvent( | 222 ProcessUnfilteredFabricatedKeyPressEvent( |
| 216 ET_KEY_PRESSED, event.key_code(), event.flags(), 0); | 223 ET_KEY_PRESSED, event.key_code(), event.flags(), 0, 0); |
| 217 } else { | 224 } else { |
| 218 DispatchFabricatedKeyEventPostIME( | 225 DispatchFabricatedKeyEventPostIME( |
| 219 ET_KEY_RELEASED, | 226 ET_KEY_RELEASED, |
| 220 event.key_code(), | 227 event.key_code(), |
| 221 event.flags()); | 228 event.flags()); |
| 222 } | 229 } |
| 223 return true; | 230 return true; |
| 224 } | 231 } |
| 225 | 232 |
| 226 void InputMethodIBus::OnTextInputTypeChanged(const TextInputClient* client) { | 233 void InputMethodIBus::OnTextInputTypeChanged(const TextInputClient* client) { |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 uint32 capability = kIBusCapabilityFocus | kIBusCapabilitySurroundingText; | 454 uint32 capability = kIBusCapabilityFocus | kIBusCapabilitySurroundingText; |
| 448 if (CanComposeInline()) | 455 if (CanComposeInline()) |
| 449 capability |= kIBusCapabilityPreeditText; | 456 capability |= kIBusCapabilityPreeditText; |
| 450 GetInputContextClient()->SetCapabilities(capability); | 457 GetInputContextClient()->SetCapabilities(capability); |
| 451 } | 458 } |
| 452 } | 459 } |
| 453 | 460 |
| 454 void InputMethodIBus::ProcessKeyEventPostIME( | 461 void InputMethodIBus::ProcessKeyEventPostIME( |
| 455 const base::NativeEvent& native_event, | 462 const base::NativeEvent& native_event, |
| 456 uint32 ibus_keyval, | 463 uint32 ibus_keyval, |
| 464 uint32 ibus_keycode, |
| 465 uint32 ibus_state, |
| 457 bool handled) { | 466 bool handled) { |
| 458 TextInputClient* client = GetTextInputClient(); | 467 TextInputClient* client = GetTextInputClient(); |
| 459 | 468 |
| 460 if (!client) { | 469 if (!client) { |
| 461 // As ibus works asynchronously, there is a chance that the focused client | 470 // As ibus works asynchronously, there is a chance that the focused client |
| 462 // loses focus before this method gets called. | 471 // loses focus before this method gets called. |
| 463 DispatchKeyEventPostIME(native_event); | 472 DispatchKeyEventPostIME(native_event); |
| 464 return; | 473 return; |
| 465 } | 474 } |
| 466 | 475 |
| 467 if (native_event->type == KeyPress && handled) | 476 if (native_event->type == KeyPress && handled) |
| 468 ProcessFilteredKeyPressEvent(native_event); | 477 ProcessFilteredKeyPressEvent(native_event); |
| 469 | 478 |
| 470 // In case the focus was changed by the key event. The |context_| should have | 479 // In case the focus was changed by the key event. The |context_| should have |
| 471 // been reset when the focused window changed. | 480 // been reset when the focused window changed. |
| 472 if (client != GetTextInputClient()) | 481 if (client != GetTextInputClient()) |
| 473 return; | 482 return; |
| 474 | 483 |
| 475 if (HasInputMethodResult()) | 484 if (HasInputMethodResult()) |
| 476 ProcessInputMethodResult(native_event, handled); | 485 ProcessInputMethodResult(native_event, handled); |
| 477 | 486 |
| 478 // In case the focus was changed when sending input method results to the | 487 // In case the focus was changed when sending input method results to the |
| 479 // focused window. | 488 // focused window. |
| 480 if (client != GetTextInputClient()) | 489 if (client != GetTextInputClient()) |
| 481 return; | 490 return; |
| 482 | 491 |
| 483 if (native_event->type == KeyPress && !handled) | 492 if (native_event->type == KeyPress && !handled) |
| 484 ProcessUnfilteredKeyPressEvent(native_event, ibus_keyval); | 493 ProcessUnfilteredKeyPressEvent(native_event, |
| 494 ibus_keyval, ibus_keycode, ibus_state); |
| 485 else if (native_event->type == KeyRelease) | 495 else if (native_event->type == KeyRelease) |
| 486 DispatchKeyEventPostIME(native_event); | 496 DispatchKeyEventPostIME(native_event); |
| 487 } | 497 } |
| 488 | 498 |
| 489 void InputMethodIBus::IBusKeyEventFromNativeKeyEvent( | 499 void InputMethodIBus::IBusKeyEventFromNativeKeyEvent( |
| 490 const base::NativeEvent& native_event, | 500 const base::NativeEvent& native_event, |
| 491 uint32* ibus_keyval, | 501 uint32* ibus_keyval, |
| 492 uint32* ibus_keycode, | 502 uint32* ibus_keycode, |
| 493 uint32* ibus_state) { | 503 uint32* ibus_state) { |
| 494 DCHECK(native_event); // A fabricated event is not supported here. | 504 DCHECK(native_event); // A fabricated event is not supported here. |
| 495 XKeyEvent* x_key = GetKeyEvent(native_event); | 505 XKeyEvent* x_key = GetKeyEvent(native_event); |
| 496 | 506 |
| 497 // Yes, ibus uses X11 keysym. We cannot use XLookupKeysym(), which doesn't | 507 // Yes, ibus uses X11 keysym. We cannot use XLookupKeysym(), which doesn't |
| 498 // translate Shift and CapsLock states. | 508 // translate Shift and CapsLock states. |
| 499 KeySym keysym = NoSymbol; | 509 KeySym keysym = NoSymbol; |
| 500 ::XLookupString(x_key, NULL, 0, &keysym, NULL); | 510 ::XLookupString(x_key, NULL, 0, &keysym, NULL); |
| 501 *ibus_keyval = keysym; | 511 *ibus_keyval = keysym; |
| 502 *ibus_keycode = x_key->keycode; | 512 *ibus_keycode = x_key->keycode; |
| 503 *ibus_state = IBusStateFromXFlags(x_key->state); | 513 *ibus_state = IBusStateFromXState(x_key->state); |
| 504 if (native_event->type == KeyRelease) | 514 if (native_event->type == KeyRelease) |
| 505 *ibus_state |= kIBusReleaseMask; | 515 *ibus_state |= kIBusReleaseMask; |
| 506 } | 516 } |
| 507 | 517 |
| 508 void InputMethodIBus::ProcessFilteredKeyPressEvent( | 518 void InputMethodIBus::ProcessFilteredKeyPressEvent( |
| 509 const base::NativeEvent& native_event) { | 519 const base::NativeEvent& native_event) { |
| 510 if (NeedInsertChar()) | 520 if (NeedInsertChar()) |
| 511 DispatchKeyEventPostIME(native_event); | 521 DispatchKeyEventPostIME(native_event); |
| 512 else | 522 else |
| 513 DispatchFabricatedKeyEventPostIME( | 523 DispatchFabricatedKeyEventPostIME( |
| 514 ET_KEY_PRESSED, | 524 ET_KEY_PRESSED, |
| 515 VKEY_PROCESSKEY, | 525 VKEY_PROCESSKEY, |
| 516 EventFlagsFromXFlags(GetKeyEvent(native_event)->state)); | 526 EventFlagsFromXState(GetKeyEvent(native_event)->state)); |
| 517 } | 527 } |
| 518 | 528 |
| 519 void InputMethodIBus::ProcessUnfilteredKeyPressEvent( | 529 void InputMethodIBus::ProcessUnfilteredKeyPressEvent( |
| 520 const base::NativeEvent& native_event, | 530 const base::NativeEvent& native_event, |
| 521 uint32 ibus_keyval) { | 531 uint32 ibus_keyval, |
| 532 uint32 ibus_keycode, |
| 533 uint32 ibus_state) { |
| 522 // For a fabricated event, ProcessUnfilteredFabricatedKeyPressEvent should be | 534 // For a fabricated event, ProcessUnfilteredFabricatedKeyPressEvent should be |
| 523 // called instead. | 535 // called instead. |
| 524 DCHECK(native_event); | 536 DCHECK(native_event); |
| 525 | 537 |
| 526 TextInputClient* client = GetTextInputClient(); | 538 TextInputClient* client = GetTextInputClient(); |
| 527 DispatchKeyEventPostIME(native_event); | 539 DispatchKeyEventPostIME(native_event); |
| 528 | 540 |
| 529 // We shouldn't dispatch the character anymore if the key event dispatch | 541 // We shouldn't dispatch the character anymore if the key event dispatch |
| 530 // caused focus change. For example, in the following scenario, | 542 // caused focus change. For example, in the following scenario, |
| 531 // 1. visit a web page which has a <textarea>. | 543 // 1. visit a web page which has a <textarea>. |
| 532 // 2. click Omnibox. | 544 // 2. click Omnibox. |
| 533 // 3. enable Korean IME, press A, then press Tab to move the focus to the web | 545 // 3. enable Korean IME, press A, then press Tab to move the focus to the web |
| 534 // page. | 546 // page. |
| 535 // We should return here not to send the Tab key event to RWHV. | 547 // We should return here not to send the Tab key event to RWHV. |
| 536 if (client != GetTextInputClient()) | 548 if (client != GetTextInputClient()) |
| 537 return; | 549 return; |
| 538 | 550 |
| 539 const uint32 state = | 551 const uint32 event_flags = EventFlagsFromXState(ibus_state); |
| 540 EventFlagsFromXFlags(GetKeyEvent(native_event)->state); | |
| 541 | 552 |
| 542 // Process compose and dead keys | 553 // Process compose and dead keys |
| 543 if (ProcessUnfilteredKeyPressEventWithCharacterComposer(ibus_keyval, state)) | 554 if (ProcessUnfilteredKeyPressEventWithCharacterComposer( |
| 555 ibus_keyval, ibus_keycode, event_flags)) |
| 544 return; | 556 return; |
| 545 | 557 |
| 546 // If a key event was not filtered by |context_| and |character_composer_|, | 558 // If a key event was not filtered by |context_| and |character_composer_|, |
| 547 // then it means the key event didn't generate any result text. So we need | 559 // then it means the key event didn't generate any result text. So we need |
| 548 // to send corresponding character to the focused text input client. | 560 // to send corresponding character to the focused text input client. |
| 549 client = GetTextInputClient(); | 561 client = GetTextInputClient(); |
| 550 | 562 |
| 551 uint16 ch = 0; | 563 uint16 ch = 0; |
| 552 if (!(state & ui::EF_CONTROL_DOWN)) | 564 if (!(event_flags & ui::EF_CONTROL_DOWN)) |
| 553 ch = ui::GetCharacterFromXEvent(native_event); | 565 ch = ui::GetCharacterFromXEvent(native_event); |
| 554 if (!ch) { | 566 if (!ch) { |
| 555 ch = ui::GetCharacterFromKeyCode( | 567 ch = ui::GetCharacterFromKeyCode( |
| 556 ui::KeyboardCodeFromNative(native_event), state); | 568 ui::KeyboardCodeFromNative(native_event), event_flags); |
| 557 } | 569 } |
| 558 | 570 |
| 559 if (client && ch) | 571 if (client && ch) |
| 560 client->InsertChar(ch, state); | 572 client->InsertChar(ch, event_flags); |
| 561 } | 573 } |
| 562 | 574 |
| 563 void InputMethodIBus::ProcessUnfilteredFabricatedKeyPressEvent( | 575 void InputMethodIBus::ProcessUnfilteredFabricatedKeyPressEvent( |
| 564 EventType type, | 576 EventType type, |
| 565 KeyboardCode key_code, | 577 KeyboardCode key_code, |
| 566 int flags, | 578 int event_flags, |
| 567 uint32 ibus_keyval) { | 579 uint32 ibus_keyval, |
| 580 uint32 ibus_keycode) { |
| 568 TextInputClient* client = GetTextInputClient(); | 581 TextInputClient* client = GetTextInputClient(); |
| 569 DispatchFabricatedKeyEventPostIME(type, key_code, flags); | 582 DispatchFabricatedKeyEventPostIME(type, key_code, event_flags); |
| 570 | 583 |
| 571 if (client != GetTextInputClient()) | 584 if (client != GetTextInputClient()) |
| 572 return; | 585 return; |
| 573 | 586 |
| 574 if (ProcessUnfilteredKeyPressEventWithCharacterComposer(ibus_keyval, flags)) | 587 if (ProcessUnfilteredKeyPressEventWithCharacterComposer( |
| 588 ibus_keyval, ibus_keycode, event_flags)) |
| 575 return; | 589 return; |
| 576 | 590 |
| 577 client = GetTextInputClient(); | 591 client = GetTextInputClient(); |
| 578 const uint16 ch = ui::GetCharacterFromKeyCode(key_code, flags); | 592 const uint16 ch = ui::GetCharacterFromKeyCode(key_code, event_flags); |
| 579 if (client && ch) | 593 if (client && ch) |
| 580 client->InsertChar(ch, flags); | 594 client->InsertChar(ch, event_flags); |
| 581 } | 595 } |
| 582 | 596 |
| 583 bool InputMethodIBus::ProcessUnfilteredKeyPressEventWithCharacterComposer( | 597 bool InputMethodIBus::ProcessUnfilteredKeyPressEventWithCharacterComposer( |
| 584 uint32 ibus_keyval, | 598 uint32 ibus_keyval, |
| 585 uint32 state) { | 599 uint32 ibus_keycode, |
| 600 int event_flags) { |
| 586 // We don't filter key presses for inappropriate input types. | 601 // We don't filter key presses for inappropriate input types. |
| 587 const TextInputType text_input_type = GetTextInputType(); | 602 const TextInputType text_input_type = GetTextInputType(); |
| 588 if (text_input_type == TEXT_INPUT_TYPE_NONE || | 603 if (text_input_type == TEXT_INPUT_TYPE_NONE || |
| 589 text_input_type == TEXT_INPUT_TYPE_PASSWORD) | 604 text_input_type == TEXT_INPUT_TYPE_PASSWORD) |
| 590 return false; | 605 return false; |
| 591 | 606 |
| 592 // Do nothing if the key press is not filtered by our composer. | 607 // Do nothing if the key press is not filtered by our composer. |
| 593 if (!character_composer_.FilterKeyPress(ibus_keyval, state)) | 608 if (!character_composer_.FilterKeyPress(ibus_keyval, ibus_keycode, |
| 609 event_flags)) |
| 594 return false; | 610 return false; |
| 595 | 611 |
| 596 TextInputClient* client = GetTextInputClient(); | 612 TextInputClient* client = GetTextInputClient(); |
| 597 if (!client) // Do nothing if we cannot get the client. | 613 if (!client) // Do nothing if we cannot get the client. |
| 598 return true; | 614 return true; |
| 599 | 615 |
| 600 // Insert composed character. | 616 // Insert composed character. |
| 601 const string16 composed = character_composer_.composed_character(); | 617 const string16 composed = character_composer_.composed_character(); |
| 602 if (!composed.empty()) { | 618 if (!composed.empty()) { |
| 603 if (composed.size() == 1) { | 619 if (composed.size() == 1) { |
| 604 client->InsertChar(composed[0], state); | 620 client->InsertChar(composed[0], event_flags); |
| 605 } else { | 621 } else { |
| 606 CompositionText composition; | 622 CompositionText composition; |
| 607 composition.text = composed; | 623 composition.text = composed; |
| 608 client->SetCompositionText(composition); | 624 client->SetCompositionText(composition); |
| 609 client->ConfirmCompositionText(); | 625 client->ConfirmCompositionText(); |
| 610 } | 626 } |
| 611 } | 627 } |
| 612 return true; | 628 return true; |
| 613 } | 629 } |
| 614 | 630 |
| 615 void InputMethodIBus::ProcessInputMethodResult( | 631 void InputMethodIBus::ProcessInputMethodResult( |
| 616 const base::NativeEvent& native_event, | 632 const base::NativeEvent& native_event, |
| 617 bool handled) { | 633 bool handled) { |
| 618 TextInputClient* client = GetTextInputClient(); | 634 TextInputClient* client = GetTextInputClient(); |
| 619 DCHECK(client); | 635 DCHECK(client); |
| 620 | 636 |
| 621 if (result_text_.length()) { | 637 if (result_text_.length()) { |
| 622 if (handled && NeedInsertChar()) { | 638 if (handled && NeedInsertChar()) { |
| 623 const uint32 state = | 639 const uint32 state = |
| 624 EventFlagsFromXFlags(GetKeyEvent(native_event)->state); | 640 EventFlagsFromXState(GetKeyEvent(native_event)->state); |
| 625 for (string16::const_iterator i = result_text_.begin(); | 641 for (string16::const_iterator i = result_text_.begin(); |
| 626 i != result_text_.end(); ++i) { | 642 i != result_text_.end(); ++i) { |
| 627 client->InsertChar(*i, state); | 643 client->InsertChar(*i, state); |
| 628 } | 644 } |
| 629 } else { | 645 } else { |
| 630 client->InsertText(result_text_); | 646 client->InsertText(result_text_); |
| 631 composing_text_ = false; | 647 composing_text_ = false; |
| 632 } | 648 } |
| 633 } | 649 } |
| 634 | 650 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 // focused text input client does not support text input. | 705 // focused text input client does not support text input. |
| 690 if (pending_key_events_.empty() && !IsTextInputTypeNone()) { | 706 if (pending_key_events_.empty() && !IsTextInputTypeNone()) { |
| 691 SendFakeProcessKeyEvent(true); | 707 SendFakeProcessKeyEvent(true); |
| 692 GetTextInputClient()->InsertText(utf16_text); | 708 GetTextInputClient()->InsertText(utf16_text); |
| 693 SendFakeProcessKeyEvent(false); | 709 SendFakeProcessKeyEvent(false); |
| 694 result_text_.clear(); | 710 result_text_.clear(); |
| 695 } | 711 } |
| 696 } | 712 } |
| 697 | 713 |
| 698 void InputMethodIBus::ForwardKeyEvent(uint32 keyval, | 714 void InputMethodIBus::ForwardKeyEvent(uint32 keyval, |
| 699 uint32 keycode, | 715 uint32 keycode, |
| 700 uint32 state) { | 716 uint32 state) { |
| 701 KeyboardCode ui_key_code = KeyboardCodeFromXKeysym(keyval); | 717 KeyboardCode ui_key_code = KeyboardCodeFromXKeysym(keyval); |
| 702 if (!ui_key_code) | 718 if (!ui_key_code) |
| 703 return; | 719 return; |
| 704 | 720 |
| 705 const EventType event_type = | 721 const EventType event_type = |
| 706 (state & kIBusReleaseMask) ? ET_KEY_RELEASED : ET_KEY_PRESSED; | 722 (state & kIBusReleaseMask) ? ET_KEY_RELEASED : ET_KEY_PRESSED; |
| 707 const int event_flags = EventFlagsFromXFlags(state); | 723 const int event_flags = EventFlagsFromXState(state); |
| 708 | 724 |
| 709 // It is not clear when the input method will forward us a fake key event. | 725 // It is not clear when the input method will forward us a fake key event. |
| 710 // If there is a pending key event, then we may already received some input | 726 // If there is a pending key event, then we may already received some input |
| 711 // method results, so we dispatch this fake key event directly rather than | 727 // method results, so we dispatch this fake key event directly rather than |
| 712 // calling ProcessKeyEventPostIME(), which will clear pending input method | 728 // calling ProcessKeyEventPostIME(), which will clear pending input method |
| 713 // results. | 729 // results. |
| 714 if (event_type == ET_KEY_PRESSED) { | 730 if (event_type == ET_KEY_PRESSED) { |
| 715 ProcessUnfilteredFabricatedKeyPressEvent( | 731 ProcessUnfilteredFabricatedKeyPressEvent( |
| 716 event_type, ui_key_code, event_flags, keyval); | 732 event_type, ui_key_code, event_flags, keyval, keycode); |
| 717 } else { | 733 } else { |
| 718 DispatchFabricatedKeyEventPostIME(event_type, ui_key_code, event_flags); | 734 DispatchFabricatedKeyEventPostIME(event_type, ui_key_code, event_flags); |
| 719 } | 735 } |
| 720 } | 736 } |
| 721 | 737 |
| 722 void InputMethodIBus::ShowPreeditText() { | 738 void InputMethodIBus::ShowPreeditText() { |
| 723 if (suppress_next_result_ || IsTextInputTypeNone()) | 739 if (suppress_next_result_ || IsTextInputTypeNone()) |
| 724 return; | 740 return; |
| 725 | 741 |
| 726 composing_text_ = true; | 742 composing_text_ = true; |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 949 } | 965 } |
| 950 | 966 |
| 951 // Use a black thin underline by default. | 967 // Use a black thin underline by default. |
| 952 if (out_composition->underlines.empty()) { | 968 if (out_composition->underlines.empty()) { |
| 953 out_composition->underlines.push_back(CompositionUnderline( | 969 out_composition->underlines.push_back(CompositionUnderline( |
| 954 0, length, SK_ColorBLACK, false /* thick */)); | 970 0, length, SK_ColorBLACK, false /* thick */)); |
| 955 } | 971 } |
| 956 } | 972 } |
| 957 | 973 |
| 958 } // namespace ui | 974 } // namespace ui |
| OLD | NEW |