// Copyright (c) 2012 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/x/touch_factory_x11.h"

#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/XIproto.h>

#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "ui/events/event_switches.h"
#include "ui/events/x/device_data_manager_x11.h"
#include "ui/events/x/device_list_cache_x.h"
#include "ui/gfx/x/x11_types.h"

namespace ui {

TouchFactory::TouchFactory()
    : pointer_device_lookup_(),
      touch_device_available_(false),
      touch_events_disabled_(false),
      touch_device_list_(),
      max_touch_points_(-1),
      id_generator_(0) {
  if (!DeviceDataManagerX11::GetInstance()->IsXInput2Available())
    return;

  XDisplay* display = gfx::GetXDisplay();
  UpdateDeviceList(display);

  CommandLine* cmdline = CommandLine::ForCurrentProcess();
  touch_events_disabled_ = cmdline->HasSwitch(switches::kTouchEvents) &&
      cmdline->GetSwitchValueASCII(switches::kTouchEvents) ==
          switches::kTouchEventsDisabled;
}

TouchFactory::~TouchFactory() {
}

// static
TouchFactory* TouchFactory::GetInstance() {
  return Singleton<TouchFactory>::get();
}

// static
void TouchFactory::SetTouchDeviceListFromCommandLine() {
  // Get a list of pointer-devices that should be treated as touch-devices.
  // This is primarily used for testing/debugging touch-event processing when a
  // touch-device isn't available.
  std::string touch_devices =
      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          switches::kTouchDevices);

  if (!touch_devices.empty()) {
    std::vector<std::string> devs;
    std::vector<unsigned int> device_ids;
    unsigned int devid;
    base::SplitString(touch_devices, ',', &devs);
    for (std::vector<std::string>::iterator iter = devs.begin();
        iter != devs.end(); ++iter) {
      if (base::StringToInt(*iter, reinterpret_cast<int*>(&devid)))
        device_ids.push_back(devid);
      else
        DLOG(WARNING) << "Invalid touch-device id: " << *iter;
    }
    ui::TouchFactory::GetInstance()->SetTouchDeviceList(device_ids);
  }
}

void TouchFactory::UpdateDeviceList(Display* display) {
  // Detect touch devices.
  touch_device_available_ = false;
  touch_device_lookup_.reset();
  touch_device_list_.clear();
  touchscreen_ids_.clear();
  max_touch_points_ = -1;

#if !defined(USE_XI2_MT)
  // NOTE: The new API for retrieving the list of devices (XIQueryDevice) does
  // not provide enough information to detect a touch device. As a result, the
  // old version of query function (XListInputDevices) is used instead.
  // If XInput2 is not supported, this will return null (with count of -1) so
  // we assume there cannot be any touch devices.
  // With XI2.1 or older, we allow only single touch devices.
  XDeviceList dev_list =
      DeviceListCacheX::GetInstance()->GetXDeviceList(display);
  Atom xi_touchscreen = XInternAtom(display, XI_TOUCHSCREEN, false);
  for (int i = 0; i < dev_list.count; i++) {
    if (dev_list[i].type == xi_touchscreen) {
      touch_device_lookup_[dev_list[i].id] = true;
      touch_device_list_[dev_list[i].id] = false;
      touch_device_available_ = true;
    }
  }
#endif

  if (!DeviceDataManagerX11::GetInstance()->IsXInput2Available())
    return;

  // Instead of asking X for the list of devices all the time, let's maintain a
  // list of pointer devices we care about.
  // It should not be necessary to select for slave devices. XInput2 provides
  // enough information to the event callback to decide which slave device
  // triggered the event, thus decide whether the 'pointer event' is a
  // 'mouse event' or a 'touch event'.
  // However, on some desktops, some events from a master pointer are
  // not delivered to the client. So we select for slave devices instead.
  // If the touch device has 'GrabDevice' set and 'SendCoreEvents' unset (which
  // is possible), then the device is detected as a floating device, and a
  // floating device is not connected to a master device. So it is necessary to
  // also select on the floating devices.
  pointer_device_lookup_.reset();
  XIDeviceList xi_dev_list =
      DeviceListCacheX::GetInstance()->GetXI2DeviceList(display);
  for (int i = 0; i < xi_dev_list.count; i++) {
    XIDeviceInfo* devinfo = xi_dev_list.devices + i;
    if (devinfo->use == XIFloatingSlave || devinfo->use == XIMasterPointer) {
#if defined(USE_XI2_MT)
      for (int k = 0; k < devinfo->num_classes; ++k) {
        XIAnyClassInfo* xiclassinfo = devinfo->classes[k];
        if (xiclassinfo->type == XITouchClass) {
          XITouchClassInfo* tci =
              reinterpret_cast<XITouchClassInfo*>(xiclassinfo);
          // Only care direct touch device (such as touch screen) right now
          if (tci->mode == XIDirectTouch) {
            touch_device_lookup_[devinfo->deviceid] = true;
            touch_device_list_[devinfo->deviceid] = true;
            touch_device_available_ = true;
            if (tci->num_touches > 0 && tci->num_touches > max_touch_points_)
              max_touch_points_ = tci->num_touches;
          }
        }
      }
#endif
      pointer_device_lookup_[devinfo->deviceid] = true;
    }

#if defined(USE_XI2_MT)
    if (devinfo->use == XIFloatingSlave || devinfo->use == XISlavePointer) {
      for (int k = 0; k < devinfo->num_classes; ++k) {
        XIAnyClassInfo* xiclassinfo = devinfo->classes[k];
        if (xiclassinfo->type == XITouchClass) {
          XITouchClassInfo* tci =
              reinterpret_cast<XITouchClassInfo*>(xiclassinfo);
          // Only care direct touch device (such as touch screen) right now
          if (tci->mode == XIDirectTouch)
            CacheTouchscreenIds(display, devinfo->deviceid);
        }
      }
    }
#endif
  }
}

