Home | History | Annotate | Download | only in x
      1 // Copyright 2013 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/x/device_data_manager.h"
      6 
      7 #include <X11/extensions/XInput.h>
      8 #include <X11/extensions/XInput2.h>
      9 #include <X11/Xlib.h>
     10 
     11 #include "base/logging.h"
     12 #include "base/memory/singleton.h"
     13 #include "base/sys_info.h"
     14 #include "ui/events/event_constants.h"
     15 #include "ui/events/event_switches.h"
     16 #include "ui/events/x/device_list_cache_x.h"
     17 #include "ui/events/x/touch_factory_x11.h"
     18 #include "ui/gfx/display.h"
     19 #include "ui/gfx/point3_f.h"
     20 #include "ui/gfx/x/x11_types.h"
     21 
     22 // XIScrollClass was introduced in XI 2.1 so we need to define it here
     23 // for backward-compatibility with older versions of XInput.
     24 #if !defined(XIScrollClass)
     25 #define XIScrollClass 3
     26 #endif
     27 
     28 // Multi-touch support was introduced in XI 2.2. Add XI event types here
     29 // for backward-compatibility with older versions of XInput.
     30 #if !defined(XI_TouchBegin)
     31 #define XI_TouchBegin  18
     32 #define XI_TouchUpdate 19
     33 #define XI_TouchEnd    20
     34 #endif
     35 
     36 // Copied from xserver-properties.h
     37 #define AXIS_LABEL_PROP_REL_HWHEEL "Rel Horiz Wheel"
     38 #define AXIS_LABEL_PROP_REL_WHEEL "Rel Vert Wheel"
     39 
     40 // CMT specific timings
     41 #define AXIS_LABEL_PROP_ABS_DBL_START_TIME "Abs Dbl Start Timestamp"
     42 #define AXIS_LABEL_PROP_ABS_DBL_END_TIME   "Abs Dbl End Timestamp"
     43 
     44 // Ordinal values
     45 #define AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X   "Abs Dbl Ordinal X"
     46 #define AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y   "Abs Dbl Ordinal Y"
     47 
     48 // Fling properties
     49 #define AXIS_LABEL_PROP_ABS_DBL_FLING_VX   "Abs Dbl Fling X Velocity"
     50 #define AXIS_LABEL_PROP_ABS_DBL_FLING_VY   "Abs Dbl Fling Y Velocity"
     51 #define AXIS_LABEL_PROP_ABS_FLING_STATE   "Abs Fling State"
     52 
     53 #define AXIS_LABEL_PROP_ABS_FINGER_COUNT   "Abs Finger Count"
     54 
     55 // Cros metrics gesture from touchpad
     56 #define AXIS_LABEL_PROP_ABS_METRICS_TYPE      "Abs Metrics Type"
     57 #define AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA1 "Abs Dbl Metrics Data 1"
     58 #define AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA2 "Abs Dbl Metrics Data 2"
     59 
     60 // Touchscreen multi-touch
     61 #define AXIS_LABEL_ABS_MT_TOUCH_MAJOR "Abs MT Touch Major"
     62 #define AXIS_LABEL_ABS_MT_TOUCH_MINOR "Abs MT Touch Minor"
     63 #define AXIS_LABEL_ABS_MT_ORIENTATION "Abs MT Orientation"
     64 #define AXIS_LABEL_ABS_MT_PRESSURE    "Abs MT Pressure"
     65 #define AXIS_LABEL_ABS_MT_TRACKING_ID "Abs MT Tracking ID"
     66 #define AXIS_LABEL_TOUCH_TIMESTAMP    "Touch Timestamp"
     67 
     68 // When you add new data types, please make sure the order here is aligned
     69 // with the order in the DataType enum in the header file because we assume
     70 // they are in sync when updating the device list (see UpdateDeviceList).
     71 const char* kCachedAtoms[] = {
     72   AXIS_LABEL_PROP_REL_HWHEEL,
     73   AXIS_LABEL_PROP_REL_WHEEL,
     74   AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X,
     75   AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y,
     76   AXIS_LABEL_PROP_ABS_DBL_START_TIME,
     77   AXIS_LABEL_PROP_ABS_DBL_END_TIME,
     78   AXIS_LABEL_PROP_ABS_DBL_FLING_VX,
     79   AXIS_LABEL_PROP_ABS_DBL_FLING_VY,
     80   AXIS_LABEL_PROP_ABS_FLING_STATE,
     81   AXIS_LABEL_PROP_ABS_METRICS_TYPE,
     82   AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA1,
     83   AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA2,
     84   AXIS_LABEL_PROP_ABS_FINGER_COUNT,
     85   AXIS_LABEL_ABS_MT_TOUCH_MAJOR,
     86   AXIS_LABEL_ABS_MT_TOUCH_MINOR,
     87   AXIS_LABEL_ABS_MT_ORIENTATION,
     88   AXIS_LABEL_ABS_MT_PRESSURE,
     89   AXIS_LABEL_ABS_MT_TRACKING_ID,
     90   AXIS_LABEL_TOUCH_TIMESTAMP,
     91 
     92   NULL
     93 };
     94 
     95 // Constants for checking if a data type lies in the range of CMT/Touch data
     96 // types.
     97 const int kCMTDataTypeStart = ui::DeviceDataManager::DT_CMT_SCROLL_X;
     98 const int kCMTDataTypeEnd = ui::DeviceDataManager::DT_CMT_FINGER_COUNT;
     99 const int kTouchDataTypeStart = ui::DeviceDataManager::DT_TOUCH_MAJOR;
    100 const int kTouchDataTypeEnd = ui::DeviceDataManager::DT_TOUCH_RAW_TIMESTAMP;
    101 
    102 namespace ui {
    103 
    104 bool DeviceDataManager::IsCMTDataType(const int type) {
    105   return (type >= kCMTDataTypeStart) && (type <= kCMTDataTypeEnd);
    106 }
    107 
    108 bool DeviceDataManager::IsTouchDataType(const int type) {
    109   return (type >= kTouchDataTypeStart) && (type <= kTouchDataTypeEnd);
    110 }
    111 
    112 DeviceDataManager* DeviceDataManager::GetInstance() {
    113   return Singleton<DeviceDataManager>::get();
    114 }
    115 
    116 DeviceDataManager::DeviceDataManager()
    117     : xi_opcode_(-1),
    118       atom_cache_(gfx::GetXDisplay(), kCachedAtoms),
    119       button_map_count_(0) {
    120   CHECK(gfx::GetXDisplay());
    121   InitializeXInputInternal();
    122 
    123   // Make sure the sizes of enum and kCachedAtoms are aligned.
    124   CHECK(arraysize(kCachedAtoms) == static_cast<size_t>(DT_LAST_ENTRY) + 1);
    125   UpdateDeviceList(gfx::GetXDisplay());
    126   UpdateButtonMap();
    127   for (int i = 0; i < kMaxDeviceNum; i++)
    128     touch_device_to_display_map_[i] = gfx::Display::kInvalidDisplayID;
    129 }
    130 
    131 DeviceDataManager::~DeviceDataManager() {
    132 }
    133 
    134 bool DeviceDataManager::InitializeXInputInternal() {
    135   // Check if XInput is available on the system.
    136   xi_opcode_ = -1;
    137   int opcode, event, error;
    138   if (!XQueryExtension(
    139       gfx::GetXDisplay(), "XInputExtension", &opcode, &event, &error)) {
    140     VLOG(1) << "X Input extension not available: error=" << error;
    141     return false;
    142   }
    143 
    144   // Check the XInput version.
    145 #if defined(USE_XI2_MT)
    146   int major = 2, minor = USE_XI2_MT;
    147 #else
    148   int major = 2, minor = 0;
    149 #endif
    150   if (XIQueryVersion(gfx::GetXDisplay(), &major, &minor) == BadRequest) {
    151     VLOG(1) << "XInput2 not supported in the server.";
    152     return false;
    153   }
    154 #if defined(USE_XI2_MT)
    155   if (major < 2 || (major == 2 && minor < USE_XI2_MT)) {
    156     DVLOG(1) << "XI version on server is " << major << "." << minor << ". "
    157             << "But 2." << USE_XI2_MT << " is required.";
    158     return false;
    159   }
    160 #endif
    161 
    162   xi_opcode_ = opcode;
    163   CHECK_NE(-1, xi_opcode_);
    164 
    165   // Possible XI event types for XIDeviceEvent. See the XI2 protocol
    166   // specification.
    167   xi_device_event_types_[XI_KeyPress] = true;
    168   xi_device_event_types_[XI_KeyRelease] = true;
    169   xi_device_event_types_[XI_ButtonPress] = true;
    170   xi_device_event_types_[XI_ButtonRelease] = true;
    171   xi_device_event_types_[XI_Motion] = true;
    172   // Multi-touch support was introduced in XI 2.2.
    173   if (minor >= 2) {
    174     xi_device_event_types_[XI_TouchBegin] = true;
    175     xi_device_event_types_[XI_TouchUpdate] = true;
    176     xi_device_event_types_[XI_TouchEnd] = true;
    177   }
    178   return true;
    179 }
    180 
    181 bool DeviceDataManager::IsXInput2Available() const {
    182   return xi_opcode_ != -1;
    183 }
    184 
    185 void DeviceDataManager::UpdateDeviceList(Display* display) {
    186   cmt_devices_.reset();
    187   touchpads_.reset();
    188   for (int i = 0; i < kMaxDeviceNum; ++i) {
    189     valuator_count_[i] = 0;
    190     valuator_lookup_[i].clear();
    191     data_type_lookup_[i].clear();
    192     valuator_min_[i].clear();
    193     valuator_max_[i].clear();
    194     for (int j = 0; j < kMaxSlotNum; j++)
    195       last_seen_valuator_[i][j].clear();
    196   }
    197 
    198   // Find all the touchpad devices.
    199   XDeviceList dev_list =
    200       ui::DeviceListCacheX::GetInstance()->GetXDeviceList(display);
    201   Atom xi_touchpad = XInternAtom(display, XI_TOUCHPAD, false);
    202   for (int i = 0; i < dev_list.count; ++i)
    203     if (dev_list[i].type == xi_touchpad)
    204       touchpads_[dev_list[i].id] = true;
    205 
    206   if (!IsXInput2Available())
    207     return;
    208 
    209   // Update the structs with new valuator information
    210   XIDeviceList info_list =
    211       ui::DeviceListCacheX::GetInstance()->GetXI2DeviceList(display);
    212   Atom atoms[DT_LAST_ENTRY];
    213   for (int data_type = 0; data_type < DT_LAST_ENTRY; ++data_type)
    214     atoms[data_type] = atom_cache_.GetAtom(kCachedAtoms[data_type]);
    215 
    216   for (int i = 0; i < info_list.count; ++i) {
    217     XIDeviceInfo* info = info_list.devices + i;
    218 
    219     // We currently handle only slave, non-keyboard devices
    220     if (info->use != XISlavePointer && info->use != XIFloatingSlave)
    221       continue;
    222 
    223     bool possible_cmt = false;
    224     bool not_cmt = false;
    225     const int deviceid = info->deviceid;
    226 
    227     for (int j = 0; j < info->num_classes; ++j) {
    228       if (info->classes[j]->type == XIValuatorClass)
    229         ++valuator_count_[deviceid];
    230       else if (info->classes[j]->type == XIScrollClass)
    231         not_cmt = true;
    232     }
    233 
    234     // Skip devices that don't use any valuator
    235     if (!valuator_count_[deviceid])
    236       continue;
    237 
    238     valuator_lookup_[deviceid].resize(DT_LAST_ENTRY, -1);
    239     data_type_lookup_[deviceid].resize(
    240         valuator_count_[deviceid], DT_LAST_ENTRY);
    241     valuator_min_[deviceid].resize(DT_LAST_ENTRY, 0);
    242     valuator_max_[deviceid].resize(DT_LAST_ENTRY, 0);
    243     for (int j = 0; j < kMaxSlotNum; j++)
    244       last_seen_valuator_[deviceid][j].resize(DT_LAST_ENTRY, 0);
    245     for (int j = 0; j < info->num_classes; ++j) {
    246       if (info->classes[j]->type != XIValuatorClass)
    247         continue;
    248 
    249       XIValuatorClassInfo* v =
    250           reinterpret_cast<XIValuatorClassInfo*>(info->classes[j]);
    251       for (int data_type = 0; data_type < DT_LAST_ENTRY; ++data_type) {
    252         if (v->label == atoms[data_type]) {
    253           valuator_lookup_[deviceid][data_type] = v->number;
    254           data_type_lookup_[deviceid][v->number] = data_type;
    255           valuator_min_[deviceid][data_type] = v->min;
    256           valuator_max_[deviceid][data_type] = v->max;
    257           if (IsCMTDataType(data_type))
    258             possible_cmt = true;
    259           break;
    260         }
    261       }
    262     }
    263 
    264     if (possible_cmt && !not_cmt)
    265       cmt_devices_[deviceid] = true;
    266   }
    267 }
    268 
    269 bool DeviceDataManager::GetSlotNumber(const XIDeviceEvent* xiev, int* slot) {
    270 #if defined(USE_XI2_MT)
    271   ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
    272   if (!factory->IsMultiTouchDevice(xiev->sourceid)) {
    273     *slot = 0;
    274     return true;
    275   }
    276   return factory->QuerySlotForTrackingID(xiev->detail, slot);
    277 #else
    278   *slot = 0;
    279   return true;
    280 #endif
    281 }
    282 
    283 void DeviceDataManager::GetEventRawData(const XEvent& xev, EventData* data) {
    284   if (xev.type != GenericEvent)
    285     return;
    286 
    287   XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
    288   if (xiev->sourceid >= kMaxDeviceNum || xiev->deviceid >= kMaxDeviceNum)
    289     return;
    290   data->clear();
    291   const int sourceid = xiev->sourceid;
    292   double* valuators = xiev->valuators.values;
    293   for (int i = 0; i <= valuator_count_[sourceid]; ++i) {
    294     if (XIMaskIsSet(xiev->valuators.mask, i)) {
    295       int type = data_type_lookup_[sourceid][i];
    296       if (type != DT_LAST_ENTRY) {
    297         (*data)[type] = *valuators;
    298         if (IsTouchDataType(type)) {
    299           int slot = -1;
    300           if (GetSlotNumber(xiev, &slot) && slot >= 0 && slot < kMaxSlotNum)
    301             last_seen_valuator_[sourceid][slot][type] = *valuators;
    302         }
    303       }
    304       valuators++;
    305     }
    306   }
    307 }
    308 
    309 bool DeviceDataManager::GetEventData(const XEvent& xev,
    310     const DataType type, double* value) {
    311   if (xev.type != GenericEvent)
    312     return false;
    313 
    314   XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
    315   if (xiev->sourceid >= kMaxDeviceNum || xiev->deviceid >= kMaxDeviceNum)
    316     return false;
    317   const int sourceid = xiev->sourceid;
    318   if (valuator_lookup_[sourceid].empty())
    319     return false;
    320 
    321   if (type == DT_TOUCH_TRACKING_ID) {
    322     // With XInput2 MT, Tracking ID is provided in the detail field for touch
    323     // events.
    324     if (xiev->evtype == XI_TouchBegin ||
    325         xiev->evtype == XI_TouchEnd ||
    326         xiev->evtype == XI_TouchUpdate) {
    327       *value = xiev->detail;
    328     } else {
    329       *value = 0;
    330     }
    331     return true;
    332   }
    333 
    334   int val_index = valuator_lookup_[sourceid][type];
    335   int slot = 0;
    336   if (val_index >= 0) {
    337     if (XIMaskIsSet(xiev->valuators.mask, val_index)) {
    338       double* valuators = xiev->valuators.values;
    339       while (val_index--) {
    340         if (XIMaskIsSet(xiev->valuators.mask, val_index))
    341           ++valuators;
    342       }
    343       *value = *valuators;
    344       if (IsTouchDataType(type)) {
    345         if (GetSlotNumber(xiev, &slot) && slot >= 0 && slot < kMaxSlotNum)
    346           last_seen_valuator_[sourceid][slot][type] = *value;
    347       }
    348       return true;
    349     } else if (IsTouchDataType(type)) {
    350       if (GetSlotNumber(xiev, &slot) && slot >= 0 && slot < kMaxSlotNum)
    351         *value = last_seen_valuator_[sourceid][slot][type];
    352     }
    353   }
    354 
    355   return false;
    356 }
    357 
    358 bool DeviceDataManager::IsXIDeviceEvent(
    359     const base::NativeEvent& native_event) const {
    360   if (native_event->type != GenericEvent ||
    361       native_event->xcookie.extension != xi_opcode_)
    362     return false;
    363   return xi_device_event_types_[native_event->xcookie.evtype];
    364 }
    365 
    366 bool DeviceDataManager::IsTouchpadXInputEvent(
    367     const base::NativeEvent& native_event) const {
    368   if (native_event->type != GenericEvent)
    369     return false;
    370 
    371   XIDeviceEvent* xievent =
    372       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    373   if (xievent->sourceid >= kMaxDeviceNum)
    374     return false;
    375   return touchpads_[xievent->sourceid];
    376 }
    377 
    378 bool DeviceDataManager::IsCMTDeviceEvent(
    379     const base::NativeEvent& native_event) const {
    380   if (native_event->type != GenericEvent)
    381     return false;
    382 
    383   XIDeviceEvent* xievent =
    384       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    385   if (xievent->sourceid >= kMaxDeviceNum)
    386     return false;
    387   return cmt_devices_[xievent->sourceid];
    388 }
    389 
    390 bool DeviceDataManager::IsCMTGestureEvent(
    391     const base::NativeEvent& native_event) const {
    392   return (IsScrollEvent(native_event) ||
    393           IsFlingEvent(native_event) ||
    394           IsCMTMetricsEvent(native_event));
    395 }
    396 
    397 bool DeviceDataManager::HasEventData(
    398     const XIDeviceEvent* xiev, const DataType type) const {
    399   const int idx = valuator_lookup_[xiev->sourceid][type];
    400   return (idx >= 0) && XIMaskIsSet(xiev->valuators.mask, idx);
    401 }
    402 
    403 bool DeviceDataManager::IsScrollEvent(
    404     const base::NativeEvent& native_event) const {
    405   if (!IsCMTDeviceEvent(native_event))
    406     return false;
    407 
    408   XIDeviceEvent* xiev =
    409       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    410   return (HasEventData(xiev, DT_CMT_SCROLL_X) ||
    411           HasEventData(xiev, DT_CMT_SCROLL_Y));
    412 }
    413 
    414 bool DeviceDataManager::IsFlingEvent(
    415     const base::NativeEvent& native_event) const {
    416   if (!IsCMTDeviceEvent(native_event))
    417     return false;
    418 
    419   XIDeviceEvent* xiev =
    420       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    421   return (HasEventData(xiev, DT_CMT_FLING_X) &&
    422           HasEventData(xiev, DT_CMT_FLING_Y) &&
    423           HasEventData(xiev, DT_CMT_FLING_STATE));
    424 }
    425 
    426 bool DeviceDataManager::IsCMTMetricsEvent(
    427     const base::NativeEvent& native_event) const {
    428   if (!IsCMTDeviceEvent(native_event))
    429     return false;
    430 
    431   XIDeviceEvent* xiev =
    432       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    433   return (HasEventData(xiev, DT_CMT_METRICS_TYPE) &&
    434           HasEventData(xiev, DT_CMT_METRICS_DATA1) &&
    435           HasEventData(xiev, DT_CMT_METRICS_DATA2));
    436 }
    437 
    438 bool DeviceDataManager::HasGestureTimes(
    439     const base::NativeEvent& native_event) const {
    440   if (!IsCMTDeviceEvent(native_event))
    441     return false;
    442 
    443   XIDeviceEvent* xiev =
    444       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    445   return (HasEventData(xiev, DT_CMT_START_TIME) &&
    446           HasEventData(xiev, DT_CMT_END_TIME));
    447 }
    448 
    449 void DeviceDataManager::GetScrollOffsets(const base::NativeEvent& native_event,
    450                                          float* x_offset, float* y_offset,
    451                                          float* x_offset_ordinal,
    452                                          float* y_offset_ordinal,
    453                                          int* finger_count) {
    454   *x_offset = 0;
    455   *y_offset = 0;
    456   *x_offset_ordinal = 0;
    457   *y_offset_ordinal = 0;
    458   *finger_count = 2;
    459 
    460   EventData data;
    461   GetEventRawData(*native_event, &data);
    462 
    463   if (data.find(DT_CMT_SCROLL_X) != data.end())
    464     *x_offset = data[DT_CMT_SCROLL_X];
    465   if (data.find(DT_CMT_SCROLL_Y) != data.end())
    466     *y_offset = data[DT_CMT_SCROLL_Y];
    467   if (data.find(DT_CMT_ORDINAL_X) != data.end())
    468     *x_offset_ordinal = data[DT_CMT_ORDINAL_X];
    469   if (data.find(DT_CMT_ORDINAL_Y) != data.end())
    470     *y_offset_ordinal = data[DT_CMT_ORDINAL_Y];
    471   if (data.find(DT_CMT_FINGER_COUNT) != data.end())
    472     *finger_count = static_cast<int>(data[DT_CMT_FINGER_COUNT]);
    473 }
    474 
    475 void DeviceDataManager::GetFlingData(const base::NativeEvent& native_event,
    476                                      float* vx, float* vy,
    477                                      float* vx_ordinal, float* vy_ordinal,
    478                                      bool* is_cancel) {
    479   *vx = 0;
    480   *vy = 0;
    481   *vx_ordinal = 0;
    482   *vy_ordinal = 0;
    483   *is_cancel = false;
    484 
    485   EventData data;
    486   GetEventRawData(*native_event, &data);
    487 
    488   if (data.find(DT_CMT_FLING_X) != data.end())
    489     *vx = data[DT_CMT_FLING_X];
    490   if (data.find(DT_CMT_FLING_Y) != data.end())
    491     *vy = data[DT_CMT_FLING_Y];
    492   if (data.find(DT_CMT_FLING_STATE) != data.end())
    493     *is_cancel = !!static_cast<unsigned int>(data[DT_CMT_FLING_STATE]);
    494   if (data.find(DT_CMT_ORDINAL_X) != data.end())
    495     *vx_ordinal = data[DT_CMT_ORDINAL_X];
    496   if (data.find(DT_CMT_ORDINAL_Y) != data.end())
    497     *vy_ordinal = data[DT_CMT_ORDINAL_Y];
    498 }
    499 
    500 void DeviceDataManager::GetMetricsData(const base::NativeEvent& native_event,
    501                                        GestureMetricsType* type,
    502                                        float* data1, float* data2) {
    503   *type = kGestureMetricsTypeUnknown;
    504   *data1 = 0;
    505   *data2 = 0;
    506 
    507   EventData data;
    508   GetEventRawData(*native_event, &data);
    509 
    510   if (data.find(DT_CMT_METRICS_TYPE) != data.end()) {
    511     int val = static_cast<int>(data[DT_CMT_METRICS_TYPE]);
    512     if (val == 0)
    513       *type = kGestureMetricsTypeNoisyGround;
    514     else
    515       *type = kGestureMetricsTypeUnknown;
    516   }
    517   if (data.find(DT_CMT_METRICS_DATA1) != data.end())
    518     *data1 = data[DT_CMT_METRICS_DATA1];
    519   if (data.find(DT_CMT_METRICS_DATA2) != data.end())
    520     *data2 = data[DT_CMT_METRICS_DATA2];
    521 }
    522 
    523 int DeviceDataManager::GetMappedButton(int button) {
    524   return button > 0 && button <= button_map_count_ ? button_map_[button - 1] :
    525                                                      button;
    526 }
    527 
    528 void DeviceDataManager::UpdateButtonMap() {
    529   button_map_count_ = XGetPointerMapping(gfx::GetXDisplay(),
    530                                          button_map_,
    531                                          arraysize(button_map_));
    532 }
    533 
    534 void DeviceDataManager::GetGestureTimes(const base::NativeEvent& native_event,
    535                                         double* start_time,
    536                                         double* end_time) {
    537   *start_time = 0;
    538   *end_time = 0;
    539 
    540   EventData data;
    541   GetEventRawData(*native_event, &data);
    542 
    543   if (data.find(DT_CMT_START_TIME) != data.end())
    544     *start_time = data[DT_CMT_START_TIME];
    545   if (data.find(DT_CMT_END_TIME) != data.end())
    546     *end_time = data[DT_CMT_END_TIME];
    547 }
    548 
    549 bool DeviceDataManager::NormalizeData(unsigned int deviceid,
    550                                       const DataType type,
    551                                       double* value) {
    552   double max_value;
    553   double min_value;
    554   if (GetDataRange(deviceid, type, &min_value, &max_value)) {
    555     *value = (*value - min_value) / (max_value - min_value);
    556     DCHECK(*value >= 0.0 && *value <= 1.0);
    557     return true;
    558   }
    559   return false;
    560 }
    561 
    562 bool DeviceDataManager::GetDataRange(unsigned int deviceid,
    563                                      const DataType type,
    564                                      double* min, double* max) {
    565   if (deviceid >= static_cast<unsigned int>(kMaxDeviceNum))
    566     return false;
    567   if (valuator_lookup_[deviceid][type] >= 0) {
    568     *min = valuator_min_[deviceid][type];
    569     *max = valuator_max_[deviceid][type];
    570     return true;
    571   }
    572   return false;
    573 }
    574 
    575 void DeviceDataManager::SetDeviceListForTest(
    576     const std::vector<unsigned int>& touchscreen,
    577     const std::vector<unsigned int>& cmt_devices) {
    578   for (int i = 0; i < kMaxDeviceNum; ++i) {
    579     valuator_count_[i] = 0;
    580     valuator_lookup_[i].clear();
    581     data_type_lookup_[i].clear();
    582     valuator_min_[i].clear();
    583     valuator_max_[i].clear();
    584     for (int j = 0; j < kMaxSlotNum; j++)
    585       last_seen_valuator_[i][j].clear();
    586   }
    587 
    588   for (size_t i = 0; i < touchscreen.size(); i++) {
    589     unsigned int deviceid = touchscreen[i];
    590     InitializeValuatorsForTest(deviceid, kTouchDataTypeStart, kTouchDataTypeEnd,
    591                                0, 1000);
    592   }
    593 
    594   cmt_devices_.reset();
    595   for (size_t i = 0; i < cmt_devices.size(); ++i) {
    596     unsigned int deviceid = cmt_devices[i];
    597     cmt_devices_[deviceid] = true;
    598     touchpads_[deviceid] = true;
    599     InitializeValuatorsForTest(deviceid, kCMTDataTypeStart, kCMTDataTypeEnd,
    600                                -1000, 1000);
    601   }
    602 }
    603 
    604 void DeviceDataManager::SetValuatorDataForTest(XIDeviceEvent* xievent,
    605                                                DataType type,
    606                                                double value) {
    607   int index = valuator_lookup_[xievent->deviceid][type];
    608   CHECK(!XIMaskIsSet(xievent->valuators.mask, index));
    609   CHECK(index >= 0 && index < valuator_count_[xievent->deviceid]);
    610   XISetMask(xievent->valuators.mask, index);
    611 
    612   double* valuators = xievent->valuators.values;
    613   for (int i = 0; i < index; ++i) {
    614     if (XIMaskIsSet(xievent->valuators.mask, i))
    615       valuators++;
    616   }
    617   for (int i = DT_LAST_ENTRY - 1; i > valuators - xievent->valuators.values;
    618        --i)
    619     xievent->valuators.values[i] = xievent->valuators.values[i - 1];
    620   *valuators = value;
    621 }
    622 
    623 void DeviceDataManager::InitializeValuatorsForTest(int deviceid,
    624                                                    int start_valuator,
    625                                                    int end_valuator,
    626                                                    double min_value,
    627                                                    double max_value) {
    628   valuator_lookup_[deviceid].resize(DT_LAST_ENTRY, -1);
    629   data_type_lookup_[deviceid].resize(DT_LAST_ENTRY, DT_LAST_ENTRY);
    630   valuator_min_[deviceid].resize(DT_LAST_ENTRY, 0);
    631   valuator_max_[deviceid].resize(DT_LAST_ENTRY, 0);
    632   for (int j = 0; j < kMaxSlotNum; j++)
    633     last_seen_valuator_[deviceid][j].resize(DT_LAST_ENTRY, 0);
    634   for (int j = start_valuator; j <= end_valuator; ++j) {
    635     valuator_lookup_[deviceid][j] = valuator_count_[deviceid];
    636     data_type_lookup_[deviceid][valuator_count_[deviceid]] = j;
    637     valuator_min_[deviceid][j] = min_value;
    638     valuator_max_[deviceid][j] = max_value;
    639     valuator_count_[deviceid]++;
    640   }
    641 }
    642 
    643 bool DeviceDataManager::TouchEventNeedsCalibrate(int touch_device_id) const {
    644 #if defined(OS_CHROMEOS) && defined(USE_XI2_MT)
    645   int64 touch_display_id = GetDisplayForTouchDevice(touch_device_id);
    646   if (base::SysInfo::IsRunningOnChromeOS() &&
    647       touch_display_id == gfx::Display::InternalDisplayId()) {
    648     return true;
    649   }
    650 #endif  // defined(OS_CHROMEOS) && defined(USE_XI2_MT)
    651   return false;
    652 }
    653 
    654 void DeviceDataManager::ClearTouchTransformerRecord() {
    655   for (int i = 0; i < kMaxDeviceNum; i++) {
    656     touch_device_transformer_map_[i] = gfx::Transform();
    657     touch_device_to_display_map_[i] = gfx::Display::kInvalidDisplayID;
    658   }
    659 }
    660 
    661 bool DeviceDataManager::IsTouchDeviceIdValid(int touch_device_id) const {
    662   return (touch_device_id > 0 && touch_device_id < kMaxDeviceNum);
    663 }
    664 
    665 void DeviceDataManager::UpdateTouchInfoForDisplay(
    666     int64 display_id,
    667     int touch_device_id,
    668     const gfx::Transform& touch_transformer) {
    669   if (IsTouchDeviceIdValid(touch_device_id)) {
    670     touch_device_to_display_map_[touch_device_id] = display_id;
    671     touch_device_transformer_map_[touch_device_id] = touch_transformer;
    672   }
    673 }
    674 
    675 void DeviceDataManager::ApplyTouchTransformer(int touch_device_id,
    676                                               float* x, float* y) {
    677   if (IsTouchDeviceIdValid(touch_device_id)) {
    678     gfx::Point3F point(*x, *y, 0.0);
    679     const gfx::Transform& trans =
    680         touch_device_transformer_map_[touch_device_id];
    681     trans.TransformPoint(&point);
    682     *x = point.x();
    683     *y = point.y();
    684   }
    685 }
    686 
    687 int64 DeviceDataManager::GetDisplayForTouchDevice(int touch_device_id) const {
    688   if (IsTouchDeviceIdValid(touch_device_id))
    689     return touch_device_to_display_map_[touch_device_id];
    690   return gfx::Display::kInvalidDisplayID;
    691 }
    692 
    693 }  // namespace ui
    694