Home | History | Annotate | Download | only in x
      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_constants.h"
      6 
      7 #include <cmath>
      8 #include <string.h>
      9 #include <X11/extensions/XInput.h>
     10 #include <X11/extensions/XInput2.h>
     11 #include <X11/Xlib.h>
     12 #include <X11/Xutil.h>
     13 
     14 #include "base/logging.h"
     15 #include "base/memory/singleton.h"
     16 #include "ui/events/event_utils.h"
     17 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
     18 #include "ui/events/x/device_data_manager.h"
     19 #include "ui/events/x/device_list_cache_x.h"
     20 #include "ui/events/x/touch_factory_x11.h"
     21 #include "ui/gfx/display.h"
     22 #include "ui/gfx/point.h"
     23 #include "ui/gfx/rect.h"
     24 #include "ui/gfx/screen.h"
     25 #include "ui/gfx/x/x11_atom_cache.h"
     26 #include "ui/gfx/x/x11_types.h"
     27 
     28 namespace {
     29 
     30 // Scroll amount for each wheelscroll event. 53 is also the value used for GTK+.
     31 const int kWheelScrollAmount = 53;
     32 
     33 const int kMinWheelButton = 4;
     34 const int kMaxWheelButton = 7;
     35 
     36 // A class to track current modifier state on master device. Only track ctrl,
     37 // alt, shift and caps lock keys currently. The tracked state can then be used
     38 // by floating device.
     39 class XModifierStateWatcher{
     40  public:
     41   static XModifierStateWatcher* GetInstance() {
     42     return Singleton<XModifierStateWatcher>::get();
     43   }
     44 
     45   void UpdateStateFromEvent(const base::NativeEvent& native_event) {
     46     // Floating device can't access the modifer state from master device.
     47     // We need to track the states of modifier keys in a singleton for
     48     // floating devices such as touch screen. Issue 106426 is one example
     49     // of why we need the modifier states for floating device.
     50     state_ = native_event->xkey.state;
     51     // master_state is the state before key press. We need to track the
     52     // state after key press for floating device. Currently only ctrl,
     53     // shift, alt and caps lock keys are tracked.
     54     ui::KeyboardCode keyboard_code = ui::KeyboardCodeFromNative(native_event);
     55     unsigned int mask = 0;
     56 
     57     switch (keyboard_code) {
     58       case ui::VKEY_CONTROL: {
     59         mask = ControlMask;
     60         break;
     61       }
     62       case ui::VKEY_SHIFT: {
     63         mask = ShiftMask;
     64         break;
     65       }
     66       case ui::VKEY_MENU: {
     67         mask = Mod1Mask;
     68         break;
     69       }
     70       case ui::VKEY_CAPITAL: {
     71         mask = LockMask;
     72         break;
     73       }
     74       default:
     75         break;
     76     }
     77 
     78     if (native_event->type == KeyPress)
     79       state_ |= mask;
     80     else
     81       state_ &= ~mask;
     82   }
     83 
     84   // Returns the current modifer state in master device. It only contains the
     85   // state of ctrl, shift, alt and caps lock keys.
     86   unsigned int state() { return state_; }
     87 
     88  private:
     89   friend struct DefaultSingletonTraits<XModifierStateWatcher>;
     90 
     91   XModifierStateWatcher() : state_(0) { }
     92 
     93   unsigned int state_;
     94 
     95   DISALLOW_COPY_AND_ASSIGN(XModifierStateWatcher);
     96 };
     97 
     98 #if defined(USE_XI2_MT)
     99 // Detects if a touch event is a driver-generated 'special event'.
    100 // A 'special event' is a touch event with maximum radius and pressure at
    101 // location (0, 0).
    102 // This needs to be done in a cleaner way: http://crbug.com/169256
    103 bool TouchEventIsGeneratedHack(const base::NativeEvent& native_event) {
    104   XIDeviceEvent* event =
    105       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    106   CHECK(event->evtype == XI_TouchBegin ||
    107         event->evtype == XI_TouchUpdate ||
    108         event->evtype == XI_TouchEnd);
    109 
    110   // Force is normalized to [0, 1].
    111   if (ui::GetTouchForce(native_event) < 1.0f)
    112     return false;
    113 
    114   if (ui::EventLocationFromNative(native_event) != gfx::Point())
    115     return false;
    116 
    117   // Radius is in pixels, and the valuator is the diameter in pixels.
    118   double radius = ui::GetTouchRadiusX(native_event), min, max;
    119   unsigned int deviceid =
    120       static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
    121   if (!ui::DeviceDataManager::GetInstance()->GetDataRange(
    122       deviceid, ui::DeviceDataManager::DT_TOUCH_MAJOR, &min, &max)) {
    123     return false;
    124   }
    125 
    126   return radius * 2 == max;
    127 }
    128 #endif
    129 
    130 int GetEventFlagsFromXState(unsigned int state) {
    131   int flags = 0;
    132   if (state & ControlMask)
    133     flags |= ui::EF_CONTROL_DOWN;
    134   if (state & ShiftMask)
    135     flags |= ui::EF_SHIFT_DOWN;
    136   if (state & Mod1Mask)
    137     flags |= ui::EF_ALT_DOWN;
    138   if (state & LockMask)
    139     flags |= ui::EF_CAPS_LOCK_DOWN;
    140   if (state & Mod3Mask)
    141     flags |= ui::EF_MOD3_DOWN;
    142   if (state & Mod4Mask)
    143     flags |= ui::EF_COMMAND_DOWN;
    144   if (state & Mod5Mask)
    145     flags |= ui::EF_ALTGR_DOWN;
    146   if (state & Button1Mask)
    147     flags |= ui::EF_LEFT_MOUSE_BUTTON;
    148   if (state & Button2Mask)
    149     flags |= ui::EF_MIDDLE_MOUSE_BUTTON;
    150   if (state & Button3Mask)
    151     flags |= ui::EF_RIGHT_MOUSE_BUTTON;
    152   return flags;
    153 }
    154 
    155 int GetEventFlagsFromXKeyEvent(XEvent* xevent) {
    156   DCHECK(xevent->type == KeyPress || xevent->type == KeyRelease);
    157 
    158 #if defined(OS_CHROMEOS)
    159   const int ime_fabricated_flag = 0;
    160 #else
    161   // XIM fabricates key events for the character compositions by XK_Multi_key.
    162   // For example, when a user hits XK_Multi_key, XK_apostrophe, and XK_e in
    163   // order to input "", then XIM generates a key event with keycode=0 and
    164   // state=0 for the composition, and the sequence of X11 key events will be
    165   // XK_Multi_key, XK_apostrophe, **NoSymbol**, and XK_e.  If the user used
    166   // shift key and/or caps lock key, state can be ShiftMask, LockMask or both.
    167   //
    168   // We have to send these fabricated key events to XIM so it can correctly
    169   // handle the character compositions.
    170   const unsigned int shift_lock_mask = ShiftMask | LockMask;
    171   const bool fabricated_by_xim =
    172       xevent->xkey.keycode == 0 &&
    173       (xevent->xkey.state & ~shift_lock_mask) == 0;
    174   const int ime_fabricated_flag =
    175       fabricated_by_xim ? ui::EF_IME_FABRICATED_KEY : 0;
    176 #endif
    177 
    178   return GetEventFlagsFromXState(xevent->xkey.state) |
    179       (IsKeypadKey(XLookupKeysym(&xevent->xkey, 0)) ? ui::EF_NUMPAD_KEY : 0) |
    180       (IsFunctionKey(XLookupKeysym(&xevent->xkey, 0)) ?
    181           ui::EF_FUNCTION_KEY : 0) |
    182       ime_fabricated_flag;
    183 }
    184 
    185 // Get the event flag for the button in XButtonEvent. During a ButtonPress
    186 // event, |state| in XButtonEvent does not include the button that has just been
    187 // pressed. Instead |state| contains flags for the buttons (if any) that had
    188 // already been pressed before the current button, and |button| stores the most
    189 // current pressed button. So, if you press down left mouse button, and while
    190 // pressing it down, press down the right mouse button, then for the latter
    191 // event, |state| would have Button1Mask set but not Button3Mask, and |button|
    192 // would be 3.
    193 int GetEventFlagsForButton(int button) {
    194   switch (button) {
    195     case 1:
    196       return ui::EF_LEFT_MOUSE_BUTTON;
    197     case 2:
    198       return ui::EF_MIDDLE_MOUSE_BUTTON;
    199     case 3:
    200       return ui::EF_RIGHT_MOUSE_BUTTON;
    201     default:
    202       return 0;
    203   }
    204 }
    205 
    206 int GetButtonMaskForX2Event(XIDeviceEvent* xievent) {
    207   int buttonflags = 0;
    208   for (int i = 0; i < 8 * xievent->buttons.mask_len; i++) {
    209     if (XIMaskIsSet(xievent->buttons.mask, i)) {
    210       int button = (xievent->sourceid == xievent->deviceid) ?
    211                    ui::DeviceDataManager::GetInstance()->GetMappedButton(i) : i;
    212       buttonflags |= GetEventFlagsForButton(button);
    213     }
    214   }
    215   return buttonflags;
    216 }
    217 
    218 ui::EventType GetTouchEventType(const base::NativeEvent& native_event) {
    219   XIDeviceEvent* event =
    220       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    221 #if defined(USE_XI2_MT)
    222   switch(event->evtype) {
    223     case XI_TouchBegin:
    224       return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN :
    225                                                        ui::ET_TOUCH_PRESSED;
    226     case XI_TouchUpdate:
    227       return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN :
    228                                                        ui::ET_TOUCH_MOVED;
    229     case XI_TouchEnd:
    230       return TouchEventIsGeneratedHack(native_event) ? ui::ET_TOUCH_CANCELLED :
    231                                                        ui::ET_TOUCH_RELEASED;
    232   }
    233 #endif  // defined(USE_XI2_MT)
    234 
    235   DCHECK(ui::TouchFactory::GetInstance()->IsTouchDevice(event->sourceid));
    236   switch (event->evtype) {
    237     case XI_ButtonPress:
    238       return ui::ET_TOUCH_PRESSED;
    239     case XI_ButtonRelease:
    240       return ui::ET_TOUCH_RELEASED;
    241     case XI_Motion:
    242       // Should not convert any emulated Motion event from touch device to
    243       // touch event.
    244       if (!(event->flags & XIPointerEmulated) &&
    245           GetButtonMaskForX2Event(event))
    246         return ui::ET_TOUCH_MOVED;
    247       return ui::ET_UNKNOWN;
    248     default:
    249       NOTREACHED();
    250   }
    251   return ui::ET_UNKNOWN;
    252 }
    253 
    254 double GetTouchParamFromXEvent(XEvent* xev,
    255                               ui::DeviceDataManager::DataType val,
    256                               double default_value) {
    257   ui::DeviceDataManager::GetInstance()->GetEventData(
    258       *xev, val, &default_value);
    259   return default_value;
    260 }
    261 
    262 }  // namespace
    263 
    264 namespace ui {
    265 
    266 void UpdateDeviceList() {
    267   XDisplay* display = gfx::GetXDisplay();
    268   DeviceListCacheX::GetInstance()->UpdateDeviceList(display);
    269   TouchFactory::GetInstance()->UpdateDeviceList(display);
    270   DeviceDataManager::GetInstance()->UpdateDeviceList(display);
    271 }
    272 
    273 EventType EventTypeFromNative(const base::NativeEvent& native_event) {
    274   switch (native_event->type) {
    275     case KeyPress:
    276       return ET_KEY_PRESSED;
    277     case KeyRelease:
    278       return ET_KEY_RELEASED;
    279     case ButtonPress:
    280       if (static_cast<int>(native_event->xbutton.button) >= kMinWheelButton &&
    281           static_cast<int>(native_event->xbutton.button) <= kMaxWheelButton)
    282         return ET_MOUSEWHEEL;
    283       return ET_MOUSE_PRESSED;
    284     case ButtonRelease:
    285       // Drop wheel events; we should've already scrolled on the press.
    286       if (static_cast<int>(native_event->xbutton.button) >= kMinWheelButton &&
    287           static_cast<int>(native_event->xbutton.button) <= kMaxWheelButton)
    288         return ET_UNKNOWN;
    289       return ET_MOUSE_RELEASED;
    290     case MotionNotify:
    291       if (native_event->xmotion.state &
    292           (Button1Mask | Button2Mask | Button3Mask))
    293         return ET_MOUSE_DRAGGED;
    294       return ET_MOUSE_MOVED;
    295     case EnterNotify:
    296       // The standard on Windows is to send a MouseMove event when the mouse
    297       // first enters a window instead of sending a special mouse enter event.
    298       // To be consistent we follow the same style.
    299       return ET_MOUSE_MOVED;
    300     case LeaveNotify:
    301       return ET_MOUSE_EXITED;
    302     case GenericEvent: {
    303       TouchFactory* factory = TouchFactory::GetInstance();
    304       if (!factory->ShouldProcessXI2Event(native_event))
    305         return ET_UNKNOWN;
    306 
    307       XIDeviceEvent* xievent =
    308           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    309 
    310       // This check works only for master and floating slave devices. That is
    311       // why it is necessary to check for the XI_Touch* events in the following
    312       // switch statement to account for attached-slave touchscreens.
    313       if (factory->IsTouchDevice(xievent->sourceid))
    314         return GetTouchEventType(native_event);
    315 
    316       switch (xievent->evtype) {
    317         case XI_TouchBegin:
    318           return ui::ET_TOUCH_PRESSED;
    319         case XI_TouchUpdate:
    320           return ui::ET_TOUCH_MOVED;
    321         case XI_TouchEnd:
    322           return ui::ET_TOUCH_RELEASED;
    323         case XI_ButtonPress: {
    324           int button = EventButtonFromNative(native_event);
    325           if (button >= kMinWheelButton && button <= kMaxWheelButton)
    326             return ET_MOUSEWHEEL;
    327           return ET_MOUSE_PRESSED;
    328         }
    329         case XI_ButtonRelease: {
    330           int button = EventButtonFromNative(native_event);
    331           // Drop wheel events; we should've already scrolled on the press.
    332           if (button >= kMinWheelButton && button <= kMaxWheelButton)
    333             return ET_UNKNOWN;
    334           return ET_MOUSE_RELEASED;
    335         }
    336         case XI_Motion: {
    337           bool is_cancel;
    338           if (GetFlingData(native_event, NULL, NULL, NULL, NULL, &is_cancel)) {
    339             return is_cancel ? ET_SCROLL_FLING_CANCEL : ET_SCROLL_FLING_START;
    340           } else if (DeviceDataManager::GetInstance()->IsScrollEvent(
    341               native_event)) {
    342             return IsTouchpadEvent(native_event) ? ET_SCROLL : ET_MOUSEWHEEL;
    343           } else if (DeviceDataManager::GetInstance()->IsCMTMetricsEvent(
    344               native_event)) {
    345             return ET_UMA_DATA;
    346           } else if (GetButtonMaskForX2Event(xievent)) {
    347             return ET_MOUSE_DRAGGED;
    348           } else {
    349             return ET_MOUSE_MOVED;
    350           }
    351         }
    352       }
    353     }
    354     default:
    355       break;
    356   }
    357   return ET_UNKNOWN;
    358 }
    359 
    360 int EventFlagsFromNative(const base::NativeEvent& native_event) {
    361   switch (native_event->type) {
    362     case KeyPress:
    363     case KeyRelease: {
    364       XModifierStateWatcher::GetInstance()->UpdateStateFromEvent(native_event);
    365       return GetEventFlagsFromXKeyEvent(native_event);
    366     }
    367     case ButtonPress:
    368     case ButtonRelease: {
    369       int flags = GetEventFlagsFromXState(native_event->xbutton.state);
    370       const EventType type = EventTypeFromNative(native_event);
    371       if (type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED)
    372         flags |= GetEventFlagsForButton(native_event->xbutton.button);
    373       return flags;
    374     }
    375     case EnterNotify:
    376     case LeaveNotify:
    377       return GetEventFlagsFromXState(native_event->xcrossing.state);
    378     case MotionNotify:
    379       return GetEventFlagsFromXState(native_event->xmotion.state);
    380     case GenericEvent: {
    381       XIDeviceEvent* xievent =
    382           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    383 
    384       switch (xievent->evtype) {
    385 #if defined(USE_XI2_MT)
    386         case XI_TouchBegin:
    387         case XI_TouchUpdate:
    388         case XI_TouchEnd:
    389           return GetButtonMaskForX2Event(xievent) |
    390                  GetEventFlagsFromXState(xievent->mods.effective) |
    391                  GetEventFlagsFromXState(
    392                      XModifierStateWatcher::GetInstance()->state());
    393           break;
    394 #endif
    395         case XI_ButtonPress:
    396         case XI_ButtonRelease: {
    397           const bool touch =
    398               TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid);
    399           int flags = GetButtonMaskForX2Event(xievent) |
    400               GetEventFlagsFromXState(xievent->mods.effective);
    401           if (touch) {
    402             flags |= GetEventFlagsFromXState(
    403                 XModifierStateWatcher::GetInstance()->state());
    404           }
    405 
    406           const EventType type = EventTypeFromNative(native_event);
    407           int button = EventButtonFromNative(native_event);
    408           if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch)
    409             flags |= GetEventFlagsForButton(button);
    410           return flags;
    411         }
    412         case XI_Motion:
    413            return GetButtonMaskForX2Event(xievent) |
    414                   GetEventFlagsFromXState(xievent->mods.effective);
    415       }
    416     }
    417   }
    418   return 0;
    419 }
    420 
    421 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) {
    422   switch(native_event->type) {
    423     case KeyPress:
    424     case KeyRelease:
    425       return base::TimeDelta::FromMilliseconds(native_event->xkey.time);
    426     case ButtonPress:
    427     case ButtonRelease:
    428       return base::TimeDelta::FromMilliseconds(native_event->xbutton.time);
    429       break;
    430     case MotionNotify:
    431       return base::TimeDelta::FromMilliseconds(native_event->xmotion.time);
    432       break;
    433     case EnterNotify:
    434     case LeaveNotify:
    435       return base::TimeDelta::FromMilliseconds(native_event->xcrossing.time);
    436       break;
    437     case GenericEvent: {
    438       double start, end;
    439       double touch_timestamp;
    440       if (GetGestureTimes(native_event, &start, &end)) {
    441         // If the driver supports gesture times, use them.
    442         return base::TimeDelta::FromMicroseconds(end * 1000000);
    443       } else if (DeviceDataManager::GetInstance()->GetEventData(*native_event,
    444                  DeviceDataManager::DT_TOUCH_RAW_TIMESTAMP, &touch_timestamp)) {
    445         return base::TimeDelta::FromMicroseconds(touch_timestamp * 1000000);
    446       } else {
    447         XIDeviceEvent* xide =
    448             static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    449         return base::TimeDelta::FromMilliseconds(xide->time);
    450       }
    451       break;
    452     }
    453   }
    454   NOTREACHED();
    455   return base::TimeDelta();
    456 }
    457 
    458 gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) {
    459   switch (native_event->type) {
    460     case EnterNotify:
    461     case LeaveNotify:
    462       return gfx::Point(native_event->xcrossing.x, native_event->xcrossing.y);
    463     case ButtonPress:
    464     case ButtonRelease:
    465       return gfx::Point(native_event->xbutton.x, native_event->xbutton.y);
    466     case MotionNotify:
    467       return gfx::Point(native_event->xmotion.x, native_event->xmotion.y);
    468     case GenericEvent: {
    469       XIDeviceEvent* xievent =
    470           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    471       float x = xievent->event_x;
    472       float y = xievent->event_y;
    473 #if defined(OS_CHROMEOS)
    474       switch (xievent->evtype) {
    475         case XI_TouchBegin:
    476         case XI_TouchUpdate:
    477         case XI_TouchEnd:
    478           ui::DeviceDataManager::GetInstance()->ApplyTouchTransformer(
    479               xievent->deviceid, &x, &y);
    480           break;
    481         default:
    482           break;
    483       }
    484 #endif  // defined(OS_CHROMEOS)
    485       return gfx::Point(static_cast<int>(x), static_cast<int>(y));
    486     }
    487   }
    488   return gfx::Point();
    489 }
    490 
    491 gfx::Point EventSystemLocationFromNative(
    492     const base::NativeEvent& native_event) {
    493   switch (native_event->type) {
    494     case EnterNotify:
    495     case LeaveNotify: {
    496       return gfx::Point(native_event->xcrossing.x_root,
    497                         native_event->xcrossing.y_root);
    498     }
    499     case ButtonPress:
    500     case ButtonRelease: {
    501       return gfx::Point(native_event->xbutton.x_root,
    502                         native_event->xbutton.y_root);
    503     }
    504     case MotionNotify: {
    505       return gfx::Point(native_event->xmotion.x_root,
    506                         native_event->xmotion.y_root);
    507     }
    508     case GenericEvent: {
    509       XIDeviceEvent* xievent =
    510           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    511       return gfx::Point(xievent->root_x, xievent->root_y);
    512     }
    513   }
    514 
    515   return gfx::Point();
    516 }
    517 
    518 int EventButtonFromNative(const base::NativeEvent& native_event) {
    519   CHECK_EQ(GenericEvent, native_event->type);
    520   XIDeviceEvent* xievent =
    521       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    522   int button = xievent->detail;
    523 
    524   return (xievent->sourceid == xievent->deviceid) ?
    525          DeviceDataManager::GetInstance()->GetMappedButton(button) : button;
    526 }
    527 
    528 KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
    529   return KeyboardCodeFromXKeyEvent(native_event);
    530 }
    531 
    532 const char* CodeFromNative(const base::NativeEvent& native_event) {
    533   return CodeFromXEvent(native_event);
    534 }
    535 
    536 uint32 PlatformKeycodeFromNative(const base::NativeEvent& native_event) {
    537   KeySym keysym;
    538   XLookupString(&native_event->xkey, NULL, 0, &keysym, NULL);
    539   return keysym;
    540 }
    541 
    542 int GetChangedMouseButtonFlagsFromNative(
    543     const base::NativeEvent& native_event) {
    544   switch (native_event->type) {
    545     case ButtonPress:
    546     case ButtonRelease:
    547       return GetEventFlagsFromXState(native_event->xbutton.state);
    548     case GenericEvent: {
    549       XIDeviceEvent* xievent =
    550           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    551       switch (xievent->evtype) {
    552         case XI_ButtonPress:
    553         case XI_ButtonRelease:
    554           return GetEventFlagsForButton(EventButtonFromNative(native_event));
    555         default:
    556           break;
    557       }
    558     }
    559     default:
    560       break;
    561   }
    562   return 0;
    563 }
    564 
    565 gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
    566   float x_offset, y_offset;
    567   if (GetScrollOffsets(
    568       native_event, &x_offset, &y_offset, NULL, NULL, NULL)) {
    569     return gfx::Vector2d(static_cast<int>(x_offset),
    570                          static_cast<int>(y_offset));
    571   }
    572 
    573   int button = native_event->type == GenericEvent ?
    574       EventButtonFromNative(native_event) : native_event->xbutton.button;
    575 
    576   switch (button) {
    577     case 4:
    578       return gfx::Vector2d(0, kWheelScrollAmount);
    579     case 5:
    580       return gfx::Vector2d(0, -kWheelScrollAmount);
    581     case 6:
    582       return gfx::Vector2d(kWheelScrollAmount, 0);
    583     case 7:
    584       return gfx::Vector2d(-kWheelScrollAmount, 0);
    585     default:
    586       return gfx::Vector2d();
    587   }
    588 }
    589 
    590 base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
    591   if (!event || event->type == GenericEvent)
    592     return NULL;
    593   XEvent* copy = new XEvent;
    594   *copy = *event;
    595   return copy;
    596 }
    597 
    598 void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
    599   delete event;
    600 }
    601 
    602 void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
    603   ui::EventType type = ui::EventTypeFromNative(xev);
    604   if (type == ui::ET_TOUCH_CANCELLED ||
    605       type == ui::ET_TOUCH_RELEASED) {
    606     ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
    607     ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
    608     double tracking_id;
    609     if (manager->GetEventData(
    610         *xev, ui::DeviceDataManager::DT_TOUCH_TRACKING_ID, &tracking_id)) {
    611       factory->ReleaseSlotForTrackingID(tracking_id);
    612     }
    613   }
    614 }
    615 
    616 int GetTouchId(const base::NativeEvent& xev) {
    617   double slot = 0;
    618   ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
    619   double tracking_id;
    620   if (!manager->GetEventData(
    621       *xev, ui::DeviceDataManager::DT_TOUCH_TRACKING_ID, &tracking_id)) {
    622     LOG(ERROR) << "Could not get the tracking ID for the event. Using 0.";
    623   } else {
    624     ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
    625     slot = factory->GetSlotForTrackingID(tracking_id);
    626   }
    627   return slot;
    628 }
    629 
    630 float GetTouchRadiusX(const base::NativeEvent& native_event) {
    631   return GetTouchParamFromXEvent(native_event,
    632       ui::DeviceDataManager::DT_TOUCH_MAJOR, 0.0) / 2.0;
    633 }
    634 
    635 float GetTouchRadiusY(const base::NativeEvent& native_event) {
    636   return GetTouchParamFromXEvent(native_event,
    637       ui::DeviceDataManager::DT_TOUCH_MINOR, 0.0) / 2.0;
    638 }
    639 
    640 float GetTouchAngle(const base::NativeEvent& native_event) {
    641   return GetTouchParamFromXEvent(native_event,
    642       ui::DeviceDataManager::DT_TOUCH_ORIENTATION, 0.0) / 2.0;
    643 }
    644 
    645 float GetTouchForce(const base::NativeEvent& native_event) {
    646   double force = 0.0;
    647   force = GetTouchParamFromXEvent(native_event,
    648       ui::DeviceDataManager::DT_TOUCH_PRESSURE, 0.0);
    649   unsigned int deviceid =
    650       static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
    651   // Force is normalized to fall into [0, 1]
    652   if (!ui::DeviceDataManager::GetInstance()->NormalizeData(
    653       deviceid, ui::DeviceDataManager::DT_TOUCH_PRESSURE, &force))
    654     force = 0.0;
    655   return force;
    656 }
    657 
    658 bool GetScrollOffsets(const base::NativeEvent& native_event,
    659                       float* x_offset,
    660                       float* y_offset,
    661                       float* x_offset_ordinal,
    662                       float* y_offset_ordinal,
    663                       int* finger_count) {
    664   if (!DeviceDataManager::GetInstance()->IsScrollEvent(native_event))
    665     return false;
    666 
    667   // Temp values to prevent passing NULLs to DeviceDataManager.
    668   float x_offset_, y_offset_;
    669   float x_offset_ordinal_, y_offset_ordinal_;
    670   int finger_count_;
    671   if (!x_offset)
    672     x_offset = &x_offset_;
    673   if (!y_offset)
    674     y_offset = &y_offset_;
    675   if (!x_offset_ordinal)
    676     x_offset_ordinal = &x_offset_ordinal_;
    677   if (!y_offset_ordinal)
    678     y_offset_ordinal = &y_offset_ordinal_;
    679   if (!finger_count)
    680     finger_count = &finger_count_;
    681 
    682   DeviceDataManager::GetInstance()->GetScrollOffsets(
    683       native_event,
    684       x_offset, y_offset,
    685       x_offset_ordinal, y_offset_ordinal,
    686       finger_count);
    687   return true;
    688 }
    689 
    690 bool GetFlingData(const base::NativeEvent& native_event,
    691                   float* vx,
    692                   float* vy,
    693                   float* vx_ordinal,
    694                   float* vy_ordinal,
    695                   bool* is_cancel) {
    696   if (!DeviceDataManager::GetInstance()->IsFlingEvent(native_event))
    697     return false;
    698 
    699   float vx_, vy_;
    700   float vx_ordinal_, vy_ordinal_;
    701   bool is_cancel_;
    702   if (!vx)
    703     vx = &vx_;
    704   if (!vy)
    705     vy = &vy_;
    706   if (!vx_ordinal)
    707     vx_ordinal = &vx_ordinal_;
    708   if (!vy_ordinal)
    709     vy_ordinal = &vy_ordinal_;
    710   if (!is_cancel)
    711     is_cancel = &is_cancel_;
    712 
    713   DeviceDataManager::GetInstance()->GetFlingData(
    714       native_event, vx, vy, vx_ordinal, vy_ordinal, is_cancel);
    715   return true;
    716 }
    717 
    718 bool GetGestureTimes(const base::NativeEvent& native_event,
    719                      double* start_time,
    720                      double* end_time) {
    721   if (!DeviceDataManager::GetInstance()->HasGestureTimes(native_event))
    722     return false;
    723 
    724   double start_time_, end_time_;
    725   if (!start_time)
    726     start_time = &start_time_;
    727   if (!end_time)
    728     end_time = &end_time_;
    729 
    730   DeviceDataManager::GetInstance()->GetGestureTimes(
    731       native_event, start_time, end_time);
    732   return true;
    733 }
    734 
    735 bool IsTouchpadEvent(const base::NativeEvent& event) {
    736   return DeviceDataManager::GetInstance()->IsTouchpadXInputEvent(event);
    737 }
    738 
    739 }  // namespace ui
    740