Split the event library into a cross-platform and native part. Part 1.

This removes construction of ui::Event and subclasses from
base::NativeEvents. It removes all usage of NativeEvents from that
file. It moves the code from there to the ui/events/platform/ directory,
which will eventually be its own library. The previous constructors have
been refactored into ui/events/platform/platform_event_builder.h. Tests
that relied on events were moved or rewritten.

Also adds events_unittests to the build.

BUG=443439
R=sky@chromium.org

Review URL: https://codereview.chromium.org/862093002
diff --git a/BUILD.gn b/BUILD.gn
index 0982382..3044654 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -13,6 +13,7 @@
     "//shell",
     "//sky",
     "//ui/gfx:gfx_unittests",
+    "//ui/events:events_unittests",
   ]
 
   if (!is_android && !is_win) {
diff --git a/mojo/converters/input_events/input_events_type_converters.cc b/mojo/converters/input_events/input_events_type_converters.cc
index 78ea0c2..c52f9ae 100644
--- a/mojo/converters/input_events/input_events_type_converters.cc
+++ b/mojo/converters/input_events/input_events_type_converters.cc
@@ -12,7 +12,6 @@
 #include "mojo/converters/geometry/geometry_type_converters.h"
 #include "mojo/converters/input_events/mojo_extended_key_event_data.h"
 #include "mojo/services/input_events/public/interfaces/input_events.mojom.h"
-#include "ui/events/event_utils.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 
 namespace mojo {
@@ -102,10 +101,8 @@
 
     LocationDataPtr location_data(LocationData::New());
     location_data->in_view_location = Point::From(located_event->location());
-    if (input.HasNativeEvent()) {
-      location_data->screen_location =
-          Point::From(ui::EventSystemLocationFromNative(input.native_event()));
-    }
+    location_data->screen_location =
+        Point::From(located_event->screen_location());
 
     event->location_data = location_data.Pass();
   }
diff --git a/mojo/tools/data/unittests b/mojo/tools/data/unittests
index 225a606..fe62c3f 100644
--- a/mojo/tools/data/unittests
+++ b/mojo/tools/data/unittests
@@ -52,6 +52,9 @@
   {
     "test": "gfx_unittests",
   },
+  {
+    "test": "events_unittests",
+  },
 
   # JavaScript tests:
   {
diff --git a/ui/events/BUILD.gn b/ui/events/BUILD.gn
index 139bd8a..5ba2e19 100644
--- a/ui/events/BUILD.gn
+++ b/ui/events/BUILD.gn
@@ -59,7 +59,6 @@
 
   public_deps = [
     "//base",
-    "//ui/events/platform",
     "//ui/gfx",
     "//ui/gfx/geometry",
   ]
@@ -267,6 +266,7 @@
     "keycodes/dom4/keycode_converter_unittest.cc",
     "latency_info_unittest.cc",
     "platform/platform_event_source_unittest.cc",
+    "platform/platform_event_builder_x_unittest.cc",
     "x/events_x_unittest.cc",
   ]
 
@@ -288,6 +288,9 @@
     configs += [ "//build/config/linux:x11" ]
     deps += [ "//ui/gfx/x" ]
   } else {
-    sources -= [ "x/events_x_unittest.cc" ]
+    sources -= [
+      "platform/platform_event_builder_x_unittest.cc",
+      "x/events_x_unittest.cc",
+    ]
   }
 }
diff --git a/ui/events/cocoa/events_mac.mm b/ui/events/cocoa/events_mac.mm
index 4772b27..373d47f 100644
--- a/ui/events/cocoa/events_mac.mm
+++ b/ui/events/cocoa/events_mac.mm
@@ -152,14 +152,6 @@
   }
 }
 
-base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
-  return [event copy];
-}
-
-void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
-  [event release];
-}
-
 void IncrementTouchIdRefCount(const base::NativeEvent& native_event) {
   NOTIMPLEMENTED();
 }
diff --git a/ui/events/event.cc b/ui/events/event.cc
index fa6dbac..16784a4 100644
--- a/ui/events/event.cc
+++ b/ui/events/event.cc
@@ -13,7 +13,6 @@
 #include <cmath>
 #include <cstring>
 
-#include "base/metrics/histogram.h"
 #include "base/strings/stringprintf.h"
 #include "ui/events/event_utils.h"
 #include "ui/events/keycodes/keyboard_code_conversion.h"
@@ -25,89 +24,8 @@
 
 #if defined(USE_X11)
 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
-#elif defined(USE_OZONE)
-#include "ui/events/keycodes/keyboard_code_conversion.h"
 #endif
 
-namespace {
-
-std::string EventTypeName(ui::EventType type) {
-#define RETURN_IF_TYPE(t) if (type == ui::t)  return #t
-#define CASE_TYPE(t) case ui::t:  return #t
-  switch (type) {
-    CASE_TYPE(ET_UNKNOWN);
-    CASE_TYPE(ET_MOUSE_PRESSED);
-    CASE_TYPE(ET_MOUSE_DRAGGED);
-    CASE_TYPE(ET_MOUSE_RELEASED);
-    CASE_TYPE(ET_MOUSE_MOVED);
-    CASE_TYPE(ET_MOUSE_ENTERED);
-    CASE_TYPE(ET_MOUSE_EXITED);
-    CASE_TYPE(ET_KEY_PRESSED);
-    CASE_TYPE(ET_KEY_RELEASED);
-    CASE_TYPE(ET_MOUSEWHEEL);
-    CASE_TYPE(ET_MOUSE_CAPTURE_CHANGED);
-    CASE_TYPE(ET_TOUCH_RELEASED);
-    CASE_TYPE(ET_TOUCH_PRESSED);
-    CASE_TYPE(ET_TOUCH_MOVED);
-    CASE_TYPE(ET_TOUCH_CANCELLED);
-    CASE_TYPE(ET_DROP_TARGET_EVENT);
-    CASE_TYPE(ET_TRANSLATED_KEY_PRESS);
-    CASE_TYPE(ET_TRANSLATED_KEY_RELEASE);
-    CASE_TYPE(ET_GESTURE_SCROLL_BEGIN);
-    CASE_TYPE(ET_GESTURE_SCROLL_END);
-    CASE_TYPE(ET_GESTURE_SCROLL_UPDATE);
-    CASE_TYPE(ET_GESTURE_SHOW_PRESS);
-    CASE_TYPE(ET_GESTURE_WIN8_EDGE_SWIPE);
-    CASE_TYPE(ET_GESTURE_TAP);
-    CASE_TYPE(ET_GESTURE_TAP_DOWN);
-    CASE_TYPE(ET_GESTURE_TAP_CANCEL);
-    CASE_TYPE(ET_GESTURE_BEGIN);
-    CASE_TYPE(ET_GESTURE_END);
-    CASE_TYPE(ET_GESTURE_TWO_FINGER_TAP);
-    CASE_TYPE(ET_GESTURE_PINCH_BEGIN);
-    CASE_TYPE(ET_GESTURE_PINCH_END);
-    CASE_TYPE(ET_GESTURE_PINCH_UPDATE);
-    CASE_TYPE(ET_GESTURE_LONG_PRESS);
-    CASE_TYPE(ET_GESTURE_LONG_TAP);
-    CASE_TYPE(ET_GESTURE_SWIPE);
-    CASE_TYPE(ET_GESTURE_TAP_UNCONFIRMED);
-    CASE_TYPE(ET_GESTURE_DOUBLE_TAP);
-    CASE_TYPE(ET_SCROLL);
-    CASE_TYPE(ET_SCROLL_FLING_START);
-    CASE_TYPE(ET_SCROLL_FLING_CANCEL);
-    CASE_TYPE(ET_CANCEL_MODE);
-    CASE_TYPE(ET_UMA_DATA);
-    case ui::ET_LAST: NOTREACHED(); return std::string();
-    // Don't include default, so that we get an error when new type is added.
-  }
-#undef CASE_TYPE
-
-  NOTREACHED();
-  return std::string();
-}
-
-bool IsX11SendEventTrue(const base::NativeEvent& event) {
-#if defined(USE_X11)
-  return event && event->xany.send_event;
-#else
-  return false;
-#endif
-}
-
-bool X11EventHasNonStandardState(const base::NativeEvent& event) {
-#if defined(USE_X11)
-  const unsigned int kAllStateMask =
-      Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask |
-      Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask |
-      LockMask | ControlMask | AnyModifier;
-  return event && (event->xkey.state & ~kAllStateMask) != 0;
-#else
-  return false;
-#endif
-}
-
-}  // namespace
-
 namespace ui {
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -148,8 +66,6 @@
 }
 
 Event::~Event() {
-  if (delete_native_event_)
-    ReleaseCopiedNativeEvent(native_event_);
 }
 
 GestureEvent* Event::AsGestureEvent() {
@@ -162,12 +78,6 @@
   return static_cast<const GestureEvent*>(this);
 }
 
-bool Event::HasNativeEvent() const {
-  base::NativeEvent null_event;
-  std::memset(&null_event, 0, sizeof(null_event));
-  return !!std::memcmp(&native_event_, &null_event, sizeof(null_event));
-}
-
 void Event::StopPropagation() {
   // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
   // events.
@@ -184,59 +94,26 @@
   result_ = static_cast<EventResult>(result_ | ER_HANDLED);
 }
 
+Event::Event()
+    : type_(ET_UNKNOWN),
+      time_stamp_(base::TimeDelta()),
+      flags_(EF_NONE),
+      cancelable_(true),
+      target_(NULL),
+      phase_(EP_PREDISPATCH),
+      result_(ER_UNHANDLED),
+      source_device_id_(ED_UNKNOWN_DEVICE) {
+}
+
 Event::Event(EventType type, base::TimeDelta time_stamp, int flags)
     : type_(type),
       time_stamp_(time_stamp),
       flags_(flags),
-      native_event_(base::NativeEvent()),
-      delete_native_event_(false),
       cancelable_(true),
       target_(NULL),
       phase_(EP_PREDISPATCH),
       result_(ER_UNHANDLED),
       source_device_id_(ED_UNKNOWN_DEVICE) {
-  if (type_ < ET_LAST)
-    name_ = EventTypeName(type_);
-}
-
-Event::Event(const base::NativeEvent& native_event,
-             EventType type,
-             int flags)
-    : type_(type),
-      time_stamp_(EventTimeFromNative(native_event)),
-      flags_(flags),
-      native_event_(native_event),
-      delete_native_event_(false),
-      cancelable_(true),
-      target_(NULL),
-      phase_(EP_PREDISPATCH),
-      result_(ER_UNHANDLED),
-      source_device_id_(ED_UNKNOWN_DEVICE) {
-  base::TimeDelta delta = EventTimeForNow() - time_stamp_;
-  if (type_ < ET_LAST)
-    name_ = EventTypeName(type_);
-  base::HistogramBase::Sample delta_sample =
-      static_cast<base::HistogramBase::Sample>(delta.InMicroseconds());
-  UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser", delta_sample, 1, 1000000,
-                              100);
-  std::string name_for_event =
-      base::StringPrintf("Event.Latency.Browser.%s", name_.c_str());
-  base::HistogramBase* counter_for_type =
-      base::Histogram::FactoryGet(
-          name_for_event,
-          1,
-          1000000,
-          100,
-          base::HistogramBase::kUmaTargetedHistogramFlag);
-  counter_for_type->Add(delta_sample);
-
-#if defined(USE_X11)
-  if (native_event->type == GenericEvent) {
-    XIDeviceEvent* xiev =
-        static_cast<XIDeviceEvent*>(native_event->xcookie.data);
-    source_device_id_ = xiev->sourceid;
-  }
-#endif
 }
 
 Event::Event(const Event& copy)
@@ -244,23 +121,15 @@
       time_stamp_(copy.time_stamp_),
       latency_(copy.latency_),
       flags_(copy.flags_),