bool TouchFactory::ShouldProcessXI2Event(XEvent* xev) {
  DCHECK_EQ(GenericEvent, xev->type);
  XIEvent* event = static_cast<XIEvent*>(xev->xcookie.data);
  XIDeviceEvent* xiev = reinterpret_cast<XIDeviceEvent*>(event);

#if defined(USE_XI2_MT)
  if (event->evtype == XI_TouchBegin ||
      event->evtype == XI_TouchUpdate ||
      event->evtype == XI_TouchEnd) {
    return !touch_events_disabled_ && IsTouchDevice(xiev->deviceid);
  }
#endif
  // Make sure only key-events from the master device are processed.
  if (event->evtype == XI_KeyPress || event->evtype == XI_KeyRelease)
    return xiev->deviceid == xiev->sourceid;

  if (event->evtype != XI_ButtonPress &&
      event->evtype != XI_ButtonRelease &&
      event->evtype != XI_Motion)
    return true;

  if (!pointer_device_lookup_[xiev->deviceid])
    return false;

  return IsTouchDevice(xiev->deviceid) ? !touch_events_disabled_ : true;
}

void TouchFactory::SetupXI2ForXWindow(Window window) {
  // Setup mask for mouse events. It is possible that a device is loaded/plugged
  // in after we have setup XInput2 on a window. In such cases, we need to
  // either resetup XInput2 for the window, so that we get events from the new
  // device, or we need to listen to events from all devices, and then filter
  // the events from uninteresting devices. We do the latter because that's
  // simpler.

  XDisplay* display = gfx::GetXDisplay();

  unsigned char mask[XIMaskLen(XI_LASTEVENT)];
  memset(mask, 0, sizeof(mask));

#if defined(USE_XI2_MT)
  XISetMask(mask, XI_TouchBegin);
  XISetMask(mask, XI_TouchUpdate);
  XISetMask(mask, XI_TouchEnd);
#endif
  XISetMask(mask, XI_ButtonPress);
  XISetMask(mask, XI_ButtonRelease);
  XISetMask(mask, XI_Motion);

  XIEventMask evmask;
  evmask.deviceid = XIAllDevices;
  evmask.mask_len = sizeof(mask);
  evmask.mask = mask;
  XISelectEvents(display, window, &evmask, 1);
  XFlush(display);
}

