// Copyright 2013 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/test/events_test_utils_x11.h"

#include <X11/extensions/XI2.h>
#include <X11/keysym.h>
#include <X11/X.h>
#include <X11/Xlib.h>

#include "base/logging.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/keyboard_code_conversion_x.h"
#include "ui/events/x/touch_factory_x11.h"

namespace {

// Converts ui::EventType to state for X*Events.
unsigned int XEventState(int flags) {
  return
      ((flags & ui::EF_SHIFT_DOWN) ? ShiftMask : 0) |
      ((flags & ui::EF_CONTROL_DOWN) ? ControlMask : 0) |
      ((flags & ui::EF_ALT_DOWN) ? Mod1Mask : 0) |
      ((flags & ui::EF_CAPS_LOCK_DOWN) ? LockMask : 0) |
      ((flags & ui::EF_ALTGR_DOWN) ? Mod5Mask : 0) |
      ((flags & ui::EF_COMMAND_DOWN) ? Mod4Mask : 0) |
      ((flags & ui::EF_MOD3_DOWN) ? Mod3Mask : 0) |
      ((flags & ui::EF_NUMPAD_KEY) ? Mod2Mask : 0) |
      ((flags & ui::EF_LEFT_MOUSE_BUTTON) ? Button1Mask: 0) |
      ((flags & ui::EF_MIDDLE_MOUSE_BUTTON) ? Button2Mask: 0) |
      ((flags & ui::EF_RIGHT_MOUSE_BUTTON) ? Button3Mask: 0);
}

// Converts EventType to XKeyEvent type.
int XKeyEventType(ui::EventType type) {
  switch (type) {
    case ui::ET_KEY_PRESSED:
      return KeyPress;
    case ui::ET_KEY_RELEASED:
      return KeyRelease;
    default:
      return 0;
  }
}

// Converts EventType to XI2 event type.
int XIKeyEventType(ui::EventType type) {
  switch (type) {
    case ui::ET_KEY_PRESSED:
      return XI_KeyPress;
    case ui::ET_KEY_RELEASED:
      return XI_KeyRelease;
    default:
      return 0;
  }
}

int XIButtonEventType(ui::EventType type) {
  switch (type) {
    case ui::ET_MOUSEWHEEL:
    case ui::ET_MOUSE_PRESSED:
      // The button release X events for mouse wheels are dropped by Aura.
      return XI_ButtonPress;
    case ui::ET_MOUSE_RELEASED:
      return XI_ButtonRelease;
    default:
      NOTREACHED();
      return 0;
  }
}

// Converts Aura event type and flag to X button event.
unsigned int XButtonEventButton(ui::EventType type,
                                int flags) {
  // Aura events don't keep track of mouse wheel button, so just return
  // the first mouse wheel button.
  if (type == ui::ET_MOUSEWHEEL)
    return Button4;

  if (flags & ui::EF_LEFT_MOUSE_BUTTON)
    return Button1;
  if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
    return Button2;
  if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
    return Button3;

  return 0;
}

void InitValuatorsForXIDeviceEvent(XIDeviceEvent* xiev) {
  int valuator_count = ui::DeviceDataManagerX11::DT_LAST_ENTRY;
  xiev->valuators.mask_len = (valuator_count / 8) + 1;
  xiev->valuators.mask = new unsigned char[xiev->valuators.mask_len];
  memset(xiev->valuators.mask, 0, xiev->valuators.mask_len);
  xiev->valuators.values = new double[valuator_count];
}

XEvent* CreateXInput2Event(int deviceid,
                           int evtype,
                           int tracking_id,
                           const gfx::Point& location) {
  XEvent* event = new XEvent;
  memset(event, 0, sizeof(*event));
  event->type = GenericEvent;
  event->xcookie.data = new XIDeviceEvent;
  XIDeviceEvent* xiev =
      static_cast<XIDeviceEvent*>(event->xcookie.data);
  memset(xiev, 0, sizeof(XIDeviceEvent));
  xiev->deviceid = deviceid;
  xiev->sourceid = deviceid;
  xiev->evtype = evtype;
  xiev->detail = tracking_id;
  xiev->event_x = location.x();
  xiev->event_y = location.y();
  xiev->event = DefaultRootWindow(gfx::GetXDisplay());
  if (evtype == XI_ButtonPress || evtype == XI_ButtonRelease) {
    xiev->buttons.mask_len = 8;
    xiev->buttons.mask = new unsigned char[xiev->buttons.mask_len];
    memset(xiev->buttons.mask, 0, xiev->buttons.mask_len);
  }
  return event;
}

}  // namespace

namespace ui {

// XInput2 events contain additional data that need to be explicitly freed (see
// |CreateXInput2Event()|.
void XEventDeleter::operator()(XEvent* event) {
  if (event->type == GenericEvent) {
    XIDeviceEvent* xiev =
        static_cast<XIDeviceEvent*>(event->xcookie.data);
    if (xiev) {
      delete[] xiev->valuators.mask;
      delete[] xiev->valuators.values;
      delete[] xiev->buttons.mask;
      delete xiev;
    }
  }
  delete event;
}

ScopedXI2Event::ScopedXI2Event() {}
ScopedXI2Event::~ScopedXI2Event() {}

void ScopedXI2Event::InitKeyEvent(EventType type,
                                  KeyboardCode key_code,
                                  int flags) {
  XDisplay* display = gfx::GetXDisplay();
  event_.reset(new XEvent);
  memset(event_.get(), 0, sizeof(XEvent));
  event_->type = XKeyEventType(type);
  CHECK_NE(0, event_->type);
  event_->xkey.serial = 0;
  event_->xkey.send_event = 0;
  event_->xkey.display = display;
  event_->xkey.time = 0;
  event_->xkey.window = 0;
  event_->xkey.root = 0;
  event_->xkey.subwindow = 0;
  event_->xkey.x = 0;
  event_->xkey.y = 0;
  event_->xkey.x_root = 0;
  event_->xkey.y_root = 0;
  event_->xkey.state = XEventState(flags);
  event_->xkey.keycode = XKeyCodeForWindowsKeyCode(key_code, flags, display);
  event_->xkey.same_screen = 1;
}

void ScopedXI2Event::InitGenericKeyEvent(int deviceid,
                                         int sourceid,
                                         EventType type,
                                         KeyboardCode key_code,
                                         int flags) {
  event_.reset(
      CreateXInput2Event(deviceid, XIKeyEventType(type), 0, gfx::Point()));
  XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event_->xcookie.data);
  CHECK_NE(0, xievent->evtype);
  XDisplay* display = gfx::GetXDisplay();
  event_->xgeneric.display = display;
  xievent->display = display;
  xievent->mods.effective = XEventState(flags);
  xievent->detail = XKeyCodeForWindowsKeyCode(key_code, flags, display);
  xievent->sourceid = sourceid;
}

