// 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 <cstring>
#include <set>

#include <X11/extensions/XInput2.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/XKBlib.h>

// Generically-named #defines from Xlib that conflict with symbols in GTest.
#undef Bool
#undef None

#include "base/memory/scoped_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_utils.h"
#include "ui/events/test/events_test_utils.h"
#include "ui/events/test/events_test_utils_x11.h"
#include "ui/events/x/device_data_manager_x11.h"
#include "ui/events/x/touch_factory_x11.h"
#include "ui/gfx/point.h"

namespace ui {

namespace {

// Initializes the passed-in Xlib event.
void InitButtonEvent(XEvent* event,
                     bool is_press,
                     const gfx::Point& location,
                     int button,
                     int state) {
  memset(event, 0, sizeof(*event));

  // We don't bother setting fields that the event code doesn't use, such as
  // x_root/y_root and window/root/subwindow.
  XButtonEvent* button_event = &(event->xbutton);
  button_event->type = is_press ? ButtonPress : ButtonRelease;
  button_event->x = location.x();
  button_event->y = location.y();
  button_event->button = button;
  button_event->state = state;
}

// Initializes the passed-in Xlib event.
void InitKeyEvent(Display* display,
                  XEvent* event,
                  bool is_press,
                  int keycode,
                  int state) {
  memset(event, 0, sizeof(*event));

  // We don't bother setting fields that the event code doesn't use, such as
  // x_root/y_root and window/root/subwindow.
  XKeyEvent* key_event = &(event->xkey);
  key_event->display = display;
  key_event->type = is_press ? KeyPress : KeyRelease;
  key_event->keycode = keycode;
  key_event->state = state;
}

// Returns true if the keysym maps to a KeyEvent with the EF_FUNCTION_KEY
// flag set, or the keysym maps to a zero key code.
bool HasFunctionKeyFlagSetIfSupported(Display* display, int x_keysym) {
  XEvent event;
  int x_keycode = XKeysymToKeycode(display, x_keysym);
  // Exclude keysyms for which the server has no corresponding keycode.
  if (x_keycode) {
    InitKeyEvent(display, &event, true, x_keycode, 0);
    ui::KeyEvent ui_key_event(&event);
    return (ui_key_event.flags() & ui::EF_FUNCTION_KEY);
  }
  return true;
}

}  // namespace

class EventsXTest : public testing::Test {
 public:
  EventsXTest() {}
  virtual ~EventsXTest() {}

  virtual void SetUp() override {
    DeviceDataManagerX11::CreateInstance();
    ui::TouchFactory::GetInstance()->ResetForTest();
  }
 private:
  DISALLOW_COPY_AND_ASSIGN(EventsXTest);
};

TEST_F(EventsXTest, ButtonEvents) {
  XEvent event;
  gfx::Point location(5, 10);
  gfx::Vector2d offset;

  InitButtonEvent(&event, true, location, 1, 0);
  EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(&event));
  EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, ui::EventFlagsFromNative(&event));
  EXPECT_EQ(location, ui::EventLocationFromNative(&event));

  InitButtonEvent(&event, true, location, 2, Button1Mask | ShiftMask);
  EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(&event));
  EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON |
                ui::EF_SHIFT_DOWN,
            ui::EventFlagsFromNative(&event));
  EXPECT_EQ(location, ui::EventLocationFromNative(&event));

  InitButtonEvent(&event, false, location, 3, 0);
  EXPECT_EQ(ui::ET_MOUSE_RELEASED, ui::EventTypeFromNative(&event));
  EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, ui::EventFlagsFromNative(&event));
  EXPECT_EQ(location, ui::EventLocationFromNative(&event));

  // Scroll up.
  InitButtonEvent(&event, true, location, 4, 0);
  EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromNative(&event));
  EXPECT_EQ(0, ui::EventFlagsFromNative(&event));
  EXPECT_EQ(location, ui::EventLocationFromNative(&event));
  offset = ui::GetMouseWheelOffset(&event);
  EXPECT_GT(offset.y(), 0);
  EXPECT_EQ(0, offset.x());

  // Scroll down.
  InitButtonEvent(&event, true, location, 5, 0);
  EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromNative(&event));
  EXPECT_EQ(0, ui::EventFlagsFromNative(&event));
  EXPECT_EQ(location, ui::EventLocationFromNative(&event));
  offset = ui::GetMouseWheelOffset(&event);
  EXPECT_LT(offset.y(), 0);
  EXPECT_EQ(0, offset.x());

  // Scroll left.
  InitButtonEvent(&event, true, location, 6, 0);
  EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromNative(&event));
  EXPECT_EQ(0, ui::EventFlagsFromNative(&event));
  EXPECT_EQ(location, ui::EventLocationFromNative(&event));
  offset = ui::GetMouseWheelOffset(&event);
  EXPECT_EQ(0, offset.y());
  EXPECT_GT(offset.x(), 0);

  // Scroll right.
  InitButtonEvent(&event, true, location, 7, 0);
  EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromNative(&event));
  EXPECT_EQ(0, ui::EventFlagsFromNative(&event));
  EXPECT_EQ(location, ui::EventLocationFromNative(&event));
  offset = ui::GetMouseWheelOffset(&event);
  EXPECT_EQ(0, offset.y());
  EXPECT_LT(offset.x(), 0);

  // TODO(derat): Test XInput code.
}

