// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/events/devices/x11/device_data_manager_x11.h"

#include <stddef.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>
#include <X11/Xlib.h>

#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/sys_info.h"
#include "build/build_config.h"
#include "ui/display/display.h"
#include "ui/events/devices/x11/device_list_cache_x11.h"
#include "ui/events/devices/x11/touch_factory_x11.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_switches.h"
#include "ui/events/keycodes/keyboard_code_conversion_x.h"
#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/x/x11_types.h"

// XIScrollClass was introduced in XI 2.1 so we need to define it here
// for backward-compatibility with older versions of XInput.
#if !defined(XIScrollClass)
#define XIScrollClass 3
#endif

// Multi-touch support was introduced in XI 2.2. Add XI event types here
// for backward-compatibility with older versions of XInput.
#if !defined(XI_TouchBegin)
#define XI_TouchBegin  18
#define XI_TouchUpdate 19
#define XI_TouchEnd    20
#endif

// Copied from xserver-properties.h
#define AXIS_LABEL_PROP_REL_HWHEEL "Rel Horiz Wheel"
#define AXIS_LABEL_PROP_REL_WHEEL "Rel Vert Wheel"

// CMT specific timings
#define AXIS_LABEL_PROP_ABS_DBL_START_TIME "Abs Dbl Start Timestamp"
#define AXIS_LABEL_PROP_ABS_DBL_END_TIME   "Abs Dbl End Timestamp"

// Ordinal values
#define AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X   "Abs Dbl Ordinal X"
#define AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y   "Abs Dbl Ordinal Y"

// Fling properties
#define AXIS_LABEL_PROP_ABS_DBL_FLING_VX   "Abs Dbl Fling X Velocity"
#define AXIS_LABEL_PROP_ABS_DBL_FLING_VY   "Abs Dbl Fling Y Velocity"
#define AXIS_LABEL_PROP_ABS_FLING_STATE   "Abs Fling State"

#define AXIS_LABEL_PROP_ABS_FINGER_COUNT   "Abs Finger Count"

// Cros metrics gesture from touchpad
#define AXIS_LABEL_PROP_ABS_METRICS_TYPE      "Abs Metrics Type"
#define AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA1 "Abs Dbl Metrics Data 1"
#define AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA2 "Abs Dbl Metrics Data 2"

// Touchscreen multi-touch
#define AXIS_LABEL_ABS_MT_TOUCH_MAJOR "Abs MT Touch Major"
#define AXIS_LABEL_ABS_MT_TOUCH_MINOR "Abs MT Touch Minor"
#define AXIS_LABEL_ABS_MT_ORIENTATION "Abs MT Orientation"
#define AXIS_LABEL_ABS_MT_PRESSURE    "Abs MT Pressure"
#define AXIS_LABEL_ABS_MT_POSITION_X  "Abs MT Position X"
#define AXIS_LABEL_ABS_MT_POSITION_Y  "Abs MT Position Y"
#define AXIS_LABEL_ABS_MT_TRACKING_ID "Abs MT Tracking ID"
#define AXIS_LABEL_TOUCH_TIMESTAMP    "Touch Timestamp"

// When you add new data types, please make sure the order here is aligned
// with the order in the DataType enum in the header file because we assume
// they are in sync when updating the device list (see UpdateDeviceList).
const char* kCachedAtoms[] = {
  AXIS_LABEL_PROP_REL_HWHEEL,
  AXIS_LABEL_PROP_REL_WHEEL,
  AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X,
  AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y,
  AXIS_LABEL_PROP_ABS_DBL_START_TIME,
  AXIS_LABEL_PROP_ABS_DBL_END_TIME,
  AXIS_LABEL_PROP_ABS_DBL_FLING_VX,
  AXIS_LABEL_PROP_ABS_DBL_FLING_VY,
  AXIS_LABEL_PROP_ABS_FLING_STATE,
  AXIS_LABEL_PROP_ABS_METRICS_TYPE,
  AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA1,
  AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA2,
  AXIS_LABEL_PROP_ABS_FINGER_COUNT,
  AXIS_LABEL_ABS_MT_TOUCH_MAJOR,
  AXIS_LABEL_ABS_MT_TOUCH_MINOR,
  AXIS_LABEL_ABS_MT_ORIENTATION,
  AXIS_LABEL_ABS_MT_PRESSURE,
  AXIS_LABEL_ABS_MT_POSITION_X,
  AXIS_LABEL_ABS_MT_POSITION_Y,
  AXIS_LABEL_ABS_MT_TRACKING_ID,
  AXIS_LABEL_TOUCH_TIMESTAMP,

  NULL
};

