summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryusukes@google.com <yusukes@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-27 02:18:57 +0000
committeryusukes@google.com <yusukes@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-27 02:18:57 +0000
commit000216bf8f9e65726df376d6cec16ab87f725fe0 (patch)
treefc410cc775afd396dab5541c5000085044fac025
parent54edcea75724b0cf2d883768c247ac448f2b408e (diff)
downloadchromium_src-000216bf8f9e65726df376d6cec16ab87f725fe0.zip
chromium_src-000216bf8f9e65726df376d6cec16ab87f725fe0.tar.gz
chromium_src-000216bf8f9e65726df376d6cec16ab87f725fe0.tar.bz2
Add Unicode character support to chrome.input.sendKeyboardEvent.
Currently, the API can fabricate a key event which is supported by src/ui/base/keycodes/keyboard_codes_posix.h. This means the API only supports ASCII characters (<= 0x7f). However, since some i18n virtual keyboards need to call the API to generate a key event which is not supported by the header, it'd be better to relax the limitation. For example, French virtual keyboard might call the API with U+00E1 (LATIN SMALL LETTER A WITH ACUTE), Russian one might do it with U+0410 (CYRILLIC CAPITAL LETTER A). BUG=chromium-os:18048 TEST=run browser_tests Review URL: http://codereview.chromium.org/7473025 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@94236 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/extension_input_api.cc33
-rw-r--r--chrome/test/data/extensions/api_test/input/test.js67
-rw-r--r--views/events/event.cc4
-rw-r--r--views/events/event.h12
-rw-r--r--views/events/event_gtk.cc4
-rw-r--r--views/events/event_unittest.cc13
-rw-r--r--views/events/event_win.cc8
-rw-r--r--views/events/event_x.cc10
8 files changed, 143 insertions, 8 deletions
diff --git a/chrome/browser/extensions/extension_input_api.cc b/chrome/browser/extensions/extension_input_api.cc
index 503bea3..7916a5f 100644
--- a/chrome/browser/extensions/extension_input_api.cc
+++ b/chrome/browser/extensions/extension_input_api.cc
@@ -6,6 +6,7 @@
#include <string>
+#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/extensions/key_identifier_conversion_views.h"
@@ -58,6 +59,20 @@ ui::EventType GetTypeFromString(const std::string& type) {
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
void InputFunction::Run() {
@@ -109,13 +124,20 @@ bool SendKeyboardEventInputFunction::RunImpl() {
const views::KeyEvent& prototype_event =
KeyEventFromKeyIdentifier(identifier);
+ uint16 character = 0;
if (prototype_event.key_code() == ui::VKEY_UNKNOWN) {
- error_ = kUnknownOrUnsupportedKeyIdentiferError;
- return false;
+ // Check if |identifier| is "U+NNNN" format.
+ character = UnicodeIdentifierStringToInt(identifier);
+ if (!character) {
+ error_ = kUnknownOrUnsupportedKeyIdentiferError;
+ return false;
+ }
}
bool flag = false;
- int flags = prototype_event.flags();
+ 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;
@@ -132,6 +154,11 @@ bool SendKeyboardEventInputFunction::RunImpl() {
}
views::KeyEvent event(type, prototype_event.key_code(), flags);
+ if (character) {
+ event.set_character(character);
+ event.set_unmodified_character(character);
+ }
+
views::InputMethod* ime = widget->GetInputMethod();
if (ime) {
ime->DispatchKeyEvent(event);
diff --git a/chrome/test/data/extensions/api_test/input/test.js b/chrome/test/data/extensions/api_test/input/test.js
index 2506400..e1ef0f9 100644
--- a/chrome/test/data/extensions/api_test/input/test.js
+++ b/chrome/test/data/extensions/api_test/input/test.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -48,4 +48,69 @@ chrome.test.runTests([
chrome.test.succeed();
});
},
+
+ function sendKeyboardEventUnicode1() {
+ // U+00E1: LATIN SMALL LATTER A WITH ACUTE.
+ var e = { 'type': 'keydown', 'keyIdentifier': 'U+00E1' };
+ chrome.experimental.input.sendKeyboardEvent(e, function() {
+ if (chrome.extension.lastError) {
+ // this is expected for now. See sendKeyboardEvent().
+ // chrome.test.fail();
+ }
+ chrome.test.succeed();
+ });
+ },
+
+ function sendKeyboardEventUnicode2() {
+ // U+043A: CYRILLIC SMALL LETTER KA
+ var e = { 'type': 'keydown',
+ 'keyIdentifier': 'U+043a' }; // lower case is also ok.
+ chrome.experimental.input.sendKeyboardEvent(e, function() {
+ if (chrome.extension.lastError) {
+ // this is expected for now. See sendKeyboardEvent().
+ // chrome.test.fail();
+ }
+ chrome.test.succeed();
+ });
+ },
+
+ function sendKeyboardEventBadUnicode1() {
+ var e = { 'type': 'keydown', 'keyIdentifier': 'U+' };
+ chrome.experimental.input.sendKeyboardEvent(e, function() {
+ if (!chrome.extension.lastError) {
+ chrome.test.fail();
+ }
+ chrome.test.succeed();
+ });
+ },
+
+ function sendKeyboardEventBadUnicode2() {
+ var e = { 'type': 'keydown', 'keyIdentifier': 'U+1' };
+ chrome.experimental.input.sendKeyboardEvent(e, function() {
+ if (!chrome.extension.lastError) {
+ chrome.test.fail();
+ }
+ chrome.test.succeed();
+ });
+ },
+
+ function sendKeyboardEventBadUnicode3() {
+ var e = { 'type': 'keydown', 'keyIdentifier': 'U+111g' };
+ chrome.experimental.input.sendKeyboardEvent(e, function() {
+ if (!chrome.extension.lastError) {
+ chrome.test.fail();
+ }
+ chrome.test.succeed();
+ });
+ },
+
+ function sendKeyboardEventBadUnicode4() {
+ var e = { 'type': 'keydown', 'keyIdentifier': 'U+11111' };
+ chrome.experimental.input.sendKeyboardEvent(e, function() {
+ if (!chrome.extension.lastError) {
+ chrome.test.fail();
+ }
+ chrome.test.succeed();
+ });
+ },
]);
diff --git a/views/events/event.cc b/views/events/event.cc
index 102243a..a8db132 100644
--- a/views/events/event.cc
+++ b/views/events/event.cc
@@ -66,7 +66,9 @@ LocatedEvent::LocatedEvent(const LocatedEvent& model, View* root)
KeyEvent::KeyEvent(ui::EventType type, ui::KeyboardCode key_code,
int event_flags)
: Event(type, event_flags),
- key_code_(key_code) {
+ key_code_(key_code),
+ character_(0),
+ unmodified_character_(0) {
}
// KeyEvent, private: ---------------------------------------------------------
diff --git a/views/events/event.h b/views/events/event.h
index 03eec99..7c42537 100644
--- a/views/events/event.h
+++ b/views/events/event.h
@@ -316,6 +316,15 @@ class KeyEvent : public Event {
ui::KeyboardCode key_code() const { return key_code_; }
+ // These setters allow an I18N virtual keyboard to fabricate a keyboard event
+ // which does not have a corresponding ui::KeyboardCode (example: U+00E1 Latin
+ // small letter A with acute, U+0410 Cyrillic capital letter A.)
+ // GetCharacter() and GetUnmodifiedCharacter() return the character.
+ void set_character(uint16 character) { character_ = character; }
+ void set_unmodified_character(uint16 unmodified_character) {
+ unmodified_character_ = unmodified_character;
+ }
+
// Gets the character generated by this key event. It only supports Unicode
// BMP characters.
uint16 GetCharacter() const;
@@ -351,6 +360,9 @@ class KeyEvent : public Event {
ui::KeyboardCode key_code_;
+ uint16 character_;
+ uint16 unmodified_character_;
+
DISALLOW_COPY_AND_ASSIGN(KeyEvent);
};
diff --git a/views/events/event_gtk.cc b/views/events/event_gtk.cc
index e5018df..13c8a8d 100644
--- a/views/events/event_gtk.cc
+++ b/views/events/event_gtk.cc
@@ -169,7 +169,9 @@ KeyEvent::KeyEvent(NativeEvent native_event)
: Event(native_event, EventTypeFromNative(native_event),
GetFlagsFromGdkEvent(native_event)),
key_code_(ui::KeyboardCodeFromGdkEventKey(
- GetGdkEventKeyFromNative(native_event))) {
+ GetGdkEventKeyFromNative(native_event))),
+ character_(0),
+ unmodified_character_(0) {
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/views/events/event_unittest.cc b/views/events/event_unittest.cc
index 8afb48e..4694b59 100644
--- a/views/events/event_unittest.cc
+++ b/views/events/event_unittest.cc
@@ -103,4 +103,17 @@ TEST_F(EventTest, KeyEvent) {
}
}
+TEST_F(EventTest, KeyEventDirectUnicode) {
+ KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, ui::EF_SHIFT_DOWN);
+ key.set_character(0x1234U);
+ key.set_unmodified_character(0x4321U);
+ EXPECT_EQ(0x1234U, key.GetCharacter());
+ EXPECT_EQ(0x4321U, key.GetUnmodifiedCharacter());
+ KeyEvent key2(ui::ET_KEY_RELEASED, ui::VKEY_UNKNOWN, ui::EF_CONTROL_DOWN);
+ key2.set_character(0x4321U);
+ key2.set_unmodified_character(0x1234U);
+ EXPECT_EQ(0x4321U, key2.GetCharacter());
+ EXPECT_EQ(0x1234U, key2.GetUnmodifiedCharacter());
+}
+
} // namespace views
diff --git a/views/events/event_win.cc b/views/events/event_win.cc
index 683a4be..609e190 100644
--- a/views/events/event_win.cc
+++ b/views/events/event_win.cc
@@ -233,7 +233,9 @@ KeyEvent::KeyEvent(NativeEvent native_event)
: Event(native_event,
EventTypeFromNative(native_event),
GetKeyStateFlags()),
- key_code_(ui::KeyboardCodeForWindowsKeyCode(native_event.wParam)) {
+ key_code_(ui::KeyboardCodeForWindowsKeyCode(native_event.wParam)),
+ character_(0),
+ unmodified_character_(0) {
}
KeyEvent::KeyEvent(NativeEvent2 native_event_2, FromNativeEvent2 from_native)
@@ -244,11 +246,15 @@ KeyEvent::KeyEvent(NativeEvent2 native_event_2, FromNativeEvent2 from_native)
}
uint16 KeyEvent::GetCharacter() const {
+ if (character_)
+ return character_;
return (native_event().message == WM_CHAR) ? key_code_ :
GetCharacterFromKeyCode(key_code_, flags());
}
uint16 KeyEvent::GetUnmodifiedCharacter() const {
+ if (unmodified_character_)
+ return unmodified_character_;
// Looks like there is no way to get unmodified character on Windows.
return (native_event().message == WM_CHAR) ? key_code_ :
GetCharacterFromKeyCode(key_code_, flags() & ui::EF_SHIFT_DOWN);
diff --git a/views/events/event_x.cc b/views/events/event_x.cc
index dc88121..1f54303 100644
--- a/views/events/event_x.cc
+++ b/views/events/event_x.cc
@@ -295,10 +295,15 @@ KeyEvent::KeyEvent(NativeEvent2 native_event_2, FromNativeEvent2 from_native)
EventTypeFromNative(native_event_2),
GetEventFlagsFromXState(native_event_2->xkey.state),
from_native),
- key_code_(ui::KeyboardCodeFromXKeyEvent(native_event_2)) {
+ key_code_(ui::KeyboardCodeFromXKeyEvent(native_event_2)),
+ character_(0),
+ unmodified_character_(0) {
}
uint16 KeyEvent::GetCharacter() const {
+ if (character_)
+ return character_;
+
if (!native_event_2()) {
// This event may have been created from a Gdk event.
if (IsControlDown() || !native_event())
@@ -317,6 +322,9 @@ uint16 KeyEvent::GetCharacter() const {
}
uint16 KeyEvent::GetUnmodifiedCharacter() const {
+ if (unmodified_character_)
+ return unmodified_character_;
+
if (!native_event_2()) {
// This event may have been created from a Gdk event.
if (!native_event())