[PATCH v2] Add regression test for button event state for touch emulation

Chase Douglas chase.douglas at canonical.com
Mon Jul 9 17:13:15 PDT 2012


When a touch begin is pointer emulated, the initial motion and button
press events should not have the first button set in the button mask.
The button mask represents the state of the buttons *before* the event.

Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
---
 .../recordings/intellimouse/device.prop            |   24 ++++
 .../recordings/intellimouse/move_right.record      |    2 +
 test/integration/xi2.cpp                           |  132 ++++++++++++++++++++
 3 files changed, 158 insertions(+)
 create mode 100644 test/integration/recordings/intellimouse/device.prop
 create mode 100644 test/integration/recordings/intellimouse/move_right.record

diff --git a/test/integration/recordings/intellimouse/device.prop b/test/integration/recordings/intellimouse/device.prop
new file mode 100644
index 0000000..9fa8b75
--- /dev/null
+++ b/test/integration/recordings/intellimouse/device.prop
@@ -0,0 +1,24 @@
+N: Microsoft Microsoft IntelliMouse® Optical (Virtual Test Device)
+I: 0003 045e 0029 0100
+P: 00 00 00 00 00 00 00 00
+B: 00 17 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 1f 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 02 03 01 00 00 00 00 00 00
+B: 03 00 00 00 00 00 00 00 00
+B: 04 10 00 00 00 00 00 00 00
+B: 05 00 00 00 00 00 00 00 00
+B: 11 00 00 00 00 00 00 00 00
+B: 12 00 00 00 00 00 00 00 00
+B: 15 00 00 00 00 00 00 00 00
+B: 15 00 00 00 00 00 00 00 00
diff --git a/test/integration/recordings/intellimouse/move_right.record b/test/integration/recordings/intellimouse/move_right.record
new file mode 100644
index 0000000..944ce4a
--- /dev/null
+++ b/test/integration/recordings/intellimouse/move_right.record
@@ -0,0 +1,2 @@
+E: 1327542640.244087 0002 0000 1
+E: 1327542640.244088 0000 0000 0
diff --git a/test/integration/xi2.cpp b/test/integration/xi2.cpp
index 1cbbe05..f2af071 100644
--- a/test/integration/xi2.cpp
+++ b/test/integration/xi2.cpp
@@ -1,4 +1,6 @@
+#include <list>
 #include <stdexcept>
+#include <sstream>
 
 #include <xorg/gtest/xorg-gtest.h>
 
@@ -353,4 +355,134 @@ TEST_P(XInput2Test, DisableDeviceEndTouches)
                                    XI_TouchEnd));
 }
 
