#include "config.h" #include #include #include "util-munit.h" #include "libei.h" #include "eierpecken.h" MUNIT_TEST(test_ei_ref_unref) { struct ei *ei = ei_new(NULL); struct ei *refd = ei_ref(ei); munit_assert_ptr_equal(ei, refd); struct ei *unrefd = ei_unref(ei); munit_assert_ptr_null(unrefd); unrefd = ei_unref(ei); munit_assert_ptr_null(unrefd); /* memleak only shows up in valgrind */ return MUNIT_OK; } MUNIT_TEST(test_ei_disconnect_immediately) { _cleanup_peck_ struct peck *peck = peck_new(); /* Client is immediately rejected */ peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_REJECT_CLIENT); peck_dispatch_until_stable(peck); /* Expect the client to get a disconnect event */ with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *disconnect = peck_ei_next_event(ei, EI_EVENT_DISCONNECT); } return MUNIT_OK; } MUNIT_TEST(test_ei_disconnect_after_connect) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_eis_client_ struct eis_client *client = NULL; peck_dispatch_until_stable(peck); with_server(peck) { eis_dispatch(eis); _cleanup_eis_event_ struct eis_event *e = peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT); client = eis_client_ref(eis_event_get_client(e)); eis_client_connect(client); } with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *e = peck_ei_next_event(ei, EI_EVENT_CONNECT); } with_server(peck) { eis_client_disconnect(client); } with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *e = peck_ei_next_event(ei, EI_EVENT_DISCONNECT); } return MUNIT_OK; } MUNIT_TEST(test_ei_disconnect_after_add_before_received) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_eis_client_ struct eis_client *client = NULL; peck_dispatch_until_stable(peck); with_server(peck) { eis_dispatch(eis); _cleanup_eis_event_ struct eis_event *e = peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT); client = eis_client_ref(eis_event_get_client(e)); eis_client_connect(client); } peck_dispatch_until_stable(peck); with_client(peck) { _cleanup_ei_device_ struct ei_device *device = ei_device_new(ei); ei_device_configure_name(device, __func__); ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER); ei_device_add(device); } /* We have *not* called eis_dispatch, so the device add hasn't been * processed by the server yet */ with_server(peck) { eis_client_disconnect(client); } with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *removed = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); _cleanup_ei_event_ struct ei_event *disconnect = peck_ei_next_event(ei, EI_EVENT_DISCONNECT); } return MUNIT_OK; } MUNIT_TEST(test_ei_disconnect_after_add_after_received) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_eis_client_ struct eis_client *client = NULL; peck_dispatch_until_stable(peck); with_server(peck) { eis_dispatch(eis); _cleanup_eis_event_ struct eis_event *e = peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT); client = eis_client_ref(eis_event_get_client(e)); eis_client_connect(client); } peck_dispatch_until_stable(peck); with_client(peck) { _cleanup_ei_device_ struct ei_device *device = ei_device_new(ei); ei_device_configure_name(device, __func__); ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER); ei_device_add(device); } /* Receive the Added event but don't actually add the device */ peck_dispatch_eis(peck); with_server(peck) { eis_client_disconnect(client); } with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *removed = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); _cleanup_ei_event_ struct ei_event *disconnect = peck_ei_next_event(ei, EI_EVENT_DISCONNECT); } return MUNIT_OK; } MUNIT_TEST(test_ei_disconnect_after_remove_before_received) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_eis_client_ struct eis_client *client = NULL; _cleanup_ei_device_ struct ei_device *device = NULL; peck_dispatch_until_stable(peck); with_server(peck) { eis_dispatch(eis); _cleanup_eis_event_ struct eis_event *e = peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT); client = eis_client_ref(eis_event_get_client(e)); eis_client_connect(client); } peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_dispatch_until_stable(peck); with_client(peck) { device = ei_device_new(ei); ei_device_configure_name(device, __func__); ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER); ei_device_add(device); } /* server has the device now */ peck_dispatch_until_stable(peck); with_client(peck) { _cleanup_ei_event_ struct ei_event *added = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); _cleanup_ei_event_ struct ei_event *resumed = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); ei_device_remove(device); } /* No server dispatch here so the server isn't aware of the * ei_device_remove() call. Disconnect the client, this * automatically removes all devices */ with_server(peck) { eis_client_disconnect(client); } with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *removed = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); _cleanup_ei_event_ struct ei_event *disconnect = peck_ei_next_event(ei, EI_EVENT_DISCONNECT); } return MUNIT_OK; } MUNIT_TEST(test_ei_disconnect_after_remove_after_received) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_eis_client_ struct eis_client *client = NULL; _cleanup_ei_device_ struct ei_device *device = NULL; peck_dispatch_until_stable(peck); with_server(peck) { eis_dispatch(eis); _cleanup_eis_event_ struct eis_event *e = peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT); client = eis_client_ref(eis_event_get_client(e)); eis_client_connect(client); } peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_dispatch_until_stable(peck); with_client(peck) { device = ei_device_new(ei); ei_device_configure_name(device, __func__); ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER); ei_device_add(device); } /* server has the device now */ peck_dispatch_until_stable(peck); with_client(peck) { _cleanup_ei_event_ struct ei_event *added = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); _cleanup_ei_event_ struct ei_event *resumed = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); ei_device_remove(device); } /* Dispatch, server is aware of the ei_device_remove() */ peck_dispatch_eis(peck); with_server(peck) { eis_client_disconnect(client); } with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *removed = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); _cleanup_ei_event_ struct ei_event *disconnect = peck_ei_next_event(ei, EI_EVENT_DISCONNECT); } return MUNIT_OK; } MUNIT_TEST(test_ei_device_basics) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_ei_device_ struct ei_device *device = NULL; peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_dispatch_until_stable(peck); /* device creation and getters/setters test */ with_client(peck) { device = ei_device_new(ei); munit_assert_not_null(device); ei_device_configure_name(device, __func__); munit_assert_string_equal(ei_device_get_name(device), __func__); bool success = ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER); munit_assert(success); munit_assert(ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)); /* Add it, but we don't care about whether it worked correctly in this test */ ei_device_add(device); /* Device is immutable after ei_device_add() */ bool failed_caps = ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER); munit_assert(failed_caps == false); munit_assert(ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)); } /* Drain both sides, we don't care about the events themselves */ with_server(peck) { peck_drain_eis(eis); } with_client(peck) { peck_drain_ei(ei); } /* device is still immutable */ with_client(peck) { bool failed_caps = ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER); munit_assert(failed_caps == false); munit_assert(ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)); } return MUNIT_OK; } MUNIT_TEST(test_ei_device_set_name) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_ei_device_ struct ei_device *d1 = NULL; _cleanup_ei_device_ struct ei_device *d2 = NULL; _cleanup_ei_device_ struct ei_device *d3 = NULL; peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); peck_dispatch_until_stable(peck); with_client(peck) { d1 = ei_device_new(ei); ei_device_configure_name(d1, "first device"); ei_device_configure_capability(d1, EI_DEVICE_CAP_POINTER); ei_device_add(d1); d2 = ei_device_new(ei); munit_assert_not_null(d2); ei_device_configure_name(d2, "second device"); ei_device_configure_capability(d2, EI_DEVICE_CAP_POINTER); ei_device_add(d2); d3 = ei_device_new(ei); munit_assert_not_null(d3); ei_device_configure_name(d3, "third device"); ei_device_configure_capability(d3, EI_DEVICE_CAP_POINTER); ei_device_add(d3); } peck_dispatch_until_stable(peck); with_server(peck) { _cleanup_eis_event_ struct eis_event *e1 = peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); struct eis_device *d1 = eis_event_get_device(e1); munit_assert_string_equal(eis_device_get_name(d1), "first device"); /* change the name */ eis_device_set_name(d1, "other name"); munit_assert_string_equal(eis_device_get_name(d1), "other name"); eis_device_allow_capability(d1, EIS_DEVICE_CAP_POINTER); eis_device_connect(d1); _cleanup_eis_event_ struct eis_event *e2 = peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); struct eis_device *d2 = eis_event_get_device(e2); munit_assert_string_equal(eis_device_get_name(d2), "second device"); /* unset the name */ eis_device_set_name(d2, NULL); munit_assert_ptr_null(eis_device_get_name(d2)); eis_device_allow_capability(d2, EIS_DEVICE_CAP_POINTER); eis_device_connect(d2); _cleanup_eis_event_ struct eis_event *e3 = peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); struct eis_device *d3 = eis_event_get_device(e3); munit_assert_string_equal(eis_device_get_name(d3), "third device"); /* leave the name as-is */ eis_device_allow_capability(d3, EIS_DEVICE_CAP_POINTER); eis_device_connect(d3); } peck_dispatch_until_stable(peck); with_client(peck) { _cleanup_ei_event_ struct ei_event *e1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); munit_assert_ptr_equal(d1, ei_event_get_device(e1)); munit_assert_string_equal(ei_device_get_name(d1), "other name"); _cleanup_ei_event_ struct ei_event *e2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); munit_assert_ptr_equal(d2, ei_event_get_device(e2)); munit_assert_ptr_null(ei_device_get_name(d2)); _cleanup_ei_event_ struct ei_event *e3 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); munit_assert_ptr_equal(d3, ei_event_get_device(e3)); munit_assert_string_equal(ei_device_get_name(d3), "third device"); } return MUNIT_OK; } MUNIT_TEST(test_ei_device_add_remove) { _cleanup_peck_ struct peck *peck = peck_new(); with_server(peck) { peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); peck_dispatch_eis(peck); } with_client(peck) { peck_drain_ei(ei); } _cleanup_ei_device_ struct ei_device *device = NULL; with_client(peck) { device = ei_device_new(ei); ei_device_configure_name(device, __func__); ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER); ei_device_add(device); } peck_dispatch_until_stable(peck); _cleanup_eis_device_ struct eis_device *eis_device = NULL; with_server(peck) { _cleanup_eis_event_ struct eis_event *event = peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); eis_device = eis_device_ref(eis_event_get_device(event)); eis_device_allow_capability(eis_device, EIS_DEVICE_CAP_POINTER); eis_device_connect(eis_device); } with_client(peck) { peck_dispatch_ei(peck); _cleanup_ei_event_ struct ei_event *event = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); struct ei_device *added = ei_event_get_device(event); munit_assert_ptr_equal(device, added); munit_assert(ei_device_has_capability(added, EI_DEVICE_CAP_POINTER)); ei_device_remove(device); } with_server(peck) { peck_dispatch_eis(peck); _cleanup_eis_event_ struct eis_event *event = peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED); munit_assert_ptr_equal(eis_event_get_device(event), eis_device); eis_device_disconnect(eis_device); } with_client(peck) { peck_dispatch_ei(peck); _cleanup_ei_event_ struct ei_event *event = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); struct ei_device *removed = ei_event_get_device(event); munit_assert_ptr_equal(device, removed); } return MUNIT_OK; } MUNIT_TEST(test_ei_device_remove_forget_disconnect) { _cleanup_peck_ struct peck *peck = peck_new(); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); peck_dispatch_until_stable(peck); _cleanup_ei_device_ struct ei_device *d1 = NULL; _cleanup_ei_device_ struct ei_device *d2 = NULL; with_client(peck) { d1 = ei_device_new(ei); ei_device_configure_name(d1, "first"); ei_device_configure_capability(d1, EI_DEVICE_CAP_POINTER); ei_device_add(d1); d2 = ei_device_new(ei); ei_device_configure_name(d2, "second"); ei_device_configure_capability(d2, EI_DEVICE_CAP_KEYBOARD); ei_device_add(d2); } peck_dispatch_until_stable(peck); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE); with_client(peck) { /* remove in order d1, d2 */ ei_device_remove(d1); ei_device_remove(d2); } peck_dispatch_until_stable(peck); struct eis_event *e1 = NULL; with_server(peck) { e1 = peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED); _cleanup_eis_event_ struct eis_event *e2 = peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED); /* Explicitly disconnect device d2 */ eis_device_disconnect(eis_event_get_device(e2)); /* But forget to eis_device_disconnect(d1), happens * automatically when the event is unref'd */ } peck_dispatch_ei(peck); with_client(peck) { _cleanup_ei_event_ struct ei_event *event = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); struct ei_device *removed = ei_event_get_device(event); munit_assert_ptr_equal(d2, removed); peck_assert_no_ei_events(ei); } /* unref should trigger eis_device_disconnect() */ eis_event_unref(e1); peck_dispatch_ei(peck); with_client(peck) { _cleanup_ei_event_ struct ei_event *event = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); struct ei_device *removed = ei_event_get_device(event); munit_assert_ptr_equal(d1, removed); peck_assert_no_ei_events(ei); } return MUNIT_OK; } MUNIT_TEST(test_ei_device_add_drop_caps) { _cleanup_peck_ struct peck *peck = peck_new(); /* Device with pointer and keyboard caps but pointer is dropped */ peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DROP_POINTER); peck_dispatch_until_stable(peck); _cleanup_ei_device_ struct ei_device *device = NULL; with_client(peck) { device = ei_device_new(ei); ei_device_configure_name(device, __func__); ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER); ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD); ei_device_add(device); } peck_dispatch_eis(peck); with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *event = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); struct ei_device *d = ei_event_get_device(event); munit_assert_ptr_equal(d, device); munit_assert(ei_device_has_capability(d, EI_DEVICE_CAP_KEYBOARD)); munit_assert(!ei_device_has_capability(d, EI_DEVICE_CAP_POINTER)); } return MUNIT_OK; } MUNIT_TEST(test_ei_device_add_zero_caps) { _cleanup_peck_ struct peck *peck = peck_new(); /* Device with pointer caps but those caps are rejected -> device immediately removed by EIS */ peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DROP_POINTER); peck_dispatch_until_stable(peck); _cleanup_ei_device_ struct ei_device *device = NULL; with_client(peck) { device = ei_device_new(ei); ei_device_configure_name(device, __func__); ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER); ei_device_add(device); } peck_dispatch_eis(peck); with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *event = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); } return MUNIT_OK; } MUNIT_TEST(test_ei_device_pointer_rel) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_ei_device_ struct ei_device *device = NULL; peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); peck_dispatch_until_stable(peck); with_client(peck) { device = ei_device_new(ei); munit_assert_not_null(device); ei_device_configure_name(device, __func__); ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER); ei_device_add(device); } peck_dispatch_until_stable(peck); with_client(peck) { ei_device_pointer_motion(device, 1, 2); ei_device_pointer_motion(device, 0.3, 1.4); ei_device_pointer_motion(device, 100, 200); } peck_dispatch_until_stable(peck); with_server(peck) { _cleanup_eis_event_ struct eis_event *first = peck_eis_next_event(eis, EIS_EVENT_POINTER_MOTION); munit_assert_double_equal(eis_event_pointer_get_dx(first), 1.0, 2 /* precision */); munit_assert_double_equal(eis_event_pointer_get_dy(first), 2.0, 2 /* precision */); _cleanup_eis_event_ struct eis_event *second = peck_eis_next_event(eis, EIS_EVENT_POINTER_MOTION); munit_assert_double_equal(eis_event_pointer_get_dx(second), 0.3, 2 /* precision */); munit_assert_double_equal(eis_event_pointer_get_dy(second), 1.4, 2 /* precision */); _cleanup_eis_event_ struct eis_event *third = peck_eis_next_event(eis, EIS_EVENT_POINTER_MOTION); munit_assert_double_equal(eis_event_pointer_get_dx(third), 100, 2 /* precision */); munit_assert_double_equal(eis_event_pointer_get_dy(third), 200, 2 /* precision */); } return MUNIT_OK; } MUNIT_TEST(test_ei_device_pointer_abs) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_ei_device_ struct ei_device *device = NULL; peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); peck_dispatch_until_stable(peck); with_client(peck) { device = ei_device_new(ei); munit_assert_not_null(device); ei_device_configure_name(device, __func__); ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE); ei_device_pointer_configure_range(device, 1920, 1200); ei_device_add(device); } peck_dispatch_until_stable(peck); with_client(peck) { for (int i = 0; i < 10; i++) ei_device_pointer_motion_absolute(device, 1 * i , 2 + i); } peck_dispatch_until_stable(peck); with_server(peck) { for (int i = 0; i < 10; i++) { _cleanup_eis_event_ struct eis_event *e = peck_eis_next_event(eis, EIS_EVENT_POINTER_MOTION_ABSOLUTE); munit_assert_double_equal(eis_event_pointer_get_absolute_x(e), 1.0 * i, 2 /* precision */); munit_assert_double_equal(eis_event_pointer_get_absolute_y(e), 2.0 + i, 2 /* precision */); } } with_client(peck) { /* outside of pointer range, expect to be discarded */ ei_device_pointer_motion_absolute(device, 1920, 1200); ei_device_pointer_motion_absolute(device, 2000, 1400); } peck_dispatch_until_stable(peck); with_server(peck) { peck_assert_no_eis_events(eis); } with_client(peck) { ei_device_remove(device); /* absmotion after remove must not trigger an event */ ei_device_pointer_motion_absolute(device, 100, 200); } with_server(peck) { /* Don't auto-handle the removed event */ peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE); peck_dispatch_eis(peck); _cleanup_eis_event_ struct eis_event *e = peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED); peck_assert_no_eis_events(eis); } return MUNIT_OK; } MUNIT_TEST(test_ei_device_touch) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_ei_device_ struct ei_device *device = NULL; peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); peck_dispatch_until_stable(peck); with_client(peck) { device = ei_device_new(ei); munit_assert_not_null(device); ei_device_configure_name(device, __func__); ei_device_configure_capability(device, EI_DEVICE_CAP_TOUCH); ei_device_touch_configure_range(device, 1024, 768); ei_device_add(device); } peck_dispatch_until_stable(peck); with_client(peck) { _cleanup_ei_touch_ struct ei_touch *t = ei_device_touch_new(device); ei_touch_down(t, 1, 2); ei_touch_motion(t, 200, 500); ei_touch_up(t); } peck_dispatch_until_stable(peck); with_server(peck) { _cleanup_eis_event_ struct eis_event *down = peck_eis_touch_down(eis, 1, 2); uint32_t tid = eis_event_touch_get_id(down); _cleanup_eis_event_ struct eis_event *motion = peck_eis_touch_motion(eis, 200, 500); munit_assert_uint32(eis_event_touch_get_id(motion), ==, tid); _cleanup_eis_event_ struct eis_event *up = peck_eis_touch_up(eis); munit_assert_uint32(eis_event_touch_get_id(up), ==, tid); } with_client(peck) { _cleanup_ei_touch_ struct ei_touch *t = ei_device_touch_new(device); /* outside clip range, expect touch to be dropped */ ei_touch_down(t, 1200, 100); ei_touch_motion(t, 200, 200); ei_touch_up(t); } peck_dispatch_until_stable(peck); with_server(peck) { peck_assert_no_eis_events(eis); } with_client(peck) { _cleanup_ei_touch_ struct ei_touch *t = ei_device_touch_new(device); ei_touch_down(t, 100, 200); /* outside allowed range, generates a touch up */ ei_touch_motion(t, 1200, 200); ei_touch_up(t); } peck_dispatch_until_stable(peck); with_server(peck) { _cleanup_eis_event_ struct eis_event *down = peck_eis_touch_down(eis, 100, 200); _cleanup_eis_event_ struct eis_event *up = peck_eis_touch_up(eis); } with_client(peck) { _cleanup_ei_touch_ struct ei_touch *t = ei_device_touch_new(device); ei_touch_down(t, 100, 100); /* client forgets to touch up, touch_unref takes care of it */ } peck_dispatch_until_stable(peck); with_server(peck) { _cleanup_eis_event_ struct eis_event *down = peck_eis_touch_down(eis, 100, 100); _cleanup_eis_event_ struct eis_event *up = peck_eis_touch_up(eis); } with_client(peck) { /* touch only allocated, not actually set down */ _cleanup_ei_touch_ struct ei_touch *t1 = ei_device_touch_new(device); /* touch never set down */ _cleanup_ei_touch_ struct ei_touch *t2 = ei_device_touch_new(device); ei_touch_up(t2); /* touch never set down */ _cleanup_ei_touch_ struct ei_touch *t3 = ei_device_touch_new(device); ei_touch_motion(t3, 100, 200); ei_touch_up(t3); } peck_dispatch_until_stable(peck); with_server(peck) { peck_assert_no_eis_events(eis); } with_client(peck) { /* touch re-used */ _cleanup_ei_touch_ struct ei_touch *t = ei_device_touch_new(device); ei_touch_down(t, 100, 200); ei_touch_up(t); ei_touch_down(t, 200, 300); ei_touch_motion(t, 300, 400); ei_touch_up(t); } peck_dispatch_until_stable(peck); with_server(peck) { _cleanup_eis_event_ struct eis_event *down = peck_eis_touch_down(eis, 100, 200); _cleanup_eis_event_ struct eis_event *up = peck_eis_touch_up(eis); peck_assert_no_eis_events(eis); } with_client(peck) { /* double-down, double-up */ _cleanup_ei_touch_ struct ei_touch *t = ei_device_touch_new(device); ei_touch_down(t, 100, 200); ei_touch_down(t, 200, 300); /* ignored */ ei_touch_motion(t, 300, 400); ei_touch_up(t); ei_touch_up(t); /* ignored */ } peck_dispatch_until_stable(peck); with_server(peck) { _cleanup_eis_event_ struct eis_event *down = peck_eis_touch_down(eis, 100, 200); _cleanup_eis_event_ struct eis_event *motion = peck_eis_touch_motion(eis, 300, 400); _cleanup_eis_event_ struct eis_event *up = peck_eis_touch_up(eis); peck_assert_no_eis_events(eis); } return MUNIT_OK; } MUNIT_TEST(test_ei_device_multitouch) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_ei_device_ struct ei_device *device = NULL; peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); peck_dispatch_until_stable(peck); with_client(peck) { device = ei_device_new(ei); munit_assert_not_null(device); ei_device_configure_name(device, __func__); ei_device_configure_capability(device, EI_DEVICE_CAP_TOUCH); ei_device_touch_configure_range(device, 1024, 768); ei_device_add(device); } peck_dispatch_until_stable(peck); with_client(peck) { _cleanup_ei_touch_ struct ei_touch *t1 = ei_device_touch_new(device); _cleanup_ei_touch_ struct ei_touch *t2 = ei_device_touch_new(device); ei_touch_down(t1, 1, 2); ei_touch_motion(t1, 2, 3); ei_touch_down(t2, 3, 4); ei_touch_motion(t2, 4, 5); ei_touch_up(t2); ei_touch_up(t1); } peck_dispatch_until_stable(peck); with_server(peck) { _cleanup_eis_event_ struct eis_event *down1 = peck_eis_touch_down(eis, 1, 2); uint32_t tid1 = eis_event_touch_get_id(down1); _cleanup_eis_event_ struct eis_event *motion1 = peck_eis_touch_motion(eis, 2, 3); munit_assert_uint32(eis_event_touch_get_id(motion1), ==, tid1); _cleanup_eis_event_ struct eis_event *down2 = peck_eis_touch_down(eis, 3, 4); uint32_t tid2 = eis_event_touch_get_id(down2); munit_assert_uint32(tid2, !=, tid1); _cleanup_eis_event_ struct eis_event *motion2 = peck_eis_touch_motion(eis, 4, 5); munit_assert_uint32(eis_event_touch_get_id(motion2), ==, tid2); _cleanup_eis_event_ struct eis_event *up2 = peck_eis_touch_up(eis); munit_assert_uint32(eis_event_touch_get_id(up2), ==, tid2); _cleanup_eis_event_ struct eis_event *up1 = peck_eis_touch_up(eis); munit_assert_uint32(eis_event_touch_get_id(up1), ==, tid1); } return MUNIT_OK; } int main(int argc, char **argv) { return munit_tests_run(argc, argv); }