TEST_F(EventsXTest, AvoidExtraEventsOnWheelRelease) {
  XEvent event;
  gfx::Point location(5, 10);

  InitButtonEvent(&event, true, location, 4, 0);
  EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromNative(&event));

  // We should return ET_UNKNOWN for the release event instead of returning
  // ET_MOUSEWHEEL; otherwise we'll scroll twice for each scrollwheel step.
  InitButtonEvent(&event, false, location, 4, 0);
  EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromNative(&event));

  // TODO(derat): Test XInput code.
}

TEST_F(EventsXTest, EnterLeaveEvent) {
  XEvent event;
  event.xcrossing.type = EnterNotify;
  event.xcrossing.x = 10;
  event.xcrossing.y = 20;
  event.xcrossing.x_root = 110;
  event.xcrossing.y_root = 120;

  // Mouse enter events are converted to mouse move events to be consistent with
  // the way views handle mouse enter. See comments for EnterNotify case in
  // ui::EventTypeFromNative for more details.
  EXPECT_EQ(ui::ET_MOUSE_MOVED, ui::EventTypeFromNative(&event));
  EXPECT_EQ("10,20", ui::EventLocationFromNative(&event).ToString());
  EXPECT_EQ("110,120", ui::EventSystemLocationFromNative(&event).ToString());

  event.xcrossing.type = LeaveNotify;
  event.xcrossing.x = 30;
  event.xcrossing.y = 40;
  event.xcrossing.x_root = 230;
  event.xcrossing.y_root = 240;
  EXPECT_EQ(ui::ET_MOUSE_EXITED, ui::EventTypeFromNative(&event));
  EXPECT_EQ("30,40", ui::EventLocationFromNative(&event).ToString());
  EXPECT_EQ("230,240", ui::EventSystemLocationFromNative(&event).ToString());
}

TEST_F(EventsXTest, ClickCount) {
  XEvent event;
  gfx::Point location(5, 10);

  for (int i = 1; i <= 3; ++i) {
    InitButtonEvent(&event, true, location, 1, 0);
    {
      MouseEvent mouseev(&event);
      EXPECT_EQ(ui::ET_MOUSE_PRESSED, mouseev.type());
      EXPECT_EQ(i, mouseev.GetClickCount());
    }

    InitButtonEvent(&event, false, location, 1, 0);
    {
      MouseEvent mouseev(&event);
      EXPECT_EQ(ui::ET_MOUSE_RELEASED, mouseev.type());
      EXPECT_EQ(i, mouseev.GetClickCount());
    }
  }
}

