// 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.

#include "ui/events/event.h"

#if defined(USE_X11)
#include <X11/extensions/XInput2.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#endif

#include <cmath>
#include <cstring>

#include "base/metrics/histogram.h"
#include "base/strings/stringprintf.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/gfx/transform.h"
#include "ui/gfx/transform_util.h"

#if defined(USE_X11)
#include "ui/events/keycodes/keyboard_code_conversion_x.h"
#elif defined(USE_OZONE)
#include "ui/events/ozone/layout/keyboard_layout_engine.h" // nogncheck
#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" // nogncheck
#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_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 {

////////////////////////////////////////////////////////////////////////////////
// Event

// static
scoped_ptr<Event> Event::Clone(const Event& event) {
  if (event.IsKeyEvent()) {
    return make_scoped_ptr(new KeyEvent(static_cast<const KeyEvent&>(event)));
  }

  if (event.IsMouseEvent()) {
    if (event.IsMouseWheelEvent()) {
      return make_scoped_ptr(
          new MouseWheelEvent(static_cast<const MouseWheelEvent&>(event)));
    }

    return make_scoped_ptr(
        new MouseEvent(static_cast<const MouseEvent&>(event)));
  }

  if (event.IsTouchEvent()) {
    return make_scoped_ptr(
        new TouchEvent(static_cast<const TouchEvent&>(event)));
  }

  if (event.IsGestureEvent()) {
    return make_scoped_ptr(
        new GestureEvent(static_cast<const GestureEvent&>(event)));
  }

  if (event.IsScrollEvent()) {
    return make_scoped_ptr(
        new ScrollEvent(static_cast<const ScrollEvent&>(event)));
  }

  return make_scoped_ptr(new Event(event));
}

Event::~Event() {
  if (delete_native_event_)
    ReleaseCopiedNativeEvent(native_event_);
}

GestureEvent* Event::AsGestureEvent() {
  CHECK(IsGestureEvent());
  return static_cast<GestureEvent*>(this);
}

const GestureEvent* Event::AsGestureEvent() const {
  CHECK(IsGestureEvent());
  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.
  // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
  CHECK(cancelable_);
  result_ = static_cast<EventResult>(result_ | ER_CONSUMED);
}

void Event::SetHandled() {
  // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
  // events.
  // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
  CHECK(cancelable_);
  result_ = static_cast<EventResult>(result_ | ER_HANDLED);
}

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
#if defined(USE_OZONE)
  source_device_id_ =
      static_cast<const Event*>(native_event)->source_device_id();
#endif
}

Event::Event(const Event& copy)
    : type_(copy.type_),
      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_);
}

////////////////////////////////////////////////////////////////////////////////
// CancelModeEvent

CancelModeEvent::CancelModeEvent()
    : Event(ET_CANCEL_MODE, base::TimeDelta(), 0) {
  set_cancelable(false);
}

CancelModeEvent::~CancelModeEvent() {
}

////////////////////////////////////////////////////////////////////////////////
// LocatedEvent

LocatedEvent::~LocatedEvent() {
}

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(EventType type,
                           const gfx::PointF& location,
                           const gfx::PointF& root_location,
                           base::TimeDelta time_stamp,
                           int flags)
    : Event(type, time_stamp, flags),
      location_(location),
      root_location_(root_location) {
}

void LocatedEvent::UpdateForRootTransform(
    const gfx::Transform& reversed_root_transform) {
  // Transform has to be done at root level.
  gfx::Point3F p(location_);
  reversed_root_transform.TransformPoint(&p);
  location_ = p.AsPointF();
  root_location_ = location_;
}

////////////////////////////////////////////////////////////////////////////////
// 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(EventType type,
                       const gfx::PointF& location,
                       const gfx::PointF& root_location,
                       base::TimeDelta time_stamp,
                       int flags,
                       int changed_button_flags)
    : LocatedEvent(type, location, root_location, time_stamp, flags),
      changed_button_flags_(changed_button_flags) {
  if (this->type() == ET_MOUSE_MOVED && IsAnyButton())
    SetType(ET_MOUSE_DRAGGED);
}

