diff options
5 files changed, 117 insertions, 1 deletions
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.cc b/chrome/browser/chromeos/input_method/input_method_engine.cc index 47f6818..8edbb57 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine.cc +++ b/chrome/browser/chromeos/input_method/input_method_engine.cc @@ -11,6 +11,7 @@ #include <X11/Xutil.h> #undef FocusIn #undef FocusOut +#undef RootWindow #include <map> #include "ash/shell.h" @@ -25,7 +26,10 @@ #include "chromeos/ime/ibus_keymap.h" #include "chromeos/ime/ibus_text.h" #include "chromeos/ime/input_method_manager.h" +#include "ui/aura/root_window.h" +#include "ui/aura/window.h" #include "ui/events/event.h" +#include "ui/events/keycodes/dom4/keycode_converter.h" #include "ui/events/keycodes/keyboard_code_conversion_x.h" #include "ui/keyboard/keyboard_controller.h" @@ -196,6 +200,47 @@ bool InputMethodEngine::CommitText(int context_id, const char* text, return true; } +bool InputMethodEngine::SendKeyEvents( + int context_id, + const std::vector<KeyboardEvent>& events) { + if (!active_) { + return false; + } + if (context_id != context_id_ || context_id_ == -1) { + return false; + } + + aura::WindowEventDispatcher* dispatcher = + ash::Shell::GetPrimaryRootWindow()->GetDispatcher(); + + for (size_t i = 0; i < events.size(); ++i) { + const KeyboardEvent& event = events[i]; + const ui::EventType type = + (event.type == "keyup") ? ui::ET_KEY_RELEASED : ui::ET_KEY_PRESSED; + + // KeyboardCodeFromXKyeSym assumes US keyboard layout. + ui::KeycodeConverter* conv = ui::KeycodeConverter::GetInstance(); + DCHECK(conv); + + // DOM code (KeyA) -> XKB -> XKeySym (XK_A) -> KeyboardCode (VKEY_A) + const uint16 native_keycode = + conv->CodeToNativeKeycode(event.code.c_str()); + const uint xkeysym = ui::DefaultXKeysymFromHardwareKeycode(native_keycode); + const ui::KeyboardCode key_code = ui::KeyboardCodeFromXKeysym(xkeysym); + + const std::string code = event.code; + int flags = ui::EF_NONE; + flags |= event.alt_key ? ui::EF_ALT_DOWN : ui::EF_NONE; + flags |= event.ctrl_key ? ui::EF_CONTROL_DOWN : ui::EF_NONE; + flags |= event.shift_key ? ui::EF_SHIFT_DOWN : ui::EF_NONE; + flags |= event.caps_lock ? ui::EF_CAPS_LOCK_DOWN : ui::EF_NONE; + + ui::KeyEvent ui_event(type, key_code, code, flags, false /* is_char */); + dispatcher->AsRootWindowHostDelegate()->OnHostKeyEvent(&ui_event); + } + return true; +} + const InputMethodEngine::CandidateWindowProperty& InputMethodEngine::GetCandidateWindowProperty() const { return candidate_window_property_; diff --git a/chrome/browser/chromeos/input_method/input_method_engine.h b/chrome/browser/chromeos/input_method/input_method_engine.h index e53cfb0..b49d1de 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine.h +++ b/chrome/browser/chromeos/input_method/input_method_engine.h @@ -53,6 +53,8 @@ class InputMethodEngine : public InputMethodEngineInterface { virtual bool ClearComposition(int context_id, std::string* error) OVERRIDE; virtual bool CommitText(int context_id, const char* text, std::string* error) OVERRIDE; + virtual bool SendKeyEvents(int context_id, + const std::vector<KeyboardEvent>& events) OVERRIDE; virtual const CandidateWindowProperty& GetCandidateWindowProperty() const OVERRIDE; virtual void SetCandidateWindowProperty( diff --git a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc index 62a1ce52..d7c6b87 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc +++ b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc @@ -403,6 +403,40 @@ IN_PROC_BROWSER_TEST_P(InputMethodEngineIBusBrowserTest, EXPECT_EQ("COMMIT_TEXT", mock_input_context->last_commit_text()); } { + SCOPED_TRACE("sendKeyEvents test"); + mock_input_context->Reset(); + mock_candidate_window->Reset(); + + const char send_key_events_test_script[] = + "chrome.input.ime.sendKeyEvents({" + " contextID: engineBridge.getFocusedContextID().contextID," + " keyData : [{" + " type : 'keydown'," + " requestId : '0'," + " key : 'z'," + " code : 'KeyZ'," + " },{" + " type : 'keyup'," + " requestId : '1'," + " key : 'z'," + " code : 'KeyZ'," + " }]" + "});"; + + ExtensionTestMessageListener keyevent_listener_down( + "onKeyEvent:keydown:z:KeyZ:false:false:false:false", false); + ExtensionTestMessageListener keyevent_listener_up( + "onKeyEvent:keyup:z:KeyZ:false:false:false:false", false); + + ASSERT_TRUE(content::ExecuteScript(host->host_contents(), + send_key_events_test_script)); + + ASSERT_TRUE(keyevent_listener_down.WaitUntilSatisfied()); + EXPECT_TRUE(keyevent_listener_down.was_satisfied()); + ASSERT_TRUE(keyevent_listener_up.WaitUntilSatisfied()); + EXPECT_TRUE(keyevent_listener_up.was_satisfied()); + } + { SCOPED_TRACE("setComposition test"); mock_input_context->Reset(); mock_candidate_window->Reset(); diff --git a/chrome/browser/chromeos/input_method/input_method_engine_interface.h b/chrome/browser/chromeos/input_method/input_method_engine_interface.h index c6b0655..4fba077 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine_interface.h +++ b/chrome/browser/chromeos/input_method/input_method_engine_interface.h @@ -186,6 +186,10 @@ class InputMethodEngineInterface : public IBusEngineHandlerInterface { virtual bool CommitText(int context_id, const char* text, std::string* error) = 0; + // Send the sequence of key events. + virtual bool SendKeyEvents(int context_id, + const std::vector<KeyboardEvent>& events) = 0; + // This function returns the current property of the candidate window. // The caller can use the returned value as the default property and // modify some of specified items. diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api.cc b/chrome/browser/extensions/api/input_ime/input_ime_api.cc index 4dc97da..7e1cefb 100644 --- a/chrome/browser/extensions/api/input_ime/input_ime_api.cc +++ b/chrome/browser/extensions/api/input_ime/input_ime_api.cc @@ -512,7 +512,38 @@ bool InputImeHideInputViewFunction::RunImpl() { } bool InputImeSendKeyEventsFunction::RunImpl() { - // TODO(komatsu): Implement here. + scoped_ptr<SendKeyEvents::Params> parent_params( + SendKeyEvents::Params::Create(*args_)); + const SendKeyEvents::Params::Parameters& params = + parent_params->parameters; + chromeos::InputMethodEngineInterface* engine = + InputImeEventRouter::GetInstance()->GetActiveEngine(extension_id()); + if (!engine) { + error_ = kErrorEngineNotAvailable; + return false; + } + + const std::vector<linked_ptr<input_ime::KeyboardEvent> >& key_data = + params.key_data; + std::vector<chromeos::InputMethodEngine::KeyboardEvent> key_data_out; + + for (size_t i = 0; i < key_data.size(); ++i) { + chromeos::InputMethodEngine::KeyboardEvent event; + event.type = input_ime::KeyboardEvent::ToString(key_data[i]->type); + event.key = key_data[i]->key; + event.code = key_data[i]->code; + if (key_data[i]->alt_key) + event.alt_key = *(key_data[i]->alt_key); + if (key_data[i]->ctrl_key) + event.ctrl_key = *(key_data[i]->ctrl_key); + if (key_data[i]->shift_key) + event.shift_key = *(key_data[i]->shift_key); + if (key_data[i]->caps_lock) + event.caps_lock = *(key_data[i]->caps_lock); + key_data_out.push_back(event); + } + + engine->SendKeyEvents(params.context_id, key_data_out); return true; } |