[fuchsia] Add support for synthesized/non-physical keypresses.
Handles input events in which there is a KeyMeaning (w/Unicode codepoint) but no physical key (e.g. accented characters unsupported by the physical key layout) * Minor refactoring of KeyboardClient. * Adds new browsertests. * Substantial cleanups of redundant code in browsertests. Bug: 1215319 Test: web_engine_browsertests Change-Id: I863cf24e0db9bb19ae23c1db450c991b651b6d8b Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2964484 Reviewed-by: Sharon Yang <yangsharon@chromium.org> Commit-Queue: Kevin Marshall <kmarshall@chromium.org> Cr-Commit-Position: refs/heads/master@{#895710}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
296d788a4a
commit
09837c8183
@ -21,6 +21,8 @@
|
||||
using fuchsia::input::Key;
|
||||
using fuchsia::ui::input3::KeyEvent;
|
||||
using fuchsia::ui::input3::KeyEventType;
|
||||
using fuchsia::ui::input3::KeyMeaning;
|
||||
using fuchsia::ui::input3::NonPrintableKey;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -29,7 +31,7 @@ const char kKeyPress[] = "keypress";
|
||||
const char kKeyUp[] = "keyup";
|
||||
const char kKeyDicts[] = "keyDicts";
|
||||
|
||||
KeyEvent FakeKeyEvent(Key key, KeyEventType event_type) {
|
||||
KeyEvent CreateKeyEvent(Key key, KeyEventType event_type) {
|
||||
KeyEvent key_event;
|
||||
key_event.set_timestamp(base::TimeTicks::Now().ToZxTime());
|
||||
key_event.set_type(event_type);
|
||||
@ -37,17 +39,40 @@ KeyEvent FakeKeyEvent(Key key, KeyEventType event_type) {
|
||||
return key_event;
|
||||
}
|
||||
|
||||
std::unique_ptr<base::Value> ExpectedKeyValue(base::StringPiece code,
|
||||
base::StringPiece key,
|
||||
base::StringPiece type) {
|
||||
std::unique_ptr<base::Value> expected =
|
||||
std::make_unique<base::DictionaryValue>();
|
||||
expected->SetStringKey("code", code);
|
||||
expected->SetStringKey("key", key);
|
||||
expected->SetStringKey("type", type);
|
||||
KeyEvent CreateCharacterEvent(uint32_t codepoint, KeyEventType event_type) {
|
||||
KeyEvent key_event;
|
||||
|
||||
fuchsia::ui::input3::KeyMeaning meaning;
|
||||
meaning.set_codepoint(codepoint);
|
||||
key_event.set_key_meaning(std::move(meaning));
|
||||
key_event.set_type(event_type);
|
||||
key_event.set_timestamp(base::TimeTicks::Now().ToZxTime());
|
||||
return key_event;
|
||||
}
|
||||
|
||||
base::Value ExpectedKeyValue(base::StringPiece code,
|
||||
base::StringPiece key,
|
||||
base::StringPiece type) {
|
||||
base::Value expected(base::Value::Type::DICTIONARY);
|
||||
expected.SetStringKey("code", code);
|
||||
expected.SetStringKey("key", key);
|
||||
expected.SetStringKey("type", type);
|
||||
return expected;
|
||||
}
|
||||
|
||||
// Recursive base case.
|
||||
template <typename T>
|
||||
void AppendValueList(std::vector<T>* vec) {}
|
||||
|
||||
// Use tail recursion to emplace a sequence of Values into |vec|.
|
||||
// It is used as an alternative to initializer lists, which don't work with
|
||||
// move-only types like base::Value.
|
||||
template <typename T, typename... Args>
|
||||
void AppendValueList(std::vector<T>* vec, T&& value, Args&&... args) {
|
||||
vec->push_back(std::move(value));
|
||||
AppendValueList(vec, std::forward<base::Value>(args)...);
|
||||
}
|
||||
|
||||
class FakeKeyboard : public fuchsia::ui::input3::testing::Keyboard_TestBase {
|
||||
public:
|
||||
explicit FakeKeyboard(sys::OutgoingDirectory* additional_services) {
|
||||
@ -137,6 +162,18 @@ class InputTest : public cr_fuchsia::WebEngineBrowserTest {
|
||||
context_impl()->GetFrameImplForTest(frame_ptr)->web_contents());
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void ExpectKeyEventsEqual(Args... events) {
|
||||
std::vector<base::Value> expected;
|
||||
AppendValueList(&expected, std::forward<Args>(events)...);
|
||||
frame_for_test_.navigation_listener().RunUntilTitleEquals(
|
||||
base::NumberToString(expected.size()));
|
||||
|
||||
absl::optional<base::Value> actual =
|
||||
cr_fuchsia::ExecuteJavaScript(frame_for_test_.ptr().get(), kKeyDicts);
|
||||
EXPECT_EQ(*actual, base::Value(expected));
|
||||
}
|
||||
|
||||
// Used to publish fake services.
|
||||
absl::optional<base::TestComponentContextForProcess> component_context_;
|
||||
|
||||
@ -145,99 +182,139 @@ class InputTest : public cr_fuchsia::WebEngineBrowserTest {
|
||||
absl::optional<FakeKeyboard> keyboard_service_;
|
||||
};
|
||||
|
||||
// Check that regular character keys are sent and received correctly.
|
||||
IN_PROC_BROWSER_TEST_F(InputTest, CharacterKeys) {
|
||||
const int kExpectedCharacterEventCount = 6;
|
||||
// Check that printable keys are sent and received correctly.
|
||||
IN_PROC_BROWSER_TEST_F(InputTest, PrintableKeys) {
|
||||
// Send key press events from the Fuchsia keyboard service.
|
||||
// Pressing character keys will generate a JavaScript keydown event followed
|
||||
// by a keypress event. Releasing any key generates a keyup event.
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateKeyEvent(Key::A, KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateKeyEvent(Key::KEY_8, KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateKeyEvent(Key::KEY_8, KeyEventType::RELEASED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateKeyEvent(Key::A, KeyEventType::RELEASED));
|
||||
|
||||
ExpectKeyEventsEqual(ExpectedKeyValue("KeyA", "a", kKeyDown),
|
||||
ExpectedKeyValue("KeyA", "a", kKeyPress),
|
||||
ExpectedKeyValue("Digit8", "8", kKeyDown),
|
||||
ExpectedKeyValue("Digit8", "8", kKeyPress),
|
||||
ExpectedKeyValue("Digit8", "8", kKeyUp),
|
||||
ExpectedKeyValue("KeyA", "a", kKeyUp));
|
||||
}
|
||||
|
||||
// Check that character virtual keys are sent and received correctly.
|
||||
IN_PROC_BROWSER_TEST_F(InputTest, Characters) {
|
||||
// Send key press events from the Fuchsia keyboard service.
|
||||
// Pressing character keys will generate a JavaScript keydown event followed
|
||||
// by a keypress event. Releasing any key generates a keyup event.
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateCharacterEvent('A', KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateCharacterEvent('A', KeyEventType::RELEASED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateCharacterEvent('b', KeyEventType::PRESSED));
|
||||
|
||||
ExpectKeyEventsEqual(ExpectedKeyValue("", "A", kKeyPress),
|
||||
ExpectedKeyValue("", "b", kKeyPress));
|
||||
}
|
||||
|
||||
// Verify that character events are not affected by active modifiers.
|
||||
IN_PROC_BROWSER_TEST_F(InputTest, ShiftCharacter) {
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateKeyEvent(Key::LEFT_SHIFT, KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateCharacterEvent('a', KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateCharacterEvent('a', KeyEventType::RELEASED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateKeyEvent(Key::LEFT_SHIFT, KeyEventType::RELEASED));
|
||||
|
||||
ExpectKeyEventsEqual(
|
||||
ExpectedKeyValue("ShiftLeft", "Shift", kKeyDown),
|
||||
ExpectedKeyValue("", "a", kKeyPress), // Remains lowercase.
|
||||
ExpectedKeyValue("ShiftLeft", "Shift", kKeyUp));
|
||||
}
|
||||
|
||||
// Verifies that codepoints outside the 16-bit Unicode BMP are rejected.
|
||||
IN_PROC_BROWSER_TEST_F(InputTest, CharacterInBmp) {
|
||||
const wchar_t kSigma = 0x03C3;
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateCharacterEvent(kSigma, KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateCharacterEvent(kSigma, KeyEventType::RELEASED));
|
||||
|
||||
std::string expected_utf8;
|
||||
ASSERT_TRUE(base::WideToUTF8(&kSigma, 1, &expected_utf8));
|
||||
ExpectKeyEventsEqual(ExpectedKeyValue("", expected_utf8, kKeyPress));
|
||||
}
|
||||
|
||||
// Verifies that codepoints beyond the range of allowable UCS-2 values
|
||||
// are rejected.
|
||||
IN_PROC_BROWSER_TEST_F(InputTest, CharacterBeyondBmp) {
|
||||
const uint32_t kRamenEmoji = 0x1F35C;
|
||||
|
||||
// Send key press events from the Fuchsia keyboard service.
|
||||
// Pressing character keys will generate a JavaScript keydown event followed
|
||||
// by a keypress event. Releasing any key generates a keyup event.
|
||||
keyboard_service_->SendKeyEvent(FakeKeyEvent(Key::A, KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
FakeKeyEvent(Key::KEY_8, KeyEventType::PRESSED));
|
||||
CreateCharacterEvent(kRamenEmoji, KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
FakeKeyEvent(Key::KEY_8, KeyEventType::RELEASED));
|
||||
keyboard_service_->SendKeyEvent(FakeKeyEvent(Key::A, KeyEventType::RELEASED));
|
||||
frame_for_test_.navigation_listener().RunUntilTitleEquals(
|
||||
base::NumberToString(kExpectedCharacterEventCount));
|
||||
CreateCharacterEvent(kRamenEmoji, KeyEventType::RELEASED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateCharacterEvent('a', KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateCharacterEvent('a', KeyEventType::RELEASED));
|
||||
|
||||
absl::optional<base::Value> result =
|
||||
cr_fuchsia::ExecuteJavaScript(frame_for_test_.ptr().get(), kKeyDicts);
|
||||
|
||||
base::ListValue expected;
|
||||
expected.Set(0, ExpectedKeyValue("KeyA", "a", kKeyDown));
|
||||
expected.Set(1, ExpectedKeyValue("KeyA", "a", kKeyPress));
|
||||
expected.Set(2, ExpectedKeyValue("Digit8", "8", kKeyDown));
|
||||
expected.Set(3, ExpectedKeyValue("Digit8", "8", kKeyPress));
|
||||
expected.Set(4, ExpectedKeyValue("Digit8", "8", kKeyUp));
|
||||
expected.Set(5, ExpectedKeyValue("KeyA", "a", kKeyUp));
|
||||
|
||||
EXPECT_EQ(*result, expected);
|
||||
ExpectKeyEventsEqual(ExpectedKeyValue("", "a", kKeyPress));
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(InputTest, ShiftCharacterKeys) {
|
||||
const int kExpectedShiftCharacterEventCount = 10;
|
||||
IN_PROC_BROWSER_TEST_F(InputTest, ShiftPrintableKeys) {
|
||||
keyboard_service_->SendKeyEvent(
|
||||
FakeKeyEvent(Key::LEFT_SHIFT, KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(FakeKeyEvent(Key::B, KeyEventType::PRESSED));
|
||||
CreateKeyEvent(Key::LEFT_SHIFT, KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
FakeKeyEvent(Key::KEY_3, KeyEventType::PRESSED));
|
||||
CreateKeyEvent(Key::B, KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
FakeKeyEvent(Key::SPACE, KeyEventType::PRESSED));
|
||||
CreateKeyEvent(Key::KEY_1, KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
FakeKeyEvent(Key::LEFT_SHIFT, KeyEventType::RELEASED));
|
||||
CreateKeyEvent(Key::SPACE, KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
FakeKeyEvent(Key::DOT, KeyEventType::PRESSED));
|
||||
frame_for_test_.navigation_listener().RunUntilTitleEquals(
|
||||
base::NumberToString(kExpectedShiftCharacterEventCount));
|
||||
CreateKeyEvent(Key::LEFT_SHIFT, KeyEventType::RELEASED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
CreateKeyEvent(Key::DOT, KeyEventType::PRESSED));
|
||||
|
||||
// Note that non-character keys (e.g. shift, control) only generate key down
|
||||
// and key up web events. They do not generate key pressed events.
|
||||
absl::optional<base::Value> result =
|
||||
cr_fuchsia::ExecuteJavaScript(frame_for_test_.ptr().get(), kKeyDicts);
|
||||
|
||||
base::ListValue expected;
|
||||
expected.Set(0, ExpectedKeyValue("ShiftLeft", "Shift", kKeyDown));
|
||||
expected.Set(1, ExpectedKeyValue("KeyB", "B", kKeyDown));
|
||||
expected.Set(2, ExpectedKeyValue("KeyB", "B", kKeyPress));
|
||||
expected.Set(3, ExpectedKeyValue("Digit3", "#", kKeyDown));
|
||||
expected.Set(4, ExpectedKeyValue("Digit3", "#", kKeyPress));
|
||||
expected.Set(5, ExpectedKeyValue("Space", " ", kKeyDown));
|
||||
expected.Set(6, ExpectedKeyValue("Space", " ", kKeyPress));
|
||||
expected.Set(7, ExpectedKeyValue("ShiftLeft", "Shift", kKeyUp));
|
||||
expected.Set(8, ExpectedKeyValue("Period", ".", kKeyDown));
|
||||
expected.Set(9, ExpectedKeyValue("Period", ".", kKeyPress));
|
||||
|
||||
EXPECT_EQ(*result, expected);
|
||||
ExpectKeyEventsEqual(ExpectedKeyValue("ShiftLeft", "Shift", kKeyDown),
|
||||
ExpectedKeyValue("KeyB", "B", kKeyDown),
|
||||
ExpectedKeyValue("KeyB", "B", kKeyPress),
|
||||
ExpectedKeyValue("Digit1", "!", kKeyDown),
|
||||
ExpectedKeyValue("Digit1", "!", kKeyPress),
|
||||
ExpectedKeyValue("Space", " ", kKeyDown),
|
||||
ExpectedKeyValue("Space", " ", kKeyPress),
|
||||
ExpectedKeyValue("ShiftLeft", "Shift", kKeyUp),
|
||||
ExpectedKeyValue("Period", ".", kKeyDown),
|
||||
ExpectedKeyValue("Period", ".", kKeyPress));
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(InputTest, ShiftNonCharacterKeys) {
|
||||
const int kExpectedShiftNonCharacterEventCount = 5;
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(InputTest, ShiftNonPrintableKeys) {
|
||||
keyboard_service_->SendKeyEvent(
|
||||
FakeKeyEvent(Key::RIGHT_SHIFT, KeyEventType::PRESSED));
|
||||
CreateKeyEvent(Key::RIGHT_SHIFT, KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
FakeKeyEvent(Key::ENTER, KeyEventType::PRESSED));
|
||||
CreateKeyEvent(Key::ENTER, KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
FakeKeyEvent(Key::LEFT_CTRL, KeyEventType::PRESSED));
|
||||
CreateKeyEvent(Key::LEFT_CTRL, KeyEventType::PRESSED));
|
||||
keyboard_service_->SendKeyEvent(
|
||||
FakeKeyEvent(Key::RIGHT_SHIFT, KeyEventType::RELEASED));
|
||||
frame_for_test_.navigation_listener().RunUntilTitleEquals(
|
||||
base::NumberToString(kExpectedShiftNonCharacterEventCount));
|
||||
CreateKeyEvent(Key::RIGHT_SHIFT, KeyEventType::RELEASED));
|
||||
|
||||
// Note that non-character keys (e.g. shift, control) only generate key down
|
||||
// and key up web events. They do not generate key pressed events.
|
||||
absl::optional<base::Value> result =
|
||||
cr_fuchsia::ExecuteJavaScript(frame_for_test_.ptr().get(), kKeyDicts);
|
||||
|
||||
base::ListValue expected;
|
||||
expected.Set(0, ExpectedKeyValue("ShiftRight", "Shift", kKeyDown));
|
||||
expected.Set(1, ExpectedKeyValue("Enter", "Enter", kKeyDown));
|
||||
expected.Set(2, ExpectedKeyValue("Enter", "Enter", kKeyPress));
|
||||
expected.Set(3, ExpectedKeyValue("ControlLeft", "Control", kKeyDown));
|
||||
expected.Set(4, ExpectedKeyValue("ShiftRight", "Shift", kKeyUp));
|
||||
|
||||
EXPECT_EQ(*result, expected);
|
||||
ExpectKeyEventsEqual(ExpectedKeyValue("ShiftRight", "Shift", kKeyDown),
|
||||
ExpectedKeyValue("Enter", "Enter", kKeyDown),
|
||||
ExpectedKeyValue("Enter", "Enter", kKeyPress),
|
||||
ExpectedKeyValue("ControlLeft", "Control", kKeyDown),
|
||||
ExpectedKeyValue("ShiftRight", "Shift", kKeyUp));
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(InputTest, Disconnect) {
|
||||
@ -251,4 +328,4 @@ IN_PROC_BROWSER_TEST_F(InputTest, Disconnect) {
|
||||
->GetBool());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
@ -8,8 +8,10 @@
|
||||
#include "base/logging.h"
|
||||
#include "base/notreached.h"
|
||||
#include "ui/events/fuchsia/input_event_sink.h"
|
||||
#include "ui/events/keycodes/dom/dom_code.h"
|
||||
#include "ui/events/keycodes/dom/keycode_converter.h"
|
||||
#include "ui/events/keycodes/keyboard_code_conversion.h"
|
||||
#include "ui/events/keycodes/keyboard_code_conversion_fuchsia.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
@ -34,6 +36,52 @@ int ModifiersToEventFlags(const fuchsia::ui::input3::Modifiers& modifiers) {
|
||||
return event_flags;
|
||||
}
|
||||
|
||||
absl::optional<EventType> ConvertKeyEventType(
|
||||
fuchsia::ui::input3::KeyEventType type) {
|
||||
switch (type) {
|
||||
case fuchsia::ui::input3::KeyEventType::PRESSED:
|
||||
return ET_KEY_PRESSED;
|
||||
break;
|
||||
case fuchsia::ui::input3::KeyEventType::RELEASED:
|
||||
return ET_KEY_RELEASED;
|
||||
break;
|
||||
case fuchsia::ui::input3::KeyEventType::SYNC:
|
||||
case fuchsia::ui::input3::KeyEventType::CANCEL:
|
||||
// SYNC and CANCEL should not generate ui::Events.
|
||||
return absl::nullopt;
|
||||
default:
|
||||
NOTREACHED() << "Unknown KeyEventType received: "
|
||||
<< static_cast<int>(type);
|
||||
return absl::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
// Creates an event for an event which has no |key|.
|
||||
absl::optional<ui::KeyEvent> ConvertToCharacterEvent(
|
||||
const fuchsia::ui::input3::KeyEvent& key_event) {
|
||||
DCHECK(!key_event.has_key());
|
||||
|
||||
absl::optional<EventType> event_type = ConvertKeyEventType(key_event.type());
|
||||
if (!event_type) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
if (event_type != ET_KEY_PRESSED) {
|
||||
// Keypress phase cannot be tracked on keypresses without hardware keys,
|
||||
// so only handle the "pressed" edge transition.
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
const uint32_t codepoint = key_event.key_meaning().codepoint();
|
||||
if (codepoint > std::numeric_limits<char16_t>::max()) {
|
||||
// TODO(crbug.com/1220260): Handle codepoints outside the BMP.
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
return ui::KeyEvent(*event_type, VKEY_UNKNOWN, DomCode::NONE,
|
||||
EF_IS_SYNTHESIZED, DomKey::FromCharacter(codepoint),
|
||||
base::TimeTicks::FromZxTime(key_event.timestamp()), true);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
KeyboardClient::KeyboardClient(fuchsia::ui::input3::Keyboard* keyboard_service,
|
||||
@ -58,6 +106,11 @@ KeyboardClient::~KeyboardClient() = default;
|
||||
void KeyboardClient::OnKeyEvent(
|
||||
fuchsia::ui::input3::KeyEvent key_event,
|
||||
fuchsia::ui::input3::KeyboardListener::OnKeyEventCallback callback) {
|
||||
if (!IsValid(key_event)) {
|
||||
binding_.Close(ZX_ERR_INVALID_ARGS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ProcessKeyEvent(key_event)) {
|
||||
callback(fuchsia::ui::input3::KeyEventStatus::HANDLED);
|
||||
} else {
|
||||
@ -65,45 +118,52 @@ void KeyboardClient::OnKeyEvent(
|
||||
}
|
||||
}
|
||||
|
||||
bool KeyboardClient::IsValid(const fuchsia::ui::input3::KeyEvent& key_event) {
|
||||
if (!key_event.has_type() || !key_event.has_timestamp())
|
||||
return false;
|
||||
|
||||
if (!key_event.has_key() && !key_event.has_key_meaning())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KeyboardClient::ProcessKeyEvent(
|
||||
const fuchsia::ui::input3::KeyEvent& key_event) {
|
||||
if (!key_event.has_type() || !key_event.has_key() ||
|
||||
!key_event.has_timestamp()) {
|
||||
LOG(ERROR) << "Could not process incomplete input3::KeyEvent.";
|
||||
const bool generate_character_event = !key_event.has_key();
|
||||
absl::optional<ui::KeyEvent> converted_event;
|
||||
if (generate_character_event) {
|
||||
converted_event = ConvertToCharacterEvent(key_event);
|
||||
} else {
|
||||
UpdateCachedModifiers(key_event);
|
||||
converted_event = ConvertKeystrokeEvent(key_event);
|
||||
}
|
||||
if (!converted_event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update activation flags of modifier keys (SHIFT, ALT, etc). This needs to
|
||||
// be done for all key event types.
|
||||
UpdatedCachedModifiers(key_event);
|
||||
event_sink_->DispatchEvent(&converted_event.value());
|
||||
return converted_event->handled();
|
||||
}
|
||||
|
||||
EventType event_type;
|
||||
switch (key_event.type()) {
|
||||
case fuchsia::ui::input3::KeyEventType::PRESSED:
|
||||
event_type = ET_KEY_PRESSED;
|
||||
break;
|
||||
case fuchsia::ui::input3::KeyEventType::RELEASED:
|
||||
event_type = ET_KEY_RELEASED;
|
||||
break;
|
||||
case fuchsia::ui::input3::KeyEventType::SYNC:
|
||||
case fuchsia::ui::input3::KeyEventType::CANCEL:
|
||||
// SYNC and CANCEL should not generate ui::Events.
|
||||
return true;
|
||||
default:
|
||||
NOTIMPLEMENTED() << "Unknown KeyEventType received: "
|
||||
<< static_cast<int>(event_type);
|
||||
return false;
|
||||
absl::optional<ui::KeyEvent> KeyboardClient::ConvertKeystrokeEvent(
|
||||
const fuchsia::ui::input3::KeyEvent& key_event) {
|
||||
DCHECK(key_event.has_key());
|
||||
|
||||
absl::optional<EventType> event_type = ConvertKeyEventType(key_event.type());
|
||||
if (!event_type) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
// Convert |key_event| to a ui::KeyEvent.
|
||||
DomCode dom_code =
|
||||
KeycodeConverter::UsbKeycodeToDomCode(static_cast<int>(key_event.key()));
|
||||
int event_flags = EventFlagsForCachedModifiers();
|
||||
if (key_event.has_modifiers())
|
||||
event_flags |= ModifiersToEventFlags(key_event.modifiers());
|
||||
|
||||
// TODO(https://crbug.com/1187257): Use input3.KeyMeaning instead of US layout
|
||||
// as the default.
|
||||
DomCode dom_code =
|
||||
KeycodeConverter::UsbKeycodeToDomCode(static_cast<int>(key_event.key()));
|
||||
DomKey dom_key;
|
||||
KeyboardCode key_code;
|
||||
if (!DomCodeToUsLayoutDomKey(dom_code, event_flags, &dom_key, &key_code)) {
|
||||
@ -111,16 +171,13 @@ bool KeyboardClient::ProcessKeyEvent(
|
||||
<< static_cast<uint32_t>(key_event.key());
|
||||
}
|
||||
|
||||
ui::KeyEvent ui_key_event(event_type, key_code, dom_code, event_flags,
|
||||
dom_key,
|
||||
base::TimeTicks::FromZxTime(key_event.timestamp()));
|
||||
event_sink_->DispatchEvent(&ui_key_event);
|
||||
return ui_key_event.handled();
|
||||
return ui::KeyEvent(*event_type, key_code, dom_code, event_flags, dom_key,
|
||||
base::TimeTicks::FromZxTime(key_event.timestamp()));
|
||||
}
|
||||
|
||||
// TODO(https://crbug.com/850697): Add additional modifiers as they become
|
||||
// supported.
|
||||
void KeyboardClient::UpdatedCachedModifiers(
|
||||
void KeyboardClient::UpdateCachedModifiers(
|
||||
const fuchsia::ui::input3::KeyEvent& key_event) {
|
||||
// A SYNC event indicates that the key was pressed while the view gained input
|
||||
// focus. A CANCEL event indicates the key was held when the view lost input
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <lib/fidl/cpp/binding.h>
|
||||
|
||||
#include "base/component_export.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
#include "ui/events/event.h"
|
||||
|
||||
namespace ui {
|
||||
@ -34,6 +35,12 @@ class COMPONENT_EXPORT(UI_BASE_IME_FUCHSIA) KeyboardClient
|
||||
fuchsia::ui::input3::KeyboardListener::OnKeyEventCallback callback) final;
|
||||
|
||||
private:
|
||||
bool IsValid(const fuchsia::ui::input3::KeyEvent& key_event);
|
||||
|
||||
// Returns an unset value if the |key_event| type is unsupported.
|
||||
absl::optional<ui::KeyEvent> ConvertKeystrokeEvent(
|
||||
const fuchsia::ui::input3::KeyEvent& key_event);
|
||||
|
||||
// Handles converting and propagating |key_event|. Returns false if critical
|
||||
// information about |key_event| is missing, or if the key's event type is not
|
||||
// supported.
|
||||
@ -42,7 +49,7 @@ class COMPONENT_EXPORT(UI_BASE_IME_FUCHSIA) KeyboardClient
|
||||
bool ProcessKeyEvent(const fuchsia::ui::input3::KeyEvent& key_event);
|
||||
|
||||
// Update the value of modifiers such as shift.
|
||||
void UpdatedCachedModifiers(const fuchsia::ui::input3::KeyEvent& key_event);
|
||||
void UpdateCachedModifiers(const fuchsia::ui::input3::KeyEvent& key_event);
|
||||
|
||||
// Translate state of locally tracked modifier keys (e.g. shift, alt) into
|
||||
// ui::Event flags.
|
||||
|
Reference in New Issue
Block a user