Commit e21d2fd8 authored by Darren Shen's avatar Darren Shen Committed by Commit Bot

ime: Send physical key events to IME service.

Add Mojo and protobuf messages for Chrome to send key events to the
IME service. Key event handling is a bit special because it requires
a callback (whether the key event was consumed by the IME or not).

Before, messages were sent from DecoderEngine and received in
ClientDelegate, so sending & receiving were independent of each other.
However, for key events, we need to track key events and their
callbacks, so sending & receiving must go through the same code at
some point.

Therefore, make ClientDelegate forward messages to DecoderEngine so
that DecoderEngine can track pending key events and call the right
callback when needed.

Change-Id: Ia3a2d976cc79f24a96d6ec390732dc64833afaff
Bug: b/161490915
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2422925
Commit-Queue: Darren Shen <shend@chromium.org>
Reviewed-by: default avatarMatthew Denton <mpdenton@chromium.org>
Reviewed-by: default avatarKeith Lee <keithlee@chromium.org>
Auto-Submit: Darren Shen <shend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#819172}
parent f38248ba
......@@ -200,14 +200,21 @@ void NativeInputMethodEngine::ImeObserver::OnKeyEvent(
return;
}
}
auto key_event = ime::mojom::PhysicalKeyEvent::New(
event.type == "keydown" ? ime::mojom::KeyEventType::kKeyDown
: ime::mojom::KeyEventType::kKeyUp,
event.code, event.key, ModifierStateFromEvent(event));
if (ShouldUseRuleBasedMojoEngine(engine_id) && remote_to_engine_.is_bound()) {
remote_to_engine_->ProcessKeypressForRulebased(
ime::mojom::PhysicalKeyEvent::New(
event.type == "keydown" ? ime::mojom::KeyEventType::kKeyDown
: ime::mojom::KeyEventType::kKeyUp,
event.code, event.key, ModifierStateFromEvent(event)),
base::BindOnce(&ImeObserver::OnKeyEventResponse, base::Unretained(this),
base::Time::Now(), std::move(callback)));
std::move(key_event),
base::BindOnce(&ImeObserver::OnRuleBasedKeyEventResponse,
base::Unretained(this), base::Time::Now(),
std::move(callback)));
} else if (ShouldUseFstMojoEngine(engine_id) &&
remote_to_engine_.is_bound()) {
remote_to_engine_->OnKeyEvent(std::move(key_event), std::move(callback));
} else {
base_observer_->OnKeyEvent(engine_id, event, std::move(callback));
}
......@@ -353,7 +360,7 @@ void NativeInputMethodEngine::ImeObserver::OnError(base::Time start) {
active_engine_id_.reset();
}
void NativeInputMethodEngine::ImeObserver::OnKeyEventResponse(
void NativeInputMethodEngine::ImeObserver::OnRuleBasedKeyEventResponse(
base::Time start,
ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback,
ime::mojom::KeypressResponseForRulebasedPtr response) {
......
......@@ -96,6 +96,8 @@ class NativeInputMethodEngine : public InputMethodEngine {
void ProcessKeypressForRulebased(
ime::mojom::PhysicalKeyEventPtr event,
ProcessKeypressForRulebasedCallback callback) override {}
void OnKeyEvent(ime::mojom::PhysicalKeyEventPtr event,
OnKeyEventCallback callback) override {}
void ResetForRulebased() override {}
void GetRulebasedKeypressCountForTesting(
GetRulebasedKeypressCountForTestingCallback callback) override {}
......@@ -114,8 +116,8 @@ class NativeInputMethodEngine : public InputMethodEngine {
// Called when there's a connection error.
void OnError(base::Time start);
// Called when a key press is processed by Mojo.
void OnKeyEventResponse(
// Called when a rule-based key press is processed by Mojo.
void OnRuleBasedKeyEventResponse(
base::Time start,
ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback,
ime::mojom::KeypressResponseForRulebasedPtr response);
......
......@@ -150,7 +150,7 @@ class NativeInputMethodEngineTest : public InProcessBrowserTest,
protected:
void SetUp() override {
chromeos::ime::FakeEngineMainEntryForTesting();
chromeos::ime::FakeEngineMainEntryForTesting(nullptr);
mojo::core::Init();
InProcessBrowserTest::SetUp();
ui::IMEBridge::Initialize();
......
......@@ -23,6 +23,8 @@ source_set("lib") {
"decoder/decoder_engine.h",
"decoder/downloader_impl.cc",
"decoder/downloader_impl.h",
"decoder/proto_conversion.cc",
"decoder/proto_conversion.h",
"ime_service.cc",
"ime_service.h",
"input_engine.cc",
......@@ -68,10 +70,15 @@ source_set("services_unittests") {
"//base",
"//base/test:test_support",
"//chromeos/services/ime/public/mojom",
"//chromeos/services/ime/public/proto:messages_proto",
"//mojo/public/cpp/bindings",
"//services/network:test_support",
"//testing/gmock",
"//testing/gtest",
]
sources = [ "ime_service_unittest.cc" ]
sources = [
"decoder/decoder_engine_unittest.cc",
"decoder/proto_conversion_unittest.cc",
"ime_service_unittest.cc",
]
}
......@@ -8,6 +8,7 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "chromeos/services/ime/constants.h"
#include "chromeos/services/ime/decoder/proto_conversion.h"
#include "chromeos/services/ime/public/cpp/buildflags.h"
#include "chromeos/services/ime/public/proto/messages.pb.h"
......@@ -16,15 +17,23 @@ namespace ime {
namespace {
// Whether to create a fake main entry.
bool g_fake_main_entry_for_testing = false;
ImeEngineMainEntry* g_fake_main_entry_for_testing = nullptr;
// A client delegate that makes calls on client side.
using ReplyCallback =
base::RepeatingCallback<void(const std::vector<uint8_t>&)>;
// A client delegate passed to the shared library in order for the
// shared library to send replies back to the engine.
class ClientDelegate : public ImeClientDelegate {
public:
// All replies from the shared library will be sent to both |remote| and
// |callback|.
ClientDelegate(const std::string& ime_spec,
mojo::PendingRemote<mojom::InputChannel> remote)
: ime_spec_(ime_spec), client_remote_(std::move(remote)) {
mojo::PendingRemote<mojom::InputChannel> remote,
ReplyCallback callback)
: ime_spec_(ime_spec),
client_remote_(std::move(remote)),
callback_(callback) {
client_remote_.set_disconnect_handler(base::BindOnce(
&ClientDelegate::OnDisconnected, base::Unretained(this)));
}
......@@ -37,6 +46,7 @@ class ClientDelegate : public ImeClientDelegate {
if (client_remote_ && client_remote_.is_bound()) {
std::vector<uint8_t> msg(data, data + size);
client_remote_->ProcessMessage(msg, base::DoNothing());
callback_.Run(msg);
}
}
......@@ -53,25 +63,27 @@ class ClientDelegate : public ImeClientDelegate {
// The InputChannel remote used to talk to the client.
mojo::Remote<mojom::InputChannel> client_remote_;
ReplyCallback callback_;
};
std::vector<uint8_t> SerializeMessage(ime::PublicMessage message) {
ime::Wrapper wrapper;
std::vector<uint8_t> WrapAndSerializeMessage(PublicMessage message) {
Wrapper wrapper;
*wrapper.mutable_public_message() = std::move(message);
std::vector<uint8_t> output;
wrapper.SerializeToArray(output.data(), wrapper.ByteSizeLong());
std::vector<uint8_t> output(wrapper.ByteSizeLong());
wrapper.SerializeToArray(output.data(), output.size());
return output;
}
} // namespace
void FakeEngineMainEntryForTesting() {
g_fake_main_entry_for_testing = true;
void FakeEngineMainEntryForTesting(ImeEngineMainEntry* main_entry) {
g_fake_main_entry_for_testing = main_entry;
}
DecoderEngine::DecoderEngine(ImeCrosPlatform* platform) : platform_(platform) {
if (g_fake_main_entry_for_testing) {
// TODO(b/156897880): Add a fake main entry.
engine_main_entry_ = g_fake_main_entry_for_testing;
} else {
if (!TryLoadDecoder()) {
LOG(WARNING) << "DecoderEngine INIT INCOMPLETED.";
......@@ -122,7 +134,9 @@ bool DecoderEngine::BindRequest(
// make safe calls on the client.
if (engine_main_entry_->ActivateIme(
ime_spec.c_str(),
new ClientDelegate(ime_spec, std::move(remote)))) {
new ClientDelegate(ime_spec, std::move(remote),
base::BindRepeating(&DecoderEngine::OnReply,
base::Unretained(this))))) {
decoder_channel_receivers_.Add(this, std::move(receiver));
// TODO(https://crbug.com/837156): Registry connection error handler.
return true;
......@@ -141,11 +155,22 @@ bool DecoderEngine::IsImeSupportedByDecoder(const std::string& ime_spec) {
}
void DecoderEngine::OnFocus() {
ime::PublicMessage message;
message.set_seq_id(current_seq_id_++);
*message.mutable_on_focus() = ime::OnFocus();
const uint64_t seq_id = current_seq_id_;
++current_seq_id_;
ProcessMessage(SerializeMessage(std::move(message)), base::DoNothing());
ProcessMessage(WrapAndSerializeMessage(OnFocusToProto(seq_id)),
base::DoNothing());
}
void DecoderEngine::OnKeyEvent(mojom::PhysicalKeyEventPtr event,
OnKeyEventCallback callback) {
const uint64_t seq_id = current_seq_id_;
++current_seq_id_;
pending_key_event_callbacks_.emplace(seq_id, std::move(callback));
ProcessMessage(
WrapAndSerializeMessage(OnKeyEventToProto(seq_id, std::move(event))),
base::DoNothing());
}
void DecoderEngine::ProcessMessage(const std::vector<uint8_t>& message,
......@@ -160,5 +185,28 @@ void DecoderEngine::ProcessMessage(const std::vector<uint8_t>& message,
std::move(callback).Run(result);
}
void DecoderEngine::OnReply(const std::vector<uint8_t>& message) {
ime::Wrapper wrapper;
if (!wrapper.ParseFromArray(message.data(), message.size()) ||
!wrapper.has_public_message()) {
return;
}
const ime::PublicMessage& reply = wrapper.public_message();
switch (reply.param_case()) {
case ime::PublicMessage::kOnKeyEventReply: {
const auto it = pending_key_event_callbacks_.find(reply.seq_id());
CHECK(it != pending_key_event_callbacks_.end());
auto callback = std::move(it->second);
std::move(callback).Run(reply.on_key_event_reply().consumed());
pending_key_event_callbacks_.erase(it);
break;
}
default:
NOTREACHED();
break;
}
}
} // namespace ime
} // namespace chromeos
......@@ -13,8 +13,8 @@
namespace chromeos {
namespace ime {
// Only used in tests to create a fake `ImeEngineMainEntry`.
void FakeEngineMainEntryForTesting();
// Only used in tests to set a fake `ImeEngineMainEntry`.
void FakeEngineMainEntryForTesting(ImeEngineMainEntry* main_entry);
// An enhanced implementation of the basic InputEngine which allows the input
// engine to call a customized transliteration library (aka decoder) to provide
......@@ -33,6 +33,8 @@ class DecoderEngine : public InputEngine {
void ProcessMessage(const std::vector<uint8_t>& message,
ProcessMessageCallback callback) override;
void OnFocus() override;
void OnKeyEvent(mojom::PhysicalKeyEventPtr event,
OnKeyEventCallback callback) override;
private:
// Try to load the decoding functions from some decoder shared library.
......@@ -42,6 +44,10 @@ class DecoderEngine : public InputEngine {
// Returns whether the decoder shared library supports this ime_spec.
bool IsImeSupportedByDecoder(const std::string& ime_spec);
// Called when there's a reply from the shared library.
// Deserializes |message| and converts it into Mojo calls to the receiver.
void OnReply(const std::vector<uint8_t>& message);
// Shared library handle of the implementation for input logic with decoders.
base::ScopedNativeLibrary library_;
......@@ -52,7 +58,9 @@ class DecoderEngine : public InputEngine {
mojo::ReceiverSet<mojom::InputChannel> decoder_channel_receivers_;
// Sequence ID for protobuf messages sent from the engine.
int current_seq_id_ = 0;
uint64_t current_seq_id_ = 0;
std::map<uint64_t, OnKeyEventCallback> pending_key_event_callbacks_;
DISALLOW_COPY_AND_ASSIGN(DecoderEngine);
};
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/services/ime/decoder/decoder_engine.h"
#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
#include "chromeos/services/ime/decoder/proto_conversion.h"
#include "chromeos/services/ime/public/proto/messages.pb.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace ime {
// EqualsProto must match against two arguments: a buffer containing the actual
// serialized proto and a number indicating the size of the buffer.
MATCHER_P(EqualsProto,
message,
"Match a proto Message equal to the matcher's argument.") {
std::string expected_serialized;
message.SerializeToString(&expected_serialized);
const char* bytes = reinterpret_cast<const char*>(std::get<0>(arg));
int size = std::get<1>(arg);
std::string actual_serialized(bytes, size);
return expected_serialized == actual_serialized;
}
constexpr char kImeSpec[] = "xkb:us::eng";
class MockImeEngineMainEntry : public ImeEngineMainEntry {
public:
bool IsImeSupported(const char*) final { return true; }
bool ActivateIme(const char*, ImeClientDelegate* delegate) final {
delegate_ = delegate;
return true;
}
MOCK_METHOD(void, Process, (const uint8_t* data, size_t size));
void Destroy() final {}
ImeClientDelegate* delegate() const { return delegate_; }
private:
ImeClientDelegate* delegate_;
};
class StubInputChannel : public mojom::InputChannel {
void ProcessMessage(const std::vector<uint8_t>& message,
ProcessMessageCallback callback) final {
std::move(callback).Run({});
}
void OnFocus() final {}
void ProcessKeypressForRulebased(
ime::mojom::PhysicalKeyEventPtr event,
ProcessKeypressForRulebasedCallback callback) final {}
void OnKeyEvent(ime::mojom::PhysicalKeyEventPtr event,
OnKeyEventCallback callback) final {}
void ResetForRulebased() final {}
void GetRulebasedKeypressCountForTesting(
GetRulebasedKeypressCountForTestingCallback callback) final {}
};
// Sets up the test environment for Mojo and inject a mock ImeEngineMainEntry.
class DecoderEngineTest : public testing::Test {
protected:
void SetUp() final { FakeEngineMainEntryForTesting(&mock_main_entry_); }
void TearDown() final { FakeEngineMainEntryForTesting(nullptr); }
MockImeEngineMainEntry mock_main_entry_;
private:
// Mojo calls need a SequencedTaskRunner.
base::test::SingleThreadTaskEnvironment task_environment;
};
TEST_F(DecoderEngineTest, BindRequestBindsInterfaces) {
DecoderEngine engine(/*platform=*/nullptr);
StubInputChannel stub_channel;
mojo::Receiver<mojom::InputChannel> receiver(&stub_channel);
mojo::Remote<mojom::InputChannel> client;
EXPECT_TRUE(engine.BindRequest(kImeSpec, client.BindNewPipeAndPassReceiver(),
receiver.BindNewPipeAndPassRemote(), {}));
EXPECT_TRUE(client.is_bound());
EXPECT_TRUE(receiver.is_bound());
}
TEST_F(DecoderEngineTest, OnFocusSendsMessageToSharedLib) {
DecoderEngine engine(/*platform=*/nullptr);
StubInputChannel stub_channel;
mojo::Receiver<mojom::InputChannel> receiver(&stub_channel);
mojo::Remote<mojom::InputChannel> client;
ASSERT_TRUE(engine.BindRequest(kImeSpec, client.BindNewPipeAndPassReceiver(),
receiver.BindNewPipeAndPassRemote(), {}));
ime::Wrapper expected_proto;
*expected_proto.mutable_public_message() = OnFocusToProto(/*seq_id=*/0);
EXPECT_CALL(mock_main_entry_, Process).With(EqualsProto(expected_proto));
client->OnFocus();
client.FlushForTesting();
}
TEST_F(DecoderEngineTest, OnKeyEventRepliesWithCallback) {
DecoderEngine engine(/*platform=*/nullptr);
StubInputChannel stub_channel;
mojo::Receiver<mojom::InputChannel> receiver(&stub_channel);
mojo::Remote<mojom::InputChannel> client;
ASSERT_TRUE(engine.BindRequest(kImeSpec, client.BindNewPipeAndPassReceiver(),
receiver.BindNewPipeAndPassRemote(), {}));
auto key_event = mojom::PhysicalKeyEvent::New(
mojom::KeyEventType::kKeyDown, "KeyA", "A", mojom::ModifierState::New());
ime::Wrapper expected_proto;
*expected_proto.mutable_public_message() =
OnKeyEventToProto(/*seq_id=*/0, key_event.Clone());
// Set up the mock shared library to reply to the key event.
bool consumed_by_test = false;
EXPECT_CALL(mock_main_entry_, Process)
.With(EqualsProto(expected_proto))
.WillOnce([this]() {
ime::Wrapper wrapper;
wrapper.mutable_public_message()
->mutable_on_key_event_reply()
->set_consumed(true);
std::vector<uint8_t> output(wrapper.ByteSizeLong());
wrapper.SerializeToArray(output.data(), output.size());
mock_main_entry_.delegate()->Process(output.data(), output.size());
});
client->OnKeyEvent(
std::move(key_event),
base::BindLambdaForTesting(
[&consumed_by_test](bool consumed) { consumed_by_test = consumed; }));
client.FlushForTesting();
EXPECT_TRUE(consumed_by_test);
}
} // namespace ime
} // namespace chromeos
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/services/ime/decoder/proto_conversion.h"
namespace chromeos {
namespace ime {
namespace {
ModifierState ModifierStateToProto(mojom::ModifierStatePtr modifier_state) {
ModifierState result;
result.set_alt(modifier_state->alt);
result.set_alt_graph(modifier_state->alt_graph);
result.set_caps_lock(modifier_state->caps_lock);
result.set_control(modifier_state->control);
result.set_meta(modifier_state->meta);
result.set_shift(modifier_state->shift);
return result;
}
} // namespace
ime::PublicMessage OnFocusToProto(uint64_t seq_id) {
ime::PublicMessage message;
message.set_seq_id(seq_id);
*message.mutable_on_focus() = ime::OnFocus();
return message;
}
ime::PublicMessage OnKeyEventToProto(uint64_t seq_id,
mojom::PhysicalKeyEventPtr event) {
ime::PublicMessage message;
message.set_seq_id(seq_id);
ime::PhysicalKeyEvent& key_event =
*message.mutable_on_key_event()->mutable_key_event();
key_event.set_type(event->type == mojom::KeyEventType::kKeyDown
? ime::PhysicalKeyEvent::EVENT_TYPE_KEY_DOWN
: ime::PhysicalKeyEvent::EVENT_TYPE_KEY_UP);
key_event.set_code(event->code);
key_event.set_key(event->key);
*key_event.mutable_modifier_state() =
ModifierStateToProto(std::move(event->modifier_state));
return message;
}
} // namespace ime
} // namespace chromeos
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_SERVICES_IME_DECODER_PROTO_CONVERSION_H_
#define CHROMEOS_SERVICES_IME_DECODER_PROTO_CONVERSION_H_
#include <vector>
#include "chromeos/services/ime/public/mojom/input_engine.mojom.h"
#include "chromeos/services/ime/public/proto/messages.pb.h"
namespace chromeos {
namespace ime {
// Converts arguments of a Mojo call to InputChannel::OnFocus into a proto.
ime::PublicMessage OnFocusToProto(uint64_t seq_id);
// Converts arguments of a Mojo call to InputChannel::OnKeyEvent into a proto.
ime::PublicMessage OnKeyEventToProto(uint64_t seq_id,
mojom::PhysicalKeyEventPtr event);
} // namespace ime
} // namespace chromeos
#endif // CHROMEOS_SERVICES_IME_DECODER_PROTO_CONVERSION_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/services/ime/decoder/proto_conversion.h"
#include "chromeos/services/ime/public/proto/messages.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace ime {
TEST(ProtoConversionTest, OnFocusToProto) {
ime::PublicMessage expected_message;
expected_message.set_seq_id(42);
*expected_message.mutable_on_focus() = ime::OnFocus();
ime::PublicMessage actual_message = OnFocusToProto(/*seq_id=*/42);
EXPECT_EQ(actual_message.SerializeAsString(),
expected_message.SerializeAsString());
}
TEST(ProtoConversionTest, OnKeyEventToProto) {
auto modifier_state = mojom::ModifierState::New();
modifier_state->shift = true;
auto key_event = mojom::PhysicalKeyEvent::New(
mojom::KeyEventType::kKeyDown, "KeyA", "A", std::move(modifier_state));
ime::PublicMessage expected_message;
expected_message.set_seq_id(42);
ime::OnKeyEvent& args = *expected_message.mutable_on_key_event();
args.mutable_key_event()->set_type(
ime::PhysicalKeyEvent::EVENT_TYPE_KEY_DOWN);
args.mutable_key_event()->set_code("KeyA");
args.mutable_key_event()->set_key("A");
args.mutable_key_event()->mutable_modifier_state()->set_alt(false);
args.mutable_key_event()->mutable_modifier_state()->set_alt_graph(false);
args.mutable_key_event()->mutable_modifier_state()->set_caps_lock(false);
args.mutable_key_event()->mutable_modifier_state()->set_control(false);
args.mutable_key_event()->mutable_modifier_state()->set_meta(false);
args.mutable_key_event()->mutable_modifier_state()->set_shift(true);
const ime::PublicMessage actual_message =
OnKeyEventToProto(/*seq_id=*/42, std::move(key_event));
EXPECT_EQ(actual_message.SerializeAsString(),
expected_message.SerializeAsString());
}
} // namespace ime
} // namespace chromeos
......@@ -59,6 +59,9 @@ class TestClientChannel : mojom::InputChannel {
MOCK_METHOD2(ProcessKeypressForRulebased,
void(const mojom::PhysicalKeyEventPtr event,
ProcessKeypressForRulebasedCallback));
MOCK_METHOD2(OnKeyEvent,
void(const mojom::PhysicalKeyEventPtr event,
OnKeyEventCallback));
MOCK_METHOD0(ResetForRulebased, void());
MOCK_METHOD1(GetRulebasedKeypressCountForTesting,
void(GetRulebasedKeypressCountForTestingCallback));
......
......@@ -153,6 +153,11 @@ void InputEngine::ProcessKeypressForRulebased(
std::move(callback).Run(std::move(keypress_response));
}
void InputEngine::OnKeyEvent(mojom::PhysicalKeyEventPtr event,
OnKeyEventCallback callback) {
NOTIMPLEMENTED(); // Not used in the rulebased engine.
}
void InputEngine::ResetForRulebased() {
auto& context = channel_receivers_.current_context();
auto& engine = context.get()->engine;
......
......@@ -30,6 +30,7 @@ class InputEngineContext {
};
// A basic implementation of InputEngine without using any decoder.
// TODO(https://crbug.com/1019541): Rename this to RuleBasedEngine.
class InputEngine : public mojom::InputChannel {
public:
InputEngine();
......@@ -49,6 +50,8 @@ class InputEngine : public mojom::InputChannel {
void ProcessKeypressForRulebased(
mojom::PhysicalKeyEventPtr event,
ProcessKeypressForRulebasedCallback callback) override;
void OnKeyEvent(mojom::PhysicalKeyEventPtr event,
OnKeyEventCallback callback) override;
void ResetForRulebased() override;
void GetRulebasedKeypressCountForTesting(
GetRulebasedKeypressCountForTestingCallback callback) override;
......
......@@ -115,6 +115,9 @@ interface InputChannel {
// Called when there's a new focused input field.
OnFocus();
// Process a PhysicalKeyEvent for non-rule-based engines.
OnKeyEvent(PhysicalKeyEvent event) => (bool consumed);
// Process a PhysicalKeyEvent using the rule-based engine and return a
// KeypressResponseForRulebased object with a list of operations to be handled
// by the caller.
......
......@@ -28,7 +28,11 @@ message Wrapper {
message PublicMessage {
optional int32 seq_id = 1;
oneof param { OnFocus on_focus = 2; }
oneof param {
OnFocus on_focus = 2;
OnKeyEvent on_key_event = 3;
OnKeyEventReply on_key_event_reply = 4;
}
}
// Protobuf version of InputEngine::OnFocus in
......@@ -36,3 +40,41 @@ message PublicMessage {
message OnFocus {
// TODO(crbug/1019541): Add information about the input field.
}
// Protobuf version of InputEngine::OnKeyEvent in
// chromeos/services/ime/public/mojom/input_engine.mojom
message OnKeyEvent {
optional PhysicalKeyEvent key_event = 1;
}
// Protobuf version of the reply from InputEngine::OnKeyEvent in
// chromeos/services/ime/public/mojom/input_engine.mojom
message OnKeyEventReply {
optional bool consumed = 1;
}
// Protobuf version of InputEngine::PhysicalKeyEvent in
// chromeos/services/ime/public/mojom/input_engine.mojom
message PhysicalKeyEvent {
enum EventType {
EVENT_TYPE_UNSPECIFIED = 0;
EVENT_TYPE_KEY_DOWN = 1;
EVENT_TYPE_KEY_UP = 2;
}
optional EventType type = 1;
optional string code = 2;
optional string key = 3;
optional ModifierState modifier_state = 4;
}
// Protobuf version of InputEngine::PhysicalKeyEvent in
// chromeos/services/ime/public/mojom/input_engine.mojom
message ModifierState {
optional bool alt = 1;
optional bool alt_graph = 2;
optional bool caps_lock = 3;
optional bool control = 4;
optional bool meta = 5;
optional bool shift = 6;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment