Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(413)

Unified Diff: ui/events/event.cc

Issue 1287103004: Sync ui/events to chromium @ https://codereview.chromium.org/1210203002 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: rebased Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/events/event.h ('k') | ui/events/event_constants.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/events/event.cc
diff --git a/ui/events/event.cc b/ui/events/event.cc
index ebecbfe443b4de08793a46e5ff430a37cc79ce06..953220d0a634f1de2ae7ec3ca738dfc34a879839 100644
--- a/ui/events/event.cc
+++ b/ui/events/event.cc
@@ -6,22 +6,111 @@
#if defined(USE_X11)
#include <X11/extensions/XInput2.h>
-#include <X11/Xlib.h>
#include <X11/keysym.h>
+#include <X11/Xlib.h>
#endif
#include <cmath>
#include <cstring>
+#include "base/metrics/histogram.h"
#include "base/strings/stringprintf.h"
+#include "ui/events/base_event_utils.h"
#include "ui/events/event_utils.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/dom_key.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
+#include "ui/gfx/geometry/point3_f.h"
+#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
-#include "ui/gfx/point3_f.h"
-#include "ui/gfx/point_conversions.h"
#include "ui/gfx/transform.h"
#include "ui/gfx/transform_util.h"
+#if defined(USE_X11)
+#include "ui/events/keycodes/keyboard_code_conversion_x.h"
+#elif defined(USE_OZONE)
+#include "ui/events/ozone/layout/keyboard_layout_engine.h"
+#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
+#endif
+
+namespace {
+
+std::string EventTypeName(ui::EventType type) {
+#define RETURN_IF_TYPE(t) if (type == ui::t) return #t
+#define CASE_TYPE(t) case ui::t: return #t
+ switch (type) {
+ CASE_TYPE(ET_UNKNOWN);
+ CASE_TYPE(ET_MOUSE_PRESSED);
+ CASE_TYPE(ET_MOUSE_DRAGGED);
+ CASE_TYPE(ET_MOUSE_RELEASED);
+ CASE_TYPE(ET_MOUSE_MOVED);
+ CASE_TYPE(ET_MOUSE_ENTERED);
+ CASE_TYPE(ET_MOUSE_EXITED);
+ CASE_TYPE(ET_KEY_PRESSED);
+ CASE_TYPE(ET_KEY_RELEASED);
+ CASE_TYPE(ET_MOUSEWHEEL);
+ CASE_TYPE(ET_MOUSE_CAPTURE_CHANGED);
+ CASE_TYPE(ET_TOUCH_RELEASED);
+ CASE_TYPE(ET_TOUCH_PRESSED);
+ CASE_TYPE(ET_TOUCH_MOVED);
+ CASE_TYPE(ET_TOUCH_CANCELLED);
+ CASE_TYPE(ET_DROP_TARGET_EVENT);
+ CASE_TYPE(ET_GESTURE_SCROLL_BEGIN);
+ CASE_TYPE(ET_GESTURE_SCROLL_END);
+ CASE_TYPE(ET_GESTURE_SCROLL_UPDATE);
+ CASE_TYPE(ET_GESTURE_SHOW_PRESS);
+ CASE_TYPE(ET_GESTURE_WIN8_EDGE_SWIPE);
+ CASE_TYPE(ET_GESTURE_TAP);
+ CASE_TYPE(ET_GESTURE_TAP_DOWN);
+ CASE_TYPE(ET_GESTURE_TAP_CANCEL);
+ CASE_TYPE(ET_GESTURE_BEGIN);
+ CASE_TYPE(ET_GESTURE_END);
+ CASE_TYPE(ET_GESTURE_TWO_FINGER_TAP);
+ CASE_TYPE(ET_GESTURE_PINCH_BEGIN);
+ CASE_TYPE(ET_GESTURE_PINCH_END);
+ CASE_TYPE(ET_GESTURE_PINCH_UPDATE);
+ CASE_TYPE(ET_GESTURE_LONG_PRESS);
+ CASE_TYPE(ET_GESTURE_LONG_TAP);
+ CASE_TYPE(ET_GESTURE_SWIPE);
+ CASE_TYPE(ET_GESTURE_TAP_UNCONFIRMED);
+ CASE_TYPE(ET_GESTURE_DOUBLE_TAP);
+ CASE_TYPE(ET_SCROLL);
+ CASE_TYPE(ET_SCROLL_FLING_START);
+ CASE_TYPE(ET_SCROLL_FLING_CANCEL);
+ CASE_TYPE(ET_CANCEL_MODE);
+ CASE_TYPE(ET_UMA_DATA);
+ case ui::ET_LAST: NOTREACHED(); return std::string();
+ // Don't include default, so that we get an error when new type is added.
+ }
+#undef CASE_TYPE
+
+ NOTREACHED();
+ return std::string();
+}
+
+bool IsX11SendEventTrue(const base::NativeEvent& event) {
+#if defined(USE_X11)
+ return event && event->xany.send_event;
+#else
+ return false;
+#endif
+}
+
+bool X11EventHasNonStandardState(const base::NativeEvent& event) {
+#if defined(USE_X11)
+ const unsigned int kAllStateMask =
+ Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask |
+ Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask |
+ LockMask | ControlMask | AnyModifier;
+ return event && (event->xkey.state & ~kAllStateMask) != 0;
+#else
+ return false;
+#endif
+}
+
+} // namespace
+
namespace ui {
////////////////////////////////////////////////////////////////////////////////
@@ -30,38 +119,40 @@ namespace ui {
// static
scoped_ptr<Event> Event::Clone(const Event& event) {
if (event.IsKeyEvent()) {
- return scoped_ptr<Event>(new KeyEvent(static_cast<const KeyEvent&>(event)));
+ return make_scoped_ptr(new KeyEvent(static_cast<const KeyEvent&>(event)));
}
if (event.IsMouseEvent()) {
if (event.IsMouseWheelEvent()) {
- return scoped_ptr<Event>(
+ return make_scoped_ptr(
new MouseWheelEvent(static_cast<const MouseWheelEvent&>(event)));
}
- return scoped_ptr<Event>(
+ return make_scoped_ptr(
new MouseEvent(static_cast<const MouseEvent&>(event)));
}
if (event.IsTouchEvent()) {
- return scoped_ptr<Event>(
+ return make_scoped_ptr(
new TouchEvent(static_cast<const TouchEvent&>(event)));
}
if (event.IsGestureEvent()) {
- return scoped_ptr<Event>(
+ return make_scoped_ptr(
new GestureEvent(static_cast<const GestureEvent&>(event)));
}
if (event.IsScrollEvent()) {
- return scoped_ptr<Event>(
+ return make_scoped_ptr(
new ScrollEvent(static_cast<const ScrollEvent&>(event)));
}
- return scoped_ptr<Event>(new Event(event));
+ return make_scoped_ptr(new Event(event));
}
Event::~Event() {
+ if (delete_native_event_)
+ ReleaseCopiedNativeEvent(native_event_);
}
GestureEvent* Event::AsGestureEvent() {
@@ -74,6 +165,12 @@ const GestureEvent* Event::AsGestureEvent() const {
return static_cast<const GestureEvent*>(this);
}
+bool Event::HasNativeEvent() const {
+ base::NativeEvent null_event;
+ std::memset(&null_event, 0, sizeof(null_event));
+ return !!std::memcmp(&native_event_, &null_event, sizeof(null_event));
+}
+
void Event::StopPropagation() {
// TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
// events.
@@ -90,26 +187,63 @@ void Event::SetHandled() {
result_ = static_cast<EventResult>(result_ | ER_HANDLED);
}
-Event::Event()
- : type_(ET_UNKNOWN),
- time_stamp_(base::TimeDelta()),
- flags_(EF_NONE),
+Event::Event(EventType type, base::TimeDelta time_stamp, int flags)
+ : type_(type),
+ time_stamp_(time_stamp),
+ flags_(flags),
+ native_event_(base::NativeEvent()),
+ delete_native_event_(false),
cancelable_(true),
target_(NULL),
phase_(EP_PREDISPATCH),
result_(ER_UNHANDLED),
source_device_id_(ED_UNKNOWN_DEVICE) {
+ if (type_ < ET_LAST)
+ name_ = EventTypeName(type_);
}
-Event::Event(EventType type, base::TimeDelta time_stamp, int flags)
+Event::Event(const base::NativeEvent& native_event,
+ EventType type,
+ int flags)
: type_(type),
- time_stamp_(time_stamp),
+ time_stamp_(EventTimeFromNative(native_event)),
flags_(flags),
+ native_event_(native_event),
+ delete_native_event_(false),
cancelable_(true),
target_(NULL),
phase_(EP_PREDISPATCH),
result_(ER_UNHANDLED),
source_device_id_(ED_UNKNOWN_DEVICE) {
+ base::TimeDelta delta = EventTimeForNow() - time_stamp_;
+ if (type_ < ET_LAST)
+ name_ = EventTypeName(type_);
+ base::HistogramBase::Sample delta_sample =
+ static_cast<base::HistogramBase::Sample>(delta.InMicroseconds());
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser", delta_sample, 1, 1000000,
+ 100);
+ std::string name_for_event =
+ base::StringPrintf("Event.Latency.Browser.%s", name_.c_str());
+ base::HistogramBase* counter_for_type =
+ base::Histogram::FactoryGet(
+ name_for_event,
+ 1,
+ 1000000,
+ 100,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ counter_for_type->Add(delta_sample);
+
+#if defined(USE_X11)
+ if (native_event->type == GenericEvent) {
+ XIDeviceEvent* xiev =
+ static_cast<XIDeviceEvent*>(native_event->xcookie.data);
+ source_device_id_ = xiev->sourceid;
+ }
+#endif
+#if defined(USE_OZONE)
+ source_device_id_ =
+ static_cast<const Event*>(native_event)->source_device_id();
+#endif
}
Event::Event(const Event& copy)
@@ -117,15 +251,23 @@ Event::Event(const Event& copy)
time_stamp_(copy.time_stamp_),
latency_(copy.latency_),
flags_(copy.flags_),
+ native_event_(CopyNativeEvent(copy.native_event_)),
+ delete_native_event_(true),
cancelable_(true),
target_(NULL),
phase_(EP_PREDISPATCH),
result_(ER_UNHANDLED),
source_device_id_(copy.source_device_id_) {
+ if (type_ < ET_LAST)
+ name_ = EventTypeName(type_);
}
void Event::SetType(EventType type) {
+ if (type_ < ET_LAST)
+ name_ = std::string();
type_ = type;
+ if (type_ < ET_LAST)
+ name_ = EventTypeName(type_);
}
////////////////////////////////////////////////////////////////////////////////
@@ -142,10 +284,15 @@ CancelModeEvent::~CancelModeEvent() {
////////////////////////////////////////////////////////////////////////////////
// LocatedEvent
-LocatedEvent::LocatedEvent() : Event() {
+LocatedEvent::~LocatedEvent() {
}
-LocatedEvent::~LocatedEvent() {
+LocatedEvent::LocatedEvent(const base::NativeEvent& native_event)
+ : Event(native_event,
+ EventTypeFromNative(native_event),
+ EventFlagsFromNative(native_event)),
+ location_(EventLocationFromNative(native_event)),
+ root_location_(location_) {
}
LocatedEvent::LocatedEvent(EventType type,
@@ -170,15 +317,21 @@ void LocatedEvent::UpdateForRootTransform(
////////////////////////////////////////////////////////////////////////////////
// MouseEvent
-MouseEvent::MouseEvent() : LocatedEvent(), changed_button_flags_(0) {
+MouseEvent::MouseEvent(const base::NativeEvent& native_event)
+ : LocatedEvent(native_event),
+ changed_button_flags_(
+ GetChangedMouseButtonFlagsFromNative(native_event)) {
+ if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED)
+ SetClickCount(GetRepeatCount(*this));
}
MouseEvent::MouseEvent(EventType type,
const gfx::PointF& location,
const gfx::PointF& root_location,
+ base::TimeDelta time_stamp,
int flags,
int changed_button_flags)
- : LocatedEvent(type, location, root_location, EventTimeForNow(), flags),
+ : LocatedEvent(type, location, root_location, time_stamp, flags),
changed_button_flags_(changed_button_flags) {
if (this->type() == ET_MOUSE_MOVED && IsAnyButton())
SetType(ET_MOUSE_DRAGGED);
@@ -202,6 +355,10 @@ bool MouseEvent::IsRepeatedClickEvent(
(event2.flags() & ~EF_IS_DOUBLE_CLICK))
return false;
+ // The new event has been created from the same native event.
+ if (event1.time_stamp() == event2.time_stamp())
+ return false;
+
base::TimeDelta time_difference = event2.time_stamp() - event1.time_stamp();
if (time_difference.InMilliseconds() > kDoubleClickTimeMS)
@@ -216,6 +373,51 @@ bool MouseEvent::IsRepeatedClickEvent(
return true;
}
+// static
+int MouseEvent::GetRepeatCount(const MouseEvent& event) {
+ int click_count = 1;
+ if (last_click_event_) {
+ if (event.type() == ui::ET_MOUSE_RELEASED) {
+ if (event.changed_button_flags() ==
+ last_click_event_->changed_button_flags()) {
+ last_click_complete_ = true;
+ return last_click_event_->GetClickCount();
+ } else {
+ // If last_click_event_ has changed since this button was pressed
+ // return a click count of 1.
+ return click_count;
+ }
+ }
+ if (event.time_stamp() != last_click_event_->time_stamp())
+ last_click_complete_ = true;
+ if (!last_click_complete_ ||
+ IsX11SendEventTrue(event.native_event())) {
+ click_count = last_click_event_->GetClickCount();
+ } else if (IsRepeatedClickEvent(*last_click_event_, event)) {
+ click_count = last_click_event_->GetClickCount() + 1;
+ }
+ delete last_click_event_;
+ }
+ last_click_event_ = new MouseEvent(event);
+ last_click_complete_ = false;
+ if (click_count > 3)
+ click_count = 3;
+ last_click_event_->SetClickCount(click_count);
+ return click_count;
+}
+
+void MouseEvent::ResetLastClickForTest() {
+ if (last_click_event_) {
+ delete last_click_event_;
+ last_click_event_ = NULL;
+ last_click_complete_ = false;
+ }
+}
+
+// static
+MouseEvent* MouseEvent::last_click_event_ = NULL;
+bool MouseEvent::last_click_complete_ = false;
+
int MouseEvent::GetClickCount() const {
if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
return 0;
@@ -256,7 +458,9 @@ void MouseEvent::SetClickCount(int click_count) {
////////////////////////////////////////////////////////////////////////////////
// MouseWheelEvent
-MouseWheelEvent::MouseWheelEvent() : MouseEvent(), offset_() {
+MouseWheelEvent::MouseWheelEvent(const base::NativeEvent& native_event)
+ : MouseEvent(native_event),
+ offset_(GetMouseWheelOffset(native_event)) {
}
MouseWheelEvent::MouseWheelEvent(const ScrollEvent& scroll_event)
@@ -282,42 +486,48 @@ MouseWheelEvent::MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event)
MouseWheelEvent::MouseWheelEvent(const gfx::Vector2d& offset,
const gfx::PointF& location,
const gfx::PointF& root_location,
+ base::TimeDelta time_stamp,
int flags,
int changed_button_flags)
- : MouseEvent(ui::ET_MOUSEWHEEL, location, root_location, flags,
+ : MouseEvent(ui::ET_MOUSEWHEEL,
+ location,
+ root_location,
+ time_stamp,
+ flags,
changed_button_flags),
offset_(offset) {
}
+#if defined(OS_WIN)
+// This value matches windows WHEEL_DELTA.
+// static
+const int MouseWheelEvent::kWheelDelta = 120;
+#else
// This value matches GTK+ wheel scroll amount.
const int MouseWheelEvent::kWheelDelta = 53;
-
-void MouseWheelEvent::UpdateForRootTransform(
- const gfx::Transform& inverted_root_transform) {
- LocatedEvent::UpdateForRootTransform(inverted_root_transform);
- gfx::DecomposedTransform decomp;
- bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
- DCHECK(success);
- if (decomp.scale[0]) {
- offset_.set_x(
- gfx::ToRoundedInt(SkMScalarToFloat(offset_.x() * decomp.scale[0])));
- }
- if (decomp.scale[1]) {
- offset_.set_y(
- gfx::ToRoundedInt(SkMScalarToFloat(offset_.y() * decomp.scale[1])));
- }
-}
+#endif
////////////////////////////////////////////////////////////////////////////////
// TouchEvent
-TouchEvent::TouchEvent()
- : LocatedEvent(),
- touch_id_(0),
- radius_x_(0),
- radius_y_(0),
- rotation_angle_(0),
- force_(0) {
+TouchEvent::TouchEvent(const base::NativeEvent& native_event)
+ : LocatedEvent(native_event),
+ touch_id_(GetTouchId(native_event)),
+ unique_event_id_(ui::GetNextTouchEventId()),
+ radius_x_(GetTouchRadiusX(native_event)),
+ radius_y_(GetTouchRadiusY(native_event)),
+ rotation_angle_(GetTouchAngle(native_event)),
+ force_(GetTouchForce(native_event)),
+ may_cause_scrolling_(false),
+ should_remove_native_touch_id_mapping_(false) {
+ latency()->AddLatencyNumberWithTimestamp(
+ INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0,
+ base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()), 1);
+ latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
+
+ FixRotationAngle();
+ if (type() == ET_TOUCH_RELEASED || type() == ET_TOUCH_CANCELLED)
+ should_remove_native_touch_id_mapping_ = true;
}
TouchEvent::TouchEvent(EventType type,
@@ -326,10 +536,13 @@ TouchEvent::TouchEvent(EventType type,
base::TimeDelta time_stamp)
: LocatedEvent(type, location, location, time_stamp, 0),
touch_id_(touch_id),
+ unique_event_id_(ui::GetNextTouchEventId()),
radius_x_(0.0f),
radius_y_(0.0f),
rotation_angle_(0.0f),
- force_(0.0f) {
+ force_(0.0f),
+ may_cause_scrolling_(false),
+ should_remove_native_touch_id_mapping_(false) {
latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
}
@@ -344,14 +557,41 @@ TouchEvent::TouchEvent(EventType type,
float force)
: LocatedEvent(type, location, location, time_stamp, flags),
touch_id_(touch_id),
+ unique_event_id_(ui::GetNextTouchEventId()),
radius_x_(radius_x),
radius_y_(radius_y),
rotation_angle_(angle),
- force_(force) {
+ force_(force),
+ may_cause_scrolling_(false),
+ should_remove_native_touch_id_mapping_(false) {
latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
+ FixRotationAngle();
+}
+
+TouchEvent::TouchEvent(const TouchEvent& copy)
+ : LocatedEvent(copy),
+ touch_id_(copy.touch_id_),
+ unique_event_id_(copy.unique_event_id_),
+ radius_x_(copy.radius_x_),
+ radius_y_(copy.radius_y_),
+ rotation_angle_(copy.rotation_angle_),
+ force_(copy.force_),
+ may_cause_scrolling_(copy.may_cause_scrolling_),
+ should_remove_native_touch_id_mapping_(false) {
+ // Copied events should not remove touch id mapping, as this either causes the
+ // mapping to be lost before the initial event has finished dispatching, or
+ // the copy to attempt to remove the mapping from a null |native_event_|.
}
TouchEvent::~TouchEvent() {
+ // In ctor TouchEvent(native_event) we call GetTouchId() which in X11
+ // platform setups the tracking_id to slot mapping. So in dtor here,
+ // if this touch event is a release event, we clear the mapping accordingly.
+ if (should_remove_native_touch_id_mapping_) {
+ DCHECK(type() == ET_TOUCH_RELEASED || type() == ET_TOUCH_CANCELLED);
+ if (type() == ET_TOUCH_RELEASED || type() == ET_TOUCH_CANCELLED)
+ ClearTouchIdIfReleased(native_event());
+ }
}
void TouchEvent::UpdateForRootTransform(
@@ -366,16 +606,84 @@ void TouchEvent::UpdateForRootTransform(
radius_y_ *= decomp.scale[1];
}
+void TouchEvent::DisableSynchronousHandling() {
+ DispatcherApi dispatcher_api(this);
+ dispatcher_api.set_result(
+ static_cast<EventResult>(result() | ER_DISABLE_SYNC_HANDLING));
+}
+
+void TouchEvent::FixRotationAngle() {
+ while (rotation_angle_ < 0)
+ rotation_angle_ += 180;
+ while (rotation_angle_ >= 180)
+ rotation_angle_ -= 180;
+}
+
////////////////////////////////////////////////////////////////////////////////
// KeyEvent
-KeyEvent::KeyEvent()
- : Event(),
- key_code_(VKEY_UNKNOWN),
- code_(),
- is_char_(false),
- platform_keycode_(0),
+// static
+KeyEvent* KeyEvent::last_key_event_ = NULL;
+
+// static
+bool KeyEvent::IsRepeated(const KeyEvent& event) {
+ // A safe guard in case if there were continous key pressed events that are
+ // not auto repeat.
+ const int kMaxAutoRepeatTimeMs = 2000;
+ // Ignore key events that have non standard state masks as it may be
+ // reposted by an IME. IBUS-GTK uses this field to detect the
+ // re-posted event for example. crbug.com/385873.
+ if (X11EventHasNonStandardState(event.native_event()))
+ return false;
+ if (event.is_char())
+ return false;
+ if (event.type() == ui::ET_KEY_RELEASED) {
+ delete last_key_event_;
+ last_key_event_ = NULL;
+ return false;
+ }
+ CHECK_EQ(ui::ET_KEY_PRESSED, event.type());
+ if (!last_key_event_) {
+ last_key_event_ = new KeyEvent(event);
+ return false;
+ } else if (event.time_stamp() == last_key_event_->time_stamp()) {
+ // The KeyEvent is created from the same native event.
+ return (last_key_event_->flags() & ui::EF_IS_REPEAT) != 0;
+ }
+ if (event.key_code() == last_key_event_->key_code() &&
+ event.flags() == (last_key_event_->flags() & ~ui::EF_IS_REPEAT) &&
+ (event.time_stamp() - last_key_event_->time_stamp()).InMilliseconds() <
+ kMaxAutoRepeatTimeMs) {
+ last_key_event_->set_time_stamp(event.time_stamp());
+ last_key_event_->set_flags(last_key_event_->flags() | ui::EF_IS_REPEAT);
+ return true;
+ }
+ delete last_key_event_;
+ last_key_event_ = new KeyEvent(event);
+ return false;
+}
+
+KeyEvent::KeyEvent(const base::NativeEvent& native_event)
+ : Event(native_event,
+ EventTypeFromNative(native_event),
+ EventFlagsFromNative(native_event)),
+ key_code_(KeyboardCodeFromNative(native_event)),
+ code_(CodeFromNative(native_event)),
+ is_char_(IsCharFromNative(native_event)),
+ platform_keycode_(PlatformKeycodeFromNative(native_event)),
+ key_(DomKey::NONE),
character_(0) {
+ if (IsRepeated(*this))
+ set_flags(flags() | ui::EF_IS_REPEAT);
+
+#if defined(USE_X11)
+ NormalizeFlags();
+#endif
+#if defined(OS_WIN)
+ // Only Windows has native character events.
+ if (is_char_)
+ character_ = native_event.wParam;
+#endif
}
KeyEvent::KeyEvent(EventType type,
@@ -383,29 +691,49 @@ KeyEvent::KeyEvent(EventType type,
int flags)
: Event(type, EventTimeForNow(), flags),
key_code_(key_code),
+ code_(UsLayoutKeyboardCodeToDomCode(key_code)),
is_char_(false),
platform_keycode_(0),
+ key_(DomKey::NONE),
character_() {
}
KeyEvent::KeyEvent(EventType type,
KeyboardCode key_code,
- const std::string& code,
+ DomCode code,
int flags)
: Event(type, EventTimeForNow(), flags),
key_code_(key_code),
code_(code),
is_char_(false),
platform_keycode_(0),
+ key_(DomKey::NONE),
character_(0) {
}
+KeyEvent::KeyEvent(EventType type,
+ KeyboardCode key_code,
+ DomCode code,
+ int flags,
+ DomKey key,
+ base::char16 character,
+ base::TimeDelta time_stamp)
+ : Event(type, time_stamp, flags),
+ key_code_(key_code),
+ code_(code),
+ is_char_(false),
+ platform_keycode_(0),
+ key_(key),
+ character_(character) {
+}
+
KeyEvent::KeyEvent(base::char16 character, KeyboardCode key_code, int flags)
: Event(ET_KEY_PRESSED, EventTimeForNow(), flags),
key_code_(key_code),
- code_(""),
+ code_(DomCode::NONE),
is_char_(true),
platform_keycode_(0),
+ key_(DomKey::CHARACTER),
character_(character) {
}
@@ -415,6 +743,7 @@ KeyEvent::KeyEvent(const KeyEvent& rhs)
code_(rhs.code_),
is_char_(rhs.is_char_),
platform_keycode_(rhs.platform_keycode_),
+ key_(rhs.key_),
character_(rhs.character_) {
if (rhs.extended_key_event_data_)
extended_key_event_data_.reset(rhs.extended_key_event_data_->Clone());
@@ -425,6 +754,7 @@ KeyEvent& KeyEvent::operator=(const KeyEvent& rhs) {
Event::operator=(rhs);
key_code_ = rhs.key_code_;
code_ = rhs.code_;
+ key_ = rhs.key_;
is_char_ = rhs.is_char_;
platform_keycode_ = rhs.platform_keycode_;
character_ = rhs.character_;
@@ -441,24 +771,80 @@ void KeyEvent::SetExtendedKeyEventData(scoped_ptr<ExtendedKeyEventData> data) {
extended_key_event_data_ = data.Pass();
}
-base::char16 KeyEvent::GetCharacter() const {
- if (is_char_ || character_)
- return character_;
-
- // TODO(kpschoedel): streamline these cases after settling Ozone
- // positional coding.
-#if defined(USE_X11)
- character_ = GetCharacterFromKeyCode(key_code_, flags());
- return character_;
+void KeyEvent::ApplyLayout() const {
+ // If the client has set the character (e.g. faked key events from virtual
+ // keyboard), it's client's responsibility to set the dom key correctly.
+ // Otherwise, set the dom key as unidentified.
+ // Please refer to crbug.com/443889.
+ if (character_ != 0) {
+ key_ = DomKey::UNIDENTIFIED;
+ return;
+ }
+ ui::DomCode code = code_;
+ if (code == DomCode::NONE) {
+ // Catch old code that tries to do layout without a physical key, and try
+ // to recover using the KeyboardCode. Once key events are fully defined
+ // on construction (see TODO in event.h) this will go away.
+ LOG(WARNING) << "DomCode::NONE keycode=" << key_code_;
+ code = UsLayoutKeyboardCodeToDomCode(key_code_);
+ if (code == DomCode::NONE) {
+ key_ = DomKey::UNIDENTIFIED;
+ return;
+ }
+ }
+ KeyboardCode dummy_key_code;
+#if defined(OS_WIN)
+// Native Windows character events always have is_char_ == true,
+// so this is a synthetic or native keystroke event.
+// Therefore, perform only the fallback action.
+#elif defined(USE_X11)
+ // When a control key is held, prefer ASCII characters to non ASCII
+ // characters in order to use it for shortcut keys. GetCharacterFromKeyCode
+ // returns 'a' for VKEY_A even if the key is actually bound to 'à' in X11.
+ // GetCharacterFromXEvent returns 'à' in that case.
+ if (!IsControlDown() && native_event()) {
+ GetMeaningFromXEvent(native_event(), &key_, &character_);
+ return;
+ }
+#elif defined(USE_OZONE)
+ if (KeyboardLayoutEngineManager::GetKeyboardLayoutEngine()->Lookup(
+ code, flags(), &key_, &character_, &dummy_key_code,
+ &platform_keycode_)) {
+ return;
+ }
#else
- return GetCharacterFromKeyCode(key_code_, flags());
+ if (native_event()) {
+ DCHECK(EventTypeFromNative(native_event()) == ET_KEY_PRESSED ||
+ EventTypeFromNative(native_event()) == ET_KEY_RELEASED);
+ }
#endif
+ if (!DomCodeToUsLayoutMeaning(code, flags(), &key_, &character_,
+ &dummy_key_code)) {
+ key_ = DomKey::UNIDENTIFIED;
+ }
+}
+
+DomKey KeyEvent::GetDomKey() const {
+ // Determination of character_ and key_ may be done lazily.
+ if (key_ == DomKey::NONE)
+ ApplyLayout();
+ return key_;
+}
+
+base::char16 KeyEvent::GetCharacter() const {
+ // Determination of character_ and key_ may be done lazily.
+ if (key_ == DomKey::NONE)
+ ApplyLayout();
+ return character_;
}
base::char16 KeyEvent::GetText() const {
if ((flags() & EF_CONTROL_DOWN) != 0) {
- return GetControlCharacterForKeycode(key_code_,
- (flags() & EF_SHIFT_DOWN) != 0);
+ base::char16 character;
+ ui::DomKey key;
+ ui::KeyboardCode key_code;
+ if (DomCodeToControlCharacter(code_, flags(), &key, &character, &key_code))
+ return character;
}
return GetUnmodifiedText();
}
@@ -470,7 +856,23 @@ base::char16 KeyEvent::GetUnmodifiedText() const {
}
bool KeyEvent::IsUnicodeKeyCode() const {
+#if defined(OS_WIN)
+ if (!IsAltDown())
+ return false;
+ const int key = key_code();
+ if (key >= VKEY_NUMPAD0 && key <= VKEY_NUMPAD9)
+ return true;
+ // Check whether the user is using the numeric keypad with num-lock off.
+ // In that case, EF_EXTENDED will not be set; if it is set, the key event
+ // originated from the relevant non-numpad dedicated key, e.g. [Insert].
+ return (!(flags() & EF_EXTENDED) &&
+ (key == VKEY_INSERT || key == VKEY_END || key == VKEY_DOWN ||
+ key == VKEY_NEXT || key == VKEY_LEFT || key == VKEY_CLEAR ||
+ key == VKEY_RIGHT || key == VKEY_HOME || key == VKEY_UP ||
+ key == VKEY_PRIOR));
+#else
return false;
+#endif
}
void KeyEvent::NormalizeFlags() {
@@ -497,104 +899,8 @@ void KeyEvent::NormalizeFlags() {
set_flags(flags() & ~mask);
}
-bool KeyEvent::IsTranslated() const {
- switch (type()) {
- case ET_KEY_PRESSED:
- case ET_KEY_RELEASED:
- return false;
- case ET_TRANSLATED_KEY_PRESS:
- case ET_TRANSLATED_KEY_RELEASE:
- return true;
- default:
- NOTREACHED();
- return false;
- }
-}
-
-void KeyEvent::SetTranslated(bool translated) {
- switch (type()) {
- case ET_KEY_PRESSED:
- case ET_TRANSLATED_KEY_PRESS:
- SetType(translated ? ET_TRANSLATED_KEY_PRESS : ET_KEY_PRESSED);
- break;
- case ET_KEY_RELEASED:
- case ET_TRANSLATED_KEY_RELEASE:
- SetType(translated ? ET_TRANSLATED_KEY_RELEASE : ET_KEY_RELEASED);
- break;
- default:
- NOTREACHED();
- }
-}
-
-bool KeyEvent::IsRightSideKey() const {
- switch (key_code_) {
- case VKEY_CONTROL:
- case VKEY_SHIFT:
- case VKEY_MENU:
- case VKEY_LWIN:
-#if defined(USE_X11)
- // Under X11, setting code_ requires platform-dependent information, and
- // currently assumes that X keycodes are based on Linux evdev keycodes.
- // In certain test environments this is not the case, and code_ is not
- // set accurately, so we need a different mechanism. Fortunately X11 key
- // mapping preserves the left-right distinction, so testing keysyms works
- // if the value is available (as it is for all X11 native-based events).
- if (platform_keycode_) {
- return (platform_keycode_ == XK_Shift_R) ||
- (platform_keycode_ == XK_Control_R) ||
- (platform_keycode_ == XK_Alt_R) ||
- (platform_keycode_ == XK_Meta_R) ||
- (platform_keycode_ == XK_Super_R) ||
- (platform_keycode_ == XK_Hyper_R);
- }
- // Fall through to the generic code if we have no platform_keycode_.
- // Under X11, this must be a synthetic event, so we can require that
- // code_ be set correctly.
-#endif
- return ((code_.size() > 5) &&
- (code_.compare(code_.size() - 5, 5, "Right", 5)) == 0);
- default:
- return false;
- }
-}
-
KeyboardCode KeyEvent::GetLocatedWindowsKeyboardCode() const {
- switch (key_code_) {
- case VKEY_SHIFT:
- return IsRightSideKey() ? VKEY_RSHIFT : VKEY_LSHIFT;
- case VKEY_CONTROL:
- return IsRightSideKey() ? VKEY_RCONTROL : VKEY_LCONTROL;
- case VKEY_MENU:
- return IsRightSideKey() ? VKEY_RMENU : VKEY_LMENU;
- case VKEY_LWIN:
- return IsRightSideKey() ? VKEY_RWIN : VKEY_LWIN;
- // TODO(kpschoedel): EF_NUMPAD_KEY is present only on X11. Currently this
- // function is only called on X11. Likely the tests here will be replaced
- // with a DOM-based code enumeration test in the course of Ozone
- // platform-indpendent key event work.
- case VKEY_0:
- return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD0 : VKEY_0;
- case VKEY_1:
- return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD1 : VKEY_1;
- case VKEY_2:
- return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD2 : VKEY_2;
- case VKEY_3:
- return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD3 : VKEY_3;
- case VKEY_4:
- return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD4 : VKEY_4;
- case VKEY_5:
- return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD5 : VKEY_5;
- case VKEY_6:
- return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD6 : VKEY_6;
- case VKEY_7:
- return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD7 : VKEY_7;
- case VKEY_8:
- return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD8 : VKEY_8;
- case VKEY_9:
- return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD9 : VKEY_9;
- default:
- return key_code_;
- }
+ return NonLocatedToLocatedKeyboardCode(key_code_, code_);
}
uint16 KeyEvent::GetConflatedWindowsKeyCode() const {
@@ -603,10 +909,30 @@ uint16 KeyEvent::GetConflatedWindowsKeyCode() const {
return key_code_;
}
+std::string KeyEvent::GetCodeString() const {
+ return KeycodeConverter::DomCodeToCodeString(code_);
+}
+
////////////////////////////////////////////////////////////////////////////////
// ScrollEvent
-ScrollEvent::ScrollEvent() : MouseEvent() {
+ScrollEvent::ScrollEvent(const base::NativeEvent& native_event)
+ : MouseEvent(native_event) {
+ if (type() == ET_SCROLL) {
+ GetScrollOffsets(native_event,
+ &x_offset_, &y_offset_,
+ &x_offset_ordinal_, &y_offset_ordinal_,
+ &finger_count_);
+ } else if (type() == ET_SCROLL_FLING_START ||
+ type() == ET_SCROLL_FLING_CANCEL) {
+ GetFlingData(native_event,
+ &x_offset_, &y_offset_,
+ &x_offset_ordinal_, &y_offset_ordinal_,
+ NULL);
+ } else {
+ NOTREACHED() << "Unexpected event type " << type()
+ << " when constructing a ScrollEvent.";
+ }
}
ScrollEvent::ScrollEvent(EventType type,
@@ -618,13 +944,12 @@ ScrollEvent::ScrollEvent(EventType type,
float x_offset_ordinal,
float y_offset_ordinal,
int finger_count)
- : MouseEvent(type, location, location, flags, 0),
+ : MouseEvent(type, location, location, time_stamp, flags, 0),
x_offset_(x_offset),
y_offset_(y_offset),
x_offset_ordinal_(x_offset_ordinal),
y_offset_ordinal_(y_offset_ordinal),
finger_count_(finger_count) {
- set_time_stamp(time_stamp);
CHECK(IsScrollEvent());
}
« no previous file with comments | « ui/events/event.h ('k') | ui/events/event_constants.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698