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

#ifndef UI_EVENTS_EVENT_H_
#define UI_EVENTS_EVENT_H_

#include <stdint.h>

#include <memory>
#include <string>
#include <vector>

#include "base/compiler_specific.h"
#include "base/containers/flat_map.h"
#include "base/gtest_prod_util.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "ui/events/event_constants.h"
#include "ui/events/gesture_event_details.h"
#include "ui/events/gestures/gesture_types.h"
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/events/platform_event.h"
#include "ui/events/pointer_details.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/latency/latency_info.h"

namespace gfx {
class Transform;
}

namespace ui {
class CancelModeEvent;
class Event;
class EventTarget;
class KeyEvent;
class LocatedEvent;
class MouseEvent;
class MouseWheelEvent;
class ScrollEvent;
class TouchEvent;

enum class DomCode;

class EVENTS_EXPORT Event {
 public:
  using Properties = base::flat_map<std::string, std::vector<uint8_t>>;

  // Copies an arbitrary event. If you have a typed event (e.g. a MouseEvent)
  // just use its copy constructor.
  static std::unique_ptr<Event> Clone(const Event& event);

  virtual ~Event();

  class DispatcherApi {
   public:
    explicit DispatcherApi(Event* event) : event_(event) {}

    void set_target(EventTarget* target) {
      event_->target_ = target;
    }

    void set_phase(EventPhase phase) { event_->phase_ = phase; }
    void set_result(int result) {
      event_->result_ = static_cast<EventResult>(result);
    }
    void set_time_stamp(base::TimeTicks time) { event_->time_stamp_ = time; }

   private:
    Event* event_;

    DISALLOW_COPY_AND_ASSIGN(DispatcherApi);
  };

  const PlatformEvent& native_event() const { return native_event_; }
  EventType type() const { return type_; }
  // time_stamp represents time since machine was booted.
  const base::TimeTicks time_stamp() const { return time_stamp_; }
  int flags() const { return flags_; }

  // Returns a name for the event, typically used in logging/debugging. This is
  // a convenience for EventTypeName(type()) (EventTypeName() is in
  // event_utils).
  const char* GetName() const;

  // This is only intended to be used externally by classes that are modifying
  // events in an EventRewriter.
  void set_flags(int flags) { flags_ = flags; }

  EventTarget* target() const { return target_; }
  EventPhase phase() const { return phase_; }
  EventResult result() const { return result_; }

  LatencyInfo* latency() { return &latency_; }
  const LatencyInfo* latency() const { return &latency_; }
  void set_latency(const LatencyInfo& latency) { latency_ = latency; }

  int source_device_id() const { return source_device_id_; }
  void set_source_device_id(int id) { source_device_id_ = id; }

  // Sets the properties associated with this Event.
  void SetProperties(const Properties& properties);

  // Returns the properties associated with this event, which may be null.
  // The properties are meant to provide a way to associate arbitrary key/value
  // pairs with Events and not used by Event.
  const Properties* properties() const { return properties_.get(); }

  // By default, events are "cancelable", this means any default processing that
  // the containing abstraction layer may perform can be prevented by calling
  // SetHandled(). SetHandled() or StopPropagation() must not be called for
  // events that are not cancelable.
  bool cancelable() const { return cancelable_; }

  // The following methods return true if the respective keys were pressed at
  // the time the event was created.
  bool IsShiftDown() const { return (flags_ & EF_SHIFT_DOWN) != 0; }
  bool IsControlDown() const { return (flags_ & EF_CONTROL_DOWN) != 0; }
  bool IsAltDown() const { return (flags_ & EF_ALT_DOWN) != 0; }
  bool IsCommandDown() const { return (flags_ & EF_COMMAND_DOWN) != 0; }
  bool IsAltGrDown() const { return (flags_ & EF_ALTGR_DOWN) != 0; }
  bool IsCapsLockOn() const { return (flags_ & EF_CAPS_LOCK_ON) != 0; }

  bool IsSynthesized() const { return (flags_ & EF_IS_SYNTHESIZED) != 0; }

  bool IsCancelModeEvent() const {
    return type_ == ET_CANCEL_MODE;
  }

  bool IsKeyEvent() const {
    return type_ == ET_KEY_PRESSED || type_ == ET_KEY_RELEASED;
  }

  bool IsMouseEvent() const {
    return type_ == ET_MOUSE_PRESSED ||
           type_ == ET_MOUSE_DRAGGED ||
           type_ == ET_MOUSE_RELEASED ||
           type_ == ET_MOUSE_MOVED ||
           type_ == ET_MOUSE_ENTERED ||
           type_ == ET_MOUSE_EXITED ||
           type_ == ET_MOUSEWHEEL ||
           type_ == ET_MOUSE_CAPTURE_CHANGED;
  }