void ScopedXI2Event::InitGenericButtonEvent(int deviceid,
                                            EventType type,
                                            const gfx::Point& location,
                                            int flags) {
  event_.reset(CreateXInput2Event(deviceid,
                                  XIButtonEventType(type), 0, gfx::Point()));
  XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event_->xcookie.data);
  xievent->mods.effective = XEventState(flags);
  xievent->detail = XButtonEventButton(type, flags);
  xievent->event_x = location.x();
  xievent->event_y = location.y();
  XISetMask(xievent->buttons.mask, xievent->detail);
  // Setup an empty valuator list for generic button events.
  SetUpValuators(std::vector<Valuator>());
}

void ScopedXI2Event::InitGenericMouseWheelEvent(int deviceid,
                                                int wheel_delta,
                                                int flags) {
  InitGenericButtonEvent(deviceid, ui::ET_MOUSEWHEEL, gfx::Point(), flags);
  XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event_->xcookie.data);
  xievent->detail = wheel_delta > 0 ? Button4 : Button5;
}

void ScopedXI2Event::InitScrollEvent(int deviceid,
                                     int x_offset,
                                     int y_offset,
                                     int x_offset_ordinal,
                                     int y_offset_ordinal,
                                     int finger_count) {
  event_.reset(CreateXInput2Event(deviceid, XI_Motion, 0, gfx::Point()));

  Valuator valuators[] = {
    Valuator(DeviceDataManagerX11::DT_CMT_SCROLL_X, x_offset),
    Valuator(DeviceDataManagerX11::DT_CMT_SCROLL_Y, y_offset),
    Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_X, x_offset_ordinal),
    Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_Y, y_offset_ordinal),
    Valuator(DeviceDataManagerX11::DT_CMT_FINGER_COUNT, finger_count)
  };
  SetUpValuators(
      std::vector<Valuator>(valuators, valuators + arraysize(valuators)));
}

void ScopedXI2Event::InitFlingScrollEvent(int deviceid,
                                          int x_velocity,
                                          int y_velocity,
                                          int x_velocity_ordinal,
                                          int y_velocity_ordinal,
                                          bool is_cancel) {
  event_.reset(CreateXInput2Event(deviceid, XI_Motion, deviceid, gfx::Point()));

  Valuator valuators[] = {
    Valuator(DeviceDataManagerX11::DT_CMT_FLING_STATE, is_cancel ? 1 : 0),
    Valuator(DeviceDataManagerX11::DT_CMT_FLING_Y, y_velocity),
    Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_Y, y_velocity_ordinal),
    Valuator(DeviceDataManagerX11::DT_CMT_FLING_X, x_velocity),
    Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_X, x_velocity_ordinal)
  };

  SetUpValuators(
      std::vector<Valuator>(valuators, valuators + arraysize(valuators)));
}

void ScopedXI2Event::InitTouchEvent(int deviceid,
                                    int evtype,
                                    int tracking_id,
                                    const gfx::Point& location,
                                    const std::vector<Valuator>& valuators) {
  event_.reset(CreateXInput2Event(deviceid, evtype, tracking_id, location));

  // If a timestamp was specified, setup the event.
  for (size_t i = 0; i < valuators.size(); ++i) {
    if (valuators[i].data_type ==
        DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP) {
      SetUpValuators(valuators);
      return;
    }
  }

  // No timestamp was specified. Use |ui::EventTimeForNow()|.
  std::vector<Valuator> valuators_with_time = valuators;
  valuators_with_time.push_back(
      Valuator(DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP,
               (ui::EventTimeForNow()).InMicroseconds()));
  SetUpValuators(valuators_with_time);
}

void ScopedXI2Event::SetUpValuators(const std::vector<Valuator>& valuators) {
  CHECK(event_.get());
  CHECK_EQ(GenericEvent, event_->type);
  XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(event_->xcookie.data);
  InitValuatorsForXIDeviceEvent(xiev);
  ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
  for (size_t i = 0; i < valuators.size(); ++i) {
    manager->SetValuatorDataForTest(xiev, valuators[i].data_type,
                                    valuators[i].value);
  }
}

void SetUpTouchPadForTest(unsigned int deviceid) {
  std::vector<unsigned int> device_list;
  device_list.push_back(deviceid);

  TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
  ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
  manager->SetDeviceListForTest(std::vector<unsigned int>(), device_list);
}

void SetUpTouchDevicesForTest(const std::vector<unsigned int>& devices) {
  TouchFactory::GetInstance()->SetTouchDeviceForTest(devices);
  ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
  manager->SetDeviceListForTest(devices, std::vector<unsigned int>());
}

}  // namespace ui