// Constants for checking if a data type lies in the range of CMT/Touch data
// types.
const int kCMTDataTypeStart = ui::DeviceDataManagerX11::DT_CMT_SCROLL_X;
const int kCMTDataTypeEnd = ui::DeviceDataManagerX11::DT_CMT_FINGER_COUNT;
const int kTouchDataTypeStart = ui::DeviceDataManagerX11::DT_TOUCH_MAJOR;
const int kTouchDataTypeEnd = ui::DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP;

namespace ui {

namespace {

template <typename Iterator>
Iterator FindDeviceWithId(Iterator begin, Iterator end, int id) {
  for (auto it = begin; it != end; ++it) {
    if (it->id == id)
      return it;
  }
  return end;
}

}  // namespace

bool DeviceDataManagerX11::IsCMTDataType(const int type) {
  return (type >= kCMTDataTypeStart) && (type <= kCMTDataTypeEnd);
}

bool DeviceDataManagerX11::IsTouchDataType(const int type) {
  return (type >= kTouchDataTypeStart) && (type <= kTouchDataTypeEnd);
}

// static
void DeviceDataManagerX11::CreateInstance() {
  if (instance())
    return;

  DeviceDataManagerX11* device_data_manager = new DeviceDataManagerX11();

  // TODO(bruthig): Replace the DeleteInstance callbacks with explicit calls.
  base::AtExitManager::RegisterTask(
      base::Bind(DeviceDataManager::DeleteInstance));

  set_instance(device_data_manager);
}

// static
DeviceDataManagerX11* DeviceDataManagerX11::GetInstance() {
  return static_cast<DeviceDataManagerX11*>(DeviceDataManager::GetInstance());
}

DeviceDataManagerX11::DeviceDataManagerX11()
    : xi_opcode_(-1),
      atom_cache_(gfx::GetXDisplay(), kCachedAtoms),
      button_map_count_(0) {
  CHECK(gfx::GetXDisplay());
  InitializeXInputInternal();

  // Make sure the sizes of enum and kCachedAtoms are aligned.
  CHECK(arraysize(kCachedAtoms) == static_cast<size_t>(DT_LAST_ENTRY) + 1);
  UpdateDeviceList(gfx::GetXDisplay());
  UpdateButtonMap();
}

DeviceDataManagerX11::~DeviceDataManagerX11() {
}

bool DeviceDataManagerX11::InitializeXInputInternal() {
  // Check if XInput is available on the system.
  xi_opcode_ = -1;
  int opcode, event, error;
  if (!XQueryExtension(
      gfx::GetXDisplay(), "XInputExtension", &opcode, &event, &error)) {
    VLOG(1) << "X Input extension not available: error=" << error;
    return false;
  }

  // Check the XInput version.
  int major = 2, minor = 2;
  if (XIQueryVersion(gfx::GetXDisplay(), &major, &minor) == BadRequest) {
    VLOG(1) << "XInput2 not supported in the server.";
    return false;
  }
  if (major < 2 || (major == 2 && minor < 2)) {
    DVLOG(1) << "XI version on server is " << major << "." << minor << ". "
            << "But 2.2 is required.";
    return false;
  }

  xi_opcode_ = opcode;
  CHECK_NE(-1, xi_opcode_);

  // Possible XI event types for XIDeviceEvent. See the XI2 protocol
  // specification.
  xi_device_event_types_[XI_KeyPress] = true;
  xi_device_event_types_[XI_KeyRelease] = true;
  xi_device_event_types_[XI_ButtonPress] = true;
  xi_device_event_types_[XI_ButtonRelease] = true;
  xi_device_event_types_[XI_Motion] = true;
  // Multi-touch support was introduced in XI 2.2.
  if (minor >= 2) {
    xi_device_event_types_[XI_TouchBegin] = true;
    xi_device_event_types_[XI_TouchUpdate] = true;
    xi_device_event_types_[XI_TouchEnd] = true;
  }
  return true;
}

bool DeviceDataManagerX11::IsXInput2Available() const {
  return xi_opcode_ != -1;
}

void DeviceDataManagerX11::UpdateDeviceList(Display* display) {
  cmt_devices_.reset();
  touchpads_.reset();
  master_pointers_.clear();
  for (int i = 0; i < kMaxDeviceNum; ++i) {
    valuator_count_[i] = 0;
    valuator_lookup_[i].clear();
    data_type_lookup_[i].clear();
    valuator_min_[i].clear();
    valuator_max_[i].clear();
    scroll_data_[i].horizontal.number = -1;
    scroll_data_[i].horizontal.seen = false;
    scroll_data_[i].vertical.number = -1;
    scroll_data_[i].vertical.seen = false;
    for (int j = 0; j < kMaxSlotNum; j++)
      last_seen_valuator_[i][j].clear();
  }

  // Find all the touchpad devices.
  const XDeviceList& dev_list =
      ui::DeviceListCacheX11::GetInstance()->GetXDeviceList(display);
  Atom xi_touchpad = XInternAtom(display, XI_TOUCHPAD, false);
  for (int i = 0; i < dev_list.count; ++i)
    if (dev_list[i].type == xi_touchpad)
      touchpads_[dev_list[i].id] = true;

  if (!IsXInput2Available())
    return;

  // Update the structs with new valuator information
  const XIDeviceList& info_list =
      ui::DeviceListCacheX11::GetInstance()->GetXI2DeviceList(display);
  Atom atoms[DT_LAST_ENTRY];
  for (int data_type = 0; data_type < DT_LAST_ENTRY; ++data_type)
    atoms[data_type] = atom_cache_.GetAtom(kCachedAtoms[data_type]);

  for (int i = 0; i < info_list.count; ++i) {
    const XIDeviceInfo& info = info_list[i];

    if (info.use == XIMasterPointer)
      master_pointers_.push_back(info.deviceid);

    // We currently handle only slave, non-keyboard devices
    if (info.use != XISlavePointer && info.use != XIFloatingSlave)
      continue;

    bool possible_cmt = false;
    bool not_cmt = false;
    const int deviceid = info.deviceid;

    for (int j = 0; j < info.num_classes; ++j) {
      if (info.classes[j]->type == XIValuatorClass)
        ++valuator_count_[deviceid];
      else if (info.classes[j]->type == XIScrollClass)
        not_cmt = true;
    }

    // Skip devices that don't use any valuator
    if (!valuator_count_[deviceid])
      continue;

    valuator_lookup_[deviceid].resize(DT_LAST_ENTRY, -1);
    data_type_lookup_[deviceid].resize(
        valuator_count_[deviceid], DT_LAST_ENTRY);
    valuator_min_[deviceid].resize(DT_LAST_ENTRY, 0);
    valuator_max_[deviceid].resize(DT_LAST_ENTRY, 0);
    for (int j = 0; j < kMaxSlotNum; j++)
      last_seen_valuator_[deviceid][j].resize(DT_LAST_ENTRY, 0);
    for (int j = 0; j < info.num_classes; ++j) {
      if (info.classes[j]->type == XIValuatorClass) {
        if (UpdateValuatorClassDevice(
                reinterpret_cast<XIValuatorClassInfo*>(info.classes[j]), atoms,
                deviceid))
          possible_cmt = true;
      } else if (info.classes[j]->type == XIScrollClass) {
        UpdateScrollClassDevice(
            reinterpret_cast<XIScrollClassInfo*>(info.classes[j]), deviceid);
      }
    }

    if (possible_cmt && !not_cmt)
      cmt_devices_[deviceid] = true;
  }
}

bool DeviceDataManagerX11::GetSlotNumber(const XIDeviceEvent* xiev, int* slot) {
  ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
  if (!factory->IsMultiTouchDevice(xiev->sourceid)) {
    *slot = 0;
    return true;
  }
  return factory->QuerySlotForTrackingID(xiev->detail, slot);
}

void DeviceDataManagerX11::GetEventRawData(const XEvent& xev, EventData* data) {
  if (xev.type != GenericEvent)
    return;

  XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
  CHECK_GE(xiev->sourceid, 0);
  CHECK_GE(xiev->deviceid, 0);
  if (xiev->sourceid >= kMaxDeviceNum || xiev->deviceid >= kMaxDeviceNum)
    return;
  data->clear();
  const int sourceid = xiev->sourceid;
  double* valuators = xiev->valuators.values;
  for (int i = 0; i <= valuator_count_[sourceid]; ++i) {
    if (XIMaskIsSet(xiev->valuators.mask, i)) {
      int type = data_type_lookup_[sourceid][i];
      if (type != DT_LAST_ENTRY) {
        (*data)[type] = *valuators;
        if (IsTouchDataType(type)) {
          int slot = -1;
          if (GetSlotNumber(xiev, &slot) && slot >= 0 && slot < kMaxSlotNum)
            last_seen_valuator_[sourceid][slot][type] = *valuators;
        }
      }
      valuators++;
    }
  }
}

bool DeviceDataManagerX11::GetEventData(const XEvent& xev,
    const DataType type, double* value) {
  if (xev.type != GenericEvent)
    return false;

  XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
  CHECK_GE(xiev->sourceid, 0);
  CHECK_GE(xiev->deviceid, 0);
  if (xiev->sourceid >= kMaxDeviceNum || xiev->deviceid >= kMaxDeviceNum)
    return false;
  const int sourceid = xiev->sourceid;
  if (valuator_lookup_[sourceid].empty())
    return false;

  if (type == DT_TOUCH_TRACKING_ID) {
    // With XInput2 MT, Tracking ID is provided in the detail field for touch
    // events.
    if (xiev->evtype == XI_TouchBegin ||
        xiev->evtype == XI_TouchEnd ||
        xiev->evtype == XI_TouchUpdate) {
      *value = xiev->detail;
    } else {
      *value = 0;
    }
    return true;
  }

  int val_index = valuator_lookup_[sourceid][type];
  int slot = 0;
  if (val_index >= 0) {
    if (XIMaskIsSet(xiev->valuators.mask, val_index)) {
      double* valuators = xiev->valuators.values;
      while (val_index--) {
        if (XIMaskIsSet(xiev->valuators.mask, val_index))
          ++valuators;
      }
      *value = *valuators;
      if (IsTouchDataType(type)) {
        if (GetSlotNumber(xiev, &slot) && slot >= 0 && slot < kMaxSlotNum)
          last_seen_valuator_[sourceid][slot][type] = *value;
      }
      return true;
    } else if (IsTouchDataType(type)) {
      if (GetSlotNumber(xiev, &slot) && slot >= 0 && slot < kMaxSlotNum)
        *value = last_seen_valuator_[sourceid][slot][type];
    }
  }

  return false;
}

bool DeviceDataManagerX11::IsXIDeviceEvent(const XEvent& xev) const {
  if (xev.type != GenericEvent || xev.xcookie.extension != xi_opcode_)
    return false;
  return xi_device_event_types_[xev.xcookie.evtype];
}

bool DeviceDataManagerX11::IsTouchpadXInputEvent(const XEvent& xev) const {
  if (xev.type != GenericEvent)
    return false;

  XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev.xcookie.data);
  CHECK_GE(xievent->sourceid, 0);
  if (xievent->sourceid >= kMaxDeviceNum)
    return false;
  return touchpads_[xievent->sourceid];
}

