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