accelerators: Add HasKeyEvent function in KeyboardCapability
HasKeyEvent will be called by AcceleratorAliasConverter class to filter out accelerators with unsupported key code. Bug: b:216049298 Test: keyboard_capability_unittest.cc Change-Id: I1ea55ec1fa1fb5f55d8d30c960d25ee43295a268 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4346571 Commit-Queue: Wenyu Zhang <zhangwenyu@google.com> Reviewed-by: David Padlipsky <dpad@google.com> Cr-Commit-Position: refs/heads/main@{#1120831}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
5b13c56c35
commit
1e4a86ec30
ash/events
ui/chromeos/events
@ -34,6 +34,27 @@ constexpr char kKbdTopRowLayoutDrallionTag[] = "4";
|
||||
constexpr int kDeviceId1 = 5;
|
||||
constexpr int kDeviceId2 = 10;
|
||||
|
||||
ui::InputDeviceType INTERNAL = ui::InputDeviceType::INPUT_DEVICE_INTERNAL;
|
||||
ui::InputDeviceType EXTERNAL_USB = ui::InputDeviceType::INPUT_DEVICE_USB;
|
||||
ui::InputDeviceType EXTERNAL_BLUETOOTH =
|
||||
ui::InputDeviceType::INPUT_DEVICE_BLUETOOTH;
|
||||
// For INPUT_DEVICE_UNKNOWN type, we treat it as external keyboard.
|
||||
ui::InputDeviceType EXTERNAL_UNKNOWN =
|
||||
ui::InputDeviceType::INPUT_DEVICE_UNKNOWN;
|
||||
|
||||
struct KeyEventTestData {
|
||||
// All currently connected keyboards' connection type, e.g.
|
||||
// INPUT_DEVICE_INTERNAL.
|
||||
std::vector<ui::InputDeviceType> keyboard_connection_types;
|
||||
// All currently connected keyboards' layout types.
|
||||
std::vector<std::string> keyboard_layout_types;
|
||||
ui::KeyboardCode key_code;
|
||||
// Expected result of whether this key event exists on each keyboard.
|
||||
std::vector<bool> expected_has_key_event;
|
||||
// Expected result of whether this key event exists on all connected.
|
||||
bool expected_has_key_event_on_any_keyboard;
|
||||
};
|
||||
|
||||
// NOTE: This only creates a simple ui::InputDevice based on a device
|
||||
// capabilities report; it is not suitable for subclasses of ui::InputDevice.
|
||||
ui::InputDevice InputDeviceFromCapabilities(
|
||||
@ -75,6 +96,11 @@ class FakeDeviceManager {
|
||||
std::move(sysfs_properties));
|
||||
}
|
||||
|
||||
void RemoveAllDevices() {
|
||||
fake_udev_.Reset();
|
||||
fake_keyboard_devices_.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
testing::FakeUdevLoader fake_udev_;
|
||||
std::vector<ui::InputDevice> fake_keyboard_devices_;
|
||||
@ -329,6 +355,21 @@ TEST_F(KeyboardCapabilityTest, TestRemoveDevicesFromList) {
|
||||
ASSERT_EQ(0u, keyboard_capability_->keyboard_info_map().size());
|
||||
}
|
||||
|
||||
TEST_F(KeyboardCapabilityTest, TestIsTopRowKey) {
|
||||
for (const auto& [key_code, _] : ui::kLayout1TopRowKeyToFKeyMap) {
|
||||
EXPECT_TRUE(keyboard_capability_->IsTopRowKey(key_code));
|
||||
}
|
||||
for (const auto& [key_code, _] : ui::kLayout2TopRowKeyToFKeyMap) {
|
||||
EXPECT_TRUE(keyboard_capability_->IsTopRowKey(key_code));
|
||||
}
|
||||
for (const auto& [key_code, _] : ui::kLayoutWilcoDrallionTopRowKeyToFKeyMap) {
|
||||
EXPECT_TRUE(keyboard_capability_->IsTopRowKey(key_code));
|
||||
}
|
||||
|
||||
// A key not in any of the above maps is not a top row key.
|
||||
EXPECT_FALSE(keyboard_capability_->IsTopRowKey(ui::KeyboardCode::VKEY_A));
|
||||
}
|
||||
|
||||
class ModifierKeyTest : public KeyboardCapabilityTest,
|
||||
public testing::WithParamInterface<
|
||||
std::tuple<ui::DeviceCapabilities,
|
||||
@ -384,4 +425,113 @@ TEST_P(ModifierKeyTest, TestGetModifierKeys) {
|
||||
EXPECT_EQ(expected_modifier_keys, modifier_keys);
|
||||
}
|
||||
|
||||
class KeyEventTest : public KeyboardCapabilityTest,
|
||||
public testing::WithParamInterface<KeyEventTestData> {};
|
||||
|
||||
// Tests that given the keyboard connection type and layout type, check if this
|
||||
// keyboard has a specific key event.
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
All,
|
||||
KeyEventTest,
|
||||
testing::ValuesIn(std::vector<KeyEventTestData>{
|
||||
// Testing top row keys.
|
||||
{{INTERNAL},
|
||||
{kKbdTopRowLayout1Tag},
|
||||
ui::VKEY_BROWSER_FORWARD,
|
||||
{true},
|
||||
true},
|
||||
{{EXTERNAL_BLUETOOTH},
|
||||
{kKbdTopRowLayout1Tag},
|
||||
ui::VKEY_ZOOM,
|
||||
{true},
|
||||
true},
|
||||
{{EXTERNAL_USB},
|
||||
{kKbdTopRowLayout1Tag},
|
||||
ui::VKEY_MEDIA_PLAY_PAUSE,
|
||||
{false},
|
||||
false},
|
||||
{{INTERNAL},
|
||||
{kKbdTopRowLayout2Tag},
|
||||
ui::VKEY_BROWSER_FORWARD,
|
||||
{false},
|
||||
false},
|
||||
{{EXTERNAL_UNKNOWN},
|
||||
{kKbdTopRowLayout2Tag},
|
||||
ui::VKEY_MEDIA_PLAY_PAUSE,
|
||||
{true},
|
||||
true},
|
||||
{{INTERNAL}, {kKbdTopRowLayoutWilcoTag}, ui::VKEY_ZOOM, {true}, true},
|
||||
{{EXTERNAL_BLUETOOTH},
|
||||
{kKbdTopRowLayoutDrallionTag},
|
||||
ui::VKEY_BRIGHTNESS_UP,
|
||||
{true},
|
||||
true},
|
||||
{{INTERNAL, EXTERNAL_BLUETOOTH},
|
||||
{kKbdTopRowLayout1Tag, kKbdTopRowLayout2Tag},
|
||||
ui::VKEY_BROWSER_FORWARD,
|
||||
{true, false},
|
||||
true},
|
||||
{{INTERNAL, EXTERNAL_BLUETOOTH},
|
||||
{kKbdTopRowLayout2Tag, kKbdTopRowLayout2Tag},
|
||||
ui::VKEY_BROWSER_FORWARD,
|
||||
{false, false},
|
||||
false},
|
||||
{{INTERNAL, EXTERNAL_USB, EXTERNAL_BLUETOOTH},
|
||||
{kKbdTopRowLayout1Tag, kKbdTopRowLayout2Tag, kKbdTopRowLayoutWilcoTag},
|
||||
ui::VKEY_VOLUME_UP,
|
||||
{true, true, true},
|
||||
true},
|
||||
|
||||
// Testing six pack keys.
|
||||
{{INTERNAL}, {kKbdTopRowLayout1Tag}, ui::VKEY_INSERT, {false}, false},
|
||||
{{EXTERNAL_USB}, {kKbdTopRowLayout1Tag}, ui::VKEY_INSERT, {true}, true},
|
||||
{{INTERNAL, EXTERNAL_BLUETOOTH},
|
||||
{kKbdTopRowLayout1Tag, kKbdTopRowLayoutWilcoTag},
|
||||
ui::VKEY_HOME,
|
||||
{false, true},
|
||||
true},
|
||||
|
||||
// Testing other keys.
|
||||
{{INTERNAL}, {kKbdTopRowLayout1Tag}, ui::VKEY_LEFT, {true}, true},
|
||||
{{EXTERNAL_BLUETOOTH},
|
||||
{kKbdTopRowLayout2Tag},
|
||||
ui::VKEY_ESCAPE,
|
||||
{true},
|
||||
true},
|
||||
{{EXTERNAL_UNKNOWN},
|
||||
{kKbdTopRowLayoutWilcoTag},
|
||||
ui::VKEY_A,
|
||||
{true},
|
||||
true},
|
||||
{{INTERNAL}, {kKbdTopRowLayoutDrallionTag}, ui::VKEY_2, {true}, true},
|
||||
}));
|
||||
|
||||
TEST_P(KeyEventTest, TestHasKeyEvent) {
|
||||
auto [keyboard_connection_types, keyboard_layout_types, key_code,
|
||||
expected_has_key_event, expected_has_key_event_on_any_keyboard] =
|
||||
GetParam();
|
||||
|
||||
fake_keyboard_manager_->RemoveAllDevices();
|
||||
for (size_t i = 0; i < keyboard_layout_types.size(); i++) {
|
||||
std::string layout = keyboard_layout_types[i];
|
||||
ui::InputDevice fake_keyboard(
|
||||
/*id=*/i, /*type=*/keyboard_connection_types[i],
|
||||
/*name=*/layout);
|
||||
fake_keyboard.sys_path = base::FilePath("path" + layout);
|
||||
fake_keyboard_manager_->AddFakeKeyboard(fake_keyboard, layout);
|
||||
|
||||
if (expected_has_key_event[i]) {
|
||||
EXPECT_TRUE(keyboard_capability_->HasKeyEvent(key_code, fake_keyboard));
|
||||
} else {
|
||||
EXPECT_FALSE(keyboard_capability_->HasKeyEvent(key_code, fake_keyboard));
|
||||
}
|
||||
}
|
||||
|
||||
if (expected_has_key_event_on_any_keyboard) {
|
||||
EXPECT_TRUE(keyboard_capability_->HasKeyEventOnAnyKeyboard(key_code));
|
||||
} else {
|
||||
EXPECT_FALSE(keyboard_capability_->HasKeyEventOnAnyKeyboard(key_code));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ash
|
||||
|
@ -166,6 +166,26 @@ bool KeyboardCapability::HasLauncherButton(
|
||||
KeyboardTopRowLayout::kKbdTopRowLayout2;
|
||||
}
|
||||
|
||||
// static
|
||||
bool KeyboardCapability::IsTopRowKey(const KeyboardCode& key_code) {
|
||||
// A set that includes all top row keys from different keyboards.
|
||||
static const base::NoDestructor<base::flat_set<KeyboardCode>>
|
||||
top_row_action_keys({
|
||||
KeyboardCode::VKEY_BROWSER_BACK,
|
||||
KeyboardCode::VKEY_BROWSER_FORWARD,
|
||||
KeyboardCode::VKEY_BROWSER_REFRESH,
|
||||
KeyboardCode::VKEY_ZOOM,
|
||||
KeyboardCode::VKEY_MEDIA_LAUNCH_APP1,
|
||||
KeyboardCode::VKEY_BRIGHTNESS_DOWN,
|
||||
KeyboardCode::VKEY_BRIGHTNESS_UP,
|
||||
KeyboardCode::VKEY_MEDIA_PLAY_PAUSE,
|
||||
KeyboardCode::VKEY_VOLUME_MUTE,
|
||||
KeyboardCode::VKEY_VOLUME_DOWN,
|
||||
KeyboardCode::VKEY_VOLUME_UP,
|
||||
});
|
||||
return base::Contains(*top_row_action_keys, key_code);
|
||||
}
|
||||
|
||||
// static
|
||||
bool KeyboardCapability::HasSixPackKey(const InputDevice& keyboard) {
|
||||
// If the keyboard is an internal keyboard, return false. Otherwise, return
|
||||
@ -298,4 +318,44 @@ void KeyboardCapability::TrimKeyboardInfoMap() {
|
||||
}
|
||||
}
|
||||
|
||||
bool KeyboardCapability::HasKeyEvent(const KeyboardCode& key_code,
|
||||
const InputDevice& keyboard) const {
|
||||
// Handle top row keys.
|
||||
if (IsTopRowKey(key_code)) {
|
||||
KeyboardTopRowLayout layout =
|
||||
EventRewriterChromeOS::GetKeyboardTopRowLayout(keyboard);
|
||||
switch (layout) {
|
||||
case KeyboardTopRowLayout::kKbdTopRowLayout1:
|
||||
return kLayout1TopRowKeyToFKeyMap.contains(key_code);
|
||||
case KeyboardTopRowLayout::kKbdTopRowLayout2:
|
||||
return kLayout2TopRowKeyToFKeyMap.contains(key_code);
|
||||
case KeyboardTopRowLayout::kKbdTopRowLayoutWilco:
|
||||
case KeyboardTopRowLayout::kKbdTopRowLayoutDrallion:
|
||||
return kLayoutWilcoDrallionTopRowKeyToFKeyMap.contains(key_code);
|
||||
case KeyboardTopRowLayout::kKbdTopRowLayoutCustom:
|
||||
// TODO(zhangwenyu): Handle custom vivaldi layout.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle six pack keys.
|
||||
if (IsSixPackKey(key_code)) {
|
||||
return HasSixPackKey(keyboard);
|
||||
}
|
||||
|
||||
// TODO(zhangwenyu): check other specific keys, e.g. assistant key.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KeyboardCapability::HasKeyEventOnAnyKeyboard(
|
||||
const KeyboardCode& key_code) const {
|
||||
for (const ui::InputDevice& keyboard :
|
||||
ui::DeviceDataManager::GetInstance()->GetKeyboardDevices()) {
|
||||
if (HasKeyEvent(key_code, keyboard)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
|
@ -177,6 +177,9 @@ class KeyboardCapability : public InputDeviceEventObserver {
|
||||
// Enable or disable top row keys as F-Keys.
|
||||
void SetTopRowKeysAsFKeysEnabledForTesting(bool enabled) const;
|
||||
|
||||
// Check if a key code is one of the top row keys.
|
||||
static bool IsTopRowKey(const KeyboardCode& key_code);
|
||||
|
||||
// Check if a key code is one of the six pack keys.
|
||||
static bool IsSixPackKey(const KeyboardCode& key_code);
|
||||
|
||||
@ -217,6 +220,13 @@ class KeyboardCapability : public InputDeviceEventObserver {
|
||||
void OnDeviceListsComplete() override;
|
||||
void OnInputDeviceConfigurationChanged(uint8_t input_device_types) override;
|
||||
|
||||
// Check if a specific key event exists on a given keyboard.
|
||||
bool HasKeyEvent(const KeyboardCode& key_code,
|
||||
const InputDevice& keyboard) const;
|
||||
|
||||
// Check if any of the connected keyboards has a specific key event.
|
||||
bool HasKeyEventOnAnyKeyboard(const KeyboardCode& key_code) const;
|
||||
|
||||
const base::flat_map<int, KeyboardInfo>& keyboard_info_map() {
|
||||
return keyboard_info_map_;
|
||||
}
|
||||
|
Reference in New Issue
Block a user