// 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/Xlib.h>
#include <X11/keysym.h>
#endif

#include <cmath>
#include <cstring>

#include "base/strings/stringprintf.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/gfx/point3_f.h"
#include "ui/gfx/point_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"
#endif

namespace ui {

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

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

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

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

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

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

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

  return scoped_ptr<Event>(new Event(event));
}

Event::~Event() {
}

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

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

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()
    : 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),
      cancelable_(true),
      target_(NULL),
      phase_(EP_PREDISPATCH),
      result_(ER_UNHANDLED),
      source_device_id_(ED_UNKNOWN_DEVICE) {
}

Event::Event(const Event& copy)
    : type_(copy.type_),
      time_stamp_(copy.time_stamp_),
      latency_(copy.latency_),
      flags_(copy.flags_),
      cancelable_(true),
      target_(NULL),
      phase_(EP_PREDISPATCH),
      result_(ER_UNHANDLED),
      source_device_id_(copy.source_device_id_) {
}

void Event::SetType(EventType type) {
  type_ = type;
}

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

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

CancelModeEvent::~CancelModeEvent() {
}

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

LocatedEvent::LocatedEvent() : Event() {
}

LocatedEvent::~LocatedEvent() {
}

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() : LocatedEvent(), changed_button_flags_(0) {
}

MouseEvent::MouseEvent(EventType type,
                       const gfx::PointF& location,
                       const gfx::PointF& root_location,
                       int flags,
                       int changed_button_flags)
    : LocatedEvent(type, location, root_location, EventTimeForNow(), 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;

  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;
}

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() : MouseEvent(), offset_() {
}

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,
                                 int flags,
                                 int changed_button_flags)
    : MouseEvent(ui::ET_MOUSEWHEEL, location, root_location, 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

void MouseWheelEvent::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]) {
    offset_.set_x(
        gfx::ToRoundedInt(SkMScalarToFloat(offset_.x() * decomp.scale[0])));
  }
  if (decomp.scale[1]) {
    offset_.set_y(
        gfx::ToRoundedInt(SkMScalarToFloat(offset_.y() * decomp.scale[1])));
  }
}

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

TouchEvent::TouchEvent()
    : LocatedEvent(),
      touch_id_(0),
      radius_x_(0),
      radius_y_(0),
      rotation_angle_(0),
      force_(0) {
}

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),
      radius_x_(0.0f),
      radius_y_(0.0f),
      rotation_angle_(0.0f),
      force_(0.0f) {
  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),
      radius_x_(radius_x),
      radius_y_(radius_y),
      rotation_angle_(angle),
      force_(force) {
  latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
}

TouchEvent::~TouchEvent() {
}

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];
}

////////////////////////////////////////////////////////////////////////////////
// KeyEvent

KeyEvent::KeyEvent()
    : Event(),
      key_code_(VKEY_UNKNOWN),
      code_(),
      is_char_(false),
      platform_keycode_(0),
      character_(0) {
}

KeyEvent::KeyEvent(EventType type,
                   KeyboardCode key_code,
                   int flags)
    : Event(type, EventTimeForNow(), flags),
      key_code_(key_code),
      is_char_(false),
      platform_keycode_(0),
      character_() {
}

KeyEvent::KeyEvent(EventType type,
                   KeyboardCode key_code,
                   const std::string& code,
                   int flags)
    : Event(type, EventTimeForNow(), flags),
      key_code_(key_code),
      code_(code),
      is_char_(false),
      platform_keycode_(0),
      character_(0) {
}

KeyEvent::KeyEvent(base::char16 character, KeyboardCode key_code, int flags)
    : Event(ET_KEY_PRESSED, EventTimeForNow(), flags),
      key_code_(key_code),
      code_(""),
      is_char_(true),
      platform_keycode_(0),
      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_),
      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_;
    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();
}

base::char16 KeyEvent::GetCharacter() const {
  if (is_char_ || character_)
    return character_;

  // TODO(kpschoedel): streamline these cases after settling Ozone
  // positional coding.
#if defined(OS_WIN)
  // Native Windows character events always have is_char_ == true,
  // so this is a synthetic or native keystroke event.
  character_ = GetCharacterFromKeyCode(key_code_, flags());
  return character_;
#elif defined(USE_X11)
  character_ = GetCharacterFromKeyCode(key_code_, flags());
  return character_;
#else
  return GetCharacterFromKeyCode(key_code_, flags());
#endif
}

