[PATCH 8/8] Test: Input: Add touch tests

Daniel Stone daniel at fooishbar.org
Wed Jan 19 15:11:50 PST 2011


Add tests for:
    * checking basic functionality of BeginTouchPoint,
      FindTouchPoint*, and EndTouchPoint
    * ensuring all touch event types match each other in
      GrabMatchesSecond
    * ensuring all touch events are selected together, or not at all, in
      XISelectEvents (this test authored by Chase Douglas)
    * ensuring EventToXI2 is predictable between runs
    * validating TouchBegin, TouchMotion, TouchMotionUnowned, TouchEnd,
      and TouchOwnership protocol conversion

Signed-off-by: Daniel Stone <daniel at fooishbar.org>
Reviewed-by: Chase Douglas <chase.douglas at canonical.com>
---

v5: Added tests for TouchMotionUnowned and TouchOwnership as well.
    Make BeginTouchPoint/FindTouchPoint*/EndTouchPoint tests slightly more
    comprehensive.

 test/input.c                       |  169 +++++++++++++++++++++++++++++++++++-
 test/xi2/protocol-eventconvert.c   |  114 ++++++++++++++++++++++++-
 test/xi2/protocol-xiselectevents.c |   64 ++++++++++++++
 3 files changed, 345 insertions(+), 2 deletions(-)

diff --git a/test/input.c b/test/input.c
index 879e14f..21b4c8d 100644
--- a/test/input.c
+++ b/test/input.c
@@ -277,6 +277,11 @@ static void dix_event_to_core_conversion(void)
     dix_event_to_core_fail(ET_ProximityOut + 1, BadImplementation);
     dix_event_to_core_fail(ET_ProximityIn, BadMatch);
     dix_event_to_core_fail(ET_ProximityOut, BadMatch);
+    dix_event_to_core_fail(ET_TouchBegin, BadMatch);
+    dix_event_to_core_fail(ET_TouchMotion, BadMatch);
+    dix_event_to_core_fail(ET_TouchMotionUnowned, BadMatch);
+    dix_event_to_core_fail(ET_TouchOwnership, BadMatch);
+    dix_event_to_core_fail(ET_TouchEnd, BadMatch);
 
     dix_event_to_core(ET_KeyPress);
     dix_event_to_core(ET_KeyRelease);
@@ -285,6 +290,34 @@ static void dix_event_to_core_conversion(void)
     dix_event_to_core(ET_Motion);
 }
 
+static void dix_event_to_xi2_conversion(void)
+{
+    DeviceEvent ev;
+    xXIDeviceEvent *xi2, *xi2_flags;
+    int rc;
+
+    memset(&ev, 0, sizeof(ev));
+
+    ev.header   = 0xFF;
+    ev.length   = sizeof(DeviceEvent);
+    ev.type     = ET_TouchBegin;
+
+    rc          = EventToXI2((InternalEvent*)&ev, (xEvent**)&xi2);
+    g_assert(rc == Success);
+    g_assert(xi2->type == GenericEvent);
+    g_assert(xi2->evtype == XI_TouchBegin);
+    g_assert(xi2->flags == 0);
+
+    ev.flags    = XITouchOwner;
+    rc          = EventToXI2((InternalEvent*)&ev, (xEvent**)&xi2_flags);
+    g_assert(rc == Success);
+    g_assert(xi2_flags->type == GenericEvent);
+    g_assert(xi2_flags->evtype == XI_TouchBegin);
+    g_assert(xi2_flags->flags == XITouchOwner);
+    xi2_flags->flags = 0;
+    g_assert(memcmp(xi2, xi2_flags, sizeof(*xi2)) == 0);
+}
+
 static void xi2_struct_sizes(void)
 {
 #define compare(req) \
@@ -674,6 +707,38 @@ static void dix_grab_matching(void)
     g_assert(rc == TRUE);
     rc = GrabMatchesSecond(&b, &a, FALSE);
     g_assert(rc == TRUE);
+
+    /* All touch grabs must match a TouchBegin grab. */
+    a.grabtype = GRABTYPE_XI2;
+    b.grabtype = GRABTYPE_XI2;
+    a.type = XI_TouchBegin;
+    b.type = XI_TouchMotion;
+    a.detail.exact = 0;
+    b.detail.exact = 0;
+    a.modifiersDetail.exact = 0;
+    b.modifiersDetail.exact = 0;
+    rc = GrabMatchesSecond(&a, &b, FALSE);
+    g_assert(rc == TRUE);
+    rc = GrabMatchesSecond(&b, &a, FALSE);
+    g_assert(rc == TRUE);
+
+    b.type = XI_TouchMotionUnowned;
+    rc = GrabMatchesSecond(&a, &b, FALSE);
+    g_assert(rc == TRUE);
+    rc = GrabMatchesSecond(&b, &a, FALSE);
+    g_assert(rc == TRUE);
+
+    b.type = XI_TouchOwnership;
+    rc = GrabMatchesSecond(&a, &b, FALSE);
+    g_assert(rc == TRUE);
+    rc = GrabMatchesSecond(&b, &a, FALSE);
+    g_assert(rc == TRUE);
+
+    b.type = XI_TouchEnd;
+    rc = GrabMatchesSecond(&a, &b, FALSE);
+    g_assert(rc == TRUE);
+    rc = GrabMatchesSecond(&b, &a, FALSE);
+    g_assert(rc == TRUE);
 }
 
 static void test_bits_to_byte(int i)
