summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.cc
blob: e77426b41b44850373756ea2d6b40feae360434b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// 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:
          event->command = KEY_COMMAND_DOTS;
          event->braille_dots.reset(new int(argument & kAllDots));
          MapModifierFlags(code, event);
          break;
      }
  }
}

}  // namespace

scoped_ptr<KeyEvent> BrlapiKeyCodeToEvent(brlapi_keyCode_t code) {
  scoped_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