-      native_event_(CopyNativeEvent(copy.native_event_)),
-      delete_native_event_(true),
       cancelable_(true),
       target_(NULL),
       phase_(EP_PREDISPATCH),
       result_(ER_UNHANDLED),
       source_device_id_(copy.source_device_id_) {
-  if (type_ < ET_LAST)
-    name_ = EventTypeName(type_);
 }
 
 void Event::SetType(EventType type) {
-  if (type_ < ET_LAST)
-    name_ = std::string();
   type_ = type;
-  if (type_ < ET_LAST)
-    name_ = EventTypeName(type_);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -277,15 +146,10 @@
 ////////////////////////////////////////////////////////////////////////////////
 // LocatedEvent
 
-LocatedEvent::~LocatedEvent() {
+LocatedEvent::LocatedEvent() : Event() {
 }
 
-LocatedEvent::LocatedEvent(const base::NativeEvent& native_event)
-    : Event(native_event,
-            EventTypeFromNative(native_event),
-            EventFlagsFromNative(native_event)),
-      location_(EventLocationFromNative(native_event)),
-      root_location_(location_) {
+LocatedEvent::~LocatedEvent() {
 }
 
 LocatedEvent::LocatedEvent(EventType type,
@@ -310,12 +174,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // MouseEvent
 
-MouseEvent::MouseEvent(const base::NativeEvent& native_event)
-    : LocatedEvent(native_event),
-      changed_button_flags_(
-          GetChangedMouseButtonFlagsFromNative(native_event)) {
-  if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED)
-    SetClickCount(GetRepeatCount(*this));
+MouseEvent::MouseEvent() : LocatedEvent(), changed_button_flags_(0) {
 }
 
 MouseEvent::MouseEvent(EventType type,
@@ -361,51 +220,6 @@
   return true;
 }
 
-// static
-int MouseEvent::GetRepeatCount(const MouseEvent& event) {
-  int click_count = 1;
-  if (last_click_event_) {
-    if (event.type() == ui::ET_MOUSE_RELEASED) {
-      if (event.changed_button_flags() ==
-              last_click_event_->changed_button_flags()) {
-        last_click_complete_ = true;
-        return last_click_event_->GetClickCount();
-      } else {
-        // If last_click_event_ has changed since this button was pressed
-        // return a click count of 1.
-        return click_count;
-      }
-    }
-    if (event.time_stamp() != last_click_event_->time_stamp())
-      last_click_complete_ = true;
-    if (!last_click_complete_ ||
-        IsX11SendEventTrue(event.native_event())) {
-      click_count = last_click_event_->GetClickCount();
-    } else if (IsRepeatedClickEvent(*last_click_event_, event)) {
-      click_count = last_click_event_->GetClickCount() + 1;
-    }
-    delete last_click_event_;
-  }
-  last_click_event_ = new MouseEvent(event);
-  last_click_complete_ = false;
-  if (click_count > 3)
-    click_count = 3;
-  last_click_event_->SetClickCount(click_count);
-  return click_count;
-}
-
-void MouseEvent::ResetLastClickForTest() {
-  if (last_click_event_) {
-    delete last_click_event_;
-    last_click_event_ = NULL;
-    last_click_complete_ = false;
-  }
-}
-
-// static
-MouseEvent* MouseEvent::last_click_event_ = NULL;
-bool MouseEvent::last_click_complete_ = false;
-
 int MouseEvent::GetClickCount() const {
   if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
     return 0;
@@ -446,9 +260,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // MouseWheelEvent
 
-MouseWheelEvent::MouseWheelEvent(const base::NativeEvent& native_event)
-    : MouseEvent(native_event),
-      offset_(GetMouseWheelOffset(native_event)) {
+MouseWheelEvent::MouseWheelEvent() : MouseEvent(), offset_() {
 }
 
 MouseWheelEvent::MouseWheelEvent(const ScrollEvent& scroll_event)
@@ -509,24 +321,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 // TouchEvent
 
-TouchEvent::TouchEvent(const base::NativeEvent& native_event)
-    : LocatedEvent(native_event),
-      touch_id_(GetTouchId(native_event)),
-      radius_x_(GetTouchRadiusX(native_event)),
-      radius_y_(GetTouchRadiusY(native_event)),
-      rotation_angle_(GetTouchAngle(native_event)),
-      force_(GetTouchForce(native_event)) {
-  latency()->AddLatencyNumberWithTimestamp(
-      INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
-      0,
-      0,
-      base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()),
-      1);
-
-  latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
-
-  if (type() == ET_TOUCH_PRESSED)
-    IncrementTouchIdRefCount(native_event);
+TouchEvent::TouchEvent()
+    : LocatedEvent(),
+      touch_id_(0),
+      radius_x_(0),
+      radius_y_(0),
+      rotation_angle_(0),
+      force_(0) {
 }
 
 TouchEvent::TouchEvent(EventType type,
@@ -561,11 +362,6 @@
 }
 
 TouchEvent::~TouchEvent() {
-  // In ctor TouchEvent(native_event) we call GetTouchId() which in X11
-  // platform setups the tracking_id to slot mapping. So in dtor here,
-  // if this touch event is a release event, we clear the mapping accordingly.
-  if (HasNativeEvent())
-    ClearTouchIdIfReleased(native_event());
 }
 
 void TouchEvent::UpdateForRootTransform(
@@ -583,62 +379,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 // KeyEvent
 
-// static
-KeyEvent* KeyEvent::last_key_event_ = NULL;
-
-// static
-bool KeyEvent::IsRepeated(const KeyEvent& event) {
-  // A safe guard in case if there were continous key pressed events that are
-  // not auto repeat.
-  const int kMaxAutoRepeatTimeMs = 2000;
-  // Ignore key events that have non standard state masks as it may be
-  // reposted by an IME. IBUS-GTK uses this field to detect the
-  // re-posted event for example. crbug.com/385873.
-  if (X11EventHasNonStandardState(event.native_event()))
-    return false;
-  if (event.is_char())
-    return false;
-  if (event.type() == ui::ET_KEY_RELEASED) {
-    delete last_key_event_;
-    last_key_event_ = NULL;
-    return false;
-  }
-  CHECK_EQ(ui::ET_KEY_PRESSED, event.type());
-  if (!last_key_event_) {
-    last_key_event_ = new KeyEvent(event);
-    return false;
-  }
-  if (event.key_code() == last_key_event_->key_code() &&
-      event.flags() == last_key_event_->flags() &&
-      (event.time_stamp() - last_key_event_->time_stamp()).InMilliseconds() <
-      kMaxAutoRepeatTimeMs) {
-    return true;
-  }
-  delete last_key_event_;
-  last_key_event_ = new KeyEvent(event);
-  return false;
-}
-
-KeyEvent::KeyEvent(const base::NativeEvent& native_event)
-    : Event(native_event,
-            EventTypeFromNative(native_event),
-            EventFlagsFromNative(native_event)),
-      key_code_(KeyboardCodeFromNative(native_event)),
-      code_(CodeFromNative(native_event)),
-      is_char_(IsCharFromNative(native_event)),
-      platform_keycode_(PlatformKeycodeFromNative(native_event)),
+KeyEvent::KeyEvent()
+    : Event(),
+      key_code_(VKEY_UNKNOWN),
+      code_(),
+      is_char_(false),
+      platform_keycode_(0),
       character_(0) {
-  if (IsRepeated(*this))
-    set_flags(flags() | ui::EF_IS_REPEAT);
-
-#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,
@@ -716,30 +463,9 @@
   character_ = GetCharacterFromKeyCode(key_code_, flags());
   return character_;
 #elif defined(USE_X11)
-  if (!native_event()) {
-    character_ = GetCharacterFromKeyCode(key_code_, flags());
-    return character_;
-  }
-
-  DCHECK(native_event()->type == KeyPress ||
-         native_event()->type == KeyRelease ||
-         (native_event()->type == GenericEvent &&
-          (native_event()->xgeneric.evtype == XI_KeyPress ||
-           native_event()->xgeneric.evtype == XI_KeyRelease)));
-
-  // When a control key is held, prefer ASCII characters to non ASCII
-  // characters in order to use it for shortcut keys.  GetCharacterFromKeyCode
-  // returns 'a' for VKEY_A even if the key is actually bound to 'à' in X11.
-  // GetCharacterFromXEvent returns 'à' in that case.
-  return IsControlDown() ?
-      GetCharacterFromKeyCode(key_code_, flags()) :
-      GetCharacterFromXEvent(native_event());
+  character_ = GetCharacterFromKeyCode(key_code_, flags());
+  return character_;
 #else
-  if (native_event()) {
-    DCHECK(EventTypeFromNative(native_event()) == ET_KEY_PRESSED ||
-           EventTypeFromNative(native_event()) == ET_KEY_RELEASED);
-  }
-
   return GetCharacterFromKeyCode(key_code_, flags());
 #endif
 }
@@ -911,23 +637,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ScrollEvent
 
-ScrollEvent::ScrollEvent(const base::NativeEvent& native_event)
-    : MouseEvent(native_event) {
-  if (type() == ET_SCROLL) {
-    GetScrollOffsets(native_event,
-                     &x_offset_, &y_offset_,
-                     &x_offset_ordinal_, &y_offset_ordinal_,
-                     &finger_count_);
-  } else if (type() == ET_SCROLL_FLING_START ||
-             type() == ET_SCROLL_FLING_CANCEL) {
-    GetFlingData(native_event,
-                 &x_offset_, &y_offset_,
-                 &x_offset_ordinal_, &y_offset_ordinal_,
-                 NULL);
-  } else {
-    NOTREACHED() << "Unexpected event type " << type()
-        << " when constructing a ScrollEvent.";
-  }
+ScrollEvent::ScrollEvent() : MouseEvent() {
 }
 
 ScrollEvent::ScrollEvent(EventType type,
diff --git a/ui/events/event.h b/ui/events/event.h
index d774897..334dc7e 100644
--- a/ui/events/event.h
+++ b/ui/events/event.h
@@ -53,15 +53,14 @@
     DISALLOW_COPY_AND_ASSIGN(DispatcherApi);
   };
 
-  const base::NativeEvent& native_event() const { return native_event_; }
   EventType type() const { return type_; }
-  const std::string& name() const { return name_; }
+  void set_type(EventType type) { type_ = type; }
+
   // time_stamp represents time since machine was booted.
   const base::TimeDelta& time_stamp() const { return time_stamp_; }
-  int flags() const { return flags_; }
+  void set_time_stamp(const base::TimeDelta& stamp) { time_stamp_ = stamp; }
 
-  // This is only intended to be used externally by classes that are modifying
-  // events in an EventRewriter.
+  int flags() const { return flags_; }
   void set_flags(int flags) { flags_ = flags; }
 
   EventTarget* target() const { return target_; }
@@ -73,6 +72,7 @@
   void set_latency(const LatencyInfo& latency) { latency_ = latency; }
 
   int source_device_id() const { return source_device_id_; }
+  void set_source_device_id(const int id) { source_device_id_ = id; }
 
   // By default, events are "cancelable", this means any default processing that
   // the containing abstraction layer may perform can be prevented by calling
@@ -199,9 +199,6 @@
   GestureEvent* AsGestureEvent();
   const GestureEvent* AsGestureEvent() const;
 
-  // Returns true if the event has a valid |native_event_|.
-  bool HasNativeEvent() const;
-
   // Immediately stops the propagation of the event. This must be called only
   // from an EventHandler during an event-dispatch. Any event handler that may
   // be in the list will not receive the event after this is called.
@@ -218,31 +215,19 @@
   bool handled() const { return result_ != ER_UNHANDLED; }
 
  protected:
+  Event();
   Event(EventType type, base::TimeDelta time_stamp, int flags);
-  Event(const base::NativeEvent& native_event, EventType type, int flags);
   Event(const Event& copy);
   void SetType(EventType type);
-  void set_delete_native_event(bool delete_native_event) {
-    delete_native_event_ = delete_native_event;
-  }
   void set_cancelable(bool cancelable) { cancelable_ = cancelable; }
 
-  void set_time_stamp(const base::TimeDelta& time_stamp) {
-    time_stamp_ = time_stamp;
-  }
-
-  void set_name(const std::string& name) { name_ = name; }
-
  private:
   friend class EventTestApi;
 
   EventType type_;
-  std::string name_;
   base::TimeDelta time_stamp_;
   LatencyInfo latency_;
   int flags_;
-  base::NativeEvent native_event_;
-  bool delete_native_event_;
   bool cancelable_;
   EventTarget* target_;
   EventPhase phase_;
@@ -261,6 +246,7 @@
 
 class EVENTS_EXPORT LocatedEvent : public Event {
  public:
+  LocatedEvent();
   ~LocatedEvent() override;
 
   float x() const { return location_.x(); }
@@ -279,6 +265,10 @@
   const gfx::PointF& root_location_f() const {
     return root_location_;
   }
+  const gfx::Point& screen_location() const { return screen_location_; }
+  void set_screen_location(const gfx::Point& screen_location) {
+    screen_location_ = screen_location;
+  }
 
   // Transform the locations using |inverted_root_transform|.
   // This is applied to both |location_| and |root_location_|.
@@ -298,7 +288,6 @@
 
  protected:
   friend class LocatedEventTestApi;
-  explicit LocatedEvent(const base::NativeEvent& native_event);
 
   // Create a new LocatedEvent which is identical to the provided model.
   // If source / target windows are provided, the model location will be
@@ -307,7 +296,8 @@
   LocatedEvent(const LocatedEvent& model, T* source, T* target)
       : Event(model),
         location_(model.location_),
-        root_location_(model.root_location_) {
+        root_location_(model.root_location_),
+        screen_location_(model.screen_location_) {
     ConvertLocationToTarget(source, target);
   }
 
@@ -323,11 +313,14 @@
   // |location_| multiplied by an optional transformation matrix for
   // rotations, animations and skews.
   gfx::PointF root_location_;
+
+  // The system provided location of the event.
+  gfx::Point screen_location_;
 };
 
 class EVENTS_EXPORT MouseEvent : public LocatedEvent {
  public:
-  explicit MouseEvent(const base::NativeEvent& native_event);
+  MouseEvent();
 
   // Create a new MouseEvent based on the provided model.
   // Uses the provided |type| and |flags| for the new event.
@@ -413,26 +406,16 @@
   // Updates the button that changed.
   void set_changed_button_flags(int flags) { changed_button_flags_ = flags; }
 
- private:
-  FRIEND_TEST_ALL_PREFIXES(EventTest, DoubleClickRequiresRelease);
-  FRIEND_TEST_ALL_PREFIXES(EventTest, SingleClickRightLeft);
-
   // Returns the repeat count based on the previous mouse click, if it is
   // recent enough and within a small enough distance.
   static int GetRepeatCount(const MouseEvent& click_event);
 
-  // Resets the last_click_event_ for unit tests.
-  static void ResetLastClickForTest();
+ private:
+  FRIEND_TEST_ALL_PREFIXES(EventTest, DoubleClickRequiresRelease);
+  FRIEND_TEST_ALL_PREFIXES(EventTest, SingleClickRightLeft);
 
   // See description above getter for details.
   int changed_button_flags_;
-
-  static MouseEvent* last_click_event_;
-
-  // We can create a MouseEvent for a native event more than once. We set this
-  // to true when the next event either has a different timestamp or we see a
-  // release signalling that the press (click) event was completed.
-  static bool last_click_complete_;
 };
 
 class ScrollEvent;
@@ -442,7 +425,7 @@
   // See |offset| for details.
   static const int kWheelDelta;
 
-  explicit MouseWheelEvent(const base::NativeEvent& native_event);
+  MouseWheelEvent();
   explicit MouseWheelEvent(const ScrollEvent& scroll_event);
   MouseWheelEvent(const MouseEvent& mouse_event, int x_offset, int y_offset);
   MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event);
@@ -467,6 +450,7 @@
   int x_offset() const { return offset_.x(); }
   int y_offset() const { return offset_.y(); }
   const gfx::Vector2d& offset() const { return offset_; }
+  void set_offset(const gfx::Vector2d& offset) { offset_ = offset; }
 
   // Overridden from LocatedEvent.
   void UpdateForRootTransform(
@@ -478,7 +462,7 @@
 
 class EVENTS_EXPORT TouchEvent : public LocatedEvent {
  public:
-  explicit TouchEvent(const base::NativeEvent& native_event);
+  TouchEvent();
 
   // Create a new TouchEvent which is identical to the provided model.
   // If source / target windows are provided, the model location will be
@@ -511,15 +495,21 @@
   ~TouchEvent() override;
 
   int touch_id() const { return touch_id_; }
-  float radius_x() const { return radius_x_; }
-  float radius_y() const { return radius_y_; }
-  float rotation_angle() const { return rotation_angle_; }
-  float force() const { return force_; }
+  void set_touch_id(int touch_id) { touch_id_ = touch_id; }
 
-  // Used for unit tests.
+  float radius_x() const { return radius_x_; }
   void set_radius_x(const float r) { radius_x_ = r; }
+  float radius_y() const { return radius_y_; }
   void set_radius_y(const float r) { radius_y_ = r; }
 
+  float rotation_angle() const { return rotation_angle_; }
+  void set_rotation_angle(float rotation_angle) {
+    rotation_angle_ = rotation_angle;
+  }
+
+  float force() const { return force_; }
+  void set_force(float force) { force_ = force; }
+
   // Overridden from LocatedEvent.
   void UpdateForRootTransform(
       const gfx::Transform& inverted_root_transform) override;
@@ -530,16 +520,10 @@
     radius_y_ = radius_y;
   }
 
-  void set_rotation_angle(float rotation_angle) {
-    rotation_angle_ = rotation_angle;
-  }
-
-  void set_force(float force) { force_ = force; }
-
  private:
   // The identity (typically finger) of the touch starting at 0 and incrementing
   // for each separable additional touch that the hardware can detect.
-  const int touch_id_;
+  int touch_id_;
 
   // Radius of the X (major) axis of the touch ellipse. 0.0 if unknown.
   float radius_x_;
@@ -593,10 +577,7 @@
 //
 class EVENTS_EXPORT KeyEvent : public Event {
  public:
-  // Create a KeyEvent from a NativeEvent. For Windows this native event can
-  // be either a keystroke message (WM_KEYUP/WM_KEYDOWN) or a character message
-  // (WM_CHAR). Other systems have only keystroke events.
-  explicit KeyEvent(const base::NativeEvent& native_event);
+  KeyEvent();
 
   // Create a keystroke event.
   KeyEvent(EventType type, KeyboardCode key_code, int flags);
@@ -648,8 +629,8 @@
   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_; }
+  void set_platform_keycode(uint32 keycode) { platform_keycode_ = keycode; }
 
   // Gets the associated (Windows-based) KeyboardCode for this key event.
   // Historically, this has also been used to obtain the character associated
@@ -657,13 +638,11 @@
   // This should be avoided; if necessary for backwards compatibility, use
   // GetConflatedWindowsKeyCode().
   KeyboardCode key_code() const { return key_code_; }
+  void set_key_code(KeyboardCode key_code) { key_code_ = key_code; }
 
   // True if this is a character event, false if this is a keystroke event.
   bool is_char() const { return is_char_; }
-
-  // This is only intended to be used externally by classes that are modifying
-  // events in an EventRewriter.
-  void set_key_code(KeyboardCode key_code) { key_code_ = key_code; }
+  void set_is_char(bool is_char) { is_char_ = is_char; }
 
   // 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
@@ -681,6 +660,7 @@
   bool IsUnicodeKeyCode() const;
 
   std::string code() const { return code_; }
+  void set_code(const std::string& code) { code_ = code; }
 
   // Normalizes flags_ so that it describes the state after the event.
   // (Native X11 event flags describe the state before the event.)
@@ -695,9 +675,6 @@
  protected:
   friend class KeyEventTestApi;
 
-  // This allows a subclass TranslatedKeyEvent to be a non character event.
-  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;
@@ -731,15 +708,11 @@
   // mojo instead serializes and deserializes events in potentially different
   // processes, we need to have a mechanism to keep track of this data.
   scoped_ptr<ExtendedKeyEventData> extended_key_event_data_;
-
-  static bool IsRepeated(const KeyEvent& event);
-
-  static KeyEvent* last_key_event_;
 };
 
 class EVENTS_EXPORT ScrollEvent : public MouseEvent {
  public:
-  explicit ScrollEvent(const base::NativeEvent& native_event);
+  ScrollEvent();
   template <class T>
   ScrollEvent(const ScrollEvent& model,
               T* source,
@@ -770,9 +743,20 @@
 
   float x_offset() const { return x_offset_; }
   float y_offset() const { return y_offset_; }
+  void set_offset(float x, float y) {
+    x_offset_ = x;
+    y_offset_ = y;
+  }
+
   float x_offset_ordinal() const { return x_offset_ordinal_; }
   float y_offset_ordinal() const { return y_offset_ordinal_; }
+  void set_offset_ordinal(float x, float y) {
+    x_offset_ordinal_ = x;
+    y_offset_ordinal_ = y;
+  }
+
   int finger_count() const { return finger_count_; }
+  void set_finger_count(int finger_count) { finger_count_ = finger_count; }
 
  private:
   // Potential accelerated offsets.
diff --git a/ui/events/event_unittest.cc b/ui/events/event_unittest.cc
index d2a6a69..6193036 100644
--- a/ui/events/event_unittest.cc
+++ b/ui/events/event_unittest.cc
@@ -17,24 +17,6 @@
 
 namespace ui {
 
-TEST(EventTest, NoNativeEvent) {
-  KeyEvent keyev(ET_KEY_PRESSED, VKEY_SPACE, EF_NONE);
-  EXPECT_FALSE(keyev.HasNativeEvent());
-}
-
-TEST(EventTest, NativeEvent) {
-#if defined(OS_WIN)
-  MSG native_event = { NULL, WM_KEYUP, VKEY_A, 0 };
-  KeyEvent keyev(native_event);
-  EXPECT_TRUE(keyev.HasNativeEvent());
-#elif defined(USE_X11)
-  ScopedXI2Event event;
-  event.InitKeyEvent(ET_KEY_RELEASED, VKEY_A, EF_NONE);
-  KeyEvent keyev(event);
-  EXPECT_TRUE(keyev.HasNativeEvent());
-#endif
-}
-
 TEST(EventTest, GetCharacter) {
   // Check if Control+Enter returns 10.
   KeyEvent keyev1(ET_KEY_PRESSED, VKEY_RETURN, EF_CONTROL_DOWN);
@@ -42,18 +24,6 @@
   // Check if Enter returns 13.
   KeyEvent keyev2(ET_KEY_PRESSED, VKEY_RETURN, EF_NONE);
   EXPECT_EQ(13, keyev2.GetCharacter());
-
-#if defined(USE_X11)
-  // For X11, test the functions with native_event() as well. crbug.com/107837
-  ScopedXI2Event event;
-  event.InitKeyEvent(ET_KEY_PRESSED, VKEY_RETURN, EF_CONTROL_DOWN);
-  KeyEvent keyev3(event);
-  EXPECT_EQ(10, keyev3.GetCharacter());
-
-  event.InitKeyEvent(ET_KEY_PRESSED, VKEY_RETURN, EF_NONE);
-  KeyEvent keyev4(event);
-  EXPECT_EQ(13, keyev4.GetCharacter());
-#endif
 }
 
 TEST(EventTest, ClickCount) {
@@ -98,68 +68,6 @@
   EXPECT_FALSE(MouseEvent::IsRepeatedClickEvent(mouse_ev1, mouse_ev2));
 }
 
-// Tests that an event only increases the click count and gets marked as a
-// double click if a release event was seen for the previous click. This
-// prevents the same PRESSED event from being processed twice:
-// http://crbug.com/389162
-TEST(EventTest, DoubleClickRequiresRelease) {
-  const gfx::Point origin1(0, 0);
-  const gfx::Point origin2(100, 0);
-  scoped_ptr<MouseEvent> ev;
-  base::TimeDelta start = base::TimeDelta::FromMilliseconds(0);
-
-  ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin1, origin1, 0, 0));
-  ev->set_time_stamp(start);
-  EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev));
-  ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin1, origin1, 0, 0));
-  ev->set_time_stamp(start);
-  EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev));
-
-  ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin2, origin2, 0, 0));
-  ev->set_time_stamp(start);
-  EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev));
-  ev.reset(new MouseEvent(ET_MOUSE_RELEASED, origin2, origin2, 0, 0));
-  ev->set_time_stamp(start);
-  EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev));
-  ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin2, origin2, 0, 0));
-  ev->set_time_stamp(start);
-  EXPECT_EQ(2, MouseEvent::GetRepeatCount(*ev));
-  ev.reset(new MouseEvent(ET_MOUSE_RELEASED, origin2, origin2, 0, 0));
-  ev->set_time_stamp(start);
-  EXPECT_EQ(2, MouseEvent::GetRepeatCount(*ev));
-  MouseEvent::ResetLastClickForTest();
-}
-
-// Tests that clicking right and then left clicking does not generate a double
-// click.
-TEST(EventTest, SingleClickRightLeft) {
-  const gfx::Point origin(0, 0);
-  scoped_ptr<MouseEvent> ev;
-  base::TimeDelta start = base::TimeDelta::FromMilliseconds(0);
-
-  ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin, origin,
-                          ui::EF_RIGHT_MOUSE_BUTTON,
-                          ui::EF_RIGHT_MOUSE_BUTTON));
-  ev->set_time_stamp(start);
-  EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev));
-  ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin, origin,
-                          ui::EF_LEFT_MOUSE_BUTTON,
-                          ui::EF_LEFT_MOUSE_BUTTON));
-  ev->set_time_stamp(start);
-  EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev));
-  ev.reset(new MouseEvent(ET_MOUSE_RELEASED, origin, origin,
-                          ui::EF_LEFT_MOUSE_BUTTON,
-                          ui::EF_LEFT_MOUSE_BUTTON));
-  ev->set_time_stamp(start);
-  EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev));
-  ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin, origin,
-                          ui::EF_LEFT_MOUSE_BUTTON,
-                          ui::EF_LEFT_MOUSE_BUTTON));
-  ev->set_time_stamp(start);
-  EXPECT_EQ(2, MouseEvent::GetRepeatCount(*ev));
-  MouseEvent::ResetLastClickForTest();
-}
-
 TEST(EventTest, KeyEvent) {
   static const struct {
     KeyboardCode key_code;
@@ -252,41 +160,6 @@
 }
 
 TEST(EventTest, NormalizeKeyEventFlags) {
-#if defined(USE_X11)
-  // Normalize flags when KeyEvent is created from XEvent.
-  ScopedXI2Event event;
-  {
-    event.InitKeyEvent(ET_KEY_PRESSED, VKEY_SHIFT, EF_SHIFT_DOWN);
-    KeyEvent keyev(event);
-    EXPECT_EQ(EF_SHIFT_DOWN, keyev.flags());
-  }
-  {
-    event.InitKeyEvent(ET_KEY_RELEASED, VKEY_SHIFT, EF_SHIFT_DOWN);
-    KeyEvent keyev(event);
-    EXPECT_EQ(EF_NONE, keyev.flags());
-  }
-  {
-    event.InitKeyEvent(ET_KEY_PRESSED, VKEY_CONTROL, EF_CONTROL_DOWN);
-    KeyEvent keyev(event);
-    EXPECT_EQ(EF_CONTROL_DOWN, keyev.flags());
-  }
-  {
-    event.InitKeyEvent(ET_KEY_RELEASED, VKEY_CONTROL, EF_CONTROL_DOWN);
-    KeyEvent keyev(event);
-    EXPECT_EQ(EF_NONE, keyev.flags());
-  }
-  {
-    event.InitKeyEvent(ET_KEY_PRESSED, VKEY_MENU,  EF_ALT_DOWN);
-    KeyEvent keyev(event);
-    EXPECT_EQ(EF_ALT_DOWN, keyev.flags());
-  }
-  {
-    event.InitKeyEvent(ET_KEY_RELEASED, VKEY_MENU, EF_ALT_DOWN);
-    KeyEvent keyev(event);
-    EXPECT_EQ(EF_NONE, keyev.flags());
-  }
-#endif
-
   // Do not normalize flags for synthesized events without
   // KeyEvent::NormalizeFlags called explicitly.
   {
@@ -351,15 +224,6 @@
     KeyEvent key(ET_KEY_PRESSED, VKEY_SPACE, EF_NONE);
     EXPECT_TRUE(key.code().empty());
   }
-#if defined(USE_X11)
-  {
-    // KeyEvent converts from the native keycode (XKB) to the code.
-    ScopedXI2Event xevent;
-    xevent.InitKeyEvent(ET_KEY_PRESSED, VKEY_SPACE, kNativeCodeSpace);
-    KeyEvent key(xevent);
-    EXPECT_EQ(kCodeForSpace, key.code());
-  }
-#endif  // USE_X11
 #if defined(OS_WIN)
   {
     // Test a non extended key.
@@ -389,64 +253,4 @@
 #endif  // OS_WIN
 }
 
-#if defined(USE_X11) || defined(OS_WIN)
-TEST(EventTest, AutoRepeat) {
-  const uint16 kNativeCodeA = ui::KeycodeConverter::CodeToNativeKeycode("KeyA");
-  const uint16 kNativeCodeB = ui::KeycodeConverter::CodeToNativeKeycode("KeyB");
-#if defined(USE_X11)
-  ScopedXI2Event native_event_a_pressed;
-  native_event_a_pressed.InitKeyEvent(ET_KEY_PRESSED, VKEY_A, kNativeCodeA);
-  ScopedXI2Event native_event_a_released;
-  native_event_a_released.InitKeyEvent(ET_KEY_RELEASED, VKEY_A, kNativeCodeA);
-  ScopedXI2Event native_event_b_pressed;
-  native_event_b_pressed.InitKeyEvent(ET_KEY_PRESSED, VKEY_B, kNativeCodeB);
-  ScopedXI2Event native_event_a_pressed_nonstandard_state;
-  native_event_a_pressed_nonstandard_state.InitKeyEvent(
-      ET_KEY_PRESSED, VKEY_A, kNativeCodeA);
-  // IBUS-GTK uses the mask (1 << 25) to detect reposted event.
-  static_cast<XEvent*>(native_event_a_pressed_nonstandard_state)->xkey.state |=
-      1 << 25;
-#elif defined(OS_WIN)
-  const LPARAM lParam_a = GetLParamFromScanCode(kNativeCodeA);
-  const LPARAM lParam_b = GetLParamFromScanCode(kNativeCodeB);
-  MSG native_event_a_pressed = { NULL, WM_KEYDOWN, VKEY_A, lParam_a };
-  MSG native_event_a_released = { NULL, WM_KEYUP, VKEY_A, lParam_a };
-  MSG native_event_b_pressed = { NULL, WM_KEYUP, VKEY_B, lParam_b };
-#endif
-  KeyEvent key_a1(native_event_a_pressed);
-  EXPECT_FALSE(key_a1.IsRepeat());
-  KeyEvent key_a1_released(native_event_a_released);
-  EXPECT_FALSE(key_a1_released.IsRepeat());
-
-  KeyEvent key_a2(native_event_a_pressed);
-  EXPECT_FALSE(key_a2.IsRepeat());
-  KeyEvent key_a2_repeated(native_event_a_pressed);
-  EXPECT_TRUE(key_a2_repeated.IsRepeat());
-  KeyEvent key_a2_released(native_event_a_released);
-  EXPECT_FALSE(key_a2_released.IsRepeat());
-
-  KeyEvent key_a3(native_event_a_pressed);
-  EXPECT_FALSE(key_a3.IsRepeat());
-  KeyEvent key_b(native_event_b_pressed);
-  EXPECT_FALSE(key_b.IsRepeat());
-  KeyEvent key_a3_again(native_event_a_pressed);
-  EXPECT_FALSE(key_a3_again.IsRepeat());
-  KeyEvent key_a3_repeated(native_event_a_pressed);
-  EXPECT_TRUE(key_a3_repeated.IsRepeat());
-  KeyEvent key_a3_repeated2(native_event_a_pressed);
-  EXPECT_TRUE(key_a3_repeated2.IsRepeat());
-  KeyEvent key_a3_released(native_event_a_released);
-  EXPECT_FALSE(key_a3_released.IsRepeat());
-
-#if defined(USE_X11)
-  KeyEvent key_a4_pressed(native_event_a_pressed);
-  EXPECT_FALSE(key_a4_pressed.IsRepeat());
-
-  KeyEvent key_a4_pressed_nonstandard_state(
-      native_event_a_pressed_nonstandard_state);
-  EXPECT_FALSE(key_a4_pressed_nonstandard_state.IsRepeat());
-#endif
-}
-#endif  // USE_X11 || OS_WIN
-
 }  // namespace ui
diff --git a/ui/events/event_utils.cc b/ui/events/event_utils.cc
index 084a84d..db6215f 100644
--- a/ui/events/event_utils.cc
+++ b/ui/events/event_utils.cc
@@ -11,57 +11,6 @@
 
 namespace ui {
 
-namespace {
-int g_custom_event_types = ET_LAST;
-}  // namespace
-
-scoped_ptr<Event> EventFromNative(const base::NativeEvent& native_event) {
-  scoped_ptr<Event> event;
-  EventType type = EventTypeFromNative(native_event);
-  switch(type) {
-    case ET_KEY_PRESSED:
-    case ET_KEY_RELEASED:
-      event.reset(new KeyEvent(native_event));
-      break;
-
-    case ET_TRANSLATED_KEY_PRESS:
-    case ET_TRANSLATED_KEY_RELEASE:
-      // These should not be generated by native events.
-      NOTREACHED();
-      break;
-
-    case ET_MOUSE_PRESSED:
-    case ET_MOUSE_DRAGGED:
-    case ET_MOUSE_RELEASED:
-    case ET_MOUSE_MOVED:
-    case ET_MOUSE_ENTERED:
-    case ET_MOUSE_EXITED:
-      event.reset(new MouseEvent(native_event));
-      break;
-
-    case ET_MOUSEWHEEL:
-      event.reset(new MouseWheelEvent(native_event));
-      break;
-
-    case ET_SCROLL_FLING_START:
-    case ET_SCROLL_FLING_CANCEL:
-    case ET_SCROLL:
-      event.reset(new ScrollEvent(native_event));
-      break;
-
-    case ET_TOUCH_RELEASED:
-    case ET_TOUCH_PRESSED:
-    case ET_TOUCH_MOVED:
-    case ET_TOUCH_CANCELLED:
-      event.reset(new TouchEvent(native_event));
-      break;
-
-    default:
-      break;
-  }
-  return event.Pass();
-}
-
 // From third_party/WebKit/Source/web/gtk/WebInputEventFactory.cpp:
 base::char16 GetControlCharacterForKeycode(int windows_key_code, bool shift) {
   if (windows_key_code >= ui::VKEY_A &&
@@ -107,10 +56,6 @@
   return 0;
 }
 
-int RegisterCustomEventType() {
-  return ++g_custom_event_types;
-}
-
 base::TimeDelta EventTimeForNow() {
   return base::TimeDelta::FromInternalValue(
       base::TimeTicks::Now().ToInternalValue());
diff --git a/ui/events/event_utils.h b/ui/events/event_utils.h
index b17f506..115f1d8 100644
--- a/ui/events/event_utils.h
+++ b/ui/events/event_utils.h
@@ -36,11 +36,6 @@
 // Updates the list of devices for cached properties.
 EVENTS_EXPORT void UpdateDeviceList();
 
-// Returns a ui::Event wrapping a native event. Ownership of the returned value
-// is transferred to the caller.
-EVENTS_EXPORT scoped_ptr<Event> EventFromNative(
-    const base::NativeEvent& native_event);
-
 // Get the EventType from a native event.
 EVENTS_EXPORT EventType EventTypeFromNative(
     const base::NativeEvent& native_event);
@@ -105,15 +100,6 @@
 EVENTS_EXPORT gfx::Vector2d GetMouseWheelOffset(
     const base::NativeEvent& native_event);
 
-// Returns a copy of |native_event|. Depending on the platform, this copy may
-// need to be deleted with ReleaseCopiedNativeEvent().
-base::NativeEvent CopyNativeEvent(
-    const base::NativeEvent& native_event);
-
-// Delete a |native_event| previously created by CopyNativeEvent().
-void ReleaseCopiedNativeEvent(
-    const base::NativeEvent& native_event);
-
 // Gets the touch id from a native event.
 EVENTS_EXPORT int GetTouchId(const base::NativeEvent& native_event);
 
@@ -155,9 +141,6 @@
                                     int* finger_count);
 
 #if defined(OS_WIN)
-EVENTS_EXPORT int GetModifiersFromACCEL(const ACCEL& accel);
-EVENTS_EXPORT int GetModifiersFromKeyState();
-
 // Returns true if |message| identifies a mouse event that was generated as the
 // result of a touch event.
 EVENTS_EXPORT bool IsMouseEventFromTouch(UINT message);
@@ -169,16 +152,6 @@
 
 #endif
 
-#if defined(USE_X11)
-// Update the native X11 event to correspond to the new flags.
-EVENTS_EXPORT void UpdateX11EventForFlags(Event* event);
-// Update the native X11 event to correspond to the new button flags.
-EVENTS_EXPORT void UpdateX11EventForChangedButtonFlags(MouseEvent* event);
-#endif
-
-// Registers a custom event type.
-EVENTS_EXPORT int RegisterCustomEventType();
-
 }  // namespace ui
 
 #endif  // UI_EVENTS_EVENT_UTILS_H_
diff --git a/ui/events/events_stub.cc b/ui/events/events_stub.cc
index 5c83974..39274f6 100644
--- a/ui/events/events_stub.cc
+++ b/ui/events/events_stub.cc
@@ -60,15 +60,6 @@
   return gfx::Vector2d();
 }
 
-base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
-  NOTIMPLEMENTED() <<
-      "Don't know how to copy base::NativeEvent for this platform";
-  return NULL;
-}
-
-void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
-}
-
 void IncrementTouchIdRefCount(const base::NativeEvent& native_event) {
   NOTIMPLEMENTED();
 }