@@ -1061,6 +1126,105 @@ static void include_bit_test_macros(void)
     }
 }
 
+static void touch_create(void)
+{
+    DeviceIntRec dev;
+    TouchClassRec touch;
+    TouchPointInfoRec touches[2];
+    TouchPointInfoPtr ti;
+
+    memset(&dev, 0, sizeof(dev));
+    memset(&touch, 0, sizeof(touch));
+    memset(touches, 0, sizeof(*touches) * 2);
+    touch.touches = touches;
+    touch.num_touches = 2;
+    touch.num_axes = 2;
+    touch.next_client_id = 1;
+    dev.touch = &touch;
+
+    /* Make sure we get a valid touchpoint back. */
+    ti = BeginTouchPoint(&dev, 0xdeadbeef);
+    g_assert(ti);
+    g_assert(ti->active == TRUE);
+    g_assert(ti->ddx_id == 0xdeadbeef);
+    g_assert(ti->client_id != 0);
+    g_assert(ti->pending_finish == 0);
+    g_assert(ti->num_listeners == 0);
+    g_assert(ti->num_grabs == 0);
+    g_assert(ti->sprite.spriteTraceGood == 0);
+}
+
+static void touch_find_point(void)
+{
+    DeviceIntRec dev;
+    TouchClassRec touch;
+    TouchPointInfoRec touches[2];
+    TouchPointInfoPtr create_ret, find_ret;
+
+    memset(&dev, 0, sizeof(dev));
+    memset(&touch, 0, sizeof(touch));
+    memset(touches, 0, sizeof(*touches) * 2);
+    touch.touches = touches;
+    touch.num_touches = 2;
+    touch.num_axes = 2;
+    touch.next_client_id = 1;
+    dev.touch = &touch;
+
+    create_ret = BeginTouchPoint(&dev, 0xdeadbeef);
+    g_assert(create_ret);
+
+    /* Make sure we can find the touch by both DDX and client ID. */
+    find_ret = FindTouchPointByDDXID(&dev, 0xdeadbeef);
+    g_assert(create_ret == find_ret);
+    find_ret = FindTouchPointByClientID(&dev, create_ret->client_id);
+    g_assert(find_ret->active == TRUE);
+    g_assert(find_ret->ddx_id == 0xdeadbeef);
+
+    /* Touches which are pending finish must be findable by their client ID,
+     * but not by their DDX ID, as only the DIX can inject ownership change
+     * events. */
+    find_ret->pending_finish = 1;
+    find_ret = FindTouchPointByClientID(&dev, create_ret->client_id);
+    g_assert(find_ret == create_ret);
+    find_ret = FindTouchPointByDDXID(&dev, 0xdeadbeef);
+    g_assert(!find_ret);
+}
+
+static void touch_finish(void)
+{
+    DeviceIntRec dev;
+    TouchClassRec touch;
+    TouchPointInfoRec touches[2];
+    TouchPointInfoPtr ti;
+    uint32_t client_id;
+
+    memset(&dev, 0, sizeof(dev));
+    memset(&touch, 0, sizeof(touch));
+    memset(touches, 0, sizeof(*touches) * 2);
+    touch.touches = touches;
+    touch.num_touches = 2;
+    touch.num_axes = 2;
+    touch.next_client_id = 1;
+    dev.touch = &touch;
+
+    /* Make sure the touch is in a sane state once we kill it, and that we
+     * can't find it once it's gone. */
+    ti = BeginTouchPoint(&dev, 0xdeadbeef);
+    g_assert(ti);
+    client_id = ti->client_id;
+    EndTouchPoint(&dev, ti);
+    g_assert(ti->active == FALSE);
+    g_assert(ti->pending_finish == 0);
+    g_assert(ti->num_listeners == 0);
+    g_assert(ti->num_grabs == 0);
+    g_assert(ti->sprite.spriteTraceGood == 0);
+    g_assert(ti->client_id == 0);
+    g_assert(ti->ddx_id == 0);
+
+    g_assert(FindTouchPointByDDXID(&dev, 0xdeadbeef) == NULL);
+    g_assert(FindTouchPointByClientID(&dev, client_id) == NULL);
+}
+
 int main(int argc, char** argv)
 {
     g_test_init(&argc, &argv,NULL);
@@ -1070,6 +1234,7 @@ int main(int argc, char** argv)
     g_test_add_func("/dix/input/attributes", dix_input_attributes);
     g_test_add_func("/dix/input/init-valuators", dix_init_valuators);
     g_test_add_func("/dix/input/event-core-conversion", dix_event_to_core_conversion);
+    g_test_add_func("/dix/input/event-xi2-conversion", dix_event_to_xi2_conversion);
     g_test_add_func("/dix/input/check-grab-values", dix_check_grab_values);
     g_test_add_func("/dix/input/xi2-struct-sizes", xi2_struct_sizes);
     g_test_add_func("/dix/input/grab_matching", dix_grab_matching);
@@ -1077,7 +1242,9 @@ int main(int argc, char** argv)
     g_test_add_func("/include/byte_padding_macros", include_byte_padding_macros);
     g_test_add_func("/include/bit_test_macros", include_bit_test_macros);
     g_test_add_func("/Xi/xiproperty/register-unregister", xi_unregister_handlers);
-
+    g_test_add_func("/dix/input/touch-create", touch_create);
+    g_test_add_func("/dix/input/touch-find-point", touch_find_point);
+    g_test_add_func("/dix/input/touch-finish", touch_finish);
 
     return g_test_run();
 }