// static
bool MouseEvent::IsRepeatedClickEvent(
    const MouseEvent& event1,
    const MouseEvent& event2) {
  // These values match the Windows defaults.
  static const int kDoubleClickTimeMS = 500;
  static const int kDoubleClickWidth = 4;
  static const int kDoubleClickHeight = 4;

  if (event1.type() != ET_MOUSE_PRESSED ||
      event2.type() != ET_MOUSE_PRESSED)
    return false;

  // Compare flags, but ignore EF_IS_DOUBLE_CLICK to allow triple clicks.
  if ((event1.flags() & ~EF_IS_DOUBLE_CLICK) !=
      (event2.flags() & ~EF_IS_DOUBLE_CLICK))
    return false;

  // The new event has been created from the same native event.
  if (event1.time_stamp() == event2.time_stamp())
    return false;

  base::TimeDelta time_difference = event2.time_stamp() - event1.time_stamp();

  if (time_difference.InMilliseconds() > kDoubleClickTimeMS)
    return false;

  if (std::abs(event2.x() - event1.x()) > kDoubleClickWidth / 2)
    return false;

  if (std::abs(event2.y() - event1.y()) > kDoubleClickHeight / 2)
    return false;

  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;

  if (flags() & EF_IS_TRIPLE_CLICK)
    return 3;
  else if (flags() & EF_IS_DOUBLE_CLICK)
    return 2;
  else
    return 1;
}

void MouseEvent::SetClickCount(int click_count) {
  if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
    return;

  DCHECK(click_count > 0);
  DCHECK(click_count <= 3);

  int f = flags();
  switch (click_count) {
    case 1:
      f &= ~EF_IS_DOUBLE_CLICK;
      f &= ~EF_IS_TRIPLE_CLICK;
      break;
    case 2:
      f |= EF_IS_DOUBLE_CLICK;
      f &= ~EF_IS_TRIPLE_CLICK;
      break;
    case 3:
      f &= ~EF_IS_DOUBLE_CLICK;
      f |= EF_IS_TRIPLE_CLICK;
      break;
  }
  set_flags(f);
}

////////////////////////////////////////////////////////////////////////////////
// MouseWheelEvent

MouseWheelEvent::MouseWheelEvent(const base::NativeEvent& native_event)
    : MouseEvent(native_event),
      offset_(GetMouseWheelOffset(native_event)) {
}

MouseWheelEvent::MouseWheelEvent(const ScrollEvent& scroll_event)
    : MouseEvent(scroll_event),
      offset_(gfx::ToRoundedInt(scroll_event.x_offset()),
              gfx::ToRoundedInt(scroll_event.y_offset())) {
  SetType(ET_MOUSEWHEEL);
}

MouseWheelEvent::MouseWheelEvent(const MouseEvent& mouse_event,
                                 int x_offset,
                                 int y_offset)
    : MouseEvent(mouse_event), offset_(x_offset, y_offset) {
  DCHECK(type() == ET_MOUSEWHEEL);
}

MouseWheelEvent::MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event)
    : MouseEvent(mouse_wheel_event),
      offset_(mouse_wheel_event.offset()) {
  DCHECK(type() == ET_MOUSEWHEEL);
}

MouseWheelEvent::MouseWheelEvent(const gfx::Vector2d& offset,
                                 const gfx::PointF& location,
                                 const gfx::PointF& root_location,
                                 base::TimeDelta time_stamp,
                                 int flags,
                                 int changed_button_flags)
    : MouseEvent(ui::ET_MOUSEWHEEL,
                 location,
                 root_location,
                 time_stamp,
                 flags,
                 changed_button_flags),
      offset_(offset) {
}

#if defined(OS_WIN)
// This value matches windows WHEEL_DELTA.
// static
const int MouseWheelEvent::kWheelDelta = 120;
#else
// This value matches GTK+ wheel scroll amount.
const int MouseWheelEvent::kWheelDelta = 53;
#endif

////////////////////////////////////////////////////////////////////////////////
// TouchEvent

TouchEvent::TouchEvent(const base::NativeEvent& native_event)
    : LocatedEvent(native_event),
      touch_id_(GetTouchId(native_event)),
      unique_event_id_(ui::GetNextTouchEventId()),
      radius_x_(GetTouchRadiusX(native_event)),
      radius_y_(GetTouchRadiusY(native_event)),
      rotation_angle_(GetTouchAngle(native_event)),
      force_(GetTouchForce(native_event)),
      may_cause_scrolling_(false),
      should_remove_native_touch_id_mapping_(false) {
  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);

  FixRotationAngle();
  if (type() == ET_TOUCH_RELEASED || type() == ET_TOUCH_CANCELLED)
    should_remove_native_touch_id_mapping_ = true;
}

