// 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_UNSAFE(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_UNSAFE(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_UNSAFE(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