diff --git a/test/xi2/protocol-eventconvert.c b/test/xi2/protocol-eventconvert.c
index 0478c33..f8de46b 100644
--- a/test/xi2/protocol-eventconvert.c
+++ b/test/xi2/protocol-eventconvert.c
@@ -149,6 +149,61 @@ static void test_XIRawEvent(RawDeviceEvent *in)
     free(swapped);
 }
 
+static void test_values_XITouchOwnershipEvent(TouchOwnershipEvent *in,
+                                              xXITouchOwnershipEvent *out,
+                                              BOOL swap)
+{
+    char n;
+
+    if (swap)
+    {
+        swaps(&out->sequenceNumber, n);
+        swapl(&out->length, n);
+        swaps(&out->evtype, n);
+        swaps(&out->deviceid, n);
+        swapl(&out->time, n);
+        swaps(&out->sourceid, n);
+        swapl(&out->touchid, n);
+        swapl(&out->flags, n);
+    }
+
+    g_assert(out->type == GenericEvent);
+    g_assert(out->extension == 0);
+    g_assert(out->length == bytes_to_int32(sizeof(*out) - sizeof(xEvent)));
+    g_assert(out->evtype == XI_TouchOwnership);
+    g_assert(out->deviceid == in->deviceid);
+    g_assert(out->time == in->time);
+    g_assert(out->sourceid == in->sourceid);
+    g_assert(out->reason == in->reason);
+    g_assert(out->touchid == in->touchid);
+    g_assert(out->flags == in->flags);
+}
+
+static void test_convert_XITouchOwnershipEvent(void)
+{
+    TouchOwnershipEvent in;
+    xXITouchOwnershipEvent *out, swapped;
+    int rc;
+
+    in.header = ET_Internal;
+    in.type = ET_TouchOwnership;
+    in.touchid = 0xdeadbeef;
+    in.time = 234;
+    in.deviceid = 12;
+    in.sourceid = 14;
+    in.reason = XITouchOwnerAccept;
+    in.resource = 0xcafebabe;
+    in.flags = 0;
+    rc = EventToXI2((InternalEvent *) &in, (xEvent **) &out);
+    g_assert(rc == Success);
+
+    test_values_XITouchOwnershipEvent(&in, out, FALSE);
+    XI2EventSwap((xGenericEvent*)out, (xGenericEvent*)&swapped);
+    test_values_XITouchOwnershipEvent(&in, &swapped, TRUE);
+
+    free(out);
+}
+
 static void test_convert_XIFocusEvent(void)
 {
     xEvent *out;
@@ -272,7 +327,7 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
     int buttons, valuators;
     int i;
     unsigned char *ptr;
-    uint32_t flagmask = 0;
+    uint32_t flagmask;
     FP3232 *values;
 
     if (swap) {
@@ -311,9 +366,20 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
     g_assert(out->sourceid == in->sourceid);
 
     switch (in->type) {
+        case ET_TouchBegin:
+        case ET_TouchEnd:
+            flagmask = XITouchOwner;
+            break;
+        case ET_ButtonPress:
+        case ET_ButtonRelease:
+        case ET_Motion:
+            flagmask = XITouchPointer;
+            break;
         case ET_KeyPress:
             flagmask = XIKeyRepeat;
             break;
+        case ET_TouchMotion:
+        case ET_TouchMotionUnowned:
         default:
             flagmask = 0;
             break;
@@ -636,6 +702,50 @@ static void test_convert_XIDeviceEvent(void)
     }
 }
 
+static void test_convert_XITouch(void)
+{
+    DeviceEvent in;
+
+    memset(&in, 0, sizeof(in));
+
+    g_test_message("Testing TouchBegin");
+    in.header = ET_Internal;
+    in.type = ET_TouchBegin;
+    in.length = sizeof(DeviceEvent);
+    in.time             = 0;
+    in.deviceid         = 1;
+    in.sourceid         = 2;
+    in.root             = 3;
+    in.root_x           = 4;
+    in.root_x_frac      = 5;
+    in.root_y           = 6;
+    in.root_y_frac      = 7;
+    in.detail.button    = 8;
+    in.mods.base        = 9;
+    in.mods.latched     = 10;
+    in.mods.locked      = 11;
+    in.mods.effective   = 11;
+    in.group.base       = 12;
+    in.group.latched    = 13;
+    in.group.locked     = 14;
+    in.group.effective  = 15;
+    in.flags            = XITouchOwner;
+    test_XIDeviceEvent(&in);
+
+    in.flags = 0;
+    g_test_message("Testing TouchMotion");
+    in.type = ET_TouchMotion;
+    test_XIDeviceEvent(&in);
+
+    g_test_message("Testing TouchMotionUnowned");
+    in.type = ET_TouchMotionUnowned;
+    test_XIDeviceEvent(&in);
+
+    g_test_message("Testing TouchEnd");
+    in.type = ET_TouchEnd;
+    test_XIDeviceEvent(&in);
+}
+
 static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in,
                                              xXIDeviceChangedEvent *out,
                                              BOOL swap)