void TouchFactory::SetTouchDeviceList(
    const std::vector<unsigned int>& devices) {
  touch_device_lookup_.reset();
  touch_device_list_.clear();
  for (std::vector<unsigned int>::const_iterator iter = devices.begin();
       iter != devices.end(); ++iter) {
    DCHECK(*iter < touch_device_lookup_.size());
    touch_device_lookup_[*iter] = true;
    touch_device_list_[*iter] = false;
  }
}

bool TouchFactory::IsTouchDevice(unsigned deviceid) const {
  return deviceid < touch_device_lookup_.size() ?
      touch_device_lookup_[deviceid] : false;
}

bool TouchFactory::IsMultiTouchDevice(unsigned int deviceid) const {
  return (deviceid < touch_device_lookup_.size() &&
          touch_device_lookup_[deviceid]) ?
          touch_device_list_.find(deviceid)->second :
          false;
}

bool TouchFactory::QuerySlotForTrackingID(uint32 tracking_id, int* slot) {
  if (!id_generator_.HasGeneratedIDFor(tracking_id))
    return false;
  *slot = static_cast<int>(id_generator_.GetGeneratedID(tracking_id));
  return true;
}

int TouchFactory::GetSlotForTrackingID(uint32 tracking_id) {
  return id_generator_.GetGeneratedID(tracking_id);
}

void TouchFactory::ReleaseSlotForTrackingID(uint32 tracking_id) {
  id_generator_.ReleaseNumber(tracking_id);
}

bool TouchFactory::IsTouchDevicePresent() {
  return !touch_events_disabled_ && touch_device_available_;
}

int TouchFactory::GetMaxTouchPoints() const {
  return max_touch_points_;
}

void TouchFactory::SetTouchDeviceForTest(
    const std::vector<unsigned int>& devices) {
  touch_device_lookup_.reset();
  touch_device_list_.clear();
  for (std::vector<unsigned int>::const_iterator iter = devices.begin();
       iter != devices.end(); ++iter) {
    DCHECK(*iter < touch_device_lookup_.size());
    touch_device_lookup_[*iter] = true;
    touch_device_list_[*iter] = true;
  }
  touch_device_available_ = true;
  touch_events_disabled_ = false;
}

void TouchFactory::SetPointerDeviceForTest(
    const std::vector<unsigned int>& devices) {
  pointer_device_lookup_.reset();
  for (std::vector<unsigned int>::const_iterator iter = devices.begin();
       iter != devices.end(); ++iter) {
    pointer_device_lookup_[*iter] = true;
  }
}

void TouchFactory::CacheTouchscreenIds(Display* display, int device_id) {
  XDevice* device = XOpenDevice(display, device_id);
  if (!device)
    return;

  Atom actual_type_return;
  int actual_format_return;
  unsigned long nitems_return;
  unsigned long bytes_after_return;
  unsigned char *prop_return;

  const char kDeviceProductIdString[] = "Device Product ID";
  Atom device_product_id_atom =
      XInternAtom(display, kDeviceProductIdString, false);

  if (device_product_id_atom != None &&
      XGetDeviceProperty(display, device, device_product_id_atom, 0, 2,
                         False, XA_INTEGER, &actual_type_return,
                         &actual_format_return, &nitems_return,
                         &bytes_after_return, &prop_return) == Success) {
    if (actual_type_return == XA_INTEGER &&
        actual_format_return == 32 &&
        nitems_return == 2) {
      // An actual_format_return of 32 implies that the returned data is an
      // array of longs. See the description of |prop_return| in `man
      // XGetDeviceProperty` for details.
      long* ptr = reinterpret_cast<long*>(prop_return);

      // Internal displays will have a vid and pid of 0. Ignore them.
      // ptr[0] is the vid, and ptr[1] is the pid.
      if (ptr[0] || ptr[1])
        touchscreen_ids_.insert(std::make_pair(ptr[0], ptr[1]));
    }
    XFree(prop_return);
  }

  XCloseDevice(display, device);
}

}  // namespace ui