  bool IsTouchEvent() const {
    return type_ == ET_TOUCH_RELEASED ||
           type_ == ET_TOUCH_PRESSED ||
           type_ == ET_TOUCH_MOVED ||
           type_ == ET_TOUCH_CANCELLED;
  }

  bool IsGestureEvent() const {
    switch (type_) {
      case ET_GESTURE_SCROLL_BEGIN:
      case ET_GESTURE_SCROLL_END:
      case ET_GESTURE_SCROLL_UPDATE:
      case ET_GESTURE_TAP:
      case ET_GESTURE_DOUBLE_TAP:
      case ET_GESTURE_TAP_CANCEL:
      case ET_GESTURE_TAP_DOWN:
      case ET_GESTURE_TAP_UNCONFIRMED:
      case ET_GESTURE_BEGIN:
      case ET_GESTURE_END:
      case ET_GESTURE_TWO_FINGER_TAP:
      case ET_GESTURE_PINCH_BEGIN:
      case ET_GESTURE_PINCH_END:
      case ET_GESTURE_PINCH_UPDATE:
      case ET_GESTURE_LONG_PRESS:
      case ET_GESTURE_LONG_TAP:
      case ET_GESTURE_SWIPE:
      case ET_GESTURE_SHOW_PRESS:
        // When adding a gesture event which is paired with an event which
        // occurs earlier, add the event to |IsEndingEvent|.
        return true;

      case ET_SCROLL_FLING_CANCEL:
      case ET_SCROLL_FLING_START:
        // These can be ScrollEvents too. EF_FROM_TOUCH determines if they're
        // Gesture or Scroll events.
        return (flags_ & EF_FROM_TOUCH) == EF_FROM_TOUCH;

      default:
        break;
    }
    return false;
  }

  // An ending event is paired with the event which started it. Setting capture
  // should not prevent ending events from getting to their initial target.
  bool IsEndingEvent() const {
    switch(type_) {
      case ui::ET_TOUCH_CANCELLED:
      case ui::ET_GESTURE_TAP_CANCEL:
      case ui::ET_GESTURE_END:
      case ui::ET_GESTURE_SCROLL_END:
      case ui::ET_GESTURE_PINCH_END:
        return true;
      default:
        return false;
    }
  }

  bool IsScrollEvent() const {
    // Flings can be GestureEvents too. EF_FROM_TOUCH determines if they're
    // Gesture or Scroll events.
    return type_ == ET_SCROLL ||
           ((type_ == ET_SCROLL_FLING_START ||
           type_ == ET_SCROLL_FLING_CANCEL) &&
           !(flags() & EF_FROM_TOUCH));
  }

  bool IsPinchEvent() const {
    return type_ == ET_GESTURE_PINCH_BEGIN ||
           type_ == ET_GESTURE_PINCH_UPDATE || type_ == ET_GESTURE_PINCH_END;
  }

  bool IsScrollGestureEvent() const {
    return type_ == ET_GESTURE_SCROLL_BEGIN ||
           type_ == ET_GESTURE_SCROLL_UPDATE ||
           type_ == ET_GESTURE_SCROLL_END;
  }

  bool IsFlingScrollEvent() const {
    return type_ == ET_SCROLL_FLING_CANCEL ||
           type_ == ET_SCROLL_FLING_START;
  }

  bool IsMouseWheelEvent() const {
    return type_ == ET_MOUSEWHEEL;
  }

  bool IsLocatedEvent() const {
    return IsMouseEvent() || IsScrollEvent() || IsTouchEvent() ||
           IsGestureEvent();
  }

  // Convenience methods to cast |this| to a CancelModeEvent.
  // IsCancelModeEvent() must be true as a precondition to calling these
  // methods.
  CancelModeEvent* AsCancelModeEvent();
  const CancelModeEvent* AsCancelModeEvent() const;

  // Convenience methods to cast |this| to a GestureEvent. IsGestureEvent()
  // must be true as a precondition to calling these methods.
  GestureEvent* AsGestureEvent();
  const GestureEvent* AsGestureEvent() const;

  // Convenience methods to cast |this| to a KeyEvent. IsKeyEvent()
  // must be true as a precondition to calling these methods.
  KeyEvent* AsKeyEvent();
  const KeyEvent* AsKeyEvent() const;

  // Convenience methods to cast |this| to a LocatedEvent. IsLocatedEvent()
  // must be true as a precondition to calling these methods.
  LocatedEvent* AsLocatedEvent();
  const LocatedEvent* AsLocatedEvent() const;