bool DeviceDataManagerX11::IsCMTDeviceEvent(const XEvent& xev) const {
  if (xev.type != GenericEvent)
    return false;

  XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev.xcookie.data);
  CHECK_GE(xievent->sourceid, 0);
  if (xievent->sourceid >= kMaxDeviceNum)
    return false;
  return cmt_devices_[xievent->sourceid];
}

int DeviceDataManagerX11::GetScrollClassEventDetail(const XEvent& xev) const {
  if (xev.type != GenericEvent)
    return SCROLL_TYPE_NO_SCROLL;

  XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev.xcookie.data);
  if (xievent->sourceid >= kMaxDeviceNum)
    return SCROLL_TYPE_NO_SCROLL;
  int horizontal_id = scroll_data_[xievent->sourceid].horizontal.number;
  int vertical_id = scroll_data_[xievent->sourceid].vertical.number;
  return (horizontal_id != -1 &&
                  XIMaskIsSet(xievent->valuators.mask, horizontal_id)
              ? SCROLL_TYPE_HORIZONTAL
              : 0) |
         (vertical_id != -1 && XIMaskIsSet(xievent->valuators.mask, vertical_id)
              ? SCROLL_TYPE_VERTICAL
              : 0);
}

int DeviceDataManagerX11::GetScrollClassDeviceDetail(const XEvent& xev) const {
  if (xev.type != GenericEvent)
    return SCROLL_TYPE_NO_SCROLL;

  XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
  if (xiev->sourceid >= kMaxDeviceNum || xiev->deviceid >= kMaxDeviceNum)
    return SCROLL_TYPE_NO_SCROLL;
  const int sourceid = xiev->sourceid;
  const ScrollInfo& device_data = scroll_data_[sourceid];
  return (device_data.vertical.number >= 0 ? SCROLL_TYPE_VERTICAL : 0) |
         (device_data.horizontal.number >= 0 ? SCROLL_TYPE_HORIZONTAL : 0);
}