diff --git a/ui/events/ipc/BUILD.gn b/ui/events/ipc/BUILD.gn
deleted file mode 100644
index c7585f6..0000000
--- a/ui/events/ipc/BUILD.gn
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2014 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.
-
-import("//build/config/ui.gni")
-
-component("ipc") {
-  output_name = "events_ipc"
-  sources = [
-    "latency_info_param_traits.cc",
-    "latency_info_param_traits.h",
-  ]
-
-  defines = [ "EVENTS_IMPLEMENTATION" ]
-
-  deps = [
-    "//ipc",
-    "//ui/events",
-  ]
-}
diff --git a/ui/events/ipc/OWNERS b/ui/events/ipc/OWNERS
deleted file mode 100644
index 6732300..0000000
--- a/ui/events/ipc/OWNERS
+++ /dev/null
@@ -1,12 +0,0 @@
-set noparent
-dcheng@chromium.org
-inferno@chromium.org
-jln@chromium.org
-jschuh@chromium.org
-kenrb@chromium.org
-nasko@chromium.org
-palmer@chromium.org
-tsepez@chromium.org
-
-per-file *.gyp*=*
-per-file BUILD.gn=*
diff --git a/ui/events/ipc/latency_info_param_traits.cc b/ui/events/ipc/latency_info_param_traits.cc
deleted file mode 100644
index 0b36c31..0000000
--- a/ui/events/ipc/latency_info_param_traits.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2014 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.
-
-#include "ui/events/ipc/latency_info_param_traits.h"
-
-// Generate param traits write methods.
-#include "ipc/param_traits_write_macros.h"
-namespace IPC {
-#undef UI_EVENTS_IPC_LATENCY_INFO_PARAM_TRAITS_H_
-#include "ui/events/ipc/latency_info_param_traits.h"
-}  // namespace IPC
-
-// Generate param traits read methods.
-#include "ipc/param_traits_read_macros.h"
-namespace IPC {
-#undef UI_EVENTS_IPC_LATENCY_INFO_PARAM_TRAITS_H_
-#include "ui/events/ipc/latency_info_param_traits.h"
-}  // namespace IPC
-
-// Generate param traits log methods.
-#include "ipc/param_traits_log_macros.h"
-namespace IPC {
-#undef UI_EVENTS_IPC_LATENCY_INFO_PARAM_TRAITS_H_
-#include "ui/events/ipc/latency_info_param_traits.h"
-}  // namespace IPC
diff --git a/ui/events/ipc/latency_info_param_traits.h b/ui/events/ipc/latency_info_param_traits.h
deleted file mode 100644
index 289ecb4..0000000
--- a/ui/events/ipc/latency_info_param_traits.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 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.
-
-#ifndef UI_EVENTS_IPC_LATENCY_INFO_PARAM_TRAITS_H_
-#define UI_EVENTS_IPC_LATENCY_INFO_PARAM_TRAITS_H_
-
-#include "ipc/ipc_message_macros.h"
-#include "ui/events/events_export.h"
-#include "ui/events/latency_info.h"
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT EVENTS_EXPORT
-
-IPC_ENUM_TRAITS_MAX_VALUE(ui::LatencyComponentType,
-                          ui::LATENCY_COMPONENT_TYPE_LAST)
-
-IPC_STRUCT_TRAITS_BEGIN(ui::LatencyInfo::LatencyComponent)
-  IPC_STRUCT_TRAITS_MEMBER(sequence_number)
-  IPC_STRUCT_TRAITS_MEMBER(event_time)
-  IPC_STRUCT_TRAITS_MEMBER(event_count)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(ui::LatencyInfo::InputCoordinate)
-IPC_STRUCT_TRAITS_MEMBER(x)
-IPC_STRUCT_TRAITS_MEMBER(y)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(ui::LatencyInfo)
-  IPC_STRUCT_TRAITS_MEMBER(latency_components)
-  IPC_STRUCT_TRAITS_MEMBER(trace_id)
-  IPC_STRUCT_TRAITS_MEMBER(terminated)
-  IPC_STRUCT_TRAITS_MEMBER(input_coordinates_size)
-  IPC_STRUCT_TRAITS_MEMBER(input_coordinates[0])
-  IPC_STRUCT_TRAITS_MEMBER(input_coordinates[1])
-IPC_STRUCT_TRAITS_END()
-
-#endif // UI_EVENTS_IPC_LATENCY_INFO_PARAM_TRAITS_H_
diff --git a/ui/events/platform/BUILD.gn b/ui/events/platform/BUILD.gn
index b9a977f..bcfec56 100644
--- a/ui/events/platform/BUILD.gn
+++ b/ui/events/platform/BUILD.gn
@@ -9,6 +9,8 @@
     # Allow this target to include events_export.h without depending on the
     # events target (which would be circular).
     "../events_export.h",