base::char16 KeyEvent::GetText() const {
  if ((flags() & EF_CONTROL_DOWN) != 0) {
    return GetControlCharacterForKeycode(key_code_,
                                         (flags() & EF_SHIFT_DOWN) != 0);
  }
  return GetUnmodifiedText();
}

base::char16 KeyEvent::GetUnmodifiedText() const {
  if (!is_char_ && (key_code_ == VKEY_RETURN))
    return '\r';
  return GetCharacter();
}

bool KeyEvent::IsUnicodeKeyCode() const {
#if defined(OS_WIN)
  if (!IsAltDown())
    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);
}

bool KeyEvent::IsTranslated() const {
  switch (type()) {
    case ET_KEY_PRESSED:
    case ET_KEY_RELEASED:
      return false;
    case ET_TRANSLATED_KEY_PRESS:
    case ET_TRANSLATED_KEY_RELEASE:
      return true;
    default:
      NOTREACHED();
      return false;
  }
}

void KeyEvent::SetTranslated(bool translated) {
  switch (type()) {
    case ET_KEY_PRESSED:
    case ET_TRANSLATED_KEY_PRESS:
      SetType(translated ? ET_TRANSLATED_KEY_PRESS : ET_KEY_PRESSED);
      break;
    case ET_KEY_RELEASED:
    case ET_TRANSLATED_KEY_RELEASE:
      SetType(translated ? ET_TRANSLATED_KEY_RELEASE : ET_KEY_RELEASED);
      break;
    default:
      NOTREACHED();
  }
}

bool KeyEvent::IsRightSideKey() const {
  switch (key_code_) {
    case VKEY_CONTROL:
    case VKEY_SHIFT:
    case VKEY_MENU:
    case VKEY_LWIN:
#if defined(USE_X11)
      // Under X11, setting code_ requires platform-dependent information, and
      // currently assumes that X keycodes are based on Linux evdev keycodes.
      // In certain test environments this is not the case, and code_ is not
      // set accurately, so we need a different mechanism. Fortunately X11 key
      // mapping preserves the left-right distinction, so testing keysyms works
      // if the value is available (as it is for all X11 native-based events).
      if (platform_keycode_) {
        return (platform_keycode_ == XK_Shift_R) ||
               (platform_keycode_ == XK_Control_R) ||
               (platform_keycode_ == XK_Alt_R) ||
               (platform_keycode_ == XK_Meta_R) ||
               (platform_keycode_ == XK_Super_R) ||
               (platform_keycode_ == XK_Hyper_R);
      }
      // Fall through to the generic code if we have no platform_keycode_.
      // Under X11, this must be a synthetic event, so we can require that
      // code_ be set correctly.
#endif
      return ((code_.size() > 5) &&
              (code_.compare(code_.size() - 5, 5, "Right", 5)) == 0);
    default:
      return false;
  }
}

KeyboardCode KeyEvent::GetLocatedWindowsKeyboardCode() const {
  switch (key_code_) {
    case VKEY_SHIFT:
      return IsRightSideKey() ? VKEY_RSHIFT : VKEY_LSHIFT;
    case VKEY_CONTROL:
      return IsRightSideKey() ? VKEY_RCONTROL : VKEY_LCONTROL;
    case VKEY_MENU:
      return IsRightSideKey() ? VKEY_RMENU : VKEY_LMENU;
    case VKEY_LWIN:
      return IsRightSideKey() ? VKEY_RWIN : VKEY_LWIN;
    // TODO(kpschoedel): EF_NUMPAD_KEY is present only on X11. Currently this
    // function is only called on X11. Likely the tests here will be replaced
    // with a DOM-based code enumeration test in the course of Ozone
    // platform-indpendent key event work.
    case VKEY_0:
      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD0 : VKEY_0;
    case VKEY_1:
      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD1 : VKEY_1;
    case VKEY_2:
      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD2 : VKEY_2;
    case VKEY_3:
      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD3 : VKEY_3;
    case VKEY_4:
      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD4 : VKEY_4;
    case VKEY_5:
      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD5 : VKEY_5;
    case VKEY_6:
      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD6 : VKEY_6;
    case VKEY_7:
      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD7 : VKEY_7;
    case VKEY_8:
      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD8 : VKEY_8;
    case VKEY_9:
      return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD9 : VKEY_9;
    default:
      return key_code_;
  }
}

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

////////////////////////////////////////////////////////////////////////////////
// ScrollEvent

ScrollEvent::ScrollEvent() : MouseEvent() {
}

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, 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) {
  set_time_stamp(time_stamp);
  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