bool DeviceDataManagerX11::IsCMTGestureEvent(const XEvent& xev) const {
  return (IsScrollEvent(xev) || IsFlingEvent(xev) || IsCMTMetricsEvent(xev));
}

bool DeviceDataManagerX11::HasEventData(
    const XIDeviceEvent* xiev, const DataType type) const {
  CHECK_GE(xiev->sourceid, 0);
  if (xiev->sourceid >= kMaxDeviceNum)
    return false;
  if (type >= valuator_lookup_[xiev->sourceid].size())
    return false;
  const int idx = valuator_lookup_[xiev->sourceid][type];
  return (idx >= 0) && XIMaskIsSet(xiev->valuators.mask, idx);
}

bool DeviceDataManagerX11::IsScrollEvent(const XEvent& xev) const {
  if (!IsCMTDeviceEvent(xev))
    return false;

  XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
  return (HasEventData(xiev, DT_CMT_SCROLL_X) ||
          HasEventData(xiev, DT_CMT_SCROLL_Y));
}

bool DeviceDataManagerX11::IsFlingEvent(const XEvent& xev) const {
  if (!IsCMTDeviceEvent(xev))
    return false;

  XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
  return (HasEventData(xiev, DT_CMT_FLING_X) &&
          HasEventData(xiev, DT_CMT_FLING_Y) &&
          HasEventData(xiev, DT_CMT_FLING_STATE));
}