+    "platform_event_builder.cc",
+    "platform_event_builder.h",
     "platform_event_dispatcher.h",
     "platform_event_observer.h",
     "platform_event_source.cc",
@@ -23,6 +25,10 @@
 
   deps = [
     "//base",
+
+    # TODO(erg): Figure out what to do with this dependency later. Maybe get to
+    # the point where we can remove it before we commit this.
+    "//ui/events",
   ]
 
   if (use_x11) {
diff --git a/ui/events/platform/platform_event_builder.cc b/ui/events/platform/platform_event_builder.cc
new file mode 100644
index 0000000..c546011
--- /dev/null
+++ b/ui/events/platform/platform_event_builder.cc
@@ -0,0 +1,282 @@
+// Copyright 2015 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.
+
+#include "ui/events/platform/platform_event_builder.h"
+
+#if defined(USE_X11)
+#include <X11/extensions/XInput2.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#endif
+
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
+
+namespace ui {
+namespace {
+
+bool X11EventHasNonStandardState(const base::NativeEvent& event) {
+#if defined(USE_X11)
+  const unsigned int kAllStateMask =
+      Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask |
+      Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask |
+      LockMask | ControlMask | AnyModifier;
+  return event && (event->xkey.state & ~kAllStateMask) != 0;
+#else
+  return false;
+#endif
+}
+
+bool IsX11SendEventTrue(const base::NativeEvent& event) {
+#if defined(USE_X11)
+  return event && event->xany.send_event;
+#else
+  return false;
+#endif
+}
+
+KeyEvent* last_key_event_ = nullptr;
+MouseEvent* last_click_event_ = nullptr;
+
+// We can create a MouseEvent for a native event more than once. We set this
+// to true when the next event either has a different timestamp or we see a
+// release signalling that the press (click) event was completed.
+bool last_click_complete_ = false;
+
+bool IsRepeated(const base::NativeEvent& native_event, const KeyEvent& event) {
+  // A safe guard in case if there were continous key pressed events that are
+  // not auto repeat.
+  const int kMaxAutoRepeatTimeMs = 2000;
+  // Ignore key events that have non standard state masks as it may be
+  // reposted by an IME. IBUS-GTK uses this field to detect the
+  // re-posted event for example. crbug.com/385873.
+  if (X11EventHasNonStandardState(native_event))
+    return false;
+  if (event.is_char())
+    return false;
+  if (event.type() == ui::ET_KEY_RELEASED) {
+    delete last_key_event_;
+    last_key_event_ = NULL;
+    return false;
+  }
+  CHECK_EQ(ui::ET_KEY_PRESSED, event.type());
+  if (!last_key_event_) {
+    last_key_event_ = new KeyEvent(event);
+    return false;
+  }
+  if (event.key_code() == last_key_event_->key_code() &&
+      event.flags() == last_key_event_->flags() &&
+      (event.time_stamp() - last_key_event_->time_stamp()).InMilliseconds() <
+          kMaxAutoRepeatTimeMs) {
+    return true;
+  }
+  delete last_key_event_;
+  last_key_event_ = new KeyEvent(event);
+  return false;
+}
+
+}  // namespace
+
+// static
+MouseEvent PlatformEventBuilder::BuildMouseEvent(
+    const base::NativeEvent& native_event) {
+  MouseEvent mouse_event;
+  FillEventFrom(native_event, &mouse_event);
+  FillLocatedEventFrom(native_event, &mouse_event);
+  FillMouseEventFrom(native_event, &mouse_event);
+  return mouse_event;
+}
+
+// static
+MouseWheelEvent PlatformEventBuilder::BuildMouseWheelEvent(
+    const base::NativeEvent& native_event) {
+  MouseWheelEvent mouse_wheel_event;
+  FillEventFrom(native_event, &mouse_wheel_event);
+  FillLocatedEventFrom(native_event, &mouse_wheel_event);
+  FillMouseEventFrom(native_event, &mouse_wheel_event);
+  FillMouseWheelEventFrom(native_event, &mouse_wheel_event);
+  return mouse_wheel_event;
+}
+
+// static
+TouchEvent PlatformEventBuilder::BuildTouchEvent(
+    const base::NativeEvent& native_event) {
+  TouchEvent touch_event;
+  FillEventFrom(native_event, &touch_event);
+  FillLocatedEventFrom(native_event, &touch_event);
+  FillTouchEventFrom(native_event, &touch_event);
+  return touch_event;
+}
+
+// static
+KeyEvent PlatformEventBuilder::BuildKeyEvent(
+    const base::NativeEvent& native_event) {
+  KeyEvent key_event;
+  FillEventFrom(native_event, &key_event);
+  FillKeyEventFrom(native_event, &key_event);
+  return key_event;
+}
+
+// static
+ScrollEvent PlatformEventBuilder::BuildScrollEvent(
+    const base::NativeEvent& native_event) {
+  ScrollEvent scroll_event;
+  FillEventFrom(native_event, &scroll_event);
+  FillLocatedEventFrom(native_event, &scroll_event);
+  FillMouseEventFrom(native_event, &scroll_event);
+  FillScrollEventFrom(native_event, &scroll_event);
+  return scroll_event;
+}
+
+// static
+int PlatformEventBuilder::GetRepeatCount(const base::NativeEvent& native_event,
+                                         const MouseEvent& event) {
+  int click_count = 1;
+  if (last_click_event_) {
+    if (event.type() == ui::ET_MOUSE_RELEASED) {
+      if (event.changed_button_flags() ==
+          last_click_event_->changed_button_flags()) {
+        last_click_complete_ = true;
+        return last_click_event_->GetClickCount();
+      } else {
+        // If last_click_event_ has changed since this button was pressed
+        // return a click count of 1.
+        return click_count;
+      }
+    }
+    if (event.time_stamp() != last_click_event_->time_stamp())
+      last_click_complete_ = true;
+    if (!last_click_complete_ || IsX11SendEventTrue(native_event)) {
+      click_count = last_click_event_->GetClickCount();
+    } else if (MouseEvent::IsRepeatedClickEvent(*last_click_event_, event)) {
+      click_count = last_click_event_->GetClickCount() + 1;
+    }
+    delete last_click_event_;
+  }
+  last_click_event_ = new MouseEvent(event);
+  last_click_complete_ = false;
+  if (click_count > 3)
+    click_count = 3;
+  last_click_event_->SetClickCount(click_count);
+  return click_count;
+}
+
+// static
+void PlatformEventBuilder::ResetLastClickForTest() {
+  if (last_click_event_) {
+    delete last_click_event_;
+    last_click_event_ = NULL;
+    last_click_complete_ = false;
+  }
+}
+
+// static
+void PlatformEventBuilder::FillEventFrom(const base::NativeEvent& native_event,
+                                         Event* event) {
+  event->set_type(EventTypeFromNative(native_event));
+  event->set_time_stamp(EventTimeFromNative(native_event));
+  event->set_flags(EventFlagsFromNative(native_event));
+
+#if defined(USE_X11)
+  if (native_event->type == GenericEvent) {
+    XIDeviceEvent* xiev =
+        static_cast<XIDeviceEvent*>(native_event->xcookie.data);
+    event->set_source_device_id(xiev->sourceid);
+  }
+#endif
+}
+
+// static
+void PlatformEventBuilder::FillLocatedEventFrom(
+    const base::NativeEvent& native_event,
+    LocatedEvent* located_event) {
+  gfx::PointF event_location = EventLocationFromNative(native_event);
+  located_event->set_location(event_location);
+  located_event->set_root_location(event_location);
+  located_event->set_screen_location(
+      EventSystemLocationFromNative(native_event));
+}
+
+// static
+void PlatformEventBuilder::FillMouseEventFrom(
+    const base::NativeEvent& native_event,
+    MouseEvent* mouse_event) {
+  mouse_event->set_changed_button_flags(
+      GetChangedMouseButtonFlagsFromNative(native_event));
+
+  if (mouse_event->type() == ET_MOUSE_PRESSED ||
+      mouse_event->type() == ET_MOUSE_RELEASED) {
+    mouse_event->SetClickCount(GetRepeatCount(native_event, *mouse_event));
+  }
+}
+
+// static
+void PlatformEventBuilder::FillMouseWheelEventFrom(
+    const base::NativeEvent& native_event,
+    MouseWheelEvent* mouse_wheel_event) {
+  mouse_wheel_event->set_offset(GetMouseWheelOffset(native_event));
+}
+
+// static
+void PlatformEventBuilder::FillTouchEventFrom(
+    const base::NativeEvent& native_event,
+    TouchEvent* touch_event) {
+  touch_event->set_touch_id(GetTouchId(native_event));
+  touch_event->set_radius_x(GetTouchRadiusX(native_event));
+  touch_event->set_radius_y(GetTouchRadiusY(native_event));
+  touch_event->set_rotation_angle(GetTouchAngle(native_event));
+  touch_event->set_force(GetTouchForce(native_event));
+}
+
+// static
+void PlatformEventBuilder::FillKeyEventFrom(
+    const base::NativeEvent& native_event,
+    KeyEvent* key_event) {
+  key_event->set_key_code(KeyboardCodeFromNative(native_event));
+  key_event->set_code(CodeFromNative(native_event));
+  key_event->set_is_char(IsCharFromNative(native_event));
+  key_event->set_platform_keycode(PlatformKeycodeFromNative(native_event));
+
+  if (IsRepeated(native_event, *key_event))
+    key_event->set_flags(key_event->flags() | ui::EF_IS_REPEAT);
+
+#if defined(USE_X11)
+  key_event->NormalizeFlags();
+#endif
+#if defined(OS_WIN)
+  // Only Windows has native character events.
+  if (key_event->is_char())
+    key_event->set_character(native_event.wParam);
+#endif
+}
+
+// static
+void PlatformEventBuilder::FillScrollEventFrom(
+    const base::NativeEvent& native_event,
+    ScrollEvent* scroll_event) {
+  float x_offset = 0;
+  float y_offset = 0;
+  float x_offset_ordinal = 0;
+  float y_offset_ordinal = 0;
+  int finger_count = 0;
+
+  if (scroll_event->type() == ET_SCROLL) {
+    GetScrollOffsets(native_event, &x_offset, &y_offset, &x_offset_ordinal,
+                     &y_offset_ordinal, &finger_count);
+    scroll_event->set_offset(x_offset, y_offset);
+    scroll_event->set_offset_ordinal(x_offset_ordinal, y_offset_ordinal);
+    scroll_event->set_finger_count(finger_count);
+  } else if (scroll_event->type() == ET_SCROLL_FLING_START ||
+             scroll_event->type() == ET_SCROLL_FLING_CANCEL) {
+    GetFlingData(native_event, &x_offset, &y_offset, &x_offset_ordinal,
+                 &y_offset_ordinal, NULL);
+    scroll_event->set_offset(x_offset, y_offset);
+    scroll_event->set_offset_ordinal(x_offset_ordinal, y_offset_ordinal);
+  } else {
+    NOTREACHED() << "Unexpected event type " << scroll_event->type()
+                 << " when constructing a ScrollEvent.";
+  }
+}
+
+}  // namespace ui
diff --git a/ui/events/platform/platform_event_builder.h b/ui/events/platform/platform_event_builder.h
new file mode 100644
index 0000000..32aa80d
--- /dev/null
+++ b/ui/events/platform/platform_event_builder.h
@@ -0,0 +1,72 @@
+// Copyright 2015 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.
+
+#ifndef UI_EVENTS_PLATFORM_EVENT_PLATFORM_EVENT_BUILDER_H_
+#define UI_EVENTS_PLATFORM_EVENT_PLATFORM_EVENT_BUILDER_H_
+
+#include "base/event_types.h"
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+
+namespace ui {
+
+class Event;
+class KeyEvent;
+class LocatedEvent;
+class MouseEvent;
+class MouseWheelEvent;
+class ScrollEvent;
+class TouchEvent;
+
+// Builds ui::Events from native events.
+//
+// In chromium, this functionality was put inline on the individual Event
+// subclasses. This was fine there since all chromium binaries included the
+// system windowing system libraries. In mojo, we have small binaries which
+// have want to have generic events while only the native viewport needs the
+// capability to generate events from platform events.
+class PlatformEventBuilder {
+ public:
+  static MouseEvent BuildMouseEvent(const base::NativeEvent& native_event);
+  static MouseWheelEvent BuildMouseWheelEvent(
+      const base::NativeEvent& native_event);
+  static TouchEvent BuildTouchEvent(const base::NativeEvent& native_event);
+  static KeyEvent BuildKeyEvent(const base::NativeEvent& native_event);
+  static ScrollEvent BuildScrollEvent(const base::NativeEvent& native_event);
+
+  // Returns the repeat count based on the previous mouse click, if it is
+  // recent enough and within a small enough distance. Exposed for testing.
+  static int GetRepeatCount(const base::NativeEvent& native_event,
+                            const MouseEvent& event);
+
+ private:
+  FRIEND_TEST_ALL_PREFIXES(PlatformEventBuilderXTest,
+                           DoubleClickRequiresRelease);
+  FRIEND_TEST_ALL_PREFIXES(PlatformEventBuilderXTest, SingleClickRightLeft);
+
+  // Resets the last_click_event_ for unit tests.
+  static void ResetLastClickForTest();
+
+  // Takes data from |native_event| and fills the per class details on |event|.
+  static void FillEventFrom(const base::NativeEvent& native_event,
+                            Event* event);
+  static void FillLocatedEventFrom(const base::NativeEvent& native_event,
+                                   LocatedEvent* located_event);
+  static void FillMouseEventFrom(const base::NativeEvent& native_event,
+                                 MouseEvent* mouse_event);
+  static void FillMouseWheelEventFrom(const base::NativeEvent& native_event,
+                                      MouseWheelEvent* mouse_wheel_event);
+  static void FillTouchEventFrom(const base::NativeEvent& native_event,
+                                 TouchEvent* touch_event);
+  static void FillKeyEventFrom(const base::NativeEvent& native_event,
+                               KeyEvent* key_event);
+  static void FillScrollEventFrom(const base::NativeEvent& native_event,
+                                  ScrollEvent* scroll_event);
+
+  DISALLOW_COPY_AND_ASSIGN(PlatformEventBuilder);
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_PLATFORM_EVENT_PLATFORM_EVENT_BUILDER_H_
diff --git a/ui/events/platform/platform_event_builder_x_unittest.cc b/ui/events/platform/platform_event_builder_x_unittest.cc
new file mode 100644
index 0000000..8960f63
--- /dev/null
+++ b/ui/events/platform/platform_event_builder_x_unittest.cc
@@ -0,0 +1,250 @@
+// Copyright 2015 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.
+
+#include "ui/events/platform/platform_event_builder.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/event.h"
+#include "ui/events/keycodes/dom4/keycode_converter.h"
+#include "ui/events/test/events_test_utils_x11.h"
+#include "ui/events/x/device_data_manager_x11.h"
+#include "ui/events/x/touch_factory_x11.h"
+
+namespace ui {
+
+class PlatformEventBuilderXTest : public testing::Test {
+ public:
+  PlatformEventBuilderXTest() {}
+  virtual ~PlatformEventBuilderXTest() {}
+
+  void SetUp() override {
+    DeviceDataManagerX11::CreateInstance();
+    ui::TouchFactory::GetInstance()->ResetForTest();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PlatformEventBuilderXTest);
+};
+
+TEST_F(PlatformEventBuilderXTest, GetCharacter) {
+  // For X11, test the functions with native_event() as well. crbug.com/107837
+  ScopedXI2Event event;
+  event.InitKeyEvent(ET_KEY_PRESSED, VKEY_RETURN, EF_CONTROL_DOWN);
+  KeyEvent keyev3 = PlatformEventBuilder::BuildKeyEvent(event);
+  EXPECT_EQ(10, keyev3.GetCharacter());
+
+  event.InitKeyEvent(ET_KEY_PRESSED, VKEY_RETURN, EF_NONE);
+  KeyEvent keyev4 = PlatformEventBuilder::BuildKeyEvent(event);
+  EXPECT_EQ(13, keyev4.GetCharacter());
+}
+
+TEST_F(PlatformEventBuilderXTest, NormalizeKeyEventFlags) {
+  // Normalize flags when KeyEvent is created from XEvent.
+  ScopedXI2Event event;
+  {
+    event.InitKeyEvent(ET_KEY_PRESSED, VKEY_SHIFT, EF_SHIFT_DOWN);
+    KeyEvent keyev = PlatformEventBuilder::BuildKeyEvent(event);
+    EXPECT_EQ(EF_SHIFT_DOWN, keyev.flags());
+  }
+  {
+    event.InitKeyEvent(ET_KEY_RELEASED, VKEY_SHIFT, EF_SHIFT_DOWN);
+    KeyEvent keyev = PlatformEventBuilder::BuildKeyEvent(event);
+    EXPECT_EQ(EF_NONE, keyev.flags());
+  }
+  {
+    event.InitKeyEvent(ET_KEY_PRESSED, VKEY_CONTROL, EF_CONTROL_DOWN);
+    KeyEvent keyev = PlatformEventBuilder::BuildKeyEvent(event);
+    EXPECT_EQ(EF_CONTROL_DOWN, keyev.flags());
+  }
+  {
+    event.InitKeyEvent(ET_KEY_RELEASED, VKEY_CONTROL, EF_CONTROL_DOWN);
+    KeyEvent keyev = PlatformEventBuilder::BuildKeyEvent(event);
+    EXPECT_EQ(EF_NONE, keyev.flags());
+  }
+  {
+    event.InitKeyEvent(ET_KEY_PRESSED, VKEY_MENU, EF_ALT_DOWN);
+    KeyEvent keyev = PlatformEventBuilder::BuildKeyEvent(event);
+    EXPECT_EQ(EF_ALT_DOWN, keyev.flags());
+  }
+  {
+    event.InitKeyEvent(ET_KEY_RELEASED, VKEY_MENU, EF_ALT_DOWN);
+    KeyEvent keyev = PlatformEventBuilder::BuildKeyEvent(event);
+    EXPECT_EQ(EF_NONE, keyev.flags());
+  }
+}
+
+TEST_F(PlatformEventBuilderXTest, KeyEventCode) {
+  const char kCodeForSpace[] = "Space";
+  const uint16 kNativeCodeSpace =
+      ui::KeycodeConverter::CodeToNativeKeycode(kCodeForSpace);
+
+  // KeyEvent converts from the native keycode (XKB) to the code.
+  ScopedXI2Event xevent;
+  xevent.InitKeyEvent(ET_KEY_PRESSED, VKEY_SPACE, kNativeCodeSpace);
+  KeyEvent key = PlatformEventBuilder::BuildKeyEvent(xevent);
+  EXPECT_EQ(kCodeForSpace, key.code());
+}
+
+// TODO(erg): When we bring up mojo on Windows, we'll need to port this test to
+// Windows too.
+TEST_F(PlatformEventBuilderXTest, AutoRepeat) {
+  const uint16 kNativeCodeA = ui::KeycodeConverter::CodeToNativeKeycode("KeyA");
+  const uint16 kNativeCodeB = ui::KeycodeConverter::CodeToNativeKeycode("KeyB");
+#if defined(USE_X11)
+  ScopedXI2Event native_event_a_pressed;
+  native_event_a_pressed.InitKeyEvent(ET_KEY_PRESSED, VKEY_A, kNativeCodeA);
+  ScopedXI2Event native_event_a_released;
+  native_event_a_released.InitKeyEvent(ET_KEY_RELEASED, VKEY_A, kNativeCodeA);
+  ScopedXI2Event native_event_b_pressed;
+  native_event_b_pressed.InitKeyEvent(ET_KEY_PRESSED, VKEY_B, kNativeCodeB);
+  ScopedXI2Event native_event_a_pressed_nonstandard_state;
+  native_event_a_pressed_nonstandard_state.InitKeyEvent(ET_KEY_PRESSED, VKEY_A,
+                                                        kNativeCodeA);
+  // IBUS-GTK uses the mask (1 << 25) to detect reposted event.
+  static_cast<XEvent*>(native_event_a_pressed_nonstandard_state)->xkey.state |=
+      1 << 25;
+#elif defined(OS_WIN)
+  const LPARAM lParam_a = GetLParamFromScanCode(kNativeCodeA);
+  const LPARAM lParam_b = GetLParamFromScanCode(kNativeCodeB);
+  MSG native_event_a_pressed = {NULL, WM_KEYDOWN, VKEY_A, lParam_a};
+  MSG native_event_a_released = {NULL, WM_KEYUP, VKEY_A, lParam_a};
+  MSG native_event_b_pressed = {NULL, WM_KEYUP, VKEY_B, lParam_b};
+#endif
+  KeyEvent key_a1 = PlatformEventBuilder::BuildKeyEvent(native_event_a_pressed);
+  EXPECT_FALSE(key_a1.IsRepeat());
+  KeyEvent key_a1_released =
+      PlatformEventBuilder::BuildKeyEvent(native_event_a_released);
+  EXPECT_FALSE(key_a1_released.IsRepeat());
+
+  KeyEvent key_a2 = PlatformEventBuilder::BuildKeyEvent(native_event_a_pressed);
+  EXPECT_FALSE(key_a2.IsRepeat());
+  KeyEvent key_a2_repeated =
+      PlatformEventBuilder::BuildKeyEvent(native_event_a_pressed);
+  EXPECT_TRUE(key_a2_repeated.IsRepeat());
+  KeyEvent key_a2_released =
+      PlatformEventBuilder::BuildKeyEvent(native_event_a_released);
+  EXPECT_FALSE(key_a2_released.IsRepeat());
+
+  KeyEvent key_a3 = PlatformEventBuilder::BuildKeyEvent(native_event_a_pressed);
+  EXPECT_FALSE(key_a3.IsRepeat());
+  KeyEvent key_b = PlatformEventBuilder::BuildKeyEvent(native_event_b_pressed);
+  EXPECT_FALSE(key_b.IsRepeat());
+  KeyEvent key_a3_again =
+      PlatformEventBuilder::BuildKeyEvent(native_event_a_pressed);
+  EXPECT_FALSE(key_a3_again.IsRepeat());
+  KeyEvent key_a3_repeated =
+      PlatformEventBuilder::BuildKeyEvent(native_event_a_pressed);
+  EXPECT_TRUE(key_a3_repeated.IsRepeat());
+  KeyEvent key_a3_repeated2 =
+      PlatformEventBuilder::BuildKeyEvent(native_event_a_pressed);
+  EXPECT_TRUE(key_a3_repeated2.IsRepeat());
+  KeyEvent key_a3_released =
+      PlatformEventBuilder::BuildKeyEvent(native_event_a_released);
+  EXPECT_FALSE(key_a3_released.IsRepeat());
+
+#if defined(USE_X11)
+  KeyEvent key_a4_pressed =
+      PlatformEventBuilder::BuildKeyEvent(native_event_a_pressed);
+  EXPECT_FALSE(key_a4_pressed.IsRepeat());
+
+  KeyEvent key_a4_pressed_nonstandard_state =
+      PlatformEventBuilder::BuildKeyEvent(
+          native_event_a_pressed_nonstandard_state);
+  EXPECT_FALSE(key_a4_pressed_nonstandard_state.IsRepeat());
+#endif
+}
+
+// Tests that an event only increases the click count and gets marked as a
+// double click if a release event was seen for the previous click. This
+// prevents the same PRESSED event from being processed twice:
+// http://crbug.com/389162
+TEST_F(PlatformEventBuilderXTest, DoubleClickRequiresRelease) {
+  const gfx::Point origin1(0, 0);
+  const gfx::Point origin2(100, 0);
+  base::TimeDelta start = base::TimeDelta::FromMilliseconds(0);
+
+  unsigned int device_id = 1;
+  std::vector<unsigned int> device_list;
+  device_list.push_back(device_id);
+  TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
+  ScopedXI2Event native_event;
+
+  native_event.InitGenericButtonEvent(device_id, ET_MOUSE_PRESSED, origin1,
+                                      EF_LEFT_MOUSE_BUTTON);
+  MouseEvent event = PlatformEventBuilder::BuildMouseEvent(native_event);
+  event.set_time_stamp(start);
+  EXPECT_EQ(1, PlatformEventBuilder::GetRepeatCount(native_event, event));
+
+  native_event.InitGenericButtonEvent(device_id, ET_MOUSE_PRESSED, origin1,
+                                      EF_LEFT_MOUSE_BUTTON);
+  event = PlatformEventBuilder::BuildMouseEvent(native_event);
+  event.set_time_stamp(start);
+  EXPECT_EQ(1, PlatformEventBuilder::GetRepeatCount(native_event, event));
+
+  native_event.InitGenericButtonEvent(device_id, ET_MOUSE_PRESSED, origin2,
+                                      EF_LEFT_MOUSE_BUTTON);
+  event = PlatformEventBuilder::BuildMouseEvent(native_event);
+  event.set_time_stamp(start);
+  EXPECT_EQ(1, PlatformEventBuilder::GetRepeatCount(native_event, event));
+
+  native_event.InitGenericButtonEvent(device_id, ET_MOUSE_RELEASED, origin2,
+                                      EF_LEFT_MOUSE_BUTTON);
+  event = PlatformEventBuilder::BuildMouseEvent(native_event);
+  event.set_time_stamp(start);
+  EXPECT_EQ(1, PlatformEventBuilder::GetRepeatCount(native_event, event));
+
+  native_event.InitGenericButtonEvent(device_id, ET_MOUSE_PRESSED, origin2,
+                                      EF_LEFT_MOUSE_BUTTON);
+  event = PlatformEventBuilder::BuildMouseEvent(native_event);
+  event.set_time_stamp(start);
+  EXPECT_EQ(2, PlatformEventBuilder::GetRepeatCount(native_event, event));
+
+  native_event.InitGenericButtonEvent(device_id, ET_MOUSE_RELEASED, origin2,
+                                      EF_LEFT_MOUSE_BUTTON);
+  event = PlatformEventBuilder::BuildMouseEvent(native_event);
+  event.set_time_stamp(start);
+  EXPECT_EQ(2, PlatformEventBuilder::GetRepeatCount(native_event, event));
+
+  PlatformEventBuilder::ResetLastClickForTest();
+}
+
+// Tests that clicking right and then left clicking does not generate a double
+// click.
+TEST_F(PlatformEventBuilderXTest, SingleClickRightLeft) {
+  const gfx::Point origin(0, 0);
+  base::TimeDelta start = base::TimeDelta::FromMilliseconds(0);
+
+  unsigned int device_id = 1;
+  std::vector<unsigned int> device_list;
+  device_list.push_back(device_id);
+  TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
+  ScopedXI2Event native_event;
+
+  native_event.InitGenericButtonEvent(device_id, ET_MOUSE_PRESSED, origin,
+                                      EF_RIGHT_MOUSE_BUTTON);
+  MouseEvent event = PlatformEventBuilder::BuildMouseEvent(native_event);
+  event.set_time_stamp(start);
+  EXPECT_EQ(1, PlatformEventBuilder::GetRepeatCount(native_event, event));
+
+  native_event.InitGenericButtonEvent(device_id, ET_MOUSE_PRESSED, origin,
+                                      EF_LEFT_MOUSE_BUTTON);
+  event = PlatformEventBuilder::BuildMouseEvent(native_event);
+  event.set_time_stamp(start);
+  EXPECT_EQ(1, PlatformEventBuilder::GetRepeatCount(native_event, event));
+
+  native_event.InitGenericButtonEvent(device_id, ET_MOUSE_RELEASED, origin,
+                                      EF_LEFT_MOUSE_BUTTON);
+  event = PlatformEventBuilder::BuildMouseEvent(native_event);
+  event.set_time_stamp(start);
+  EXPECT_EQ(1, PlatformEventBuilder::GetRepeatCount(native_event, event));
+
+  native_event.InitGenericButtonEvent(device_id, ET_MOUSE_PRESSED, origin,
+                                      EF_LEFT_MOUSE_BUTTON);
+  event = PlatformEventBuilder::BuildMouseEvent(native_event);
+  event.set_time_stamp(start);
+  EXPECT_EQ(2, PlatformEventBuilder::GetRepeatCount(native_event, event));
+  PlatformEventBuilder::ResetLastClickForTest();
+}
+
+}  // namespace ui
diff --git a/ui/events/win/events_win.cc b/ui/events/win/events_win.cc
index ae9d403..bcbb2c8 100644
--- a/ui/events/win/events_win.cc
+++ b/ui/events/win/events_win.cc
@@ -292,13 +292,6 @@
   return gfx::Vector2d(GET_WHEEL_DELTA_WPARAM(native_event.wParam), 0);
 }
 
-base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
-  return event;
-}
-
-void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
-}
-
 void IncrementTouchIdRefCount(const base::NativeEvent& event) {
   NOTIMPLEMENTED();
 }
