| Index: ui/base/ime/input_method_ibus.cc
|
| diff --git a/ui/base/ime/input_method_ibus.cc b/ui/base/ime/input_method_ibus.cc
|
| index 426b799c2dbd4b1264f96bee223d3e562522d1bd..b6f6e09cad20c098a16904dbd683419f296643e5 100644
|
| --- a/ui/base/ime/input_method_ibus.cc
|
| +++ b/ui/base/ime/input_method_ibus.cc
|
| @@ -23,6 +23,7 @@
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "base/third_party/icu/icu_utf.h"
|
| #include "chromeos/dbus/ibus/ibus_text.h"
|
| +#include "chromeos/ime/ibus_keymap.h"
|
| #include "chromeos/ime/input_method_descriptor.h"
|
| #include "chromeos/ime/input_method_manager.h"
|
| #include "ui/base/ime/text_input_client.h"
|
| @@ -38,9 +39,23 @@ namespace {
|
|
|
| const int kIBusReleaseMask = 1 << 30;
|
|
|
| -XKeyEvent* GetKeyEvent(XEvent* event) {
|
| - DCHECK(event && (event->type == KeyPress || event->type == KeyRelease));
|
| - return &event->xkey;
|
| +void IBusKeyEventFromKeyEvent(const ui::KeyEvent& event,
|
| + uint32* ibus_keyval,
|
| + uint32* ibus_keycode) {
|
| + DCHECK(event.type() == ui::ET_KEY_PRESSED ||
|
| + event.type() == ui::ET_KEY_RELEASED);
|
| + if (event.HasNativeEvent()) {
|
| + XKeyEvent* x_key = &(event.native_event()->xkey);
|
| +
|
| + // Yes, ibus uses X11 keysym. We cannot use XLookupKeysym(), which
|
| + // doesn't translate Shift and CapsLock states.
|
| + KeySym keysym = NoSymbol;
|
| + ::XLookupString(x_key, NULL, 0, &keysym, NULL);
|
| + *ibus_keyval = keysym;
|
| + *ibus_keycode = x_key->keycode;
|
| + } else {
|
| + // TODO(komatsu): Fill the correct values.
|
| + }
|
| }
|
|
|
| // Converts X (and ibus) state to event flags.
|
| @@ -54,12 +69,6 @@ int EventFlagsFromXState(unsigned int state) {
|
| (state & Button3Mask ? ui::EF_RIGHT_MOUSE_BUTTON : 0);
|
| }
|
|
|
| -// Converts X state to ibus key and button state.
|
| -uint32 IBusStateFromXState(unsigned int state) {
|
| - return (state & (LockMask | ControlMask | ShiftMask | Mod1Mask |
|
| - Button1Mask | Button2Mask | Button3Mask));
|
| -}
|
| -
|
| // Converts gfx::Rect to ibus::Rect.
|
| chromeos::ibus::Rect GfxRectToIBusRect(const gfx::Rect& rect) {
|
| return chromeos::ibus::Rect(rect.x(), rect.y(), rect.width(), rect.height());
|
| @@ -120,6 +129,248 @@ chromeos::ibus::TextInputType UiToIbusTextInputType(ui::TextInputType type) {
|
| return static_cast<chromeos::ibus::TextInputType>(type);
|
| }
|
|
|
| +std::string GetIBusKeyCodeFromKeyboardCode(ui::KeyboardCode keycode) {
|
| + // See also:
|
| + // src/chrome/test/remoting/key_code_map.h
|
| + // src/chromeos/ime/ibus_keymap.cc
|
| + switch (keycode) {
|
| + case ui::VKEY_BACK: return "Backspace"; // 0x08 -> 0x16
|
| + case ui::VKEY_TAB: return "Tab"; // 0x09 -> 0x17
|
| + case ui::VKEY_BACKTAB: return ""; // 0x0A
|
| + case ui::VKEY_CLEAR: return ""; // 0x0C
|
| + case ui::VKEY_RETURN: return "Enter"; // 0x0D -> 0x24
|
| + case ui::VKEY_SHIFT: return "ShiftLeft"; // 0x10 -> 0x32
|
| + case ui::VKEY_CONTROL: return "ControlLeft"; // 0x11 -> 0x25
|
| + case ui::VKEY_MENU: return ""; // 0x12
|
| + case ui::VKEY_PAUSE: return "Pause"; // 0x13 -> 0x7F
|
| + case ui::VKEY_CAPITAL: return "CapsLock"; // 0x14 -> 0x42
|
| + case ui::VKEY_KANA: return "KanaMode"; // 0x15 -> 0x65
|
| + // case ui::VKEY_HANGUL: return "HangulMode"; // 0x15 -> 0x82
|
| + /*
|
| + case ui::VKEY_JUNJA: return "JUNJA"; // 0x17
|
| + case ui::VKEY_FINAL: return "FINAL"; // 0x18
|
| + case ui::VKEY_HANJA: return "HANJA"; // 0x19
|
| + case ui::VKEY_KANJI: return "KANJI"; // 0x19
|
| + case ui::VKEY_ESCAPE: return "ESCAPE"; // 0x1B
|
| + case ui::VKEY_CONVERT: return "CONVERT"; // 0x1C
|
| + case ui::VKEY_NONCONVERT: return "NONCONVERT"; // 0x1D
|
| + case ui::VKEY_ACCEPT: return "ACCEPT"; // 0x1E
|
| + case ui::VKEY_MODECHANGE: return "MODECHANGE"; // 0x1F
|
| + */
|
| + case ui::VKEY_SPACE: return "Space"; // 0x20 -> 0x41
|
| + /*
|
| + case ui::VKEY_PRIOR: return "PRIOR"; // 0x21
|
| + case ui::VKEY_NEXT: return "NEXT"; // 0x22
|
| + case ui::VKEY_END: return "END"; // 0x23
|
| + case ui::VKEY_HOME: return "HOME"; // 0x24
|
| + */
|
| + case ui::VKEY_LEFT: return "ArrowLeft"; // 0x25 -> 0x71
|
| + case ui::VKEY_UP: return "ArrowUp"; // 0x26 -> 0x6f
|
| + case ui::VKEY_RIGHT: return "ArrowRight"; // 0x27 -> 0x72
|
| + case ui::VKEY_DOWN: return "ArrowDown"; // 0x28 -> 0x74
|
| + /*
|
| + case ui::VKEY_SELECT: return "SELECT"; // 0x29
|
| + case ui::VKEY_PRINT: return "PRINT"; // 0x2A
|
| + case ui::VKEY_EXECUTE: return "EXECUTE"; // 0x2B
|
| + case ui::VKEY_SNAPSHOT: return "SNAPSHOT"; // 0x2C
|
| + case ui::VKEY_INSERT: return "INSERT"; // 0x2D
|
| + case ui::VKEY_DELETE: return "DELETE"; // 0x2E
|
| + case ui::VKEY_HELP: return "HELP"; // 0x2F
|
| + */
|
| + case ui::VKEY_0: return "Digit0"; // 0x30
|
| + case ui::VKEY_1: return "Digit1"; // 0x31
|
| + case ui::VKEY_2: return "Digit2"; // 0x32
|
| + case ui::VKEY_3: return "Digit3"; // 0x33
|
| + case ui::VKEY_4: return "Digit4"; // 0x34
|
| + case ui::VKEY_5: return "Digit5"; // 0x35
|
| + case ui::VKEY_6: return "Digit6"; // 0x36
|
| + case ui::VKEY_7: return "Digit7"; // 0x37
|
| + case ui::VKEY_8: return "Digit8"; // 0x38
|
| + case ui::VKEY_9: return "Digit9"; // 0x39
|
| + case ui::VKEY_A: return "KeyA"; // 0x41
|
| + case ui::VKEY_B: return "KeyB"; // 0x42
|
| + case ui::VKEY_C: return "KeyC"; // 0x43
|
| + case ui::VKEY_D: return "KeyD"; // 0x44
|
| + case ui::VKEY_E: return "KeyE"; // 0x45
|
| + case ui::VKEY_F: return "KeyF"; // 0x46
|
| + case ui::VKEY_G: return "KeyG"; // 0x47
|
| + case ui::VKEY_H: return "KeyH"; // 0x48
|
| + case ui::VKEY_I: return "KeyI"; // 0x49
|
| + case ui::VKEY_J: return "KeyJ"; // 0x4A
|
| + case ui::VKEY_K: return "KeyK"; // 0x4B
|
| + case ui::VKEY_L: return "KeyL"; // 0x4C
|
| + case ui::VKEY_M: return "KeyM"; // 0x4D
|
| + case ui::VKEY_N: return "KeyN"; // 0x4E
|
| + case ui::VKEY_O: return "KeyO"; // 0x4F
|
| + case ui::VKEY_P: return "KeyP"; // 0x50
|
| + case ui::VKEY_Q: return "KeyQ"; // 0x51
|
| + case ui::VKEY_R: return "KeyR"; // 0x52
|
| + case ui::VKEY_S: return "KeyS"; // 0x53
|
| + case ui::VKEY_T: return "KeyT"; // 0x54
|
| + case ui::VKEY_U: return "KeyU"; // 0x55
|
| + case ui::VKEY_V: return "KeyV"; // 0x56
|
| + case ui::VKEY_W: return "KeyW"; // 0x57
|
| + case ui::VKEY_X: return "KeyX"; // 0x58
|
| + case ui::VKEY_Y: return "KeyY"; // 0x59
|
| + case ui::VKEY_Z: return "KeyZ"; // 0x5A
|
| +/*
|
| + case ui::VKEY_LWIN: return "LWIN"; // 0x5B
|
| + case ui::VKEY_COMMAND: return "COMMAND"; // VKEY_LWIN // Provide the Mac name for convenience.
|
| + case ui::VKEY_RWIN: return "RWIN"; // 0x5C
|
| + case ui::VKEY_APPS: return "APPS"; // 0x5D
|
| + case ui::VKEY_SLEEP: return "SLEEP"; // 0x5F
|
| + case ui::VKEY_NUMPAD0: return "NUMPAD0"; // 0x60
|
| + case ui::VKEY_NUMPAD1: return "NUMPAD1"; // 0x61
|
| + case ui::VKEY_NUMPAD2: return "NUMPAD2"; // 0x62
|
| + case ui::VKEY_NUMPAD3: return "NUMPAD3"; // 0x63
|
| + case ui::VKEY_NUMPAD4: return "NUMPAD4"; // 0x64
|
| + case ui::VKEY_NUMPAD5: return "NUMPAD5"; // 0x65
|
| + case ui::VKEY_NUMPAD6: return "NUMPAD6"; // 0x66
|
| + case ui::VKEY_NUMPAD7: return "NUMPAD7"; // 0x67
|
| + case ui::VKEY_NUMPAD8: return "NUMPAD8"; // 0x68
|
| + case ui::VKEY_NUMPAD9: return "NUMPAD9"; // 0x69
|
| + case ui::VKEY_MULTIPLY: return "MULTIPLY"; // 0x6A
|
| + case ui::VKEY_ADD: return "ADD"; // 0x6B
|
| + case ui::VKEY_SEPARATOR: return "SEPARATOR"; // 0x6C
|
| + case ui::VKEY_SUBTRACT: return "SUBTRACT"; // 0x6D
|
| + case ui::VKEY_DECIMAL: return "DECIMAL"; // 0x6E
|
| + case ui::VKEY_DIVIDE: return "DIVIDE"; // 0x6F
|
| +*/
|
| + case ui::VKEY_F1: return "F1"; // 0x70
|
| + case ui::VKEY_F2: return "F2"; // 0x71
|
| + case ui::VKEY_F3: return "F3"; // 0x72
|
| + case ui::VKEY_F4: return "F4"; // 0x73
|
| + case ui::VKEY_F5: return "F5"; // 0x74
|
| + case ui::VKEY_F6: return "F6"; // 0x75
|
| + case ui::VKEY_F7: return "F7"; // 0x76
|
| + case ui::VKEY_F8: return "F8"; // 0x77
|
| + case ui::VKEY_F9: return "F9"; // 0x78
|
| + case ui::VKEY_F10: return "F10"; // 0x79
|
| + case ui::VKEY_F11: return "F11"; // 0x7A
|
| + case ui::VKEY_F12: return "F12"; // 0x7B
|
| + case ui::VKEY_F13: return "F13"; // 0x7C
|
| + case ui::VKEY_F14: return "F14"; // 0x7D
|
| + case ui::VKEY_F15: return "F15"; // 0x7E
|
| + case ui::VKEY_F16: return "F16"; // 0x7F
|
| + case ui::VKEY_F17: return "F17"; // 0x80
|
| + case ui::VKEY_F18: return "F18"; // 0x81
|
| + case ui::VKEY_F19: return "F19"; // 0x82
|
| + case ui::VKEY_F20: return "F20"; // 0x83
|
| + case ui::VKEY_F21: return "F21"; // 0x84
|
| + case ui::VKEY_F22: return "F22"; // 0x85
|
| + case ui::VKEY_F23: return "F23"; // 0x86
|
| + case ui::VKEY_F24: return "F24"; // 0x87
|
| +/*
|
| + case ui::VKEY_NUMLOCK: return "NUMLOCK"; // 0x90
|
| + case ui::VKEY_SCROLL: return "SCROLL"; // 0x91
|
| + case ui::VKEY_LSHIFT: return "LSHIFT"; // 0xA0
|
| + case ui::VKEY_RSHIFT: return "RSHIFT"; // 0xA1
|
| + case ui::VKEY_LCONTROL: return "LCONTROL"; // 0xA2
|
| + case ui::VKEY_RCONTROL: return "RCONTROL"; // 0xA3
|
| + case ui::VKEY_LMENU: return "LMENU"; // 0xA4
|
| + case ui::VKEY_RMENU: return "RMENU"; // 0xA5
|
| + case ui::VKEY_BROWSER_BACK: return "BROWSER_BACK"; // 0xA6
|
| + case ui::VKEY_BROWSER_FORWARD: return "BROWSER_FORWARD"; // 0xA7
|
| + case ui::VKEY_BROWSER_REFRESH: return "BROWSER_REFRESH"; // 0xA8
|
| + case ui::VKEY_BROWSER_STOP: return "BROWSER_STOP"; // 0xA9
|
| + case ui::VKEY_BROWSER_SEARCH: return "BROWSER_SEARCH"; // 0xAA
|
| + case ui::VKEY_BROWSER_FAVORITES: return "BROWSER_FAVORITES"; // 0xAB
|
| + case ui::VKEY_BROWSER_HOME: return "BROWSER_HOME"; // 0xAC
|
| + case ui::VKEY_VOLUME_MUTE: return "VOLUME_MUTE"; // 0xAD
|
| + case ui::VKEY_VOLUME_DOWN: return "VOLUME_DOWN"; // 0xAE
|
| + case ui::VKEY_VOLUME_UP: return "VOLUME_UP"; // 0xAF
|
| + case ui::VKEY_MEDIA_NEXT_TRACK: return "MEDIA_NEXT_TRACK"; // 0xB0
|
| + case ui::VKEY_MEDIA_PREV_TRACK: return "MEDIA_PREV_TRACK"; // 0xB1
|
| + case ui::VKEY_MEDIA_STOP: return "MEDIA_STOP"; // 0xB2
|
| + case ui::VKEY_MEDIA_PLAY_PAUSE: return "MEDIA_PLAY_PAUSE"; // 0xB3
|
| + case ui::VKEY_MEDIA_LAUNCH_MAIL: return "MEDIA_LAUNCH_MAIL"; // 0xB4
|
| + case ui::VKEY_MEDIA_LAUNCH_MEDIA_SELECT: return "MEDIA_LAUNCH_MEDIA_SELECT"; // 0xB5
|
| + case ui::VKEY_MEDIA_LAUNCH_APP1: return "MEDIA_LAUNCH_APP1"; // 0xB6
|
| + case ui::VKEY_MEDIA_LAUNCH_APP2: return "MEDIA_LAUNCH_APP2"; // 0xB7
|
| +*/
|
| + case ui::VKEY_OEM_1: return "Semicolon"; // 0xBA -> 0x2F
|
| + case ui::VKEY_OEM_PLUS: return "Equal"; // 0xBB -> 0x15
|
| + case ui::VKEY_OEM_COMMA: return "Comma"; // 0xBC -> 0x3B
|
| + case ui::VKEY_OEM_MINUS: return "Minus"; // 0xBD -> 0x14
|
| + case ui::VKEY_OEM_PERIOD: return "Period"; // 0xBE -> 0x3C
|
| + case ui::VKEY_OEM_2: return "Slash"; // 0xBF -> 0x3D
|
| + case ui::VKEY_OEM_3: return "Backquote"; // 0xC0 -> 0x31
|
| + case ui::VKEY_OEM_4: return "BracketLeft"; // 0xDB -> 0x22
|
| + case ui::VKEY_OEM_5: return "Backslash"; // 0xDC -> 0x33
|
| + case ui::VKEY_OEM_6: return "BracketRight"; // 0xDD -> 0x23
|
| + case ui::VKEY_OEM_7: return "Quote"; // 0xDE -> 0x30
|
| + /*
|
| + case ui::VKEY_OEM_8: return "OEM_8"; // 0xDF
|
| + case ui::VKEY_OEM_102: return "OEM_102"; // 0xE2
|
| + case ui::VKEY_OEM_103: return "OEM_103"; // 0xE3 // GTV KEYCODE_MEDIA_REWIND
|
| + case ui::VKEY_OEM_104: return "OEM_104"; // 0xE4 // GTV KEYCODE_MEDIA_FAST_FORWARD
|
| + case ui::VKEY_PROCESSKEY: return "PROCESSKEY"; // 0xE5
|
| + case ui::VKEY_PACKET: return "PACKET"; // 0xE7
|
| + case ui::VKEY_DBE_SBCSCHAR: return "DBE_SBCSCHAR"; // 0xF3
|
| + case ui::VKEY_DBE_DBCSCHAR: return "DBE_DBCSCHAR"; // 0xF4
|
| + case ui::VKEY_ATTN: return "ATTN"; // 0xF6
|
| + case ui::VKEY_CRSEL: return "CRSEL"; // 0xF7
|
| + case ui::VKEY_EXSEL: return "EXSEL"; // 0xF8
|
| + case ui::VKEY_EREOF: return "EREOF"; // 0xF9
|
| + case ui::VKEY_PLAY: return "PLAY"; // 0xFA
|
| + case ui::VKEY_ZOOM: return "ZOOM"; // 0xFB
|
| + case ui::VKEY_NONAME: return "NONAME"; // 0xFC
|
| + case ui::VKEY_PA1: return "PA1"; // 0xFD
|
| + case ui::VKEY_OEM_CLEAR: return "OEM_CLEAR"; // 0xFE
|
| + case ui::VKEY_UNKNOWN: return "UNKNOWN"; // 0
|
| +
|
| + // POSIX specific VKEYs. Note that as of Windows SDK 7.1, 0x97-9F, 0xD8-DA,
|
| + // and 0xE8 are unassigned.
|
| + case ui::VKEY_WLAN: return "WLAN"; // 0x97
|
| + case ui::VKEY_POWER: return "POWER"; // 0x98
|
| + case ui::VKEY_BRIGHTNESS_DOWN: return "BRIGHTNESS_DOWN"; // 0xD8
|
| + case ui::VKEY_BRIGHTNESS_UP: return "BRIGHTNESS_UP"; // 0xD9
|
| + case ui::VKEY_KBD_BRIGHTNESS_DOWN: return "KBD_BRIGHTNESS_DOWN"; // 0xDA
|
| + case ui::VKEY_KBD_BRIGHTNESS_UP: return "KBD_BRIGHTNESS_UP"; // 0xE8
|
| +
|
| + // Windows does not have a specific key code for AltGr. We use the unused 0xE1
|
| + // (VK_OEM_AX) code to represent AltGr, matching the behaviour of Firefox on
|
| + // Linux.
|
| + case ui::VKEY_ALTGR: return "ALTGR"; // 0xE1
|
| +*/
|
| + default:
|
| + return "";
|
| + }
|
| +}
|
| +
|
| +// Return key and code of KeyboardEvent.
|
| +// See: http://developer.chrome.com/extensions/input_ime.html
|
| +void GetKeyAndCode(const ui::KeyEvent& event,
|
| + std::string *key,
|
| + std::string *code) {
|
| + DCHECK(key);
|
| + DCHECK(code);
|
| + key->clear();
|
| + code->clear();
|
| +
|
| + if (event.HasNativeEvent()) {
|
| + uint32 ibus_keyval = 0;
|
| + uint32 ibus_keycode = 0;
|
| + IBusKeyEventFromKeyEvent(event, &ibus_keyval, &ibus_keycode);
|
| +
|
| + *key = chromeos::input_method::GetIBusKey(ibus_keyval);
|
| + *code = chromeos::input_method::GetIBusKeyCode(ibus_keycode);
|
| +
|
| + } else {
|
| + // Convert ui::KeyEvent to key
|
| + const uint16 key_char16 = event.GetCharacter();
|
| + if (key_char16 != 0) {
|
| + char16 key16[2];
|
| + key16[0] = key_char16;
|
| + key16[1] = '\0';
|
| + *key = UTF16ToUTF8(key16);
|
| + }
|
| +
|
| + // Convert ui::KeyEvent to keycode
|
| + *code = GetIBusKeyCodeFromKeyboardCode(event.key_code());
|
| + }
|
| +}
|
| +
|
| } // namespace
|
|
|
| namespace ui {
|
| @@ -168,18 +419,14 @@ bool InputMethodIBus::OnUntranslatedIMEMessage(const base::NativeEvent& event,
|
| }
|
|
|
| void InputMethodIBus::ProcessKeyEventDone(uint32 id,
|
| - XEvent* event,
|
| - uint32 ibus_keyval,
|
| - uint32 ibus_keycode,
|
| - uint32 ibus_state,
|
| + ui::KeyEvent* event,
|
| bool is_handled) {
|
| DCHECK(event);
|
| - std::set<uint32>::iterator it = pending_key_events_.find(id);
|
|
|
| - if (it == pending_key_events_.end())
|
| + if (pending_key_events_.find(id) == pending_key_events_.end())
|
| return; // Abandoned key event.
|
|
|
| - if (event->type == KeyPress) {
|
| + if (event->type() == ui::ET_KEY_PRESSED) {
|
| if (is_handled) {
|
| // IME event has a priority to be handled, so that character composer
|
| // should be reset.
|
| @@ -187,31 +434,22 @@ void InputMethodIBus::ProcessKeyEventDone(uint32 id,
|
| } else {
|
| // If IME does not handle key event, passes keyevent to character composer
|
| // to be able to compose complex characters.
|
| - is_handled = ExecuteCharacterComposer(ibus_keyval, ibus_keycode,
|
| - ibus_state);
|
| + is_handled = ExecuteCharacterComposer(*event);
|
| }
|
| }
|
|
|
| - if (event->type == KeyPress || event->type == KeyRelease)
|
| - ProcessKeyEventPostIME(event, ibus_state, is_handled);
|
| + if (event->type() == ui::ET_KEY_PRESSED ||
|
| + event->type() == ui::ET_KEY_RELEASED)
|
| + ProcessKeyEventPostIME(*event, is_handled);
|
|
|
| - // Do not use |it| for erasing, ProcessKeyEventPostIME may change the
|
| - // |pending_key_events_|.
|
| pending_key_events_.erase(id);
|
| }
|
|
|
| -bool InputMethodIBus::DispatchKeyEvent(const base::NativeEvent& native_event) {
|
| - DCHECK(native_event && (native_event->type == KeyPress ||
|
| - native_event->type == KeyRelease));
|
| +bool InputMethodIBus::DispatchKeyEvent(const ui::KeyEvent& event) {
|
| + DCHECK(event.type() == ui::ET_KEY_PRESSED ||
|
| + event.type() == ui::ET_KEY_RELEASED);
|
| DCHECK(system_toplevel_window_focused());
|
|
|
| - uint32 ibus_keyval = 0;
|
| - uint32 ibus_keycode = 0;
|
| - uint32 ibus_state = 0;
|
| - IBusKeyEventFromNativeKeyEvent(
|
| - native_event,
|
| - &ibus_keyval, &ibus_keycode, &ibus_state);
|
| -
|
| // If |context_| is not usable, then we can only dispatch the key event as is.
|
| // We also dispatch the key event directly if the current text input type is
|
| // TEXT_INPUT_TYPE_PASSWORD, to bypass the input method.
|
| @@ -219,38 +457,52 @@ bool InputMethodIBus::DispatchKeyEvent(const base::NativeEvent& native_event) {
|
| // enabled, so that ibus can have a chance to enable the |context_|.
|
| if (!context_focused_ || !GetEngine() ||
|
| GetTextInputType() == TEXT_INPUT_TYPE_PASSWORD ) {
|
| - if (native_event->type == KeyPress) {
|
| - if (ExecuteCharacterComposer(ibus_keyval, ibus_keycode, ibus_state)) {
|
| - // Treating as PostIME event if character composer handles key event and
|
| - // generates some IME event,
|
| - ProcessKeyEventPostIME(native_event, ibus_state, true);
|
| + if (event.type() == ui::ET_KEY_PRESSED) {
|
| + // TODO(komatsu): Enable ExecuteCharacterComposer to work with
|
| + // with fabricated keyevents.
|
| + if (ExecuteCharacterComposer(event)) {
|
| + // Treating as PostIME event if character composer handles key
|
| + // event and generates some IME event,
|
| + ProcessKeyEventPostIME(event, true); // true == Handled.
|
| return true;
|
| }
|
| - ProcessUnfilteredKeyPressEvent(native_event, ibus_state);
|
| + ProcessUnfilteredKeyPressEvent(event);
|
| } else {
|
| - DispatchKeyEventPostIME(native_event);
|
| + DispatchKeyEventPostIME(event);
|
| }
|
| return true;
|
| }
|
|
|
| pending_key_events_.insert(current_keyevent_id_);
|
|
|
| - // Since |native_event| might be treated as XEvent whose size is bigger than
|
| - // XKeyEvent e.g. in CopyNativeEvent() in ui/events/event.cc, allocating
|
| - // |event| as XKeyEvent and casting it to XEvent is unsafe. crbug.com/151884
|
| - XEvent* event = new XEvent;
|
| - *event = *native_event;
|
| + std::string key;
|
| + std::string code;
|
| + GetKeyAndCode(event, &key, &code);
|
| +
|
| + LOG(ERROR) << "key: " << key;
|
| + LOG(ERROR) << "code: " << code;
|
| +
|
| + ui::KeyEvent* copied_event = NULL;
|
| + // TODO: Fix ui::KeyEvent itself.
|
| + if (event.HasNativeEvent()) {
|
| + copied_event = event.Copy();
|
| + } else {
|
| + copied_event = new KeyEvent(event);
|
| + }
|
| +
|
| GetEngine()->ProcessKeyEvent(
|
| - ibus_keyval,
|
| - ibus_keycode,
|
| - ibus_state,
|
| + key,
|
| + code,
|
| + event.type() == ET_KEY_PRESSED,
|
| + event.IsAltDown(),
|
| + event.IsControlDown(),
|
| + event.IsShiftDown(),
|
| + event.IsCapsLockDown(),
|
| base::Bind(&InputMethodIBus::ProcessKeyEventDone,
|
| weak_ptr_factory_.GetWeakPtr(),
|
| current_keyevent_id_,
|
| - base::Owned(event), // Pass the ownership of |event|.
|
| - ibus_keyval,
|
| - ibus_keycode,
|
| - ibus_state));
|
| + // Pass the ownership of |copied_event|.
|
| + base::Owned(copied_event)));
|
|
|
| ++current_keyevent_id_;
|
|
|
| @@ -261,17 +513,7 @@ bool InputMethodIBus::DispatchKeyEvent(const base::NativeEvent& native_event) {
|
| }
|
|
|
| bool InputMethodIBus::DispatchFabricatedKeyEvent(const ui::KeyEvent& event) {
|
| - // TODO(bryeung): The fabricated events should also pass through IME.
|
| - if (event.type() == ET_KEY_PRESSED) {
|
| - ProcessUnfilteredFabricatedKeyPressEvent(
|
| - ET_KEY_PRESSED, event.key_code(), event.flags());
|
| - } else {
|
| - DispatchFabricatedKeyEventPostIME(
|
| - ET_KEY_RELEASED,
|
| - event.key_code(),
|
| - event.flags());
|
| - }
|
| - return true;
|
| + return DispatchKeyEvent(event);
|
| }
|
|
|
| void InputMethodIBus::OnTextInputTypeChanged(const TextInputClient* client) {
|
| @@ -407,21 +649,19 @@ void InputMethodIBus::UpdateContextFocusState() {
|
| }
|
| }
|
|
|
| -void InputMethodIBus::ProcessKeyEventPostIME(
|
| - const base::NativeEvent& native_event,
|
| - uint32 ibus_state,
|
| - bool handled) {
|
| +void InputMethodIBus::ProcessKeyEventPostIME(const ui::KeyEvent& event,
|
| + bool handled) {
|
| TextInputClient* client = GetTextInputClient();
|
|
|
| if (!client) {
|
| // As ibus works asynchronously, there is a chance that the focused client
|
| // loses focus before this method gets called.
|
| - DispatchKeyEventPostIME(native_event);
|
| + DispatchKeyEventPostIME(event);
|
| return;
|
| }
|
|
|
| - if (native_event->type == KeyPress && handled)
|
| - ProcessFilteredKeyPressEvent(native_event);
|
| + if (event.type() == ui::ET_KEY_PRESSED && handled)
|
| + ProcessFilteredKeyPressEvent(event);
|
|
|
| // In case the focus was changed by the key event. The |context_| should have
|
| // been reset when the focused window changed.
|
| @@ -429,58 +669,35 @@ void InputMethodIBus::ProcessKeyEventPostIME(
|
| return;
|
|
|
| if (HasInputMethodResult())
|
| - ProcessInputMethodResult(native_event, handled);
|
| + ProcessInputMethodResult(event, handled);
|
|
|
| // In case the focus was changed when sending input method results to the
|
| // focused window.
|
| if (client != GetTextInputClient())
|
| return;
|
|
|
| - if (native_event->type == KeyPress && !handled)
|
| - ProcessUnfilteredKeyPressEvent(native_event, ibus_state);
|
| - else if (native_event->type == KeyRelease)
|
| - DispatchKeyEventPostIME(native_event);
|
| -}
|
| -
|
| -void InputMethodIBus::IBusKeyEventFromNativeKeyEvent(
|
| - const base::NativeEvent& native_event,
|
| - uint32* ibus_keyval,
|
| - uint32* ibus_keycode,
|
| - uint32* ibus_state) {
|
| - DCHECK(native_event); // A fabricated event is not supported here.
|
| - XKeyEvent* x_key = GetKeyEvent(native_event);
|
| -
|
| - // Yes, ibus uses X11 keysym. We cannot use XLookupKeysym(), which doesn't
|
| - // translate Shift and CapsLock states.
|
| - KeySym keysym = NoSymbol;
|
| - ::XLookupString(x_key, NULL, 0, &keysym, NULL);
|
| - *ibus_keyval = keysym;
|
| - *ibus_keycode = x_key->keycode;
|
| - *ibus_state = IBusStateFromXState(x_key->state);
|
| - if (native_event->type == KeyRelease)
|
| - *ibus_state |= kIBusReleaseMask;
|
| -}
|
| -
|
| -void InputMethodIBus::ProcessFilteredKeyPressEvent(
|
| - const base::NativeEvent& native_event) {
|
| - if (NeedInsertChar())
|
| - DispatchKeyEventPostIME(native_event);
|
| - else
|
| - DispatchFabricatedKeyEventPostIME(
|
| - ET_KEY_PRESSED,
|
| - VKEY_PROCESSKEY,
|
| - EventFlagsFromXState(GetKeyEvent(native_event)->state));
|
| + if (event.type() == ui::ET_KEY_PRESSED && !handled)
|
| + ProcessUnfilteredKeyPressEvent(event);
|
| + else if (event.type() == ui::ET_KEY_RELEASED)
|
| + DispatchKeyEventPostIME(event);
|
| }
|
|
|
| -void InputMethodIBus::ProcessUnfilteredKeyPressEvent(
|
| - const base::NativeEvent& native_event,
|
| - uint32 ibus_state) {
|
| - // For a fabricated event, ProcessUnfilteredFabricatedKeyPressEvent should be
|
| - // called instead.
|
| - DCHECK(native_event);
|
| +void InputMethodIBus::ProcessFilteredKeyPressEvent(const ui::KeyEvent& event) {
|
| + if (NeedInsertChar()) {
|
| + DispatchKeyEventPostIME(event);
|
| + } else {
|
| + const ui::KeyEvent fabricated_event(ET_KEY_PRESSED,
|
| + VKEY_PROCESSKEY,
|
| + event.flags(),
|
| + false); // is_char
|
| + DispatchKeyEventPostIME(fabricated_event);
|
| + }
|
| +}
|
|
|
| +void InputMethodIBus::ProcessUnfilteredKeyPressEvent(
|
| + const ui::KeyEvent& event) {
|
| TextInputClient* client = GetTextInputClient();
|
| - DispatchKeyEventPostIME(native_event);
|
| + DispatchKeyEventPostIME(event); // This may change the focus.
|
|
|
| // We shouldn't dispatch the character anymore if the key event dispatch
|
| // caused focus change. For example, in the following scenario,
|
| @@ -492,54 +709,43 @@ void InputMethodIBus::ProcessUnfilteredKeyPressEvent(
|
| if (client != GetTextInputClient())
|
| return;
|
|
|
| - const uint32 event_flags = EventFlagsFromXState(ibus_state);
|
| + DCHECK_EQ(client, GetTextInputClient());
|
| + if (!client)
|
| + return;
|
|
|
| // If a key event was not filtered by |context_| and |character_composer_|,
|
| // then it means the key event didn't generate any result text. So we need
|
| // to send corresponding character to the focused text input client.
|
| - client = GetTextInputClient();
|
| -
|
| uint16 ch = 0;
|
| - if (!(event_flags & ui::EF_CONTROL_DOWN))
|
| - ch = ui::GetCharacterFromXEvent(native_event);
|
| - if (!ch) {
|
| - ch = ui::GetCharacterFromKeyCode(
|
| - ui::KeyboardCodeFromNative(native_event), event_flags);
|
| + const uint32 event_flags = event.flags();
|
| + // TODO(komatsu): The following logic could be simplified.
|
| + if (event.HasNativeEvent()) {
|
| + const base::NativeEvent& native_event = event.native_event();
|
| +
|
| + if (!(event_flags & ui::EF_CONTROL_DOWN))
|
| + ch = ui::GetCharacterFromXEvent(native_event);
|
| + if (!ch) {
|
| + ch = ui::GetCharacterFromKeyCode(
|
| + ui::KeyboardCodeFromNative(native_event), event_flags);
|
| + }
|
| + } else {
|
| + ch = ui::GetCharacterFromKeyCode(event.key_code(), event_flags);
|
| }
|
|
|
| - if (client && ch)
|
| + if (ch)
|
| client->InsertChar(ch, event_flags);
|
| }
|
|
|
| -void InputMethodIBus::ProcessUnfilteredFabricatedKeyPressEvent(
|
| - EventType type,
|
| - KeyboardCode key_code,
|
| - int event_flags) {
|
| - TextInputClient* client = GetTextInputClient();
|
| - DispatchFabricatedKeyEventPostIME(type, key_code, event_flags);
|
| -
|
| - if (client != GetTextInputClient())
|
| - return;
|
| -
|
| - client = GetTextInputClient();
|
| - const uint16 ch = ui::GetCharacterFromKeyCode(key_code, event_flags);
|
| - if (client && ch)
|
| - client->InsertChar(ch, event_flags);
|
| -}
|
| -
|
| -void InputMethodIBus::ProcessInputMethodResult(
|
| - const base::NativeEvent& native_event,
|
| - bool handled) {
|
| +void InputMethodIBus::ProcessInputMethodResult(const ui::KeyEvent& event,
|
| + bool handled) {
|
| TextInputClient* client = GetTextInputClient();
|
| DCHECK(client);
|
|
|
| if (result_text_.length()) {
|
| if (handled && NeedInsertChar()) {
|
| - const uint32 state =
|
| - EventFlagsFromXState(GetKeyEvent(native_event)->state);
|
| for (string16::const_iterator i = result_text_.begin();
|
| i != result_text_.end(); ++i) {
|
| - client->InsertChar(*i, state);
|
| + client->InsertChar(*i, event.flags());
|
| }
|
| } else {
|
| client->InsertText(result_text_);
|
| @@ -618,11 +824,12 @@ void InputMethodIBus::ForwardKeyEvent(uint32 keyval,
|
| // method results, so we dispatch this fake key event directly rather than
|
| // calling ProcessKeyEventPostIME(), which will clear pending input method
|
| // results.
|
| + const bool kIsChar = false;
|
| + const ui::KeyEvent event(event_type, ui_key_code, event_flags, kIsChar);
|
| if (event_type == ET_KEY_PRESSED) {
|
| - ProcessUnfilteredFabricatedKeyPressEvent(event_type, ui_key_code,
|
| - event_flags);
|
| + ProcessUnfilteredKeyPressEvent(event);
|
| } else {
|
| - DispatchFabricatedKeyEventPostIME(event_type, ui_key_code, event_flags);
|
| + DispatchKeyEventPostIME(event);
|
| }
|
| }
|
|
|
| @@ -700,13 +907,19 @@ void InputMethodIBus::DeleteSurroundingText(int32 offset, uint32 length) {
|
| GetTextInputClient()->ExtendSelectionAndDelete(length, 0U);
|
| }
|
|
|
| -bool InputMethodIBus::ExecuteCharacterComposer(uint32 ibus_keyval,
|
| - uint32 ibus_keycode,
|
| - uint32 ibus_state) {
|
| +bool InputMethodIBus::ExecuteCharacterComposer(const ui::KeyEvent& event) {
|
| + // TODO(komatsu): Support fabricated events too.
|
| + if (!event.HasNativeEvent())
|
| + return false;
|
| +
|
| + uint32 ibus_keyval = 0;
|
| + uint32 ibus_keycode = 0;
|
| + IBusKeyEventFromKeyEvent(event, &ibus_keyval, &ibus_keycode);
|
| +
|
| bool consumed = character_composer_.FilterKeyPress(
|
| ibus_keyval,
|
| ibus_keycode,
|
| - EventFlagsFromXState(ibus_state));
|
| + event.flags());
|
|
|
| suppress_next_result_ = false;
|
| chromeos::IBusText preedit;
|
|
|