Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions shell/platform/fuchsia/flutter/keyboard.cc
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ bool Keyboard::IsShift() {
}

bool Keyboard::IsKeys() {
return (static_cast<uint64_t>(last_event_.key()) & 0xFFFF0000) == 0x00070000;
return LastHIDUsagePage() == 0x7;
}

uint32_t Keyboard::Modifiers() {
Expand All @@ -298,21 +298,39 @@ uint32_t Keyboard::Modifiers() {
}

uint32_t Keyboard::LastCodePoint() {
// TODO(https://github.com/flutter/flutter/issues/93891):
// `KeyEvent::key_meaning` should be used here to do key mapping before US
// QWERTY is applied. The US QWERTY should be applied only if `key_meaning`
// is not available.
static const int qwerty_map_size =
sizeof(QWERTY_TO_CODE_POINTS) / sizeof(QWERTY_TO_CODE_POINTS[0]);
if (!IsKeys()) {
return 0;
}
const auto usage = LastHIDUsage();
const auto usage = LastHIDUsageID();
if (usage < qwerty_map_size) {
return QWERTY_TO_CODE_POINTS[usage][IsShift() & 1];
}
// Any other keys don't have a code point.
return 0;
}

uint32_t Keyboard::GetLastKey() {
// TODO(https://github.com/flutter/flutter/issues/93898): key is not always
// set. Figure out what to do then.
return static_cast<uint32_t>(last_event_.key());
}

uint32_t Keyboard::LastHIDUsage() {
return static_cast<uint64_t>(last_event_.key()) & 0xFFFF;
return GetLastKey() & 0xFFFFFFFF;
}

uint16_t Keyboard::LastHIDUsageID() {
return GetLastKey() & 0xFFFF;
}

uint16_t Keyboard::LastHIDUsagePage() {
return (GetLastKey() >> 16) & 0xFFFF;
}

} // namespace flutter_runner
22 changes: 21 additions & 1 deletion shell/platform/fuchsia/flutter/keyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,26 @@ class Keyboard final {
// the state of the modifier keys.
uint32_t LastCodePoint();

// Gets the last encountered HID usage.
// Gets the last encountered HID usage. This is a 32-bit number, with the
// upper 16 bits equal to `LastHidUsagePage()`, and the lower 16 bits equal
// to `LastHIDUsageID()`.
//
// The key corresponding to A will have the usage 0x7004. This function will
// return 0x7004 in that case.
uint32_t LastHIDUsage();

// Gets the last encountered HID usage page.
//
// The key corresponding to A will have the usage 0x7004. This function will
// return 0x7 in that case.
uint16_t LastHIDUsagePage();

// Gets the last encountered HID usage ID.
//
// The key corresponding to A will have the usage 0x7004. This function will
// return 0x4 in that case.
uint16_t LastHIDUsageID();

private:
// Return true if any level shift is active.
bool IsShift();
Expand All @@ -39,6 +56,9 @@ class Keyboard final {
// point associated.
bool IsKeys();

// Returns the value of the last key as a uint32_t.
uint32_t GetLastKey();

// Set to false until any event is received.
bool any_events_received_ : 1;

Expand Down
30 changes: 29 additions & 1 deletion shell/platform/fuchsia/flutter/keyboard_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,40 @@ class KeyboardTest : public testing::Test {
}

// Converts a pressed key to usage value.
uint32_t ToUsage(Key key) { return static_cast<uint64_t>(key) & 0xFFFF; }
uint32_t ToUsage(Key key) { return static_cast<uint64_t>(key) & 0xFFFFFFFF; }

private:
zx_time_t timestamp_ = 0;
};

// Checks whether the HID usage, page and ID values are reported correctly.
TEST_F(KeyboardTest, UsageValues) {
std::vector<KeyEvent> keys;
keys.emplace_back(NewKeyEvent(KeyEventType::SYNC, Key::CAPS_LOCK));
Keyboard keyboard;
ConsumeEvents(&keyboard, keys);

// Values for Caps Lock.
// See spec at:
// https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/fidl/fuchsia.input/keys.fidl;l=177;drc=e3b39f2b57e720770773b857feca4f770ee0619e
EXPECT_EQ(0x07u, keyboard.LastHIDUsagePage());
EXPECT_EQ(0x39u, keyboard.LastHIDUsageID());
EXPECT_EQ(0x70039u, keyboard.LastHIDUsage());

// Try also an usage that is not on page 7. This one is on page 0x0C.
// See spec at:
// https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/fidl/fuchsia.input/keys.fidl;l=339;drc=e3b39f2b57e720770773b857feca4f770ee0619e
// Note that Fuchsia does not define constants for every key you may think of,
// rather only those that we had the need for. However it is not an issue
// to add more keys if needed.
keys.clear();
keys.emplace_back(NewKeyEvent(KeyEventType::SYNC, Key::MEDIA_MUTE));
ConsumeEvents(&keyboard, keys);
EXPECT_EQ(0x0Cu, keyboard.LastHIDUsagePage());
EXPECT_EQ(0xE2u, keyboard.LastHIDUsageID());
EXPECT_EQ(0xC00E2u, keyboard.LastHIDUsage());
}

// This test checks that if a caps lock has been pressed when we didn't have
// focus, the effect of caps lock remains. Only this first test case is
// commented to explain how the test case works.
Expand Down
15 changes: 8 additions & 7 deletions shell/platform/fuchsia/flutter/platform_view_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1250,49 +1250,50 @@ TEST_F(PlatformViewTests, OnKeyEvent) {

std::vector<EventFlow> events;
// Press A. Get 'a'.
// The HID usage for the key A is 0x70004, or 458756.
events.emplace_back(EventFlow{
MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
fuchsia::input::Key::A),
fuchsia::ui::input3::KeyEventStatus::HANDLED,
R"({"type":"keydown","keymap":"fuchsia","hidUsage":4,"codePoint":97,"modifiers":0})",
R"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":97,"modifiers":0})",
});
// Release A. Get 'a' release.
events.emplace_back(EventFlow{
MakeEvent(fuchsia::ui::input3::KeyEventType::RELEASED, std::nullopt,
fuchsia::input::Key::A),
fuchsia::ui::input3::KeyEventStatus::HANDLED,
R"({"type":"keyup","keymap":"fuchsia","hidUsage":4,"codePoint":97,"modifiers":0})",
R"({"type":"keyup","keymap":"fuchsia","hidUsage":458756,"codePoint":97,"modifiers":0})",
});
// Press CAPS_LOCK. Modifier now active.
events.emplace_back(EventFlow{
MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED,
fuchsia::ui::input3::Modifiers::CAPS_LOCK,
fuchsia::input::Key::CAPS_LOCK),
fuchsia::ui::input3::KeyEventStatus::HANDLED,
R"({"type":"keydown","keymap":"fuchsia","hidUsage":57,"codePoint":0,"modifiers":1})",
R"({"type":"keydown","keymap":"fuchsia","hidUsage":458809,"codePoint":0,"modifiers":1})",
});
// Pres A. Get 'A'.
// Press A. Get 'A'.
events.emplace_back(EventFlow{
MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
fuchsia::input::Key::A),
fuchsia::ui::input3::KeyEventStatus::HANDLED,
R"({"type":"keydown","keymap":"fuchsia","hidUsage":4,"codePoint":65,"modifiers":1})",
R"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":65,"modifiers":1})",
});
// Release CAPS_LOCK.
events.emplace_back(EventFlow{
MakeEvent(fuchsia::ui::input3::KeyEventType::RELEASED,
fuchsia::ui::input3::Modifiers::CAPS_LOCK,
fuchsia::input::Key::CAPS_LOCK),
fuchsia::ui::input3::KeyEventStatus::HANDLED,
R"({"type":"keyup","keymap":"fuchsia","hidUsage":57,"codePoint":0,"modifiers":1})",
R"({"type":"keyup","keymap":"fuchsia","hidUsage":458809,"codePoint":0,"modifiers":1})",
});
// Press A again. This time get 'A'.
// CAPS_LOCK is latched active even if it was just released.
events.emplace_back(EventFlow{
MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
fuchsia::input::Key::A),
fuchsia::ui::input3::KeyEventStatus::HANDLED,
R"({"type":"keydown","keymap":"fuchsia","hidUsage":4,"codePoint":65,"modifiers":1})",
R"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":65,"modifiers":1})",
});

for (const auto& event : events) {
Expand Down