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; |