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/point3_f.h"
21 #include "ui/gfx/point_conversions.h"
22 #include "ui/gfx/transform.h"
23 #include "ui/gfx/transform_util.h"
26 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
27 #elif defined(USE_OZONE)
28 #include "ui/events/keycodes/keyboard_code_conversion.h"
33 std::string
EventTypeName(ui::EventType type
) {
34 #define RETURN_IF_TYPE(t) if (type == ui::t) return #t
35 #define CASE_TYPE(t) case ui::t: return #t
37 CASE_TYPE(ET_UNKNOWN
);
38 CASE_TYPE(ET_MOUSE_PRESSED
);
39 CASE_TYPE(ET_MOUSE_DRAGGED
);
40 CASE_TYPE(ET_MOUSE_RELEASED
);
41 CASE_TYPE(ET_MOUSE_MOVED
);
42 CASE_TYPE(ET_MOUSE_ENTERED
);
43 CASE_TYPE(ET_MOUSE_EXITED
);
44 CASE_TYPE(ET_KEY_PRESSED
);
45 CASE_TYPE(ET_KEY_RELEASED
);
46 CASE_TYPE(ET_MOUSEWHEEL
);
47 CASE_TYPE(ET_MOUSE_CAPTURE_CHANGED
);
48 CASE_TYPE(ET_TOUCH_RELEASED
);
49 CASE_TYPE(ET_TOUCH_PRESSED
);
50 CASE_TYPE(ET_TOUCH_MOVED
);
51 CASE_TYPE(ET_TOUCH_CANCELLED
);
52 CASE_TYPE(ET_DROP_TARGET_EVENT
);
53 CASE_TYPE(ET_TRANSLATED_KEY_PRESS
);
54 CASE_TYPE(ET_TRANSLATED_KEY_RELEASE
);
55 CASE_TYPE(ET_GESTURE_SCROLL_BEGIN
);
56 CASE_TYPE(ET_GESTURE_SCROLL_END
);
57 CASE_TYPE(ET_GESTURE_SCROLL_UPDATE
);
58 CASE_TYPE(ET_GESTURE_SHOW_PRESS
);
59 CASE_TYPE(ET_GESTURE_WIN8_EDGE_SWIPE
);
60 CASE_TYPE(ET_GESTURE_TAP
);
61 CASE_TYPE(ET_GESTURE_TAP_DOWN
);
62 CASE_TYPE(ET_GESTURE_TAP_CANCEL
);
63 CASE_TYPE(ET_GESTURE_BEGIN
);
64 CASE_TYPE(ET_GESTURE_END
);
65 CASE_TYPE(ET_GESTURE_TWO_FINGER_TAP
);
66 CASE_TYPE(ET_GESTURE_PINCH_BEGIN
);
67 CASE_TYPE(ET_GESTURE_PINCH_END
);
68 CASE_TYPE(ET_GESTURE_PINCH_UPDATE
);
69 CASE_TYPE(ET_GESTURE_LONG_PRESS
);
70 CASE_TYPE(ET_GESTURE_LONG_TAP
);
71 CASE_TYPE(ET_GESTURE_SWIPE
);
72 CASE_TYPE(ET_GESTURE_TAP_UNCONFIRMED
);
73 CASE_TYPE(ET_GESTURE_DOUBLE_TAP
);
75 CASE_TYPE(ET_SCROLL_FLING_START
);
76 CASE_TYPE(ET_SCROLL_FLING_CANCEL
);
77 CASE_TYPE(ET_CANCEL_MODE
);
78 CASE_TYPE(ET_UMA_DATA
);
79 case ui::ET_LAST
: NOTREACHED(); return std::string();
80 // Don't include default, so that we get an error when new type is added.
88 bool IsX11SendEventTrue(const base::NativeEvent
& event
) {
90 return event
&& event
->xany
.send_event
;
96 bool X11EventHasNonStandardState(const base::NativeEvent
& event
) {
98 const unsigned int kAllStateMask
=
99 Button1Mask
| Button2Mask
| Button3Mask
| Button4Mask
| Button5Mask
|
100 Mod1Mask
| Mod2Mask
| Mod3Mask
| Mod4Mask
| Mod5Mask
| ShiftMask
|
101 LockMask
| ControlMask
| AnyModifier
;
102 return event
&& (event
->xkey
.state
& ~kAllStateMask
) != 0;
112 ////////////////////////////////////////////////////////////////////////////////
116 scoped_ptr
<Event
> Event::Clone(const Event
& event
) {
117 if (event
.IsKeyEvent()) {
118 return scoped_ptr
<Event
>(new KeyEvent(static_cast<const KeyEvent
&>(event
)));
121 if (event
.IsMouseEvent()) {
122 if (event
.IsMouseWheelEvent()) {
123 return scoped_ptr
<Event
>(
124 new MouseWheelEvent(static_cast<const MouseWheelEvent
&>(event
)));
127 return scoped_ptr
<Event
>(
128 new MouseEvent(static_cast<const MouseEvent
&>(event
)));
131 if (event
.IsTouchEvent()) {
132 return scoped_ptr
<Event
>(
133 new TouchEvent(static_cast<const TouchEvent
&>(event
)));
136 if (event
.IsGestureEvent()) {
137 return scoped_ptr
<Event
>(
138 new GestureEvent(static_cast<const GestureEvent
&>(event
)));
141 if (event
.IsScrollEvent()) {
142 return scoped_ptr
<Event
>(
143 new ScrollEvent(static_cast<const ScrollEvent
&>(event
)));
146 return scoped_ptr
<Event
>(new Event(event
));
150 if (delete_native_event_
)
151 ReleaseCopiedNativeEvent(native_event_
);
154 GestureEvent
* Event::AsGestureEvent() {
155 CHECK(IsGestureEvent());
156 return static_cast<GestureEvent
*>(this);
159 const GestureEvent
* Event::AsGestureEvent() const {
160 CHECK(IsGestureEvent());
161 return static_cast<const GestureEvent
*>(this);
164 bool Event::HasNativeEvent() const {
165 base::NativeEvent null_event
;
166 std::memset(&null_event
, 0, sizeof(null_event
));
167 return !!std::memcmp(&native_event_
, &null_event
, sizeof(null_event
));
170 void Event::StopPropagation() {
171 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
173 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
175 result_
= static_cast<EventResult
>(result_
| ER_CONSUMED
);
178 void Event::SetHandled() {
179 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
181 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
183 result_
= static_cast<EventResult
>(result_
| ER_HANDLED
);
186 Event::Event(EventType type
, base::TimeDelta time_stamp
, int flags
)
188 time_stamp_(time_stamp
),
190 native_event_(base::NativeEvent()),
191 delete_native_event_(false),
194 phase_(EP_PREDISPATCH
),
195 result_(ER_UNHANDLED
),
196 source_device_id_(ED_UNKNOWN_DEVICE
) {
198 name_
= EventTypeName(type_
);
201 Event::Event(const base::NativeEvent
& native_event
,
205 time_stamp_(EventTimeFromNative(native_event
)),
207 native_event_(native_event
),
208 delete_native_event_(false),
211 phase_(EP_PREDISPATCH
),
212 result_(ER_UNHANDLED
),
213 source_device_id_(ED_UNKNOWN_DEVICE
) {
214 base::TimeDelta delta
= EventTimeForNow() - time_stamp_
;
216 name_
= EventTypeName(type_
);
217 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser",
218 delta
.InMicroseconds(), 1, 1000000, 100);
219 std::string name_for_event
=
220 base::StringPrintf("Event.Latency.Browser.%s", name_
.c_str());
221 base::HistogramBase
* counter_for_type
=
222 base::Histogram::FactoryGet(
227 base::HistogramBase::kUmaTargetedHistogramFlag
);
228 counter_for_type
->Add(delta
.InMicroseconds());
231 if (native_event
->type
== GenericEvent
) {
232 XIDeviceEvent
* xiev
=
233 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
234 source_device_id_
= xiev
->sourceid
;
239 Event::Event(const Event
& copy
)
241 time_stamp_(copy
.time_stamp_
),
242 latency_(copy
.latency_
),
244 native_event_(CopyNativeEvent(copy
.native_event_
)),
245 delete_native_event_(true),
248 phase_(EP_PREDISPATCH
),
249 result_(ER_UNHANDLED
),
250 source_device_id_(copy
.source_device_id_
) {
252 name_
= EventTypeName(type_
);
255 void Event::SetType(EventType type
) {
257 name_
= std::string();
260 name_
= EventTypeName(type_
);
263 ////////////////////////////////////////////////////////////////////////////////
266 CancelModeEvent::CancelModeEvent()
267 : Event(ET_CANCEL_MODE
, base::TimeDelta(), 0) {
268 set_cancelable(false);
271 CancelModeEvent::~CancelModeEvent() {
274 ////////////////////////////////////////////////////////////////////////////////
277 LocatedEvent::~LocatedEvent() {
280 LocatedEvent::LocatedEvent(const base::NativeEvent
& native_event
)
281 : Event(native_event
,
282 EventTypeFromNative(native_event
),
283 EventFlagsFromNative(native_event
)),
284 location_(EventLocationFromNative(native_event
)),
285 root_location_(location_
) {
288 LocatedEvent::LocatedEvent(EventType type
,
289 const gfx::PointF
& location
,
290 const gfx::PointF
& root_location
,
291 base::TimeDelta time_stamp
,
293 : Event(type
, time_stamp
, flags
),
295 root_location_(root_location
) {
298 void LocatedEvent::UpdateForRootTransform(
299 const gfx::Transform
& reversed_root_transform
) {
300 // Transform has to be done at root level.
301 gfx::Point3F
p(location_
);
302 reversed_root_transform
.TransformPoint(&p
);
303 location_
= p
.AsPointF();
304 root_location_
= location_
;
307 ////////////////////////////////////////////////////////////////////////////////
310 MouseEvent::MouseEvent(const base::NativeEvent
& native_event
)
311 : LocatedEvent(native_event
),
312 changed_button_flags_(
313 GetChangedMouseButtonFlagsFromNative(native_event
)) {
314 if (type() == ET_MOUSE_PRESSED
|| type() == ET_MOUSE_RELEASED
)
315 SetClickCount(GetRepeatCount(*this));
318 MouseEvent::MouseEvent(EventType type
,
319 const gfx::PointF
& location
,
320 const gfx::PointF
& root_location
,
322 int changed_button_flags
)
323 : LocatedEvent(type
, location
, root_location
, EventTimeForNow(), flags
),
324 changed_button_flags_(changed_button_flags
) {
325 if (this->type() == ET_MOUSE_MOVED
&& IsAnyButton())
326 SetType(ET_MOUSE_DRAGGED
);
330 bool MouseEvent::IsRepeatedClickEvent(
331 const MouseEvent
& event1
,
332 const MouseEvent
& event2
) {
333 // These values match the Windows defaults.
334 static const int kDoubleClickTimeMS
= 500;
335 static const int kDoubleClickWidth
= 4;
336 static const int kDoubleClickHeight
= 4;
338 if (event1
.type() != ET_MOUSE_PRESSED
||
339 event2
.type() != ET_MOUSE_PRESSED
)
342 // Compare flags, but ignore EF_IS_DOUBLE_CLICK to allow triple clicks.
343 if ((event1
.flags() & ~EF_IS_DOUBLE_CLICK
) !=
344 (event2
.flags() & ~EF_IS_DOUBLE_CLICK
))
347 base::TimeDelta time_difference
= event2
.time_stamp() - event1
.time_stamp();
349 if (time_difference
.InMilliseconds() > kDoubleClickTimeMS
)
352 if (std::abs(event2
.x() - event1
.x()) > kDoubleClickWidth
/ 2)
355 if (std::abs(event2
.y() - event1
.y()) > kDoubleClickHeight
/ 2)
362 int MouseEvent::GetRepeatCount(const MouseEvent
& event
) {
364 if (last_click_event_
) {
365 if (event
.type() == ui::ET_MOUSE_RELEASED
) {
366 if (event
.changed_button_flags() ==
367 last_click_event_
->changed_button_flags()) {
368 last_click_complete_
= true;
369 return last_click_event_
->GetClickCount();
371 // If last_click_event_ has changed since this button was pressed
372 // return a click count of 1.
376 if (event
.time_stamp() != last_click_event_
->time_stamp())
377 last_click_complete_
= true;
378 if (!last_click_complete_
||
379 IsX11SendEventTrue(event
.native_event())) {
380 click_count
= last_click_event_
->GetClickCount();
381 } else if (IsRepeatedClickEvent(*last_click_event_
, event
)) {
382 click_count
= last_click_event_
->GetClickCount() + 1;
384 delete last_click_event_
;
386 last_click_event_
= new MouseEvent(event
);
387 last_click_complete_
= false;
390 last_click_event_
->SetClickCount(click_count
);
394 void MouseEvent::ResetLastClickForTest() {
395 if (last_click_event_
) {
396 delete last_click_event_
;
397 last_click_event_
= NULL
;
398 last_click_complete_
= false;
403 MouseEvent
* MouseEvent::last_click_event_
= NULL
;
404 bool MouseEvent::last_click_complete_
= false;
406 int MouseEvent::GetClickCount() const {
407 if (type() != ET_MOUSE_PRESSED
&& type() != ET_MOUSE_RELEASED
)
410 if (flags() & EF_IS_TRIPLE_CLICK
)
412 else if (flags() & EF_IS_DOUBLE_CLICK
)
418 void MouseEvent::SetClickCount(int click_count
) {
419 if (type() != ET_MOUSE_PRESSED
&& type() != ET_MOUSE_RELEASED
)
422 DCHECK(click_count
> 0);
423 DCHECK(click_count
<= 3);
426 switch (click_count
) {
428 f
&= ~EF_IS_DOUBLE_CLICK
;
429 f
&= ~EF_IS_TRIPLE_CLICK
;
432 f
|= EF_IS_DOUBLE_CLICK
;
433 f
&= ~EF_IS_TRIPLE_CLICK
;
436 f
&= ~EF_IS_DOUBLE_CLICK
;
437 f
|= EF_IS_TRIPLE_CLICK
;
443 ////////////////////////////////////////////////////////////////////////////////
446 MouseWheelEvent::MouseWheelEvent(const base::NativeEvent
& native_event
)
447 : MouseEvent(native_event
),
448 offset_(GetMouseWheelOffset(native_event
)) {
451 MouseWheelEvent::MouseWheelEvent(const ScrollEvent
& scroll_event
)
452 : MouseEvent(scroll_event
),
453 offset_(scroll_event
.x_offset(), scroll_event
.y_offset()){
454 SetType(ET_MOUSEWHEEL
);
457 MouseWheelEvent::MouseWheelEvent(const MouseEvent
& mouse_event
,
460 : MouseEvent(mouse_event
), offset_(x_offset
, y_offset
) {
461 DCHECK(type() == ET_MOUSEWHEEL
);
464 MouseWheelEvent::MouseWheelEvent(const MouseWheelEvent
& mouse_wheel_event
)
465 : MouseEvent(mouse_wheel_event
),
466 offset_(mouse_wheel_event
.offset()) {
467 DCHECK(type() == ET_MOUSEWHEEL
);
470 MouseWheelEvent::MouseWheelEvent(const gfx::Vector2d
& offset
,
471 const gfx::PointF
& location
,
472 const gfx::PointF
& root_location
,
474 int changed_button_flags
)
475 : MouseEvent(ui::ET_MOUSEWHEEL
, location
, root_location
, flags
,
476 changed_button_flags
),
481 // This value matches windows WHEEL_DELTA.
483 const int MouseWheelEvent::kWheelDelta
= 120;
485 // This value matches GTK+ wheel scroll amount.
486 const int MouseWheelEvent::kWheelDelta
= 53;
489 void MouseWheelEvent::UpdateForRootTransform(
490 const gfx::Transform
& inverted_root_transform
) {
491 LocatedEvent::UpdateForRootTransform(inverted_root_transform
);
492 gfx::DecomposedTransform decomp
;
493 bool success
= gfx::DecomposeTransform(&decomp
, inverted_root_transform
);
496 offset_
.set_x(offset_
.x() * decomp
.scale
[0]);
498 offset_
.set_y(offset_
.y() * decomp
.scale
[1]);
501 ////////////////////////////////////////////////////////////////////////////////
504 TouchEvent::TouchEvent(const base::NativeEvent
& native_event
)
505 : LocatedEvent(native_event
),
506 touch_id_(GetTouchId(native_event
)),
507 radius_x_(GetTouchRadiusX(native_event
)),
508 radius_y_(GetTouchRadiusY(native_event
)),
509 rotation_angle_(GetTouchAngle(native_event
)),
510 force_(GetTouchForce(native_event
)) {
511 latency()->AddLatencyNumberWithTimestamp(
512 INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT
,
515 base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()),
518 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT
, 0, 0);
520 if (type() == ET_TOUCH_PRESSED
)
521 IncrementTouchIdRefCount(native_event
);
524 TouchEvent::TouchEvent(EventType type
,
525 const gfx::PointF
& location
,
527 base::TimeDelta time_stamp
)
528 : LocatedEvent(type
, location
, location
, time_stamp
, 0),
532 rotation_angle_(0.0f
),
534 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT
, 0, 0);
537 TouchEvent::TouchEvent(EventType type
,
538 const gfx::PointF
& location
,
541 base::TimeDelta time_stamp
,
546 : LocatedEvent(type
, location
, location
, time_stamp
, flags
),
550 rotation_angle_(angle
),
552 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT
, 0, 0);
555 TouchEvent::~TouchEvent() {
556 // In ctor TouchEvent(native_event) we call GetTouchId() which in X11
557 // platform setups the tracking_id to slot mapping. So in dtor here,
558 // if this touch event is a release event, we clear the mapping accordingly.
559 if (HasNativeEvent())
560 ClearTouchIdIfReleased(native_event());
563 void TouchEvent::UpdateForRootTransform(
564 const gfx::Transform
& inverted_root_transform
) {
565 LocatedEvent::UpdateForRootTransform(inverted_root_transform
);
566 gfx::DecomposedTransform decomp
;
567 bool success
= gfx::DecomposeTransform(&decomp
, inverted_root_transform
);
570 radius_x_
*= decomp
.scale
[0];
572 radius_y_
*= decomp
.scale
[1];
575 ////////////////////////////////////////////////////////////////////////////////
579 KeyEvent
* KeyEvent::last_key_event_
= NULL
;
582 bool KeyEvent::IsRepeated(const KeyEvent
& event
) {
583 // A safe guard in case if there were continous key pressed events that are
585 const int kMaxAutoRepeatTimeMs
= 2000;
586 // Ignore key events that have non standard state masks as it may be
587 // reposted by an IME. IBUS-GTK uses this field to detect the
588 // re-posted event for example. crbug.com/385873.
589 if (X11EventHasNonStandardState(event
.native_event()))
593 if (event
.type() == ui::ET_KEY_RELEASED
) {
594 delete last_key_event_
;
595 last_key_event_
= NULL
;
598 CHECK_EQ(ui::ET_KEY_PRESSED
, event
.type());
599 if (!last_key_event_
) {
600 last_key_event_
= new KeyEvent(event
);
603 if (event
.key_code() == last_key_event_
->key_code() &&
604 event
.flags() == last_key_event_
->flags() &&
605 (event
.time_stamp() - last_key_event_
->time_stamp()).InMilliseconds() <
606 kMaxAutoRepeatTimeMs
) {
609 delete last_key_event_
;
610 last_key_event_
= new KeyEvent(event
);
614 KeyEvent::KeyEvent(const base::NativeEvent
& native_event
)
615 : Event(native_event
,
616 EventTypeFromNative(native_event
),
617 EventFlagsFromNative(native_event
)),
618 key_code_(KeyboardCodeFromNative(native_event
)),
619 code_(CodeFromNative(native_event
)),
620 is_char_(IsCharFromNative(native_event
)),
621 platform_keycode_(PlatformKeycodeFromNative(native_event
)),
623 if (IsRepeated(*this))
624 set_flags(flags() | ui::EF_IS_REPEAT
);
630 // Only Windows has native character events.
632 character_
= native_event
.wParam
;
636 KeyEvent::KeyEvent(EventType type
,
637 KeyboardCode key_code
,
639 : Event(type
, EventTimeForNow(), flags
),
642 platform_keycode_(0),
646 KeyEvent::KeyEvent(EventType type
,
647 KeyboardCode key_code
,
648 const std::string
& code
,
650 : Event(type
, EventTimeForNow(), flags
),
654 platform_keycode_(0),
658 KeyEvent::KeyEvent(base::char16 character
, KeyboardCode key_code
, int flags
)
659 : Event(ET_KEY_PRESSED
, EventTimeForNow(), flags
),
663 platform_keycode_(0),
664 character_(character
) {
667 KeyEvent::KeyEvent(const KeyEvent
& rhs
)
669 key_code_(rhs
.key_code_
),
671 is_char_(rhs
.is_char_
),
672 platform_keycode_(rhs
.platform_keycode_
),
673 character_(rhs
.character_
) {
674 if (rhs
.extended_key_event_data_
)
675 extended_key_event_data_
.reset(rhs
.extended_key_event_data_
->Clone());
678 KeyEvent
& KeyEvent::operator=(const KeyEvent
& rhs
) {
680 Event::operator=(rhs
);
681 key_code_
= rhs
.key_code_
;
683 is_char_
= rhs
.is_char_
;
684 platform_keycode_
= rhs
.platform_keycode_
;
685 character_
= rhs
.character_
;
687 if (rhs
.extended_key_event_data_
)
688 extended_key_event_data_
.reset(rhs
.extended_key_event_data_
->Clone());
693 KeyEvent::~KeyEvent() {}
695 void KeyEvent::SetExtendedKeyEventData(scoped_ptr
<ExtendedKeyEventData
> data
) {
696 extended_key_event_data_
= data
.Pass();
699 base::char16
KeyEvent::GetCharacter() const {
700 if (is_char_
|| character_
)
703 // TODO(kpschoedel): streamline these cases after settling Ozone
704 // positional coding.
706 // Native Windows character events always have is_char_ == true,
707 // so this is a synthetic or native keystroke event.
708 character_
= GetCharacterFromKeyCode(key_code_
, flags());
710 #elif defined(USE_X11)
711 if (!native_event()) {
712 character_
= GetCharacterFromKeyCode(key_code_
, flags());
716 DCHECK(native_event()->type
== KeyPress
||
717 native_event()->type
== KeyRelease
||
718 (native_event()->type
== GenericEvent
&&
719 (native_event()->xgeneric
.evtype
== XI_KeyPress
||
720 native_event()->xgeneric
.evtype
== XI_KeyRelease
)));
722 // When a control key is held, prefer ASCII characters to non ASCII
723 // characters in order to use it for shortcut keys. GetCharacterFromKeyCode
724 // returns 'a' for VKEY_A even if the key is actually bound to 'Ã ' in X11.
725 // GetCharacterFromXEvent returns 'Ã ' in that case.
726 return IsControlDown() ?
727 GetCharacterFromKeyCode(key_code_
, flags()) :
728 GetCharacterFromXEvent(native_event());
730 if (native_event()) {
731 DCHECK(EventTypeFromNative(native_event()) == ET_KEY_PRESSED
||
732 EventTypeFromNative(native_event()) == ET_KEY_RELEASED
);
735 return GetCharacterFromKeyCode(key_code_
, flags());
739 base::char16
KeyEvent::GetText() const {
740 if ((flags() & EF_CONTROL_DOWN
) != 0) {
741 return GetControlCharacterForKeycode(key_code_
,
742 (flags() & EF_SHIFT_DOWN
) != 0);
744 return GetUnmodifiedText();
747 base::char16
KeyEvent::GetUnmodifiedText() const {
748 if (!is_char_
&& (key_code_
== VKEY_RETURN
))
750 return GetCharacter();
753 bool KeyEvent::IsUnicodeKeyCode() const {
757 const int key
= key_code();
758 if (key
>= VKEY_NUMPAD0
&& key
<= VKEY_NUMPAD9
)
760 // Check whether the user is using the numeric keypad with num-lock off.
761 // In that case, EF_EXTENDED will not be set; if it is set, the key event
762 // originated from the relevant non-numpad dedicated key, e.g. [Insert].
763 return (!(flags() & EF_EXTENDED
) &&
764 (key
== VKEY_INSERT
|| key
== VKEY_END
|| key
== VKEY_DOWN
||
765 key
== VKEY_NEXT
|| key
== VKEY_LEFT
|| key
== VKEY_CLEAR
||
766 key
== VKEY_RIGHT
|| key
== VKEY_HOME
|| key
== VKEY_UP
||
773 void KeyEvent::NormalizeFlags() {
775 switch (key_code()) {
777 mask
= EF_CONTROL_DOWN
;
780 mask
= EF_SHIFT_DOWN
;
786 mask
= EF_CAPS_LOCK_DOWN
;
791 if (type() == ET_KEY_PRESSED
)
792 set_flags(flags() | mask
);
794 set_flags(flags() & ~mask
);
797 bool KeyEvent::IsTranslated() const {
800 case ET_KEY_RELEASED
:
802 case ET_TRANSLATED_KEY_PRESS
:
803 case ET_TRANSLATED_KEY_RELEASE
:
811 void KeyEvent::SetTranslated(bool translated
) {
814 case ET_TRANSLATED_KEY_PRESS
:
815 SetType(translated
? ET_TRANSLATED_KEY_PRESS
: ET_KEY_PRESSED
);
817 case ET_KEY_RELEASED
:
818 case ET_TRANSLATED_KEY_RELEASE
:
819 SetType(translated
? ET_TRANSLATED_KEY_RELEASE
: ET_KEY_RELEASED
);
826 bool KeyEvent::IsRightSideKey() const {
833 // Under X11, setting code_ requires platform-dependent information, and
834 // currently assumes that X keycodes are based on Linux evdev keycodes.
835 // In certain test environments this is not the case, and code_ is not
836 // set accurately, so we need a different mechanism. Fortunately X11 key
837 // mapping preserves the left-right distinction, so testing keysyms works
838 // if the value is available (as it is for all X11 native-based events).
839 if (platform_keycode_
) {
840 return (platform_keycode_
== XK_Shift_R
) ||
841 (platform_keycode_
== XK_Control_R
) ||
842 (platform_keycode_
== XK_Alt_R
) ||
843 (platform_keycode_
== XK_Meta_R
) ||
844 (platform_keycode_
== XK_Super_R
) ||
845 (platform_keycode_
== XK_Hyper_R
);
847 // Fall through to the generic code if we have no platform_keycode_.
848 // Under X11, this must be a synthetic event, so we can require that
849 // code_ be set correctly.
851 return ((code_
.size() > 5) &&
852 (code_
.compare(code_
.size() - 5, 5, "Right", 5)) == 0);
858 KeyboardCode
KeyEvent::GetLocatedWindowsKeyboardCode() const {
861 return IsRightSideKey() ? VKEY_RSHIFT
: VKEY_LSHIFT
;
863 return IsRightSideKey() ? VKEY_RCONTROL
: VKEY_LCONTROL
;
865 return IsRightSideKey() ? VKEY_RMENU
: VKEY_LMENU
;
867 return IsRightSideKey() ? VKEY_RWIN
: VKEY_LWIN
;
868 // TODO(kpschoedel): EF_NUMPAD_KEY is present only on X11. Currently this
869 // function is only called on X11. Likely the tests here will be replaced
870 // with a DOM-based code enumeration test in the course of Ozone
871 // platform-indpendent key event work.
873 return (flags() & EF_NUMPAD_KEY
) ? VKEY_NUMPAD0
: VKEY_0
;
875 return (flags() & EF_NUMPAD_KEY
) ? VKEY_NUMPAD1
: VKEY_1
;
877 return (flags() & EF_NUMPAD_KEY
) ? VKEY_NUMPAD2
: VKEY_2
;
879 return (flags() & EF_NUMPAD_KEY
) ? VKEY_NUMPAD3
: VKEY_3
;
881 return (flags() & EF_NUMPAD_KEY
) ? VKEY_NUMPAD4
: VKEY_4
;
883 return (flags() & EF_NUMPAD_KEY
) ? VKEY_NUMPAD5
: VKEY_5
;
885 return (flags() & EF_NUMPAD_KEY
) ? VKEY_NUMPAD6
: VKEY_6
;
887 return (flags() & EF_NUMPAD_KEY
) ? VKEY_NUMPAD7
: VKEY_7
;
889 return (flags() & EF_NUMPAD_KEY
) ? VKEY_NUMPAD8
: VKEY_8
;
891 return (flags() & EF_NUMPAD_KEY
) ? VKEY_NUMPAD9
: VKEY_9
;
897 uint16
KeyEvent::GetConflatedWindowsKeyCode() const {
903 ////////////////////////////////////////////////////////////////////////////////
906 ScrollEvent::ScrollEvent(const base::NativeEvent
& native_event
)
907 : MouseEvent(native_event
) {
908 if (type() == ET_SCROLL
) {
909 GetScrollOffsets(native_event
,
910 &x_offset_
, &y_offset_
,
911 &x_offset_ordinal_
, &y_offset_ordinal_
,
913 } else if (type() == ET_SCROLL_FLING_START
||
914 type() == ET_SCROLL_FLING_CANCEL
) {
915 GetFlingData(native_event
,
916 &x_offset_
, &y_offset_
,
917 &x_offset_ordinal_
, &y_offset_ordinal_
,
920 NOTREACHED() << "Unexpected event type " << type()
921 << " when constructing a ScrollEvent.";
925 ScrollEvent::ScrollEvent(EventType type
,
926 const gfx::PointF
& location
,
927 base::TimeDelta time_stamp
,
931 float x_offset_ordinal
,
932 float y_offset_ordinal
,
934 : MouseEvent(type
, location
, location
, flags
, 0),
937 x_offset_ordinal_(x_offset_ordinal
),
938 y_offset_ordinal_(y_offset_ordinal
),
939 finger_count_(finger_count
) {
940 set_time_stamp(time_stamp
);
941 CHECK(IsScrollEvent());
944 void ScrollEvent::Scale(const float factor
) {
947 x_offset_ordinal_
*= factor
;
948 y_offset_ordinal_
*= factor
;
951 ////////////////////////////////////////////////////////////////////////////////
954 GestureEvent::GestureEvent(float x
,
957 base::TimeDelta time_stamp
,
958 const GestureEventDetails
& details
)
959 : LocatedEvent(details
.type(),
963 flags
| EF_FROM_TOUCH
),
967 GestureEvent::~GestureEvent() {