#if defined(USE_XI2_MT)
TEST_F(EventsXTest, TouchEventBasic) {
  std::vector<unsigned int> devices;
  devices.push_back(0);
  ui::SetUpTouchDevicesForTest(devices);
  std::vector<Valuator> valuators;

  // Init touch begin with tracking id 5, touch id 0.
  valuators.push_back(Valuator(DeviceDataManagerX11::DT_TOUCH_MAJOR, 20));
  valuators.push_back(
      Valuator(DeviceDataManagerX11::DT_TOUCH_ORIENTATION, 0.3f));
  valuators.push_back(Valuator(DeviceDataManagerX11::DT_TOUCH_PRESSURE, 100));
  ui::ScopedXI2Event scoped_xevent;
  scoped_xevent.InitTouchEvent(
      0, XI_TouchBegin, 5, gfx::Point(10, 10), valuators);
  EXPECT_EQ(ui::ET_TOUCH_PRESSED, ui::EventTypeFromNative(scoped_xevent));
  EXPECT_EQ("10,10", ui::EventLocationFromNative(scoped_xevent).ToString());
  EXPECT_EQ(GetTouchId(scoped_xevent), 0);
  EXPECT_EQ(GetTouchRadiusX(scoped_xevent), 10);
  EXPECT_FLOAT_EQ(GetTouchAngle(scoped_xevent), 0.15f);
  EXPECT_FLOAT_EQ(GetTouchForce(scoped_xevent), 0.1f);

  // Touch update, with new orientation info.
  valuators.clear();
  valuators.push_back(
      Valuator(DeviceDataManagerX11::DT_TOUCH_ORIENTATION, 0.5f));
  scoped_xevent.InitTouchEvent(
      0, XI_TouchUpdate, 5, gfx::Point(20, 20), valuators);
  EXPECT_EQ(ui::ET_TOUCH_MOVED, ui::EventTypeFromNative(scoped_xevent));
  EXPECT_EQ("20,20", ui::EventLocationFromNative(scoped_xevent).ToString());
  EXPECT_EQ(GetTouchId(scoped_xevent), 0);
  EXPECT_EQ(GetTouchRadiusX(scoped_xevent), 10);
  EXPECT_FLOAT_EQ(GetTouchAngle(scoped_xevent), 0.25f);
  EXPECT_FLOAT_EQ(GetTouchForce(scoped_xevent), 0.1f);

  // Another touch with tracking id 6, touch id 1.
  valuators.clear();
  valuators.push_back(Valuator(DeviceDataManagerX11::DT_TOUCH_MAJOR, 100));
  valuators.push_back(Valuator(
      DeviceDataManagerX11::DT_TOUCH_ORIENTATION, 0.9f));
  valuators.push_back(Valuator(DeviceDataManagerX11::DT_TOUCH_PRESSURE, 500));
  scoped_xevent.InitTouchEvent(
      0, XI_TouchBegin, 6, gfx::Point(200, 200), valuators);
  EXPECT_EQ(ui::ET_TOUCH_PRESSED, ui::EventTypeFromNative(scoped_xevent));
  EXPECT_EQ("200,200", ui::EventLocationFromNative(scoped_xevent).ToString());
  EXPECT_EQ(GetTouchId(scoped_xevent), 1);
  EXPECT_EQ(GetTouchRadiusX(scoped_xevent), 50);
  EXPECT_FLOAT_EQ(GetTouchAngle(scoped_xevent), 0.45f);
  EXPECT_FLOAT_EQ(GetTouchForce(scoped_xevent), 0.5f);

  // Touch with tracking id 5 should have old radius/angle value and new pressue
  // value.
  valuators.clear();
  valuators.push_back(Valuator(DeviceDataManagerX11::DT_TOUCH_PRESSURE, 50));
  scoped_xevent.InitTouchEvent(
      0, XI_TouchEnd, 5, gfx::Point(30, 30), valuators);
  EXPECT_EQ(ui::ET_TOUCH_RELEASED, ui::EventTypeFromNative(scoped_xevent));
  EXPECT_EQ("30,30", ui::EventLocationFromNative(scoped_xevent).ToString());
  EXPECT_EQ(GetTouchId(scoped_xevent), 0);
  EXPECT_EQ(GetTouchRadiusX(scoped_xevent), 10);
  EXPECT_FLOAT_EQ(GetTouchAngle(scoped_xevent), 0.25f);
  EXPECT_FLOAT_EQ(GetTouchForce(scoped_xevent), 0.05f);

  // Touch with tracking id 6 should have old angle/pressure value and new
  // radius value.
  valuators.clear();
  valuators.push_back(Valuator(DeviceDataManagerX11::DT_TOUCH_MAJOR, 50));
  scoped_xevent.InitTouchEvent(
      0, XI_TouchEnd, 6, gfx::Point(200, 200), valuators);
  EXPECT_EQ(ui::ET_TOUCH_RELEASED, ui::EventTypeFromNative(scoped_xevent));
  EXPECT_EQ("200,200", ui::EventLocationFromNative(scoped_xevent).ToString());
  EXPECT_EQ(GetTouchId(scoped_xevent), 1);
  EXPECT_EQ(GetTouchRadiusX(scoped_xevent), 25);
  EXPECT_FLOAT_EQ(GetTouchAngle(scoped_xevent), 0.45f);
  EXPECT_FLOAT_EQ(GetTouchForce(scoped_xevent), 0.5f);
}