  // Convenience methods to cast |this| to a MouseEvent. IsMouseEvent()
  // must be true as a precondition to calling these methods.
  MouseEvent* AsMouseEvent();
  const MouseEvent* AsMouseEvent() const;

  // Convenience methods to cast |this| to a MouseWheelEvent.
  // IsMouseWheelEvent() must be true as a precondition to calling these
  // methods.
  MouseWheelEvent* AsMouseWheelEvent();
  const MouseWheelEvent* AsMouseWheelEvent() const;

  // Convenience methods to cast |this| to a ScrollEvent. IsScrollEvent()
  // must be true as a precondition to calling these methods.
  ScrollEvent* AsScrollEvent();
  const ScrollEvent* AsScrollEvent() const;

  // Convenience methods to cast |this| to a TouchEvent. IsTouchEvent()
  // must be true as a precondition to calling these methods.
  TouchEvent* AsTouchEvent();
  const TouchEvent* AsTouchEvent() 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.
  // Note that StopPropagation() can be called only for cancelable events.
  void StopPropagation();
  bool stopped_propagation() const { return !!(result_ & ER_CONSUMED); }

  // Marks the event as having been handled. A handled event does not reach the
  // next event phase. For example, if an event is handled during the pre-target
  // phase, then the event is dispatched to all pre-target handlers, but not to
  // the target or post-target handlers.
  // Note that SetHandled() can be called only for cancelable events.
  void SetHandled();
  bool handled() const { return result_ != ER_UNHANDLED; }

  // For debugging. Not a stable serialization format.
  virtual std::string ToString() const;

 protected:
  Event(EventType type, base::TimeTicks time_stamp, int flags);
  Event(const PlatformEvent& native_event, EventType type, int flags);
  Event(const Event& copy);
  Event& operator=(const Event& rhs);

  void SetType(EventType type);
  void set_cancelable(bool cancelable) { cancelable_ = cancelable; }

  void set_time_stamp(base::TimeTicks time_stamp) {
    time_stamp_ = time_stamp;
  }

 private:
  friend class EventTestApi;

  EventType type_;
  base::TimeTicks time_stamp_;
  LatencyInfo latency_;
  int flags_;
  PlatformEvent native_event_;
  bool delete_native_event_;
  bool cancelable_;
  EventTarget* target_;
  EventPhase phase_;
  EventResult result_;

  // The device id the event came from, or ED_UNKNOWN_DEVICE if the information
  // is not available.
  int source_device_id_;

  std::unique_ptr<Properties> properties_;
};

class EVENTS_EXPORT CancelModeEvent : public Event {
 public:
  CancelModeEvent();
  ~CancelModeEvent() override;
};

class EVENTS_EXPORT LocatedEvent : public Event {
 public:
  // Convenience function that casts |event| to a LocatedEvent if it is one,
  // otherwise returns null.
  static const ui::LocatedEvent* FromIfValid(const ui::Event* event) {
    return event && event->IsLocatedEvent() ? event->AsLocatedEvent() : nullptr;
  }

  ~LocatedEvent() override;

  float x() const { return location_.x(); }
  float y() const { return location_.y(); }
  void set_location(const gfx::Point& location) {
    location_ = gfx::PointF(location);
  }
  void set_location_f(const gfx::PointF& location) { location_ = location; }
  gfx::Point location() const { return gfx::ToFlooredPoint(location_); }
  const gfx::PointF& location_f() const { return location_; }
  void set_root_location(const gfx::Point& root_location) {
    root_location_ = gfx::PointF(root_location);
  }
  void set_root_location_f(const gfx::PointF& root_location) {
    root_location_ = root_location;
  }
  gfx::Point root_location() const {
    return gfx::ToFlooredPoint(root_location_);
  }
  const gfx::PointF& root_location_f() const {
    return root_location_;
  }

  // Transform the locations using |inverted_root_transform| and
  // |inverted_local_transform|. |inverted_local_transform| is only used if
  // the event has a target.
  virtual void UpdateForRootTransform(
      const gfx::Transform& inverted_root_transform,
      const gfx::Transform& inverted_local_transform);

  template <class T>
  void ConvertLocationToTarget(const T* source, const T* target) {
    if (!target || target == source)
      return;
    gfx::Point offset = gfx::ToFlooredPoint(location_);
    T::ConvertPointToTarget(source, target, &offset);
    gfx::Vector2d diff = gfx::ToFlooredPoint(location_) - offset;
    location_ = location_ - diff;
  }

  // Event:
  std::string ToString() const override;

 protected:
  friend class LocatedEventTestApi;

