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