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>
9 #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/dom3/dom_code.h"
20 #include "ui/events/keycodes/dom3/dom_key.h"
21 #include "ui/events/keycodes/dom4/keycode_converter.h"
22 #include "ui/events/keycodes/keyboard_code_conversion.h"
23 #include "ui/gfx/geometry/point3_f.h"
24 #include "ui/gfx/geometry/point_conversions.h"
25 #include "ui/gfx/geometry/safe_integer_conversions.h"
26 #include "ui/gfx/transform.h"
27 #include "ui/gfx/transform_util.h"
30 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
31 #elif defined(USE_OZONE)
32 #include "ui/events/ozone/layout/keyboard_layout_engine.h"
33 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
38 std::string
EventTypeName(ui::EventType type
) {
39 #define RETURN_IF_TYPE(t) if (type == ui::t) return #t
40 #define CASE_TYPE(t) case ui::t: return #t
42 CASE_TYPE(ET_UNKNOWN
);
43 CASE_TYPE(ET_MOUSE_PRESSED
);
44 CASE_TYPE(ET_MOUSE_DRAGGED
);
45 CASE_TYPE(ET_MOUSE_RELEASED
);
46 CASE_TYPE(ET_MOUSE_MOVED
);
47 CASE_TYPE(ET_MOUSE_ENTERED
);
48 CASE_TYPE(ET_MOUSE_EXITED
);
49 CASE_TYPE(ET_KEY_PRESSED
);
50 CASE_TYPE(ET_KEY_RELEASED
);
51 CASE_TYPE(ET_MOUSEWHEEL
);
52 CASE_TYPE(ET_MOUSE_CAPTURE_CHANGED
);
53 CASE_TYPE(ET_TOUCH_RELEASED
);
54 CASE_TYPE(ET_TOUCH_PRESSED
);
55 CASE_TYPE(ET_TOUCH_MOVED
);
56 CASE_TYPE(ET_TOUCH_CANCELLED
);
57 CASE_TYPE(ET_DROP_TARGET_EVENT
);
58 CASE_TYPE(ET_TRANSLATED_KEY_PRESS
);
59 CASE_TYPE(ET_TRANSLATED_KEY_RELEASE
);
60 CASE_TYPE(ET_GESTURE_SCROLL_BEGIN
);
61 CASE_TYPE(ET_GESTURE_SCROLL_END
);
62 CASE_TYPE(ET_GESTURE_SCROLL_UPDATE
);
63 CASE_TYPE(ET_GESTURE_SHOW_PRESS
);
64 CASE_TYPE(ET_GESTURE_WIN8_EDGE_SWIPE
);
65 CASE_TYPE(ET_GESTURE_TAP
);
66 CASE_TYPE(ET_GESTURE_TAP_DOWN
);
67 CASE_TYPE(ET_GESTURE_TAP_CANCEL
);
68 CASE_TYPE(ET_GESTURE_BEGIN
);
69 CASE_TYPE(ET_GESTURE_END
);
70 CASE_TYPE(ET_GESTURE_TWO_FINGER_TAP
);
71 CASE_TYPE(ET_GESTURE_PINCH_BEGIN
);
72 CASE_TYPE(ET_GESTURE_PINCH_END
);
73 CASE_TYPE(ET_GESTURE_PINCH_UPDATE
);
74 CASE_TYPE(ET_GESTURE_LONG_PRESS
);
75 CASE_TYPE(ET_GESTURE_LONG_TAP
);
76 CASE_TYPE(ET_GESTURE_SWIPE
);
77 CASE_TYPE(ET_GESTURE_TAP_UNCONFIRMED
);
78 CASE_TYPE(ET_GESTURE_DOUBLE_TAP
);
80 CASE_TYPE(ET_SCROLL_FLING_START
);
81 CASE_TYPE(ET_SCROLL_FLING_CANCEL
);
82 CASE_TYPE(ET_CANCEL_MODE
);
83 CASE_TYPE(ET_UMA_DATA
);
84 case ui::ET_LAST
: NOTREACHED(); return std::string();
85 // Don't include default, so that we get an error when new type is added.
93 bool IsX11SendEventTrue(const base::NativeEvent
& event
) {
95 return event
&& event
->xany
.send_event
;
101 bool X11EventHasNonStandardState(const base::NativeEvent
& event
) {
103 const unsigned int kAllStateMask
=
104 Button1Mask
| Button2Mask
| Button3Mask
| Button4Mask
| Button5Mask
|
105 Mod1Mask
| Mod2Mask
| Mod3Mask
| Mod4Mask
| Mod5Mask
| ShiftMask
|
106 LockMask
| ControlMask
| AnyModifier
;
107 return event
&& (event
->xkey
.state
& ~kAllStateMask
) != 0;
113 unsigned long long get_next_touch_event_id() {
114 static unsigned long long id
= 0;
122 ////////////////////////////////////////////////////////////////////////////////
126 scoped_ptr
<Event
> Event::Clone(const Event
& event
) {
127 if (event
.IsKeyEvent()) {
128 return scoped_ptr
<Event
>(new KeyEvent(static_cast<const KeyEvent
&>(event
)));
131 if (event
.IsMouseEvent()) {
132 if (event
.IsMouseWheelEvent()) {
133 return scoped_ptr
<Event
>(
134 new MouseWheelEvent(static_cast<const MouseWheelEvent
&>(event
)));
137 return scoped_ptr
<Event
>(
138 new MouseEvent(static_cast<const MouseEvent
&>(event
)));
141 if (event
.IsTouchEvent()) {
142 return scoped_ptr
<Event
>(
143 new TouchEvent(static_cast<const TouchEvent
&>(event
)));
146 if (event
.IsGestureEvent()) {
147 return scoped_ptr
<Event
>(
148 new GestureEvent(static_cast<const GestureEvent
&>(event
)));
151 if (event
.IsScrollEvent()) {
152 return scoped_ptr
<Event
>(
153 new ScrollEvent(static_cast<const ScrollEvent
&>(event
)));
156 return scoped_ptr
<Event
>(new Event(event
));
160 if (delete_native_event_
)
161 ReleaseCopiedNativeEvent(native_event_
);
164 GestureEvent
* Event::AsGestureEvent() {
165 CHECK(IsGestureEvent());
166 return static_cast<GestureEvent
*>(this);
169 const GestureEvent
* Event::AsGestureEvent() const {
170 CHECK(IsGestureEvent());
171 return static_cast<const GestureEvent
*>(this);
174 bool Event::HasNativeEvent() const {
175 base::NativeEvent null_event
;
176 std::memset(&null_event
, 0, sizeof(null_event
));
177 return !!std::memcmp(&native_event_
, &null_event
, sizeof(null_event
));
180 void Event::StopPropagation() {
181 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
183 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
185 result_
= static_cast<EventResult
>(result_
| ER_CONSUMED
);
188 void Event::SetHandled() {
189 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
191 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
193 result_
= static_cast<EventResult
>(result_
| ER_HANDLED
);
196 Event::Event(EventType type
, base::TimeDelta time_stamp
, int flags
)
198 time_stamp_(time_stamp
),
200 native_event_(base::NativeEvent()),
201 delete_native_event_(false),
204 phase_(EP_PREDISPATCH
),
205 result_(ER_UNHANDLED
),
206 source_device_id_(ED_UNKNOWN_DEVICE
) {
208 name_
= EventTypeName(type_
);
211 Event::Event(const base::NativeEvent
& native_event
,
215 time_stamp_(EventTimeFromNative(native_event
)),
217 native_event_(native_event
),
218 delete_native_event_(false),
221 phase_(EP_PREDISPATCH
),
222 result_(ER_UNHANDLED
),
223 source_device_id_(ED_UNKNOWN_DEVICE
) {
224 base::TimeDelta delta
= EventTimeForNow() - time_stamp_
;
226 name_
= EventTypeName(type_
);
227 base::HistogramBase::Sample delta_sample
=
228 static_cast<base::HistogramBase::Sample
>(delta
.InMicroseconds());
229 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser", delta_sample
, 1, 1000000,
231 std::string name_for_event
=
232 base::StringPrintf("Event.Latency.Browser.%s", name_
.c_str());
233 base::HistogramBase
* counter_for_type
=
234 base::Histogram::FactoryGet(
239 base::HistogramBase::kUmaTargetedHistogramFlag
);
240 counter_for_type
->Add(delta_sample
);
243 if (native_event
->type
== GenericEvent
) {
244 XIDeviceEvent
* xiev
=
245 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
246 source_device_id_
= xiev
->sourceid
;
251 Event::Event(const Event
& copy
)
253 time_stamp_(copy
.time_stamp_
),
254 latency_(copy
.latency_
),
256 native_event_(CopyNativeEvent(copy
.native_event_
)),
257 delete_native_event_(true),
260 phase_(EP_PREDISPATCH
),
261 result_(ER_UNHANDLED
),
262 source_device_id_(copy
.source_device_id_
) {
264 name_
= EventTypeName(type_
);
267 void Event::SetType(EventType type
) {
269 name_
= std::string();
272 name_
= EventTypeName(type_
);
275 ////////////////////////////////////////////////////////////////////////////////
278 CancelModeEvent::CancelModeEvent()
279 : Event(ET_CANCEL_MODE
, base::TimeDelta(), 0) {
280 set_cancelable(false);
283 CancelModeEvent::~CancelModeEvent() {
286 ////////////////////////////////////////////////////////////////////////////////
289 LocatedEvent::~LocatedEvent() {
292 LocatedEvent::LocatedEvent(const base::NativeEvent
& native_event
)
293 : Event(native_event
,
294 EventTypeFromNative(native_event
),
295 EventFlagsFromNative(native_event
)),
296 location_(EventLocationFromNative(native_event
)),
297 root_location_(location_
) {
300 LocatedEvent::LocatedEvent(EventType type
,
301 const gfx::PointF
& location
,
302 const gfx::PointF
& root_location
,
303 base::TimeDelta time_stamp
,
305 : Event(type
, time_stamp
, flags
),
307 root_location_(root_location
) {
310 void LocatedEvent::UpdateForRootTransform(
311 const gfx::Transform
& reversed_root_transform
) {
312 // Transform has to be done at root level.
313 gfx::Point3F
p(location_
);
314 reversed_root_transform
.TransformPoint(&p
);
315 location_
= p
.AsPointF();
316 root_location_
= location_
;
319 ////////////////////////////////////////////////////////////////////////////////
322 MouseEvent::MouseEvent(const base::NativeEvent
& native_event
)
323 : LocatedEvent(native_event
),
324 changed_button_flags_(
325 GetChangedMouseButtonFlagsFromNative(native_event
)) {
326 if (type() == ET_MOUSE_PRESSED
|| type() == ET_MOUSE_RELEASED
)
327 SetClickCount(GetRepeatCount(*this));
330 MouseEvent::MouseEvent(EventType type
,
331 const gfx::PointF
& location
,
332 const gfx::PointF
& root_location
,
333 base::TimeDelta time_stamp
,
335 int changed_button_flags
)
336 : LocatedEvent(type
, location
, root_location
, time_stamp
, flags
),
337 changed_button_flags_(changed_button_flags
) {
338 if (this->type() == ET_MOUSE_MOVED
&& IsAnyButton())
339 SetType(ET_MOUSE_DRAGGED
);
343 bool MouseEvent::IsRepeatedClickEvent(
344 const MouseEvent
& event1
,
345 const MouseEvent
& event2
) {
346 // These values match the Windows defaults.
347 static const int kDoubleClickTimeMS
= 500;
348 static const int kDoubleClickWidth
= 4;
349 static const int kDoubleClickHeight
= 4;
351 if (event1
.type() != ET_MOUSE_PRESSED
||
352 event2
.type() != ET_MOUSE_PRESSED
)
355 // Compare flags, but ignore EF_IS_DOUBLE_CLICK to allow triple clicks.
356 if ((event1
.flags() & ~EF_IS_DOUBLE_CLICK
) !=
357 (event2
.flags() & ~EF_IS_DOUBLE_CLICK
))
360 base::TimeDelta time_difference
= event2
.time_stamp() - event1
.time_stamp();
362 if (time_difference
.InMilliseconds() > kDoubleClickTimeMS
)
365 if (std::abs(event2
.x() - event1
.x()) > kDoubleClickWidth
/ 2)
368 if (std::abs(event2
.y() - event1
.y()) > kDoubleClickHeight
/ 2)
375 int MouseEvent::GetRepeatCount(const MouseEvent
& event
) {
377 if (last_click_event_
) {
378 if (event
.type() == ui::ET_MOUSE_RELEASED
) {
379 if (event
.changed_button_flags() ==
380 last_click_event_
->changed_button_flags()) {
381 last_click_complete_
= true;
382 return last_click_event_
->GetClickCount();
384 // If last_click_event_ has changed since this button was pressed
385 // return a click count of 1.
389 if (event
.time_stamp() != last_click_event_
->time_stamp())
390 last_click_complete_
= true;
391 if (!last_click_complete_
||
392 IsX11SendEventTrue(event
.native_event())) {
393 click_count
= last_click_event_
->GetClickCount();
394 } else if (IsRepeatedClickEvent(*last_click_event_
, event
)) {
395 click_count
= last_click_event_
->GetClickCount() + 1;
397 delete last_click_event_
;
399 last_click_event_
= new MouseEvent(event
);
400 last_click_complete_
= false;
403 last_click_event_
->SetClickCount(click_count
);
407 void MouseEvent::ResetLastClickForTest() {
408 if (last_click_event_
) {
409 delete last_click_event_
;
410 last_click_event_
= NULL
;
411 last_click_complete_
= false;
416 MouseEvent
* MouseEvent::last_click_event_
= NULL
;
417 bool MouseEvent::last_click_complete_
= false;
419 int MouseEvent::GetClickCount() const {
420 if (type() != ET_MOUSE_PRESSED
&& type() != ET_MOUSE_RELEASED
)
423 if (flags() & EF_IS_TRIPLE_CLICK
)
425 else if (flags() & EF_IS_DOUBLE_CLICK
)
431 void MouseEvent::SetClickCount(int click_count
) {
432 if (type() != ET_MOUSE_PRESSED
&& type() != ET_MOUSE_RELEASED
)
435 DCHECK(click_count
> 0);
436 DCHECK(click_count
<= 3);
439 switch (click_count
) {
441 f
&= ~EF_IS_DOUBLE_CLICK
;
442 f
&= ~EF_IS_TRIPLE_CLICK
;
445 f
|= EF_IS_DOUBLE_CLICK
;
446 f
&= ~EF_IS_TRIPLE_CLICK
;
449 f
&= ~EF_IS_DOUBLE_CLICK
;
450 f
|= EF_IS_TRIPLE_CLICK
;
456 ////////////////////////////////////////////////////////////////////////////////
459 MouseWheelEvent::MouseWheelEvent(const base::NativeEvent
& native_event
)
460 : MouseEvent(native_event
),
461 offset_(GetMouseWheelOffset(native_event
)) {
464 MouseWheelEvent::MouseWheelEvent(const ScrollEvent
& scroll_event
)
465 : MouseEvent(scroll_event
),
466 offset_(gfx::ToRoundedInt(scroll_event
.x_offset()),
467 gfx::ToRoundedInt(scroll_event
.y_offset())) {
468 SetType(ET_MOUSEWHEEL
);
471 MouseWheelEvent::MouseWheelEvent(const MouseEvent
& mouse_event
,
474 : MouseEvent(mouse_event
), offset_(x_offset
, y_offset
) {
475 DCHECK(type() == ET_MOUSEWHEEL
);
478 MouseWheelEvent::MouseWheelEvent(const MouseWheelEvent
& mouse_wheel_event
)
479 : MouseEvent(mouse_wheel_event
),
480 offset_(mouse_wheel_event
.offset()) {
481 DCHECK(type() == ET_MOUSEWHEEL
);
484 MouseWheelEvent::MouseWheelEvent(const gfx::Vector2d
& offset
,
485 const gfx::PointF
& location
,
486 const gfx::PointF
& root_location
,
488 int changed_button_flags
)
489 : MouseEvent(ui::ET_MOUSEWHEEL
,
494 changed_button_flags
),
499 // This value matches windows WHEEL_DELTA.
501 const int MouseWheelEvent::kWheelDelta
= 120;
503 // This value matches GTK+ wheel scroll amount.
504 const int MouseWheelEvent::kWheelDelta
= 53;
507 void MouseWheelEvent::UpdateForRootTransform(
508 const gfx::Transform
& inverted_root_transform
) {
509 LocatedEvent::UpdateForRootTransform(inverted_root_transform
);
510 gfx::DecomposedTransform decomp
;
511 bool success
= gfx::DecomposeTransform(&decomp
, inverted_root_transform
);
513 if (decomp
.scale
[0]) {
515 gfx::ToRoundedInt(SkMScalarToFloat(offset_
.x() * decomp
.scale
[0])));
517 if (decomp
.scale
[1]) {
519 gfx::ToRoundedInt(SkMScalarToFloat(offset_
.y() * decomp
.scale
[1])));
523 ////////////////////////////////////////////////////////////////////////////////
526 TouchEvent::TouchEvent(const base::NativeEvent
& native_event
)
527 : LocatedEvent(native_event
),
528 touch_id_(GetTouchId(native_event
)),
529 unique_event_id_(get_next_touch_event_id()),
530 radius_x_(GetTouchRadiusX(native_event
)),
531 radius_y_(GetTouchRadiusY(native_event
)),
532 rotation_angle_(GetTouchAngle(native_event
)),
533 force_(GetTouchForce(native_event
)),
534 may_cause_scrolling_(false),
535 should_remove_native_touch_id_mapping_(false) {
536 latency()->AddLatencyNumberWithTimestamp(
537 INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT
, 0, 0,
538 base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()), 1);
539 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT
, 0, 0);
542 if (type() == ET_TOUCH_RELEASED
|| type() == ET_TOUCH_CANCELLED
)
543 should_remove_native_touch_id_mapping_
= true;
546 TouchEvent::TouchEvent(EventType type
,
547 const gfx::PointF
& location
,
549 base::TimeDelta time_stamp
)
550 : LocatedEvent(type
, location
, location
, time_stamp
, 0),
552 unique_event_id_(get_next_touch_event_id()),
555 rotation_angle_(0.0f
),
557 may_cause_scrolling_(false),
558 should_remove_native_touch_id_mapping_(false) {
559 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT
, 0, 0);
562 TouchEvent::TouchEvent(EventType type
,
563 const gfx::PointF
& location
,
566 base::TimeDelta time_stamp
,
571 : LocatedEvent(type
, location
, location
, time_stamp
, flags
),
573 unique_event_id_(get_next_touch_event_id()),
576 rotation_angle_(angle
),
578 may_cause_scrolling_(false),
579 should_remove_native_touch_id_mapping_(false) {
580 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT
, 0, 0);
584 TouchEvent::~TouchEvent() {
585 // In ctor TouchEvent(native_event) we call GetTouchId() which in X11
586 // platform setups the tracking_id to slot mapping. So in dtor here,
587 // if this touch event is a release event, we clear the mapping accordingly.
588 if (should_remove_native_touch_id_mapping_
) {
589 DCHECK(type() == ET_TOUCH_RELEASED
|| type() == ET_TOUCH_CANCELLED
);
590 if (type() == ET_TOUCH_RELEASED
|| type() == ET_TOUCH_CANCELLED
)
591 ClearTouchIdIfReleased(native_event());
595 void TouchEvent::UpdateForRootTransform(
596 const gfx::Transform
& inverted_root_transform
) {
597 LocatedEvent::UpdateForRootTransform(inverted_root_transform
);
598 gfx::DecomposedTransform decomp
;
599 bool success
= gfx::DecomposeTransform(&decomp
, inverted_root_transform
);
602 radius_x_
*= decomp
.scale
[0];
604 radius_y_
*= decomp
.scale
[1];
607 void TouchEvent::DisableSynchronousHandling() {
608 DispatcherApi
dispatcher_api(this);
609 dispatcher_api
.set_result(
610 static_cast<EventResult
>(result() | ER_DISABLE_SYNC_HANDLING
));
613 void TouchEvent::FixRotationAngle() {
614 while (rotation_angle_
< 0)
615 rotation_angle_
+= 180;
616 while (rotation_angle_
>= 180)
617 rotation_angle_
-= 180;
620 ////////////////////////////////////////////////////////////////////////////////
624 KeyEvent
* KeyEvent::last_key_event_
= NULL
;
627 bool KeyEvent::IsRepeated(const KeyEvent
& event
) {
628 // A safe guard in case if there were continous key pressed events that are
630 const int kMaxAutoRepeatTimeMs
= 2000;
631 // Ignore key events that have non standard state masks as it may be
632 // reposted by an IME. IBUS-GTK uses this field to detect the
633 // re-posted event for example. crbug.com/385873.
634 if (X11EventHasNonStandardState(event
.native_event()))
638 if (event
.type() == ui::ET_KEY_RELEASED
) {
639 delete last_key_event_
;
640 last_key_event_
= NULL
;
643 CHECK_EQ(ui::ET_KEY_PRESSED
, event
.type());
644 if (!last_key_event_
) {
645 last_key_event_
= new KeyEvent(event
);
648 if (event
.key_code() == last_key_event_
->key_code() &&
649 event
.flags() == last_key_event_
->flags() &&
650 (event
.time_stamp() - last_key_event_
->time_stamp()).InMilliseconds() <
651 kMaxAutoRepeatTimeMs
) {
652 last_key_event_
->set_time_stamp(event
.time_stamp());
655 delete last_key_event_
;
656 last_key_event_
= new KeyEvent(event
);
660 KeyEvent::KeyEvent(const base::NativeEvent
& native_event
)
661 : Event(native_event
,
662 EventTypeFromNative(native_event
),
663 EventFlagsFromNative(native_event
)),
664 key_code_(KeyboardCodeFromNative(native_event
)),
665 code_(CodeFromNative(native_event
)),
666 is_char_(IsCharFromNative(native_event
)),
667 platform_keycode_(PlatformKeycodeFromNative(native_event
)),
670 if (IsRepeated(*this))
671 set_flags(flags() | ui::EF_IS_REPEAT
);
677 // Only Windows has native character events.
679 character_
= native_event
.wParam
;
683 KeyEvent::KeyEvent(EventType type
,
684 KeyboardCode key_code
,
686 : Event(type
, EventTimeForNow(), flags
),
688 code_(DomCode::NONE
),
690 platform_keycode_(0),
695 KeyEvent::KeyEvent(EventType type
,
696 KeyboardCode key_code
,
699 : Event(type
, EventTimeForNow(), flags
),
703 platform_keycode_(0),
708 KeyEvent::KeyEvent(EventType type
,
709 KeyboardCode key_code
,
713 base::char16 character
,
714 base::TimeDelta time_stamp
)
715 : Event(type
, time_stamp
, flags
),
719 platform_keycode_(0),
721 character_(character
) {
724 KeyEvent::KeyEvent(base::char16 character
, KeyboardCode key_code
, int flags
)
725 : Event(ET_KEY_PRESSED
, EventTimeForNow(), flags
),
727 code_(DomCode::NONE
),
729 platform_keycode_(0),
730 key_(DomKey::CHARACTER
),
731 character_(character
) {
734 KeyEvent::KeyEvent(const KeyEvent
& rhs
)
736 key_code_(rhs
.key_code_
),
738 is_char_(rhs
.is_char_
),
739 platform_keycode_(rhs
.platform_keycode_
),
741 character_(rhs
.character_
) {
742 if (rhs
.extended_key_event_data_
)
743 extended_key_event_data_
.reset(rhs
.extended_key_event_data_
->Clone());
746 KeyEvent
& KeyEvent::operator=(const KeyEvent
& rhs
) {
748 Event::operator=(rhs
);
749 key_code_
= rhs
.key_code_
;
752 is_char_
= rhs
.is_char_
;
753 platform_keycode_
= rhs
.platform_keycode_
;
754 character_
= rhs
.character_
;
756 if (rhs
.extended_key_event_data_
)
757 extended_key_event_data_
.reset(rhs
.extended_key_event_data_
->Clone());
762 KeyEvent::~KeyEvent() {}
764 void KeyEvent::SetExtendedKeyEventData(scoped_ptr
<ExtendedKeyEventData
> data
) {
765 extended_key_event_data_
= data
.Pass();
768 void KeyEvent::ApplyLayout() const {
769 // If the client has set the character (e.g. faked key events from virtual
770 // keyboard), it's client's responsibility to set the dom key correctly.
771 // Otherwise, set the dom key as unidentified.
772 // Please refer to crbug.com/443889.
773 if (character_
!= 0) {
774 key_
= DomKey::UNIDENTIFIED
;
778 // Native Windows character events always have is_char_ == true,
779 // so this is a synthetic or native keystroke event.
780 // Therefore, perform only the fallback action.
781 GetMeaningFromKeyCode(key_code_
, flags(), &key_
, &character_
);
782 #elif defined(USE_X11)
783 // When a control key is held, prefer ASCII characters to non ASCII
784 // characters in order to use it for shortcut keys. GetCharacterFromKeyCode
785 // returns 'a' for VKEY_A even if the key is actually bound to 'à' in X11.
786 // GetCharacterFromXEvent returns 'à' in that case.
787 character_
= (IsControlDown() || !native_event()) ?
788 GetCharacterFromKeyCode(key_code_
, flags()) :
789 GetCharacterFromXEvent(native_event());
790 // TODO(kpschoedel): set key_ field for X11.
791 #elif defined(USE_OZONE)
792 KeyboardCode key_code
;
793 if (!KeyboardLayoutEngineManager::GetKeyboardLayoutEngine()->Lookup(
794 code_
, flags(), &key_
, &character_
, &key_code
, &platform_keycode_
)) {
795 GetMeaningFromKeyCode(key_code_
, flags(), &key_
, &character_
);
798 if (native_event()) {
799 DCHECK(EventTypeFromNative(native_event()) == ET_KEY_PRESSED
||
800 EventTypeFromNative(native_event()) == ET_KEY_RELEASED
);
802 // TODO(kpschoedel): revise to use DOM code_ instead of Windows key_code_
803 GetMeaningFromKeyCode(key_code_
, flags(), &key_
, &character_
);
807 DomKey
KeyEvent::GetDomKey() const {
808 // Determination of character_ and key_ may be done lazily.
809 if (key_
== DomKey::NONE
)
814 base::char16
KeyEvent::GetCharacter() const {
815 // Determination of character_ and key_ may be done lazily.
816 if (key_
== DomKey::NONE
)
821 base::char16
KeyEvent::GetText() const {
822 if ((flags() & EF_CONTROL_DOWN
) != 0) {
823 // TODO(kpschoedel): revise to use DOM code_ instead of Windows key_code_
824 return GetControlCharacterForKeycode(key_code_
,
825 (flags() & EF_SHIFT_DOWN
) != 0);
827 return GetUnmodifiedText();
830 base::char16
KeyEvent::GetUnmodifiedText() const {
831 if (!is_char_
&& (key_code_
== VKEY_RETURN
))
833 return GetCharacter();
836 bool KeyEvent::IsUnicodeKeyCode() const {
840 const int key
= key_code();
841 if (key
>= VKEY_NUMPAD0
&& key
<= VKEY_NUMPAD9
)
843 // Check whether the user is using the numeric keypad with num-lock off.
844 // In that case, EF_EXTENDED will not be set; if it is set, the key event
845 // originated from the relevant non-numpad dedicated key, e.g. [Insert].
846 return (!(flags() & EF_EXTENDED
) &&
847 (key
== VKEY_INSERT
|| key
== VKEY_END
|| key
== VKEY_DOWN
||
848 key
== VKEY_NEXT
|| key
== VKEY_LEFT
|| key
== VKEY_CLEAR
||
849 key
== VKEY_RIGHT
|| key
== VKEY_HOME
|| key
== VKEY_UP
||
856 void KeyEvent::NormalizeFlags() {
858 switch (key_code()) {
860 mask
= EF_CONTROL_DOWN
;
863 mask
= EF_SHIFT_DOWN
;
869 mask
= EF_CAPS_LOCK_DOWN
;
874 if (type() == ET_KEY_PRESSED
)
875 set_flags(flags() | mask
);
877 set_flags(flags() & ~mask
);
880 bool KeyEvent::IsTranslated() const {
883 case ET_KEY_RELEASED
:
885 case ET_TRANSLATED_KEY_PRESS
:
886 case ET_TRANSLATED_KEY_RELEASE
:
894 void KeyEvent::SetTranslated(bool translated
) {
897 case ET_TRANSLATED_KEY_PRESS
:
898 SetType(translated
? ET_TRANSLATED_KEY_PRESS
: ET_KEY_PRESSED
);
900 case ET_KEY_RELEASED
:
901 case ET_TRANSLATED_KEY_RELEASE
:
902 SetType(translated
? ET_TRANSLATED_KEY_RELEASE
: ET_KEY_RELEASED
);
909 KeyboardCode
KeyEvent::GetLocatedWindowsKeyboardCode() const {
910 return NonLocatedToLocatedKeyboardCode(key_code_
, code_
);
913 uint16
KeyEvent::GetConflatedWindowsKeyCode() const {
919 std::string
KeyEvent::GetCodeString() const {
920 return KeycodeConverter::DomCodeToCodeString(code_
);
923 ////////////////////////////////////////////////////////////////////////////////
926 ScrollEvent::ScrollEvent(const base::NativeEvent
& native_event
)
927 : MouseEvent(native_event
) {
928 if (type() == ET_SCROLL
) {
929 GetScrollOffsets(native_event
,
930 &x_offset_
, &y_offset_
,
931 &x_offset_ordinal_
, &y_offset_ordinal_
,
933 } else if (type() == ET_SCROLL_FLING_START
||
934 type() == ET_SCROLL_FLING_CANCEL
) {
935 GetFlingData(native_event
,
936 &x_offset_
, &y_offset_
,
937 &x_offset_ordinal_
, &y_offset_ordinal_
,
940 NOTREACHED() << "Unexpected event type " << type()
941 << " when constructing a ScrollEvent.";
945 ScrollEvent::ScrollEvent(EventType type
,
946 const gfx::PointF
& location
,
947 base::TimeDelta time_stamp
,
951 float x_offset_ordinal
,
952 float y_offset_ordinal
,
954 : MouseEvent(type
, location
, location
, time_stamp
, flags
, 0),
957 x_offset_ordinal_(x_offset_ordinal
),
958 y_offset_ordinal_(y_offset_ordinal
),
959 finger_count_(finger_count
) {
960 CHECK(IsScrollEvent());
963 void ScrollEvent::Scale(const float factor
) {
966 x_offset_ordinal_
*= factor
;
967 y_offset_ordinal_
*= factor
;
970 ////////////////////////////////////////////////////////////////////////////////
973 GestureEvent::GestureEvent(float x
,
976 base::TimeDelta time_stamp
,
977 const GestureEventDetails
& details
)
978 : LocatedEvent(details
.type(),
982 flags
| EF_FROM_TOUCH
),
986 GestureEvent::~GestureEvent() {