// 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 #include #include #include #include "base/containers/flat_map.h" #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" #include "base/time/time.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/events/types/event_type.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>; // Copies an arbitrary event. If you have a typed event (e.g. a MouseEvent) // just use its copy constructor. static std::unique_ptr Clone(const Event& event); virtual ~Event(); class DispatcherApi { public: explicit DispatcherApi(Event* event) : event_(event) {} DispatcherApi(const DispatcherApi&) = delete; DispatcherApi& operator=(const DispatcherApi&) = delete; 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(result); } void set_time_stamp(base::TimeTicks time) { event_->time_stamp_ = time; } private: raw_ptr event_; }; void SetNativeEvent(const PlatformEvent& event); 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 ET_TOUCH_CANCELLED: case ET_GESTURE_TAP_CANCEL: case ET_GESTURE_END: case ET_GESTURE_SCROLL_END: case 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_ = false; bool cancelable_ = true; // Neither Event copy constructor nor the assignment operator copies // `target_`, as `target_` should be explicitly set so the setter will be // responsible for tracking it. raw_ptr target_ = nullptr; EventPhase phase_ = EP_PREDISPATCH; EventResult result_ = ER_UNHANDLED; // The device id the event came from, or ED_UNKNOWN_DEVICE if the information // is not available. int source_device_id_ = ED_UNKNOWN_DEVICE; std::unique_ptr 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 LocatedEvent* FromIfValid(const 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 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 overrides. 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 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 MouseEvent(const MouseEvent& model, T* source, T* target) : LocatedEvent(model, source, target), changed_button_flags_(model.changed_button_flags_), movement_(model.movement_), pointer_details_(model.pointer_details_) {} template MouseEvent(const MouseEvent& model, T* source, T* target, EventType type, int flags) : LocatedEvent(model, source, target), changed_button_flags_(model.changed_button_flags_), movement_(model.movement_), 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::kMouse, 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::kMouse, kPointerIdMouse)); MouseEvent(const MouseEvent& copy); ~MouseEvent() override; void InitializeNative(); class DispatcherApi { public: explicit DispatcherApi(MouseEvent* event) : event_(event) {} DispatcherApi(const DispatcherApi&) = delete; DispatcherApi& operator=(const DispatcherApi&) = delete; // 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: raw_ptr event_; }; // 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_; } // Event overides. std::string ToString() const override; 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 (which is the case on windows platforms, and CrOS if the // kEnableOrdinalMotion flag is set). // // TODO(b/171249701): always enable on CrOS. 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 MouseWheelEvent(const MouseWheelEvent& model, T* source, T* target) : MouseEvent(model, source, target, model.type(), model.flags()), offset_(model.x_offset(), model.y_offset()), tick_120ths_(model.tick_120ths()) {} // 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, const absl::optional tick_120ths = absl::nullopt); // 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 not necessarily linearly related to the // amount that the wheel moved, due to scroll acceleration. // 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_; } // The amount the wheel(s) moved, in 120ths of a tick. const gfx::Vector2d& tick_120ths() const { return tick_120ths_; } private: gfx::Vector2d offset_; gfx::Vector2d tick_120ths_; }; // NOTE: Pen (stylus) events use TouchEvent with kPen. 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 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_ = false; // True for devices like some pens when they support hovering over // digitizer and they send events while hovering. bool hovering_ = false; // 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). // -- |uint32_t scan_code_| [USE_OZONE only] supports remapping of the top // function row based on a sysfs attribute provided by the kernel. This // allows devices to have a custom top row layout and still be able to // perform translation back and forth between F-Key and Action-Key. The // value of this scan code is device specific. // // 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(char16_t 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; // Returns true if synthesizing key repeat in InitializeNative is enabled. static bool IsSynthesizeKeyRepeatEnabled(); // Sets whether to enable synthesizing key repeat in InitializeNative(). static void SetSynthesizeKeyRepeatEnabled(bool enabled); void InitializeNative(); // 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(char16_t character) { key_ = DomKey::FromCharacter(character); } // Gets the character generated by this key event. It only supports Unicode // BMP characters. char16_t GetCharacter() const; // If this is a keystroke event with key_code_ VKEY_RETURN, returns '\r'; // otherwise returns the same as GetCharacter(). char16_t 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(). char16_t 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; } #if defined(USE_OZONE) // The scan code of the physical key. This is used to perform the mapping // of top row keys from Actions back to F-Keys on new Chrome OS keyboards // that supply the mapping via the kernel. uint32_t scan_code() const { return scan_code_; } void set_scan_code(uint32_t scan_code) { scan_code_ = scan_code; } #endif // defined(USE_OZONE) // 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]+ 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(); // Event overrides. std::string ToString() const override; 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); // Returns the pointer for the last processed KeyEvent. KeyEvent** GetLastKeyEvent(); KeyboardCode key_code_; #if defined(USE_OZONE) // The scan code of the physical key on Chrome OS. uint32_t scan_code_ = 0; #endif // defined(USE_OZONE) // 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_OZONE) static KeyEvent* last_ibus_key_event_; #endif static bool synthesize_key_repeat_enabled_; }; class EVENTS_EXPORT ScrollEvent : public MouseEvent { public: explicit ScrollEvent(const PlatformEvent& native_event); template 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 overrides. 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 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_; } // Event overrides. std::string ToString() const override; 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_