TouchEvent::TouchEvent(EventType type,
                       const gfx::PointF& location,
                       int touch_id,
                       base::TimeDelta time_stamp)
    : LocatedEvent(type, location, location, time_stamp, 0),
      touch_id_(touch_id),
      unique_event_id_(ui::GetNextTouchEventId()),
      radius_x_(0.0f),
      radius_y_(0.0f),
      rotation_angle_(0.0f),
      force_(0.0f),
      may_cause_scrolling_(false),
      should_remove_native_touch_id_mapping_(false) {
  latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
}

TouchEvent::TouchEvent(EventType type,
                       const gfx::PointF& location,
                       int flags,
                       int touch_id,
                       base::TimeDelta time_stamp,
                       float radius_x,
                       float radius_y,
                       float angle,
                       float force)
    : LocatedEvent(type, location, location, time_stamp, flags),
      touch_id_(touch_id),
      unique_event_id_(ui::GetNextTouchEventId()),
      radius_x_(radius_x),
      radius_y_(radius_y),
      rotation_angle_(angle),
      force_(force),
      may_cause_scrolling_(false),
      should_remove_native_touch_id_mapping_(false) {
  latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
  FixRotationAngle();
}

TouchEvent::TouchEvent(const TouchEvent& copy)
    : LocatedEvent(copy),
      touch_id_(copy.touch_id_),
      unique_event_id_(copy.unique_event_id_),
      radius_x_(copy.radius_x_),
      radius_y_(copy.radius_y_),
      rotation_angle_(copy.rotation_angle_),
      force_(copy.force_),
      may_cause_scrolling_(copy.may_cause_scrolling_),
      should_remove_native_touch_id_mapping_(false) {
  // Copied events should not remove touch id mapping, as this either causes the
  // mapping to be lost before the initial event has finished dispatching, or
  // the copy to attempt to remove the mapping from a null |native_event_|.
}

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 (should_remove_native_touch_id_mapping_) {
    DCHECK(type() == ET_TOUCH_RELEASED || type() == ET_TOUCH_CANCELLED);
    if (type() == ET_TOUCH_RELEASED || type() == ET_TOUCH_CANCELLED)
      ClearTouchIdIfReleased(native_event());
  }
}

void TouchEvent::UpdateForRootTransform(
    const gfx::Transform& inverted_root_transform) {
  LocatedEvent::UpdateForRootTransform(inverted_root_transform);
  gfx::DecomposedTransform decomp;
  bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
  DCHECK(success);
  if (decomp.scale[0])
    radius_x_ *= decomp.scale[0];
  if (decomp.scale[1])
    radius_y_ *= decomp.scale[1];
}

void TouchEvent::DisableSynchronousHandling() {
  DispatcherApi dispatcher_api(this);
  dispatcher_api.set_result(
      static_cast<EventResult>(result() | ER_DISABLE_SYNC_HANDLING));
}

void TouchEvent::FixRotationAngle() {
  while (rotation_angle_ < 0)
    rotation_angle_ += 180;
  while (rotation_angle_ >= 180)
    rotation_angle_ -= 180;
}

////////////////////////////////////////////////////////////////////////////////
// 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;
  } else if (event.time_stamp() == last_key_event_->time_stamp()) {
    // The KeyEvent is created from the same native event.
    return (last_key_event_->flags() & ui::EF_IS_REPEAT) != 0;
  }
  if (event.key_code() == last_key_event_->key_code() &&
      event.flags() == (last_key_event_->flags() & ~ui::EF_IS_REPEAT) &&
      (event.time_stamp() - last_key_event_->time_stamp()).InMilliseconds() <
          kMaxAutoRepeatTimeMs) {
    last_key_event_->set_time_stamp(event.time_stamp());
    last_key_event_->set_flags(last_key_event_->flags() | ui::EF_IS_REPEAT);
    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)),
      key_(DomKey::NONE),
      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,
                   KeyboardCode key_code,
                   int flags)
    : Event(type, EventTimeForNow(), flags),
      key_code_(key_code),
      code_(UsLayoutKeyboardCodeToDomCode(key_code)),
      is_char_(false),
      platform_keycode_(0),
      key_(DomKey::NONE),
      character_() {
}