int GetTouchIdForTrackingId(uint32 tracking_id) {
  int slot = 0;
  bool success =
      TouchFactory::GetInstance()->QuerySlotForTrackingID(tracking_id, &slot);
  if (success)
    return slot;
  return -1;
}

TEST_F(EventsXTest, TouchEventIdRefcounting) {
  std::vector<unsigned int> devices;
  devices.push_back(0);
  ui::SetUpTouchDevicesForTest(devices);
  std::vector<Valuator> valuators;

  const int kTrackingId0 = 5;
  const int kTrackingId1 = 7;

  // Increment ref count once for first touch.
  ui::ScopedXI2Event xpress0;
  xpress0.InitTouchEvent(
      0, XI_TouchBegin, kTrackingId0, gfx::Point(10, 10), valuators);
  scoped_ptr<ui::TouchEvent> upress0(new ui::TouchEvent(xpress0));
  EXPECT_EQ(0, GetTouchIdForTrackingId(kTrackingId0));

  // Increment ref count 4 times for second touch.
  ui::ScopedXI2Event xpress1;
  xpress1.InitTouchEvent(
      0, XI_TouchBegin, kTrackingId1, gfx::Point(20, 20), valuators);

  for (int i = 0; i < 4; ++i) {
    ui::TouchEvent upress1(xpress1);
    EXPECT_EQ(1, GetTouchIdForTrackingId(kTrackingId1));
  }

  ui::ScopedXI2Event xrelease1;
  xrelease1.InitTouchEvent(
      0, XI_TouchEnd, kTrackingId1, gfx::Point(10, 10), valuators);

  // Decrement ref count 3 times for second touch.
  for (int i = 0; i < 3; ++i) {
    ui::TouchEvent urelease1(xrelease1);
    EXPECT_EQ(1, GetTouchIdForTrackingId(kTrackingId1));
  }

  // This should clear the touch id of the second touch.
  scoped_ptr<ui::TouchEvent> urelease1(new ui::TouchEvent(xrelease1));
  urelease1.reset();
  EXPECT_EQ(-1, GetTouchIdForTrackingId(kTrackingId1));

  // This should clear the touch id of the first touch.
  ui::ScopedXI2Event xrelease0;
  xrelease0.InitTouchEvent(
      0, XI_TouchEnd, kTrackingId0, gfx::Point(10, 10), valuators);
  scoped_ptr<ui::TouchEvent> urelease0(new ui::TouchEvent(xrelease0));
  urelease0.reset();
  EXPECT_EQ(-1, GetTouchIdForTrackingId(kTrackingId0));
}
#endif