@@ -356,30 +349,6 @@
   return false;
 }
 
-int GetModifiersFromACCEL(const ACCEL& accel) {
-  int modifiers = EF_NONE;
-  if (accel.fVirt & FSHIFT)
-    modifiers |= EF_SHIFT_DOWN;
-  if (accel.fVirt & FCONTROL)
-    modifiers |= EF_CONTROL_DOWN;
-  if (accel.fVirt & FALT)
-    modifiers |= EF_ALT_DOWN;
-  return modifiers;
-}
-
-int GetModifiersFromKeyState() {
-  int modifiers = EF_NONE;
-  if (base::win::IsShiftPressed())
-    modifiers |= EF_SHIFT_DOWN;
-  if (base::win::IsCtrlPressed())
-    modifiers |= EF_CONTROL_DOWN;
-  if (base::win::IsAltPressed())
-    modifiers |= EF_ALT_DOWN;
-  if (base::win::IsAltGrPressed())
-    modifiers |= EF_ALTGR_DOWN;
-  return modifiers;
-}
-
 // Windows emulates mouse messages for touch events.
 bool IsMouseEventFromTouch(UINT message) {
   return (message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST) &&
diff --git a/ui/events/x/events_x.cc b/ui/events/x/events_x.cc
index 40124b9..e49e6a5 100644
--- a/ui/events/x/events_x.cc
+++ b/ui/events/x/events_x.cc
@@ -293,47 +293,6 @@
       xiev->sourceid, radius);
 }
 
