From ce5916aa7b8323c651af377941093c774077cce8 Mon Sep 17 00:00:00 2001 From: "kevers@chromium.org" Date: Thu, 5 Sep 2013 13:04:09 +0000 Subject: 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 --- ui/keyboard/keyboard_ui_handler.cc | 38 ++++++++++++++ ui/keyboard/keyboard_ui_handler.h | 5 ++ ui/keyboard/keyboard_util.cc | 64 ++++++++++++++++-------- ui/keyboard/keyboard_util.h | 15 +++++- ui/keyboard/resources/api_adapter.js | 6 ++- ui/keyboard/resources/elements/kb-key-base.html | 19 +++---- ui/keyboard/resources/elements/kb-key-codes.html | 46 ++++++++++------- ui/keyboard/resources/elements/kb-key.html | 13 ++++- ui/keyboard/resources/elements/kb-keyboard.html | 22 ++++++-- ui/keyboard/resources/webui/api_adapter.js | 4 ++ 10 files changed, 175 insertions(+), 57 deletions(-) (limited to 'ui/keyboard') 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, ¶ms) || + !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(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(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 + }; + }, }); 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 @@ 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. --> +