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