-unsigned int UpdateX11EventFlags(int ui_flags, unsigned int old_x_flags) {
-  static struct {
-    int ui;
-    int x;
-  } flags[] = {
-    {ui::EF_CONTROL_DOWN, ControlMask},
-    {ui::EF_SHIFT_DOWN, ShiftMask},
-    {ui::EF_ALT_DOWN, Mod1Mask},
-    {ui::EF_CAPS_LOCK_DOWN, LockMask},
-    {ui::EF_ALTGR_DOWN, Mod5Mask},
-    {ui::EF_COMMAND_DOWN, Mod4Mask},
-    {ui::EF_MOD3_DOWN, Mod3Mask},
-    {ui::EF_NUMPAD_KEY, Mod2Mask},
-    {ui::EF_LEFT_MOUSE_BUTTON, Button1Mask},
-    {ui::EF_MIDDLE_MOUSE_BUTTON, Button2Mask},
-    {ui::EF_RIGHT_MOUSE_BUTTON, Button3Mask},
-  };
-  unsigned int new_x_flags = old_x_flags;
-  for (size_t i = 0; i < arraysize(flags); ++i) {
-    if (ui_flags & flags[i].ui)
-      new_x_flags |= flags[i].x;
-    else
-      new_x_flags &= ~flags[i].x;
-  }
-  return new_x_flags;
-}
-
-unsigned int UpdateX11EventButton(int ui_flag, unsigned int old_x_button) {
-  switch (ui_flag) {
-    case ui::EF_LEFT_MOUSE_BUTTON:
-      return Button1;
-    case ui::EF_MIDDLE_MOUSE_BUTTON:
-      return Button2;
-    case ui::EF_RIGHT_MOUSE_BUTTON:
-      return Button3;
-    default:
-      return old_x_button;
-  }
-  NOTREACHED();
-}
-
 bool GetGestureTimes(const base::NativeEvent& native_event,
                      double* start_time,
                      double* end_time) {
@@ -732,18 +691,6 @@
   }
 }
 
