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.
4
5 #include "ui/events/event.h"
6
7 #if defined(USE_X11)
8 #include <X11/extensions/XInput2.h>
9 #include <X11/Xlib.h>
10 #endif
11
12 #include <cmath>
13 #include <cstring>
14
15 #include "base/metrics/histogram.h"
16 #include "base/strings/stringprintf.h"
17 #include "ui/events/event_utils.h"
18 #include "ui/events/keycodes/keyboard_code_conversion.h"
19 #include "ui/gfx/point3_f.h"
20 #include "ui/gfx/point_conversions.h"
21 #include "ui/gfx/transform.h"
22 #include "ui/gfx/transform_util.h"
23
24 #if defined(USE_X11)
25 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
26 #elif defined(USE_OZONE)
27 #include "ui/events/keycodes/keyboard_code_conversion.h"
28 #endif
29
30 namespace {
31
EventTypeName(ui::EventType type)32 std::string EventTypeName(ui::EventType type) {
33 #define RETURN_IF_TYPE(t) if (type == ui::t) return #t
34 #define CASE_TYPE(t) case ui::t: return #t
35 switch (type) {
36 CASE_TYPE(ET_UNKNOWN);
37 CASE_TYPE(ET_MOUSE_PRESSED);
38 CASE_TYPE(ET_MOUSE_DRAGGED);
39 CASE_TYPE(ET_MOUSE_RELEASED);
40 CASE_TYPE(ET_MOUSE_MOVED);
41 CASE_TYPE(ET_MOUSE_ENTERED);
42 CASE_TYPE(ET_MOUSE_EXITED);
43 CASE_TYPE(ET_KEY_PRESSED);
44 CASE_TYPE(ET_KEY_RELEASED);
45 CASE_TYPE(ET_MOUSEWHEEL);
46 CASE_TYPE(ET_MOUSE_CAPTURE_CHANGED);
47 CASE_TYPE(ET_TOUCH_RELEASED);
48 CASE_TYPE(ET_TOUCH_PRESSED);
49 CASE_TYPE(ET_TOUCH_MOVED);
50 CASE_TYPE(ET_TOUCH_CANCELLED);
51 CASE_TYPE(ET_DROP_TARGET_EVENT);
52 CASE_TYPE(ET_TRANSLATED_KEY_PRESS);
53 CASE_TYPE(ET_TRANSLATED_KEY_RELEASE);
54 CASE_TYPE(ET_GESTURE_SCROLL_BEGIN);
55 CASE_TYPE(ET_GESTURE_SCROLL_END);
56 CASE_TYPE(ET_GESTURE_SCROLL_UPDATE);
57 CASE_TYPE(ET_GESTURE_SHOW_PRESS);
58 CASE_TYPE(ET_GESTURE_WIN8_EDGE_SWIPE);
59 CASE_TYPE(ET_GESTURE_TAP);
60 CASE_TYPE(ET_GESTURE_TAP_DOWN);
61 CASE_TYPE(ET_GESTURE_TAP_CANCEL);
62 CASE_TYPE(ET_GESTURE_BEGIN);
63 CASE_TYPE(ET_GESTURE_END);
64 CASE_TYPE(ET_GESTURE_TWO_FINGER_TAP);
65 CASE_TYPE(ET_GESTURE_PINCH_BEGIN);
66 CASE_TYPE(ET_GESTURE_PINCH_END);
67 CASE_TYPE(ET_GESTURE_PINCH_UPDATE);
68 CASE_TYPE(ET_GESTURE_LONG_PRESS);
69 CASE_TYPE(ET_GESTURE_LONG_TAP);
70 CASE_TYPE(ET_GESTURE_SWIPE);
71 CASE_TYPE(ET_GESTURE_TAP_UNCONFIRMED);
72 CASE_TYPE(ET_GESTURE_DOUBLE_TAP);
73 CASE_TYPE(ET_SCROLL);
74 CASE_TYPE(ET_SCROLL_FLING_START);
75 CASE_TYPE(ET_SCROLL_FLING_CANCEL);
76 CASE_TYPE(ET_CANCEL_MODE);
77 CASE_TYPE(ET_UMA_DATA);
78 case ui::ET_LAST: NOTREACHED(); return std::string();
79 // Don't include default, so that we get an error when new type is added.
80 }
81 #undef CASE_TYPE
82
83 NOTREACHED();
84 return std::string();
85 }
86
IsX11SendEventTrue(const base::NativeEvent & event)87 bool IsX11SendEventTrue(const base::NativeEvent& event) {
88 #if defined(USE_X11)
89 return event && event->xany.send_event;
90 #else
91 return false;
92 #endif
93 }
94
X11EventHasNonStandardState(const base::NativeEvent & event)95 bool X11EventHasNonStandardState(const base::NativeEvent& event) {
96 #if defined(USE_X11)
97 const unsigned int kAllStateMask =
98 Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask |
99 Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask |
100 LockMask | ControlMask | AnyModifier;
101 return event && (event->xkey.state & ~kAllStateMask) != 0;
102 #else
103 return false;
104 #endif
105 }
106
107 } // namespace
108
109 namespace ui {
110
111 ////////////////////////////////////////////////////////////////////////////////
112 // Event
113
~Event()114 Event::~Event() {
115 if (delete_native_event_)
116 ReleaseCopiedNativeEvent(native_event_);
117 }
118
HasNativeEvent() const119 bool Event::HasNativeEvent() const {
120 base::NativeEvent null_event;
121 std::memset(&null_event, 0, sizeof(null_event));
122 return !!std::memcmp(&native_event_, &null_event, sizeof(null_event));
123 }
124
StopPropagation()125 void Event::StopPropagation() {
126 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
127 // events.
128 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
129 CHECK(cancelable_);
130 result_ = static_cast<EventResult>(result_ | ER_CONSUMED);
131 }
132
SetHandled()133 void Event::SetHandled() {
134 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
135 // events.
136 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
137 CHECK(cancelable_);
138 result_ = static_cast<EventResult>(result_ | ER_HANDLED);
139 }
140
Event(EventType type,base::TimeDelta time_stamp,int flags)141 Event::Event(EventType type, base::TimeDelta time_stamp, int flags)
142 : type_(type),
143 time_stamp_(time_stamp),
144 flags_(flags),
145 native_event_(base::NativeEvent()),
146 delete_native_event_(false),
147 cancelable_(true),
148 target_(NULL),
149 phase_(EP_PREDISPATCH),
150 result_(ER_UNHANDLED) {
151 if (type_ < ET_LAST)
152 name_ = EventTypeName(type_);
153 }
154
Event(const base::NativeEvent & native_event,EventType type,int flags)155 Event::Event(const base::NativeEvent& native_event,
156 EventType type,
157 int flags)
158 : type_(type),
159 time_stamp_(EventTimeFromNative(native_event)),
160 flags_(flags),
161 native_event_(native_event),
162 delete_native_event_(false),
163 cancelable_(true),
164 target_(NULL),
165 phase_(EP_PREDISPATCH),
166 result_(ER_UNHANDLED) {
167 base::TimeDelta delta = EventTimeForNow() - time_stamp_;
168 if (type_ < ET_LAST)
169 name_ = EventTypeName(type_);
170 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser",
171 delta.InMicroseconds(), 1, 1000000, 100);
172 std::string name_for_event =
173 base::StringPrintf("Event.Latency.Browser.%s", name_.c_str());
174 base::HistogramBase* counter_for_type =
175 base::Histogram::FactoryGet(
176 name_for_event,
177 1,
178 1000000,
179 100,
180 base::HistogramBase::kUmaTargetedHistogramFlag);
181 counter_for_type->Add(delta.InMicroseconds());
182 }
183
Event(const Event & copy)184 Event::Event(const Event& copy)
185 : type_(copy.type_),
186 time_stamp_(copy.time_stamp_),
187 latency_(copy.latency_),
188 flags_(copy.flags_),
189 native_event_(CopyNativeEvent(copy.native_event_)),
190 delete_native_event_(true),
191 cancelable_(true),
192 target_(NULL),
193 phase_(EP_PREDISPATCH),
194 result_(ER_UNHANDLED) {
195 if (type_ < ET_LAST)
196 name_ = EventTypeName(type_);
197 }
198
SetType(EventType type)199 void Event::SetType(EventType type) {
200 if (type_ < ET_LAST)
201 name_ = std::string();
202 type_ = type;
203 if (type_ < ET_LAST)
204 name_ = EventTypeName(type_);
205 }
206
207 ////////////////////////////////////////////////////////////////////////////////
208 // CancelModeEvent
209
CancelModeEvent()210 CancelModeEvent::CancelModeEvent()
211 : Event(ET_CANCEL_MODE, base::TimeDelta(), 0) {
212 set_cancelable(false);
213 }
214
~CancelModeEvent()215 CancelModeEvent::~CancelModeEvent() {
216 }
217
218 ////////////////////////////////////////////////////////////////////////////////
219 // LocatedEvent
220
~LocatedEvent()221 LocatedEvent::~LocatedEvent() {
222 }
223
LocatedEvent(const base::NativeEvent & native_event)224 LocatedEvent::LocatedEvent(const base::NativeEvent& native_event)
225 : Event(native_event,
226 EventTypeFromNative(native_event),
227 EventFlagsFromNative(native_event)),
228 location_(EventLocationFromNative(native_event)),
229 root_location_(location_) {
230 }
231
LocatedEvent(EventType type,const gfx::PointF & location,const gfx::PointF & root_location,base::TimeDelta time_stamp,int flags)232 LocatedEvent::LocatedEvent(EventType type,
233 const gfx::PointF& location,
234 const gfx::PointF& root_location,
235 base::TimeDelta time_stamp,
236 int flags)
237 : Event(type, time_stamp, flags),
238 location_(location),
239 root_location_(root_location) {
240 }
241
UpdateForRootTransform(const gfx::Transform & reversed_root_transform)242 void LocatedEvent::UpdateForRootTransform(
243 const gfx::Transform& reversed_root_transform) {
244 // Transform has to be done at root level.
245 gfx::Point3F p(location_);
246 reversed_root_transform.TransformPoint(&p);
247 location_ = p.AsPointF();
248 root_location_ = location_;
249 }
250
251 ////////////////////////////////////////////////////////////////////////////////
252 // MouseEvent
253
MouseEvent(const base::NativeEvent & native_event)254 MouseEvent::MouseEvent(const base::NativeEvent& native_event)
255 : LocatedEvent(native_event),
256 changed_button_flags_(
257 GetChangedMouseButtonFlagsFromNative(native_event)) {
258 if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED)
259 SetClickCount(GetRepeatCount(*this));
260 }
261
MouseEvent(EventType type,const gfx::PointF & location,const gfx::PointF & root_location,int flags,int changed_button_flags)262 MouseEvent::MouseEvent(EventType type,
263 const gfx::PointF& location,
264 const gfx::PointF& root_location,
265 int flags,
266 int changed_button_flags)
267 : LocatedEvent(type, location, root_location, EventTimeForNow(), flags),
268 changed_button_flags_(changed_button_flags) {
269 if (this->type() == ET_MOUSE_MOVED && IsAnyButton())
270 SetType(ET_MOUSE_DRAGGED);
271 }
272
273 // static
IsRepeatedClickEvent(const MouseEvent & event1,const MouseEvent & event2)274 bool MouseEvent::IsRepeatedClickEvent(
275 const MouseEvent& event1,
276 const MouseEvent& event2) {
277 // These values match the Windows defaults.
278 static const int kDoubleClickTimeMS = 500;
279 static const int kDoubleClickWidth = 4;
280 static const int kDoubleClickHeight = 4;
281
282 if (event1.type() != ET_MOUSE_PRESSED ||
283 event2.type() != ET_MOUSE_PRESSED)
284 return false;
285
286 // Compare flags, but ignore EF_IS_DOUBLE_CLICK to allow triple clicks.
287 if ((event1.flags() & ~EF_IS_DOUBLE_CLICK) !=
288 (event2.flags() & ~EF_IS_DOUBLE_CLICK))
289 return false;
290
291 base::TimeDelta time_difference = event2.time_stamp() - event1.time_stamp();
292
293 if (time_difference.InMilliseconds() > kDoubleClickTimeMS)
294 return false;
295
296 if (std::abs(event2.x() - event1.x()) > kDoubleClickWidth / 2)
297 return false;
298
299 if (std::abs(event2.y() - event1.y()) > kDoubleClickHeight / 2)
300 return false;
301
302 return true;
303 }
304
305 // static
GetRepeatCount(const MouseEvent & event)306 int MouseEvent::GetRepeatCount(const MouseEvent& event) {
307 int click_count = 1;
308 if (last_click_event_) {
309 if (event.type() == ui::ET_MOUSE_RELEASED) {
310 if (event.changed_button_flags() ==
311 last_click_event_->changed_button_flags()) {
312 last_click_complete_ = true;
313 return last_click_event_->GetClickCount();
314 } else {
315 // If last_click_event_ has changed since this button was pressed
316 // return a click count of 1.
317 return click_count;
318 }
319 }
320 if (event.time_stamp() != last_click_event_->time_stamp())
321 last_click_complete_ = true;
322 if (!last_click_complete_ ||
323 IsX11SendEventTrue(event.native_event())) {
324 click_count = last_click_event_->GetClickCount();
325 } else if (IsRepeatedClickEvent(*last_click_event_, event)) {
326 click_count = last_click_event_->GetClickCount() + 1;
327 }
328 delete last_click_event_;
329 }
330 last_click_event_ = new MouseEvent(event);
331 last_click_complete_ = false;
332 if (click_count > 3)
333 click_count = 3;
334 last_click_event_->SetClickCount(click_count);
335 return click_count;
336 }
337
ResetLastClickForTest()338 void MouseEvent::ResetLastClickForTest() {
339 if (last_click_event_) {
340 delete last_click_event_;
341 last_click_event_ = NULL;
342 last_click_complete_ = false;
343 }
344 }
345
346 // static
347 MouseEvent* MouseEvent::last_click_event_ = NULL;
348 bool MouseEvent::last_click_complete_ = false;
349
GetClickCount() const350 int MouseEvent::GetClickCount() const {
351 if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
352 return 0;
353
354 if (flags() & EF_IS_TRIPLE_CLICK)
355 return 3;
356 else if (flags() & EF_IS_DOUBLE_CLICK)
357 return 2;
358 else
359 return 1;
360 }
361
SetClickCount(int click_count)362 void MouseEvent::SetClickCount(int click_count) {
363 if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
364 return;
365
366 DCHECK(click_count > 0);
367 DCHECK(click_count <= 3);
368
369 int f = flags();
370 switch (click_count) {
371 case 1:
372 f &= ~EF_IS_DOUBLE_CLICK;
373 f &= ~EF_IS_TRIPLE_CLICK;
374 break;
375 case 2:
376 f |= EF_IS_DOUBLE_CLICK;
377 f &= ~EF_IS_TRIPLE_CLICK;
378 break;
379 case 3:
380 f &= ~EF_IS_DOUBLE_CLICK;
381 f |= EF_IS_TRIPLE_CLICK;
382 break;
383 }
384 set_flags(f);
385 }
386
387 ////////////////////////////////////////////////////////////////////////////////
388 // MouseWheelEvent
389
MouseWheelEvent(const base::NativeEvent & native_event)390 MouseWheelEvent::MouseWheelEvent(const base::NativeEvent& native_event)
391 : MouseEvent(native_event),
392 offset_(GetMouseWheelOffset(native_event)) {
393 }
394
MouseWheelEvent(const ScrollEvent & scroll_event)395 MouseWheelEvent::MouseWheelEvent(const ScrollEvent& scroll_event)
396 : MouseEvent(scroll_event),
397 offset_(scroll_event.x_offset(), scroll_event.y_offset()){
398 SetType(ET_MOUSEWHEEL);
399 }
400
MouseWheelEvent(const MouseEvent & mouse_event,int x_offset,int y_offset)401 MouseWheelEvent::MouseWheelEvent(const MouseEvent& mouse_event,
402 int x_offset,
403 int y_offset)
404 : MouseEvent(mouse_event), offset_(x_offset, y_offset) {
405 DCHECK(type() == ET_MOUSEWHEEL);
406 }
407
MouseWheelEvent(const MouseWheelEvent & mouse_wheel_event)408 MouseWheelEvent::MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event)
409 : MouseEvent(mouse_wheel_event),
410 offset_(mouse_wheel_event.offset()) {
411 DCHECK(type() == ET_MOUSEWHEEL);
412 }
413
414 #if defined(OS_WIN)
415 // This value matches windows WHEEL_DELTA.
416 // static
417 const int MouseWheelEvent::kWheelDelta = 120;
418 #else
419 // This value matches GTK+ wheel scroll amount.
420 const int MouseWheelEvent::kWheelDelta = 53;
421 #endif
422
UpdateForRootTransform(const gfx::Transform & inverted_root_transform)423 void MouseWheelEvent::UpdateForRootTransform(
424 const gfx::Transform& inverted_root_transform) {
425 LocatedEvent::UpdateForRootTransform(inverted_root_transform);
426 gfx::DecomposedTransform decomp;
427 bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
428 DCHECK(success);
429 if (decomp.scale[0])
430 offset_.set_x(offset_.x() * decomp.scale[0]);
431 if (decomp.scale[1])
432 offset_.set_y(offset_.y() * decomp.scale[1]);
433 }
434
435 ////////////////////////////////////////////////////////////////////////////////
436 // TouchEvent
437
TouchEvent(const base::NativeEvent & native_event)438 TouchEvent::TouchEvent(const base::NativeEvent& native_event)
439 : LocatedEvent(native_event),
440 touch_id_(GetTouchId(native_event)),
441 radius_x_(GetTouchRadiusX(native_event)),
442 radius_y_(GetTouchRadiusY(native_event)),
443 rotation_angle_(GetTouchAngle(native_event)),
444 force_(GetTouchForce(native_event)),
445 source_device_id_(-1) {
446 latency()->AddLatencyNumberWithTimestamp(
447 INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
448 0,
449 0,
450 base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()),
451 1);
452
453 #if defined(USE_X11)
454 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(native_event->xcookie.data);
455 source_device_id_ = xiev->deviceid;
456 #endif
457
458 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
459 }
460
TouchEvent(EventType type,const gfx::PointF & location,int touch_id,base::TimeDelta time_stamp)461 TouchEvent::TouchEvent(EventType type,
462 const gfx::PointF& location,
463 int touch_id,
464 base::TimeDelta time_stamp)
465 : LocatedEvent(type, location, location, time_stamp, 0),
466 touch_id_(touch_id),
467 radius_x_(0.0f),
468 radius_y_(0.0f),
469 rotation_angle_(0.0f),
470 force_(0.0f),
471 source_device_id_(-1) {
472 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
473 }
474
TouchEvent(EventType type,const gfx::PointF & location,int flags,int touch_id,base::TimeDelta time_stamp,float radius_x,float radius_y,float angle,float force)475 TouchEvent::TouchEvent(EventType type,
476 const gfx::PointF& location,
477 int flags,
478 int touch_id,
479 base::TimeDelta time_stamp,
480 float radius_x,
481 float radius_y,
482 float angle,
483 float force)
484 : LocatedEvent(type, location, location, time_stamp, flags),
485 touch_id_(touch_id),
486 radius_x_(radius_x),
487 radius_y_(radius_y),
488 rotation_angle_(angle),
489 force_(force),
490 source_device_id_(-1) {
491 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
492 }
493
~TouchEvent()494 TouchEvent::~TouchEvent() {
495 // In ctor TouchEvent(native_event) we call GetTouchId() which in X11
496 // platform setups the tracking_id to slot mapping. So in dtor here,
497 // if this touch event is a release event, we clear the mapping accordingly.
498 if (HasNativeEvent())
499 ClearTouchIdIfReleased(native_event());
500 }
501
UpdateForRootTransform(const gfx::Transform & inverted_root_transform)502 void TouchEvent::UpdateForRootTransform(
503 const gfx::Transform& inverted_root_transform) {
504 LocatedEvent::UpdateForRootTransform(inverted_root_transform);
505 gfx::DecomposedTransform decomp;
506 bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
507 DCHECK(success);
508 if (decomp.scale[0])
509 radius_x_ *= decomp.scale[0];
510 if (decomp.scale[1])
511 radius_y_ *= decomp.scale[1];
512 }
513
514 ////////////////////////////////////////////////////////////////////////////////
515 // KeyEvent
516
517 // static
518 KeyEvent* KeyEvent::last_key_event_ = NULL;
519
520 // static
IsRepeated(const KeyEvent & event)521 bool KeyEvent::IsRepeated(const KeyEvent& event) {
522 // A safe guard in case if there were continous key pressed events that are
523 // not auto repeat.
524 const int kMaxAutoRepeatTimeMs = 2000;
525 // Ignore key events that have non standard state masks as it may be
526 // reposted by an IME. IBUS-GTK uses this field to detect the
527 // re-posted event for example. crbug.com/385873.
528 if (X11EventHasNonStandardState(event.native_event()))
529 return false;
530 if (event.is_char())
531 return false;
532 if (event.type() == ui::ET_KEY_RELEASED) {
533 delete last_key_event_;
534 last_key_event_ = NULL;
535 return false;
536 }
537 CHECK_EQ(ui::ET_KEY_PRESSED, event.type());
538 if (!last_key_event_) {
539 last_key_event_ = new KeyEvent(event);
540 return false;
541 }
542 if (event.key_code() == last_key_event_->key_code() &&
543 event.flags() == last_key_event_->flags() &&
544 (event.time_stamp() - last_key_event_->time_stamp()).InMilliseconds() <
545 kMaxAutoRepeatTimeMs) {
546 return true;
547 }
548 delete last_key_event_;
549 last_key_event_ = new KeyEvent(event);
550 return false;
551 }
552
KeyEvent(const base::NativeEvent & native_event,bool is_char)553 KeyEvent::KeyEvent(const base::NativeEvent& native_event, bool is_char)
554 : Event(native_event,
555 EventTypeFromNative(native_event),
556 EventFlagsFromNative(native_event)),
557 key_code_(KeyboardCodeFromNative(native_event)),
558 code_(CodeFromNative(native_event)),
559 is_char_(is_char),
560 platform_keycode_(PlatformKeycodeFromNative(native_event)),
561 character_(0) {
562 if (IsRepeated(*this))
563 set_flags(flags() | ui::EF_IS_REPEAT);
564
565 #if defined(USE_X11)
566 NormalizeFlags();
567 #endif
568 }
569
KeyEvent(EventType type,KeyboardCode key_code,int flags,bool is_char)570 KeyEvent::KeyEvent(EventType type,
571 KeyboardCode key_code,
572 int flags,
573 bool is_char)
574 : Event(type, EventTimeForNow(), flags),
575 key_code_(key_code),
576 is_char_(is_char),
577 platform_keycode_(0),
578 character_(GetCharacterFromKeyCode(key_code, flags)) {
579 }
580
KeyEvent(EventType type,KeyboardCode key_code,const std::string & code,int flags,bool is_char)581 KeyEvent::KeyEvent(EventType type,
582 KeyboardCode key_code,
583 const std::string& code,
584 int flags,
585 bool is_char)
586 : Event(type, EventTimeForNow(), flags),
587 key_code_(key_code),
588 code_(code),
589 is_char_(is_char),
590 platform_keycode_(0),
591 character_(GetCharacterFromKeyCode(key_code, flags)) {
592 }
593
GetCharacter() const594 uint16 KeyEvent::GetCharacter() const {
595 if (character_)
596 return character_;
597
598 #if defined(OS_WIN)
599 return (native_event().message == WM_CHAR) ? key_code_ :
600 GetCharacterFromKeyCode(key_code_, flags());
601 #elif defined(USE_X11)
602 if (!native_event())
603 return GetCharacterFromKeyCode(key_code_, flags());
604
605 DCHECK(native_event()->type == KeyPress ||
606 native_event()->type == KeyRelease);
607
608 // When a control key is held, prefer ASCII characters to non ASCII
609 // characters in order to use it for shortcut keys. GetCharacterFromKeyCode
610 // returns 'a' for VKEY_A even if the key is actually bound to 'à' in X11.
611 // GetCharacterFromXEvent returns 'à' in that case.
612 return IsControlDown() ?
613 GetCharacterFromKeyCode(key_code_, flags()) :
614 GetCharacterFromXEvent(native_event());
615 #else
616 if (native_event()) {
617 DCHECK(EventTypeFromNative(native_event()) == ET_KEY_PRESSED ||
618 EventTypeFromNative(native_event()) == ET_KEY_RELEASED);
619 }
620
621 return GetCharacterFromKeyCode(key_code_, flags());
622 #endif
623 }
624
IsUnicodeKeyCode() const625 bool KeyEvent::IsUnicodeKeyCode() const {
626 #if defined(OS_WIN)
627 if (!IsAltDown())
628 return false;
629 const int key = key_code();
630 if (key >= VKEY_NUMPAD0 && key <= VKEY_NUMPAD9)
631 return true;
632 // Check whether the user is using the numeric keypad with num-lock off.
633 // In that case, EF_EXTENDED will not be set; if it is set, the key event
634 // originated from the relevant non-numpad dedicated key, e.g. [Insert].
635 return (!(flags() & EF_EXTENDED) &&
636 (key == VKEY_INSERT || key == VKEY_END || key == VKEY_DOWN ||
637 key == VKEY_NEXT || key == VKEY_LEFT || key == VKEY_CLEAR ||
638 key == VKEY_RIGHT || key == VKEY_HOME || key == VKEY_UP ||
639 key == VKEY_PRIOR));
640 #else
641 return false;
642 #endif
643 }
644
NormalizeFlags()645 void KeyEvent::NormalizeFlags() {
646 int mask = 0;
647 switch (key_code()) {
648 case VKEY_CONTROL:
649 mask = EF_CONTROL_DOWN;
650 break;
651 case VKEY_SHIFT:
652 mask = EF_SHIFT_DOWN;
653 break;
654 case VKEY_MENU:
655 mask = EF_ALT_DOWN;
656 break;
657 case VKEY_CAPITAL:
658 mask = EF_CAPS_LOCK_DOWN;
659 break;
660 default:
661 return;
662 }
663 if (type() == ET_KEY_PRESSED)
664 set_flags(flags() | mask);
665 else
666 set_flags(flags() & ~mask);
667 }
668
IsTranslated() const669 bool KeyEvent::IsTranslated() const {
670 switch (type()) {
671 case ET_KEY_PRESSED:
672 case ET_KEY_RELEASED:
673 return false;
674 case ET_TRANSLATED_KEY_PRESS:
675 case ET_TRANSLATED_KEY_RELEASE:
676 return true;
677 default:
678 NOTREACHED();
679 return false;
680 }
681 }
682
SetTranslated(bool translated)683 void KeyEvent::SetTranslated(bool translated) {
684 switch (type()) {
685 case ET_KEY_PRESSED:
686 case ET_TRANSLATED_KEY_PRESS:
687 SetType(translated ? ET_TRANSLATED_KEY_PRESS : ET_KEY_PRESSED);
688 break;
689 case ET_KEY_RELEASED:
690 case ET_TRANSLATED_KEY_RELEASE:
691 SetType(translated ? ET_TRANSLATED_KEY_RELEASE : ET_KEY_RELEASED);
692 break;
693 default:
694 NOTREACHED();
695 }
696 }
697
698 ////////////////////////////////////////////////////////////////////////////////
699 // ScrollEvent
700
ScrollEvent(const base::NativeEvent & native_event)701 ScrollEvent::ScrollEvent(const base::NativeEvent& native_event)
702 : MouseEvent(native_event) {
703 if (type() == ET_SCROLL) {
704 GetScrollOffsets(native_event,
705 &x_offset_, &y_offset_,
706 &x_offset_ordinal_, &y_offset_ordinal_,
707 &finger_count_);
708 } else if (type() == ET_SCROLL_FLING_START ||
709 type() == ET_SCROLL_FLING_CANCEL) {
710 GetFlingData(native_event,
711 &x_offset_, &y_offset_,
712 &x_offset_ordinal_, &y_offset_ordinal_,
713 NULL);
714 } else {
715 NOTREACHED() << "Unexpected event type " << type()
716 << " when constructing a ScrollEvent.";
717 }
718 }
719
ScrollEvent(EventType type,const gfx::PointF & location,base::TimeDelta time_stamp,int flags,float x_offset,float y_offset,float x_offset_ordinal,float y_offset_ordinal,int finger_count)720 ScrollEvent::ScrollEvent(EventType type,
721 const gfx::PointF& location,
722 base::TimeDelta time_stamp,
723 int flags,
724 float x_offset,
725 float y_offset,
726 float x_offset_ordinal,
727 float y_offset_ordinal,
728 int finger_count)
729 : MouseEvent(type, location, location, flags, 0),
730 x_offset_(x_offset),
731 y_offset_(y_offset),
732 x_offset_ordinal_(x_offset_ordinal),
733 y_offset_ordinal_(y_offset_ordinal),
734 finger_count_(finger_count) {
735 set_time_stamp(time_stamp);
736 CHECK(IsScrollEvent());
737 }
738
Scale(const float factor)739 void ScrollEvent::Scale(const float factor) {
740 x_offset_ *= factor;
741 y_offset_ *= factor;
742 x_offset_ordinal_ *= factor;
743 y_offset_ordinal_ *= factor;
744 }
745
746 ////////////////////////////////////////////////////////////////////////////////
747 // GestureEvent
748
GestureEvent(EventType type,float x,float y,int flags,base::TimeDelta time_stamp,const GestureEventDetails & details,unsigned int touch_ids_bitfield)749 GestureEvent::GestureEvent(EventType type,
750 float x,
751 float y,
752 int flags,
753 base::TimeDelta time_stamp,
754 const GestureEventDetails& details,
755 unsigned int touch_ids_bitfield)
756 : LocatedEvent(type,
757 gfx::PointF(x, y),
758 gfx::PointF(x, y),
759 time_stamp,
760 flags | EF_FROM_TOUCH),
761 details_(details),
762 touch_ids_bitfield_(touch_ids_bitfield) {
763 }
764
~GestureEvent()765 GestureEvent::~GestureEvent() {
766 }
767
GetLowestTouchId() const768 int GestureEvent::GetLowestTouchId() const {
769 if (touch_ids_bitfield_ == 0)
770 return -1;
771 int i = -1;
772 // Find the index of the least significant 1 bit
773 while (!(1 << ++i & touch_ids_bitfield_));
774 return i;
775 }
776
777 } // namespace ui
778