@@ -912,6 +1022,8 @@ int main(int argc, char** argv)
     g_test_add_func("/xi2/eventconvert/XIFocusEvent", test_convert_XIFocusEvent);
     g_test_add_func("/xi2/eventconvert/XIDeviceEvent", test_convert_XIDeviceEvent);
     g_test_add_func("/xi2/eventconvert/XIDeviceChangedEvent", test_convert_XIDeviceChangedEvent);
+    g_test_add_func("/xi2/eventconvert/XITouch", test_convert_XITouch);
+    g_test_add_func("/xi2/eventconvert/XITouchOwnership", test_convert_XITouchOwnershipEvent);
 
     return g_test_run();
 }
diff --git a/test/xi2/protocol-xiselectevents.c b/test/xi2/protocol-xiselectevents.c
index f951a14..4564840 100644
--- a/test/xi2/protocol-xiselectevents.c
+++ b/test/xi2/protocol-xiselectevents.c
@@ -159,7 +159,23 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req)
         memset(bits, 0, mask->mask_len * 4);
         for (j = 0; j <= XI2LASTEVENT; j++)
         {
+            /* Can't select for these events alone */
+            if (j == XI_TouchBegin || j == XI_TouchOwnership ||
+                j == XI_TouchEnd)
+                continue;
+
             SetBit(bits, j);
+
+            /* Must select for TouchBegin + TouchOwnership + TouchEnd together,
+             * plus TouchMotion and optionally also TouchMotionUnowned */
+            if (j == XI_TouchMotion || j == XI_TouchMotionUnowned) {
+                SetBit(bits, XI_TouchBegin);
+                SetBit(bits, XI_TouchOwnership);
+                SetBit(bits, XI_TouchEnd);
+                if (j == XI_TouchMotionUnowned)
+                    SetBit(bits, XI_TouchMotion);
+            }
+
             request_XISelectEvent(req, Success);
             ClearBit(bits, j);
         }
