1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/events/event.h"
8 #include <X11/extensions/XInput2.h>
10 #include <X11/keysym.h>
16 #include "base/metrics/histogram.h"
17 #include "base/strings/stringprintf.h"
18 #include "ui/events/event_utils.h"
19 #include "ui/events/keycodes/keyboard_code_conversion.h"
20 #include "ui/gfx/geometry/safe_integer_conversions.h"
21 #include "ui/gfx/point3_f.h"
22 #include "ui/gfx/point_conversions.h"
23 #include "ui/gfx/transform.h"
24 #include "ui/gfx/transform_util.h"
27 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
28 #elif defined(USE_OZONE)
29 #include "ui/events/keycodes/keyboard_code_conversion.h"
34 std::string EventTypeName(ui::EventType type) {
35 #define RETURN_IF_TYPE(t) if (type == ui::t) return #t
36 #define CASE_TYPE(t) case ui::t: return #t
38 CASE_TYPE(ET_UNKNOWN);
39 CASE_TYPE(ET_MOUSE_PRESSED);
40 CASE_TYPE(ET_MOUSE_DRAGGED);
41 CASE_TYPE(ET_MOUSE_RELEASED);
42 CASE_TYPE(ET_MOUSE_MOVED);
43 CASE_TYPE(ET_MOUSE_ENTERED);
44 CASE_TYPE(ET_MOUSE_EXITED);
45 CASE_TYPE(ET_KEY_PRESSED);
46 CASE_TYPE(ET_KEY_RELEASED);
47 CASE_TYPE(ET_MOUSEWHEEL);
48 CASE_TYPE(ET_MOUSE_CAPTURE_CHANGED);
49 CASE_TYPE(ET_TOUCH_RELEASED);
50 CASE_TYPE(ET_TOUCH_PRESSED);
51 CASE_TYPE(ET_TOUCH_MOVED);
52 CASE_TYPE(ET_TOUCH_CANCELLED);
53 CASE_TYPE(ET_DROP_TARGET_EVENT);
54 CASE_TYPE(ET_TRANSLATED_KEY_PRESS);
55 CASE_TYPE(ET_TRANSLATED_KEY_RELEASE);
56 CASE_TYPE(ET_GESTURE_SCROLL_BEGIN);
57 CASE_TYPE(ET_GESTURE_SCROLL_END);
58 CASE_TYPE(ET_GESTURE_SCROLL_UPDATE);
59 CASE_TYPE(ET_GESTURE_SHOW_PRESS);
60 CASE_TYPE(ET_GESTURE_WIN8_EDGE_SWIPE);
61 CASE_TYPE(ET_GESTURE_TAP);
62 CASE_TYPE(ET_GESTURE_TAP_DOWN);
63 CASE_TYPE(ET_GESTURE_TAP_CANCEL);
64 CASE_TYPE(ET_GESTURE_BEGIN);
65 CASE_TYPE(ET_GESTURE_END);
66 CASE_TYPE(ET_GESTURE_TWO_FINGER_TAP);
67 CASE_TYPE(ET_GESTURE_PINCH_BEGIN);
68 CASE_TYPE(ET_GESTURE_PINCH_END);
69 CASE_TYPE(ET_GESTURE_PINCH_UPDATE);
70 CASE_TYPE(ET_GESTURE_LONG_PRESS);
71 CASE_TYPE(ET_GESTURE_LONG_TAP);
72 CASE_TYPE(ET_GESTURE_SWIPE);
73 CASE_TYPE(ET_GESTURE_TAP_UNCONFIRMED);
74 CASE_TYPE(ET_GESTURE_DOUBLE_TAP);
76 CASE_TYPE(ET_SCROLL_FLING_START);
77 CASE_TYPE(ET_SCROLL_FLING_CANCEL);
78 CASE_TYPE(ET_CANCEL_MODE);
79 CASE_TYPE(ET_UMA_DATA);
80 case ui::ET_LAST: NOTREACHED(); return std::string();
81 // Don't include default, so that we get an error when new type is added.
89 bool IsX11SendEventTrue(const base::NativeEvent& event) {
91 return event && event->xany.send_event;
97 bool X11EventHasNonStandardState(const base::NativeEvent& event) {
99 const unsigned int kAllStateMask =
100 Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask |
101 Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask |
102 LockMask | ControlMask | AnyModifier;
103 return event && (event->xkey.state & ~kAllStateMask) != 0;
113 ////////////////////////////////////////////////////////////////////////////////
117 scoped_ptr<Event> Event::Clone(const Event& event) {
118 if (event.IsKeyEvent()) {
119 return scoped_ptr<Event>(new KeyEvent(static_cast<const KeyEvent&>(event)));
122 if (event.IsMouseEvent()) {
123 if (event.IsMouseWheelEvent()) {
124 return scoped_ptr<Event>(
125 new MouseWheelEvent(static_cast<const MouseWheelEvent&>(event)));
128 return scoped_ptr<Event>(
129 new MouseEvent(static_cast<const MouseEvent&>(event)));
132 if (event.IsTouchEvent()) {
133 return scoped_ptr<Event>(
134 new TouchEvent(static_cast<const TouchEvent&>(event)));
137 if (event.IsGestureEvent()) {
138 return scoped_ptr<Event>(
139 new GestureEvent(static_cast<const GestureEvent&>(event)));
142 if (event.IsScrollEvent()) {
143 return scoped_ptr<Event>(
144 new ScrollEvent(static_cast<const ScrollEvent&>(event)));
147 return scoped_ptr<Event>(new Event(event));
151 if (delete_native_event_)
152 ReleaseCopiedNativeEvent(native_event_);
155 GestureEvent* Event::AsGestureEvent() {
156 CHECK(IsGestureEvent());
157 return static_cast<GestureEvent*>(this);
160 const GestureEvent* Event::AsGestureEvent() const {
161 CHECK(IsGestureEvent());
162 return static_cast<const GestureEvent*>(this);
165 bool Event::HasNativeEvent() const {
166 base::NativeEvent null_event;
167 std::memset(&null_event, 0, sizeof(null_event));
168 return !!std::memcmp(&native_event_, &null_event, sizeof(null_event));
171 void Event::StopPropagation() {
172 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
174 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
176 result_ = static_cast<EventResult>(result_ | ER_CONSUMED);
179 void Event::SetHandled() {
180 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
182 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
184 result_ = static_cast<EventResult>(result_ | ER_HANDLED);
187 Event::Event(EventType type, base::TimeDelta time_stamp, int flags)
189 time_stamp_(time_stamp),
191 native_event_(base::NativeEvent()),
192 delete_native_event_(false),
195 phase_(EP_PREDISPATCH),
196 result_(ER_UNHANDLED),
197 source_device_id_(ED_UNKNOWN_DEVICE) {
199 name_ = EventTypeName(type_);
202 Event::Event(const base::NativeEvent& native_event,
206 time_stamp_(EventTimeFromNative(native_event)),
208 native_event_(native_event),
209 delete_native_event_(false),
212 phase_(EP_PREDISPATCH),
213 result_(ER_UNHANDLED),
214 source_device_id_(ED_UNKNOWN_DEVICE) {
215 base::TimeDelta delta = EventTimeForNow() - time_stamp_;
217 name_ = EventTypeName(type_);
218 base::HistogramBase::Sample delta_sample =
219 static_cast<base::HistogramBase::Sample>(delta.InMicroseconds());
220 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser", delta_sample, 1, 1000000,
222 std::string name_for_event =
223 base::StringPrintf("Event.Latency.Browser.%s", name_.c_str());
224 base::HistogramBase* counter_for_type =
225 base::Histogram::FactoryGet(
230 base::HistogramBase::kUmaTargetedHistogramFlag);
231 counter_for_type->Add(delta_sample);
234 if (native_event->type == GenericEvent) {
235 XIDeviceEvent* xiev =
236 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
237 source_device_id_ = xiev->sourceid;
242 Event::Event(const Event& copy)
244 time_stamp_(copy.time_stamp_),
245 latency_(copy.latency_),
247 native_event_(CopyNativeEvent(copy.native_event_)),
248 delete_native_event_(true),
251 phase_(EP_PREDISPATCH),
252 result_(ER_UNHANDLED),
253 source_device_id_(copy.source_device_id_) {
255 name_ = EventTypeName(type_);
258 void Event::SetType(EventType type) {
260 name_ = std::string();
263 name_ = EventTypeName(type_);
266 ////////////////////////////////////////////////////////////////////////////////
269 CancelModeEvent::CancelModeEvent()
270 : Event(ET_CANCEL_MODE, base::TimeDelta(), 0) {
271 set_cancelable(false);
274 CancelModeEvent::~CancelModeEvent() {
277 ////////////////////////////////////////////////////////////////////////////////
280 LocatedEvent::~LocatedEvent() {
283 LocatedEvent::LocatedEvent(const base::NativeEvent& native_event)
284 : Event(native_event,
285 EventTypeFromNative(native_event),
286 EventFlagsFromNative(native_event)),
287 location_(EventLocationFromNative(native_event)),
288 root_location_(location_) {
291 LocatedEvent::LocatedEvent(EventType type,
292 const gfx::PointF& location,
293 const gfx::PointF& root_location,
294 base::TimeDelta time_stamp,
296 : Event(type, time_stamp, flags),
298 root_location_(root_location) {
301 void LocatedEvent::UpdateForRootTransform(
302 const gfx::Transform& reversed_root_transform) {
303 // Transform has to be done at root level.
304 gfx::Point3F p(location_);
305 reversed_root_transform.TransformPoint(&p);
306 location_ = p.AsPointF();
307 root_location_ = location_;
310 ////////////////////////////////////////////////////////////////////////////////
313 MouseEvent::MouseEvent(const base::NativeEvent& native_event)
314 : LocatedEvent(native_event),
315 changed_button_flags_(
316 GetChangedMouseButtonFlagsFromNative(native_event)) {
317 if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED)
318 SetClickCount(GetRepeatCount(*this));
321 MouseEvent::MouseEvent(EventType type,
322 const gfx::PointF& location,
323 const gfx::PointF& root_location,
325 int changed_button_flags)
326 : LocatedEvent(type, location, root_location, EventTimeForNow(), flags),
327 changed_button_flags_(changed_button_flags) {
328 if (this->type() == ET_MOUSE_MOVED && IsAnyButton())
329 SetType(ET_MOUSE_DRAGGED);
333 bool MouseEvent::IsRepeatedClickEvent(
334 const MouseEvent& event1,
335 const MouseEvent& event2) {
336 // These values match the Windows defaults.
337 static const int kDoubleClickTimeMS = 500;
338 static const int kDoubleClickWidth = 4;
339 static const int kDoubleClickHeight = 4;
341 if (event1.type() != ET_MOUSE_PRESSED ||
342 event2.type() != ET_MOUSE_PRESSED)
345 // Compare flags, but ignore EF_IS_DOUBLE_CLICK to allow triple clicks.
346 if ((event1.flags() & ~EF_IS_DOUBLE_CLICK) !=
347 (event2.flags() & ~EF_IS_DOUBLE_CLICK))
350 base::TimeDelta time_difference = event2.time_stamp() - event1.time_stamp();
352 if (time_difference.InMilliseconds() > kDoubleClickTimeMS)
355 if (std::abs(event2.x() - event1.x()) > kDoubleClickWidth / 2)
358 if (std::abs(event2.y() - event1.y()) > kDoubleClickHeight / 2)
365 int MouseEvent::GetRepeatCount(const MouseEvent& event) {
367 if (last_click_event_) {
368 if (event.type() == ui::ET_MOUSE_RELEASED) {
369 if (event.changed_button_flags() ==
370 last_click_event_->changed_button_flags()) {
371 last_click_complete_ = true;
372 return last_click_event_->GetClickCount();
374 // If last_click_event_ has changed since this button was pressed
375 // return a click count of 1.
379 if (event.time_stamp() != last_click_event_->time_stamp())
380 last_click_complete_ = true;
381 if (!last_click_complete_ ||
382 IsX11SendEventTrue(event.native_event())) {
383 click_count = last_click_event_->GetClickCount();
384 } else if (IsRepeatedClickEvent(*last_click_event_, event)) {
385 click_count = last_click_event_->GetClickCount() + 1;
387 delete last_click_event_;
389 last_click_event_ = new MouseEvent(event);
390 last_click_complete_ = false;
393 last_click_event_->SetClickCount(click_count);
397 void MouseEvent::ResetLastClickForTest() {
398 if (last_click_event_) {
399 delete last_click_event_;
400 last_click_event_ = NULL;
401 last_click_complete_ = false;
406 MouseEvent* MouseEvent::last_click_event_ = NULL;
407 bool MouseEvent::last_click_complete_ = false;
409 int MouseEvent::GetClickCount() const {
410 if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
413 if (flags() & EF_IS_TRIPLE_CLICK)
415 else if (flags() & EF_IS_DOUBLE_CLICK)
421 void MouseEvent::SetClickCount(int click_count) {
422 if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
425 DCHECK(click_count > 0);
426 DCHECK(click_count <= 3);
429 switch (click_count) {
431 f &= ~EF_IS_DOUBLE_CLICK;
432 f &= ~EF_IS_TRIPLE_CLICK;
435 f |= EF_IS_DOUBLE_CLICK;
436 f &= ~EF_IS_TRIPLE_CLICK;
439 f &= ~EF_IS_DOUBLE_CLICK;
440 f |= EF_IS_TRIPLE_CLICK;
446 ////////////////////////////////////////////////////////////////////////////////
449 MouseWheelEvent::MouseWheelEvent(const base::NativeEvent& native_event)
450 : MouseEvent(native_event),
451 offset_(GetMouseWheelOffset(native_event)) {
454 MouseWheelEvent::MouseWheelEvent(const ScrollEvent& scroll_event)
455 : MouseEvent(scroll_event),
456 offset_(gfx::ToRoundedInt(scroll_event.x_offset()),
457 gfx::ToRoundedInt(scroll_event.y_offset())) {
458 SetType(ET_MOUSEWHEEL);
461 MouseWheelEvent::MouseWheelEvent(const MouseEvent& mouse_event,
464 : MouseEvent(mouse_event), offset_(x_offset, y_offset) {
465 DCHECK(type() == ET_MOUSEWHEEL);
468 MouseWheelEvent::MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event)
469 : MouseEvent(mouse_wheel_event),
470 offset_(mouse_wheel_event.offset()) {
471 DCHECK(type() == ET_MOUSEWHEEL);
474 MouseWheelEvent::MouseWheelEvent(const gfx::Vector2d& offset,
475 const gfx::PointF& location,
476 const gfx::PointF& root_location,
478 int changed_button_flags)
479 : MouseEvent(ui::ET_MOUSEWHEEL, location, root_location, flags,
480 changed_button_flags),
485 // This value matches windows WHEEL_DELTA.
487 const int MouseWheelEvent::kWheelDelta = 120;
489 // This value matches GTK+ wheel scroll amount.
490 const int MouseWheelEvent::kWheelDelta = 53;
493 void MouseWheelEvent::UpdateForRootTransform(
494 const gfx::Transform& inverted_root_transform) {
495 LocatedEvent::UpdateForRootTransform(inverted_root_transform);
496 gfx::DecomposedTransform decomp;
497 bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
499 if (decomp.scale[0]) {
501 gfx::ToRoundedInt(SkMScalarToFloat(offset_.x() * decomp.scale[0])));
503 if (decomp.scale[1]) {
505 gfx::ToRoundedInt(SkMScalarToFloat(offset_.y() * decomp.scale[1])));
509 ////////////////////////////////////////////////////////////////////////////////
512 TouchEvent::TouchEvent(const base::NativeEvent& native_event)
513 : LocatedEvent(native_event),
514 touch_id_(GetTouchId(native_event)),
515 radius_x_(GetTouchRadiusX(native_event)),
516 radius_y_(GetTouchRadiusY(native_event)),
517 rotation_angle_(GetTouchAngle(native_event)),
518 force_(GetTouchForce(native_event)) {
519 latency()->AddLatencyNumberWithTimestamp(
520 INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
523 base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()),
526 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
528 if (type() == ET_TOUCH_PRESSED)
529 IncrementTouchIdRefCount(native_event);
532 TouchEvent::TouchEvent(EventType type,
533 const gfx::PointF& location,
535 base::TimeDelta time_stamp)
536 : LocatedEvent(type, location, location, time_stamp, 0),
540 rotation_angle_(0.0f),
542 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
545 TouchEvent::TouchEvent(EventType type,
546 const gfx::PointF& location,
549 base::TimeDelta time_stamp,
554 : LocatedEvent(type, location, location, time_stamp, flags),
558 rotation_angle_(angle),
560 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
563 TouchEvent::~TouchEvent() {
564 // In ctor TouchEvent(native_event) we call GetTouchId() which in X11
565 // platform setups the tracking_id to slot mapping. So in dtor here,
566 // if this touch event is a release event, we clear the mapping accordingly.
567 if (HasNativeEvent())
568 ClearTouchIdIfReleased(native_event());
571 void TouchEvent::UpdateForRootTransform(
572 const gfx::Transform& inverted_root_transform) {
573 LocatedEvent::UpdateForRootTransform(inverted_root_transform);
574 gfx::DecomposedTransform decomp;
575 bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
578 radius_x_ *= decomp.scale[0];
580 radius_y_ *= decomp.scale[1];
583 ////////////////////////////////////////////////////////////////////////////////
587 KeyEvent* KeyEvent::last_key_event_ = NULL;
590 bool KeyEvent::IsRepeated(const KeyEvent& event) {
591 // A safe guard in case if there were continous key pressed events that are
593 const int kMaxAutoRepeatTimeMs = 2000;
594 // Ignore key events that have non standard state masks as it may be
595 // reposted by an IME. IBUS-GTK uses this field to detect the
596 // re-posted event for example. crbug.com/385873.
597 if (X11EventHasNonStandardState(event.native_event()))
601 if (event.type() == ui::ET_KEY_RELEASED) {
602 delete last_key_event_;
603 last_key_event_ = NULL;
606 CHECK_EQ(ui::ET_KEY_PRESSED, event.type());
607 if (!last_key_event_) {
608 last_key_event_ = new KeyEvent(event);
611 if (event.key_code() == last_key_event_->key_code() &&
612 event.flags() == last_key_event_->flags() &&
613 (event.time_stamp() - last_key_event_->time_stamp()).InMilliseconds() <
614 kMaxAutoRepeatTimeMs) {
615 last_key_event_->set_time_stamp(event.time_stamp());
618 delete last_key_event_;
619 last_key_event_ = new KeyEvent(event);
623 KeyEvent::KeyEvent(const base::NativeEvent& native_event)
624 : Event(native_event,
625 EventTypeFromNative(native_event),
626 EventFlagsFromNative(native_event)),
627 key_code_(KeyboardCodeFromNative(native_event)),
628 code_(CodeFromNative(native_event)),
629 is_char_(IsCharFromNative(native_event)),
630 platform_keycode_(PlatformKeycodeFromNative(native_event)),
632 if (IsRepeated(*this))
633 set_flags(flags() | ui::EF_IS_REPEAT);
639 // Only Windows has native character events.
641 character_ = native_event.wParam;
645 KeyEvent::KeyEvent(EventType type,
646 KeyboardCode key_code,
648 : Event(type, EventTimeForNow(), flags),
651 platform_keycode_(0),
655 KeyEvent::KeyEvent(EventType type,
656 KeyboardCode key_code,
657 const std::string& code,
659 : Event(type, EventTimeForNow(), flags),
663 platform_keycode_(0),
667 KeyEvent::KeyEvent(base::char16 character, KeyboardCode key_code, int flags)
668 : Event(ET_KEY_PRESSED, EventTimeForNow(), flags),
672 platform_keycode_(0),
673 character_(character) {
676 KeyEvent::KeyEvent(const KeyEvent& rhs)
678 key_code_(rhs.key_code_),
680 is_char_(rhs.is_char_),
681 platform_keycode_(rhs.platform_keycode_),
682 character_(rhs.character_) {
683 if (rhs.extended_key_event_data_)
684 extended_key_event_data_.reset(rhs.extended_key_event_data_->Clone());
687 KeyEvent& KeyEvent::operator=(const KeyEvent& rhs) {
689 Event::operator=(rhs);
690 key_code_ = rhs.key_code_;
692 is_char_ = rhs.is_char_;
693 platform_keycode_ = rhs.platform_keycode_;
694 character_ = rhs.character_;
696 if (rhs.extended_key_event_data_)
697 extended_key_event_data_.reset(rhs.extended_key_event_data_->Clone());
702 KeyEvent::~KeyEvent() {}
704 void KeyEvent::SetExtendedKeyEventData(scoped_ptr<ExtendedKeyEventData> data) {
705 extended_key_event_data_ = data.Pass();
708 base::char16 KeyEvent::GetCharacter() const {
709 if (is_char_ || character_)
712 // TODO(kpschoedel): streamline these cases after settling Ozone
713 // positional coding.
715 // Native Windows character events always have is_char_ == true,
716 // so this is a synthetic or native keystroke event.
717 character_ = GetCharacterFromKeyCode(key_code_, flags());
719 #elif defined(USE_X11)
720 if (!native_event()) {
721 character_ = GetCharacterFromKeyCode(key_code_, flags());
725 DCHECK(native_event()->type == KeyPress ||
726 native_event()->type == KeyRelease ||
727 (native_event()->type == GenericEvent &&
728 (native_event()->xgeneric.evtype == XI_KeyPress ||
729 native_event()->xgeneric.evtype == XI_KeyRelease)));
731 // When a control key is held, prefer ASCII characters to non ASCII
732 // characters in order to use it for shortcut keys. GetCharacterFromKeyCode
733 // returns 'a' for VKEY_A even if the key is actually bound to 'Ã ' in X11.
734 // GetCharacterFromXEvent returns 'Ã ' in that case.
735 return IsControlDown() ?
736 GetCharacterFromKeyCode(key_code_, flags()) :
737 GetCharacterFromXEvent(native_event());
739 if (native_event()) {
740 DCHECK(EventTypeFromNative(native_event()) == ET_KEY_PRESSED ||
741 EventTypeFromNative(native_event()) == ET_KEY_RELEASED);
744 return GetCharacterFromKeyCode(key_code_, flags());
748 base::char16 KeyEvent::GetText() const {
749 if ((flags() & EF_CONTROL_DOWN) != 0) {
750 return GetControlCharacterForKeycode(key_code_,
751 (flags() & EF_SHIFT_DOWN) != 0);
753 return GetUnmodifiedText();
756 base::char16 KeyEvent::GetUnmodifiedText() const {
757 if (!is_char_ && (key_code_ == VKEY_RETURN))
759 return GetCharacter();
762 bool KeyEvent::IsUnicodeKeyCode() const {
766 const int key = key_code();
767 if (key >= VKEY_NUMPAD0 && key <= VKEY_NUMPAD9)
769 // Check whether the user is using the numeric keypad with num-lock off.
770 // In that case, EF_EXTENDED will not be set; if it is set, the key event
771 // originated from the relevant non-numpad dedicated key, e.g. [Insert].
772 return (!(flags() & EF_EXTENDED) &&
773 (key == VKEY_INSERT || key == VKEY_END || key == VKEY_DOWN ||
774 key == VKEY_NEXT || key == VKEY_LEFT || key == VKEY_CLEAR ||
775 key == VKEY_RIGHT || key == VKEY_HOME || key == VKEY_UP ||
782 void KeyEvent::NormalizeFlags() {
784 switch (key_code()) {
786 mask = EF_CONTROL_DOWN;
789 mask = EF_SHIFT_DOWN;
795 mask = EF_CAPS_LOCK_DOWN;
800 if (type() == ET_KEY_PRESSED)
801 set_flags(flags() | mask);
803 set_flags(flags() & ~mask);
806 bool KeyEvent::IsTranslated() const {
809 case ET_KEY_RELEASED:
811 case ET_TRANSLATED_KEY_PRESS:
812 case ET_TRANSLATED_KEY_RELEASE:
820 void KeyEvent::SetTranslated(bool translated) {
823 case ET_TRANSLATED_KEY_PRESS:
824 SetType(translated ? ET_TRANSLATED_KEY_PRESS : ET_KEY_PRESSED);
826 case ET_KEY_RELEASED:
827 case ET_TRANSLATED_KEY_RELEASE:
828 SetType(translated ? ET_TRANSLATED_KEY_RELEASE : ET_KEY_RELEASED);
835 bool KeyEvent::IsRightSideKey() const {
842 // Under X11, setting code_ requires platform-dependent information, and
843 // currently assumes that X keycodes are based on Linux evdev keycodes.
844 // In certain test environments this is not the case, and code_ is not
845 // set accurately, so we need a different mechanism. Fortunately X11 key
846 // mapping preserves the left-right distinction, so testing keysyms works
847 // if the value is available (as it is for all X11 native-based events).
848 if (platform_keycode_) {
849 return (platform_keycode_ == XK_Shift_R) ||
850 (platform_keycode_ == XK_Control_R) ||
851 (platform_keycode_ == XK_Alt_R) ||
852 (platform_keycode_ == XK_Meta_R) ||
853 (platform_keycode_ == XK_Super_R) ||
854 (platform_keycode_ == XK_Hyper_R);
856 // Fall through to the generic code if we have no platform_keycode_.
857 // Under X11, this must be a synthetic event, so we can require that
858 // code_ be set correctly.
860 return ((code_.size() > 5) &&
861 (code_.compare(code_.size() - 5, 5, "Right", 5)) == 0);
867 KeyboardCode KeyEvent::GetLocatedWindowsKeyboardCode() const {
870 return IsRightSideKey() ? VKEY_RSHIFT : VKEY_LSHIFT;
872 return IsRightSideKey() ? VKEY_RCONTROL : VKEY_LCONTROL;
874 return IsRightSideKey() ? VKEY_RMENU : VKEY_LMENU;
876 return IsRightSideKey() ? VKEY_RWIN : VKEY_LWIN;
877 // TODO(kpschoedel): EF_NUMPAD_KEY is present only on X11. Currently this
878 // function is only called on X11. Likely the tests here will be replaced
879 // with a DOM-based code enumeration test in the course of Ozone
880 // platform-indpendent key event work.
882 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD0 : VKEY_0;
884 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD1 : VKEY_1;
886 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD2 : VKEY_2;
888 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD3 : VKEY_3;
890 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD4 : VKEY_4;
892 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD5 : VKEY_5;
894 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD6 : VKEY_6;
896 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD7 : VKEY_7;
898 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD8 : VKEY_8;
900 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD9 : VKEY_9;
906 uint16 KeyEvent::GetConflatedWindowsKeyCode() const {
912 ////////////////////////////////////////////////////////////////////////////////
915 ScrollEvent::ScrollEvent(const base::NativeEvent& native_event)
916 : MouseEvent(native_event) {
917 if (type() == ET_SCROLL) {
918 GetScrollOffsets(native_event,
919 &x_offset_, &y_offset_,
920 &x_offset_ordinal_, &y_offset_ordinal_,
922 } else if (type() == ET_SCROLL_FLING_START ||
923 type() == ET_SCROLL_FLING_CANCEL) {
924 GetFlingData(native_event,
925 &x_offset_, &y_offset_,
926 &x_offset_ordinal_, &y_offset_ordinal_,
929 NOTREACHED() << "Unexpected event type " << type()
930 << " when constructing a ScrollEvent.";
934 ScrollEvent::ScrollEvent(EventType type,
935 const gfx::PointF& location,
936 base::TimeDelta time_stamp,
940 float x_offset_ordinal,
941 float y_offset_ordinal,
943 : MouseEvent(type, location, location, flags, 0),
946 x_offset_ordinal_(x_offset_ordinal),
947 y_offset_ordinal_(y_offset_ordinal),
948 finger_count_(finger_count) {
949 set_time_stamp(time_stamp);
950 CHECK(IsScrollEvent());
953 void ScrollEvent::Scale(const float factor) {
956 x_offset_ordinal_ *= factor;
957 y_offset_ordinal_ *= factor;
960 ////////////////////////////////////////////////////////////////////////////////
963 GestureEvent::GestureEvent(float x,
966 base::TimeDelta time_stamp,
967 const GestureEventDetails& details)
968 : LocatedEvent(details.type(),
972 flags | EF_FROM_TOUCH),
976 GestureEvent::~GestureEvent() {