TEST_F(EventsXTest, NumpadKeyEvents) {
  XEvent event;
  Display* display = gfx::GetXDisplay();

  struct {
    bool is_numpad_key;
    int x_keysym;
  } keys[] = {
    // XK_KP_Space and XK_KP_Equal are the extrema in the conventional
    // keysymdef.h numbering.
    { true,  XK_KP_Space },
    { true,  XK_KP_Equal },
    // Other numpad keysyms. (This is actually exhaustive in the current list.)
    { true,  XK_KP_Tab },
    { true,  XK_KP_Enter },
    { true,  XK_KP_F1 },
    { true,  XK_KP_F2 },
    { true,  XK_KP_F3 },
    { true,  XK_KP_F4 },
    { true,  XK_KP_Home },
    { true,  XK_KP_Left },
    { true,  XK_KP_Up },
    { true,  XK_KP_Right },
    { true,  XK_KP_Down },
    { true,  XK_KP_Prior },
    { true,  XK_KP_Page_Up },
    { true,  XK_KP_Next },
    { true,  XK_KP_Page_Down },
    { true,  XK_KP_End },
    { true,  XK_KP_Begin },
    { true,  XK_KP_Insert },
    { true,  XK_KP_Delete },
    { true,  XK_KP_Multiply },
    { true,  XK_KP_Add },
    { true,  XK_KP_Separator },
    { true,  XK_KP_Subtract },
    { true,  XK_KP_Decimal },
    { true,  XK_KP_Divide },
    { true,  XK_KP_0 },
    { true,  XK_KP_1 },
    { true,  XK_KP_2 },
    { true,  XK_KP_3 },
    { true,  XK_KP_4 },
    { true,  XK_KP_5 },
    { true,  XK_KP_6 },
    { true,  XK_KP_7 },
    { true,  XK_KP_8 },
    { true,  XK_KP_9 },
    // Largest keysym preceding XK_KP_Space.
    { false, XK_Num_Lock },
    // Smallest keysym following XK_KP_Equal.
    { false, XK_F1 },
    // Non-numpad analogues of numpad keysyms.
    { false, XK_Tab },
    { false, XK_Return },
    { false, XK_F1 },
    { false, XK_F2 },
    { false, XK_F3 },
    { false, XK_F4 },
    { false, XK_Home },
    { false, XK_Left },
    { false, XK_Up },
    { false, XK_Right },
    { false, XK_Down },
    { false, XK_Prior },
    { false, XK_Page_Up },
    { false, XK_Next },
    { false, XK_Page_Down },
    { false, XK_End },
    { false, XK_Insert },
    { false, XK_Delete },
    { false, XK_multiply },
    { false, XK_plus },
    { false, XK_minus },
    { false, XK_period },
    { false, XK_slash },
    { false, XK_0 },
    { false, XK_1 },
    { false, XK_2 },
    { false, XK_3 },
    { false, XK_4 },
    { false, XK_5 },
    { false, XK_6 },
    { false, XK_7 },
    { false, XK_8 },
    { false, XK_9 },
    // Miscellaneous other keysyms.
    { false, XK_BackSpace },
    { false, XK_Scroll_Lock },
    { false, XK_Multi_key },
    { false, XK_Select },
    { false, XK_Num_Lock },
    { false, XK_Shift_L },
    { false, XK_space },
    { false, XK_A },
  };

  for (size_t k = 0; k < arraysize(keys); ++k) {
    int x_keycode = XKeysymToKeycode(display, keys[k].x_keysym);
    // Exclude keysyms for which the server has no corresponding keycode.
    if (x_keycode) {
      InitKeyEvent(display, &event, true, x_keycode, 0);
      // int keysym = XLookupKeysym(&event.xkey, 0);
      // if (keysym) {
      ui::KeyEvent ui_key_event(&event);
      EXPECT_EQ(keys[k].is_numpad_key ? ui::EF_NUMPAD_KEY : 0,
                ui_key_event.flags() & ui::EF_NUMPAD_KEY);
    }
  }
}

TEST_F(EventsXTest, FunctionKeyEvents) {
  Display* display = gfx::GetXDisplay();

  // Min  function key code minus 1.
  EXPECT_FALSE(HasFunctionKeyFlagSetIfSupported(display, XK_F1 - 1));
  // All function keys.
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F1));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F2));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F3));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F4));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F5));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F6));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F7));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F8));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F9));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F10));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F11));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F12));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F13));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F14));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F15));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F16));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F17));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F18));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F19));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F20));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F21));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F22));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F23));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F24));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F25));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F26));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F27));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F28));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F29));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F30));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F31));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F32));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F33));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F34));
  EXPECT_TRUE(HasFunctionKeyFlagSetIfSupported(display, XK_F35));
  // Max function key code plus 1.
  EXPECT_FALSE(HasFunctionKeyFlagSetIfSupported(display, XK_F35 + 1));
}

