summaryrefslogtreecommitdiffstats
path: root/ui/keyboard
diff options
context:
space:
mode:
authorkevers@chromium.org <kevers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-05 13:04:09 +0000
committerkevers@chromium.org <kevers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-05 13:04:09 +0000
commitce5916aa7b8323c651af377941093c774077cce8 (patch)
tree55efddc4cb1e0bd705ae369d777861983a61dbb1 /ui/keyboard
parent6c2beac20246525310f2e85f5f0c33fcdbd2dff8 (diff)
downloadchromium_src-ce5916aa7b8323c651af377941093c774077cce8.zip
chromium_src-ce5916aa7b8323c651af377941093c774077cce8.tar.gz
chromium_src-ce5916aa7b8323c651af377941093c774077cce8.tar.bz2
Switch from text insertion to key press and release events on the virtual keyboard. First step in integration the virtual keyboard with IMEs.
BUG=257093, 257098 Review URL: https://chromiumcodereview.appspot.com/20145004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221393 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/keyboard')
-rw-r--r--ui/keyboard/keyboard_ui_handler.cc38
-rw-r--r--ui/keyboard/keyboard_ui_handler.h5
-rw-r--r--ui/keyboard/keyboard_util.cc64
-rw-r--r--ui/keyboard/keyboard_util.h15
-rw-r--r--ui/keyboard/resources/api_adapter.js6
-rw-r--r--ui/keyboard/resources/elements/kb-key-base.html19
-rw-r--r--ui/keyboard/resources/elements/kb-key-codes.html46
-rw-r--r--ui/keyboard/resources/elements/kb-key.html13
-rw-r--r--ui/keyboard/resources/elements/kb-keyboard.html22
-rw-r--r--ui/keyboard/resources/webui/api_adapter.js4
10 files changed, 175 insertions, 57 deletions
diff --git a/ui/keyboard/keyboard_ui_handler.cc b/ui/keyboard/keyboard_ui_handler.cc
index 398d2f4..9d3920f 100644
--- a/ui/keyboard/keyboard_ui_handler.cc
+++ b/ui/keyboard/keyboard_ui_handler.cc
@@ -36,6 +36,11 @@ void KeyboardUIHandler::RegisterMessages() {
"getInputContext",
base::Bind(&KeyboardUIHandler::HandleGetInputContextMessage,
base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "sendKeyEvent",
+ base::Bind(&KeyboardUIHandler::HandleSendKeyEventMessage,
+ base::Unretained(this)));
+
}
void KeyboardUIHandler::HandleInsertTextMessage(const base::ListValue* args) {
@@ -87,4 +92,37 @@ void KeyboardUIHandler::HandleGetInputContextMessage(
results);
}
+void KeyboardUIHandler::HandleSendKeyEventMessage(
+ const base::ListValue* args) {
+ const base::DictionaryValue* params = NULL;
+ std::string type;
+ int char_value;
+ int key_code;
+ bool shift_modifier;
+
+ if (!args->GetDictionary(0, &params) ||
+ !params->GetString("type", &type) ||
+ !params->GetInteger("charValue", &char_value) ||
+ !params->GetInteger("keyCode", &key_code) ||
+ !params->GetBoolean("shiftKey", &shift_modifier)) {
+ LOG(ERROR) << "SendKeyEvent failed: bad argument";
+ return;
+ }
+
+ aura::RootWindow* root_window =
+ web_ui()->GetWebContents()->GetView()->GetNativeView()->GetRootWindow();
+ if (!root_window) {
+ LOG(ERROR) << "sendKeyEvent failed: no root window";
+ return;
+ }
+
+ if (!keyboard::SendKeyEvent(type,
+ char_value,
+ key_code,
+ shift_modifier,
+ root_window)) {
+ LOG(ERROR) << "sendKeyEvent failed";
+ }
+}
+
} // namespace keyboard
diff --git a/ui/keyboard/keyboard_ui_handler.h b/ui/keyboard/keyboard_ui_handler.h
index 5ff05a0..719852f 100644
--- a/ui/keyboard/keyboard_ui_handler.h
+++ b/ui/keyboard/keyboard_ui_handler.h
@@ -29,6 +29,11 @@ class KeyboardUIHandler : public content::WebUIMessageHandler {
// |args| should be an integer representing request ID.
void HandleGetInputContextMessage(const base::ListValue* args);
+ // Callback for the "sendKeyEvent" message. The first element in |args| is a
+ // dictionary containing an event type, the character being pressed or
+ // released, a virtual key code, and the state of the shift key.
+ void HandleSendKeyEventMessage(const base::ListValue* args);
+
DISALLOW_COPY_AND_ASSIGN(KeyboardUIHandler);
};
diff --git a/ui/keyboard/keyboard_util.cc b/ui/keyboard/keyboard_util.cc
index 8f827a8..b5afa09 100644
--- a/ui/keyboard/keyboard_util.cc
+++ b/ui/keyboard/keyboard_util.cc
@@ -17,6 +17,13 @@
#include "ui/base/ime/text_input_client.h"
#include "ui/keyboard/keyboard_switches.h"
+namespace {
+
+const char kKeyDown[] ="keydown";
+const char kKeyUp[] = "keyup";
+
+} // namespace
+
namespace keyboard {
bool IsKeyboardEnabled() {
@@ -28,28 +35,6 @@ bool InsertText(const base::string16& text, aura::RootWindow* root_window) {
if (!root_window)
return false;
- // Handle Backspace and Enter specially: using TextInputClient::InsertText is
- // very unreliable for these characters.
- // TODO(bryeung): remove this code once virtual keyboards are able to send
- // these events directly via the Input Injection API.
- if (text.length() == 1) {
- ui::KeyboardCode code = ui::VKEY_UNKNOWN;
- if (text[0] == L'\n')
- code = ui::VKEY_RETURN;
- else if (text[0] == L'\b')
- code = ui::VKEY_BACK;
-
- if (code != ui::VKEY_UNKNOWN) {
- ui::KeyEvent press_event(ui::ET_KEY_PRESSED, code, 0, 0);
- root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&press_event);
-
- ui::KeyEvent release_event(ui::ET_KEY_RELEASED, code, 0, 0);
- root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&release_event);
-
- return true;
- }
- }
-
ui::InputMethod* input_method = root_window->GetProperty(
aura::client::kRootWindowInputMethodKey);
if (!input_method)
@@ -103,6 +88,41 @@ bool MoveCursor(int swipe_direction,
return true;
}
+bool SendKeyEvent(const std::string type,
+ int key_value,
+ int key_code,
+ bool shift_modifier,
+ aura::RootWindow* root_window) {
+ ui::EventType event_type = ui::ET_UNKNOWN;
+ if (type == kKeyDown)
+ event_type = ui::ET_KEY_PRESSED;
+ else if (type == kKeyUp)
+ event_type = ui::ET_KEY_RELEASED;
+ if (event_type == ui::ET_UNKNOWN)
+ return false;
+
+ int flags = ui::EF_NONE;
+ if (shift_modifier)
+ flags = ui::EF_SHIFT_DOWN;
+
+ ui::KeyboardCode code = static_cast<ui::KeyboardCode>(key_code);
+
+ ui::KeyEvent event(event_type, code, flags, false);
+ event.set_character(key_value);
+ event.set_unmodified_character(key_value);
+
+ if (code != ui::VKEY_UNKNOWN) {
+ root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&event);
+ } else if (event_type == ui::ET_KEY_RELEASED) {
+ // TODO(kevers): Fix key handling to support key_value when code is
+ // VKEY_UNKNOWN.
+ base::string16 text;
+ text.push_back(static_cast<char16>(key_value));
+ InsertText(text, root_window);
+ }
+ return true;
+}
+
const GritResourceMap* GetKeyboardExtensionResources(size_t* size) {
// This looks a lot like the contents of a resource map; however it is
// necessary to have a custom path for the extension path, so the resource
diff --git a/ui/keyboard/keyboard_util.h b/ui/keyboard/keyboard_util.h
index 7d46433..bb0edfb 100644
--- a/ui/keyboard/keyboard_util.h
+++ b/ui/keyboard/keyboard_util.h
@@ -29,7 +29,7 @@ enum CursorMoveDirection {
KEYBOARD_EXPORT bool IsKeyboardEnabled();
// Insert |text| into the active TextInputClient associated with |root_window|,
-// if there is one. Returns true if |text| was successfully inserted. Note
+// if there is one. Returns true if |text| was successfully inserted. Note
// that this may convert |text| into ui::KeyEvents for injection in some
// special circumstances (i.e. VKEY_RETURN, VKEY_BACK).
KEYBOARD_EXPORT bool InsertText(const base::string16& text,
@@ -41,7 +41,18 @@ KEYBOARD_EXPORT bool MoveCursor(int swipe_direction,
int modifier_flags,
aura::RootWindow* root_window);
-// Get the list of keyboard resources. |size| is populated with the number of
+// Sends a fabricated key event, where |type| is the event type, |key_value|
+// is the unicode value of the character, |key_code| is the legacy key code
+// value, and |shift_modifier| indicates if the shift key is being virtually
+// pressed. The event is dispatched to the active TextInputClient associated
+// with |root_window|. The type may be "keydown" or "keyup".
+KEYBOARD_EXPORT bool SendKeyEvent(std::string type,
+ int key_value,
+ int key_code,
+ bool shift_modifier,
+ aura::RootWindow* root_window);
+
+// Get the list of keyboard resources. |size| is populated with the number of
// resources in the returned array.
KEYBOARD_EXPORT const GritResourceMap* GetKeyboardExtensionResources(
size_t* size);
diff --git a/ui/keyboard/resources/api_adapter.js b/ui/keyboard/resources/api_adapter.js
index ff6192f..b2cbdd7 100644
--- a/ui/keyboard/resources/api_adapter.js
+++ b/ui/keyboard/resources/api_adapter.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 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.
@@ -15,3 +15,7 @@ function insertText(text) {
function MoveCursor(swipe_direction, swipe_flags) {
chrome.virtualKeyboardPrivate.moveCursor(swipe_direction, swipe_flags);
}
+
+function sendKeyEvent(event) {
+ chrome.virtualKeyboardPrivate.sendKeyEvent(event, logIfError);
+}
diff --git a/ui/keyboard/resources/elements/kb-key-base.html b/ui/keyboard/resources/elements/kb-key-base.html
index 0b017ff..5968c9c 100644
--- a/ui/keyboard/resources/elements/kb-key-base.html
+++ b/ui/keyboard/resources/elements/kb-key-base.html
@@ -109,11 +109,7 @@
}
},
down: function(event) {
- var detail = {
- char: this.charValue,
- toLayout: this.toLayout,
- repeat: this.repeat
- };
+ var detail = this.PopulateDetails();
if (this.keysetRules && this.keysetRules.down != undefined) {
detail.toKeyset = this.keysetRules.down[TO_KEYSET - OFFSET];
detail.nextKeyset = this.keysetRules.down[NEXT_KEYSET - OFFSET];
@@ -136,10 +132,7 @@
},
up: function(event) {
clearTimeout(this.longPressTimer);
- var detail = {
- char: this.charValue,
- toLayout: this.toLayout
- };
+ var detail = this.PopulateDetails();
if (this.keysetRules && this.keysetRules.up != undefined) {
detail.toKeyset = this.keysetRules.up[TO_KEYSET - OFFSET];
detail.nextKeyset = this.keysetRules.up[NEXT_KEYSET - OFFSET];
@@ -156,6 +149,14 @@
get charValue() {
return this.char || this.textContent;
},
+
+ PopulateDetails: function() {
+ return {
+ char: this.charValue,
+ toLayout: this.toLayout,
+ repeat: this.repeat
+ };
+ },
});
</script>
</polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-key-codes.html b/ui/keyboard/resources/elements/kb-key-codes.html
index cf1a7c23..b8353ec 100644
--- a/ui/keyboard/resources/elements/kb-key-codes.html
+++ b/ui/keyboard/resources/elements/kb-key-codes.html
@@ -7,6 +7,9 @@
<polymer-element name="kb-key-codes">
<script>
(function() {
+ // Each virtual key event is assigned a unique ID.
+ var nextRequestID = 0;
+
// Keycodes have been deprecated in the KeyEvent specification, but are
// nonetheless required to support legacy web content. The Keycodes in the
// following table are based on subset of US-EN 101-key keyboard. These
@@ -139,31 +142,36 @@
/**
* Creates a virtual key event for use with the keyboard extension API.
- * @param {kb-key} key Instance of the kb-key element being pressed or
- * released.
+ * See http://www.w3.org/TR/DOM-Level-3-Events/#events-KeyboardEvent.
+ * @param {Object} detail Attribute of the key being pressed or released.
* @param {string} type The type of key event, which may be keydown
- * or keyreleased.
- * @return {keyCode: numeric,
- * modifiers: Array.<string>,
- * type: string,
- * value: string}
+ * or keyup.
+ * @return {?KeyboardEvent} A KeyboardEvent object, or undefined on
+ * failure.
*/
- CreateVirtualKeyEvent: function(key, type) {
- var keyCode = key.keyCode;
- var shiftModifier = key.shiftModifier;
+ createVirtualKeyEvent: function(detail, type) {
+ var char = detail.char;
+ if (!char || char.length != 1) {
+ console.error('Invalid key. Expected single character.');
+ return;
+ }
+ var keyCode = detail.keyCode;
+ var shiftModifier = detail.shiftModifier;
if (keyCode == undefined) {
- var state = this.GetKeyCodeAndModifiers(key.charValue);
- keyCode = state.keyCode;
- shiftModifier = state.shiftModifier;
+ var state = this.GetKeyCodeAndModifiers(char);
+ if (state) {
+ keyCode = state.keyCode;
+ shiftModifier = state.shiftModifier;
+ } else {
+ keyCode = 0;
+ shiftModifier = false;
+ }
}
- var modifiers = [];
- if (shiftModifier)
- modifiers.push('shiftKey');
return {
- keyCode: keyCode,
- modifiers: modifiers,
type: type,
- value: key.charValue,
+ charValue: char.charCodeAt(0),
+ keyCode: keyCode,
+ shiftKey: shiftModifier
};
},
});
diff --git a/ui/keyboard/resources/elements/kb-key.html b/ui/keyboard/resources/elements/kb-key.html
index ffa2e0b3..b8ec5cb 100644
--- a/ui/keyboard/resources/elements/kb-key.html
+++ b/ui/keyboard/resources/elements/kb-key.html
@@ -39,7 +39,18 @@
* Keys with a high weighting are wider than normal keys.
* @type {number}
*/
- weight: 1
+ weight: 1,
+
+ /**
+ * Returns a subset of the key attributes.
+ * @return {Object} Mapping of attributes for the key element.
+ */
+ PopulateDetails: function() {
+ var details = this.super();
+ details.keyCode = this.keyCode;
+ details.shiftModifier = this.shiftModifier;
+ return details;
+ },
});
</script>
</polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-keyboard.html b/ui/keyboard/resources/elements/kb-keyboard.html
index 93cc165..2082a84 100644
--- a/ui/keyboard/resources/elements/kb-keyboard.html
+++ b/ui/keyboard/resources/elements/kb-keyboard.html
@@ -23,6 +23,7 @@
-- keyboard layouts.
-->
<content select="#{{layout}}-{{keyset}}"></content>
+ <kb-key-codes id="keyCodeMetadata"></kb-key-codes>
</template>
<script>
/**
@@ -297,12 +298,13 @@
}
if (detail.repeat) {
- insertText(detail.char);
+ this.keyTyped(detail);
repeatKey.key = this.lastPressedKey;
+ var self = this;
repeatKey.timer = setTimeout(function() {
repeatKey.timer = undefined;
repeatKey.interval = setInterval(function() {
- insertText(detail.char);
+ self.keyTyped(detail);
}, REPEAT_INTERVAL_MSEC);
}, Math.max(0, REPEAT_DELAY_MSEC - REPEAT_INTERVAL_MSEC));
}
@@ -435,7 +437,10 @@
default:
break;
}
- insertText(char);
+ if (char.length == 1)
+ this.keyTyped(detail);
+ else
+ insertText(char);
},
/*
@@ -494,6 +499,17 @@
},
/**
+ * Generates fabricated key events to simulate typing on a
+ * physical keyboard.
+ * @param {Object} detail Attributes of the key being typed.
+ */
+ keyTyped: function(detail) {
+ var builder = this.$.keyCodeMetadata;
+ sendKeyEvent(builder.createVirtualKeyEvent(detail, "keydown"));
+ sendKeyEvent(builder.createVirtualKeyEvent(detail, "keyup"));
+ },
+
+ /**
* Selects the default keyset for a layout.
* @return {boolean} True if successful. This method can fail if the
* keysets corresponding to the layout have not been injected.
diff --git a/ui/keyboard/resources/webui/api_adapter.js b/ui/keyboard/resources/webui/api_adapter.js
index 3072775..4adb177 100644
--- a/ui/keyboard/resources/webui/api_adapter.js
+++ b/ui/keyboard/resources/webui/api_adapter.js
@@ -6,6 +6,10 @@ function insertText(text) {
chrome.send('insertText', [ text ]);
}
+function sendKeyEvent(event) {
+ chrome.send('sendKeyEvent', [ event ]);
+}
+
(function(exports) {
/**
* An array to save callbacks of each request.