bool DeviceDataManagerX11::IsCMTMetricsEvent(const XEvent& xev) const {
  if (!IsCMTDeviceEvent(xev))
    return false;

  XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
  return (HasEventData(xiev, DT_CMT_METRICS_TYPE) &&
          HasEventData(xiev, DT_CMT_METRICS_DATA1) &&
          HasEventData(xiev, DT_CMT_METRICS_DATA2));
}

bool DeviceDataManagerX11::HasGestureTimes(const XEvent& xev) const {
  if (!IsCMTDeviceEvent(xev))
    return false;

  XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
  return (HasEventData(xiev, DT_CMT_START_TIME) &&
          HasEventData(xiev, DT_CMT_END_TIME));
}

void DeviceDataManagerX11::GetScrollOffsets(const XEvent& xev,
                                            float* x_offset,
                                            float* y_offset,
                                            float* x_offset_ordinal,
                                            float* y_offset_ordinal,
                                            int* finger_count) {
  *x_offset = 0;
  *y_offset = 0;
  *x_offset_ordinal = 0;
  *y_offset_ordinal = 0;
  *finger_count = 2;

  EventData data;
  GetEventRawData(xev, &data);

  if (data.find(DT_CMT_SCROLL_X) != data.end())
    *x_offset = data[DT_CMT_SCROLL_X];
  if (data.find(DT_CMT_SCROLL_Y) != data.end())
    *y_offset = data[DT_CMT_SCROLL_Y];
  if (data.find(DT_CMT_ORDINAL_X) != data.end())
    *x_offset_ordinal = data[DT_CMT_ORDINAL_X];
  if (data.find(DT_CMT_ORDINAL_Y) != data.end())
    *y_offset_ordinal = data[DT_CMT_ORDINAL_Y];
  if (data.find(DT_CMT_FINGER_COUNT) != data.end())
    *finger_count = static_cast<int>(data[DT_CMT_FINGER_COUNT]);
}

void DeviceDataManagerX11::GetScrollClassOffsets(const XEvent& xev,
                                                 double* x_offset,
                                                 double* y_offset) {
  DCHECK_NE(SCROLL_TYPE_NO_SCROLL, GetScrollClassDeviceDetail(xev));

  *x_offset = 0;
  *y_offset = 0;

  if (xev.type != GenericEvent)
    return;

  XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
  if (xiev->sourceid >= kMaxDeviceNum || xiev->deviceid >= kMaxDeviceNum)
    return;
  const int sourceid = xiev->sourceid;
  double* valuators = xiev->valuators.values;

  ScrollInfo* info = &scroll_data_[sourceid];

  const int horizontal_number = info->horizontal.number;
  const int vertical_number = info->vertical.number;

  for (int i = 0; i <= valuator_count_[sourceid]; ++i) {
    if (!XIMaskIsSet(xiev->valuators.mask, i))
      continue;
    if (i == horizontal_number) {
      *x_offset = ExtractAndUpdateScrollOffset(&info->horizontal, *valuators);
    } else if (i == vertical_number) {
      *y_offset = ExtractAndUpdateScrollOffset(&info->vertical, *valuators);
    }
    valuators++;
  }
}