@@ -175,7 +191,23 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req)
 
         for (j = 0; j <= XI2LASTEVENT; j++)
         {
+            /* Can't select for these events alone */
+            if (j == XI_TouchBegin || j == XI_TouchOwnership ||
+                j == XI_TouchEnd)
+                continue;
+
             SetBit(bits, j);
+
+            /* Must select for TouchBegin + TouchOwnership + TouchEnd together,
+             * plus TouchMotion and optionally also TouchMotionUnowned */
+            if (j == XI_TouchMotion || j == XI_TouchMotionUnowned) {
+                SetBit(bits, XI_TouchBegin);
+                SetBit(bits, XI_TouchOwnership);
+                SetBit(bits, XI_TouchEnd);
+                if (j == XI_TouchMotionUnowned)
+                    SetBit(bits, XI_TouchMotion);
+            }
+
             request_XISelectEvent(req, Success);
         }
 
@@ -189,7 +221,23 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req)
 
         for (j = XI2LASTEVENT + 1; j < mask->mask_len * 4; j++)
         {
+            /* Can't select for these events alone */
+            if (j == XI_TouchBegin || j == XI_TouchOwnership ||
+                j == XI_TouchEnd)
+                continue;
+
             SetBit(bits, j);
+
+            /* Must select for TouchBegin + TouchOwnership + TouchEnd together,
+             * plus TouchMotion and optionally also TouchMotionUnowned */
+            if (j == XI_TouchMotion || j == XI_TouchMotionUnowned) {
+                SetBit(bits, XI_TouchBegin);
+                SetBit(bits, XI_TouchOwnership);
+                SetBit(bits, XI_TouchEnd);
+                if (j == XI_TouchMotionUnowned)
+                    SetBit(bits, XI_TouchMotion);
+            }
+
             request_XISelectEvent(req, BadValue);
             ClearBit(bits, j);
         }
@@ -202,7 +250,23 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req)
         memset(bits, 0, mask->mask_len * 4);
         for (j = 0; j <= XI2LASTEVENT; j++)
         {
+            /* Can't select for these events alone */
+            if (j == XI_TouchBegin || j == XI_TouchOwnership ||
+                j == XI_TouchEnd)
+                continue;
+
             SetBit(bits, j);
+
+            /* Must select for TouchBegin + TouchOwnership + TouchEnd together,
+             * plus TouchMotion and optionally also TouchMotionUnowned */
+            if (j == XI_TouchMotion || j == XI_TouchMotionUnowned) {
+                SetBit(bits, XI_TouchBegin);
+                SetBit(bits, XI_TouchOwnership);
+                SetBit(bits, XI_TouchEnd);
+                if (j == XI_TouchMotionUnowned)
+                    SetBit(bits, XI_TouchMotion);
+            }
+
             request_XISelectEvent(req, Success);
         }
 
-- 
1.7.2.3



More information about the xorg-devel mailing list