  LocatedEvent(const LocatedEvent& copy);

  explicit LocatedEvent(const PlatformEvent& native_event);

  // Create a new LocatedEvent which is identical to the provided model.
  // If source / target windows are provided, the model location will be
  // converted from |source| coordinate system to |target| coordinate system.
  template <class T>
  LocatedEvent(const LocatedEvent& model, T* source, T* target)
      : Event(model),
        location_(model.location_),
        root_location_(model.root_location_) {
    ConvertLocationToTarget(source, target);
  }

  // Used for synthetic events in testing.
  LocatedEvent(EventType type,
               const gfx::PointF& location,
               const gfx::PointF& root_location,
               base::TimeTicks time_stamp,
               int flags);

  // Location of the event relative to the target window and in the target
  // window's coordinate space. If there is no target this is the same as
  // |root_location_|. Native events may generate float values with sub-pixel
  // precision.
  gfx::PointF location_;

  // Location of the event. What coordinate system this is in depends upon the
  // phase of event dispatch. For client code (meaning EventHandlers) it is
  // generally in screen coordinates, but early on it may be in pixels and
  // relative to a display. Native events may generate float values with
  // sub-pixel precision.
  gfx::PointF root_location_;
};

class EVENTS_EXPORT MouseEvent : public LocatedEvent {
 public:
  // NOTE: On some platforms this will allow an event to be constructed from a
  // void*, see PlatformEvent.
  explicit MouseEvent(const PlatformEvent& native_event);

  // Create a new MouseEvent based on the provided model.
  // Uses the provided |type| and |flags| for the new event.
  // If source / target windows are provided, the model location will be
  // converted from |source| coordinate system to |target| coordinate system.
  template <class T>
  MouseEvent(const MouseEvent& model, T* source, T* target)
      : LocatedEvent(model, source, target),
        changed_button_flags_(model.changed_button_flags_),
        pointer_details_(model.pointer_details_) {}

  template <class T>
  MouseEvent(const MouseEvent& model,
             T* source,
             T* target,
             EventType type,
             int flags)
      : LocatedEvent(model, source, target),
        changed_button_flags_(model.changed_button_flags_),
        pointer_details_(model.pointer_details_) {
    SetType(type);
    set_flags(flags);
  }

  // Note: Use the ctor for MouseWheelEvent if type is ET_MOUSEWHEEL.
  MouseEvent(EventType type,
             const gfx::PointF& location,
             const gfx::PointF& root_location,
             base::TimeTicks time_stamp,
             int flags,
             int changed_button_flags,
             const PointerDetails& pointer_details =
                 PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
                                kPointerIdMouse));

  // DEPRECATED: Prefer constructor that takes gfx::PointF.
  MouseEvent(EventType type,
             const gfx::Point& location,
             const gfx::Point& root_location,
             base::TimeTicks time_stamp,
             int flags,
             int changed_button_flags,
             const PointerDetails& pointer_details =
                 PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
                                kPointerIdMouse));

  MouseEvent(const MouseEvent& copy);
  ~MouseEvent() override;

  class DispatcherApi {
   public:
    explicit DispatcherApi(MouseEvent* event) : event_(event) {}

    // TODO(eirage): convert this to builder pattern.
    void set_movement(const gfx::Vector2dF& movement) {
      event_->movement_ = movement;
      event_->set_flags(event_->flags() | EF_UNADJUSTED_MOUSE);
    }

   private:
    MouseEvent* event_;

    DISALLOW_COPY_AND_ASSIGN(DispatcherApi);
  };

  // Conveniences to quickly test what button is down
  bool IsOnlyLeftMouseButton() const {
    return button_flags() == EF_LEFT_MOUSE_BUTTON;
  }

  bool IsLeftMouseButton() const {
    return (flags() & EF_LEFT_MOUSE_BUTTON) != 0;
  }

  bool IsOnlyMiddleMouseButton() const {
    return button_flags() == EF_MIDDLE_MOUSE_BUTTON;
  }

  bool IsMiddleMouseButton() const {
    return (flags() & EF_MIDDLE_MOUSE_BUTTON) != 0;
  }

  bool IsOnlyRightMouseButton() const {
    return button_flags() == EF_RIGHT_MOUSE_BUTTON;
  }

  bool IsRightMouseButton() const {
    return (flags() & EF_RIGHT_MOUSE_BUTTON) != 0;
  }

  bool IsAnyButton() const {
    return button_flags() != 0;
  }

  // Returns the flags for the mouse buttons.
  int button_flags() const {
    return flags() & (EF_LEFT_MOUSE_BUTTON | EF_MIDDLE_MOUSE_BUTTON |
                      EF_RIGHT_MOUSE_BUTTON | EF_BACK_MOUSE_BUTTON |
                      EF_FORWARD_MOUSE_BUTTON);
  }

  // Compares two mouse down events and returns true if the second one should
  // be considered a repeat of the first.
  static bool IsRepeatedClickEvent(
      const MouseEvent& event1,
      const MouseEvent& event2);

  // Get the click count. Can be 1, 2 or 3 for mousedown messages, 0 otherwise.
  int GetClickCount() const;

  // Set the click count for a mousedown message. Can be 1, 2 or 3.
  void SetClickCount(int click_count);

  // Identifies the button that changed. During a press this corresponds to the
  // button that was pressed and during a release this corresponds to the button
  // that was released.
  // NOTE: during a press and release flags() contains the complete set of
  // flags. Use this to determine the button that was pressed or released.
  int changed_button_flags() const { return changed_button_flags_; }

  // Updates the button that changed.
  void set_changed_button_flags(int flags) { changed_button_flags_ = flags; }

  const gfx::Vector2dF& movement() const { return movement_; }

  const PointerDetails& pointer_details() const { return pointer_details_; }

 private:
  FRIEND_TEST_ALL_PREFIXES(EventTest, DoubleClickRequiresUniqueTimestamp);
  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();

  // See description above getter for details.
  int changed_button_flags_;

  // Raw mouse movement value reported from mouse hardware. The value of this is
  // platform dependent and may change depending upon the hardware connected to
  // the device. This field is only set if the flag EF_UNADJUSTED_MOUSE is
  // present.
  gfx::Vector2dF movement_;

  // The most recent user-generated MouseEvent, used to detect double clicks.
  static MouseEvent* last_click_event_;

  // Structure for holding pointer details for implementing PointerEvents API.
  PointerDetails pointer_details_;
};

