summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/input_method/input_method_engine.cc56
-rw-r--r--chrome/browser/chromeos/input_method/input_method_engine.h3
-rw-r--r--chrome/browser/extensions/api/input_ime/input_ime_api.cc38
-rw-r--r--chrome/browser/extensions/api/input_ime/input_ime_api.h11
-rw-r--r--chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc38
-rw-r--r--chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h12
-rw-r--r--chrome/browser/ui/input_method/input_method_engine.cc23
-rw-r--r--chrome/browser/ui/input_method/input_method_engine.h3
-rw-r--r--chrome/browser/ui/input_method/input_method_engine_base.cc34
-rw-r--r--chrome/browser/ui/input_method/input_method_engine_base.h6
-rw-r--r--chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc4
-rw-r--r--chrome/common/extensions/api/input_ime.json4
-rw-r--r--chrome/test/data/extensions/api_test/input_ime_nonchromeos/background.js18
-rw-r--r--ui/base/BUILD.gn5
-rw-r--r--ui/base/ime/chromeos/mock_ime_input_context_handler.cc2
-rw-r--r--ui/base/ime/chromeos/mock_ime_input_context_handler.h1
-rw-r--r--ui/base/ime/dummy_text_input_client.cc10
-rw-r--r--ui/base/ime/dummy_text_input_client.h7
-rw-r--r--ui/base/ime/ime_input_context_handler_interface.h4
-rw-r--r--ui/base/ime/input_method_auralinux.cc14
-rw-r--r--ui/base/ime/input_method_base.cc10
-rw-r--r--ui/base/ime/input_method_base.h5
-rw-r--r--ui/base/ime/input_method_win.cc17
-rw-r--r--ui/base/ui_base.gyp3
24 files changed, 205 insertions, 123 deletions
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.cc b/chrome/browser/chromeos/input_method/input_method_engine.cc
index 0c35000..71281f5 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine.cc
@@ -73,50 +73,6 @@ InputMethodEngine::InputMethodEngine()
InputMethodEngine::~InputMethodEngine() {}
-bool InputMethodEngine::SendKeyEvents(
- int context_id,
- const std::vector<KeyboardEvent>& events) {
- if (!IsActive()) {
- return false;
- }
- // context_id == 0, means sending key events to non-input field.
- // context_id_ == -1, means the focus is not in an input field.
- if (context_id != 0 && (context_id != context_id_ || context_id_ == -1)) {
- return false;
- }
-
- ui::EventProcessor* dispatcher =
- ash::Shell::GetPrimaryRootWindow()->GetHost()->event_processor();
-
- 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;
- ui::KeyboardCode key_code = static_cast<ui::KeyboardCode>(event.key_code);
- if (key_code == ui::VKEY_UNKNOWN)
- key_code = ui::DomKeycodeToKeyboardCode(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_ON : ui::EF_NONE;
-
- ui::KeyEvent ui_event(
- type, key_code,
- ui::KeycodeConverter::CodeStringToDomCode(event.code), flags,
- ui::KeycodeConverter::KeyStringToDomKey(event.key),
- ui::EventTimeForNow());
- base::AutoReset<const ui::KeyEvent*> reset_sent_key(&sent_key_event_,
- &ui_event);
- ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&ui_event);
- if (details.dispatcher_destroyed)
- break;
- }
-
- return true;
-}
-
const InputMethodEngine::CandidateWindowProperty&
InputMethodEngine::GetCandidateWindowProperty() const {
return candidate_window_property_;
@@ -368,4 +324,16 @@ void InputMethodEngine::CommitTextToInputContext(int context_id,
}
}
+bool InputMethodEngine::SendKeyEvent(ui::KeyEvent* event,
+ const std::string& code) {
+ DCHECK(event);
+ if (event->key_code() == ui::VKEY_UNKNOWN)
+ event->set_key_code(ui::DomKeycodeToKeyboardCode(code));
+
+ ui::EventProcessor* dispatcher =
+ ash::Shell::GetPrimaryRootWindow()->GetHost()->event_processor();
+ ui::EventDispatchDetails details = dispatcher->OnEventFromSource(event);
+ return !details.dispatcher_destroyed;
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.h b/chrome/browser/chromeos/input_method/input_method_engine.h
index 578950c..ed82dc0 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine.h
+++ b/chrome/browser/chromeos/input_method/input_method_engine.h
@@ -89,8 +89,6 @@ class InputMethodEngine : public ::input_method::InputMethodEngineBase {
~InputMethodEngine() override;
// IMEEngineHandlerInterface overrides.
- bool SendKeyEvents(int context_id,
- const std::vector<KeyboardEvent>& events) override;
bool SetCandidateWindowVisible(bool visible, std::string* error) override;
bool SetCursorPosition(int context_id,
int candidate_id,
@@ -139,6 +137,7 @@ class InputMethodEngine : public ::input_method::InputMethodEngineBase {
bool is_visible) override;
void CommitTextToInputContext(int context_id,
const std::string& text) override;
+ bool SendKeyEvent(ui::KeyEvent* event, const std::string& code) override;
// The current candidate window.
scoped_ptr<ui::CandidateWindow> candidate_window_;
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 31dc260..d2980016 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api.cc
@@ -12,9 +12,14 @@ namespace input_ime = extensions::api::input_ime;
namespace KeyEventHandled = extensions::api::input_ime::KeyEventHandled;
namespace SetComposition = extensions::api::input_ime::SetComposition;
namespace CommitText = extensions::api::input_ime::CommitText;
+namespace SendKeyEvents = extensions::api::input_ime::SendKeyEvents;
using ui::IMEEngineHandlerInterface;
using input_method::InputMethodEngineBase;
+namespace {
+const char kErrorEngineNotAvailable[] = "Engine is not available";
+const char kErrorSetKeyEventsFail[] = "Could not send key events";
+}
namespace ui {
ImeObserver::ImeObserver(const std::string& extension_id, Profile* profile)
@@ -329,6 +334,39 @@ ExtensionFunction::ResponseAction InputImeCommitTextFunction::Run() {
return RespondNow(ArgumentList(std::move(output)));
}
+ExtensionFunction::ResponseAction InputImeSendKeyEventsFunction::Run() {
+ InputImeEventRouter* event_router =
+ GetInputImeEventRouter(Profile::FromBrowserContext(browser_context()));
+ InputMethodEngineBase* engine =
+ event_router ? event_router->GetActiveEngine(extension_id()) : nullptr;
+ if (!engine)
+ return RespondNow(Error(kErrorEngineNotAvailable));
+
+ scoped_ptr<SendKeyEvents::Params> parent_params(
+ SendKeyEvents::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(parent_params);
+ const SendKeyEvents::Params::Parameters& params = parent_params->parameters;
+ const std::vector<linked_ptr<input_ime::KeyboardEvent>>& key_data =
+ params.key_data;
+ std::vector<InputMethodEngineBase::KeyboardEvent> key_data_out;
+
+ for (const auto& key_event : key_data) {
+ InputMethodEngineBase::KeyboardEvent event;
+ event.type = input_ime::ToString(key_event->type);
+ event.key = key_event->key;
+ event.code = key_event->code;
+ event.key_code = key_event->key_code.get() ? *(key_event->key_code) : 0;
+ event.alt_key = key_event->alt_key ? *(key_event->alt_key) : false;
+ event.ctrl_key = key_event->ctrl_key ? *(key_event->ctrl_key) : false;
+ event.shift_key = key_event->shift_key ? *(key_event->shift_key) : false;
+ event.caps_lock = key_event->caps_lock ? *(key_event->caps_lock) : false;
+ key_data_out.push_back(event);
+ }
+ if (!engine->SendKeyEvents(params.context_id, key_data_out))
+ return RespondNow(Error(kErrorSetKeyEventsFail));
+ return RespondNow(NoArguments());
+}
+
InputImeAPI::InputImeAPI(content::BrowserContext* context)
: browser_context_(context), extension_registry_observer_(this) {
extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api.h b/chrome/browser/extensions/api/input_ime/input_ime_api.h
index d16275d..26a56fb 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api.h
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api.h
@@ -151,6 +151,17 @@ class InputImeCommitTextFunction : public UIThreadExtensionFunction {
ResponseAction Run() override;
};
+class InputImeSendKeyEventsFunction : public UIThreadExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("input.ime.sendKeyEvents", INPUT_IME_SENDKEYEVENTS)
+
+ protected:
+ ~InputImeSendKeyEventsFunction() override {}
+
+ // UIThreadExtensionFunction:
+ ResponseAction Run() override;
+};
+
class InputImeAPI : public BrowserContextKeyedAPI,
public ExtensionRegistryObserver,
public EventRouter::Observer {
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
index eabbb1d..e2fdc7d 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -28,7 +28,6 @@ namespace input_ime = extensions::api::input_ime;
namespace DeleteSurroundingText =
extensions::api::input_ime::DeleteSurroundingText;
namespace UpdateMenuItems = extensions::api::input_ime::UpdateMenuItems;
-namespace SendKeyEvents = extensions::api::input_ime::SendKeyEvents;
namespace HideInputView = extensions::api::input_ime::HideInputView;
namespace SetMenuItems = extensions::api::input_ime::SetMenuItems;
namespace SetCursorPosition = extensions::api::input_ime::SetCursorPosition;
@@ -378,43 +377,6 @@ bool InputImeHideInputViewFunction::RunAsync() {
return true;
}
-bool InputImeSendKeyEventsFunction::RunAsync() {
- scoped_ptr<SendKeyEvents::Params> parent_params(
- SendKeyEvents::Params::Create(*args_));
- const SendKeyEvents::Params::Parameters& params =
- parent_params->parameters;
- InputMethodEngine* engine = GetActiveEngine(
- Profile::FromBrowserContext(browser_context()), extension_id());
- if (!engine) {
- error_ = kErrorEngineNotAvailable;
- return false;
- }
-
- const std::vector<linked_ptr<input_ime::KeyboardEvent> >& key_data =
- params.key_data;
- std::vector<InputMethodEngineBase::KeyboardEvent> key_data_out;
-
- for (size_t i = 0; i < key_data.size(); ++i) {
- InputMethodEngineBase::KeyboardEvent event;
- event.type = input_ime::ToString(key_data[i]->type);
- event.key = key_data[i]->key;
- event.code = key_data[i]->code;
- event.key_code = key_data[i]->key_code.get() ? *(key_data[i]->key_code) : 0;
- 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;
-}
-
bool InputImeSetCandidateWindowPropertiesFunction::RunSync() {
scoped_ptr<SetCandidateWindowProperties::Params> parent_params(
SetCandidateWindowProperties::Params::Create(*args_));
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h
index 4dc0b17..4516d68 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h
@@ -103,18 +103,6 @@ class InputImeDeleteSurroundingTextFunction : public SyncExtensionFunction {
bool RunSync() override;
};
-class InputImeSendKeyEventsFunction : public AsyncExtensionFunction {
- public:
- DECLARE_EXTENSION_FUNCTION("input.ime.sendKeyEvents",
- INPUT_IME_SENDKEYEVENTS)
-
- protected:
- ~InputImeSendKeyEventsFunction() override {}
-
- // ExtensionFunction:
- bool RunAsync() override;
-};
-
class InputImeHideInputViewFunction : public AsyncExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("input.ime.hideInputView",
diff --git a/chrome/browser/ui/input_method/input_method_engine.cc b/chrome/browser/ui/input_method/input_method_engine.cc
index a8c6214..644ad0a 100644
--- a/chrome/browser/ui/input_method/input_method_engine.cc
+++ b/chrome/browser/ui/input_method/input_method_engine.cc
@@ -8,6 +8,7 @@
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/ime_bridge.h"
#include "ui/base/ime/ime_input_context_handler_interface.h"
+#include "ui/events/keycodes/keyboard_code_conversion.h"
namespace {
@@ -30,13 +31,6 @@ InputMethodEngine::~InputMethodEngine() {
CloseImeWindows();
}
-bool InputMethodEngine::SendKeyEvents(
- int context_id,
- const std::vector<KeyboardEvent>& events) {
- // TODO(azurewei) Implement SendKeyEvents funciton
- return false;
-}
-
bool InputMethodEngine::IsActive() const {
return true;
}
@@ -189,4 +183,19 @@ ui::ImeWindow* InputMethodEngine::FindWindowById(int window_id) const {
return nullptr;
}
+bool InputMethodEngine::SendKeyEvent(ui::KeyEvent* event,
+ const std::string& code) {
+ DCHECK(event);
+ if (event->key_code() == ui::VKEY_UNKNOWN)
+ event->set_key_code(ui::DomCodeToUsLayoutKeyboardCode(event->code()));
+
+ ui::IMEInputContextHandlerInterface* input_context =
+ ui::IMEBridge::Get()->GetInputContextHandler();
+ if (!input_context)
+ return false;
+ input_context->SendKeyEvent(event);
+
+ return true;
+}
+
} // namespace input_method
diff --git a/chrome/browser/ui/input_method/input_method_engine.h b/chrome/browser/ui/input_method/input_method_engine.h
index 9710ced..adf1921 100644
--- a/chrome/browser/ui/input_method/input_method_engine.h
+++ b/chrome/browser/ui/input_method/input_method_engine.h
@@ -26,8 +26,6 @@ class InputMethodEngine : public InputMethodEngineBase,
~InputMethodEngine() override;
// ui::IMEEngineHandlerInterface:
- bool SendKeyEvents(int context_id,
- const std::vector<KeyboardEvent>& events) override;
bool IsActive() const override;
std::string GetExtensionId() const override;
@@ -54,6 +52,7 @@ class InputMethodEngine : public InputMethodEngineBase,
bool is_visible) override;
void CommitTextToInputContext(int context_id,
const std::string& text) override;
+ bool SendKeyEvent(ui::KeyEvent* ui_event, const std::string& code) override;
// ui::ImeWindowObserver:
void OnWindowDestroyed(ui::ImeWindow* ime_window) override;
diff --git a/chrome/browser/ui/input_method/input_method_engine_base.cc b/chrome/browser/ui/input_method/input_method_engine_base.cc
index 6764d7d..3257e73 100644
--- a/chrome/browser/ui/input_method/input_method_engine_base.cc
+++ b/chrome/browser/ui/input_method/input_method_engine_base.cc
@@ -27,6 +27,7 @@
#include "ui/events/event_processor.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/keyboard/keyboard_controller.h"
#include "ui/keyboard/keyboard_util.h"
@@ -419,4 +420,37 @@ std::string InputMethodEngineBase::AddRequest(
return request_id;
}
+bool InputMethodEngineBase::SendKeyEvents(
+ int context_id,
+ const std::vector<KeyboardEvent>& events) {
+ // context_id == 0, means sending key events to non-input field.
+ // context_id_ == -1, means the focus is not in an input field.
+ if (!IsActive() ||
+ (context_id != 0 && (context_id != context_id_ || context_id_ == -1)))
+ return false;
+
+ 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;
+ ui::KeyboardCode key_code = static_cast<ui::KeyboardCode>(event.key_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_ON : ui::EF_NONE;
+
+ ui::KeyEvent ui_event(
+ type, key_code, ui::KeycodeConverter::CodeStringToDomCode(event.code),
+ flags, ui::KeycodeConverter::KeyStringToDomKey(event.key),
+ ui::EventTimeForNow());
+ base::AutoReset<const ui::KeyEvent*> reset_sent_key(&sent_key_event_,
+ &ui_event);
+ if (!SendKeyEvent(&ui_event, event.code))
+ return false;
+ }
+ return true;
+}
+
} // namespace input_method
diff --git a/chrome/browser/ui/input_method/input_method_engine_base.h b/chrome/browser/ui/input_method/input_method_engine_base.h
index 1ca4a16..bdd2f40 100644
--- a/chrome/browser/ui/input_method/input_method_engine_base.h
+++ b/chrome/browser/ui/input_method/input_method_engine_base.h
@@ -154,8 +154,7 @@ class InputMethodEngineBase : virtual public ui::IMEEngineHandlerInterface {
bool IsInterestedInKeyEvent() const override;
// Send the sequence of key events.
- virtual bool SendKeyEvents(int context_id,
- const std::vector<KeyboardEvent>& events) = 0;
+ bool SendKeyEvents(int context_id, const std::vector<KeyboardEvent>& events);
// Set the current composition and associated properties.
bool SetComposition(int context_id,
@@ -186,6 +185,9 @@ class InputMethodEngineBase : virtual public ui::IMEEngineHandlerInterface {
// Notifies InputContextHanlder to commit |text|.
virtual void CommitTextToInputContext(int context_id,
const std::string& text) = 0;
+ // Sends the key event to the window tree host.
+ virtual bool SendKeyEvent(ui::KeyEvent* ui_event,
+ const std::string& code) = 0;
ui::TextInputType current_input_type_;
diff --git a/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc b/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc
index 31de3d9..e1341b9 100644
--- a/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc
+++ b/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc
@@ -38,6 +38,10 @@ IN_PROC_BROWSER_TEST_F(InputImeApiTest, CreateWindowTest) {
ASSERT_TRUE(RunExtensionTest("input_ime_nonchromeos")) << message_;
+ // Test the input.ime.sendKeyEvents API.
+ ASSERT_EQ(client->insert_char_count(), 1);
+ ASSERT_EQ(client->last_insert_char(), L'a');
+
input_method->DetachTextInputClient(client.get());
}
diff --git a/chrome/common/extensions/api/input_ime.json b/chrome/common/extensions/api/input_ime.json
index 0f981fc..4656903 100644
--- a/chrome/common/extensions/api/input_ime.json
+++ b/chrome/common/extensions/api/input_ime.json
@@ -269,7 +269,7 @@
"name": "sendKeyEvents",
"type": "function",
"description": "Sends the key events. This function is expected to be used by virtual keyboards. When key(s) on a virtual keyboard is pressed by a user, this function is used to propagate that event to the system.",
- "platforms": ["chromeos"],
+ "platforms": ["chromeos", "win", "linux"],
"parameters": [
{
"name": "parameters",
@@ -744,7 +744,7 @@
{
"name": "onKeyEvent",
"type": "function",
- "description": "This event is sent if this extension owns the active IME.",
+ "description": "Fired when a key event is sent from the operating system. The event will be sent to the extension if this extension owns the active IME.",
"platforms": ["chromeos", "win", "linux"],
"options": {
"supportsFilters": false,
diff --git a/chrome/test/data/extensions/api_test/input_ime_nonchromeos/background.js b/chrome/test/data/extensions/api_test/input_ime_nonchromeos/background.js
index e3ba1d6..d007bc6 100644
--- a/chrome/test/data/extensions/api_test/input_ime_nonchromeos/background.js
+++ b/chrome/test/data/extensions/api_test/input_ime_nonchromeos/background.js
@@ -52,5 +52,23 @@ chrome.test.runTests([
win.addEventListener('unload', function() {});
chrome.test.succeed();
});
+ },
+
+ function testSendKeyEvents() {
+ chrome.input.ime.sendKeyEvents({
+ 'contextID': 1,
+ 'keyData': [{
+ 'type': 'keydown',
+ 'requestId': '0',
+ 'key': 'a',
+ 'code': 'KeyA'
+ }, {
+ 'type': 'keyup',
+ 'requestId': '1',
+ 'key': 'a',
+ 'code': 'KeyA'
+ }]
+ });
+ chrome.test.succeed();
}
]);
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 718de9d..e2a30a8 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -675,7 +675,10 @@ source_set("test_support") {
"ime/dummy_text_input_client.h",
]
- deps += [ "//ui/base/ime" ]
+ deps += [
+ "//ui/base/ime",
+ "//ui/events",
+ ]
}
if (!use_aura) {
diff --git a/ui/base/ime/chromeos/mock_ime_input_context_handler.cc b/ui/base/ime/chromeos/mock_ime_input_context_handler.cc
index e4decfd..35cda00 100644
--- a/ui/base/ime/chromeos/mock_ime_input_context_handler.cc
+++ b/ui/base/ime/chromeos/mock_ime_input_context_handler.cc
@@ -46,4 +46,6 @@ void MockIMEInputContextHandler::Reset() {
last_commit_text_.clear();
}
+void MockIMEInputContextHandler::SendKeyEvent(ui::KeyEvent* event) {}
+
} // namespace chromeos
diff --git a/ui/base/ime/chromeos/mock_ime_input_context_handler.h b/ui/base/ime/chromeos/mock_ime_input_context_handler.h
index 78dec902..751dad9 100644
--- a/ui/base/ime/chromeos/mock_ime_input_context_handler.h
+++ b/ui/base/ime/chromeos/mock_ime_input_context_handler.h
@@ -35,6 +35,7 @@ class UI_BASE_IME_EXPORT MockIMEInputContextHandler
uint32_t cursor_pos,
bool visible) override;
void DeleteSurroundingText(int32_t offset, uint32_t length) override;
+ void SendKeyEvent(ui::KeyEvent* event) override;
int commit_text_call_count() const { return commit_text_call_count_; }
diff --git a/ui/base/ime/dummy_text_input_client.cc b/ui/base/ime/dummy_text_input_client.cc
index 478b489..ac9b973 100644
--- a/ui/base/ime/dummy_text_input_client.cc
+++ b/ui/base/ime/dummy_text_input_client.cc
@@ -3,15 +3,16 @@
// found in the LICENSE file.
#include "ui/base/ime/dummy_text_input_client.h"
+#include "ui/events/event.h"
#include "ui/gfx/geometry/rect.h"
namespace ui {
DummyTextInputClient::DummyTextInputClient()
- : text_input_type_(TEXT_INPUT_TYPE_NONE) {}
+ : text_input_type_(TEXT_INPUT_TYPE_NONE), insert_char_count_(0) {}
DummyTextInputClient::DummyTextInputClient(TextInputType text_input_type)
- : text_input_type_(text_input_type) {}
+ : text_input_type_(text_input_type), insert_char_count_(0) {}
DummyTextInputClient::~DummyTextInputClient() {
}
@@ -29,7 +30,10 @@ void DummyTextInputClient::ClearCompositionText() {
void DummyTextInputClient::InsertText(const base::string16& text) {
}
-void DummyTextInputClient::InsertChar(const KeyEvent& event) {}
+void DummyTextInputClient::InsertChar(const KeyEvent& event) {
+ ++insert_char_count_;
+ last_insert_char_ = event.GetCharacter();
+}
TextInputType DummyTextInputClient::GetTextInputType() const {
return text_input_type_;
diff --git a/ui/base/ime/dummy_text_input_client.h b/ui/base/ime/dummy_text_input_client.h
index 3c51782..a177993 100644
--- a/ui/base/ime/dummy_text_input_client.h
+++ b/ui/base/ime/dummy_text_input_client.h
@@ -49,9 +49,16 @@ class DummyTextInputClient : public TextInputClient {
bool IsEditCommandEnabled(int command_id) override;
void SetEditCommandForNextKeyEvent(int command_id) override;
+ int insert_char_count() const { return insert_char_count_; }
+ base::char16 last_insert_char() const { return last_insert_char_; }
+
TextInputType text_input_type_;
DISALLOW_COPY_AND_ASSIGN(DummyTextInputClient);
+
+ private:
+ int insert_char_count_;
+ base::char16 last_insert_char_;
};
} // namespace ui
diff --git a/ui/base/ime/ime_input_context_handler_interface.h b/ui/base/ime/ime_input_context_handler_interface.h
index 5a8f6ae..b8fbb2b 100644
--- a/ui/base/ime/ime_input_context_handler_interface.h
+++ b/ui/base/ime/ime_input_context_handler_interface.h
@@ -10,6 +10,7 @@
#include <string>
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/ui_base_ime_export.h"
+#include "ui/events/event.h"
namespace ui {
@@ -25,6 +26,9 @@ class UI_BASE_IME_EXPORT IMEInputContextHandlerInterface {
// Called when the engine request deleting surrounding string.
virtual void DeleteSurroundingText(int32_t offset, uint32_t length) = 0;
+
+ // Called when the engine sends a key event.
+ virtual void SendKeyEvent(KeyEvent* event) = 0;
};
} // namespace ui
diff --git a/ui/base/ime/input_method_auralinux.cc b/ui/base/ime/input_method_auralinux.cc
index c5c0d5e..08ec50b 100644
--- a/ui/base/ime/input_method_auralinux.cc
+++ b/ui/base/ime/input_method_auralinux.cc
@@ -65,6 +65,20 @@ void InputMethodAuraLinux::DispatchKeyEvent(ui::KeyEvent* event) {
return;
}
+ if (!event->HasNativeEvent() && sending_key_event_) {
+ // Faked key events that are sent from input.ime.sendKeyEvents.
+ ui::EventDispatchDetails details = DispatchKeyEventPostIME(event);
+ if (details.dispatcher_destroyed || details.target_destroyed ||
+ event->stopped_propagation()) {
+ return;
+ }
+ if ((event->is_char() || event->GetDomKey().IsCharacter()) &&
+ event->type() == ui::ET_KEY_PRESSED) {
+ GetTextInputClient()->InsertChar(*event);
+ }
+ return;
+ }
+
suppress_next_result_ = false;
composition_changed_ = false;
result_text_.clear();
diff --git a/ui/base/ime/input_method_base.cc b/ui/base/ime/input_method_base.cc
index e4af2e8..d66cb94 100644
--- a/ui/base/ime/input_method_base.cc
+++ b/ui/base/ime/input_method_base.cc
@@ -17,7 +17,9 @@
namespace ui {
InputMethodBase::InputMethodBase()
- : delegate_(nullptr), text_input_client_(nullptr) {}
+ : sending_key_event_(false),
+ delegate_(nullptr),
+ text_input_client_(nullptr) {}
InputMethodBase::~InputMethodBase() {
FOR_EACH_OBSERVER(InputMethodObserver,
@@ -195,4 +197,10 @@ void InputMethodBase::UpdateCompositionText(const CompositionText& composition_,
void InputMethodBase::DeleteSurroundingText(int32_t offset, uint32_t length) {}
+void InputMethodBase::SendKeyEvent(KeyEvent* event) {
+ sending_key_event_ = true;
+ DispatchKeyEvent(event);
+ sending_key_event_ = false;
+}
+
} // namespace ui
diff --git a/ui/base/ime/input_method_base.h b/ui/base/ime/input_method_base.h
index a0ac432..3a44e37 100644
--- a/ui/base/ime/input_method_base.h
+++ b/ui/base/ime/input_method_base.h
@@ -69,6 +69,7 @@ class UI_BASE_IME_EXPORT InputMethodBase
uint32_t cursor_pos,
bool visible) override;
void DeleteSurroundingText(int32_t offset, uint32_t length) override;
+ void SendKeyEvent(KeyEvent* event) override;
// Sends a fake key event for IME composing without physical key events.
// Returns true if the faked key event is stopped propagation.
@@ -102,6 +103,10 @@ class UI_BASE_IME_EXPORT InputMethodBase
// Gets the bounds of the composition text or cursor in |client|.
std::vector<gfx::Rect> GetCompositionBounds(const TextInputClient* client);
+ // Indicates whether the IME extension is currently sending a fake key event.
+ // This is used in SendKeyEvent.
+ bool sending_key_event_;
+
private:
void SetFocusedTextInputClientInternal(TextInputClient* client);
diff --git a/ui/base/ime/input_method_win.cc b/ui/base/ime/input_method_win.cc
index 0bc9052..9b04a8d 100644
--- a/ui/base/ime/input_method_win.cc
+++ b/ui/base/ime/input_method_win.cc
@@ -623,15 +623,16 @@ bool InputMethodWin::IsWindowFocused(const TextInputClient* client) const {
}
void InputMethodWin::DispatchFabricatedKeyEvent(ui::KeyEvent* event) {
- if (event->is_char()) {
- if (GetTextInputClient()) {
- ui::KeyEvent ch_event(*event);
- ch_event.set_character(static_cast<base::char16>(event->key_code()));
- GetTextInputClient()->InsertChar(ch_event);
- return;
- }
+ // The key event if from calling input.ime.sendKeyEvent or test.
+ ui::EventDispatchDetails details = DispatchKeyEventPostIME(event);
+ if (details.dispatcher_destroyed || details.target_destroyed ||
+ event->stopped_propagation()) {
+ return;
}
- ignore_result(DispatchKeyEventPostIME(event));
+
+ if ((event->is_char() || event->GetDomKey().IsCharacter()) &&
+ event->type() == ui::ET_KEY_PRESSED && GetTextInputClient())
+ GetTextInputClient()->InsertChar(*event);
}
void InputMethodWin::ConfirmCompositionText() {
diff --git a/ui/base/ui_base.gyp b/ui/base/ui_base.gyp
index ae6f6e57..853e95e 100644
--- a/ui/base/ui_base.gyp
+++ b/ui/base/ui_base.gyp
@@ -726,7 +726,8 @@
],
'conditions': [
['OS!="ios"', {
- 'dependecies': [
+ 'dependencies': [
+ '../events/events.gyp:events',
'ime/ui_base_ime.gyp:ui_base_ime',
],
'sources': [