-base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
-  if (!event || event->type == GenericEvent)
-    return NULL;
-  XEvent* copy = new XEvent;
-  *copy = *event;
-  return copy;
-}
-
-void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
-  delete event;
-}
-
 void IncrementTouchIdRefCount(const base::NativeEvent& xev) {
   ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
   double tracking_id;
@@ -876,53 +823,4 @@
   return true;
 }
 
-void UpdateX11EventForFlags(Event* event) {
-  XEvent* xev = event->native_event();
-  if (!xev)
-    return;
-  switch (xev->type) {
-    case KeyPress:
-    case KeyRelease:
-      xev->xkey.state = UpdateX11EventFlags(event->flags(), xev->xkey.state);
-      break;
-    case ButtonPress:
-    case ButtonRelease:
-      xev->xbutton.state =
-          UpdateX11EventFlags(event->flags(), xev->xbutton.state);
-      break;
-    case GenericEvent: {
-      XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data);
-      DCHECK(xievent);
-      xievent->mods.effective =
-          UpdateX11EventFlags(event->flags(), xievent->mods.effective);
-      break;
-    }
-    default:
-      break;
-  }
-}
-
-void UpdateX11EventForChangedButtonFlags(MouseEvent* event) {
-  XEvent* xev = event->native_event();
-  if (!xev)
-    return;
-  switch (xev->type) {
-    case ButtonPress:
-    case ButtonRelease:
-      xev->xbutton.button = UpdateX11EventButton(event->changed_button_flags(),
-                                                 xev->xbutton.button);
-      break;
-    case GenericEvent: {
-      XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data);
-      CHECK(xievent && (xievent->evtype == XI_ButtonPress ||
-                        xievent->evtype == XI_ButtonRelease));
-      xievent->detail =
-          UpdateX11EventButton(event->changed_button_flags(), xievent->detail);
-      break;
-    }
-    default:
-      break;
-  }
-}
-
 }  // namespace ui
