blob: aa4e913a4fc0b55f9b735de4676fbdb8a76e906f [file] [log] [blame]
// Copyright 2014 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 "chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.h"
#include <stdint.h>
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversion_utils.h"
namespace extensions {
namespace api {
namespace braille_display_private {
namespace {
// Bitmask for all braille dots in a key command argument, which coincides
// with the representation in the braille_dots member of the KeyEvent
// class.
const int kAllDots = BRLAPI_DOT1 | BRLAPI_DOT2 | BRLAPI_DOT3 | BRLAPI_DOT4 |
BRLAPI_DOT5 | BRLAPI_DOT6 | BRLAPI_DOT7 | BRLAPI_DOT8;
// Maximum Latin 1 character keyboard symbol.
const brlapi_keyCode_t kMaxLatin1KeySym = 0xff;
// Range of function keys that we support.
// See ui/events/keycodes/dom/keycode_converter_data.inc for the list of all
// key codes.
const brlapi_keyCode_t kMinFunctionKey = BRLAPI_KEY_SYM_FUNCTION;
const brlapi_keyCode_t kMaxFunctionKey = BRLAPI_KEY_SYM_FUNCTION + 23;
// Maps the keyboard modifier flags to their corresponding flags in a
// |KeyEvent|.
void MapModifierFlags(brlapi_keyCode_t code, KeyEvent* event) {
if (code & BRLAPI_KEY_FLG_CONTROL)
event->ctrl_key.reset(new bool(true));
if (code & BRLAPI_KEY_FLG_META)
event->alt_key.reset(new bool(true));
if (code & BRLAPI_KEY_FLG_SHIFT)
event->shift_key.reset(new bool(true));
}
// Maps a brlapi keysym, which is similar to an X keysym into the
// provided event.
// See ui/events/keycodes/dom/keycode_converter_data.cc for the full
// list of key codes.
void MapKeySym(brlapi_keyCode_t code, KeyEvent* event) {
brlapi_keyCode_t key_sym = code & BRLAPI_KEY_CODE_MASK;
if (key_sym < kMaxLatin1KeySym ||
(key_sym & BRLAPI_KEY_SYM_UNICODE) != 0) {
uint32_t code_point = key_sym & ~BRLAPI_KEY_SYM_UNICODE;
if (!base::IsValidCharacter(code_point))
return;
event->standard_key_char.reset(new std::string);
base::WriteUnicodeCharacter(code_point, event->standard_key_char.get());
} else if (key_sym >= kMinFunctionKey && key_sym <= kMaxFunctionKey) {
// Function keys are 0-based here, so we need to add one to get e.g.
// 'F1' for the first key.
int function_key_number = key_sym - kMinFunctionKey + 1;
event->standard_key_code.reset(
new std::string(base::StringPrintf("F%d", function_key_number)));
} else {
// Explicitly map the keys that brlapi provides.
const char* code_string;
switch (key_sym) {
case BRLAPI_KEY_SYM_BACKSPACE:
code_string = "Backspace";
break;
case BRLAPI_KEY_SYM_TAB:
code_string = "Tab";
break;
case BRLAPI_KEY_SYM_LINEFEED:
code_string = "Enter";
break;
case BRLAPI_KEY_SYM_ESCAPE:
code_string = "Escape";
break;
case BRLAPI_KEY_SYM_HOME:
code_string = "Home";
break;
case BRLAPI_KEY_SYM_LEFT:
code_string = "ArrowLeft";
break;
case BRLAPI_KEY_SYM_UP:
code_string = "ArrowUp";
break;
case BRLAPI_KEY_SYM_RIGHT:
code_string = "ArrowRight";
break;
case BRLAPI_KEY_SYM_DOWN:
code_string = "ArrowDown";
break;
case BRLAPI_KEY_SYM_PAGE_UP:
code_string = "PageUp";
break;
case BRLAPI_KEY_SYM_PAGE_DOWN:
code_string = "PageDown";
break;
case BRLAPI_KEY_SYM_END:
code_string = "End";
break;
case BRLAPI_KEY_SYM_INSERT:
code_string = "Insert";
break;
case BRLAPI_KEY_SYM_DELETE:
code_string = "Delete";
break;
default:
return;
}
event->standard_key_code.reset(new std::string(code_string));
}
MapModifierFlags(code, event);
event->command = KEY_COMMAND_STANDARD_KEY;
}
void MapCommand(brlapi_keyCode_t code, KeyEvent* event) {
brlapi_keyCode_t argument = code & BRLAPI_KEY_CMD_ARG_MASK;
switch (code & BRLAPI_KEY_CODE_MASK) {
case BRLAPI_KEY_CMD_LNUP:
event->command = KEY_COMMAND_LINE_UP;
break;
case BRLAPI_KEY_CMD_LNDN:
event->command = KEY_COMMAND_LINE_DOWN;
break;
case BRLAPI_KEY_CMD_FWINLT:
event->command = KEY_COMMAND_PAN_LEFT;
break;
case BRLAPI_KEY_CMD_FWINRT:
event->command = KEY_COMMAND_PAN_RIGHT;
break;
case BRLAPI_KEY_CMD_TOP:
event->command = KEY_COMMAND_TOP;
break;
case BRLAPI_KEY_CMD_BOT:
event->command = KEY_COMMAND_BOTTOM;
break;
default:
switch (code & BRLAPI_KEY_CMD_BLK_MASK) {
case BRLAPI_KEY_CMD_ROUTE:
event->command = KEY_COMMAND_ROUTING;
event->display_position.reset(new int(argument));
break;
case BRLAPI_KEY_CMD_PASSDOTS:
unsigned int dots = argument & kAllDots;
event->braille_dots.reset(new int(dots));
// BRLAPI_DOTC represents when the braille space key is pressed.
if (dots && (argument & BRLAPI_DOTC))
event->command = KEY_COMMAND_CHORD;
else
event->command = KEY_COMMAND_DOTS;
MapModifierFlags(code, event);
break;
}
}
}
} // namespace
std::unique_ptr<KeyEvent> BrlapiKeyCodeToEvent(brlapi_keyCode_t code) {
std::unique_ptr<KeyEvent> result(new KeyEvent);
result->command = KEY_COMMAND_NONE;
switch (code & BRLAPI_KEY_TYPE_MASK) {
case BRLAPI_KEY_TYPE_SYM:
MapKeySym(code, result.get());
break;
case BRLAPI_KEY_TYPE_CMD:
MapCommand(code, result.get());
break;
}
if (result->command == KEY_COMMAND_NONE)
result.reset();
return result;
}
} // namespace braille_display_private
} // namespace api
} // namespace extensions