class ScrollEvent;

class EVENTS_EXPORT MouseWheelEvent : public MouseEvent {
 public:
  // See |offset| for details.
  static const int kWheelDelta;

  explicit MouseWheelEvent(const PlatformEvent& native_event);
  explicit MouseWheelEvent(const ScrollEvent& scroll_event);
  MouseWheelEvent(const MouseEvent& mouse_event, int x_offset, int y_offset);
  MouseWheelEvent(const MouseWheelEvent& copy);
  ~MouseWheelEvent() override;

  template <class T>
  MouseWheelEvent(const MouseWheelEvent& model,
                  T* source,
                  T* target)
      : MouseEvent(model, source, target, model.type(), model.flags()),
        offset_(model.x_offset(), model.y_offset()) {
  }

  // Used for synthetic events in testing and by the gesture recognizer.
  MouseWheelEvent(const gfx::Vector2d& offset,
                  const gfx::PointF& location,
                  const gfx::PointF& root_location,
                  base::TimeTicks time_stamp,
                  int flags,
                  int changed_button_flags);

  // DEPRECATED: Prefer the constructor that takes gfx::PointF.
  MouseWheelEvent(const gfx::Vector2d& offset,
                  const gfx::Point& location,
                  const gfx::Point& root_location,
                  base::TimeTicks time_stamp,
                  int flags,
                  int changed_button_flags);

  // The amount to scroll. This is in multiples of kWheelDelta.
  // Note: x_offset() > 0/y_offset() > 0 means scroll left/up.
  int x_offset() const { return offset_.x(); }
  int y_offset() const { return offset_.y(); }
  const gfx::Vector2d& offset() const { return offset_; }

 private:
  gfx::Vector2d offset_;
};

// NOTE: Pen (stylus) events use TouchEvent with POINTER_TYPE_PEN. They were
// originally implemented as MouseEvent but switched to TouchEvent when UX
// decided not to show hover effects for pen.
class EVENTS_EXPORT TouchEvent : public LocatedEvent {
 public:
  explicit TouchEvent(const PlatformEvent& native_event);

  // Create a new TouchEvent which is identical to the provided model.
  // If source / target windows are provided, the model location will be
  // converted from |source| coordinate system to |target| coordinate system.
  template <class T>
  TouchEvent(const TouchEvent& model, T* source, T* target)
      : LocatedEvent(model, source, target),
        unique_event_id_(model.unique_event_id_),
        may_cause_scrolling_(model.may_cause_scrolling_),
        hovering_(false),
        pointer_details_(model.pointer_details_) {}

  TouchEvent(EventType type,
             const gfx::PointF& location,
             const gfx::PointF& root_location,
             base::TimeTicks time_stamp,
             const PointerDetails& pointer_details,
             int flags = 0);

