#include "ash/public/cpp/accelerators_util.h"
#include <string>
#include "ash/public/cpp/accelerator_keycode_lookup_cache.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/ime/ash/input_method_manager.h"
#include "ui/base/ui_base_features.h"
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/dom/dom_codes_array.h"
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/keycodes/keyboard_codes_posix.h"
#include "ui/events/ozone/layout/keyboard_layout_engine.h"
#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
namespace {
std::u16string GetStringForDeadKey(ui::DomKey dom_key) {
DCHECK(dom_key.IsDeadKey());
int32_t ch = dom_key.ToDeadKeyCombiningCharacter();
switch (ch) {
case 0x300:
return u"`";
case 0x301:
return u"´";
case 0x302:
return u"^";
case 0x303:
return u"~";
case 0x308:
return u"¨";
default:
break;
}
LOG(WARNING) << "No mapping for dead key: " << ch;
return base::UTF8ToUTF16(ui::KeycodeConverter::DomKeyToKeyString(dom_key));
}
}
namespace ash {
std::u16string KeycodeToKeyString(ui::KeyboardCode key_code,
bool remap_positional_key) {
ui::DomKey dom_key;
ui::KeyboardCode key_code_to_compare = ui::VKEY_UNKNOWN;
const ui::KeyboardLayoutEngine* layout_engine =
ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine();
if (remap_positional_key &&
::features::IsImprovedKeyboardShortcutsEnabled()) {
ui::DomCode dom_code =
ui::KeycodeConverter::MapUSPositionalShortcutKeyToDomCode(key_code);
if (dom_code != ui::DomCode::NONE) {
if (layout_engine->Lookup(dom_code, ui::EF_NONE, &dom_key,
&key_code_to_compare)) {
if (dom_key.IsDeadKey()) {
return GetStringForDeadKey(dom_key);
}
if (!dom_key.IsValid()) {
return std::u16string();
}
return base::UTF8ToUTF16(
ui::KeycodeConverter::DomKeyToKeyString(dom_key));
}
return std::u16string();
}
}
const absl::optional<std::u16string> cached_key_string =
AcceleratorKeycodeLookupCache::Get()->Find(key_code);
if (cached_key_string.has_value()) {
return std::move(cached_key_string).value();
}
for (const auto& dom_code : ui::kDomCodesArray) {
if (!layout_engine->Lookup(dom_code, ui::EF_NONE, &dom_key,
&key_code_to_compare)) {
continue;
}
if (key_code_to_compare != key_code) {
AcceleratorKeycodeLookupCache::Get()->InsertOrAssign(
key_code_to_compare,
base::UTF8ToUTF16(ui::KeycodeConverter::DomKeyToKeyString(dom_key)));
continue;
}
if (!dom_key.IsValid() || dom_key.IsDeadKey()) {
continue;
}
const std::u16string key_string =
base::UTF8ToUTF16(ui::KeycodeConverter::DomKeyToKeyString(dom_key));
AcceleratorKeycodeLookupCache::Get()->InsertOrAssign(key_code, key_string);
return key_string;
}
return std::u16string();
}
}