#if defined(USE_XI2_MT)
// Verifies that the type of events from a disabled keyboard is ET_UNKNOWN, but
// that an exception list of keys can still be processed.
TEST_F(EventsXTest, DisableKeyboard) {
  DeviceDataManagerX11* device_data_manager =
      static_cast<DeviceDataManagerX11*>(
          DeviceDataManager::GetInstance());
  unsigned int blocked_device_id = 1;
  unsigned int other_device_id = 2;
  unsigned int master_device_id = 3;
  device_data_manager->DisableDevice(blocked_device_id);

  scoped_ptr<std::set<KeyboardCode> > excepted_keys(new std::set<KeyboardCode>);
  excepted_keys->insert(VKEY_B);
  device_data_manager->SetDisabledKeyboardAllowedKeys(excepted_keys.Pass());

  ScopedXI2Event xev;
  // A is not allowed on the blocked keyboard, and should return ET_UNKNOWN.
  xev.InitGenericKeyEvent(master_device_id,
                          blocked_device_id,
                          ui::ET_KEY_PRESSED,
                          ui::VKEY_A,
                          0);
  EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromNative(xev));

  // The B key is allowed as an exception, and should return KEY_PRESSED.
  xev.InitGenericKeyEvent(master_device_id,
                          blocked_device_id,
                          ui::ET_KEY_PRESSED,
                          ui::VKEY_B,
                          0);
  EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromNative(xev));

  // Both A and B are allowed on an unblocked keyboard device.
  xev.InitGenericKeyEvent(master_device_id,
                          other_device_id,
                          ui::ET_KEY_PRESSED,
                          ui::VKEY_A,
                          0);
  EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromNative(xev));
  xev.InitGenericKeyEvent(master_device_id,
                          other_device_id,
                          ui::ET_KEY_PRESSED,
                          ui::VKEY_B,
                          0);
  EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromNative(xev));

  device_data_manager->EnableDevice(blocked_device_id);
  device_data_manager->SetDisabledKeyboardAllowedKeys(
      scoped_ptr<std::set<KeyboardCode> >());

  // A key returns KEY_PRESSED as per usual now that keyboard was re-enabled.
  xev.InitGenericKeyEvent(master_device_id,
                          blocked_device_id,
                          ui::ET_KEY_PRESSED,
                          ui::VKEY_A,
                          0);
  EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromNative(xev));
}

// Verifies that the type of events from a disabled mouse is ET_UNKNOWN.
TEST_F(EventsXTest, DisableMouse) {
  DeviceDataManagerX11* device_data_manager =
      static_cast<DeviceDataManagerX11*>(
          DeviceDataManager::GetInstance());
  unsigned int blocked_device_id = 1;
  unsigned int other_device_id = 2;
  std::vector<unsigned int> device_list;
  device_list.push_back(blocked_device_id);
  device_list.push_back(other_device_id);
  TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);

  device_data_manager->DisableDevice(blocked_device_id);

  ScopedXI2Event xev;
  xev.InitGenericButtonEvent(blocked_device_id, ET_MOUSE_PRESSED, gfx::Point(),
      EF_LEFT_MOUSE_BUTTON);
  EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromNative(xev));

  xev.InitGenericButtonEvent(other_device_id, ET_MOUSE_PRESSED, gfx::Point(),
      EF_LEFT_MOUSE_BUTTON);
  EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(xev));

  device_data_manager->EnableDevice(blocked_device_id);

  xev.InitGenericButtonEvent(blocked_device_id, ET_MOUSE_PRESSED, gfx::Point(),
      EF_LEFT_MOUSE_BUTTON);
  EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(xev));
}
#endif  // defined(USE_XI2_MT)

#if !defined(OS_CHROMEOS)
TEST_F(EventsXTest, ImeFabricatedKeyEvents) {
  Display* display = gfx::GetXDisplay();

  unsigned int state_to_be_fabricated[] = {
    0, ShiftMask, LockMask, ShiftMask | LockMask,
  };
  for (size_t i = 0; i < arraysize(state_to_be_fabricated); ++i) {
    unsigned int state = state_to_be_fabricated[i];
    for (int is_char = 0; is_char < 2; ++is_char) {
      XEvent x_event;
      InitKeyEvent(display, &x_event, true, 0, state);
      ui::KeyEvent key_event(&x_event);
      if (is_char) {
        KeyEventTestApi test_event(&key_event);
        test_event.set_is_char(true);
      }
      EXPECT_TRUE(key_event.flags() & ui::EF_IME_FABRICATED_KEY);
    }
  }

  unsigned int state_to_be_not_fabricated[] = {
    ControlMask, Mod1Mask, Mod2Mask, ShiftMask | ControlMask,
  };
  for (size_t i = 0; i < arraysize(state_to_be_not_fabricated); ++i) {
    unsigned int state = state_to_be_not_fabricated[i];
    for (int is_char = 0; is_char < 2; ++is_char) {
      XEvent x_event;
      InitKeyEvent(display, &x_event, true, 0, state);
      ui::KeyEvent key_event(&x_event);
      if (is_char) {
        KeyEventTestApi test_event(&key_event);
        test_event.set_is_char(true);
      }
      EXPECT_FALSE(key_event.flags() & ui::EF_IME_FABRICATED_KEY);
    }
  }
}
#endif

}  // namespace ui