  // DEPRECATED: Prefer the constructor that takes gfx::PointF.
  TouchEvent(EventType type,
             const gfx::Point& location,
             base::TimeTicks time_stamp,
             const PointerDetails& pointer_details,
             int flags = 0);

  TouchEvent(const TouchEvent& copy);

  ~TouchEvent() override;

  // A unique identifier for this event.
  uint32_t unique_event_id() const { return unique_event_id_; }

  void set_may_cause_scrolling(bool causes) { may_cause_scrolling_ = causes; }
  bool may_cause_scrolling() const { return may_cause_scrolling_; }

  void set_hovering(bool hovering) { hovering_ = hovering; }
  bool hovering() const { return hovering_; }

  // Overridden from LocatedEvent.
  void UpdateForRootTransform(
      const gfx::Transform& inverted_root_transform,
      const gfx::Transform& inverted_local_transform) override;

  // Marks the event as not participating in synchronous gesture recognition.
  void DisableSynchronousHandling();
  bool synchronous_handling_disabled() const {
    return !!(result() & ER_DISABLE_SYNC_HANDLING);
  }

  const PointerDetails& pointer_details() const { return pointer_details_; }
  void SetPointerDetailsForTest(const PointerDetails& pointer_details);

  float ComputeRotationAngle() const;

 private:
  // A unique identifier for the touch event.
  // NOTE: this is *not* serialized over mojom, as the number is unique to
  // a particular process, and as mojom may go cross process, to serialize could
  // lead to conflicts.
  uint32_t unique_event_id_;

  // Whether the (unhandled) touch event will produce a scroll event (e.g., a
  // touchmove that exceeds the platform slop region, or a touchend that
  // causes a fling). Defaults to false.
  bool may_cause_scrolling_;

  // True for devices like some pens when they support hovering over
  // digitizer and they send events while hovering.
  bool hovering_;

  // Structure for holding pointer details for implementing PointerEvents API.
  PointerDetails pointer_details_;
};

