Commit be12e75c authored by Joe Downing's avatar Joe Downing Committed by Commit Bot

[KeyboardMap] Base class and Windows implementation

This CL contains a base class and unittests for generating
a keyboard layout map for the KeyboardMap API.  It also
includes a a Windows implementation which uses the base
class.

BUG=832811

Change-Id: I7ff20cf8b2a34cf8c7a9bbe9609e40f39bb89634
Reviewed-on: https://chromium-review.googlesource.com/1077596
Commit-Queue: Joe Downing <joedow@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarGary Kacmarcik <garykac@chromium.org>
Cr-Commit-Position: refs/heads/master@{#564918}
parent b9413fec
...@@ -17,16 +17,23 @@ if (is_ios) { ...@@ -17,16 +17,23 @@ if (is_ios) {
} }
static_library("dom_keycode_converter") { static_library("dom_keycode_converter") {
sources = [ public = [
"keycodes/dom/dom_code.h", "keycodes/dom/dom_code.h",
"keycodes/dom/dom_key.h", "keycodes/dom/dom_key.h",
"keycodes/dom/dom_keyboard_layout.h",
"keycodes/dom/dom_keyboard_layout_manager.h",
"keycodes/dom/dom_keyboard_layout_map.h",
"keycodes/dom/keycode_converter.h",
]
sources = [
"keycodes/dom/dom_key_data.inc", "keycodes/dom/dom_key_data.inc",
"keycodes/dom/dom_keyboard_layout.cc", "keycodes/dom/dom_keyboard_layout.cc",
"keycodes/dom/dom_keyboard_layout.h",
"keycodes/dom/dom_keyboard_layout_manager.cc", "keycodes/dom/dom_keyboard_layout_manager.cc",
"keycodes/dom/dom_keyboard_layout_manager.h", "keycodes/dom/dom_keyboard_layout_map_base.cc",
"keycodes/dom/dom_keyboard_layout_map_base.h",
"keycodes/dom/dom_keyboard_layout_map_win.cc",
"keycodes/dom/keycode_converter.cc", "keycodes/dom/keycode_converter.cc",
"keycodes/dom/keycode_converter.h",
"keycodes/dom/keycode_converter_data.inc", "keycodes/dom/keycode_converter_data.inc",
] ]
...@@ -37,6 +44,18 @@ static_library("dom_keycode_converter") { ...@@ -37,6 +44,18 @@ static_library("dom_keycode_converter") {
if (!is_ios) { if (!is_ios) {
deps += [ "//ipc:param_traits" ] deps += [ "//ipc:param_traits" ]
} }
# Expose the internals of this target to other packages in this BUILD file
# so the unit tests can access the private header files.
# Note: Only 'events_unittests' needs access in this file, however it uses a
# template which generates different target names on different platforms.
# TODO(joedow): Remove the ash friend. There is a cc file in that directory
# which includes the private inc file, we should expose the funcitonality they
# need in the KeycodeConverter and then clean this up.
friend = [
":*",
"//ash/components/shortcut_viewer:lib",
]
} }
source_set("event_constants") { source_set("event_constants") {
...@@ -429,6 +448,7 @@ if (!is_ios) { ...@@ -429,6 +448,7 @@ if (!is_ios) {
"gesture_detection/velocity_tracker_unittest.cc", "gesture_detection/velocity_tracker_unittest.cc",
"gestures/blink/web_gesture_curve_impl_unittest.cc", "gestures/blink/web_gesture_curve_impl_unittest.cc",
"gestures/fling_curve_unittest.cc", "gestures/fling_curve_unittest.cc",
"keycodes/dom/dom_keyboard_layout_map_unittest.cc",
"keycodes/dom/keycode_converter_unittest.cc", "keycodes/dom/keycode_converter_unittest.cc",
"keycodes/keyboard_code_conversion_unittest.cc", "keycodes/keyboard_code_conversion_unittest.cc",
"keycodes/platform_key_map_win_unittest.cc", "keycodes/platform_key_map_win_unittest.cc",
......
// Copyright 2018 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 UI_EVENTS_KEYCODES_DOM_DOM_KEYBOARD_LAYOUT_MAP_H_
#define UI_EVENTS_KEYCODES_DOM_DOM_KEYBOARD_LAYOUT_MAP_H_
#include <string>
#include "base/containers/flat_map.h"
namespace ui {
// Generates a map representing the physical keys on the current keyboard
// layout. Each entry maps a DomCode string to a DomKey string. The current
// layout is determined by the underlying OS platform which may be the active
// layout or the first ASCII capable layout available.
// More info at: https://wicg.github.io/keyboard-map/
base::flat_map<std::string, std::string> GenerateDomKeyboardLayoutMap();
} // namespace ui
#endif // UI_EVENTS_KEYCODES_DOM_DOM_KEYBOARD_LAYOUT_MAP_H_
// Copyright 2018 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 "ui/events/keycodes/dom/dom_keyboard_layout_map_base.h"
#include <cstdint>
#include <memory>
#include <string>
#include "base/logging.h"
#include "base/stl_util.h"
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/events/keycodes/dom/dom_keyboard_layout_manager.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
namespace ui {
DomKeyboardLayoutMapBase::DomKeyboardLayoutMapBase() = default;
DomKeyboardLayoutMapBase::~DomKeyboardLayoutMapBase() = default;
base::flat_map<std::string, std::string> DomKeyboardLayoutMapBase::Generate() {
uint32_t keyboard_layout_count = GetKeyboardLayoutCount();
if (!keyboard_layout_count)
return {};
std::unique_ptr<ui::DomKeyboardLayoutManager> keyboard_layout_manager =
std::make_unique<ui::DomKeyboardLayoutManager>();
for (size_t i = 0; i < keyboard_layout_count; i++) {
DomKeyboardLayout* const dom_keyboard_layout =
keyboard_layout_manager->GetLayout(i);
PopulateLayout(i, dom_keyboard_layout);
if (dom_keyboard_layout->IsAsciiCapable())
return dom_keyboard_layout->GetMap();
}
return keyboard_layout_manager->GetFirstAsciiCapableLayout()->GetMap();
}
void DomKeyboardLayoutMapBase::PopulateLayout(uint32_t keyboard_layout_index,
ui::DomKeyboardLayout* layout) {
DCHECK(layout);
for (size_t entry = 0; entry < ui::kWritingSystemKeyDomCodeEntries; entry++) {
ui::DomCode dom_code = ui::writing_system_key_domcodes[entry];
ui::DomKey dom_key =
GetDomKeyFromDomCodeForLayout(dom_code, keyboard_layout_index);
if (dom_key == ui::DomKey::NONE)
continue;
uint32_t unicode_value = 0;
if (dom_key.IsCharacter())
unicode_value = dom_key.ToCharacter();
else if (dom_key.IsDeadKey())
unicode_value = dom_key.ToDeadKeyCombiningCharacter();
if (unicode_value != 0)
layout->AddKeyMapping(dom_code, unicode_value);
}
}
} // namespace ui
// Copyright 2018 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 UI_EVENTS_KEYCODES_DOM_DOM_KEYBOARD_LAYOUT_MAP_BASE_H_
#define UI_EVENTS_KEYCODES_DOM_DOM_KEYBOARD_LAYOUT_MAP_BASE_H_
#include <cstdint>
#include <string>
#include "base/containers/flat_map.h"
#include "base/macros.h"
namespace ui {
enum class DomCode;
class DomKey;
class DomKeyboardLayout;
// Provides the platform agnostic logic for generating a dom keyboard layout
// map, subclassing is required for each platform to retrieve the layout
// information from the underlying operating system.
class DomKeyboardLayoutMapBase {
public:
virtual ~DomKeyboardLayoutMapBase();
// Generates a KeyboardLayoutMap based on the keyboard layouts provided by the
// operating system.
base::flat_map<std::string, std::string> Generate();
protected:
DomKeyboardLayoutMapBase();
// Returns the number of keyboard layouts available from the operating system.
// It could represent the set of all layouts, if available, or only the active
// layout, depending on what the platform provides.
virtual uint32_t GetKeyboardLayoutCount() = 0;
// Returns an initialized DomKey using the value of |dom_code| associated with
// |keyboard_layout_index| using platform APIs. |keyboard_layout_index| is a
// value in the interval of [0, keyboard_layout_count) which is used by the
// platform implementation to choose the layout to map |dom_code| to.
virtual ui::DomKey GetDomKeyFromDomCodeForLayout(
ui::DomCode dom_code,
uint32_t keyboard_layout_index) = 0;
private:
// Retrieves each writing system key from the layout associated with
// |keyboard_layout_index| and populates |keyboard_layout| with the
// corresponding dom key.
void PopulateLayout(uint32_t keyboard_layout_index,
ui::DomKeyboardLayout* keyboard_layout);
DISALLOW_COPY_AND_ASSIGN(DomKeyboardLayoutMapBase);
};
} // namespace ui
#endif // UI_EVENTS_KEYCODES_DOM_DOM_KEYBOARD_LAYOUT_MAP_BASE_H_
// Copyright 2018 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 <string>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/events/keycodes/dom/dom_keyboard_layout.h"
#include "ui/events/keycodes/dom/dom_keyboard_layout_manager.h"
#include "ui/events/keycodes/dom/dom_keyboard_layout_map_base.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
namespace ui {
namespace {
// Represents a keyboard layout where every key is ASCII capable.
constexpr uint32_t kKeyboardLayoutWithAllValidKeys = 1;
// Layout contains all valid keys so this number represents a complete layout.
constexpr uint32_t kKeyboardLayoutWithAllValidKeysCount = 50;
// Represents a keyboard layout where every alpha key is ASCII capable.
constexpr uint32_t kKeyboardLayoutWithAllValidAlphaKeys = 2;
// Layout contains all valid alpha keys so this number represents a complete
// layout minus two INTL keys which are subbed.
constexpr uint32_t kKeyboardLayoutWithAllValidAlphaKeysCount = 48;
// Represents a keyboard layout where some alpha keys are ASCII capable.
constexpr uint32_t kKeyboardLayoutWithSomeValidKeys = 3;
// The mostly valid keyboard does not pass the 'IsAsciiCapable()' test however
// the DomKeyboardLayoutManager will pass the first layout it has if it doesn't
// find an ASCII capable layout first.
constexpr uint32_t kKeyboardLayoutWithSomeValidKeysCount = 47;
// Represents a keyboard layout where no alpha keys are ASCII capable.
constexpr uint32_t kKeyboardLayoutWithNoValidKeys = 4;
constexpr uint32_t kKeyboardLayoutWithNoValidKeysCount = 0;
DomKey GetKeyFromFullLookupTable(DomCode dom_code) {
// Includes all DomCodes used in |writing_system_key_domcodes|. Tests can
// use this table to retrieve valid DomKeys for each DomCode to simulate a
// 'complete' keyboard layout. They can also use this to construct a partial
// layout with valid DomKey values for the populated entries.
static base::flat_map<DomCode, DomKey> kFullLookupTable(
{{DomCode::DIGIT0, DomKey::Constant<'0'>::Character},
{DomCode::DIGIT1, DomKey::Constant<'1'>::Character},
{DomCode::DIGIT2, DomKey::Constant<'2'>::Character},
{DomCode::DIGIT3, DomKey::Constant<'3'>::Character},
{DomCode::DIGIT4, DomKey::Constant<'4'>::Character},
{DomCode::DIGIT5, DomKey::Constant<'5'>::Character},
{DomCode::DIGIT6, DomKey::Constant<'6'>::Character},
{DomCode::DIGIT7, DomKey::Constant<'7'>::Character},
{DomCode::DIGIT8, DomKey::Constant<'8'>::Character},
{DomCode::DIGIT9, DomKey::Constant<'9'>::Character},
{DomCode::US_A, DomKey::Constant<'a'>::Character},
{DomCode::US_B, DomKey::Constant<'b'>::Character},
{DomCode::US_C, DomKey::Constant<'c'>::Character},
{DomCode::US_D, DomKey::Constant<'d'>::Character},
{DomCode::US_E, DomKey::Constant<'e'>::Character},
{DomCode::US_F, DomKey::Constant<'f'>::Character},
{DomCode::US_G, DomKey::Constant<'g'>::Character},
{DomCode::US_H, DomKey::Constant<'h'>::Character},
{DomCode::US_I, DomKey::Constant<'i'>::Character},
{DomCode::US_J, DomKey::Constant<'j'>::Character},
{DomCode::US_K, DomKey::Constant<'k'>::Character},
{DomCode::US_L, DomKey::Constant<'l'>::Character},
{DomCode::US_M, DomKey::Constant<'m'>::Character},
{DomCode::US_N, DomKey::Constant<'n'>::Character},
{DomCode::US_O, DomKey::Constant<'o'>::Character},
{DomCode::US_P, DomKey::Constant<'p'>::Character},
{DomCode::US_Q, DomKey::Constant<'q'>::Character},
{DomCode::US_R, DomKey::Constant<'r'>::Character},
{DomCode::US_S, DomKey::Constant<'s'>::Character},
{DomCode::US_T, DomKey::Constant<'t'>::Character},
{DomCode::US_U, DomKey::Constant<'u'>::Character},
{DomCode::US_V, DomKey::Constant<'v'>::Character},
{DomCode::US_W, DomKey::Constant<'w'>::Character},
{DomCode::US_X, DomKey::Constant<'x'>::Character},
{DomCode::US_Y, DomKey::Constant<'y'>::Character},
{DomCode::US_Z, DomKey::Constant<'z'>::Character},
{DomCode::BACKQUOTE, DomKey::Constant<'`'>::Character},
{DomCode::MINUS, DomKey::Constant<'-'>::Character},
{DomCode::EQUAL, DomKey::Constant<'='>::Character},
{DomCode::INTL_YEN, DomKey::Constant<0x00A5>::Dead},
{DomCode::BRACKET_LEFT, DomKey::Constant<'{'>::Character},
{DomCode::BRACKET_RIGHT, DomKey::Constant<'}'>::Character},
{DomCode::BACKSLASH, DomKey::Constant<'\\'>::Character},
{DomCode::SEMICOLON, DomKey::Constant<';'>::Character},
{DomCode::QUOTE, DomKey::Constant<'\''>::Character},
{DomCode::INTL_BACKSLASH, DomKey::Constant<'/'>::Character},
{DomCode::COMMA, DomKey::Constant<','>::Character},
{DomCode::PERIOD, DomKey::Constant<'.'>::Character},
{DomCode::SLASH, DomKey::Constant<'/'>::Character},
{DomCode::INTL_RO, DomKey::Constant<0x308D>::Dead}});
// Ensure the 'full' lookup table contains the same number of elements as the
// writing system table used by the class under test. Ideally this would be a
// static assert however that doesn't work since the other table is in a
// different compilation unit.
DCHECK_EQ(base::size(kFullLookupTable), kWritingSystemKeyDomCodeEntries);
if (kFullLookupTable.count(dom_code) == 0)
return DomKey::NONE;
return kFullLookupTable[dom_code];
}
DomKey GetKeyFromCombiningLayoutTable(DomCode dom_code) {
// Used for testing combining keys in both printable and combining forms.
static base::flat_map<DomCode, DomKey> kCombiningLayoutTable({
// Grave, combining.
{DomCode::DIGIT0, DomKey::Constant<0x0300>::Dead},
// Grave, printable.
{DomCode::DIGIT1, DomKey::Constant<0x0060>::Character},
// Acute, combining.
{DomCode::DIGIT2, DomKey::Constant<0x0301>::Dead},
// Acute, printable.
{DomCode::DIGIT3, DomKey::Constant<0x0027>::Character},
// Circumflex, combining.
{DomCode::DIGIT4, DomKey::Constant<0x0302>::Dead},
// Circumflex, printable.
{DomCode::DIGIT5, DomKey::Constant<0x005e>::Character},
// Tilde, combining.
{DomCode::DIGIT6, DomKey::Constant<0x0303>::Dead},
// Tilde, printable.
{DomCode::DIGIT7, DomKey::Constant<0x007e>::Character},
// Diaeresis, combining.
{DomCode::DIGIT8, DomKey::Constant<0x0308>::Dead},
// Diaeresis, printable.
{DomCode::DIGIT9, DomKey::Constant<0x00a8>::Character},
});
if (kCombiningLayoutTable.count(dom_code) == 0)
return DomKey::NONE;
return kCombiningLayoutTable[dom_code];
}
} // namespace
class TestDomKeyboardLayoutMap : public DomKeyboardLayoutMapBase {
public:
TestDomKeyboardLayoutMap();
~TestDomKeyboardLayoutMap() override;
// DomKeyboardLayoutMapBase overrides.
uint32_t GetKeyboardLayoutCount() override;
DomKey GetDomKeyFromDomCodeForLayout(DomCode dom_code,
uint32_t keyboard_layout_id) override;
// Adds a new keyboard layout in FIFO order.
void AddKeyboardLayout(uint32_t test_layout_id);
private:
// Helper methods used to populate a layout for testing.
DomKey GetDomKeyForLayoutWithAllValidKeys(DomCode dom_code);
DomKey GetDomKeyForLayoutWithAllValidAlphaKeys(DomCode dom_code);
DomKey GetDomKeyForLayoutWithSomeValidKeys(DomCode dom_code);
DomKey GetDomKeyForLayoutWithNoValidKeys();
std::vector<uint32_t> test_keyboard_layouts_;
DISALLOW_COPY_AND_ASSIGN(TestDomKeyboardLayoutMap);
};
TestDomKeyboardLayoutMap::TestDomKeyboardLayoutMap() = default;
TestDomKeyboardLayoutMap::~TestDomKeyboardLayoutMap() = default;
uint32_t TestDomKeyboardLayoutMap::GetKeyboardLayoutCount() {
return test_keyboard_layouts_.size();
}
DomKey TestDomKeyboardLayoutMap::GetDomKeyFromDomCodeForLayout(
DomCode dom_code,
uint32_t keyboard_layout_id) {
uint32_t test_layout_id = test_keyboard_layouts_[keyboard_layout_id];
if (test_layout_id == kKeyboardLayoutWithAllValidKeys)
return GetDomKeyForLayoutWithAllValidKeys(dom_code);
if (test_layout_id == kKeyboardLayoutWithAllValidAlphaKeys)
return GetDomKeyForLayoutWithAllValidAlphaKeys(dom_code);
if (test_layout_id == kKeyboardLayoutWithSomeValidKeys)
return GetDomKeyForLayoutWithSomeValidKeys(dom_code);
if (test_layout_id == kKeyboardLayoutWithNoValidKeys)
return GetDomKeyForLayoutWithNoValidKeys();
NOTREACHED();
return DomKey::NONE;
}
void TestDomKeyboardLayoutMap::AddKeyboardLayout(uint32_t test_layout_id) {
test_keyboard_layouts_.push_back(test_layout_id);
}
DomKey TestDomKeyboardLayoutMap::GetDomKeyForLayoutWithAllValidKeys(
DomCode dom_code) {
return GetKeyFromFullLookupTable(dom_code);
}
DomKey TestDomKeyboardLayoutMap::GetDomKeyForLayoutWithAllValidAlphaKeys(
DomCode dom_code) {
// If the number of excluded keys changes, please modify
// |kKeyboardLayoutWithAllValidAlphaKeysCount| to match the new value.
if (dom_code == DomCode::INTL_RO || dom_code == DomCode::INTL_YEN)
return DomKey::NONE;
// DIGIT 0 - 9 are overridden for combining char tests so use those here since
// this method only ensures the alpha keys are valid.
if (GetKeyFromCombiningLayoutTable(dom_code) != DomKey::NONE)
return GetKeyFromCombiningLayoutTable(dom_code);
return GetKeyFromFullLookupTable(dom_code);
}
DomKey TestDomKeyboardLayoutMap::GetDomKeyForLayoutWithSomeValidKeys(
DomCode dom_code) {
if (dom_code == DomCode::US_A || dom_code == DomCode::US_Z ||
dom_code == DomCode::BACKQUOTE)
return DomKey::NONE;
return GetKeyFromFullLookupTable(dom_code);
}
DomKey TestDomKeyboardLayoutMap::GetDomKeyForLayoutWithNoValidKeys() {
return DomKey::NONE;
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithZeroLayouts) {
TestDomKeyboardLayoutMap test_keyboard_layout_map;
auto map = test_keyboard_layout_map.Generate();
ASSERT_EQ(0UL, map.size());
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithCompletelyValidLayout) {
TestDomKeyboardLayoutMap test_keyboard_layout_map;
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithAllValidKeys);
auto map = test_keyboard_layout_map.Generate();
ASSERT_EQ(kKeyboardLayoutWithAllValidKeysCount, map.size());
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithValidAlphaKeys) {
TestDomKeyboardLayoutMap test_keyboard_layout_map;
test_keyboard_layout_map.AddKeyboardLayout(
kKeyboardLayoutWithAllValidAlphaKeys);
auto map = test_keyboard_layout_map.Generate();
ASSERT_EQ(kKeyboardLayoutWithAllValidAlphaKeysCount, map.size());
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithMostlyValidAlphaKeys) {
TestDomKeyboardLayoutMap test_keyboard_layout_map;
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithSomeValidKeys);
auto map = test_keyboard_layout_map.Generate();
ASSERT_EQ(kKeyboardLayoutWithSomeValidKeysCount, map.size());
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithNoValidKeys) {
TestDomKeyboardLayoutMap test_keyboard_layout_map;
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithNoValidKeys);
auto map = test_keyboard_layout_map.Generate();
ASSERT_EQ(kKeyboardLayoutWithNoValidKeysCount, map.size());
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithValidLayoutFirst) {
TestDomKeyboardLayoutMap test_keyboard_layout_map;
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithAllValidKeys);
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithSomeValidKeys);
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithNoValidKeys);
auto map = test_keyboard_layout_map.Generate();
ASSERT_EQ(kKeyboardLayoutWithAllValidKeysCount, map.size());
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithValidLayoutLast) {
TestDomKeyboardLayoutMap test_keyboard_layout_map;
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithSomeValidKeys);
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithNoValidKeys);
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithAllValidKeys);
auto map = test_keyboard_layout_map.Generate();
ASSERT_EQ(kKeyboardLayoutWithAllValidKeysCount, map.size());
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithTwoValidLayouts) {
TestDomKeyboardLayoutMap test_keyboard_layout_map_1;
test_keyboard_layout_map_1.AddKeyboardLayout(kKeyboardLayoutWithAllValidKeys);
test_keyboard_layout_map_1.AddKeyboardLayout(
kKeyboardLayoutWithAllValidAlphaKeys);
auto map_1 = test_keyboard_layout_map_1.Generate();
EXPECT_EQ(kKeyboardLayoutWithAllValidKeysCount, map_1.size());
TestDomKeyboardLayoutMap test_keyboard_layout_map_2;
test_keyboard_layout_map_2.AddKeyboardLayout(
kKeyboardLayoutWithAllValidAlphaKeys);
test_keyboard_layout_map_2.AddKeyboardLayout(kKeyboardLayoutWithAllValidKeys);
auto map_2 = test_keyboard_layout_map_2.Generate();
EXPECT_EQ(kKeyboardLayoutWithAllValidAlphaKeysCount, map_2.size());
}
} // namespace ui
// Copyright 2018 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 <windows.h>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/stl_util.h"
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/events/keycodes/dom/dom_keyboard_layout_manager.h"
#include "ui/events/keycodes/dom/dom_keyboard_layout_map_base.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
namespace ui {
namespace {
class DomKeyboardLayoutMapWin : public DomKeyboardLayoutMapBase {
public:
DomKeyboardLayoutMapWin();
~DomKeyboardLayoutMapWin() override;
private:
// ui::DomKeyboardLayoutMapBase implementation.
uint32_t GetKeyboardLayoutCount() override;
ui::DomKey GetDomKeyFromDomCodeForLayout(
ui::DomCode dom_code,
uint32_t keyboard_layout_index) override;
// Set of keyboard layout handles provided by the operating system.
// The handles stored do not need to be released when the vector is destroyed.
std::vector<HKL> keyboard_layout_handles_;
DISALLOW_COPY_AND_ASSIGN(DomKeyboardLayoutMapWin);
};
DomKeyboardLayoutMapWin::DomKeyboardLayoutMapWin() = default;
DomKeyboardLayoutMapWin::~DomKeyboardLayoutMapWin() = default;
uint32_t DomKeyboardLayoutMapWin::GetKeyboardLayoutCount() {
keyboard_layout_handles_.clear();
const size_t keyboard_layout_count = ::GetKeyboardLayoutList(0, nullptr);
if (!keyboard_layout_count) {
DPLOG(ERROR) << "GetKeyboardLayoutList failed: ";
return false;
}
keyboard_layout_handles_.resize(keyboard_layout_count);
const size_t copy_count = ::GetKeyboardLayoutList(
keyboard_layout_handles_.size(), keyboard_layout_handles_.data());
if (!copy_count) {
DPLOG(ERROR) << "GetKeyboardLayoutList failed: ";
return false;
}
DCHECK_EQ(keyboard_layout_count, copy_count);
return keyboard_layout_handles_.size();
}
ui::DomKey DomKeyboardLayoutMapWin::GetDomKeyFromDomCodeForLayout(
ui::DomCode dom_code,
uint32_t keyboard_layout_index) {
DCHECK_NE(dom_code, ui::DomCode::NONE);
DCHECK_LT(keyboard_layout_index, keyboard_layout_handles_.size());
HKL keyboard_layout = keyboard_layout_handles_[keyboard_layout_index];
int32_t scan_code = ui::KeycodeConverter::DomCodeToNativeKeycode(dom_code);
uint32_t virtual_key_code =
MapVirtualKeyEx(scan_code, MAPVK_VSC_TO_VK_EX, keyboard_layout);
if (!virtual_key_code) {
if (GetLastError() != 0)
DPLOG(ERROR) << "MapVirtualKeyEx failed: ";
return ui::DomKey::NONE;
}
// Represents a keyboard state with all keys up (i.e. no keys pressed).
BYTE keyboard_state[256] = {0};
// ToUnicodeEx() return value indicates the category for the scan code
// passed in for the keyboard layout provided.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms646322(v=vs.85).aspx
wchar_t char_buffer[1] = {0};
int key_type =
::ToUnicodeEx(virtual_key_code, scan_code, keyboard_state, char_buffer,
base::size(char_buffer), /*wFlags=*/0, keyboard_layout);
if (key_type == 1)
return ui::DomKey::FromCharacter(char_buffer[0]);
if (key_type == -1)
return ui::DomKey::DeadKeyFromCombiningCharacter(char_buffer[0]);
return ui::DomKey::NONE;
}
} // namespace
// static
base::flat_map<std::string, std::string> GenerateDomKeyboardLayoutMap() {
return DomKeyboardLayoutMapWin().Generate();
}
} // namespace ui
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "ui/display/win/screen_win.h" #include "ui/display/win/screen_win.h"
#include "ui/events/keyboard_hook.h" #include "ui/events/keyboard_hook.h"
#include "ui/events/keycodes/dom/dom_code.h" #include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/dom_keyboard_layout_map.h"
#include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
...@@ -587,8 +588,7 @@ bool DesktopWindowTreeHostWin::IsKeyLocked(ui::DomCode dom_code) { ...@@ -587,8 +588,7 @@ bool DesktopWindowTreeHostWin::IsKeyLocked(ui::DomCode dom_code) {
base::flat_map<std::string, std::string> base::flat_map<std::string, std::string>
DesktopWindowTreeHostWin::GetKeyboardLayoutMap() { DesktopWindowTreeHostWin::GetKeyboardLayoutMap() {
NOTIMPLEMENTED(); return ui::GenerateDomKeyboardLayoutMap();
return {};
} }
void DesktopWindowTreeHostWin::SetCursorNative(gfx::NativeCursor cursor) { void DesktopWindowTreeHostWin::SetCursorNative(gfx::NativeCursor cursor) {
......
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