Removing uses of X11 native key events.

BUG=380349

Review URL: https://codereview.chromium.org/479873002

Cr-Commit-Position: refs/heads/master@{#293166}
diff --git a/ash/accelerators/key_hold_detector.cc b/ash/accelerators/key_hold_detector.cc
index 131568e..79cd93d5 100644
--- a/ash/accelerators/key_hold_detector.cc
+++ b/ash/accelerators/key_hold_detector.cc
@@ -19,29 +19,30 @@
 namespace ash {
 namespace {
 
-void DispatchPressedEvent(XEvent native_event,
+void DispatchPressedEvent(const ui::KeyEvent& key_event,
                           scoped_ptr<aura::WindowTracker> tracker) {
   // The target window may be gone.
   if (tracker->windows().empty())
     return;
+  ui::KeyEvent event(key_event);
   aura::Window* target = *(tracker->windows().begin());
-  ui::KeyEvent event(&native_event);
-  event.set_flags(event.flags() | ui::EF_IS_SYNTHESIZED);
   ui::EventDispatchDetails result ALLOW_UNUSED =
       target->GetHost()->event_processor()->OnEventFromSource(&event);
 }
 
 void PostPressedEvent(ui::KeyEvent* event) {
   // Modify RELEASED event to PRESSED event.
-  XEvent xkey = *(event->native_event());
-  xkey.xkey.type = KeyPress;
-  xkey.xkey.state |= ShiftMask;
+  const ui::KeyEvent pressed_event(
+      ui::ET_KEY_PRESSED,
+      event->key_code(),
+      event->code(),
+      event->flags() | ui::EF_SHIFT_DOWN | ui::EF_IS_SYNTHESIZED);
   scoped_ptr<aura::WindowTracker> tracker(new aura::WindowTracker);
   tracker->Add(static_cast<aura::Window*>(event->target()));
 
   base::MessageLoopForUI::current()->PostTask(
       FROM_HERE,
-      base::Bind(&DispatchPressedEvent, xkey, base::Passed(&tracker)));
+      base::Bind(&DispatchPressedEvent, pressed_event, base::Passed(&tracker)));
 }
 
 }  // namespace
diff --git a/content/browser/renderer_host/web_input_event_aura.cc b/content/browser/renderer_host/web_input_event_aura.cc
index a4cf12b..69c8960f 100644
--- a/content/browser/renderer_host/web_input_event_aura.cc
+++ b/content/browser/renderer_host/web_input_event_aura.cc
@@ -24,20 +24,16 @@
     const base::NativeEvent& native_event);
 blink::WebGestureEvent MakeWebGestureEventFromNativeEvent(
     const base::NativeEvent& native_event);
-#elif defined(USE_X11)
-blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
-    ui::KeyEvent* event);
-#elif defined(USE_OZONE)
+#endif
+#if defined(USE_X11) || defined(USE_OZONE)
 blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
     ui::KeyEvent* event) {
-  const base::NativeEvent& native_event = event->native_event();
-  ui::EventType type = ui::EventTypeFromNative(native_event);
   blink::WebKeyboardEvent webkit_event;
 
   webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
   webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
 
-  switch (type) {
+  switch (event->type()) {
     case ui::ET_KEY_PRESSED:
       webkit_event.type = event->is_char() ? blink::WebInputEvent::Char :
           blink::WebInputEvent::RawKeyDown;
@@ -52,31 +48,16 @@
   if (webkit_event.modifiers & blink::WebInputEvent::AltKey)
     webkit_event.isSystemKey = true;
 
-  wchar_t character = ui::KeyboardCodeFromNative(native_event);
-  webkit_event.windowsKeyCode = character;
-  webkit_event.nativeKeyCode = character;
-
-  if (webkit_event.windowsKeyCode == ui::VKEY_RETURN)
-    webkit_event.unmodifiedText[0] = '\r';
-  else
-    webkit_event.unmodifiedText[0] = ui::GetCharacterFromKeyCode(
-        ui::KeyboardCodeFromNative(native_event),
-        ui::EventFlagsFromNative(native_event));
-
-  if (webkit_event.modifiers & blink::WebInputEvent::ControlKey) {
-    webkit_event.text[0] = ui::GetControlCharacterForKeycode(
-        webkit_event.windowsKeyCode,
-        webkit_event.modifiers & blink::WebInputEvent::ShiftKey);
-  } else {
-    webkit_event.text[0] = webkit_event.unmodifiedText[0];
-  }
+  webkit_event.windowsKeyCode = event->GetLocatedWindowsKeyboardCode();
+  webkit_event.nativeKeyCode = event->platform_keycode();
+  webkit_event.unmodifiedText[0] = event->GetUnmodifiedText();
+  webkit_event.text[0] = event->GetText();
 
   webkit_event.setKeyIdentifierFromWindowsKeyCode();
 
   return webkit_event;
 }
-#endif
-#if defined(USE_X11) || defined(USE_OZONE)
+
 blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
     ui::ScrollEvent* event) {
   blink::WebMouseWheelEvent webkit_event;
@@ -240,9 +221,6 @@
 }
 
 blink::WebKeyboardEvent MakeWebKeyboardEvent(ui::KeyEvent* event) {
-  if (!event->HasNativeEvent())
-    return blink::WebKeyboardEvent();
-
   // Windows can figure out whether or not to construct a RawKeyDown or a Char
   // WebInputEvent based on the type of message carried in
   // event->native_event(). X11 is not so fortunate, there is no separate
@@ -250,6 +228,9 @@
   // is_char() == true. We need to pass the ui::KeyEvent to the X11 function
   // to detect this case so the right event type can be constructed.
 #if defined(OS_WIN)
+  if (!event->HasNativeEvent())
+    return blink::WebKeyboardEvent();
+
   // Key events require no translation by the aura system.
   return MakeWebKeyboardEventFromNativeEvent(event->native_event());
 #else
diff --git a/content/browser/renderer_host/web_input_event_aurax11.cc b/content/browser/renderer_host/web_input_event_aurax11.cc
deleted file mode 100644
index e07cf07..0000000
--- a/content/browser/renderer_host/web_input_event_aurax11.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2012 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.
-
-// Portions based heavily on:
-// third_party/WebKit/public/web/gtk/WebInputEventFactory.cpp
-//
-/*
- * Copyright (C) 2006-2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "content/browser/renderer_host/web_input_event_aura.h"
-
-#include <X11/keysym.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <cstdlib>
-
-#include "base/event_types.h"
-#include "base/logging.h"
-#include "content/browser/renderer_host/ui_events_helper.h"
-#include "ui/events/event.h"
-#include "ui/events/event_constants.h"
-#include "ui/events/event_utils.h"
-#include "ui/events/keycodes/keyboard_code_conversion_x.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-
-namespace content {
-
-// chromium WebKit does not provide a WebInputEventFactory for X11, so we have
-// to do the work here ourselves.
-
-blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
-    ui::KeyEvent* event) {
-  const base::NativeEvent& native_event = event->native_event();
-  blink::WebKeyboardEvent webkit_event;
-  XKeyEvent* native_key_event = &native_event->xkey;
-
-  webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
-  webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
-
-  switch (native_event->type) {
-    case KeyPress:
-      webkit_event.type = event->is_char() ? blink::WebInputEvent::Char :
-          blink::WebInputEvent::RawKeyDown;
-      break;
-    case KeyRelease:
-      webkit_event.type = blink::WebInputEvent::KeyUp;
-      break;
-    default:
-      NOTREACHED();
-  }
-
-  if (webkit_event.modifiers & blink::WebInputEvent::AltKey)
-    webkit_event.isSystemKey = true;
-
-  webkit_event.windowsKeyCode = ui::WindowsKeycodeFromNative(native_event);
-  webkit_event.nativeKeyCode = native_key_event->keycode;
-  webkit_event.unmodifiedText[0] =
-      ui::UnmodifiedTextFromNative(native_event);
-  webkit_event.text[0] = ui::TextFromNative(native_event);
-
-  webkit_event.setKeyIdentifierFromWindowsKeyCode();
-
-  // TODO: IsKeyPad?
-
-  return webkit_event;
-}
-
-}  // namespace content
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 29f39777..7006e40 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -1098,7 +1098,6 @@
       'browser/renderer_host/web_input_event_aura.cc',
       'browser/renderer_host/web_input_event_aura.h',
       'browser/renderer_host/web_input_event_aurawin.cc',
-      'browser/renderer_host/web_input_event_aurax11.cc',
       'browser/renderer_host/webmenurunner_mac.h',
       'browser/renderer_host/webmenurunner_mac.mm',
       'browser/renderer_host/websocket_dispatcher_host.cc',
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 6b8232d..810afc20 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -236,6 +236,8 @@
                         static_cast<ui::KeyboardCode>(key_code),
                         flags);
     ui::KeyEvent event2(xevent);
+    event2.set_character(GetCharacterFromKeyCode(event2.key_code(),
+                                                 event2.flags()));
     ui::KeyEventTestApi test_event2(&event2);
     test_event2.set_is_char(true);
     NativeWebKeyboardEvent char_event(&event2);
@@ -255,26 +257,21 @@
 #elif defined(USE_OZONE)
     const int flags = ConvertMockKeyboardModifier(modifiers);
 
-    // Ozone's native events are ui::Events. So first create the "native" event,
-    // then create the actual ui::KeyEvent with the native event.
-    ui::KeyEvent keydown_native_event(ui::ET_KEY_PRESSED,
-                                   static_cast<ui::KeyboardCode>(key_code),
-                                   flags);
-    ui::KeyEvent keydown_event(&keydown_native_event);
+    ui::KeyEvent keydown_event(ui::ET_KEY_PRESSED,
+                               static_cast<ui::KeyboardCode>(key_code),
+                               flags);
     NativeWebKeyboardEvent keydown_web_event(&keydown_event);
     SendNativeKeyEvent(keydown_web_event);
 
-    ui::KeyEvent char_native_event(static_cast<base::char16>(key_code),
-                                   static_cast<ui::KeyboardCode>(key_code),
-                                   flags);
-    ui::KeyEvent char_event(&char_native_event);
+    ui::KeyEvent char_event(keydown_event.GetCharacter(),
+                            static_cast<ui::KeyboardCode>(key_code),
+                            flags);
     NativeWebKeyboardEvent char_web_event(&char_event);
     SendNativeKeyEvent(char_web_event);
 
-    ui::KeyEvent keyup_native_event(ui::ET_KEY_RELEASED,
-                                    static_cast<ui::KeyboardCode>(key_code),
-                                    flags);
-    ui::KeyEvent keyup_event(&keyup_native_event);
+    ui::KeyEvent keyup_event(ui::ET_KEY_RELEASED,
+                             static_cast<ui::KeyboardCode>(key_code),
+                             flags);
     NativeWebKeyboardEvent keyup_web_event(&keyup_event);
     SendNativeKeyEvent(keyup_web_event);
 
diff --git a/mojo/services/native_viewport/platform_viewport_x11.cc b/mojo/services/native_viewport/platform_viewport_x11.cc
index dbf7fb80..d4914c7 100644
--- a/mojo/services/native_viewport/platform_viewport_x11.cc
+++ b/mojo/services/native_viewport/platform_viewport_x11.cc
@@ -104,9 +104,9 @@
 
       char_event.SetExtendedKeyEventData(scoped_ptr<ui::ExtendedKeyEventData>(
           new MojoExtendedKeyEventData(
-              ui::WindowsKeycodeFromNative(key_press_event->native_event()),
-              ui::TextFromNative(key_press_event->native_event()),
-              ui::UnmodifiedTextFromNative(key_press_event->native_event()))));
+              key_press_event->GetLocatedWindowsKeyboardCode(),
+              key_press_event->GetText(),
+              key_press_event->GetUnmodifiedText())));
       char_event.set_platform_keycode(key_press_event->platform_keycode());
 
       delegate_->OnEvent(&char_event);
diff --git a/mojo/services/public/cpp/input_events/lib/input_events_type_converters.cc b/mojo/services/public/cpp/input_events/lib/input_events_type_converters.cc
index 4520aa4..340e200 100644
--- a/mojo/services/public/cpp/input_events/lib/input_events_type_converters.cc
+++ b/mojo/services/public/cpp/input_events/lib/input_events_type_converters.cc
@@ -119,18 +119,12 @@
   } else if (input.IsKeyEvent()) {
     const ui::KeyEvent* key_event = static_cast<const ui::KeyEvent*>(&input);
     KeyDataPtr key_data(KeyData::New());
-    key_data->key_code = key_event->key_code();
+    key_data->key_code = key_event->GetConflatedWindowsKeyCode();
     key_data->native_key_code = key_event->platform_keycode();
     key_data->is_char = key_event->is_char();
     key_data->character = key_event->GetCharacter();
 
-    if (key_event->HasNativeEvent()) {
-      key_data->windows_key_code = static_cast<mojo::KeyboardCode>(
-          ui::WindowsKeycodeFromNative(key_event->native_event()));
-      key_data->text = ui::TextFromNative(key_event->native_event());
-      key_data->unmodified_text =
-          ui::UnmodifiedTextFromNative(key_event->native_event());
-    } else if (key_event->extended_key_event_data()) {
+    if (key_event->extended_key_event_data()) {
       const MojoExtendedKeyEventData* data =
           static_cast<const MojoExtendedKeyEventData*>(
               key_event->extended_key_event_data());
@@ -139,8 +133,10 @@
       key_data->text = data->text();
       key_data->unmodified_text = data->unmodified_text();
     } else {
-      NOTREACHED() << "Synthesized event which never contained a native event "
-          "passed to mojo::TypeConverter.";
+      key_data->windows_key_code = static_cast<mojo::KeyboardCode>(
+          key_event->GetLocatedWindowsKeyboardCode());
+      key_data->text = key_event->GetText();
+      key_data->unmodified_text = key_event->GetUnmodifiedText();
     }
 
     event->key_data = key_data.Pass();
diff --git a/ui/events/event.cc b/ui/events/event.cc
index 27de2a9..0ee1709 100644
--- a/ui/events/event.cc
+++ b/ui/events/event.cc
@@ -7,6 +7,7 @@
 #if defined(USE_X11)
 #include <X11/extensions/XInput2.h>
 #include <X11/Xlib.h>
+#include <X11/keysym.h>
 #endif
 
 #include <cmath>
@@ -591,6 +592,11 @@
 #if defined(USE_X11)
   NormalizeFlags();
 #endif
+#if defined(OS_WIN)
+  // Only Windows has native character events.
+  if (is_char_)
+    character_ = native_event.wParam;
+#endif
 }
 
 KeyEvent::KeyEvent(EventType type,
@@ -600,7 +606,7 @@
       key_code_(key_code),
       is_char_(false),
       platform_keycode_(0),
-      character_(GetCharacterFromKeyCode(key_code, flags)) {
+      character_() {
 }
 
 KeyEvent::KeyEvent(EventType type,
@@ -612,7 +618,7 @@
       code_(code),
       is_char_(false),
       platform_keycode_(0),
-      character_(GetCharacterFromKeyCode(key_code, flags)) {
+      character_(0) {
 }
 
 KeyEvent::KeyEvent(base::char16 character, KeyboardCode key_code, int flags)
@@ -657,15 +663,21 @@
 }
 
 base::char16 KeyEvent::GetCharacter() const {
-  if (character_)
+  if (is_char_ || character_)
     return character_;
 
+  // TODO(kpschoedel): streamline these cases after settling Ozone
+  // positional coding.
 #if defined(OS_WIN)
-  return (native_event().message == WM_CHAR) ? key_code_ :
-      GetCharacterFromKeyCode(key_code_, flags());
+  // Native Windows character events always have is_char_ == true,
+  // so this is a synthetic or native keystroke event.
+  character_ = GetCharacterFromKeyCode(key_code_, flags());
+  return character_;
 #elif defined(USE_X11)
-  if (!native_event())
-    return GetCharacterFromKeyCode(key_code_, flags());
+  if (!native_event()) {
+    character_ = GetCharacterFromKeyCode(key_code_, flags());
+    return character_;
+  }
 
   DCHECK(native_event()->type == KeyPress ||
          native_event()->type == KeyRelease ||
@@ -690,6 +702,20 @@
 #endif
 }
 
+base::char16 KeyEvent::GetText() const {
+  if ((flags() & EF_CONTROL_DOWN) != 0) {
+    return GetControlCharacterForKeycode(key_code_,
+                                         (flags() & EF_SHIFT_DOWN) != 0);
+  }
+  return GetUnmodifiedText();
+}
+
+base::char16 KeyEvent::GetUnmodifiedText() const {
+  if (!is_char_ && (key_code_ == VKEY_RETURN))
+    return '\r';
+  return GetCharacter();
+}
+
 bool KeyEvent::IsUnicodeKeyCode() const {
 #if defined(OS_WIN)
   if (!IsAltDown())
@@ -763,6 +789,83 @@
   }
 }
 
+bool KeyEvent::IsRightSideKey() const {
+  switch (key_code_) {
+    case VKEY_CONTROL:
+    case VKEY_SHIFT:
+    case VKEY_MENU:
+    case VKEY_LWIN:
+#if defined(USE_X11)
+      // Under X11, setting code_ requires platform-dependent information, and
+      // currently assumes that X keycodes are based on Linux evdev keycodes.
+      // In certain test environments this is not the case, and code_ is not
+      // set accurately, so we need a different mechanism. Fortunately X11 key
+      // mapping preserves the left-right distinction, so testing keysyms works
+      // if the value is available (as it is for all X11 native-based events).
+      if (platform_keycode_) {
+        return (platform_keycode_ == XK_Shift_R) ||
+               (platform_keycode_ == XK_Control_R) ||
+               (platform_keycode_ == XK_Alt_R) ||
+               (platform_keycode_ == XK_Meta_R) ||
+               (platform_keycode_ == XK_Super_R) ||
+               (platform_keycode_ == XK_Hyper_R);
+      }
+      // Fall through to the generic code if we have no platform_keycode_.
+      // Under X11, this must be a synthetic event, so we can require that
+      // code_ be set correctly.
+#endif
+      return ((code_.size() > 5) &&
+              (code_.compare(code_.size() - 5, 5, "Right", 5)) == 0);
+    default:
+      return false;
+  }
+}
+
+KeyboardCode KeyEvent::GetLocatedWindowsKeyboardCode() const {
+  switch (key_code_) {
+    case VKEY_SHIFT:
+      return IsRightSideKey() ? VKEY_RSHIFT : VKEY_LSHIFT;
+    case VKEY_CONTROL:
+      return IsRightSideKey() ? VKEY_RCONTROL : VKEY_LCONTROL;
+    case VKEY_MENU:
+      return IsRightSideKey() ? VKEY_RMENU : VKEY_LMENU;
+    case VKEY_LWIN:
+      return IsRightSideKey() ? VKEY_RWIN : VKEY_LWIN;
+    // TODO(kpschoedel): EF_NUMPAD_KEY is present only on X11. Currently this
+    // function is only called on X11. Likely the tests here will be replaced
+    // with a DOM-based code enumeration test in the course of Ozone
+    // platform-indpendent key event work.
+    case VKEY_0:
+      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD0 : VKEY_0;
+    case VKEY_1:
+      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD1 : VKEY_1;
+    case VKEY_2:
+      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD2 : VKEY_2;
+    case VKEY_3:
+      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD3 : VKEY_3;
+    case VKEY_4:
+      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD4 : VKEY_4;
+    case VKEY_5:
+      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD5 : VKEY_5;
+    case VKEY_6:
+      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD6 : VKEY_6;
+    case VKEY_7:
+      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD7 : VKEY_7;
+    case VKEY_8:
+      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD8 : VKEY_8;
+    case VKEY_9:
+      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD9 : VKEY_9;
+    default:
+      return key_code_;
+  }
+}
+
+uint16 KeyEvent::GetConflatedWindowsKeyCode() const {
+  if (is_char_)
+    return character_;
+  return key_code_;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // ScrollEvent
 
diff --git a/ui/events/event.h b/ui/events/event.h
index 7257f625..b950125 100644
--- a/ui/events/event.h
+++ b/ui/events/event.h
@@ -587,7 +587,7 @@
 // -- character_ is a UTF-16 character value.
 // -- key_code_ is conflated with character_ by some code, because both
 //    arrive in the wParam field of a Windows event.
-// -- code_ is "".
+// -- code_ is the empty string.
 //
 class EVENTS_EXPORT KeyEvent : public Event {
  public:
@@ -636,9 +636,24 @@
   // BMP characters.
   base::char16 GetCharacter() const;
 
+  // If this is a keystroke event with key_code_ VKEY_RETURN, returns '\r';
+  // otherwise returns the same as GetCharacter().
+  base::char16 GetUnmodifiedText() const;
+
+  // If the Control key is down in the event, returns a layout-independent
+  // character (corresponding to US layout); otherwise returns the same
+  // as GetUnmodifiedText().
+  base::char16 GetText() const;
+
   // Gets the platform key code. For XKB, this is the xksym value.
   void set_platform_keycode(uint32 keycode) { platform_keycode_ = keycode; }
   uint32 platform_keycode() const { return platform_keycode_; }
+
+  // Gets the associated (Windows-based) KeyboardCode for this key event.
+  // Historically, this has also been used to obtain the character associated
+  // with a character event, because both use the Window message 'wParam' field.
+  // This should be avoided; if necessary for backwards compatibility, use
+  // GetConflatedWindowsKeyCode().
   KeyboardCode key_code() const { return key_code_; }
 
   // True if this is a character event, false if this is a keystroke event.
@@ -648,6 +663,17 @@
   // events in an EventRewriter.
   void set_key_code(KeyboardCode key_code) { key_code_ = key_code; }
 
+  // Returns the same value as key_code(), except that located codes are
+  // returned in place of non-located ones (e.g. VKEY_LSHIFT or VKEY_RSHIFT
+  // instead of VKEY_SHIFT). This is a hybrid of semantic and physical
+  // for legacy DOM reasons.
+  KeyboardCode GetLocatedWindowsKeyboardCode() const;
+
+  // For a keystroke event, returns the same value as key_code().
+  // For a character event, returns the same value as GetCharacter().
+  // This exists for backwards compatibility with Windows key events.
+  uint16 GetConflatedWindowsKeyCode() const;
+
   // Returns true for [Alt]+<num-pad digit> Unicode alt key codes used by Win.
   // TODO(msw): Additional work may be needed for analogues on other platforms.
   bool IsUnicodeKeyCode() const;
@@ -671,6 +697,9 @@
   void set_is_char(bool is_char) { is_char_ = is_char; }
 
  private:
+  // True if the key press originated from a 'right' key (VKEY_RSHIFT, etc.).
+  bool IsRightSideKey() const;
+
   KeyboardCode key_code_;
 
   // String of 'code' defined in DOM KeyboardEvent (e.g. 'KeyA', 'Space')
@@ -693,7 +722,7 @@
   // This value represents the text that the key event will insert to input
   // field. For key with modifier key, it may have specifial text.
   // e.g. CTRL+A has '\x01'.
-  base::char16 character_;
+  mutable base::char16 character_;
 
   // Parts of our event handling require raw native events (see both the
   // windows and linux implementations of web_input_event in content/). Because
diff --git a/ui/events/event_utils.cc b/ui/events/event_utils.cc
index c775e10..2e3517e 100644
--- a/ui/events/event_utils.cc
+++ b/ui/events/event_utils.cc
@@ -63,9 +63,8 @@
   return event.Pass();
 }
 
-#if defined(OS_LINUX)
 // From third_party/WebKit/Source/web/gtk/WebInputEventFactory.cpp:
-uint16 GetControlCharacterForKeycode(int windows_key_code, bool shift) {
+base::char16 GetControlCharacterForKeycode(int windows_key_code, bool shift) {
   if (windows_key_code >= ui::VKEY_A &&
     windows_key_code <= ui::VKEY_Z) {
     // ctrl-A ~ ctrl-Z map to \x01 ~ \x1A
@@ -108,7 +107,6 @@
   }
   return 0;
 }
-#endif
 
 int RegisterCustomEventType() {
   return ++g_custom_event_types;
diff --git a/ui/events/event_utils.h b/ui/events/event_utils.h
index 312d580..f1f5f34d 100644
--- a/ui/events/event_utils.h
+++ b/ui/events/event_utils.h
@@ -5,8 +5,10 @@
 #ifndef UI_EVENTS_EVENT_UTILS_H_
 #define UI_EVENTS_EVENT_UTILS_H_
 
+#include "base/basictypes.h"
 #include "base/event_types.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/strings/string16.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/gfx/display.h"
@@ -87,26 +89,9 @@
 EVENTS_EXPORT uint32 PlatformKeycodeFromNative(
     const base::NativeEvent& native_event);
 
-// Returns the windows key code. Note that this value is different from
-// KeyboardCodeFromNative (there is a divergence between ui::KeyboardCode and
-// windows key codes).
-EVENTS_EXPORT uint32 WindowsKeycodeFromNative(
-    const base::NativeEvent& native_event);
-
-// Returns the text generated by this keystroke. Used in the value we pass to
-// blink.
-EVENTS_EXPORT uint16 TextFromNative(const base::NativeEvent& native_event);
-
-// Returns the unmodified text generated by this keystroke. Used in the value
-// we pass to blink.
-EVENTS_EXPORT uint16 UnmodifiedTextFromNative(
-    const base::NativeEvent& native_event);
-
-#if defined(OS_LINUX)
 // Returns a control character sequences from a |windows_key_code|.
-EVENTS_EXPORT uint16 GetControlCharacterForKeycode(int windows_key_code,
-                                                   bool shift);
-#endif
+EVENTS_EXPORT base::char16 GetControlCharacterForKeycode(int windows_key_code,
+                                                         bool shift);
 
 // Returns true if the keyboard event is a character event rather than
 // a keystroke event.
diff --git a/ui/events/ozone/events_ozone.cc b/ui/events/ozone/events_ozone.cc
index 57892532..65ad063 100644
--- a/ui/events/ozone/events_ozone.cc
+++ b/ui/events/ozone/events_ozone.cc
@@ -70,21 +70,6 @@
   return event->is_char();
 }
 
-uint32 WindowsKeycodeFromNative(const base::NativeEvent& native_event) {
-  NOTIMPLEMENTED();
-  return 0;
-}
-
-uint16 TextFromNative(const base::NativeEvent& native_event) {
-  NOTIMPLEMENTED();
-  return 0;
-}
-
-uint16 UnmodifiedTextFromNative(const base::NativeEvent& native_event) {
-  NOTIMPLEMENTED();
-  return 0;
-}
-
 gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
   const ui::MouseWheelEvent* event =
       static_cast<const ui::MouseWheelEvent*>(native_event);
diff --git a/ui/events/win/events_win.cc b/ui/events/win/events_win.cc
index a1c512e9..6365c76 100644
--- a/ui/events/win/events_win.cc
+++ b/ui/events/win/events_win.cc
@@ -264,18 +264,6 @@
   return native_event.message == WM_CHAR;
 }
 
-uint32 WindowsKeycodeFromNative(const base::NativeEvent& native_event) {
-  return static_cast<uint32>(native_event.wParam);
-}
-
-uint16 TextFromNative(const base::NativeEvent& native_event) {
-  return static_cast<uint32>(native_event.wParam);
-}
-
-uint16 UnmodifiedTextFromNative(const base::NativeEvent& native_event) {
-  return static_cast<uint32>(native_event.wParam);
-}
-
 int GetChangedMouseButtonFlagsFromNative(
     const base::NativeEvent& native_event) {
   switch (GetNativeMouseKey(native_event)) {
diff --git a/ui/events/x/events_x.cc b/ui/events/x/events_x.cc
index b3fc9bb0..371c8f58 100644
--- a/ui/events/x/events_x.cc
+++ b/ui/events/x/events_x.cc
@@ -685,54 +685,6 @@
   return false;
 }
 
-uint32 WindowsKeycodeFromNative(const base::NativeEvent& native_event) {
-  int windows_key_code = ui::KeyboardCodeFromXKeyEvent(native_event);
-  if (windows_key_code == ui::VKEY_SHIFT ||
-      windows_key_code == ui::VKEY_CONTROL ||
-      windows_key_code == ui::VKEY_MENU) {
-    // To support DOM3 'location' attribute, we need to lookup an X KeySym and
-    // set ui::VKEY_[LR]XXX instead of ui::VKEY_XXX.
-    KeySym keysym = XK_VoidSymbol;
-    XLookupString(&native_event->xkey, NULL, 0, &keysym, NULL);
-    switch (keysym) {
-      case XK_Shift_L:
-        return ui::VKEY_LSHIFT;
-      case XK_Shift_R:
-        return ui::VKEY_RSHIFT;
-      case XK_Control_L:
-        return ui::VKEY_LCONTROL;
-      case XK_Control_R:
-        return ui::VKEY_RCONTROL;
-      case XK_Meta_L:
-      case XK_Alt_L:
-        return ui::VKEY_LMENU;
-      case XK_Meta_R:
-      case XK_Alt_R:
-        return ui::VKEY_RMENU;
-    }
-  }
-  return windows_key_code;
-}
-
-uint16 TextFromNative(const base::NativeEvent& native_event) {
-  int flags = EventFlagsFromNative(native_event);
-  if ((flags & ui::EF_CONTROL_DOWN) != 0) {
-    int windows_key_code = WindowsKeycodeFromNative(native_event);
-    return ui::GetControlCharacterForKeycode(windows_key_code,
-                                             flags & ui::EF_SHIFT_DOWN);
-  }
-
-  return UnmodifiedTextFromNative(native_event);
-}
-
-uint16 UnmodifiedTextFromNative(const base::NativeEvent& native_event) {
-  uint32 keycode = WindowsKeycodeFromNative(native_event);
-  if (keycode == ui::VKEY_RETURN)
-    return '\r';
-  else
-    return ui::GetCharacterFromXEvent(native_event);
-}
-
 int GetChangedMouseButtonFlagsFromNative(
     const base::NativeEvent& native_event) {
   switch (native_event->type) {