KeyEvent::KeyEvent(EventType type,
                   KeyboardCode key_code,
                   DomCode code,
                   int flags)
    : Event(type, EventTimeForNow(), flags),
      key_code_(key_code),
      code_(code),
      is_char_(false),
      platform_keycode_(0),
      key_(DomKey::NONE),
      character_(0) {
}

KeyEvent::KeyEvent(EventType type,
                   KeyboardCode key_code,
                   DomCode code,
                   int flags,
                   DomKey key,
                   base::char16 character,
                   base::TimeDelta time_stamp)
    : Event(type, time_stamp, flags),
      key_code_(key_code),
      code_(code),
      is_char_(false),
      platform_keycode_(0),
      key_(key),
      character_(character) {
}

KeyEvent::KeyEvent(base::char16 character, KeyboardCode key_code, int flags)
    : Event(ET_KEY_PRESSED, EventTimeForNow(), flags),
      key_code_(key_code),
      code_(DomCode::NONE),
      is_char_(true),
      platform_keycode_(0),
      key_(DomKey::CHARACTER),
      character_(character) {
}

KeyEvent::KeyEvent(const KeyEvent& rhs)
    : Event(rhs),
      key_code_(rhs.key_code_),
      code_(rhs.code_),
      is_char_(rhs.is_char_),
      platform_keycode_(rhs.platform_keycode_),
      key_(rhs.key_),
      character_(rhs.character_) {
  if (rhs.extended_key_event_data_)
    extended_key_event_data_.reset(rhs.extended_key_event_data_->Clone());
}

KeyEvent& KeyEvent::operator=(const KeyEvent& rhs) {
  if (this != &rhs) {
    Event::operator=(rhs);
    key_code_ = rhs.key_code_;
    code_ = rhs.code_;
    key_ = rhs.key_;
    is_char_ = rhs.is_char_;
    platform_keycode_ = rhs.platform_keycode_;
    character_ = rhs.character_;

    if (rhs.extended_key_event_data_)
      extended_key_event_data_.reset(rhs.extended_key_event_data_->Clone());
  }
  return *this;
}

KeyEvent::~KeyEvent() {}

void KeyEvent::SetExtendedKeyEventData(scoped_ptr<ExtendedKeyEventData> data) {
  extended_key_event_data_ = data.Pass();
}

void KeyEvent::ApplyLayout() const {
  // If the client has set the character (e.g. faked key events from virtual
  // keyboard), it's client's responsibility to set the dom key correctly.
  // Otherwise, set the dom key as unidentified.
  // Please refer to crbug.com/443889.
  if (character_ != 0) {
    key_ = DomKey::UNIDENTIFIED;
    return;
  }
  ui::DomCode code = code_;
  if (code == DomCode::NONE) {
    // Catch old code that tries to do layout without a physical key, and try
    // to recover using the KeyboardCode. Once key events are fully defined
    // on construction (see TODO in event.h) this will go away.
    LOG(WARNING) << "DomCode::NONE keycode=" << key_code_;
    code = UsLayoutKeyboardCodeToDomCode(key_code_);
    if (code == DomCode::NONE) {
      key_ = DomKey::UNIDENTIFIED;
      return;
    }
  }
  KeyboardCode dummy_key_code;
#if defined(OS_WIN)
// Native Windows character events always have is_char_ == true,
// so this is a synthetic or native keystroke event.
// Therefore, perform only the fallback action.
#elif defined(USE_X11)
  // 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.
  if (!IsControlDown() && native_event()) {
    GetMeaningFromXEvent(native_event(), &key_, &character_);
    return;
  }
#elif defined(USE_OZONE)
  if (KeyboardLayoutEngineManager::GetKeyboardLayoutEngine()->Lookup(
          code, flags(), &key_, &character_, &dummy_key_code,
          &platform_keycode_)) {
    return;
  }
#else
  if (native_event()) {
    DCHECK(EventTypeFromNative(native_event()) == ET_KEY_PRESSED ||
           EventTypeFromNative(native_event()) == ET_KEY_RELEASED);
  }
#endif
  if (!DomCodeToUsLayoutMeaning(code, flags(), &key_, &character_,
                                &dummy_key_code)) {
    key_ = DomKey::UNIDENTIFIED;
  }
}

