summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/linux/system.gyp1
-rw-r--r--chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc55
-rw-r--r--chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h1
-rw-r--r--chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc50
-rw-r--r--chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.cc171
-rw-r--r--chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.h23
-rw-r--r--chrome/chrome_browser_extensions.gypi3
-rw-r--r--chrome/common/extensions/api/braille_display_private.idl11
-rw-r--r--chrome/test/data/extensions/api_test/braille_display_private/key_events/test.js25
9 files changed, 271 insertions, 69 deletions
diff --git a/build/linux/system.gyp b/build/linux/system.gyp
index b798256..6a7cae0 100644
--- a/build/linux/system.gyp
+++ b/build/linux/system.gyp
@@ -746,7 +746,6 @@
'--link-directly=<(linux_link_libbrlapi)',
'brlapi_getHandleSize',
'brlapi_error_location',
- 'brlapi_expandKeyCode',
'brlapi_strerror',
'brlapi__acceptKeys',
'brlapi__openConnection',
diff --git a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
index 60eaa5e..96a79de 100644
--- a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
+++ b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
@@ -13,6 +13,7 @@
#include "base/bind_helpers.h"
#include "base/time/time.h"
#include "chrome/browser/extensions/api/braille_display_private/brlapi_connection.h"
+#include "chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.h"
#include "content/public/browser/browser_thread.h"
namespace extensions {
@@ -29,11 +30,6 @@ const int64 kConnectionDelayMs = 500;
// How long to periodically retry connecting after a brltty restart.
// Some displays are slow to connect.
const int64 kConnectRetryTimeout = 20000;
-// 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;
} // namespace
BrailleController::BrailleController() {
@@ -268,53 +264,6 @@ scoped_ptr<BrlapiConnection> BrailleControllerImpl::CreateBrlapiConnection() {
return BrlapiConnection::Create(&libbrlapi_loader_);
}
-scoped_ptr<KeyEvent> BrailleControllerImpl::MapKeyCode(brlapi_keyCode_t code) {
- brlapi_expandedKeyCode_t expanded;
- if (libbrlapi_loader_.brlapi_expandKeyCode(code, &expanded) != 0) {
- LOG(ERROR) << "Couldn't expand key code " << code;
- return scoped_ptr<KeyEvent>();
- }
- scoped_ptr<KeyEvent> result(new KeyEvent);
- result->command = KEY_COMMAND_NONE;
- switch (expanded.type) {
- case BRLAPI_KEY_TYPE_CMD:
- switch (expanded.command) {
- case BRLAPI_KEY_CMD_LNUP:
- result->command = KEY_COMMAND_LINE_UP;
- break;
- case BRLAPI_KEY_CMD_LNDN:
- result->command = KEY_COMMAND_LINE_DOWN;
- break;
- case BRLAPI_KEY_CMD_FWINLT:
- result->command = KEY_COMMAND_PAN_LEFT;
- break;
- case BRLAPI_KEY_CMD_FWINRT:
- result->command = KEY_COMMAND_PAN_RIGHT;
- break;
- case BRLAPI_KEY_CMD_TOP:
- result->command = KEY_COMMAND_TOP;
- break;
- case BRLAPI_KEY_CMD_BOT:
- result->command = KEY_COMMAND_BOTTOM;
- break;
- case BRLAPI_KEY_CMD_ROUTE:
- result->command = KEY_COMMAND_ROUTING;
- result->display_position.reset(new int(expanded.argument));
- break;
- case BRLAPI_KEY_CMD_PASSDOTS:
- result->command = KEY_COMMAND_DOTS;
- result->braille_dots.reset(new int(expanded.argument & kAllDots));
- if ((expanded.argument & BRLAPI_DOTC) != 0)
- result->space_key.reset(new bool(true));
- break;
- }
- break;
- }
- if (result->command == KEY_COMMAND_NONE)
- result.reset();
- return result.Pass();
-}
-
void BrailleControllerImpl::DispatchKeys() {
DCHECK(connection_.get());
brlapi_keyCode_t code;
@@ -331,7 +280,7 @@ void BrailleControllerImpl::DispatchKeys() {
} else if (result == 0) { // No more data.
return;
}
- scoped_ptr<KeyEvent> event = MapKeyCode(code);
+ scoped_ptr<KeyEvent> event = BrlapiKeyCodeToEvent(code);
if (event)
DispatchKeyEvent(event.Pass());
}
diff --git a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h
index 20fbf9d..41c2b82 100644
--- a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h
+++ b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h
@@ -61,7 +61,6 @@ class BrailleControllerImpl : public BrailleController {
void Disconnect();
scoped_ptr<BrlapiConnection> CreateBrlapiConnection();
void DispatchKeys();
- scoped_ptr<KeyEvent> MapKeyCode(brlapi_keyCode_t code);
void DispatchKeyEvent(scoped_ptr<KeyEvent> event);
void DispatchOnDisplayStateChanged(scoped_ptr<DisplayState> new_state);
diff --git a/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc b/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc
index cfa1712..ae2300c 100644
--- a/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc
+++ b/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc
@@ -42,6 +42,9 @@ namespace {
const char kTestUserName[] = "owner@invalid.domain";
+// Used to make ReadKeys return an error.
+brlapi_keyCode_t kErrorKeyCode = BRLAPI_KEY_MAX;
+
} // namespace
// Data maintained by the mock BrlapiConnection. This data lives throughout
@@ -114,9 +117,9 @@ class MockBrlapiConnection : public BrlapiConnection {
virtual int ReadKey(brlapi_keyCode_t* key_code) OVERRIDE {
if (!data_->pending_keys.empty()) {
- int queued_key_code = data_->pending_keys.front();
+ brlapi_keyCode_t queued_key_code = data_->pending_keys.front();
data_->pending_keys.pop_front();
- if (queued_key_code < 0) {
+ if (queued_key_code == kErrorKeyCode) {
data_->error.brlerrno = BRLAPI_ERROR_EOF;
return -1; // Signal error.
}
@@ -194,6 +197,8 @@ IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, WriteDots) {
IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, KeyEvents) {
connection_data_.display_size = 11;
+
+ // Braille navigation commands.
connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
BRLAPI_KEY_CMD_LNUP);
connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
@@ -208,17 +213,54 @@ IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, KeyEvents) {
BRLAPI_KEY_CMD_BOT);
connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
BRLAPI_KEY_CMD_ROUTE | 5);
- // Space (0) and all combinations of dots.
+
+ // Braille display standard keyboard emulation.
+
+ // An ascii character.
+ connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_SYM | 'A');
+ // A non-ascii 'latin1' character. Small letter a with ring above.
+ connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_SYM | 0xE5);
+ // A non-latin1 Unicode character. LATIN SMALL LETTER A WITH MACRON.
+ connection_data_.pending_keys.push_back(
+ BRLAPI_KEY_TYPE_SYM | BRLAPI_KEY_SYM_UNICODE | 0x100);
+ // A Unicode character outside the BMP. CAT FACE WITH TEARS OF JOY.
+ // With anticipation for the first emoji-enabled braille display.
+ connection_data_.pending_keys.push_back(
+ BRLAPI_KEY_TYPE_SYM | BRLAPI_KEY_SYM_UNICODE | 0x1F639);
+ // Invalid Unicode character.
+ connection_data_.pending_keys.push_back(
+ BRLAPI_KEY_TYPE_SYM | BRLAPI_KEY_SYM_UNICODE | 0x110000);
+
+ // Non-alphanumeric function keys.
+
+ // Backspace.
+ connection_data_.pending_keys.push_back(
+ BRLAPI_KEY_TYPE_SYM | BRLAPI_KEY_SYM_BACKSPACE);
+ // Shift+Tab.
+ connection_data_.pending_keys.push_back(
+ BRLAPI_KEY_TYPE_SYM | BRLAPI_KEY_FLG_SHIFT | BRLAPI_KEY_SYM_TAB);
+ // Alt+F3. (0-based).
+ connection_data_.pending_keys.push_back(
+ BRLAPI_KEY_TYPE_SYM | BRLAPI_KEY_FLG_META |
+ (BRLAPI_KEY_SYM_FUNCTION + 2));
+
+ // ctrl+dot1+dot2.
+ connection_data_.pending_keys.push_back(
+ BRLAPI_KEY_TYPE_CMD | BRLAPI_KEY_FLG_CONTROL | BRLAPI_KEY_CMD_PASSDOTS |
+ BRLAPI_DOT1 | BRLAPI_DOT2);
+
+ // Braille dot keys, all combinations including space (0).
for (int i = 0; i < 256; ++i) {
connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
BRLAPI_KEY_CMD_PASSDOTS | i);
}
+
ASSERT_TRUE(RunComponentExtensionTest("braille_display_private/key_events"));
}
IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, DisplayStateChanges) {
connection_data_.display_size = 11;
- connection_data_.pending_keys.push_back(-1);
+ connection_data_.pending_keys.push_back(kErrorKeyCode);
connection_data_.reappear_on_disconnect = true;
ASSERT_TRUE(RunComponentExtensionTest(
"braille_display_private/display_state_changes"));
diff --git a/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.cc b/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.cc
new file mode 100644
index 0000000..20225c4
--- /dev/null
+++ b/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.cc
@@ -0,0 +1,171 @@
+// 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 "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/dom4/keycode_converter_data.h 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/dom4/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 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.Pass();
+}
+
+} // namespace braille_display_private
+} // namespace api
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.h b/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.h
new file mode 100644
index 0000000..177e058
--- /dev/null
+++ b/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.h
@@ -0,0 +1,23 @@
+// 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.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_BRAILLE_DISPLAY_PRIVATE_BRLAPI_KEYCODE_MAP_H_
+#define CHROME_BROWSER_EXTENSIONS_API_BRAILLE_DISPLAY_PRIVATE_BRLAPI_KEYCODE_MAP_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "chrome/common/extensions/api/braille_display_private.h"
+#include "library_loaders/libbrlapi.h"
+
+namespace extensions {
+namespace api {
+namespace braille_display_private {
+
+// Maps a 64 bit BrlAPI keycode to a braille |KeyEvent| object.
+scoped_ptr<KeyEvent> BrlapiKeyCodeToEvent(brlapi_keyCode_t code);
+
+} // namespace braille_display_private
+} // namespace api
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_BRAILLE_DISPLAY_PRIVATE_BRLAPI_KEYCODE_MAP_H_
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index 20b5ff0..588b601 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -191,6 +191,8 @@
'browser/extensions/api/braille_display_private/braille_display_private_api.cc',
'browser/extensions/api/braille_display_private/brlapi_connection.cc',
'browser/extensions/api/braille_display_private/brlapi_connection.h',
+ 'browser/extensions/api/braille_display_private/brlapi_keycode_map.cc',
+ 'browser/extensions/api/braille_display_private/brlapi_keycode_map.h',
'browser/extensions/api/braille_display_private/stub_braille_controller.cc',
'browser/extensions/api/braille_display_private/stub_braille_controller.h',
'browser/extensions/api/browser/browser_api.cc',
@@ -1219,6 +1221,7 @@
'sources!': [
'browser/extensions/api/braille_display_private/braille_controller_brlapi.cc',
'browser/extensions/api/braille_display_private/brlapi_connection.cc',
+ 'browser/extensions/api/braille_display_private/brlapi_keycode_map.cc',
],
}],
['enable_webrtc==0', {
diff --git a/chrome/common/extensions/api/braille_display_private.idl b/chrome/common/extensions/api/braille_display_private.idl
index 166b932..0c7a3e6 100644
--- a/chrome/common/extensions/api/braille_display_private.idl
+++ b/chrome/common/extensions/api/braille_display_private.idl
@@ -28,8 +28,15 @@ namespace brailleDisplayPrivate {
// Braille dot keys that were pressed, stored in the low-order bits.
// Dot 1 is stored in bit 0, dot2 in bit 1, etc.
long? brailleDots;
- // DOM keyboard event for a key that corresponds to a standard key.
- DOMString? standardKeyName;
+ // DOM keyboard event code. This is present when command is standard_key
+ // and the braille display event represents a non-alphanumeric key such
+ // as an arrow key or function key.
+ // The value is as defined by the |code| property in
+ // http://www.w3.org/TR/uievents/#keyboard-event-interface
+ DOMString? standardKeyCode;
+ // DOM keyboard event character value. This is present if the
+ // braille key event corresponds to a character.
+ DOMString? standardKeyChar;
// Whether the space key was pressed.
boolean? spaceKey;
// Whether the alt key was pressed.
diff --git a/chrome/test/data/extensions/api_test/braille_display_private/key_events/test.js b/chrome/test/data/extensions/api_test/braille_display_private/key_events/test.js
index 875e4be..7437bb0 100644
--- a/chrome/test/data/extensions/api_test/braille_display_private/key_events/test.js
+++ b/chrome/test/data/extensions/api_test/braille_display_private/key_events/test.js
@@ -8,16 +8,25 @@
var pass = chrome.test.callbackPass;
var EXPECTED_EVENTS = [
- { "command": "line_up" },
- { "command": "line_down" },
- { "command": "pan_left" },
- { "command": "pan_right" },
- { "command": "top" },
- { "command": "bottom" },
- { "command": "routing", "displayPosition": 5 },
+ { command: "line_up" },
+ { command: "line_down" },
+ { command: "pan_left" },
+ { command: "pan_right" },
+ { command: "top" },
+ { command: "bottom" },
+ { command: "routing", "displayPosition": 5 },
+ { command: "standard_key", standardKeyChar: "A" },
+ { command: "standard_key", standardKeyChar: "\u00E5" },
+ { command: "standard_key", standardKeyChar: "\u0100" },
+ // UTF-16 of U+1F639.
+ { command: "standard_key", standardKeyChar: "\uD83D\uDE39" },
+ { command: "standard_key", standardKeyCode: "Backspace" },
+ { command: "standard_key", standardKeyCode: "Tab", shiftKey: true },
+ { command: "standard_key", standardKeyCode: "F3", altKey: true },
+ { command: "dots", ctrlKey: true, brailleDots: 0x1 | 0x2}
]
for (var i = 0; i < 256; ++i) {
- EXPECTED_EVENTS.push({ "command": "dots", "brailleDots": i });
+ EXPECTED_EVENTS.push({ command: "dots", "brailleDots": i });
}
var event_number = 0;