void DeviceDataManagerX11::InvalidateScrollClasses() {
  for (int i = 0; i < kMaxDeviceNum; i++) {
    scroll_data_[i].horizontal.seen = false;
    scroll_data_[i].vertical.seen = false;
  }
}

void DeviceDataManagerX11::GetFlingData(const XEvent& xev,
                                        float* vx,
                                        float* vy,
                                        float* vx_ordinal,
                                        float* vy_ordinal,
                                        bool* is_cancel) {
  *vx = 0;
  *vy = 0;
  *vx_ordinal = 0;
  *vy_ordinal = 0;
  *is_cancel = false;

  EventData data;
  GetEventRawData(xev, &data);

  if (data.find(DT_CMT_FLING_X) != data.end())
    *vx = data[DT_CMT_FLING_X];
  if (data.find(DT_CMT_FLING_Y) != data.end())
    *vy = data[DT_CMT_FLING_Y];
  if (data.find(DT_CMT_FLING_STATE) != data.end())
    *is_cancel = !!static_cast<unsigned int>(data[DT_CMT_FLING_STATE]);
  if (data.find(DT_CMT_ORDINAL_X) != data.end())
    *vx_ordinal = data[DT_CMT_ORDINAL_X];
  if (data.find(DT_CMT_ORDINAL_Y) != data.end())
    *vy_ordinal = data[DT_CMT_ORDINAL_Y];
}

void DeviceDataManagerX11::GetMetricsData(const XEvent& xev,
                                          GestureMetricsType* type,
                                          float* data1,
                                          float* data2) {
  *type = kGestureMetricsTypeUnknown;
  *data1 = 0;
  *data2 = 0;

  EventData data;
  GetEventRawData(xev, &data);

  if (data.find(DT_CMT_METRICS_TYPE) != data.end()) {
    int val = static_cast<int>(data[DT_CMT_METRICS_TYPE]);
    if (val == 0)
      *type = kGestureMetricsTypeNoisyGround;
    else
      *type = kGestureMetricsTypeUnknown;
  }
  if (data.find(DT_CMT_METRICS_DATA1) != data.end())
    *data1 = data[DT_CMT_METRICS_DATA1];
  if (data.find(DT_CMT_METRICS_DATA2) != data.end())
    *data2 = data[DT_CMT_METRICS_DATA2];
}

int DeviceDataManagerX11::GetMappedButton(int button) {
  return button > 0 && button <= button_map_count_ ? button_map_[button - 1] :
                                                     button;
}

void DeviceDataManagerX11::UpdateButtonMap() {
  button_map_count_ = XGetPointerMapping(gfx::GetXDisplay(),
                                         button_map_,
                                         arraysize(button_map_));
}

void DeviceDataManagerX11::GetGestureTimes(const XEvent& xev,
                                           double* start_time,
                                           double* end_time) {
  *start_time = 0;
  *end_time = 0;

  EventData data;
  GetEventRawData(xev, &data);

  if (data.find(DT_CMT_START_TIME) != data.end())
    *start_time = data[DT_CMT_START_TIME];
  if (data.find(DT_CMT_END_TIME) != data.end())
    *end_time = data[DT_CMT_END_TIME];
}

bool DeviceDataManagerX11::NormalizeData(int deviceid,
                                         const DataType type,
                                         double* value) {
  double max_value;
  double min_value;
  if (GetDataRange(deviceid, type, &min_value, &max_value)) {
    *value = (*value - min_value) / (max_value - min_value);
    DCHECK(*value >= 0.0 && *value <= 1.0);
    return true;
  }
  return false;
}

bool DeviceDataManagerX11::GetDataRange(int deviceid,
                                        const DataType type,
                                        double* min,
                                        double* max) {
  CHECK_GE(deviceid, 0);
  if (deviceid >= kMaxDeviceNum)
    return false;
  if (valuator_lookup_[deviceid][type] >= 0) {
    *min = valuator_min_[deviceid][type];
    *max = valuator_max_[deviceid][type];
    return true;
  }
  return false;
}