DomKey KeyEvent::GetDomKey() const {
  // Determination of character_ and key_ may be done lazily.
  if (key_ == DomKey::NONE)
    ApplyLayout();
  return key_;
}

base::char16 KeyEvent::GetCharacter() const {
  // Determination of character_ and key_ may be done lazily.
  if (key_ == DomKey::NONE)
    ApplyLayout();
  return character_;
}

base::char16 KeyEvent::GetText() const {
  if ((flags() & EF_CONTROL_DOWN) != 0) {
    base::char16 character;
    ui::DomKey key;
    ui::KeyboardCode key_code;
    if (DomCodeToControlCharacter(code_, flags(), &key, &character, &key_code))
      return character;
  }
  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())
    return false;
  const int key = key_code();
  if (key >= VKEY_NUMPAD0 && key <= VKEY_NUMPAD9)
    return true;
  // Check whether the user is using the numeric keypad with num-lock off.
  // In that case, EF_EXTENDED will not be set; if it is set, the key event
  // originated from the relevant non-numpad dedicated key, e.g. [Insert].
  return (!(flags() & EF_EXTENDED) &&
          (key == VKEY_INSERT || key == VKEY_END  || key == VKEY_DOWN ||
           key == VKEY_NEXT   || key == VKEY_LEFT || key == VKEY_CLEAR ||
           key == VKEY_RIGHT  || key == VKEY_HOME || key == VKEY_UP ||
           key == VKEY_PRIOR));
#else
  return false;
#endif
}

void KeyEvent::NormalizeFlags() {
  int mask = 0;
  switch (key_code()) {
    case VKEY_CONTROL:
      mask = EF_CONTROL_DOWN;
      break;
    case VKEY_SHIFT:
      mask = EF_SHIFT_DOWN;
      break;
    case VKEY_MENU:
      mask = EF_ALT_DOWN;
      break;
    case VKEY_CAPITAL:
      mask = EF_CAPS_LOCK_DOWN;
      break;
    default:
      return;
  }
  if (type() == ET_KEY_PRESSED)
    set_flags(flags() | mask);
  else
    set_flags(flags() & ~mask);
}

KeyboardCode KeyEvent::GetLocatedWindowsKeyboardCode() const {
  return NonLocatedToLocatedKeyboardCode(key_code_, code_);
}

uint16 KeyEvent::GetConflatedWindowsKeyCode() const {
  if (is_char_)
    return character_;
  return key_code_;
}

std::string KeyEvent::GetCodeString() const {
  return KeycodeConverter::DomCodeToCodeString(code_);
}

////////////////////////////////////////////////////////////////////////////////
// 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(EventType type,
                         const gfx::PointF& location,
                         base::TimeDelta time_stamp,
                         int flags,
                         float x_offset,
                         float y_offset,
                         float x_offset_ordinal,
                         float y_offset_ordinal,
                         int finger_count)
    : MouseEvent(type, location, location, time_stamp, flags, 0),
      x_offset_(x_offset),
      y_offset_(y_offset),
      x_offset_ordinal_(x_offset_ordinal),
      y_offset_ordinal_(y_offset_ordinal),
      finger_count_(finger_count) {
  CHECK(IsScrollEvent());
}

void ScrollEvent::Scale(const float factor) {
  x_offset_ *= factor;
  y_offset_ *= factor;
  x_offset_ordinal_ *= factor;
  y_offset_ordinal_ *= factor;
}

////////////////////////////////////////////////////////////////////////////////
// GestureEvent

GestureEvent::GestureEvent(float x,
                           float y,
                           int flags,
                           base::TimeDelta time_stamp,
                           const GestureEventDetails& details)
    : LocatedEvent(details.type(),
                   gfx::PointF(x, y),
                   gfx::PointF(x, y),
                   time_stamp,
                   flags | EF_FROM_TOUCH),
      details_(details) {
}

GestureEvent::~GestureEvent() {
}

}  // namespace ui
