Commit 837055f7 authored by bryeung@chromium.org's avatar bryeung@chromium.org

WebUIHandler for chrome://keyboard

This also moves processing of the KeyEvent JSON structure into
ui/keyboard/ from chrome/browser/extensions/api/input/input.cc.

The JS is setup with a separate implementation of send_key_event.js
(send_key_event_webui.js) that is mapped to the send_key_event.js
resource by the WebUIController.  This allows the WebUI and extension
code to be entirely shared.

BUG=222801

Review URL: https://chromiumcodereview.appspot.com/14161009

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@195218 0039d316-1c4b-4281-b951-d872f2087c98
parent d7ad3e9a
...@@ -7,126 +7,42 @@ ...@@ -7,126 +7,42 @@
#include <string> #include <string>
#include "base/lazy_instance.h" #include "base/lazy_instance.h"
#include "base/string_util.h" #include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_function_registry.h" #include "chrome/browser/extensions/extension_function_registry.h"
#include "chrome/browser/ui/top_level_widget.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "ui/base/events/event.h" #include "ui/base/events/event.h"
#include "ui/base/events/key_identifier_conversion.h"
#if defined(USE_ASH) && defined(USE_AURA) #if defined(USE_ASH)
#include "ash/shell.h" #include "ash/shell.h"
#include "ui/aura/root_window.h" #include "ui/aura/root_window.h"
#include "ui/keyboard/keyboard_util.h"
#endif #endif
namespace extensions {
namespace { namespace {
// Keys. const char kNotYetImplementedError[] =
const char kType[] = "type"; "API is not implemented on this platform.";
const char kKeyIdentifier[] = "keyIdentifier";
const char kAlt[] = "altKey";
const char kCtrl[] = "ctrlKey";
const char kMeta[] = "metaKey";
const char kShift[] = "shiftKey";
const char kKeyDown[] = "keydown";
const char kKeyUp[] = "keyup";
// Errors.
const char kUnknownEventTypeError[] = "Unknown event type.";
const char kUnknownOrUnsupportedKeyIdentiferError[] = "Unknown or unsupported "
"key identifier.";
const char kUnsupportedModifier[] = "Unsupported modifier.";
const char kNoValidRecipientError[] = "No valid recipient for event.";
const char kKeyEventUnprocessedError[] = "Event was not handled.";
ui::EventType GetTypeFromString(const std::string& type) {
if (type == kKeyDown) {
return ui::ET_KEY_PRESSED;
} else if (type == kKeyUp) {
return ui::ET_KEY_RELEASED;
}
return ui::ET_UNKNOWN;
}
// Converts a hex string "U+NNNN" to uint16. Returns 0 on error.
uint16 UnicodeIdentifierStringToInt(const std::string& key_identifier) {
int character = 0;
if ((key_identifier.length() == 6) &&
(key_identifier.substr(0, 2) == "U+") &&
(key_identifier.substr(2).find_first_not_of("0123456789abcdefABCDEF") ==
std::string::npos)) {
const bool result =
base::HexStringToInt(key_identifier.substr(2), &character);
DCHECK(result) << key_identifier;
}
return character;
}
} // namespace } // namespace
bool SendKeyboardEventInputFunction::RunImpl() { namespace extensions {
DictionaryValue* args;
EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
std::string type_name;
EXTENSION_FUNCTION_VALIDATE(args->GetString(kType, &type_name));
ui::EventType type = GetTypeFromString(type_name);
if (type == ui::ET_UNKNOWN) {
error_ = kUnknownEventTypeError;
return false;
}
std::string identifier;
EXTENSION_FUNCTION_VALIDATE(args->GetString(kKeyIdentifier, &identifier));
TrimWhitespaceASCII(identifier, TRIM_ALL, &identifier);
bool SendKeyboardEventInputFunction::RunImpl() {
#if defined(USE_ASH)
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
const ui::KeyEvent& prototype_event =
ui::KeyEventFromKeyIdentifier(identifier); scoped_ptr<ui::KeyEvent> event(
uint16 character = 0; keyboard::KeyEventFromArgs(args_.get(), &error_));
if (prototype_event.key_code() == ui::VKEY_UNKNOWN) { if (!event)
// Check if |identifier| is "U+NNNN" format.
character = UnicodeIdentifierStringToInt(identifier);
if (!character) {
error_ = kUnknownOrUnsupportedKeyIdentiferError;
return false;
}
}
bool flag = false;
int flags = 0;
if (prototype_event.key_code() != ui::VKEY_UNKNOWN)
flags = prototype_event.flags();
flags |= (args->GetBoolean(kAlt, &flag) && flag) ? ui::EF_ALT_DOWN : 0;
flags |= (args->GetBoolean(kCtrl, &flag) && flag) ? ui::EF_CONTROL_DOWN : 0;
flags |= (args->GetBoolean(kShift, &flag) && flag) ? ui::EF_SHIFT_DOWN : 0;
if (args->GetBoolean(kMeta, &flag) && flag) {
// Views does not have a Meta event flag, so return an error for now.
error_ = kUnsupportedModifier;
return false; return false;
}
ui::KeyEvent event(type,
prototype_event.key_code(),
flags,
prototype_event.is_char());
if (character) {
event.set_character(character);
event.set_unmodified_character(character);
}
#if defined(USE_ASH) && defined(USE_AURA)
ash::Shell::GetActiveRootWindow()->AsRootWindowHostDelegate()->OnHostKeyEvent( ash::Shell::GetActiveRootWindow()->AsRootWindowHostDelegate()->OnHostKeyEvent(
&event); event.get());
return true; return true;
#else
return false;
#endif #endif
error_ = kNotYetImplementedError;
return false;
} }
InputAPI::InputAPI(Profile* profile) { InputAPI::InputAPI(Profile* profile) {
......
...@@ -175,19 +175,20 @@ bool ImageLoader::IsComponentExtensionResource( ...@@ -175,19 +175,20 @@ bool ImageLoader::IsComponentExtensionResource(
{"settings_app/settings_app_icon_48.png", IDR_SETTINGS_APP_ICON_48}, {"settings_app/settings_app_icon_48.png", IDR_SETTINGS_APP_ICON_48},
#endif #endif
#if defined(USE_AURA) #if defined(USE_AURA)
{"keyboard/index.html", IDR_KEYBOARD_INDEX},
{"keyboard/main.css", IDR_KEYBOARD_MAIN_CSS},
{"keyboard/main.js", IDR_KEYBOARD_MAIN_JS},
{"keyboard/common.js", IDR_KEYBOARD_COMMON_JS}, {"keyboard/common.js", IDR_KEYBOARD_COMMON_JS},
{"keyboard/layout_us.js", IDR_KEYBOARD_LAYOUT_US_JS},
{"keyboard/images/chevron.svg", IDR_KEYBOARD_IMAGES_CHEVRON}, {"keyboard/images/chevron.svg", IDR_KEYBOARD_IMAGES_CHEVRON},
{"keyboard/images/del.svg", IDR_KEYBOARD_IMAGES_DEL}, {"keyboard/images/del.svg", IDR_KEYBOARD_IMAGES_DEL},
{"keyboard/images/keyboard.svg", IDR_KEYBOARD_IMAGES_KEYBOARD}, {"keyboard/images/keyboard.svg", IDR_KEYBOARD_IMAGES_KEYBOARD},
{"keyboard/images/mic.svg", IDR_KEYBOARD_IMAGES_MIC}, {"keyboard/images/mic.svg", IDR_KEYBOARD_IMAGES_MIC},
{"keyboard/images/ret.svg", IDR_KEYBOARD_IMAGES_RET}, {"keyboard/images/ret.svg", IDR_KEYBOARD_IMAGES_RET},
{"keyboard/images/shift_down.svg", IDR_KEYBOARD_IMAGES_SHIFT_DOWN},
{"keyboard/images/shift.svg", IDR_KEYBOARD_IMAGES_SHIFT}, {"keyboard/images/shift.svg", IDR_KEYBOARD_IMAGES_SHIFT},
{"keyboard/images/shift_down.svg", IDR_KEYBOARD_IMAGES_SHIFT_DOWN},
{"keyboard/images/tab.svg", IDR_KEYBOARD_IMAGES_TAB}, {"keyboard/images/tab.svg", IDR_KEYBOARD_IMAGES_TAB},
{"keyboard/index.html", IDR_KEYBOARD_INDEX},
{"keyboard/layout_us.js", IDR_KEYBOARD_LAYOUT_US_JS},
{"keyboard/main.css", IDR_KEYBOARD_MAIN_CSS},
{"keyboard/main.js", IDR_KEYBOARD_MAIN_JS},
{"keyboard/send_key_event.js", IDR_KEYBOARD_SEND_KEY_EVENT_JS},
#endif #endif
}; };
static const size_t kExtraComponentExtensionResourcesSize = static const size_t kExtraComponentExtensionResourcesSize =
......
...@@ -50,6 +50,8 @@ ...@@ -50,6 +50,8 @@
'keyboard_switches.h', 'keyboard_switches.h',
'keyboard_ui_controller.cc', 'keyboard_ui_controller.cc',
'keyboard_ui_controller.h', 'keyboard_ui_controller.h',
'keyboard_ui_handler.cc',
'keyboard_ui_handler.h',
'keyboard_util.cc', 'keyboard_util.cc',
'keyboard_util.h', 'keyboard_util.h',
] ]
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
NOTE: if you are adding resources here, you should probably also edit: NOTE: if you are adding resources here, you should probably also edit:
chrome/browser/ui/webui/virtual_keyboard_ui.cc // FIXME: this will move
chrome/browser/extensions/image_loader.cc chrome/browser/extensions/image_loader.cc
ui/keyboard/keyboard_ui_controller.cc
--> -->
<grit latest_public_release="0" current_release="1"> <grit latest_public_release="0" current_release="1">
<outputs> <outputs>
...@@ -14,20 +14,22 @@ ...@@ -14,20 +14,22 @@
</outputs> </outputs>
<release seq="1"> <release seq="1">
<includes> <includes>
<include name="IDR_KEYBOARD_MANIFEST" file="resources/manifest.json" type="BINDATA" />
<include name="IDR_KEYBOARD_INDEX" file="resources/index.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_KEYBOARD_MAIN_CSS" file="resources/main.css" type="BINDATA" />
<include name="IDR_KEYBOARD_MAIN_JS" file="resources/main.js" type="BINDATA" />
<include name="IDR_KEYBOARD_COMMON_JS" file="resources/common.js" type="BINDATA" /> <include name="IDR_KEYBOARD_COMMON_JS" file="resources/common.js" type="BINDATA" />
<include name="IDR_KEYBOARD_LAYOUT_US_JS" file="resources/layout_us.js" type="BINDATA" />
<include name="IDR_KEYBOARD_IMAGES_CHEVRON" file="resources/images/chevron.svg" type="BINDATA" /> <include name="IDR_KEYBOARD_IMAGES_CHEVRON" file="resources/images/chevron.svg" type="BINDATA" />
<include name="IDR_KEYBOARD_IMAGES_DEL" file="resources/images/del.svg" type="BINDATA" /> <include name="IDR_KEYBOARD_IMAGES_DEL" file="resources/images/del.svg" type="BINDATA" />
<include name="IDR_KEYBOARD_IMAGES_KEYBOARD" file="resources/images/keyboard.svg" type="BINDATA" /> <include name="IDR_KEYBOARD_IMAGES_KEYBOARD" file="resources/images/keyboard.svg" type="BINDATA" />
<include name="IDR_KEYBOARD_IMAGES_MIC" file="resources/images/mic.svg" type="BINDATA" /> <include name="IDR_KEYBOARD_IMAGES_MIC" file="resources/images/mic.svg" type="BINDATA" />
<include name="IDR_KEYBOARD_IMAGES_RET" file="resources/images/ret.svg" type="BINDATA" /> <include name="IDR_KEYBOARD_IMAGES_RET" file="resources/images/ret.svg" type="BINDATA" />
<include name="IDR_KEYBOARD_IMAGES_SHIFT_DOWN" file="resources/images/shift-down.svg" type="BINDATA" />
<include name="IDR_KEYBOARD_IMAGES_SHIFT" file="resources/images/shift.svg" type="BINDATA" /> <include name="IDR_KEYBOARD_IMAGES_SHIFT" file="resources/images/shift.svg" type="BINDATA" />
<include name="IDR_KEYBOARD_IMAGES_SHIFT_DOWN" file="resources/images/shift-down.svg" type="BINDATA" />
<include name="IDR_KEYBOARD_IMAGES_TAB" file="resources/images/tab.svg" type="BINDATA" /> <include name="IDR_KEYBOARD_IMAGES_TAB" file="resources/images/tab.svg" type="BINDATA" />
<include name="IDR_KEYBOARD_INDEX" file="resources/index.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_KEYBOARD_LAYOUT_US_JS" file="resources/layout_us.js" type="BINDATA" />
<include name="IDR_KEYBOARD_MAIN_CSS" file="resources/main.css" type="BINDATA" />
<include name="IDR_KEYBOARD_MAIN_JS" file="resources/main.js" type="BINDATA" />
<include name="IDR_KEYBOARD_MANIFEST" file="resources/manifest.json" type="BINDATA" />
<include name="IDR_KEYBOARD_SEND_KEY_EVENT_JS" file="resources/send_key_event.js" type="BINDATA" />
<include name="IDR_KEYBOARD_SEND_KEY_EVENT_WEBUI_JS" file="resources/send_key_event_webui.js" type="BINDATA" />
</includes> </includes>
</release> </release>
</grit> </grit>
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_data_source.h"
#include "grit/keyboard_resources.h" #include "grit/keyboard_resources.h"
#include "ui/keyboard/keyboard_constants.h" #include "ui/keyboard/keyboard_constants.h"
#include "ui/keyboard/keyboard_ui_handler.h"
namespace { namespace {
...@@ -19,20 +20,21 @@ content::WebUIDataSource* CreateKeyboardUIDataSource() { ...@@ -19,20 +20,21 @@ content::WebUIDataSource* CreateKeyboardUIDataSource() {
source->SetDefaultResource(IDR_KEYBOARD_INDEX); source->SetDefaultResource(IDR_KEYBOARD_INDEX);
source->AddResourcePath("main.css", IDR_KEYBOARD_MAIN_CSS);
source->AddResourcePath("main.js", IDR_KEYBOARD_MAIN_JS);
source->AddResourcePath("common.js", IDR_KEYBOARD_COMMON_JS); source->AddResourcePath("common.js", IDR_KEYBOARD_COMMON_JS);
source->AddResourcePath("layout_us.js", IDR_KEYBOARD_LAYOUT_US_JS);
source->AddResourcePath("images/chevron.svg", IDR_KEYBOARD_IMAGES_CHEVRON); source->AddResourcePath("images/chevron.svg", IDR_KEYBOARD_IMAGES_CHEVRON);
source->AddResourcePath("images/del.svg", IDR_KEYBOARD_IMAGES_DEL); source->AddResourcePath("images/del.svg", IDR_KEYBOARD_IMAGES_DEL);
source->AddResourcePath("images/keyboard.svg", IDR_KEYBOARD_IMAGES_KEYBOARD); source->AddResourcePath("images/keyboard.svg", IDR_KEYBOARD_IMAGES_KEYBOARD);
source->AddResourcePath("images/mic.svg", IDR_KEYBOARD_IMAGES_MIC); source->AddResourcePath("images/mic.svg", IDR_KEYBOARD_IMAGES_MIC);
source->AddResourcePath("images/ret.svg", IDR_KEYBOARD_IMAGES_RET); source->AddResourcePath("images/ret.svg", IDR_KEYBOARD_IMAGES_RET);
source->AddResourcePath("images/shift.svg", IDR_KEYBOARD_IMAGES_SHIFT);
source->AddResourcePath("images/shift_down.svg", source->AddResourcePath("images/shift_down.svg",
IDR_KEYBOARD_IMAGES_SHIFT_DOWN); IDR_KEYBOARD_IMAGES_SHIFT_DOWN);
source->AddResourcePath("images/shift.svg", IDR_KEYBOARD_IMAGES_SHIFT);
source->AddResourcePath("images/tab.svg", IDR_KEYBOARD_IMAGES_TAB); source->AddResourcePath("images/tab.svg", IDR_KEYBOARD_IMAGES_TAB);
source->AddResourcePath("layout_us.js", IDR_KEYBOARD_LAYOUT_US_JS);
source->AddResourcePath("main.css", IDR_KEYBOARD_MAIN_CSS);
source->AddResourcePath("main.js", IDR_KEYBOARD_MAIN_JS);
source->AddResourcePath("send_key_event.js",
IDR_KEYBOARD_SEND_KEY_EVENT_WEBUI_JS);
return source; return source;
} }
...@@ -45,6 +47,7 @@ KeyboardUIController::KeyboardUIController(content::WebUI* web_ui) ...@@ -45,6 +47,7 @@ KeyboardUIController::KeyboardUIController(content::WebUI* web_ui)
: WebUIController(web_ui) { : WebUIController(web_ui) {
content::BrowserContext* browser_context = content::BrowserContext* browser_context =
web_ui->GetWebContents()->GetBrowserContext(); web_ui->GetWebContents()->GetBrowserContext();
web_ui->AddMessageHandler(new KeyboardUIHandler());
content::WebUIDataSource::Add( content::WebUIDataSource::Add(
browser_context, browser_context,
CreateKeyboardUIDataSource()); CreateKeyboardUIDataSource());
......
// Copyright (c) 2013 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/keyboard/keyboard_ui_handler.h"
#include <string>
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/browser/web_ui.h"
#include "ui/aura/root_window.h"
#include "ui/base/events/event.h"
#include "ui/keyboard/keyboard_util.h"
namespace keyboard {
KeyboardUIHandler::KeyboardUIHandler() {
}
KeyboardUIHandler::~KeyboardUIHandler() {
}
void KeyboardUIHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
"sendKeyEvent",
base::Bind(&KeyboardUIHandler::HandleSendKeyEventMessage,
base::Unretained(this)));
}
void KeyboardUIHandler::HandleSendKeyEventMessage(const base::ListValue* args) {
std::string error;
scoped_ptr<ui::KeyEvent> event(keyboard::KeyEventFromArgs(args, &error));
if (!event) {
LOG(ERROR) << "sendKeyEvent failed: " << error;
return;
}
aura::RootWindow* root_window =
web_ui()->GetWebContents()->GetView()->GetNativeView()->GetRootWindow();
root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(event.get());
}
} // namespace keyboard
// Copyright (c) 2013 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_KEYBOARD_KEYBOARD_UI_HANDLER_H_
#define UI_KEYBOARD_KEYBOARD_UI_HANDLER_H_
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "content/public/browser/web_ui_message_handler.h"
namespace keyboard {
// The WebUI handler for chrome://keyboard. Delivers events to the
// aura::RootWindow associated with the WebUI.
class KeyboardUIHandler : public content::WebUIMessageHandler {
public:
KeyboardUIHandler();
virtual ~KeyboardUIHandler();
private:
// |content::WebUIMessageHandler| implementation:
virtual void RegisterMessages() OVERRIDE;
// Callback for the "sendKeyEvent" message.
void HandleSendKeyEventMessage(const base::ListValue* args);
DISALLOW_COPY_AND_ASSIGN(KeyboardUIHandler);
};
} // namespace keyboard
#endif // UI_KEYBOARD_KEYBOARD_UI_HANDLER_H_
...@@ -4,9 +4,69 @@ ...@@ -4,9 +4,69 @@
#include "ui/keyboard/keyboard_util.h" #include "ui/keyboard/keyboard_util.h"
#include <string>
#include "base/command_line.h" #include "base/command_line.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "ui/base/events/event.h"
#include "ui/base/events/event_constants.h"
#include "ui/base/events/key_identifier_conversion.h"
#include "ui/keyboard/keyboard_switches.h" #include "ui/keyboard/keyboard_switches.h"
namespace {
// KeyEvent dictionary keys
const char kType[] = "type";
const char kKeyIdentifier[] = "keyIdentifier";
const char kAlt[] = "altKey";
const char kCtrl[] = "ctrlKey";
const char kMeta[] = "metaKey";
const char kShift[] = "shiftKey";
const char kKeyDown[] = "keydown";
const char kKeyUp[] = "keyup";
// Errors.
const char kInvalidArgumentsListError[] =
"Argument list does not contain a dictionary.";
const char kInvalidKeyEventMissingKeyIdentifierError[] =
"KeyEvent object is missing the keyIdentifier field";
const char kInvalidKeyEventMissingTypeError[] =
"KeyEvent object is missing the type field";
const char kUnknownKeyEventTypeError[] =
"Unknown event type in KeyEvent.";
const char kUnknownOrUnsupportedKeyIdentiferError[] =
"Unknown or unsupported key identifier.";
const char kUnsupportedModifierError[] =
"Unsupported modifier (meta).";
ui::EventType GetTypeFromString(const std::string& type) {
if (type == kKeyDown) {
return ui::ET_KEY_PRESSED;
} else if (type == kKeyUp) {
return ui::ET_KEY_RELEASED;
}
return ui::ET_UNKNOWN;
}
// Converts a hex string "U+NNNN" to uint16. Returns 0 on error.
uint16 UnicodeIdentifierStringToInt(const std::string& key_identifier) {
int character = 0;
if ((key_identifier.length() == 6) &&
(key_identifier.substr(0, 2) == "U+") &&
(key_identifier.substr(2).find_first_not_of("0123456789abcdefABCDEF") ==
std::string::npos)) {
const bool result =
base::HexStringToInt(key_identifier.substr(2), &character);
DCHECK(result) << key_identifier;
}
return character;
}
} // namespace
namespace keyboard { namespace keyboard {
bool IsKeyboardEnabled() { bool IsKeyboardEnabled() {
...@@ -14,4 +74,69 @@ bool IsKeyboardEnabled() { ...@@ -14,4 +74,69 @@ bool IsKeyboardEnabled() {
switches::kEnableVirtualKeyboard); switches::kEnableVirtualKeyboard);
} }
ui::KeyEvent* KeyEventFromArgs(const base::ListValue* args,
std::string* error) {
const DictionaryValue* key_event;
if (!args->GetDictionary(0, &key_event)) {
*error = kInvalidArgumentsListError;
return NULL;
}
std::string type_name;
if (!key_event->GetString(kType, &type_name)) {
*error = kInvalidKeyEventMissingTypeError;
return NULL;
}
ui::EventType type = GetTypeFromString(type_name);
if (type == ui::ET_UNKNOWN) {
*error = kUnknownKeyEventTypeError;
return NULL;
}
std::string identifier;
if (!key_event->GetString(kKeyIdentifier, &identifier)) {
*error = kInvalidKeyEventMissingKeyIdentifierError;
return NULL;
}
TrimWhitespaceASCII(identifier, TRIM_ALL, &identifier);
const ui::KeyEvent& prototype_event =
ui::KeyEventFromKeyIdentifier(identifier);
uint16 character = 0;
if (prototype_event.key_code() == ui::VKEY_UNKNOWN) {
character = UnicodeIdentifierStringToInt(identifier);
if (!character) {
*error = kUnknownOrUnsupportedKeyIdentiferError;
return NULL;
}
}
int flags = 0;
if (prototype_event.key_code() != ui::VKEY_UNKNOWN)
flags = prototype_event.flags();
bool flag = false;
if (key_event->GetBoolean(kAlt, &flag) && flag)
flags |= ui::EF_ALT_DOWN;
if (key_event->GetBoolean(kCtrl, &flag) && flag)
flags |= ui::EF_CONTROL_DOWN;
if (key_event->GetBoolean(kShift, &flag) && flag)
flags |= ui::EF_SHIFT_DOWN;
if (key_event->GetBoolean(kMeta, &flag) && flag) {
// ui::KeyEvent does not have a Meta flag, so return an error for now.
*error = kUnsupportedModifierError;
return NULL;
}
ui::KeyEvent* event = new ui::KeyEvent(
type, prototype_event.key_code(), flags, prototype_event.is_char());
if (character) {
event->set_character(character);
event->set_unmodified_character(character);
}
return event;
}
} // namespace keyboard } // namespace keyboard
...@@ -5,13 +5,32 @@ ...@@ -5,13 +5,32 @@
#ifndef UI_KEYBOARD_KEYBOARD_UTIL_H_ #ifndef UI_KEYBOARD_KEYBOARD_UTIL_H_
#define UI_KEYBOARD_KEYBOARD_UTIL_H_ #define UI_KEYBOARD_KEYBOARD_UTIL_H_
#include <string>
#include "ui/keyboard/keyboard_export.h" #include "ui/keyboard/keyboard_export.h"
namespace base {
class ListValue;
}
namespace ui {
class KeyEvent;
}
namespace keyboard { namespace keyboard {
// Returns true if the virtual keyboard is enabled. // Returns true if the virtual keyboard is enabled.
KEYBOARD_EXPORT bool IsKeyboardEnabled(); KEYBOARD_EXPORT bool IsKeyboardEnabled();
// Creates a ui::KeyEvent from the argument base::ListValue that is passed to
// the synthetic input APIs (either the Extension API or the WebUI API). The
// returned ui::KeyEvent is owned by the caller. If an error occurs, NULL is
// returned and |error| will be populated with a description of the error. For
// a description of the expected input, please see
// chrome/common/extensions/api/experimental_input_virtual_keyboard.json
KEYBOARD_EXPORT ui::KeyEvent* KeyEventFromArgs(const base::ListValue* args,
std::string* error);
} // namespace keyboard } // namespace keyboard
#endif // UI_KEYBOARD_KEYBOARD_UTIL_H_ #endif // UI_KEYBOARD_KEYBOARD_UTIL_H_
...@@ -114,28 +114,15 @@ function transitionMode(transition) { ...@@ -114,28 +114,15 @@ function transitionMode(transition) {
setMode(MODE_TRANSITIONS[currentMode + transition]); setMode(MODE_TRANSITIONS[currentMode + transition]);
} }
function logIfError() {
if (chrome.runtime.lastError) {
console.log(chrome.runtime.lastError);
}
}
/** /**
* Send the given key to chrome, via the experimental extension API. * Send the given key to chrome, via the experimental extension API.
* @param {string} keyIdentifier The key to send. * @param {string} keyIdentifier The key to send.
*/ */
function sendKey(keyIdentifier) { function sendKey(keyIdentifier) {
// FIXME(bryeung)
console.log('Typed: ' + keyIdentifier);
var keyEvent = { var keyEvent = {
type: 'keydown',
keyIdentifier: keyIdentifier keyIdentifier: keyIdentifier
}; };
chrome.experimental.input.virtualKeyboard.sendKeyboardEvent(keyEvent, sendKeyEvent(keyEvent);
logIfError);
keyEvent.type = 'keyup';
chrome.experimental.input.virtualKeyboard.sendKeyboardEvent(keyEvent,
logIfError);
// Exit shift mode after pressing any key but space. // Exit shift mode after pressing any key but space.
if (currentMode == SHIFT_MODE && keyIdentifier != 'Spacebar') { if (currentMode == SHIFT_MODE && keyIdentifier != 'Spacebar') {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
<html> <html>
<head> <head>
<link rel="stylesheet" href="main.css"> <link rel="stylesheet" href="main.css">
<script src="send_key_event.js"></script>
<script src="common.js"></script> <script src="common.js"></script>
<script src="layout_us.js"></script> <script src="layout_us.js"></script>
<script src="main.js"></script> <script src="main.js"></script>
......
// Copyright (c) 2013 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.
function logIfError() {
if (chrome.runtime.lastError) {
console.log(chrome.runtime.lastError);
}
}
function sendKeyEvent(keyEvent) {
keyEvent.type = 'keydown';
chrome.experimental.input.virtualKeyboard.sendKeyboardEvent(keyEvent,
logIfError);
keyEvent.type = 'keyup';
chrome.experimental.input.virtualKeyboard.sendKeyboardEvent(keyEvent,
logIfError);
}
// Copyright (c) 2013 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.
function sendKeyEvent(keyEvent) {
keyEvent.type = 'keydown';
chrome.send('sendKeyEvent', [ keyEvent ]);
keyEvent.type = 'keyup';
chrome.send('sendKeyEvent', [ keyEvent ]);
}
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