void DeviceDataManagerX11::SetDeviceListForTest(
    const std::vector<int>& touchscreen,
    const std::vector<int>& cmt_devices,
    const std::vector<int>& other_devices) {
  for (int i = 0; i < kMaxDeviceNum; ++i) {
    valuator_count_[i] = 0;
    valuator_lookup_[i].clear();
    data_type_lookup_[i].clear();
    valuator_min_[i].clear();
    valuator_max_[i].clear();
    for (int j = 0; j < kMaxSlotNum; j++)
      last_seen_valuator_[i][j].clear();
  }

  for (int deviceid : touchscreen) {
    InitializeValuatorsForTest(deviceid, kTouchDataTypeStart, kTouchDataTypeEnd,
                               0, 1000);
  }

  cmt_devices_.reset();
  for (int deviceid : cmt_devices) {
    cmt_devices_[deviceid] = true;
    touchpads_[deviceid] = true;
    InitializeValuatorsForTest(deviceid, kCMTDataTypeStart, kCMTDataTypeEnd,
                               -1000, 1000);
  }

  for (int deviceid : other_devices) {
    InitializeValuatorsForTest(deviceid, kCMTDataTypeStart, kCMTDataTypeEnd,
                               -1000, 1000);
  }
}

void DeviceDataManagerX11::SetValuatorDataForTest(XIDeviceEvent* xievent,
                                                  DataType type,
                                                  double value) {
  int index = valuator_lookup_[xievent->deviceid][type];
  CHECK(!XIMaskIsSet(xievent->valuators.mask, index));
  CHECK(index >= 0 && index < valuator_count_[xievent->deviceid]);
  XISetMask(xievent->valuators.mask, index);

  double* valuators = xievent->valuators.values;
  for (int i = 0; i < index; ++i) {
    if (XIMaskIsSet(xievent->valuators.mask, i))
      valuators++;
  }
  for (int i = DT_LAST_ENTRY - 1; i > valuators - xievent->valuators.values;
       --i)
    xievent->valuators.values[i] = xievent->valuators.values[i - 1];
  *valuators = value;
}

void DeviceDataManagerX11::InitializeValuatorsForTest(int deviceid,
                                                      int start_valuator,
                                                      int end_valuator,
                                                      double min_value,
                                                      double max_value) {
  valuator_lookup_[deviceid].resize(DT_LAST_ENTRY, -1);
  data_type_lookup_[deviceid].resize(DT_LAST_ENTRY, DT_LAST_ENTRY);
  valuator_min_[deviceid].resize(DT_LAST_ENTRY, 0);
  valuator_max_[deviceid].resize(DT_LAST_ENTRY, 0);
  for (int j = 0; j < kMaxSlotNum; j++)
    last_seen_valuator_[deviceid][j].resize(DT_LAST_ENTRY, 0);
  for (int j = start_valuator; j <= end_valuator; ++j) {
    valuator_lookup_[deviceid][j] = valuator_count_[deviceid];
    data_type_lookup_[deviceid][valuator_count_[deviceid]] = j;
    valuator_min_[deviceid][j] = min_value;
    valuator_max_[deviceid][j] = max_value;
    valuator_count_[deviceid]++;
  }
}

bool DeviceDataManagerX11::UpdateValuatorClassDevice(
    XIValuatorClassInfo* valuator_class_info,
    Atom* atoms,
    int deviceid) {
  DCHECK(deviceid >= 0 && deviceid < kMaxDeviceNum);
  Atom* label =
      std::find(atoms, atoms + DT_LAST_ENTRY, valuator_class_info->label);
  if (label == atoms + DT_LAST_ENTRY) {
    return false;
  }
  int data_type = label - atoms;
  DCHECK_GE(data_type, 0);
  DCHECK_LT(data_type, DT_LAST_ENTRY);

  valuator_lookup_[deviceid][data_type] = valuator_class_info->number;
  data_type_lookup_[deviceid][valuator_class_info->number] = data_type;
  valuator_min_[deviceid][data_type] = valuator_class_info->min;
  valuator_max_[deviceid][data_type] = valuator_class_info->max;
  return IsCMTDataType(data_type);
}