+namespace {
+
+/**
+ * Helper function for TouchEmulatedButtonState test
+ */
+void CheckButtonState(::Display* display, int xi2_opcode,
+                      std::list<std::pair<int, bool> >& expect)
+{
+    for (std::list<std::pair<int, bool> >::iterator it = expect.begin();
+         it != expect.end();
+         ++it) {
+        ASSERT_TRUE(WaitForEventOfType(display, GenericEvent, xi2_opcode,
+                                       it->first));
+
+        XEvent event;
+        ASSERT_EQ(Success, XNextEvent(display, &event));
+
+        XGenericEventCookie *xcookie = &event.xcookie;
+        ASSERT_TRUE(XGetEventData(display, xcookie));
+
+        XIDeviceEvent *device_event =
+            reinterpret_cast<XIDeviceEvent*>(xcookie->data);
+
+        std::stringstream msg;
+        msg << "Failed for ";
+        switch (it->first) {
+        case XI_Motion:
+            msg << "XI_Motion ";
+            break; 
+        case XI_ButtonPress:
+            msg << "XI_ButtonPress ";
+            break; 
+        case XI_ButtonRelease:
+            msg << "XI_ButtonRelease ";
+            break; 
+        }
+        msg << "event";
+
+        EXPECT_EQ(it->second,
+                  static_cast<bool>(XIMaskIsSet(device_event->buttons.mask, 1)))
+            << msg.str();
+
+        XFreeEventData(display, xcookie);
+    }
+}
+
+}
+
+/**
+ * The button state should represent the logical state of the buttons before the
+ * event. Thus, a button press should not have any button state under normal
+ * circumstances. This holds for touch events emulated as motion and button
+ * events as well.
+ */
+TEST_P(XInput2Test, TouchEmulatedButtonState)
+{
+    XIEventMask mask;
+    mask.deviceid = XIAllDevices;
+    mask.mask_len = XIMaskLen(XI_HierarchyChanged);
+    mask.mask = reinterpret_cast<unsigned char*>(calloc(mask.mask_len, 1));
+    XISetMask(mask.mask, XI_HierarchyChanged);
+
+    ASSERT_EQ(Success,
+              XISelectEvents(Display(), DefaultRootWindow(Display()), &mask,
+                             1));
+
+    mask.deviceid = XIAllMasterDevices;
+    XIClearMask(mask.mask, XI_HierarchyChanged);
+    XISetMask(mask.mask, XI_ButtonPress);
+    XISetMask(mask.mask, XI_ButtonRelease);
+    XISetMask(mask.mask, XI_Motion);
+
+    ASSERT_EQ(Success,
+              XISelectEvents(Display(), DefaultRootWindow(Display()), &mask,
+                             1));
+
+    free(mask.mask);
+
+    XFlush(Display());
+
+    std::auto_ptr<xorg::testing::evemu::Device> touchscreen;
+    std::auto_ptr<xorg::testing::evemu::Device> mouse;
+    try {
+      touchscreen = std::auto_ptr<xorg::testing::evemu::Device>(
+          new xorg::testing::evemu::Device(
+              TEST_ROOT_DIR "recordings/ntrig_dell_xt2/device.prop"));
+      mouse = std::auto_ptr<xorg::testing::evemu::Device>(
+          new xorg::testing::evemu::Device(
+              TEST_ROOT_DIR "recordings/intellimouse/device.prop"));
+    } catch (std::runtime_error &error) {
+      std::cerr << "Failed to create evemu device, skipping test.\n";
+      return;
+    }
+
+    ASSERT_TRUE(WaitForDevice(Display(),
+                              "N-Trig MultiTouch (Virtual Test Device)"));
+    ASSERT_TRUE(
+        WaitForDevice(Display(),
+            "Microsoft Microsoft IntelliMouse® Optical (Virtual Test Device)"));
+
+    std::list<std::pair<int, bool> > expect;
+
+    SCOPED_TRACE("Testing touch begin");
+    touchscreen->Play(
+        TEST_ROOT_DIR "recordings/ntrig_dell_xt2/touch_1_begin.record");
+    expect.push_back(std::make_pair(XI_Motion, false));
+    expect.push_back(std::make_pair(XI_ButtonPress, false));
+    CheckButtonState(Display(), xi2_opcode_, expect);
+    expect.clear();
+
+    SCOPED_TRACE("Testing mouse motion while touch is active");
+    mouse->Play(TEST_ROOT_DIR "recordings/intellimouse/move_right.record");
+    expect.push_back(std::make_pair(XI_Motion, true));
+    CheckButtonState(Display(), xi2_opcode_, expect);
+    expect.clear();
+
+    SCOPED_TRACE("Testing touch end");
+    touchscreen->Play(
+        TEST_ROOT_DIR "recordings/ntrig_dell_xt2/touch_1_end.record");
+    expect.push_back(std::make_pair(XI_ButtonRelease, true));
+    CheckButtonState(Display(), xi2_opcode_, expect);
+    expect.clear();
+
+    SCOPED_TRACE("Testing mouse motion after touch has ended");
+    mouse->Play(TEST_ROOT_DIR "recordings/intellimouse/move_right.record");
+    expect.push_back(std::make_pair(XI_Motion, false));
+    CheckButtonState(Display(), xi2_opcode_, expect);
+    expect.clear();
+}
+
 INSTANTIATE_TEST_CASE_P(, XInput2Test, ::testing::Range(0, 3));
-- 
1.7.10.4



More information about the xorg-devel mailing list