Index: ui/keyboard/keyboard_util.cc |
diff --git a/ui/keyboard/keyboard_util.cc b/ui/keyboard/keyboard_util.cc |
index 076eacff109eccdc480903b38289cf1ff2d1386b..e14045ebc5512a0f16914bf3b64d9fd61f1ca684 100644 |
--- a/ui/keyboard/keyboard_util.cc |
+++ b/ui/keyboard/keyboard_util.cc |
@@ -15,8 +15,67 @@ |
#include "ui/aura/root_window.h" |
#include "ui/base/ime/input_method.h" |
#include "ui/base/ime/text_input_client.h" |
+#include "ui/base/keycodes/keyboard_code_conversion.h" |
#include "ui/keyboard/keyboard_switches.h" |
+namespace { |
+ |
+const char kKeyPressed[] ="keyPressed"; |
+const char kKeyReleased[] = "keyReleased"; |
+ |
+const int kMinKeyCode = ui::VKEY_BACK; |
+const int kMaxKeyCode = ui::VKEY_OEM_CLEAR; |
+const int kMaxKeyChar = 0x7f; |
+ |
+static bool initialized = false; |
+static int unshifted_character_map[kMaxKeyChar]; |
+static int shifted_character_map[kMaxKeyChar]; |
+ |
+// Initializes mapping of characters to keycodes. |
+void InitCharacterMapping() { |
+ for (int i = kMinKeyCode; i <= kMaxKeyCode; i++) { |
+ uint16 ch = ui::GetCharacterFromKeyCode(static_cast<ui::KeyboardCode>(i), |
bshe
2013/07/25 15:33:05
nit: indent is off here.
kevers
2013/07/26 00:53:30
Fixed.
|
+ ui::EF_NONE); |
+ if (ch > 0 && ch < kMaxKeyChar) |
+ unshifted_character_map[ch] = i; |
+ ch = ui::GetCharacterFromKeyCode(static_cast<ui::KeyboardCode>(i), |
+ ui::EF_SHIFT_DOWN); |
+ if (ch > 0 && ch < kMaxKeyChar) |
+ shifted_character_map[ch] = i; |
+ } |
+ initialized = true; |
+} |
+ |
+// Creates a synthetic KeyEvent corresponding to a |char_code|. The KeyEvent |
+// contains a keycode and modifier flags. The character code is also |
+// explicitly set to enable key events for i18n characters not found on a |
+// US-English keyboard. |
+ui::KeyEvent CreateFabricatedKeyEvent(ui::EventType type, int char_code) { |
+ if (!initialized) |
+ InitCharacterMapping(); |
+ |
+ ui::KeyboardCode keyCode = ui::VKEY_UNKNOWN; |
+ int flags = ui::EF_NONE; |
+ if (char_code < kMaxKeyChar) { |
+ int unshifted = unshifted_character_map[char_code]; |
+ if (unshifted > 0) { |
+ keyCode = static_cast<ui::KeyboardCode>(unshifted); |
+ } else { |
+ int shifted = shifted_character_map[char_code]; |
+ if (shifted > 0) { |
+ keyCode = static_cast<ui::KeyboardCode>(shifted); |
+ flags = ui::EF_SHIFT_DOWN; |
+ } |
+ } |
+ } |
+ ui::KeyEvent event(type, keyCode, flags, false); |
+ event.set_character(char_code); |
+ event.set_unmodified_character(char_code); |
+ return event; |
+} |
+ |
+} // namespace |
+ |
namespace keyboard { |
bool IsKeyboardEnabled() { |
@@ -30,7 +89,7 @@ bool InsertText(const base::string16& text, aura::RootWindow* root_window) { |
// 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 |
+ // TODO(kevers): 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; |
@@ -64,6 +123,37 @@ bool InsertText(const base::string16& text, aura::RootWindow* root_window) { |
return true; |
} |
+bool DispatchKeyEvent(const std::string type, |
+ int char_code, |
+ aura::RootWindow* root_window) { |
+ ui::EventType event_type = ui::ET_UNKNOWN; |
+ if (type == kKeyPressed) |
+ event_type = ui::ET_KEY_PRESSED; |
+ else if (type == kKeyReleased) |
+ event_type = ui::ET_KEY_RELEASED; |
+ if (event_type == ui::ET_UNKNOWN) |
+ return false; |
+ |
+ ui::KeyEvent event = CreateFabricatedKeyEvent(event_type, char_code); |
+ if (event.key_code() != ui::VKEY_UNKNOWN) { |
+ root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&event); |
+ } else if (event_type == ui::ET_KEY_RELEASED) { |
+ // Though the KeyEvent has setters for unicode characters that are intended |
+ // for use with a virtual keyboard, these values are ignored further down |
+ // the pipeline, relying on the key code. The key code is 0 for most |
+ // characters not found on a US-English keyboard (the assumed configuration |
+ // for fabricated key events). Fall back on inserting raw text as a short- |
+ // term measure. |
+ // TODO(kevers): Fix handling of unicode characters to unify the code |
+ // paths and fix use cases where raw injection fails. |
+ base::string16 text; |
+ base::char16 chars[] = {static_cast<char16>(char_code), 0}; |
+ text.append(chars); |
+ return 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 |