void DeviceDataManagerX11::UpdateScrollClassDevice(
    XIScrollClassInfo* scroll_class_info,
    int deviceid) {
  DCHECK(deviceid >= 0 && deviceid < kMaxDeviceNum);
  ScrollInfo& info = scroll_data_[deviceid];

  // TODO: xinput2 is disabled until edge cases are fixed.
  // http://crbug.com/616308
  return;

  bool legacy_scroll_available =
      (scroll_class_info->flags & XIScrollFlagNoEmulation) == 0;
  // If the device's highest resolution is lower than the resolution of xinput1
  // then use xinput1's events instead (ie. don't configure smooth scrolling).
  if (legacy_scroll_available &&
      std::abs(scroll_class_info->increment) <= 1.0) {
    return;
  }

  switch (scroll_class_info->scroll_type) {
    case XIScrollTypeVertical:
      info.vertical.number = scroll_class_info->number;
      info.vertical.increment = scroll_class_info->increment;
      info.vertical.position = 0;
      info.vertical.seen = false;
      break;
    case XIScrollTypeHorizontal:
      info.horizontal.number = scroll_class_info->number;
      info.horizontal.increment = scroll_class_info->increment;
      info.horizontal.position = 0;
      info.horizontal.seen = false;
      break;
  }
}

double DeviceDataManagerX11::ExtractAndUpdateScrollOffset(
    ScrollInfo::AxisInfo* axis,
    double valuator) const {
  double offset = 0;
  if (axis->seen)
    offset = axis->position - valuator;
  axis->seen = true;
  axis->position = valuator;
  return offset / axis->increment;
}

void DeviceDataManagerX11::SetDisabledKeyboardAllowedKeys(
    std::unique_ptr<std::set<KeyboardCode>> excepted_keys) {
  DCHECK(!excepted_keys.get() ||
         !blocked_keyboard_allowed_keys_.get());
  blocked_keyboard_allowed_keys_ = std::move(excepted_keys);
}

void DeviceDataManagerX11::DisableDevice(int deviceid) {
  blocked_devices_.set(deviceid, true);
  // TODO(rsadam@): Support blocking touchscreen devices.
  std::vector<InputDevice> keyboards = GetKeyboardDevices();
  std::vector<InputDevice>::iterator it =
      FindDeviceWithId(keyboards.begin(), keyboards.end(), deviceid);
  if (it != std::end(keyboards)) {
    blocked_keyboard_devices_.insert(
        std::pair<int, InputDevice>(deviceid, *it));
    keyboards.erase(it);
    DeviceDataManager::OnKeyboardDevicesUpdated(keyboards);
  }
}

void DeviceDataManagerX11::EnableDevice(int deviceid) {
  blocked_devices_.set(deviceid, false);
  std::map<int, InputDevice>::iterator it =
      blocked_keyboard_devices_.find(deviceid);
  if (it != blocked_keyboard_devices_.end()) {
    std::vector<InputDevice> devices = GetKeyboardDevices();
    // Add device to current list of active devices.
    devices.push_back((*it).second);
    blocked_keyboard_devices_.erase(it);
    DeviceDataManager::OnKeyboardDevicesUpdated(devices);
  }
}

bool DeviceDataManagerX11::IsDeviceEnabled(int device_id) const {
  return blocked_devices_.test(device_id);
}

bool DeviceDataManagerX11::IsEventBlocked(const XEvent& xev) {
  // Only check XI2 events which have a source device id.
  if (xev.type != GenericEvent)
    return false;

  XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev.xcookie.data);
  // Allow any key events from blocked_keyboard_allowed_keys_.
  if (blocked_keyboard_allowed_keys_ &&
      (xievent->evtype == XI_KeyPress || xievent->evtype == XI_KeyRelease) &&
      blocked_keyboard_allowed_keys_->find(KeyboardCodeFromXKeyEvent(&xev)) !=
          blocked_keyboard_allowed_keys_->end()) {
    return false;
  }

  return blocked_devices_.test(xievent->sourceid);
}

void DeviceDataManagerX11::OnKeyboardDevicesUpdated(
    const std::vector<InputDevice>& devices) {
  std::vector<InputDevice> keyboards(devices);
  for (std::map<int, InputDevice>::iterator blocked_iter =
           blocked_keyboard_devices_.begin();
       blocked_iter != blocked_keyboard_devices_.end();) {
    // Check if the blocked device still exists in list of devices.
    int device_id = blocked_iter->first;
    std::vector<InputDevice>::iterator it =
        FindDeviceWithId(keyboards.begin(), keyboards.end(), device_id);
    // If the device no longer exists, unblock it, else filter it out from our
    // active list.
    if (it == keyboards.end()) {
      blocked_devices_.set((*blocked_iter).first, false);
      blocked_keyboard_devices_.erase(blocked_iter++);
    } else {
      keyboards.erase(it);
      ++blocked_iter;
    }
  }
  // Notify base class of updated list.
  DeviceDataManager::OnKeyboardDevicesUpdated(keyboards);
}

}  // namespace ui
