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