// A KeyEvent is really two distinct classes, melded together due to the
// DOM legacy of Windows key events: a keystroke event (is_char_ == false),
// or a character event (is_char_ == true).
//
// For a keystroke event,
// -- |bool is_char_| is false.
// -- |EventType Event::type()| can be ET_KEY_PRESSED or ET_KEY_RELEASED.
// -- |DomCode code_| and |int Event::flags()| represent the physical key event.
//    - code_ is a platform-independent representation of the physical key,
//      based on DOM UI Events KeyboardEvent |code| values. It does not
//      vary depending on key layout.
//      http://www.w3.org/TR/DOM-Level-3-Events-code/
//    - Event::flags() provides the active modifiers for the physical key
//      press. Its value reflects the state after the event; that is, for
//      a modifier key, a press includes the corresponding flag and a release
//      does not.
// -- |DomKey key_| provides the meaning (character or action) of the key
//    event, in the context of the active layout and modifiers. It corresponds
//    to DOM UI Events KeyboardEvent |key| values.
//    http://www.w3.org/TR/DOM-Level-3-Events-key/
// -- |KeyboardCode key_code_| supports the legacy web event |keyCode| field,
//    and its VKEY_ values are chosen to match Windows/IE for compatibility.
//    For printable characters, this may or may not be a layout-mapped value,
//    imitating MS Windows: if the mapped key generates a character that has
//    an associated VKEY_ code, then key_code_ is that code; if not, then
//    key_code_ is the unmapped VKEY_ code. For example, US, Greek, Cyrillic,
//    Japanese, etc. all use VKEY_Q for the key beside Tab, while French uses
//    VKEY_A. The stored key_code_ is non-located (e.g. VKEY_SHIFT rather than
//    VKEY_LSHIFT, VKEY_1 rather than VKEY_NUMPAD1).
//
// For a character event,
// -- |bool is_char_| is true.
// -- |EventType Event::type()| is ET_KEY_PRESSED.
// -- |DomCode code_| is DomCode::NONE.
// -- |DomKey key_| is a UTF-16 code point.
// -- |KeyboardCode key_code_| is conflated with the character-valued key_
//    by some code, because both arrive in the wParam field of a Windows event.
//
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 PlatformEvent& native_event);

  // Create a KeyEvent from a NativeEvent but with mocked flags.
  // This method is necessary for Windows since MSG does not contain all flags.
  KeyEvent(const PlatformEvent& native_event, int event_flags);

  // Create a keystroke event from a legacy KeyboardCode.
  // This should not be used in new code.
  KeyEvent(EventType type,
           KeyboardCode key_code,
           int flags,
           base::TimeTicks time_stamp = base::TimeTicks());

  // Create a fully defined keystroke event.
  KeyEvent(EventType type,
           KeyboardCode key_code,
           DomCode code,
           int flags,
           DomKey key,
           base::TimeTicks time_stamp,
           bool is_char = false);

  // Create a character event.
  KeyEvent(base::char16 character,
           KeyboardCode key_code,
           DomCode code,
           int flags,
           base::TimeTicks time_stamp = base::TimeTicks());

  // Used for synthetic events with code of DOM KeyboardEvent (e.g. 'KeyA')
  // See also: ui/events/keycodes/dom/dom_values.txt
  KeyEvent(EventType type,
           KeyboardCode key_code,
           DomCode code,
           int flags);

  KeyEvent(const KeyEvent& rhs);

  KeyEvent& operator=(const KeyEvent& rhs);

  ~KeyEvent() override;

  // This bypasses the normal mapping from keystroke events to characters,
  // which allows an I18N virtual keyboard to fabricate a keyboard event that
  // does not have a corresponding KeyboardCode (example: U+00E1 Latin small
  // letter A with acute, U+0410 Cyrillic capital letter A).
  void set_character(base::char16 character) {
    key_ = DomKey::FromCharacter(character);
  }

  // Gets the character generated by this key event. It only supports Unicode
  // BMP characters.
  base::char16 GetCharacter() const;

  // If this is a keystroke event with key_code_ VKEY_RETURN, returns '\r';
  // otherwise returns the same as GetCharacter().
  base::char16 GetUnmodifiedText() const;

  // If the Control key is down in the event, returns a layout-independent
  // character (corresponding to US layout); otherwise returns the same
  // as GetUnmodifiedText().
  base::char16 GetText() const;

  // True if this is a character event, false if this is a keystroke event.
  bool is_char() const { return is_char_; }

  bool is_repeat() const { return (flags() & EF_IS_REPEAT) != 0; }

  // Gets the associated (Windows-based) KeyboardCode for this key event.
  // Historically, this has also been used to obtain the character associated
  // with a character event, because both use the Window message 'wParam' field.
  // This should be avoided; if necessary for backwards compatibility, use
  // GetConflatedWindowsKeyCode().
  KeyboardCode key_code() const { return key_code_; }

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

  // Returns the same value as key_code(), except that located codes are
  // returned in place of non-located ones (e.g. VKEY_LSHIFT or VKEY_RSHIFT
  // instead of VKEY_SHIFT). This is a hybrid of semantic and physical
  // for legacy DOM reasons.
  KeyboardCode GetLocatedWindowsKeyboardCode() const;

  // For a keystroke event, returns the same value as key_code().
  // For a character event, returns the same value as GetCharacter().
  // This exists for backwards compatibility with Windows key events.
  uint16_t GetConflatedWindowsKeyCode() const;

  // Returns true for [Alt]+<num-pad digit> Unicode alt key codes used by Win.
  // TODO(msw): Additional work may be needed for analogues on other platforms.
  bool IsUnicodeKeyCode() const;

  // Returns the DOM .code (physical key identifier) for a keystroke event.
  DomCode code() const { return code_; }
  std::string GetCodeString() const;

  // Returns the DOM .key (layout meaning) for a keystroke event.
  DomKey GetDomKey() const;

  // Normalizes flags_ so that it describes the state after the event.
  // (Native X11 event flags describe the state before the event.)
  void NormalizeFlags();

 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:
  // Determine key_ on a keystroke event from code_ and flags().
  void ApplyLayout() const;

  // Tells if this is a repeated KeyEvent based on |last_key_event|, which is
  // then updated with the new last KeyEvent address.
  bool IsRepeated(KeyEvent** last_key_event);

  KeyboardCode key_code_;

  // DOM KeyboardEvent |code| (e.g. DomCode::US_A, DomCode::SPACE).
  // http://www.w3.org/TR/DOM-Level-3-Events-code/
  //
  // This value represents the physical position in the keyboard and can be
  // converted from / to keyboard scan code like XKB.
  DomCode code_;

  // True if this is a character event, false if this is a keystroke event.
  bool is_char_ = false;

  // TODO(kpschoedel): refactor so that key_ is not mutable.
  // This requires defining the KeyEvent completely at construction rather
  // than lazily under GetCharacter(), which likely also means removing
  // the two 'incomplete' constructors. crbug.com/444045
  //
  // DOM KeyboardEvent |key|
  // http://www.w3.org/TR/DOM-Level-3-Events-key/
  //
  // This value represents the meaning of a key, which is either a Unicode
  // character, or a named DomKey:: value.
  // This is not necessarily initialized when the event is constructed;
  // it may be set only if and when GetCharacter() or GetDomKey() is called.
  mutable DomKey key_ = DomKey::NONE;

  static KeyEvent* last_key_event_;