diff --git a/ui/events/x/events_x_unittest.cc b/ui/events/x/events_x_unittest.cc
index 2e33674..0c4b36a 100644
--- a/ui/events/x/events_x_unittest.cc
+++ b/ui/events/x/events_x_unittest.cc
@@ -19,6 +19,7 @@
 #include "ui/events/event.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/event_utils.h"
+#include "ui/events/platform/platform_event_builder.h"
 #include "ui/events/test/events_test_utils.h"
 #include "ui/events/test/events_test_utils_x11.h"
 #include "ui/events/x/device_data_manager_x11.h"
@@ -72,7 +73,7 @@
   // Exclude keysyms for which the server has no corresponding keycode.
   if (x_keycode) {
     InitKeyEvent(display, &event, true, x_keycode, 0);
-    ui::KeyEvent ui_key_event(&event);
+    ui::KeyEvent ui_key_event = PlatformEventBuilder::BuildKeyEvent(&event);
     return (ui_key_event.flags() & ui::EF_FUNCTION_KEY);
   }
   return true;
@@ -201,14 +202,14 @@
   for (int i = 1; i <= 3; ++i) {
     InitButtonEvent(&event, true, location, 1, 0);
     {
-      MouseEvent mouseev(&event);
+      MouseEvent mouseev = PlatformEventBuilder::BuildMouseEvent(&event);
       EXPECT_EQ(ui::ET_MOUSE_PRESSED, mouseev.type());
       EXPECT_EQ(i, mouseev.GetClickCount());
     }
 
     InitButtonEvent(&event, false, location, 1, 0);
     {
-      MouseEvent mouseev(&event);
+      MouseEvent mouseev = PlatformEventBuilder::BuildMouseEvent(&event);
       EXPECT_EQ(ui::ET_MOUSE_RELEASED, mouseev.type());
       EXPECT_EQ(i, mouseev.GetClickCount());
     }
@@ -456,7 +457,7 @@
       InitKeyEvent(display, &event, true, x_keycode, 0);
       // int keysym = XLookupKeysym(&event.xkey, 0);
       // if (keysym) {
-      ui::KeyEvent ui_key_event(&event);
+      ui::KeyEvent ui_key_event = PlatformEventBuilder::BuildKeyEvent(&event);
       EXPECT_EQ(keys[k].is_numpad_key ? ui::EF_NUMPAD_KEY : 0,
                 ui_key_event.flags() & ui::EF_NUMPAD_KEY);
     }
@@ -611,7 +612,7 @@
     for (int is_char = 0; is_char < 2; ++is_char) {
       XEvent x_event;
       InitKeyEvent(display, &x_event, true, 0, state);
-      ui::KeyEvent key_event(&x_event);
+      ui::KeyEvent key_event = PlatformEventBuilder::BuildKeyEvent(&x_event);
       if (is_char) {
         KeyEventTestApi test_event(&key_event);
         test_event.set_is_char(true);
@@ -628,7 +629,7 @@
     for (int is_char = 0; is_char < 2; ++is_char) {
       XEvent x_event;
       InitKeyEvent(display, &x_event, true, 0, state);
-      ui::KeyEvent key_event(&x_event);
+      ui::KeyEvent key_event = PlatformEventBuilder::BuildKeyEvent(&x_event);
       if (is_char) {
         KeyEventTestApi test_event(&key_event);
         test_event.set_is_char(true);
diff --git a/ui/platform_window/x11/x11_window.cc b/ui/platform_window/x11/x11_window.cc
index e3a421c..e8a9852 100644
--- a/ui/platform_window/x11/x11_window.cc
+++ b/ui/platform_window/x11/x11_window.cc
@@ -11,6 +11,7 @@
 
 #include "ui/events/event.h"
 #include "ui/events/event_utils.h"
+#include "ui/events/platform/platform_event_builder.h"
 #include "ui/events/platform/platform_event_dispatcher.h"
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/events/platform/x11/x11_event_source.h"
@@ -73,7 +74,7 @@
   switch (event_type) {
     case ET_KEY_PRESSED:
     case ET_KEY_RELEASED: {
-      KeyEvent key_event(xev);
+      KeyEvent key_event = PlatformEventBuilder::BuildKeyEvent(xev);
       delegate_->DispatchEvent(&key_event);
       break;
     }
@@ -81,19 +82,20 @@
     case ET_MOUSE_MOVED:
     case ET_MOUSE_DRAGGED:
     case ET_MOUSE_RELEASED: {
-      MouseEvent mouse_event(xev);
+      MouseEvent mouse_event = PlatformEventBuilder::BuildMouseEvent(xev);
       delegate_->DispatchEvent(&mouse_event);
       break;
     }
     case ET_MOUSEWHEEL: {
-      MouseWheelEvent wheel_event(xev);
+      MouseWheelEvent wheel_event =
+          PlatformEventBuilder::BuildMouseWheelEvent(xev);
       delegate_->DispatchEvent(&wheel_event);
       break;
     }
     case ET_SCROLL_FLING_START:
     case ET_SCROLL_FLING_CANCEL:
     case ET_SCROLL: {
-      ScrollEvent scroll_event(xev);
+      ScrollEvent scroll_event = PlatformEventBuilder::BuildScrollEvent(xev);
       delegate_->DispatchEvent(&scroll_event);
       break;
     }
@@ -101,8 +103,14 @@
     case ET_TOUCH_PRESSED:
     case ET_TOUCH_CANCELLED:
     case ET_TOUCH_RELEASED: {
-      TouchEvent touch_event(xev);
+      TouchEvent touch_event = PlatformEventBuilder::BuildTouchEvent(xev);
+
+      if (touch_event.type() == ET_TOUCH_PRESSED)
+        IncrementTouchIdRefCount(xev);
+
       delegate_->DispatchEvent(&touch_event);
+
+      ClearTouchIdIfReleased(xev);
       break;
     }
     default:
@@ -260,14 +268,14 @@
     case EnterNotify: {
       // EnterNotify creates ET_MOUSE_MOVED. Mark as synthesized as this is
       // not real mouse move event.
-      MouseEvent mouse_event(xev);
+      MouseEvent mouse_event = PlatformEventBuilder::BuildMouseEvent(xev);
       CHECK_EQ(ET_MOUSE_MOVED, mouse_event.type());
       mouse_event.set_flags(mouse_event.flags() | EF_IS_SYNTHESIZED);
       delegate_->DispatchEvent(&mouse_event);
       break;
     }
     case LeaveNotify: {
-      MouseEvent mouse_event(xev);
+      MouseEvent mouse_event = PlatformEventBuilder::BuildMouseEvent(xev);
       delegate_->DispatchEvent(&mouse_event);
       break;
     }
@@ -283,7 +291,7 @@
 
     case KeyPress:
     case KeyRelease: {
-      KeyEvent key_event(xev);
+      KeyEvent key_event = PlatformEventBuilder::BuildKeyEvent(xev);
       delegate_->DispatchEvent(&key_event);
       break;
     }
@@ -292,13 +300,14 @@
     case ButtonRelease: {
       switch (EventTypeFromNative(xev)) {
         case ET_MOUSEWHEEL: {
-          MouseWheelEvent mouseev(xev);
+          MouseWheelEvent mouseev =
+              PlatformEventBuilder::BuildMouseWheelEvent(xev);
           delegate_->DispatchEvent(&mouseev);
           break;
         }
         case ET_MOUSE_PRESSED:
         case ET_MOUSE_RELEASED: {
-          MouseEvent mouseev(xev);
+          MouseEvent mouseev = PlatformEventBuilder::BuildMouseEvent(xev);
           delegate_->DispatchEvent(&mouseev);
           break;
         }