diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2013-04-26 14:08:50 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2013-04-30 10:37:56 +1000 |
commit | 5accb6285889846aebb974d17ce4297c4777ffd4 (patch) | |
tree | 3c734915d3e5ee138e1f4fbf707c656bdcb5f8fd | |
parent | 0aa152792d7054c7dcce588b1553ade2d9925cda (diff) |
server/input: add smooth scrolling button map tests
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r-- | tests/server/input.cpp | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/tests/server/input.cpp b/tests/server/input.cpp index 1065c9e..5994bcb 100644 --- a/tests/server/input.cpp +++ b/tests/server/input.cpp @@ -33,6 +33,7 @@ #include <X11/Xatom.h> #include <X11/extensions/XInput2.h> +#include <X11/extensions/XInput.h> #include "xit-server-input-test.h" #include "xit-event.h" @@ -69,6 +70,241 @@ public: } }; +#ifdef HAVE_XI22 +enum scoll_direction { + VSCROLL_UP = 4, + VSCROLL_DOWN = 5, + HSCROLL_LEFT = 6, + HSCROLL_RIGHT = 7, +}; + +class SmoothScrollingTest : public PointerMotionTest, + public ::testing::WithParamInterface<enum scoll_direction> { +public: + virtual int GetScrollIncrement(::Display *dpy, int deviceid, int type) { + int increment = 0; + int ndevices; + + XIDeviceInfo *info = XIQueryDevice(dpy, deviceid, &ndevices); + + for (int i = 0; i < info->num_classes; i++) { + if (info->classes[i]->type != XIScrollClass) + continue; + + XIScrollClassInfo *s = reinterpret_cast<XIScrollClassInfo*>(info->classes[i]); + if (s->scroll_type == type) { + increment = s->increment; + break; + } + } + + XIFreeDeviceInfo(info); + return increment; + } + + virtual void AssertEmulatedButtonEvent(::Display *dpy, int button) { + ASSERT_EVENT(XIDeviceEvent, press, dpy, GenericEvent, xi2_opcode, XI_ButtonPress); + ASSERT_EVENT(XIDeviceEvent, release, dpy, GenericEvent, xi2_opcode, XI_ButtonRelease); + ASSERT_TRUE(press->flags & XIPointerEmulated); + ASSERT_TRUE(release->flags & XIPointerEmulated); + ASSERT_EQ(press->detail, button); + ASSERT_EQ(release->detail, button); + } + + virtual void CheckMotionEvent(XIDeviceEvent *motion) { + ASSERT_FALSE(motion->flags & XIPointerEmulated); + ASSERT_GE(motion->valuators.mask_len, XIMaskLen(3)); + /* expect x/y to be unset */ + ASSERT_FALSE(XIMaskIsSet(motion->valuators.mask, 0)); + ASSERT_FALSE(XIMaskIsSet(motion->valuators.mask, 1)); + } +}; + +TEST_P(SmoothScrollingTest, SmoothScrolling) +{ + XORG_TESTCASE("Create a pointer device.\n" + "Generate smooth scroll events.\n" + "Verify button and motion events are sent as expected\n"); + + ::Display *dpy = Display(); + + int which = GetParam(); + + int deviceid; + ASSERT_EQ(FindInputDeviceByName(dpy, "--device--", &deviceid), 1); + + int button; + int axis; + int direction; + int increment; + + switch(which) { + case VSCROLL_UP: + button = 4; + axis = REL_WHEEL; + direction = 1; + increment = GetScrollIncrement(dpy, deviceid, XIScrollTypeVertical); + break; + case VSCROLL_DOWN: + button = 5; + axis = REL_WHEEL; + direction = -1; + increment = GetScrollIncrement(dpy, deviceid, XIScrollTypeVertical); + break; + case HSCROLL_LEFT: + button = 6; + axis = REL_HWHEEL; + direction = -1; + increment = GetScrollIncrement(dpy, deviceid, XIScrollTypeHorizontal); + break; + case HSCROLL_RIGHT: + button = 7; + axis = REL_HWHEEL; + direction = 1; + increment = GetScrollIncrement(dpy, deviceid, XIScrollTypeHorizontal); + break; + } + + SelectXI2Events(dpy, VIRTUAL_CORE_POINTER_ID, DefaultRootWindow(dpy), + XI_ButtonPress, XI_ButtonRelease, XI_Motion, -1); + + dev->PlayOne(EV_REL, axis, direction, true); + dev->PlayOne(EV_REL, axis, direction, true); + + ASSERT_EVENT(XIDeviceEvent, motion1, dpy, GenericEvent, xi2_opcode, XI_Motion); + CheckMotionEvent(motion1); + AssertEmulatedButtonEvent(dpy, button); + + ASSERT_EVENT(XIDeviceEvent, motion2, dpy, GenericEvent, xi2_opcode, XI_Motion); + CheckMotionEvent(motion2); + AssertEmulatedButtonEvent(dpy, button); + + + /* expect x/y to be unset */ + if (button <= 5) { + ASSERT_TRUE(XIMaskIsSet(motion1->valuators.mask, 3)); + ASSERT_TRUE(XIMaskIsSet(motion2->valuators.mask, 3)); + } else { + ASSERT_TRUE(XIMaskIsSet(motion1->valuators.mask, 2)); + ASSERT_TRUE(XIMaskIsSet(motion2->valuators.mask, 2)); + } + + int delta = motion2->valuators.values[0] - motion1->valuators.values[0]; + switch(which) { + case VSCROLL_UP: + case HSCROLL_LEFT: + ASSERT_EQ(delta, -increment); + break; + case VSCROLL_DOWN: + case HSCROLL_RIGHT: + ASSERT_EQ(delta, increment); + break; + } +} + +TEST_P(SmoothScrollingTest, SmoothScrollingButtonInverted) +{ + XORG_TESTCASE("Create a pointer device.\n" + "Invert hscroll and vscroll mapping\n" + "Generate smooth scroll events.\n" + "Verify button mapping is reflected in smooth scrolling events\n"); + + ::Display *dpy = Display(); + + int which = GetParam(); + + int deviceid; + ASSERT_EQ(FindInputDeviceByName(dpy, "--device--", &deviceid), 1); + + XDevice *d = XOpenDevice(dpy, deviceid); + ASSERT_TRUE(d); + + unsigned char map[32]; + int nmap = 32; + XGetDeviceButtonMapping(dpy, d, map, nmap); + map[3] = 5; + map[4] = 4; + map[5] = 7; + map[6] = 6; + XSetDeviceButtonMapping(dpy, d, map, nmap); + XCloseDevice(dpy, d); + + int button; + int axis; + int direction; + int increment; + + switch(which) { + case VSCROLL_UP: + button = 5; + axis = REL_WHEEL; + direction = 1; + increment = GetScrollIncrement(dpy, deviceid, XIScrollTypeVertical); + break; + case VSCROLL_DOWN: + button = 4; + axis = REL_WHEEL; + direction = -1; + increment = GetScrollIncrement(dpy, deviceid, XIScrollTypeVertical); + break; + case HSCROLL_LEFT: + button = 7; + axis = REL_HWHEEL; + direction = -1; + increment = GetScrollIncrement(dpy, deviceid, XIScrollTypeHorizontal); + break; + case HSCROLL_RIGHT: + button = 6; + axis = REL_HWHEEL; + direction = 1; + increment = GetScrollIncrement(dpy, deviceid, XIScrollTypeHorizontal); + break; + } + + SelectXI2Events(dpy, VIRTUAL_CORE_POINTER_ID, DefaultRootWindow(dpy), + XI_ButtonPress, XI_ButtonRelease, XI_Motion, -1); + + dev->PlayOne(EV_REL, axis, direction, true); + dev->PlayOne(EV_REL, axis, direction, true); + + ASSERT_EVENT(XIDeviceEvent, motion1, dpy, GenericEvent, xi2_opcode, XI_Motion); + CheckMotionEvent(motion1); + AssertEmulatedButtonEvent(dpy, button); + + ASSERT_EVENT(XIDeviceEvent, motion2, dpy, GenericEvent, xi2_opcode, XI_Motion); + CheckMotionEvent(motion2); + AssertEmulatedButtonEvent(dpy, button); + + + /* expect x/y to be unset */ + if (button <= 5) + ASSERT_TRUE(XIMaskIsSet(motion1->valuators.mask, 3)); + else + ASSERT_TRUE(XIMaskIsSet(motion1->valuators.mask, 2)); + + if (button <= 5) + ASSERT_TRUE(XIMaskIsSet(motion2->valuators.mask, 3)); + else + ASSERT_TRUE(XIMaskIsSet(motion2->valuators.mask, 2)); + + int delta = motion2->valuators.values[0] - motion1->valuators.values[0]; + switch(which) { + case VSCROLL_UP: + case HSCROLL_LEFT: + ASSERT_EQ(delta, -increment); + break; + case VSCROLL_DOWN: + case HSCROLL_RIGHT: + ASSERT_EQ(delta, increment); + break; + } +} + +INSTANTIATE_TEST_CASE_P(, SmoothScrollingTest, + ::testing::Values(VSCROLL_UP, VSCROLL_DOWN, HSCROLL_LEFT, HSCROLL_RIGHT)); +#endif + + enum device_type { MOUSE, TABLET, TOUCHPAD }; |