#if defined(USE_X11)
  static KeyEvent* last_ibus_key_event_;
#endif
};

class EVENTS_EXPORT ScrollEvent : public MouseEvent {
 public:
  explicit ScrollEvent(const PlatformEvent& native_event);

  template <class T>
  ScrollEvent(const ScrollEvent& model, T* source, T* target)
      : MouseEvent(model, source, target),
        x_offset_(model.x_offset_),
        y_offset_(model.y_offset_),
        x_offset_ordinal_(model.x_offset_ordinal_),
        y_offset_ordinal_(model.y_offset_ordinal_),
        finger_count_(model.finger_count_),
        momentum_phase_(model.momentum_phase_),
        scroll_event_phase_(model.scroll_event_phase_) {}

  ScrollEvent(EventType type,
              const gfx::PointF& location,
              const gfx::PointF& root_location,
              base::TimeTicks time_stamp,
              int flags,
              float x_offset,
              float y_offset,
              float x_offset_ordinal,
              float y_offset_ordinal,
              int finger_count,
              EventMomentumPhase momentum_phase = EventMomentumPhase::NONE,
              ScrollEventPhase phase = ScrollEventPhase::kNone);

  // DEPRECATED: Prefer the constructor that takes gfx::PointF.
  ScrollEvent(EventType type,
              const gfx::Point& location,
              base::TimeTicks time_stamp,
              int flags,
              float x_offset,
              float y_offset,
              float x_offset_ordinal,
              float y_offset_ordinal,
              int finger_count,
              EventMomentumPhase momentum_phase = EventMomentumPhase::NONE,
              ScrollEventPhase phase = ScrollEventPhase::kNone);

  ScrollEvent(const ScrollEvent& copy);
  ~ScrollEvent() override;

  // Scale the scroll event's offset value.
  // This is useful in the multi-monitor setup where it needs to be scaled
  // to provide a consistent user experience.
  void Scale(const float factor);

  float x_offset() const { return x_offset_; }
  float y_offset() const { return y_offset_; }
  float x_offset_ordinal() const { return x_offset_ordinal_; }
  float y_offset_ordinal() const { return y_offset_ordinal_; }
  int finger_count() const { return finger_count_; }
  EventMomentumPhase momentum_phase() const { return momentum_phase_; }
  ScrollEventPhase scroll_event_phase() const { return scroll_event_phase_; }

  // Event:
  std::string ToString() const override;

 private:
  // Potential accelerated offsets.
  float x_offset_;
  float y_offset_;
  // Unaccelerated offsets.
  float x_offset_ordinal_;
  float y_offset_ordinal_;
  // Number of fingers on the pad.
  int finger_count_;

  // For non-fling events, provides momentum information (e.g. for the case
  // where the device provides continuous event updates during a fling).
  EventMomentumPhase momentum_phase_ = EventMomentumPhase::NONE;

  // Provides phase information if device can provide.
  ScrollEventPhase scroll_event_phase_ = ScrollEventPhase::kNone;
};

class EVENTS_EXPORT GestureEvent : public LocatedEvent {
 public:
    // The constructor takes a default unique_touch_id of zero to support many
    // (80+) existing tests that doesn't care about this id.
  GestureEvent(float x,
               float y,
               int flags,
               base::TimeTicks time_stamp,
               const GestureEventDetails& details,
               uint32_t unique_touch_event_id = 0);

  // Create a new GestureEvent which is identical to the provided model.
  // If source / target windows are provided, the model location will be
  // converted from |source| coordinate system to |target| coordinate system.
  template <typename T>
  GestureEvent(const GestureEvent& model, T* source, T* target)
      : LocatedEvent(model, source, target),
        details_(model.details_) {
  }
  GestureEvent(const GestureEvent& copy);
  ~GestureEvent() override;

  const GestureEventDetails& details() const { return details_; }

  uint32_t unique_touch_event_id() const {
    return unique_touch_event_id_;
  }

 private:
  GestureEventDetails details_;

  // The unique id of the touch event that caused the gesture event to be
  // dispatched. This field gets a non-zero value only for gestures that are
  // released through TouchDispositionGestureFilter::SendGesture. The gesture
  // events that aren't fired directly in response to processing a touch-event
  // (e.g. timer fired ones), this id is zero. See crbug.com/618738.
  uint32_t unique_touch_event_id_;
};

}  // namespace ui

#endif  // UI_EVENTS_EVENT_H_
