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) {
}
static_library("dom_keycode_converter") {
sources = [
public = [
"keycodes/dom/dom_code.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_keyboard_layout.cc",
"keycodes/dom/dom_keyboard_layout.h",
"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.h",
"keycodes/dom/keycode_converter_data.inc",
]
......@@ -37,6 +44,18 @@ static_library("dom_keycode_converter") {
if (!is_ios) {
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") {
......@@ -429,6 +448,7 @@ if (!is_ios) {
"gesture_detection/velocity_tracker_unittest.cc",
"gestures/blink/web_gesture_curve_impl_unittest.cc",
"gestures/fling_curve_unittest.cc",
"keycodes/dom/dom_keyboard_layout_map_unittest.cc",
"keycodes/dom/keycode_converter_unittest.cc",
"keycodes/keyboard_code_conversion_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_
This diff is collapsed.
// 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 @@
#include "ui/display/win/screen_win.h"
#include "ui/events/keyboard_hook.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/vector2d.h"
#include "ui/gfx/native_widget_types.h"
......@@ -587,8 +588,7 @@ bool DesktopWindowTreeHostWin::IsKeyLocked(ui::DomCode dom_code) {
base::flat_map<std::string, std::string>
DesktopWindowTreeHostWin::GetKeyboardLayoutMap() {
NOTIMPLEMENTED();
return {};
return ui::GenerateDomKeyboardLayoutMap();
}
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