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/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 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 
    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 
    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 
    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 
    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 
    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 
    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 
    210 CancelModeEvent::CancelModeEvent()
    211     : Event(ET_CANCEL_MODE, base::TimeDelta(), 0) {
    212   set_cancelable(false);
    213 }
    214 
    215 CancelModeEvent::~CancelModeEvent() {
    216 }
    217 
    218 ////////////////////////////////////////////////////////////////////////////////
    219 // LocatedEvent
    220 
    221 LocatedEvent::~LocatedEvent() {
    222 }
    223 
    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 
    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 
    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 
    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 
    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
    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
    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 
    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 
    350 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 
    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 
    390 MouseWheelEvent::MouseWheelEvent(const base::NativeEvent& native_event)
    391     : MouseEvent(native_event),
    392       offset_(GetMouseWheelOffset(native_event)) {
    393 }
    394 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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 
    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 
    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 
    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 
    594 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 
    625 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 
    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 
    669 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 
    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 
    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 
    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 
    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 
    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 
    765 GestureEvent::~GestureEvent() {
    766 }
    767 
    768 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