[PATCH] Add regression test for button press event button state for touch begin

Chase Douglas chase.douglas at canonical.com
Tue Jul 3 17:35:09 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>
---
The original bug report is likely against X core, but we don't have a
nice suite for X core input events yet. I've at least provided a test
here for XI 2.x, which hopefully is validation enough that the bug is
fixed.

This is meant to be applied on top of Peter's integration-testing branch.
Currently, the top commit ID is:
092d98c17999fbf696e4db8f1d85e79052c83be5.

 test/integration/xi2.cpp |   97 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 97 insertions(+)

diff --git a/test/integration/xi2.cpp b/test/integration/xi2.cpp
index 1cbbe05..b9451b2 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,99 @@ TEST_P(XInput2Test, DisableDeviceEndTouches)
                                    XI_TouchEnd));
 }
 
+/**
+ * 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, TouchBeginButtonState)
+{
+    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> device;
+    try {
+      device = std::auto_ptr<xorg::testing::evemu::Device>(
+          new xorg::testing::evemu::Device(
+              TEST_ROOT_DIR "recordings/ntrig_dell_xt2/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)"));
+
+    device->Play(
+        TEST_ROOT_DIR "recordings/ntrig_dell_xt2/touch_1_begin.record");
+    device->Play(
+        TEST_ROOT_DIR "recordings/ntrig_dell_xt2/touch_1_end.record");
+
+    /* We expect the first button to be unset for the motion and press events,
+     * but set for the release event. */
+    std::list<std::pair<int, bool> > expect;
+    expect.push_back(std::make_pair(XI_Motion, false));
+    expect.push_back(std::make_pair(XI_ButtonPress, false));
+    expect.push_back(std::make_pair(XI_ButtonRelease, true));
+
+    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);
+    }
+}
+
 INSTANTIATE_TEST_CASE_P(, XInput2Test, ::testing::Range(0, 3));
-- 
1.7.10.4



More information about the xorg-devel mailing list