diff --git a/meson.build b/meson.build index 01b915d..d94fe73 100644 --- a/meson.build +++ b/meson.build @@ -235,6 +235,8 @@ if get_option('tests') executable('eierpecken', 'test/test-main.c', 'test/test-ei.c', + 'test/test-ei-device.c', + 'test/test-ei-seat.c', 'test/test-eis.c', link_with: lib_eierpecken, dependencies: [dep_unittest, dep_libei, dep_libeis])) diff --git a/test/test-ei-device.c b/test/test-ei-device.c new file mode 100644 index 0000000..7b55961 --- /dev/null +++ b/test/test-ei-device.c @@ -0,0 +1,736 @@ +/* + * Copyright © 2020 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include +#include "util-io.h" +#include "util-munit.h" +#include "util-memfile.h" + +#include "eierpecken.h" + +DEFINE_UNREF_CLEANUP_FUNC(peck); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct memfile *, memfile_unref); +#define _cleanup_memfile_ _cleanup_(memfile_unrefp) + +MUNIT_TEST(test_ei_device_basics) +{ + _unref_(peck) *peck = peck_new(); + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); + peck_dispatch_until_stable(peck); + + with_server(peck) { + struct eis_seat *seat = peck_eis_get_default_seat(peck); + _unref_(eis_device) *device = eis_device_new(seat); + + eis_device_configure_name(device, "string is freed"); + munit_assert_string_equal(eis_device_get_name(device), "string is freed"); + + /* overwrite before eis_device_add() is possible */ + eis_device_configure_name(device, __func__); + munit_assert_string_equal(eis_device_get_name(device), __func__); + + munit_assert_false(eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER)); + munit_assert_false(eis_device_has_capability(device, EIS_DEVICE_CAP_KEYBOARD)); + munit_assert_false(eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE)); + munit_assert_false(eis_device_has_capability(device, EIS_DEVICE_CAP_TOUCH)); + + eis_device_configure_capability(device, EIS_DEVICE_CAP_POINTER); + munit_assert_true(eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER)); + eis_device_configure_capability(device, EIS_DEVICE_CAP_KEYBOARD); + munit_assert_true(eis_device_has_capability(device, EIS_DEVICE_CAP_KEYBOARD)); + + eis_device_add(device); + + /* device is read-only now */ + eis_device_configure_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE); + munit_assert_false(eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE)); + + eis_device_configure_name(device, "nope"); + munit_assert_string_equal(eis_device_get_name(device), __func__); + } + + peck_dispatch_ei(peck); + + /* device creation and getters/setters test */ + with_client(peck) { + _unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + struct ei_device *device = ei_event_get_device(event); + + munit_assert_not_null(device); + munit_assert_string_equal(ei_device_get_name(device), __func__); + + munit_assert_true(ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)); + munit_assert_true(ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD)); + munit_assert_false(ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)); + munit_assert_false(ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH)); + } + + return MUNIT_OK; +} + +MUNIT_TEST(test_ei_device_set_name_multiple_devices) +{ + _unref_(peck) *peck = peck_new(); + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT); + peck_dispatch_until_stable(peck); + + with_server(peck) { + struct eis_seat *seat = peck_eis_get_default_seat(peck); + _unref_(eis_device) *d1 = eis_device_new(seat); + eis_device_configure_name(d1, "first device"); + eis_device_configure_capability(d1, EIS_DEVICE_CAP_POINTER); + eis_device_add(d1); + + _unref_(eis_device) *d2 = eis_device_new(seat); + /* Unnamed */ + eis_device_add(d2); + + _unref_(eis_device) *d3 = eis_device_new(seat); + eis_device_configure_name(d3, "third device"); + eis_device_configure_capability(d3, EIS_DEVICE_CAP_POINTER); + eis_device_add(d3); + } + + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *e1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + struct ei_device *d1 = ei_event_get_device(e1); + munit_assert_string_equal(ei_device_get_name(d1), "first device"); + + _unref_(ei_event) *e2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + struct ei_device *d2 = ei_event_get_device(e2); + munit_assert_string_equal(ei_device_get_name(d2), "unnamed device"); + + _unref_(ei_event) *e3 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + struct ei_device *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_never_added) +{ + _unref_(peck) *peck = peck_new(); + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); + peck_dispatch_until_stable(peck); + + /* Unref after remove */ + with_server(peck) { + struct eis_seat *seat = peck_eis_get_default_seat(peck); + struct eis_device *device = eis_device_new(seat); + eis_device_remove(device); + eis_device_unref(device); + } + + peck_dispatch_until_stable(peck); + + /* device was never added, shouldn't show up */ + with_client(peck) { + peck_assert_no_ei_events(ei); + } + + /* unref before remove. + * + * This would be invalid client code since you can't expect to have + * a ref after unref, but since we know the device is still here, we + * can test for the lib being correct. + */ + with_server(peck) { + struct eis_seat *seat = peck_eis_get_default_seat(peck); + struct eis_device *device = eis_device_new(seat); + eis_device_unref(device); + eis_device_remove(device); + } + + peck_dispatch_until_stable(peck); + + with_client(peck) { + peck_assert_no_ei_events(ei); + } + + return MUNIT_OK; +} + +MUNIT_TEST(test_ei_device_add_remove) +{ + _unref_(peck) *peck = peck_new(); + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT); + peck_dispatch_until_stable(peck); + + _unref_(ei_device) *device = NULL; + _unref_(eis_device) *eis_device = NULL; + + with_server(peck) { + struct eis_seat *seat = peck_eis_get_default_seat(peck); + eis_device = eis_device_new(seat); + eis_device_configure_name(eis_device, __func__); + eis_device_configure_capability(eis_device, EIS_DEVICE_CAP_POINTER); + eis_device_add(eis_device); + } + + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *event = + peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + device = ei_device_ref(ei_event_get_device(event)); + } + + with_server(peck) { + eis_device_remove(eis_device); + } + + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *event = + peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); + + munit_assert_ptr_equal(ei_event_get_device(event), device); + } + + return MUNIT_OK; +} + + +MUNIT_TEST(test_ei_device_pointer_rel) +{ + _unref_(peck) *peck = peck_new(); + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); + peck_dispatch_until_stable(peck); + + with_client(peck) { + struct ei_device *device = peck_ei_get_default_pointer(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) { + _unref_(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 */); + + _unref_(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 */); + + _unref_(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) +{ + _unref_(peck) *peck = peck_new(); + struct ei_device *device = NULL; + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER_ABSOLUTE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); + peck_dispatch_until_stable(peck); + + /* FIXME: missing the currently unimplemented region checks */ + + with_client(peck) { + device = peck_ei_get_default_pointer_absolute(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++) { + _unref_(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); + + /* Don't auto-handle the DEVICE_CLOSED event */ + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE); + } + + with_client(peck) { + ei_device_close(device); + /* absmotion after remove must not trigger an event */ + ei_device_pointer_motion_absolute(device, 100, 200); + } + + peck_dispatch_until_stable(peck); + + with_server(peck) { + _unref_(eis_event) *e = + peck_eis_next_event(eis, EIS_EVENT_DEVICE_CLOSED); + peck_assert_no_eis_events(eis); + } + + return MUNIT_OK; +} + +MUNIT_TEST(test_ei_device_touch) +{ + _unref_(peck) *peck = peck_new(); + struct ei_device *device = NULL; + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_TOUCH); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); + peck_dispatch_until_stable(peck); + + /* FIXME: missing the currently unimplemented region checks */ + + with_client(peck) { + device = peck_ei_get_default_touch(peck); + _unref_(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) { + _unref_(eis_event) *down = peck_eis_touch_down(eis, 1, 2); + uint32_t tid = eis_event_touch_get_id(down); + + _unref_(eis_event) *motion = peck_eis_touch_motion(eis, 200, 500); + munit_assert_uint32(eis_event_touch_get_id(motion), ==, tid); + + _unref_(eis_event) *up = peck_eis_touch_up(eis); + munit_assert_uint32(eis_event_touch_get_id(up), ==, tid); + } + + with_client(peck) { + _unref_(ei_touch) *t = ei_device_touch_new(device); + /* outside clip range, expect touch to be dropped */ + ei_touch_down(t, 1920, 1200); + ei_touch_motion(t, 1920, 1000); + ei_touch_up(t); + } + + peck_dispatch_until_stable(peck); + + with_server(peck) { + peck_assert_no_eis_events(eis); + } + + with_client(peck) { + _unref_(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, 1950, 200); + ei_touch_up(t); + } + + peck_dispatch_until_stable(peck); + + with_server(peck) { + _unref_(eis_event) *down = peck_eis_touch_down(eis, 100, 200); + _unref_(eis_event) *up = peck_eis_touch_up(eis); + } + + with_client(peck) { + _unref_(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) { + _unref_(eis_event) *down = peck_eis_touch_down(eis, 100, 100); + _unref_(eis_event) *up = peck_eis_touch_up(eis); + } + + with_client(peck) { + /* touch only allocated, not actually set down */ + _unref_(ei_touch) *t1 = ei_device_touch_new(device); + + /* touch never set down */ + _unref_(ei_touch) *t2 = ei_device_touch_new(device); + ei_touch_up(t2); + + /* touch never set down */ + _unref_(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 */ + _unref_(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) { + _unref_(eis_event) *down = peck_eis_touch_down(eis, 100, 200); + _unref_(eis_event) *up = peck_eis_touch_up(eis); + peck_assert_no_eis_events(eis); + } + + with_client(peck) { + /* double-down, double-up */ + _unref_(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) { + _unref_(eis_event) *down = peck_eis_touch_down(eis, 100, 200); + _unref_(eis_event) *motion = peck_eis_touch_motion(eis, 300, 400); + _unref_(eis_event) *up = peck_eis_touch_up(eis); + peck_assert_no_eis_events(eis); + } + + return MUNIT_OK; +} + +MUNIT_TEST(test_ei_device_multitouch) +{ + _unref_(peck) *peck = peck_new(); + struct ei_device *device = NULL; + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_TOUCH); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); + peck_dispatch_until_stable(peck); + + peck_dispatch_until_stable(peck); + + with_client(peck) { + device = peck_ei_get_default_touch(peck); + _unref_(ei_touch) *t1 = ei_device_touch_new(device); + _unref_(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) { + _unref_(eis_event) *down1 = peck_eis_touch_down(eis, 1, 2); + uint32_t tid1 = eis_event_touch_get_id(down1); + + _unref_(eis_event) *motion1 = peck_eis_touch_motion(eis, 2, 3); + munit_assert_uint32(eis_event_touch_get_id(motion1), ==, tid1); + + _unref_(eis_event) *down2 = peck_eis_touch_down(eis, 3, 4); + uint32_t tid2 = eis_event_touch_get_id(down2); + munit_assert_uint32(tid2, !=, tid1); + + _unref_(eis_event) *motion2 = peck_eis_touch_motion(eis, 4, 5); + munit_assert_uint32(eis_event_touch_get_id(motion2), ==, tid2); + + _unref_(eis_event) *up2 = peck_eis_touch_up(eis); + munit_assert_uint32(eis_event_touch_get_id(up2), ==, tid2); + + _unref_(eis_event) *up1 = peck_eis_touch_up(eis); + munit_assert_uint32(eis_event_touch_get_id(up1), ==, tid1); + } + + return MUNIT_OK; +} + +MUNIT_TEST(test_ei_keymap_invalid) +{ + /* FIXME: needs review after the switch to server-side devices */ + return MUNIT_SKIP; +#if 0 + const char data[5] = {1, 2, 3, 4, 5}; + _unref_(memfile) *fd = memfile_new(data, sizeof(data)); + + munit_assert_ptr_null(ei_keymap_new(EI_KEYMAP_TYPE_XKB + 1, + memfile_get_fd(fd), memfile_get_size(fd))); + munit_assert_ptr_null(ei_keymap_new(EI_KEYMAP_TYPE_XKB - 1, + memfile_get_fd(fd), memfile_get_size(fd))); + munit_assert_ptr_null(ei_keymap_new(EI_KEYMAP_TYPE_XKB, + -1, memfile_get_size(fd))); + munit_assert_ptr_null(ei_keymap_new(EI_KEYMAP_TYPE_XKB, + memfile_get_fd(fd), 0)); + + /* Valid keymap, valgrind checks only */ + _unref_(ei_keymap) *unused = + ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd), memfile_get_size(fd)); + munit_assert_ptr_not_null(unused); + + return MUNIT_OK; +#endif +} + +MUNIT_TEST(test_ei_keymap_set) +{ + /* FIXME: needs review after the switch to server-side devices */ + return MUNIT_SKIP; +#if 0 + const char data[5] = {1, 2, 3, 4, 5}; + _unref_(peck) *peck = peck_new(); + _unref_(ei_device) *device = NULL; + _unref_(memfile) *fd1 = memfile_new(data, sizeof(data)); + _unref_(ei_keymap) *keymap = NULL; + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(memfile) *fd2 = memfile_new(data, sizeof(data)); + + struct ei_seat *seat = peck_ei_get_default_seat(peck); + device = ei_device_new(seat); + ei_device_configure_name(device, __func__); + ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD); + + keymap = ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd1), memfile_get_size(fd1)); + ei_device_keyboard_configure_keymap(device, keymap); + munit_assert_ptr_equal(ei_device_keyboard_get_keymap(device), keymap); + + /* Not possible to overwrite a keymap on a device */ + _unref_(ei_keymap) *overwrite = + ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd2), memfile_get_size(fd2)); + ei_device_keyboard_configure_keymap(device, overwrite); + munit_assert_ptr_equal(ei_device_keyboard_get_keymap(device), keymap); + + ei_device_add(device); + + /* Still impossible to overwrite after add */ + _unref_(ei_keymap) *ignored = + ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd2), memfile_get_size(fd2)); + ei_device_keyboard_configure_keymap(device, ignored); + munit_assert_ptr_equal(ei_device_keyboard_get_keymap(device), keymap); + } + + peck_dispatch_until_stable(peck); + + with_server(peck) { + _unref_(eis_event) *event = + peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); + struct eis_device *eis_device = eis_event_get_device(event); + struct eis_keymap *eis_keymap = eis_device_keyboard_get_keymap(eis_device); + + int fd = eis_keymap_get_fd(eis_keymap); + munit_assert_int(fd, !=, -1); + munit_assert_uint(eis_keymap_get_size(eis_keymap), ==, memfile_get_size(fd1)); + munit_assert_uint(eis_keymap_get_type(eis_keymap), ==, EIS_KEYMAP_TYPE_XKB); + eis_device_disconnect(eis_device); + } + + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *event = + peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); + struct ei_device *d = ei_event_get_device(event); + munit_assert_ptr_equal(d, device); + + /* Rejecting a device does not unset the keymap because + * you're not supposed to do anything with the device anyway */ + struct ei_keymap *km = ei_device_keyboard_get_keymap(device); + munit_assert_ptr_equal(keymap, km); + munit_assert_int(ei_keymap_get_source(keymap), ==, EI_KEYMAP_SOURCE_CLIENT); + } + + return MUNIT_OK; +#endif +} + +MUNIT_TEST(test_ei_keymap_null) +{ + /* FIXME: needs review after the switch to server-side devices */ + return MUNIT_SKIP; +#if 0 + const char data[5] = {1, 2, 3, 4, 5}; + _unref_(peck) *peck = peck_new(); + _unref_(memfile) *fd = memfile_new(data, sizeof(data)); + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNNECT); + peck_dispatch_until_stable(peck); + + with_client(peck) { + struct ei_seat *seat = peck_ei_get_default_seat(peck); + _unref_(ei_device) *device = ei_device_new(seat); + ei_device_configure_name(device, __func__); + ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD); + + _unref_(ei_keymap) *keymap = + ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd), memfile_get_size(fd)); + ei_device_keyboard_configure_keymap(device, keymap); + ei_device_add(device); + } + + peck_dispatch_until_stable(peck); + + /* server sets the keymap to NULL */ + with_server(peck) { + _unref_(eis_event) *event = + peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); + struct eis_device *device = eis_event_get_device(event); + eis_device_keyboard_set_keymap(device, NULL); + eis_device_allow_capability(device, EIS_DEVICE_CAP_KEYBOARD); + eis_device_connect(device); + } + + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *event = + peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + struct ei_device *device = ei_event_get_device(event); + + struct ei_keymap *keymap = ei_device_keyboard_get_keymap(device); + munit_assert_ptr_null(keymap); + } + + return MUNIT_OK; +#endif +} + +MUNIT_TEST(test_ei_keymap_changed) +{ + /* FIXME: needs review after the switch to server-side devices */ + return MUNIT_SKIP; +#if 0 + const char data[5] = {1, 2, 3, 4, 5}; + _unref_(peck) *peck = peck_new(); + _unref_(memfile) *fd1 = memfile_new(data, sizeof(data)); + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNNECT); + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_device) *device = NULL; + const char otherdata[2] = {10, 20}; + _unref_(memfile) *fd2 = memfile_new(data, sizeof(otherdata)); + + struct ei_seat *seat = peck_ei_get_default_seat(peck); + device = ei_device_new(seat); + ei_device_configure_name(device, __func__); + ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD); + + _unref_(ei_keymap) *keymap = + ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd2), memfile_get_size(fd2)); + ei_device_keyboard_configure_keymap(device, keymap); + ei_device_add(device); + } + + peck_dispatch_until_stable(peck); + + /* server sets the keymap to some other fd */ + with_server(peck) { + _unref_(eis_event) *event = + peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); + struct eis_device *device = eis_event_get_device(event); + _unref_(eis_keymap) *keymap = + eis_keymap_new(EIS_KEYMAP_TYPE_XKB, memfile_get_fd(fd1), + memfile_get_size(fd1)); + eis_device_keyboard_set_keymap(device, keymap); + eis_device_allow_capability(device, EIS_DEVICE_CAP_KEYBOARD); + eis_device_connect(device); + } + + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *event = + peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + struct ei_device *device = ei_event_get_device(event); + + struct ei_keymap *keymap = ei_device_keyboard_get_keymap(device); + munit_assert_ptr_not_null(keymap); + + munit_assert_int(ei_keymap_get_type(keymap), ==, EI_KEYMAP_TYPE_XKB); + munit_assert_int(ei_keymap_get_source(keymap), ==, EI_KEYMAP_SOURCE_SERVER); + int km = ei_keymap_get_fd(keymap); + + char buf[5]; + int rc = min(xread(km, buf, sizeof(buf)), 0); + peck_errno_check(rc); + munit_assert_int(memcmp(buf, data, sizeof(buf)), ==, 0); + } + + return MUNIT_OK; +#endif +} diff --git a/test/test-ei-seat.c b/test/test-ei-seat.c new file mode 100644 index 0000000..7602d04 --- /dev/null +++ b/test/test-ei-seat.c @@ -0,0 +1,171 @@ +/* + * Copyright © 2020 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include "util-munit.h" +#include "eierpecken.h" + +DEFINE_UNREF_CLEANUP_FUNC(peck); + +MUNIT_TEST(test_ei_seat_bind_unbind) +{ + _unref_(peck) *peck = peck_new(); + _unref_(ei_seat) *seat = NULL; + _unref_(ei_device) *dev1 = NULL; + _unref_(ei_device) *dev2 = NULL; + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_UNBIND_SEAT); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNECT); + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED); + seat = ei_seat_ref(ei_event_get_seat(event)); + ei_seat_bind(seat); + } + + /* server has the Bind event now and creates devices */ + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *e1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + _unref_(ei_event) *discard1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); + _unref_(ei_event) *e2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + _unref_(ei_event) *discard2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); + + dev1 = ei_device_ref(ei_event_get_device(e1)); + dev2 = ei_device_ref(ei_event_get_device(e2)); + + ei_seat_unbind(seat); + } + + /* Dispatch, server is aware of the ei_seat_unbind() */ + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *e1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); + _unref_(ei_event) *e2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); + + struct ei_device *d1 = ei_event_get_device(e1); + struct ei_device *d2 = ei_event_get_device(e2); + + munit_assert(d1 != d2); + munit_assert(d1 == dev1 || d1 == dev2); + munit_assert(d2 == dev1 || d2 == dev2); + + _unref_(ei_event) *eseat = peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED); + struct ei_seat *s = ei_event_get_seat(eseat); + munit_assert_ptr_equal(s, seat); + } + + return MUNIT_OK; +} + +MUNIT_TEST(test_ei_seat_bind_unbind_noref) +{ + _unref_(peck) *peck = peck_new(); + struct ei_seat *seat = NULL; + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_UNBIND_SEAT); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNECT); + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED); + seat = ei_seat_ref(ei_event_get_seat(event)); + ei_seat_bind(seat); + } + + /* server has the Bind event now and creates devices */ + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *e1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + _unref_(ei_event) *discard1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); + _unref_(ei_event) *e2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + _unref_(ei_event) *discard2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); + + /* Drop our ref before unbinding. This is technically wrong - + * must not use seat after unref, but we know there's at least + * one ref inside libei for this seat, so this tests ensures + * we don't rely on a caller ref to keep everything alive. */ + ei_seat_unref(seat); + ei_seat_unbind(seat); + } + + /* Dispatch, server is aware of the ei_seat_unbind() */ + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *e1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); + _unref_(ei_event) *e2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); + _unref_(ei_event) *eseat = peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED); + } + + return MUNIT_OK; +} + +MUNIT_TEST(test_ei_seat_bind_unbind_immediately) +{ + _unref_(peck) *peck = peck_new(); + struct ei_seat *seat = NULL; + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_UNBIND_SEAT); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNECT); + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED); + seat = ei_event_get_seat(event); + ei_seat_bind(seat); + ei_seat_unbind(seat); + } + + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *e1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + _unref_(ei_event) *e2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); + _unref_(ei_event) *e3 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + _unref_(ei_event) *e4 = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); + _unref_(ei_event) *e5 = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); + _unref_(ei_event) *e6 = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); + _unref_(ei_event) *e7 = peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED); + } + + return MUNIT_OK; +} + diff --git a/test/test-ei.c b/test/test-ei.c index a58ad15..54fb92f 100644 --- a/test/test-ei.c +++ b/test/test-ei.c @@ -1,18 +1,32 @@ +/* + * Copyright © 2020 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + #include "config.h" -#include -#include -#include -#include "util-io.h" #include "util-munit.h" -#include "util-memfile.h" - -#include "libei.h" #include "eierpecken.h" DEFINE_UNREF_CLEANUP_FUNC(peck); -DEFINE_TRIVIAL_CLEANUP_FUNC(struct memfile *, memfile_unref); -#define _cleanup_memfile_ _cleanup_(memfile_unrefp) MUNIT_TEST(test_ei_ref_unref) { @@ -442,846 +456,6 @@ MUNIT_TEST(test_ei_disconnect_after_unbind_after_received) return MUNIT_OK; } -MUNIT_TEST(test_ei_seat_bind_unbind) -{ - _unref_(peck) *peck = peck_new(); - _unref_(ei_seat) *seat = NULL; - _unref_(ei_device) *dev1 = NULL; - _unref_(ei_device) *dev2 = NULL; - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_UNBIND_SEAT); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNECT); - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED); - seat = ei_seat_ref(ei_event_get_seat(event)); - ei_seat_bind(seat); - } - - /* server has the Bind event now and creates devices */ - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_event) *e1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - _unref_(ei_event) *discard1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); - _unref_(ei_event) *e2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - _unref_(ei_event) *discard2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); - - dev1 = ei_device_ref(ei_event_get_device(e1)); - dev2 = ei_device_ref(ei_event_get_device(e2)); - - ei_seat_unbind(seat); - } - - /* Dispatch, server is aware of the ei_seat_unbind() */ - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_event) *e1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - _unref_(ei_event) *e2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - - struct ei_device *d1 = ei_event_get_device(e1); - struct ei_device *d2 = ei_event_get_device(e2); - - munit_assert(d1 != d2); - munit_assert(d1 == dev1 || d1 == dev2); - munit_assert(d2 == dev1 || d2 == dev2); - - _unref_(ei_event) *eseat = peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED); - struct ei_seat *s = ei_event_get_seat(eseat); - munit_assert_ptr_equal(s, seat); - } - - return MUNIT_OK; -} - -MUNIT_TEST(test_ei_seat_bind_unbind_noref) -{ - _unref_(peck) *peck = peck_new(); - struct ei_seat *seat = NULL; - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_UNBIND_SEAT); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNECT); - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED); - seat = ei_seat_ref(ei_event_get_seat(event)); - ei_seat_bind(seat); - } - - /* server has the Bind event now and creates devices */ - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_event) *e1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - _unref_(ei_event) *discard1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); - _unref_(ei_event) *e2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - _unref_(ei_event) *discard2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); - - /* Drop our ref before unbinding. This is technically wrong - - * must not use seat after unref, but we know there's at least - * one ref inside libei for this seat, so this tests ensures - * we don't rely on a caller ref to keep everything alive. */ - ei_seat_unref(seat); - ei_seat_unbind(seat); - } - - /* Dispatch, server is aware of the ei_seat_unbind() */ - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_event) *e1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - _unref_(ei_event) *e2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - _unref_(ei_event) *eseat = peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED); - } - - return MUNIT_OK; -} - -MUNIT_TEST(test_ei_seat_bind_unbind_immediately) -{ - _unref_(peck) *peck = peck_new(); - struct ei_seat *seat = NULL; - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_UNBIND_SEAT); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNECT); - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED); - seat = ei_event_get_seat(event); - ei_seat_bind(seat); - ei_seat_unbind(seat); - } - - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_event) *e1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - _unref_(ei_event) *e2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); - _unref_(ei_event) *e3 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - _unref_(ei_event) *e4 = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); - _unref_(ei_event) *e5 = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - _unref_(ei_event) *e6 = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - _unref_(ei_event) *e7 = peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED); - } - - return MUNIT_OK; -} - -MUNIT_TEST(test_ei_device_basics) -{ - _unref_(peck) *peck = peck_new(); - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); - peck_dispatch_until_stable(peck); - - with_server(peck) { - struct eis_seat *seat = peck_eis_get_default_seat(peck); - _unref_(eis_device) *device = eis_device_new(seat); - - eis_device_configure_name(device, "string is freed"); - munit_assert_string_equal(eis_device_get_name(device), "string is freed"); - - /* overwrite before eis_device_add() is possible */ - eis_device_configure_name(device, __func__); - munit_assert_string_equal(eis_device_get_name(device), __func__); - - munit_assert_false(eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER)); - munit_assert_false(eis_device_has_capability(device, EIS_DEVICE_CAP_KEYBOARD)); - munit_assert_false(eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE)); - munit_assert_false(eis_device_has_capability(device, EIS_DEVICE_CAP_TOUCH)); - - eis_device_configure_capability(device, EIS_DEVICE_CAP_POINTER); - munit_assert_true(eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER)); - eis_device_configure_capability(device, EIS_DEVICE_CAP_KEYBOARD); - munit_assert_true(eis_device_has_capability(device, EIS_DEVICE_CAP_KEYBOARD)); - - eis_device_add(device); - - /* device is read-only now */ - eis_device_configure_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE); - munit_assert_false(eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE)); - - eis_device_configure_name(device, "nope"); - munit_assert_string_equal(eis_device_get_name(device), __func__); - } - - peck_dispatch_ei(peck); - - /* device creation and getters/setters test */ - with_client(peck) { - _unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - struct ei_device *device = ei_event_get_device(event); - - munit_assert_not_null(device); - munit_assert_string_equal(ei_device_get_name(device), __func__); - - munit_assert_true(ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)); - munit_assert_true(ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD)); - munit_assert_false(ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)); - munit_assert_false(ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH)); - } - - return MUNIT_OK; -} - -MUNIT_TEST(test_ei_device_set_name_multiple_devices) -{ - _unref_(peck) *peck = peck_new(); - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT); - peck_dispatch_until_stable(peck); - - with_server(peck) { - struct eis_seat *seat = peck_eis_get_default_seat(peck); - _unref_(eis_device) *d1 = eis_device_new(seat); - eis_device_configure_name(d1, "first device"); - eis_device_configure_capability(d1, EIS_DEVICE_CAP_POINTER); - eis_device_add(d1); - - _unref_(eis_device) *d2 = eis_device_new(seat); - /* Unnamed */ - eis_device_add(d2); - - _unref_(eis_device) *d3 = eis_device_new(seat); - eis_device_configure_name(d3, "third device"); - eis_device_configure_capability(d3, EIS_DEVICE_CAP_POINTER); - eis_device_add(d3); - } - - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_event) *e1 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - struct ei_device *d1 = ei_event_get_device(e1); - munit_assert_string_equal(ei_device_get_name(d1), "first device"); - - _unref_(ei_event) *e2 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - struct ei_device *d2 = ei_event_get_device(e2); - munit_assert_string_equal(ei_device_get_name(d2), "unnamed device"); - - _unref_(ei_event) *e3 = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - struct ei_device *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_never_added) -{ - _unref_(peck) *peck = peck_new(); - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); - peck_dispatch_until_stable(peck); - - /* Unref after remove */ - with_server(peck) { - struct eis_seat *seat = peck_eis_get_default_seat(peck); - struct eis_device *device = eis_device_new(seat); - eis_device_remove(device); - eis_device_unref(device); - } - - peck_dispatch_until_stable(peck); - - /* device was never added, shouldn't show up */ - with_client(peck) { - peck_assert_no_ei_events(ei); - } - - /* unref before remove. - * - * This would be invalid client code since you can't expect to have - * a ref after unref, but since we know the device is still here, we - * can test for the lib being correct. - */ - with_server(peck) { - struct eis_seat *seat = peck_eis_get_default_seat(peck); - struct eis_device *device = eis_device_new(seat); - eis_device_unref(device); - eis_device_remove(device); - } - - peck_dispatch_until_stable(peck); - - with_client(peck) { - peck_assert_no_ei_events(ei); - } - - return MUNIT_OK; -} - -MUNIT_TEST(test_ei_device_add_remove) -{ - _unref_(peck) *peck = peck_new(); - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT); - peck_dispatch_until_stable(peck); - - _unref_(ei_device) *device = NULL; - _unref_(eis_device) *eis_device = NULL; - - with_server(peck) { - struct eis_seat *seat = peck_eis_get_default_seat(peck); - eis_device = eis_device_new(seat); - eis_device_configure_name(eis_device, __func__); - eis_device_configure_capability(eis_device, EIS_DEVICE_CAP_POINTER); - eis_device_add(eis_device); - } - - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_event) *event = - peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - device = ei_device_ref(ei_event_get_device(event)); - } - - with_server(peck) { - eis_device_remove(eis_device); - } - - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_event) *event = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - - munit_assert_ptr_equal(ei_event_get_device(event), device); - } - - return MUNIT_OK; -} - - -MUNIT_TEST(test_ei_device_pointer_rel) -{ - _unref_(peck) *peck = peck_new(); - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); - peck_dispatch_until_stable(peck); - - with_client(peck) { - struct ei_device *device = peck_ei_get_default_pointer(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) { - _unref_(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 */); - - _unref_(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 */); - - _unref_(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) -{ - _unref_(peck) *peck = peck_new(); - struct ei_device *device = NULL; - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER_ABSOLUTE); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); - peck_dispatch_until_stable(peck); - - /* FIXME: missing the currently unimplemented region checks */ - - with_client(peck) { - device = peck_ei_get_default_pointer_absolute(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++) { - _unref_(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); - - /* Don't auto-handle the DEVICE_CLOSED event */ - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE); - } - - with_client(peck) { - ei_device_close(device); - /* absmotion after remove must not trigger an event */ - ei_device_pointer_motion_absolute(device, 100, 200); - } - - peck_dispatch_until_stable(peck); - - with_server(peck) { - _unref_(eis_event) *e = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_CLOSED); - peck_assert_no_eis_events(eis); - } - - return MUNIT_OK; -} - -MUNIT_TEST(test_ei_device_touch) -{ - _unref_(peck) *peck = peck_new(); - struct ei_device *device = NULL; - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_TOUCH); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); - peck_dispatch_until_stable(peck); - - /* FIXME: missing the currently unimplemented region checks */ - - with_client(peck) { - device = peck_ei_get_default_touch(peck); - _unref_(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) { - _unref_(eis_event) *down = peck_eis_touch_down(eis, 1, 2); - uint32_t tid = eis_event_touch_get_id(down); - - _unref_(eis_event) *motion = peck_eis_touch_motion(eis, 200, 500); - munit_assert_uint32(eis_event_touch_get_id(motion), ==, tid); - - _unref_(eis_event) *up = peck_eis_touch_up(eis); - munit_assert_uint32(eis_event_touch_get_id(up), ==, tid); - } - - with_client(peck) { - _unref_(ei_touch) *t = ei_device_touch_new(device); - /* outside clip range, expect touch to be dropped */ - ei_touch_down(t, 1920, 1200); - ei_touch_motion(t, 1920, 1000); - ei_touch_up(t); - } - - peck_dispatch_until_stable(peck); - - with_server(peck) { - peck_assert_no_eis_events(eis); - } - - with_client(peck) { - _unref_(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, 1950, 200); - ei_touch_up(t); - } - - peck_dispatch_until_stable(peck); - - with_server(peck) { - _unref_(eis_event) *down = peck_eis_touch_down(eis, 100, 200); - _unref_(eis_event) *up = peck_eis_touch_up(eis); - } - - with_client(peck) { - _unref_(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) { - _unref_(eis_event) *down = peck_eis_touch_down(eis, 100, 100); - _unref_(eis_event) *up = peck_eis_touch_up(eis); - } - - with_client(peck) { - /* touch only allocated, not actually set down */ - _unref_(ei_touch) *t1 = ei_device_touch_new(device); - - /* touch never set down */ - _unref_(ei_touch) *t2 = ei_device_touch_new(device); - ei_touch_up(t2); - - /* touch never set down */ - _unref_(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 */ - _unref_(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) { - _unref_(eis_event) *down = peck_eis_touch_down(eis, 100, 200); - _unref_(eis_event) *up = peck_eis_touch_up(eis); - peck_assert_no_eis_events(eis); - } - - with_client(peck) { - /* double-down, double-up */ - _unref_(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) { - _unref_(eis_event) *down = peck_eis_touch_down(eis, 100, 200); - _unref_(eis_event) *motion = peck_eis_touch_motion(eis, 300, 400); - _unref_(eis_event) *up = peck_eis_touch_up(eis); - peck_assert_no_eis_events(eis); - } - - return MUNIT_OK; -} - -MUNIT_TEST(test_ei_device_multitouch) -{ - _unref_(peck) *peck = peck_new(); - struct ei_device *device = NULL; - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_TOUCH); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); - peck_dispatch_until_stable(peck); - - peck_dispatch_until_stable(peck); - - with_client(peck) { - device = peck_ei_get_default_touch(peck); - _unref_(ei_touch) *t1 = ei_device_touch_new(device); - _unref_(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) { - _unref_(eis_event) *down1 = peck_eis_touch_down(eis, 1, 2); - uint32_t tid1 = eis_event_touch_get_id(down1); - - _unref_(eis_event) *motion1 = peck_eis_touch_motion(eis, 2, 3); - munit_assert_uint32(eis_event_touch_get_id(motion1), ==, tid1); - - _unref_(eis_event) *down2 = peck_eis_touch_down(eis, 3, 4); - uint32_t tid2 = eis_event_touch_get_id(down2); - munit_assert_uint32(tid2, !=, tid1); - - _unref_(eis_event) *motion2 = peck_eis_touch_motion(eis, 4, 5); - munit_assert_uint32(eis_event_touch_get_id(motion2), ==, tid2); - - _unref_(eis_event) *up2 = peck_eis_touch_up(eis); - munit_assert_uint32(eis_event_touch_get_id(up2), ==, tid2); - - _unref_(eis_event) *up1 = peck_eis_touch_up(eis); - munit_assert_uint32(eis_event_touch_get_id(up1), ==, tid1); - } - - return MUNIT_OK; -} - -MUNIT_TEST(test_ei_keymap_invalid) -{ - /* FIXME: needs review after the switch to server-side devices */ - return MUNIT_SKIP; -#if 0 - const char data[5] = {1, 2, 3, 4, 5}; - _unref_(memfile) *fd = memfile_new(data, sizeof(data)); - - munit_assert_ptr_null(ei_keymap_new(EI_KEYMAP_TYPE_XKB + 1, - memfile_get_fd(fd), memfile_get_size(fd))); - munit_assert_ptr_null(ei_keymap_new(EI_KEYMAP_TYPE_XKB - 1, - memfile_get_fd(fd), memfile_get_size(fd))); - munit_assert_ptr_null(ei_keymap_new(EI_KEYMAP_TYPE_XKB, - -1, memfile_get_size(fd))); - munit_assert_ptr_null(ei_keymap_new(EI_KEYMAP_TYPE_XKB, - memfile_get_fd(fd), 0)); - - /* Valid keymap, valgrind checks only */ - _unref_(ei_keymap) *unused = - ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd), memfile_get_size(fd)); - munit_assert_ptr_not_null(unused); - - return MUNIT_OK; -#endif -} - -MUNIT_TEST(test_ei_keymap_set) -{ - /* FIXME: needs review after the switch to server-side devices */ - return MUNIT_SKIP; -#if 0 - const char data[5] = {1, 2, 3, 4, 5}; - _unref_(peck) *peck = peck_new(); - _unref_(ei_device) *device = NULL; - _unref_(memfile) *fd1 = memfile_new(data, sizeof(data)); - _unref_(ei_keymap) *keymap = NULL; - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(memfile) *fd2 = memfile_new(data, sizeof(data)); - - struct ei_seat *seat = peck_ei_get_default_seat(peck); - device = ei_device_new(seat); - ei_device_configure_name(device, __func__); - ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD); - - keymap = ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd1), memfile_get_size(fd1)); - ei_device_keyboard_configure_keymap(device, keymap); - munit_assert_ptr_equal(ei_device_keyboard_get_keymap(device), keymap); - - /* Not possible to overwrite a keymap on a device */ - _unref_(ei_keymap) *overwrite = - ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd2), memfile_get_size(fd2)); - ei_device_keyboard_configure_keymap(device, overwrite); - munit_assert_ptr_equal(ei_device_keyboard_get_keymap(device), keymap); - - ei_device_add(device); - - /* Still impossible to overwrite after add */ - _unref_(ei_keymap) *ignored = - ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd2), memfile_get_size(fd2)); - ei_device_keyboard_configure_keymap(device, ignored); - munit_assert_ptr_equal(ei_device_keyboard_get_keymap(device), keymap); - } - - peck_dispatch_until_stable(peck); - - with_server(peck) { - _unref_(eis_event) *event = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); - struct eis_device *eis_device = eis_event_get_device(event); - struct eis_keymap *eis_keymap = eis_device_keyboard_get_keymap(eis_device); - - int fd = eis_keymap_get_fd(eis_keymap); - munit_assert_int(fd, !=, -1); - munit_assert_uint(eis_keymap_get_size(eis_keymap), ==, memfile_get_size(fd1)); - munit_assert_uint(eis_keymap_get_type(eis_keymap), ==, EIS_KEYMAP_TYPE_XKB); - eis_device_disconnect(eis_device); - } - - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_event) *event = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - struct ei_device *d = ei_event_get_device(event); - munit_assert_ptr_equal(d, device); - - /* Rejecting a device does not unset the keymap because - * you're not supposed to do anything with the device anyway */ - struct ei_keymap *km = ei_device_keyboard_get_keymap(device); - munit_assert_ptr_equal(keymap, km); - munit_assert_int(ei_keymap_get_source(keymap), ==, EI_KEYMAP_SOURCE_CLIENT); - } - - return MUNIT_OK; -#endif -} - -MUNIT_TEST(test_ei_keymap_null) -{ - /* FIXME: needs review after the switch to server-side devices */ - return MUNIT_SKIP; -#if 0 - const char data[5] = {1, 2, 3, 4, 5}; - _unref_(peck) *peck = peck_new(); - _unref_(memfile) *fd = memfile_new(data, sizeof(data)); - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNNECT); - peck_dispatch_until_stable(peck); - - with_client(peck) { - struct ei_seat *seat = peck_ei_get_default_seat(peck); - _unref_(ei_device) *device = ei_device_new(seat); - ei_device_configure_name(device, __func__); - ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD); - - _unref_(ei_keymap) *keymap = - ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd), memfile_get_size(fd)); - ei_device_keyboard_configure_keymap(device, keymap); - ei_device_add(device); - } - - peck_dispatch_until_stable(peck); - - /* server sets the keymap to NULL */ - with_server(peck) { - _unref_(eis_event) *event = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); - struct eis_device *device = eis_event_get_device(event); - eis_device_keyboard_set_keymap(device, NULL); - eis_device_allow_capability(device, EIS_DEVICE_CAP_KEYBOARD); - eis_device_connect(device); - } - - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_event) *event = - peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - struct ei_device *device = ei_event_get_device(event); - - struct ei_keymap *keymap = ei_device_keyboard_get_keymap(device); - munit_assert_ptr_null(keymap); - } - - return MUNIT_OK; -#endif -} - -MUNIT_TEST(test_ei_keymap_changed) -{ - /* FIXME: needs review after the switch to server-side devices */ - return MUNIT_SKIP; -#if 0 - const char data[5] = {1, 2, 3, 4, 5}; - _unref_(peck) *peck = peck_new(); - _unref_(memfile) *fd1 = memfile_new(data, sizeof(data)); - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNNECT); - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_device) *device = NULL; - const char otherdata[2] = {10, 20}; - _unref_(memfile) *fd2 = memfile_new(data, sizeof(otherdata)); - - struct ei_seat *seat = peck_ei_get_default_seat(peck); - device = ei_device_new(seat); - ei_device_configure_name(device, __func__); - ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD); - - _unref_(ei_keymap) *keymap = - ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd2), memfile_get_size(fd2)); - ei_device_keyboard_configure_keymap(device, keymap); - ei_device_add(device); - } - - peck_dispatch_until_stable(peck); - - /* server sets the keymap to some other fd */ - with_server(peck) { - _unref_(eis_event) *event = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); - struct eis_device *device = eis_event_get_device(event); - _unref_(eis_keymap) *keymap = - eis_keymap_new(EIS_KEYMAP_TYPE_XKB, memfile_get_fd(fd1), - memfile_get_size(fd1)); - eis_device_keyboard_set_keymap(device, keymap); - eis_device_allow_capability(device, EIS_DEVICE_CAP_KEYBOARD); - eis_device_connect(device); - } - - peck_dispatch_until_stable(peck); - - with_client(peck) { - _unref_(ei_event) *event = - peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - struct ei_device *device = ei_event_get_device(event); - - struct ei_keymap *keymap = ei_device_keyboard_get_keymap(device); - munit_assert_ptr_not_null(keymap); - - munit_assert_int(ei_keymap_get_type(keymap), ==, EI_KEYMAP_TYPE_XKB); - munit_assert_int(ei_keymap_get_source(keymap), ==, EI_KEYMAP_SOURCE_SERVER); - int km = ei_keymap_get_fd(keymap); - - char buf[5]; - int rc = min(xread(km, buf, sizeof(buf)), 0); - peck_errno_check(rc); - munit_assert_int(memcmp(buf, data, sizeof(buf)), ==, 0); - } - - return MUNIT_OK; -#endif -} - /* Emulates the XWayland behavior for calling * xdotool mousemove_relative -- -1 10 */