summaryrefslogtreecommitdiffstats
path: root/ui/base
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-03 22:43:55 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-03 22:43:55 +0000
commit4967673d6412cbaa11e212da26742eba445cc1f9 (patch)
treecdee0a6d42949f8cabf8f5ccd3ce746b39f8b2a1 /ui/base
parent1bb25e0e19ec7e8fab908efa70a9fc16c02ae287 (diff)
downloadchromium_src-4967673d6412cbaa11e212da26742eba445cc1f9.zip
chromium_src-4967673d6412cbaa11e212da26742eba445cc1f9.tar.gz
chromium_src-4967673d6412cbaa11e212da26742eba445cc1f9.tar.bz2
Copy aura::Event into ui::Event.
http://crbug.com/125937 TEST=existing Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=149888 Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=149916 Review URL: https://chromiumcodereview.appspot.com/10831137 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@149954 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/base')
-rw-r--r--ui/base/event.cc428
-rw-r--r--ui/base/event.h422
-rw-r--r--ui/base/event_unittest.cc102
3 files changed, 952 insertions, 0 deletions
diff --git a/ui/base/event.cc b/ui/base/event.cc
new file mode 100644
index 0000000..1433f02
--- /dev/null
+++ b/ui/base/event.cc
@@ -0,0 +1,428 @@
+// 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/base/event.h"
+
+#if defined(USE_X11)
+#include <X11/Xlib.h>
+#endif
+
+#include <cstring>
+
+#include "ui/base/keycodes/keyboard_code_conversion.h"
+#include "ui/gfx/point3.h"
+#include "ui/gfx/interpolated_transform.h"
+#include "ui/gfx/transform.h"
+
+#if defined(USE_X11)
+#include "ui/base/keycodes/keyboard_code_conversion_x.h"
+#endif
+
+namespace {
+
+base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
+#if defined(USE_X11)
+ XEvent* copy = new XEvent;
+ *copy = *event;
+ return copy;
+#elif defined(OS_WIN)
+ return event;
+#else
+ NOTREACHED() <<
+ "Don't know how to copy base::NativeEvent for this platform";
+ return NULL;
+#endif
+}
+
+} // namespace
+
+namespace ui {
+
+Event::~Event() {
+#if defined(USE_X11)
+ if (delete_native_event_)
+ delete native_event_;
+#endif
+}
+
+bool Event::HasNativeEvent() const {
+ base::NativeEvent null_event;
+ std::memset(&null_event, 0, sizeof(null_event));
+ return !!std::memcmp(&native_event_, &null_event, sizeof(null_event));
+}
+
+Event::Event(EventType type, int flags)
+ : type_(type),
+ time_stamp_(base::Time::NowFromSystemTime() - base::Time()),
+ flags_(flags),
+ delete_native_event_(false) {
+ Init();
+}
+
+Event::Event(const base::NativeEvent& native_event,
+ EventType type,
+ int flags)
+ : type_(type),
+ time_stamp_(EventTimeFromNative(native_event)),
+ flags_(flags),
+ delete_native_event_(false) {
+ InitWithNativeEvent(native_event);
+}
+
+Event::Event(const Event& copy)
+ : native_event_(copy.native_event_),
+ type_(copy.type_),
+ time_stamp_(copy.time_stamp_),
+ flags_(copy.flags_),
+ delete_native_event_(false) {
+}
+
+void Event::Init() {
+ std::memset(&native_event_, 0, sizeof(native_event_));
+}
+
+void Event::InitWithNativeEvent(const base::NativeEvent& native_event) {
+ native_event_ = native_event;
+}
+
+LocatedEvent::~LocatedEvent() {
+}
+
+LocatedEvent::LocatedEvent(const base::NativeEvent& native_event)
+ : Event(native_event,
+ EventTypeFromNative(native_event),
+ EventFlagsFromNative(native_event)),
+ location_(EventLocationFromNative(native_event)),
+ root_location_(location_) {
+}
+
+LocatedEvent::LocatedEvent(EventType type,
+ const gfx::Point& location,
+ const gfx::Point& root_location,
+ int flags)
+ : Event(type, flags),
+ location_(location),
+ root_location_(root_location) {
+}
+
+void LocatedEvent::UpdateForRootTransform(const Transform& root_transform) {
+ // Transform has to be done at root level.
+ DCHECK_EQ(root_location_.x(), location_.x());
+ DCHECK_EQ(root_location_.y(), location_.y());
+ gfx::Point3f p(location_);
+ root_transform.TransformPointReverse(p);
+ root_location_ = location_ = p.AsPoint();
+}
+
+MouseEvent::MouseEvent(const base::NativeEvent& native_event)
+ : LocatedEvent(native_event) {
+ if (type() == ET_MOUSE_PRESSED)
+ SetClickCount(GetRepeatCount(*this));
+}
+
+MouseEvent::MouseEvent(EventType type,
+ const gfx::Point& location,
+ const gfx::Point& root_location,
+ int flags)
+ : LocatedEvent(type, location, root_location, flags) {
+}
+
+// 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 (abs(event2.x() - event1.x()) > kDoubleClickWidth / 2)
+ return false;
+
+ if (abs(event2.y() - event1.y()) > kDoubleClickHeight / 2)
+ return false;
+
+ return true;
+}
+
+// static
+int MouseEvent::GetRepeatCount(const MouseEvent& event) {
+ int click_count = 1;
+ if (last_click_event_) {
+ if (IsRepeatedClickEvent(*last_click_event_, event))
+ click_count = last_click_event_->GetClickCount() + 1;
+ delete last_click_event_;
+ }
+ last_click_event_ = new MouseEvent(event.native_event());
+ if (click_count > 3)
+ click_count = 3;
+ last_click_event_->SetClickCount(click_count);
+ return click_count;
+}
+
+// static
+MouseEvent* MouseEvent::last_click_event_ = NULL;
+
+int MouseEvent::GetClickCount() const {
+ if (type() != ET_MOUSE_PRESSED)
+ 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)
+ 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);
+}
+
+TouchEventImpl::TouchEventImpl(const base::NativeEvent& native_event)
+ : LocatedEvent(native_event),
+ touch_id_(ui::GetTouchId(native_event)),
+ radius_x_(GetTouchRadiusX(native_event)),
+ radius_y_(GetTouchRadiusY(native_event)),
+ rotation_angle_(GetTouchAngle(native_event)),
+ force_(GetTouchForce(native_event)) {
+}
+
+TouchEventImpl::TouchEventImpl(EventType type,
+ const gfx::Point& location,
+ int touch_id,
+ base::TimeDelta time_stamp)
+ : LocatedEvent(type, location, location, 0),
+ touch_id_(touch_id),
+ radius_x_(0.0f),
+ radius_y_(0.0f),
+ rotation_angle_(0.0f),
+ force_(0.0f) {
+ set_time_stamp(time_stamp);
+}
+
+TouchEventImpl::~TouchEventImpl() {
+}
+
+void TouchEventImpl::UpdateForRootTransform(const Transform& root_transform) {
+ LocatedEvent::UpdateForRootTransform(root_transform);
+ gfx::Point3f scale;
+ InterpolatedTransform::FactorTRS(root_transform, NULL, NULL, &scale);
+ if (scale.x())
+ radius_x_ /= scale.x();
+ if (scale.y())
+ radius_y_ /= scale.y();
+}
+
+EventType TouchEventImpl::GetEventType() const {
+ return type();
+}
+
+gfx::Point TouchEventImpl::GetLocation() const {
+ return location();
+}
+
+int TouchEventImpl::GetTouchId() const {
+ return touch_id_;
+}
+
+int TouchEventImpl::GetEventFlags() const {
+ return flags();
+}
+
+base::TimeDelta TouchEventImpl::GetTimestamp() const {
+ return time_stamp();
+}
+
+float TouchEventImpl::RadiusX() const {
+ return radius_x_;
+}
+
+float TouchEventImpl::RadiusY() const {
+ return radius_y_;
+}
+
+float TouchEventImpl::RotationAngle() const {
+ return rotation_angle_;
+}
+
+float TouchEventImpl::Force() const {
+ return force_;
+}
+
+KeyEvent::KeyEvent(const base::NativeEvent& native_event, bool is_char)
+ : Event(native_event,
+ EventTypeFromNative(native_event),
+ EventFlagsFromNative(native_event)),
+ key_code_(KeyboardCodeFromNative(native_event)),
+ is_char_(is_char),
+ character_(0),
+ unmodified_character_(0) {
+}
+
+KeyEvent::KeyEvent(EventType type,
+ KeyboardCode key_code,
+ int flags)
+ : Event(type, flags),
+ key_code_(key_code),
+ is_char_(false),
+ character_(GetCharacterFromKeyCode(key_code, flags)),
+ unmodified_character_(0) {
+}
+
+uint16 KeyEvent::GetCharacter() const {
+ if (character_)
+ return character_;
+
+#if defined(OS_WIN)
+ return (native_event().message == WM_CHAR) ? key_code_ :
+ GetCharacterFromKeyCode(key_code_, flags());
+#elif defined(USE_X11)
+ if (!native_event())
+ return GetCharacterFromKeyCode(key_code_, flags());
+
+ DCHECK(native_event()->type == KeyPress ||
+ native_event()->type == KeyRelease);
+
+ uint16 ch = 0;
+ if (!IsControlDown())
+ ch = GetCharacterFromXEvent(native_event());
+ return ch ? ch : GetCharacterFromKeyCode(key_code_, flags());
+#else
+ NOTIMPLEMENTED();
+ return 0;
+#endif
+}
+
+uint16 KeyEvent::GetUnmodifiedCharacter() const {
+ if (unmodified_character_)
+ return unmodified_character_;
+
+#if defined(OS_WIN)
+ // Looks like there is no way to get unmodified character on Windows.
+ return (native_event().message == WM_CHAR) ? key_code_ :
+ GetCharacterFromKeyCode(key_code_, flags() & EF_SHIFT_DOWN);
+#elif defined(USE_X11)
+ if (!native_event())
+ return GetCharacterFromKeyCode(key_code_, flags() & EF_SHIFT_DOWN);
+
+ DCHECK(native_event()->type == KeyPress ||
+ native_event()->type == KeyRelease);
+
+ static const unsigned int kIgnoredModifiers = ControlMask | LockMask |
+ Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask;
+
+ XKeyEvent copy = native_event()->xkey; // bit-wise copy is safe.
+ // We can't use things like (native_event()->xkey.state & ShiftMask), as it
+ // may mask out bits used by X11 internally.
+ copy.state &= ~kIgnoredModifiers;
+ uint16 ch = GetCharacterFromXEvent(reinterpret_cast<XEvent*>(&copy));
+ return ch ? ch : GetCharacterFromKeyCode(key_code_, flags() & EF_SHIFT_DOWN);
+#else
+ NOTIMPLEMENTED();
+ return 0;
+#endif
+}
+
+KeyEvent* KeyEvent::Copy() {
+ KeyEvent* copy = new KeyEvent(::CopyNativeEvent(native_event()), is_char());
+#if defined(USE_X11)
+ copy->set_delete_native_event(true);
+#endif
+ return copy;
+}
+
+TranslatedKeyEvent::TranslatedKeyEvent(const base::NativeEvent& native_event,
+ bool is_char)
+ : KeyEvent(native_event, is_char) {
+ set_type(type() == ET_KEY_PRESSED ?
+ ET_TRANSLATED_KEY_PRESS : ET_TRANSLATED_KEY_RELEASE);
+}
+
+TranslatedKeyEvent::TranslatedKeyEvent(bool is_press,
+ KeyboardCode key_code,
+ int flags)
+ : KeyEvent((is_press ? ET_TRANSLATED_KEY_PRESS : ET_TRANSLATED_KEY_RELEASE),
+ key_code,
+ flags) {
+}
+
+void TranslatedKeyEvent::ConvertToKeyEvent() {
+ set_type(type() == ET_TRANSLATED_KEY_PRESS ?
+ ET_KEY_PRESSED : ET_KEY_RELEASED);
+}
+
+ScrollEvent::ScrollEvent(const base::NativeEvent& native_event)
+ : MouseEvent(native_event) {
+ if (type() == ET_SCROLL) {
+ GetScrollOffsets(native_event, &x_offset_, &y_offset_);
+ double start, end;
+ GetGestureTimes(native_event, &start, &end);
+ } else if (type() == ET_SCROLL_FLING_START) {
+ bool is_cancel;
+ GetFlingData(native_event, &x_offset_, &y_offset_, &is_cancel);
+ }
+}
+
+GestureEventImpl::GestureEventImpl(EventType type,
+ int x,
+ int y,
+ int flags,
+ base::Time time_stamp,
+ const GestureEventDetails& details,
+ unsigned int touch_ids_bitfield)
+ : LocatedEvent(type, gfx::Point(x, y), gfx::Point(x, y), flags),
+ details_(details),
+ touch_ids_bitfield_(touch_ids_bitfield) {
+ set_time_stamp(base::TimeDelta::FromSeconds(time_stamp.ToDoubleT()));
+}
+
+GestureEventImpl::~GestureEventImpl() {
+}
+
+int GestureEventImpl::GetLowestTouchId() const {
+ if (touch_ids_bitfield_ == 0)
+ return -1;
+ int i = -1;
+ // Find the index of the least significant 1 bit
+ while (!(1 << ++i & touch_ids_bitfield_));
+ return i;
+}
+
+} // namespace ui
diff --git a/ui/base/event.h b/ui/base/event.h
new file mode 100644
index 0000000..1e20fa1
--- /dev/null
+++ b/ui/base/event.h
@@ -0,0 +1,422 @@
+// 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_BASE_EVENT_H_
+#define UI_BASE_EVENT_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/event_types.h"
+#include "base/logging.h"
+#include "base/time.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/events.h"
+#include "ui/base/gestures/gesture_types.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/base/ui_export.h"
+#include "ui/gfx/point.h"
+
+namespace ui {
+class Transform;
+
+class UI_EXPORT Event {
+ public:
+ virtual ~Event();
+
+ // For testing.
+ class TestApi {
+ public:
+ explicit TestApi(Event* event) : event_(event) {}
+
+ void set_time_stamp(const base::TimeDelta& time_stamp) {
+ event_->time_stamp_ = time_stamp;
+ }
+
+ private:
+ TestApi();
+ Event* event_;
+ };
+
+ const base::NativeEvent& native_event() const { return native_event_; }
+ EventType type() const { return type_; }
+ // time_stamp represents time since machine was booted.
+ const base::TimeDelta& time_stamp() const { return time_stamp_; }
+ int flags() const { return flags_; }
+
+ // This is only intended to be used externally by classes that are modifying
+ // events in EventFilter::PreHandleKeyEvent().
+ void set_flags(int flags) { flags_ = flags; }
+
+ // 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 IsCapsLockDown() const { return (flags_ & EF_CAPS_LOCK_DOWN) != 0; }
+ bool IsAltDown() const { return (flags_ & EF_ALT_DOWN) != 0; }
+
+ // Returns true if the event has a valid |native_event_|.
+ bool HasNativeEvent() const;
+
+ protected:
+ Event(EventType type, int flags);
+ Event(const base::NativeEvent& native_event, EventType type, int flags);
+ Event(const Event& copy);
+ void set_type(EventType type) { type_ = type; }
+ void set_delete_native_event(bool delete_native_event) {
+ delete_native_event_ = delete_native_event;
+ }
+ void set_time_stamp(base::TimeDelta time_stamp) { time_stamp_ = time_stamp; }
+
+ private:
+ void operator=(const Event&);
+
+ // Safely initializes the native event members of this class.
+ void Init();
+ void InitWithNativeEvent(const base::NativeEvent& native_event);
+
+ base::NativeEvent native_event_;
+ EventType type_;
+ base::TimeDelta time_stamp_;
+ int flags_;
+ bool delete_native_event_;
+};
+
+class UI_EXPORT LocatedEvent : public Event {
+ public:
+ // For testing.
+ class TestApi : public Event::TestApi {
+ public:
+ explicit TestApi(LocatedEvent* located_event)
+ : Event::TestApi(located_event),
+ located_event_(located_event) {}
+
+ void set_location(const gfx::Point& location) {
+ located_event_->location_ = location;
+ }
+
+ private:
+ TestApi();
+ LocatedEvent* located_event_;
+ };
+
+ virtual ~LocatedEvent();
+
+ int x() const { return location_.x(); }
+ int y() const { return location_.y(); }
+ gfx::Point location() const { return location_; }
+ gfx::Point root_location() const { return root_location_; }
+
+ // Applies |root_transform| to the event.
+ // This is applied to both |location_| and |root_location_|.
+ virtual void UpdateForRootTransform(const Transform& root_transform);
+
+ protected:
+ explicit LocatedEvent(const base::NativeEvent& native_event);
+
+ // Create a new LocatedEvent which is identical to the provided model.
+ // If source / target windows are provided, the model location will be
+ // 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_) {
+ if (target && target != source)
+ T::ConvertPointToTarget(source, target, &location_);
+ }
+
+ // Used for synthetic events in testing.
+ LocatedEvent(EventType type,
+ const gfx::Point& location,
+ const gfx::Point& root_location,
+ int flags);
+
+ gfx::Point location_;
+
+ gfx::Point root_location_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LocatedEvent);
+};
+
+class UI_EXPORT MouseEvent : public LocatedEvent {
+ public:
+ explicit MouseEvent(const base::NativeEvent& 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) {
+ }
+
+ template <class T>
+ MouseEvent(const MouseEvent& model,
+ T* source,
+ T* target,
+ EventType type,
+ int flags)
+ : LocatedEvent(model, source, target) {
+ set_type(type);
+ set_flags(flags);
+ }
+
+ // Used for synthetic events in testing and by the gesture recognizer.
+ MouseEvent(EventType type,
+ const gfx::Point& location,
+ const gfx::Point& root_location,
+ int flags);
+
+ // 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);
+
+ private:
+ gfx::Point root_location_;
+
+ static MouseEvent* last_click_event_;
+ // 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);
+
+ DISALLOW_COPY_AND_ASSIGN(MouseEvent);
+};
+
+// TODO(beng): rename to TouchEvent after conversion is complete.
+class UI_EXPORT TouchEventImpl : public LocatedEvent,
+ public TouchEvent {
+ public:
+ explicit TouchEventImpl(const base::NativeEvent& native_event);
+
+ // Create a new TouchEventImpl 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>
+ TouchEventImpl(const TouchEventImpl& model, T* source, T* target)
+ : LocatedEvent(model, source, target),
+ touch_id_(model.touch_id_),
+ radius_x_(model.radius_x_),
+ radius_y_(model.radius_y_),
+ rotation_angle_(model.rotation_angle_),
+ force_(model.force_) {
+ }
+
+ TouchEventImpl(EventType type,
+ const gfx::Point& root_location,
+ int touch_id,
+ base::TimeDelta time_stamp);
+
+ virtual ~TouchEventImpl();
+
+ int touch_id() const { return touch_id_; }
+ float radius_x() const { return radius_x_; }
+ float radius_y() const { return radius_y_; }
+ float rotation_angle() const { return rotation_angle_; }
+ float force() const { return force_; }
+
+ // Used for unit tests.
+ void set_radius_x(const float r) { radius_x_ = r; }
+ void set_radius_y(const float r) { radius_y_ = r; }
+
+ // Overridden from LocatedEvent.
+ virtual void UpdateForRootTransform(const Transform& root_transform) OVERRIDE;
+
+ // Overridden from TouchEvent.
+ virtual EventType GetEventType() const OVERRIDE;
+ virtual gfx::Point GetLocation() const OVERRIDE;
+ virtual int GetTouchId() const OVERRIDE;
+ virtual int GetEventFlags() const OVERRIDE;
+ virtual base::TimeDelta GetTimestamp() const OVERRIDE;
+ virtual float RadiusX() const OVERRIDE;
+ virtual float RadiusY() const OVERRIDE;
+ virtual float RotationAngle() const OVERRIDE;
+ virtual float Force() const OVERRIDE;
+
+ private:
+ // The identity (typically finger) of the touch starting at 0 and incrementing
+ // for each separable additional touch that the hardware can detect.
+ const int touch_id_;
+
+ // Radius of the X (major) axis of the touch ellipse. 0.0 if unknown.
+ float radius_x_;
+
+ // Radius of the Y (minor) axis of the touch ellipse. 0.0 if unknown.
+ float radius_y_;
+
+ // Angle of the major axis away from the X axis. Default 0.0.
+ const float rotation_angle_;
+
+ // Force (pressure) of the touch. Normalized to be [0, 1]. Default to be 0.0.
+ const float force_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchEventImpl);
+};
+
+class UI_EXPORT KeyEvent : public Event {
+ public:
+ KeyEvent(const base::NativeEvent& native_event, bool is_char);
+
+ // Used for synthetic events in testing.
+ KeyEvent(EventType type, KeyboardCode key_code, int flags);
+
+ // These setters allow an I18N virtual keyboard to fabricate a keyboard event
+ // which does not have a corresponding KeyboardCode (example: U+00E1 Latin
+ // small letter A with acute, U+0410 Cyrillic capital letter A.)
+ // GetCharacter() and GetUnmodifiedCharacter() return the character.
+ void set_character(uint16 character) { character_ = character; }
+ void set_unmodified_character(uint16 unmodified_character) {
+ unmodified_character_ = unmodified_character;
+ }
+
+ // Gets the character generated by this key event. It only supports Unicode
+ // BMP characters.
+ uint16 GetCharacter() const;
+
+ // Gets the character generated by this key event ignoring concurrently-held
+ // modifiers (except shift).
+ uint16 GetUnmodifiedCharacter() const;
+
+ // Returns the copy of this key event. Used in NativeWebKeyboardEvent.
+ KeyEvent* Copy();
+
+ KeyboardCode key_code() const { return key_code_; }
+ bool is_char() const { return is_char_; }
+
+ // This is only intended to be used externally by classes that are modifying
+ // events in EventFilter::PreHandleKeyEvent(). set_character() should also be
+ // called.
+ void set_key_code(KeyboardCode key_code) { key_code_ = key_code; }
+
+ private:
+ KeyboardCode key_code_;
+ // True if this is a translated character event (vs. a raw key down). Both
+ // share the same type: ET_KEY_PRESSED.
+ bool is_char_;
+
+ uint16 character_;
+ uint16 unmodified_character_;
+};
+
+// A key event which is translated by an input method (IME).
+// For example, if an IME receives a KeyEvent(VKEY_SPACE), and it does not
+// consume the key, the IME usually generates and dispatches a
+// TranslatedKeyEvent(VKEY_SPACE) event. If the IME receives a KeyEvent and
+// it does consume the event, it might dispatch a
+// TranslatedKeyEvent(VKEY_PROCESSKEY) event as defined in the DOM spec.
+class UI_EXPORT TranslatedKeyEvent : public KeyEvent {
+ public:
+ TranslatedKeyEvent(const base::NativeEvent& native_event, bool is_char);
+
+ // Used for synthetic events such as a VKEY_PROCESSKEY key event.
+ TranslatedKeyEvent(bool is_press, KeyboardCode key_code, int flags);
+
+ // Changes the type() of the object from ET_TRANSLATED_KEY_* to ET_KEY_* so
+ // that RenderWidgetHostViewAura and NativeWidgetAura could handle the event.
+ void ConvertToKeyEvent();
+};
+
+class UI_EXPORT DropTargetEvent : public LocatedEvent {
+ public:
+ DropTargetEvent(const OSExchangeData& data,
+ const gfx::Point& location,
+ const gfx::Point& root_location,
+ int source_operations)
+ : LocatedEvent(ET_DROP_TARGET_EVENT, location, root_location, 0),
+ data_(data),
+ source_operations_(source_operations) {
+ }
+
+ const OSExchangeData& data() const { return data_; }
+ int source_operations() const { return source_operations_; }
+
+ private:
+ // Data associated with the drag/drop session.
+ const OSExchangeData& data_;
+
+ // Bitmask of supported DragDropTypes::DragOperation by the source.
+ int source_operations_;
+
+ DISALLOW_COPY_AND_ASSIGN(DropTargetEvent);
+};
+
+class UI_EXPORT ScrollEvent : public MouseEvent {
+ public:
+ explicit ScrollEvent(const base::NativeEvent& native_event);
+ template <class T>
+ ScrollEvent(const ScrollEvent& model,
+ T* source,
+ T* target,
+ EventType type,
+ int flags)
+ : MouseEvent(model, source, target, type, flags),
+ x_offset_(model.x_offset_),
+ y_offset_(model.y_offset_) {
+ }
+
+ float x_offset() const { return x_offset_; }
+ float y_offset() const { return y_offset_; }
+
+ private:
+ float x_offset_;
+ float y_offset_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScrollEvent);
+};
+
+// TODO(beng): rename to GestureEvent after conversion is complete.
+class UI_EXPORT GestureEventImpl : public LocatedEvent,
+ public GestureEvent {
+ public:
+ GestureEventImpl(EventType type,
+ int x,
+ int y,
+ int flags,
+ base::Time time_stamp,
+ const GestureEventDetails& details,
+ unsigned int touch_ids_bitfield);
+
+ // Create a new GestureEventImpl 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>
+ GestureEventImpl(const GestureEventImpl& model, T* source, T* target)
+ : LocatedEvent(model, source, target),
+ details_(model.details_),
+ touch_ids_bitfield_(model.touch_ids_bitfield_) {
+ }
+
+ virtual ~GestureEventImpl();
+
+ const GestureEventDetails& details() const { return details_; }
+
+ // Returns the lowest touch-id of any of the touches which make up this
+ // gesture.
+ // If there are no touches associated with this gesture, returns -1.
+ virtual int GetLowestTouchId() const OVERRIDE;
+
+ private:
+ GestureEventDetails details_;
+
+ // The set of indices of ones in the binary representation of
+ // touch_ids_bitfield_ is the set of touch_ids associate with this gesture.
+ // This value is stored as a bitfield because the number of touch ids varies,
+ // but we currently don't need more than 32 touches at a time.
+ const unsigned int touch_ids_bitfield_;
+
+ DISALLOW_COPY_AND_ASSIGN(GestureEventImpl);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_EVENT_H_
diff --git a/ui/base/event_unittest.cc b/ui/base/event_unittest.cc
new file mode 100644
index 0000000..7411859
--- /dev/null
+++ b/ui/base/event_unittest.cc
@@ -0,0 +1,102 @@
+// 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/base/event.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(USE_X11)
+#include <X11/Xlib.h>
+#include "ui/base/x/x11_util.h"
+#endif
+
+namespace ui {
+
+TEST(EventTest, NoNativeEvent) {
+ KeyEvent keyev(ET_KEY_PRESSED, VKEY_SPACE, 0);
+ EXPECT_FALSE(keyev.HasNativeEvent());
+}
+
+TEST(EventTest, NativeEvent) {
+#if defined(OS_WIN)
+ MSG native_event = { NULL, WM_KEYUP, VKEY_A, 0 };
+ KeyEvent keyev(native_event, false);
+ EXPECT_TRUE(keyev.HasNativeEvent());
+#elif defined(USE_X11)
+ scoped_ptr<XEvent> native_event(new XEvent);
+ InitXKeyEventForTesting(ET_KEY_RELEASED, VKEY_A, 0, native_event.get());
+ KeyEvent keyev(native_event.get(), false);
+ EXPECT_TRUE(keyev.HasNativeEvent());
+#endif
+}
+
+TEST(EventTest, GetCharacter) {
+ // Check if Control+Enter returns 10.
+ KeyEvent keyev1(ET_KEY_PRESSED, VKEY_RETURN, EF_CONTROL_DOWN);
+ EXPECT_EQ(10, keyev1.GetCharacter());
+ EXPECT_EQ(13, keyev1.GetUnmodifiedCharacter());
+ // Check if Enter returns 13.
+ KeyEvent keyev2(ET_KEY_PRESSED, VKEY_RETURN, 0);
+ EXPECT_EQ(13, keyev2.GetCharacter());
+ EXPECT_EQ(13, keyev2.GetUnmodifiedCharacter());
+
+#if defined(USE_X11)
+ // For X11, test the functions with native_event() as well. crbug.com/107837
+ scoped_ptr<XEvent> native_event(new XEvent);
+
+ InitXKeyEventForTesting(ET_KEY_PRESSED, VKEY_RETURN, EF_CONTROL_DOWN,
+ native_event.get());
+ KeyEvent keyev3(native_event.get(), false);
+ EXPECT_EQ(10, keyev3.GetCharacter());
+ EXPECT_EQ(13, keyev3.GetUnmodifiedCharacter());
+
+ InitXKeyEventForTesting(ET_KEY_PRESSED, VKEY_RETURN, 0, native_event.get());
+ KeyEvent keyev4(native_event.get(), false);
+ EXPECT_EQ(13, keyev4.GetCharacter());
+ EXPECT_EQ(13, keyev4.GetUnmodifiedCharacter());
+#endif
+}
+
+TEST(EventTest, ClickCount) {
+ const gfx::Point origin(0, 0);
+ MouseEvent mouseev(ET_MOUSE_PRESSED, origin, origin, 0);
+ for (int i = 1; i <=3 ; ++i) {
+ mouseev.SetClickCount(i);
+ EXPECT_EQ(i, mouseev.GetClickCount());
+ }
+}
+
+TEST(EventTest, Repeated) {
+ const gfx::Point origin(0, 0);
+ MouseEvent mouse_ev1(ET_MOUSE_PRESSED, origin, origin, 0);
+ MouseEvent mouse_ev2(ET_MOUSE_PRESSED, origin, origin, 0);
+ MouseEvent::TestApi test_ev1(&mouse_ev1);
+ MouseEvent::TestApi test_ev2(&mouse_ev2);
+
+ base::TimeDelta start = base::TimeDelta::FromMilliseconds(0);
+ base::TimeDelta soon = start + base::TimeDelta::FromMilliseconds(1);
+ base::TimeDelta later = start + base::TimeDelta::FromMilliseconds(1000);
+
+ // Close point.
+ test_ev1.set_location(gfx::Point(0, 0));
+ test_ev2.set_location(gfx::Point(1, 0));
+ test_ev1.set_time_stamp(start);
+ test_ev2.set_time_stamp(soon);
+ EXPECT_TRUE(MouseEvent::IsRepeatedClickEvent(mouse_ev1, mouse_ev2));
+
+ // Too far.
+ test_ev1.set_location(gfx::Point(0, 0));
+ test_ev2.set_location(gfx::Point(10, 0));
+ test_ev1.set_time_stamp(start);
+ test_ev2.set_time_stamp(soon);
+ EXPECT_FALSE(MouseEvent::IsRepeatedClickEvent(mouse_ev1, mouse_ev2));
+
+ // Too long a time between clicks.
+ test_ev1.set_location(gfx::Point(0, 0));
+ test_ev2.set_location(gfx::Point(0, 0));
+ test_ev1.set_time_stamp(start);
+ test_ev2.set_time_stamp(later);
+ EXPECT_FALSE(MouseEvent::IsRepeatedClickEvent(mouse_ev1, mouse_ev2));
+}
+
+} // namespace ui