diff --git a/meson.build b/meson.build index e224c24..627079b 100644 --- a/meson.build +++ b/meson.build @@ -184,107 +184,104 @@ if get_option('portal') endif # tests -subproject('munit') +if get_option('tests') + subproject('munit') -munit = dependency('munit', fallback: ['munit', 'munit_dep']) + munit = dependency('munit', fallback: ['munit', 'munit_dep']) -lib_unittest = static_library('unittest', - 'src/util-munit.h', - 'src/util-munit.c', - dependencies: munit, -) + lib_unittest = static_library('unittest', + 'src/util-munit.h', + 'src/util-munit.c', + dependencies: munit, + ) -dep_unittest = declare_dependency( - link_with: lib_unittest, - dependencies: munit -) + dep_unittest = declare_dependency( + link_with: lib_unittest, + dependencies: munit + ) -test('unit-tests-utils', - executable('unit-tests-utils', - 'test/unit-tests.c', - src_libutil, - include_directories: 'src', - c_args: ['-D_enable_tests_'], - dependencies: [dep_unittest])) + test('unit-tests-utils', + executable('unit-tests-utils', + 'test/unit-tests.c', + src_libutil, + include_directories: 'src', + c_args: ['-D_enable_tests_'], + dependencies: [dep_unittest])) -test('unit-tests-ei', - executable('unit-tests-ei', - 'test/unit-tests.c', - src_libei, - include_directories: 'src', - c_args: ['-D_enable_tests_'], - dependencies: deps_libei + [dep_unittest])) + test('unit-tests-ei', + executable('unit-tests-ei', + 'test/unit-tests.c', + src_libei, + include_directories: 'src', + c_args: ['-D_enable_tests_'], + dependencies: deps_libei + [dep_unittest])) -test('unit-tests-eis', - executable('unit-tests-eis', - 'test/unit-tests.c', - src_libeis, - include_directories: 'src', - c_args: ['-D_enable_tests_'], - dependencies: [dep_unittest, dep_libutil, dep_protobuf])) + test('unit-tests-eis', + executable('unit-tests-eis', + 'test/unit-tests.c', + src_libeis, + include_directories: 'src', + c_args: ['-D_enable_tests_'], + dependencies: [dep_unittest, dep_libutil, dep_protobuf])) -lib_eierpecken = static_library('eierpecken', - 'test/eierpecken.h', - 'test/eierpecken.c', - include_directories: 'src', - dependencies: [munit, dep_libutil, dep_libei, dep_libeis], -) + lib_eierpecken = static_library('eierpecken', + 'test/eierpecken.h', + 'test/eierpecken.c', + include_directories: 'src', + dependencies: [munit, dep_libutil, dep_libei, dep_libeis], + ) -test('libei-integration-test', - executable('eitest', - 'test/test-ei.c', - link_with: lib_eierpecken, - dependencies: [dep_unittest, dep_libei, dep_libeis])) + test('libei-integration-test', + executable('eitest', + 'test/test-main.c', + 'test/test-ei.c', + 'test/test-eis.c', + link_with: lib_eierpecken, + dependencies: [dep_unittest, dep_libei, dep_libeis])) -test('libeis-integration-test', - executable('eistest', - 'test/test-eis.c', - link_with: lib_eierpecken, - dependencies: [dep_unittest, dep_libei, dep_libeis])) - - -valgrind = find_program('valgrind', required : false) -if valgrind.found() - add_test_setup('valgrind', - exe_wrapper : [ valgrind, - '--leak-check=full', - '--gen-suppressions=all', - '--error-exitcode=3' ], - timeout_multiplier : 100) -else - message('valgrind not found, disabling valgrind test suite') -endif + valgrind = find_program('valgrind', required : false) + if valgrind.found() + add_test_setup('valgrind', + exe_wrapper : [ valgrind, + '--leak-check=full', + '--gen-suppressions=all', + '--error-exitcode=3' ], + timeout_multiplier : 100) + else + message('valgrind not found, disabling valgrind test suite') + endif # build-test only -executable('test-build-libei', - 'test/buildtest.c', - dependencies : [dep_libei], - include_directories : 'src', - c_args : ['-Werror', '-DINCLUDE_LIBEI=1'], - install : false) + executable('test-build-libei', + 'test/buildtest.c', + dependencies : [dep_libei], + include_directories : 'src', + c_args : ['-Werror', '-DINCLUDE_LIBEI=1'], + install : false) -executable('test-build-libeis', - 'test/buildtest.c', - dependencies : [dep_libeis], - include_directories : 'src', - c_args : ['-Werror', '-DINCLUDE_LIBEIS=1'], - install : false) + executable('test-build-libeis', + 'test/buildtest.c', + dependencies : [dep_libeis], + include_directories : 'src', + c_args : ['-Werror', '-DINCLUDE_LIBEIS=1'], + install : false) -executable('test-build-libreis', - 'test/buildtest.c', - dependencies : [dep_libreis], - include_directories : 'src', - c_args : ['-Werror', '-DINCLUDE_LIBREIS=1'], - install : false) + executable('test-build-libreis', + 'test/buildtest.c', + dependencies : [dep_libreis], + include_directories : 'src', + c_args : ['-Werror', '-DINCLUDE_LIBREIS=1'], + install : false) -if add_languages('cpp', required: false) - executable('test-build-cxx', - 'test/buildtest.cc', - dependencies: [dep_libei, dep_libeis], - include_directories: 'src', - install: false) -endif + if add_languages('cpp', required: false) + executable('test-build-cxx', + 'test/buildtest.cc', + dependencies: [dep_libei, dep_libeis], + include_directories: 'src', + install: false) + endif +endif # tests configure_file(output: 'config.h', configuration: config_h) diff --git a/meson_options.txt b/meson_options.txt index 98f8f99..cbd4b9f 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,2 +1,3 @@ option('portal', type: 'boolean', value: 'true', description: 'Enable/disable org.freedesktop.portal support') option('documentation', type: 'boolean', value: 'true', description: 'Enable/disable building the API documentation') +option('tests', type: 'boolean', value: 'true', description: 'Enable/disable tests') diff --git a/proto/ei.proto b/proto/ei.proto index 58b4102..f71213f 100644 --- a/proto/ei.proto +++ b/proto/ei.proto @@ -16,24 +16,16 @@ syntax = "proto3"; * 2.a - server replies with "Connected" or * 2.b - server replies with "Disconnected" and closes its end of the socket * 3. - server sends "AddSeat" (once or multiple times) - * 4. - client sends "AddDevice" for a specific seat - * 4.a - server replies with "DeviceAdded" or - * 4.b - server replies with "DeviceRemoved" + * 4. - client sends "BindSeat" for each seat + * 5. - server sends "DeviceAdded" for any device on this seat * 5. - server sends "DeviceResumed" * 6. - client sends "PointerRelative" or any other event - * 7. - client sends "RemoveDevice" + * 7. - client sends "CloseDevice" * 8. - client sends "Disconnect" and closes its end of the socket * * The server may send Disconnect at any time. - * The server may send Removed for a device at any time after that device's - * Accepted. - * - * Where a server does not accept a client's device it is up to the client - * to decide whether to Disconnect. - * Where a server does not accept a client's device the server may send Removed - * for all current client devices and send Disconnected before closing the - * connection. IOW a client trying to create a device may result in the - * client being disconnected. This decision is up to server policy. + * The server may send SeatRemoved for a device at any time. + * The server may send DeviceRemoved for a device at any time. * * Where a connection error occurs, the library (libei or libeis) will * unroll the state as seen from the API. i.e. @@ -81,21 +73,16 @@ message Connect { message Disconnect { } -message AddDevice { - uint32 deviceid = 1; +message BindSeat { + uint32 seatid = 1; uint32 capabilities = 2; - uint32 pointer_width = 3; - uint32 pointer_height = 4; - uint32 touch_width = 5; - uint32 touch_height = 6; - /* keymap is passed as fd if type is not none */ - uint32 keymap_type = 8; - uint32 keymap_size = 9; - string name = 10; - uint32 seat = 11; } -message RemoveDevice { +message UnbindSeat { + uint32 seatid = 1; +} + +message CloseDevice { uint32 deviceid = 1; } @@ -148,17 +135,18 @@ message ClientMessage { oneof msg { Connect connect = 1; Disconnect disconnect = 2; - AddDevice add_device = 3; - RemoveDevice remove_device = 4; - PointerRelative rel = 5; - PointerAbsolute abs = 6; - Scroll scroll = 7; - ScrollDiscrete disc = 8; - PointerButton button = 9; - KeyboardKey key = 10; - Touch touch = 11; - ConfigureName configure_name = 12; - ConfigureCapabilities configure_caps = 13; + BindSeat bind_seat = 3; + UnbindSeat unbind_seat = 4; + CloseDevice close_device = 5; + PointerRelative rel = 6; + PointerAbsolute abs = 7; + Scroll scroll = 8; + ScrollDiscrete disc = 9; + PointerButton button = 10; + KeyboardKey key = 11; + Touch touch = 12; + ConfigureName configure_name = 13; + ConfigureCapabilities configure_caps = 14; } } @@ -187,6 +175,10 @@ message DeviceAdded { uint32 keymap_size = 5; string name = 6; uint32 seatid = 7; + uint32 pointer_width = 8; + uint32 pointer_height = 9; + uint32 touch_width = 10; + uint32 touch_height = 11; } message DeviceRemoved { diff --git a/src/libei-device.c b/src/libei-device.c index 8f7e500..9b2a0e1 100644 --- a/src/libei-device.c +++ b/src/libei-device.c @@ -37,8 +37,6 @@ static const char * ei_device_state_to_string(enum ei_device_state state) { switch (state) { - CASE_RETURN_STRING(EI_DEVICE_STATE_NEW); - CASE_RETURN_STRING(EI_DEVICE_STATE_CONNECTING); CASE_RETURN_STRING(EI_DEVICE_STATE_SUSPENDED); CASE_RETURN_STRING(EI_DEVICE_STATE_RESUMED); CASE_RETURN_STRING(EI_DEVICE_STATE_REMOVED_FROM_CLIENT); @@ -100,93 +98,29 @@ ei_device_get_context(struct ei_device *device) return ei_seat_get_context(ei_device_get_seat(device)); } -_public_ struct ei_device * -ei_device_new(struct ei_seat *seat) +struct ei_device * +ei_device_new(struct ei_seat *seat, uint32_t deviceid) { - /* device IDs are managed by the client, the server merely accepts - * them and fails where they're being reused. */ - static uint32_t deviceid = 0; struct ei_device *device = ei_device_create(&seat->object); device->capabilities = 0; - device->id = seat->id | ++deviceid; - device->state = EI_DEVICE_STATE_NEW; + device->id = deviceid; + device->state = EI_DEVICE_STATE_SUSPENDED; device->name = xaprintf("unnamed device %d", device->id); /* We have a ref to the seat to make sure our seat doesn't get * destroyed while a ref to the device is still alive. - * And the seat has a ref to the device, dropped when the device - * state changes to DEAD (ei_device_remove()). + * And the seat has a ref to the device in the seat->devices list. + * dropped when the device state changes to DEAD (ei_device_remove()). */ ei_seat_ref(seat); - ei_device_ref(device); + /* this list "owns" the ref for this device */ list_append(&seat->devices, &device->link); return device; } -_public_ void -ei_device_configure_name(struct ei_device *device, const char *name) -{ - if (device->state != EI_DEVICE_STATE_NEW) - return; - - free(device->name); - device->name = xstrdup(name); -} - -_public_ bool -ei_device_configure_capability(struct ei_device *device, - enum ei_device_capability cap) -{ - if (device->state != EI_DEVICE_STATE_NEW) - return false; - - switch (cap) { - case EI_DEVICE_CAP_POINTER: - case EI_DEVICE_CAP_POINTER_ABSOLUTE: - case EI_DEVICE_CAP_KEYBOARD: - case EI_DEVICE_CAP_TOUCH: - device->capabilities |= bit(cap); - return true; - } - - return false; -} - -_public_ void -ei_device_pointer_configure_range(struct ei_device *device, - uint32_t width, - uint32_t height) -{ - if (device->state != EI_DEVICE_STATE_NEW || - !flag_is_set(device->capabilities, EI_DEVICE_CAP_POINTER_ABSOLUTE)) - return; - - if (width == 0 || height == 0) - return; - - device->abs.dim.width = width; - device->abs.dim.height = height; -} - -_public_ void -ei_device_touch_configure_range(struct ei_device *device, - uint32_t width, - uint32_t height) -{ - if (device->state != EI_DEVICE_STATE_NEW || - !flag_is_set(device->capabilities, EI_DEVICE_CAP_TOUCH)) - return; - - if (width == 0 || height == 0) - return; - - device->touch.dim.width = width; - device->touch.dim.height = height; -} - _public_ OBJECT_IMPLEMENT_REF(ei_keymap); _public_ @@ -227,12 +161,6 @@ ei_device_keyboard_configure_keymap(struct ei_device *device, return; } - if (device->state != EI_DEVICE_STATE_NEW) { - log_bug_client(ei_device_get_context(device), - "%s: Device has already been added\n", __func__); - return; - } - /* Can only call this once */ if (device->keymap) { log_bug_client(ei_device_get_context(device), @@ -307,69 +235,19 @@ ei_device_set_keymap(struct ei_device *device, device->keymap = ei_keymap_ref(keymap); } -_public_ void -ei_device_add(struct ei_device *device) -{ - struct ei_seat *seat = ei_device_get_seat(device); - - switch (device->state) { - case EI_DEVICE_STATE_NEW: - /* If the caller tries to add a device to a seat that has - * been removed, immediately drop that device. But since our - * SEAT_REMOVED event may still be in the queue, prepend the - * device to the rest of the queue. - */ - if (seat->state == EI_SEAT_STATE_REMOVED) { - ei_insert_device_removed_event(device); - ei_device_set_state(device, EI_DEVICE_STATE_DEAD); - ei_device_unref(device); - return; - } - break; - case EI_DEVICE_STATE_REMOVED_FROM_CLIENT: - case EI_DEVICE_STATE_REMOVED_FROM_SERVER: - case EI_DEVICE_STATE_CONNECTING: - case EI_DEVICE_STATE_SUSPENDED: - case EI_DEVICE_STATE_RESUMED: - case EI_DEVICE_STATE_DEAD: - log_bug_client(ei_device_get_context(device), - "%s: device %s added twice by client\n", - __func__, device->name); - return; - } - - if (ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE) && - (device->abs.dim.width == 0 || device->abs.dim.height == 0)) - log_bug_client(ei_device_get_context(device), - "%s: device %s is missing an abs pointer range\n", - __func__, device->name); - - if (ei_send_add_device(device) == 0) - ei_device_set_state(device, EI_DEVICE_STATE_CONNECTING); -} _public_ void -ei_device_remove(struct ei_device *device) +ei_device_close(struct ei_device *device) { switch (device->state) { - case EI_DEVICE_STATE_NEW: - ei_device_set_state(device, EI_DEVICE_STATE_DEAD); - ei_device_unref(device); - break; case EI_DEVICE_STATE_DEAD: case EI_DEVICE_STATE_REMOVED_FROM_CLIENT: - break; case EI_DEVICE_STATE_REMOVED_FROM_SERVER: - /* device is properly dead now */ - ei_device_set_state(device, EI_DEVICE_STATE_DEAD); - ei_send_remove_device(device); - ei_device_unref(device); break; - case EI_DEVICE_STATE_CONNECTING: case EI_DEVICE_STATE_SUSPENDED: case EI_DEVICE_STATE_RESUMED: ei_device_set_state(device, EI_DEVICE_STATE_REMOVED_FROM_CLIENT); - ei_send_remove_device(device); + ei_send_close_device(device); break; } } @@ -378,27 +256,20 @@ void ei_device_removed_by_server(struct ei_device *device) { switch (device->state) { - case EI_DEVICE_STATE_NEW: case EI_DEVICE_STATE_DEAD: case EI_DEVICE_STATE_REMOVED_FROM_SERVER: break; case EI_DEVICE_STATE_REMOVED_FROM_CLIENT: - /* device is properly dead now */ - ei_queue_device_removed_event(device); - ei_device_set_state(device, EI_DEVICE_STATE_DEAD); - ei_device_unref(device); - break; - case EI_DEVICE_STATE_CONNECTING: - /* Device never seen by server, but our client still thinks - * it's there */ - ei_queue_device_removed_event(device); - ei_device_set_state(device, EI_DEVICE_STATE_DEAD); - ei_device_unref(device); - break; case EI_DEVICE_STATE_SUSPENDED: case EI_DEVICE_STATE_RESUMED: ei_queue_device_removed_event(device); - ei_device_set_state(device, EI_DEVICE_STATE_REMOVED_FROM_SERVER); + ei_device_set_state(device, EI_DEVICE_STATE_DEAD); + /* This should be the last ref to the device that libei has + * (not counting any queued events). Device is still in the + * seat->device list, will be removed from that when all + * remaining refs are at 0. + */ + ei_device_unref(device); /* the ref in the seat list */ break; } } @@ -435,6 +306,20 @@ ei_device_set_capabilities(struct ei_device *device, device->capabilities = capabilities; } +void +ei_device_set_pointer_range(struct ei_device *device, uint32_t w, uint32_t h) +{ + device->abs.dim.width = w; + device->abs.dim.height = h; +} + +void +ei_device_set_touch_range(struct ei_device *device, uint32_t w, uint32_t h) +{ + device->touch.dim.width = w; + device->touch.dim.height = h; +} + _public_ bool ei_device_has_capability(struct ei_device *device, enum ei_device_capability cap) @@ -664,196 +549,3 @@ ei_touch_up(struct ei_touch *touch) touch->state = TOUCH_IS_UP; ei_send_touch_up(touch->device, touch->tracking_id); } - - -#ifdef _enable_tests_ -#include "src/util-munit.h" -#include "src/util-memfile.h" - -#define FAKE_SEAT(_seat) \ - struct ei ei_##__LINE__ = { 0 }; \ - struct ei_seat seat_##__LINE__ = { \ - .object = { \ - .parent = &ei_##__LINE__.object, \ - .refcount = 1, \ - }, \ - .id = __LINE__ << 16, \ - .capabilities = ~0, \ - .name = "default", \ - }; \ - list_init(&seat_##__LINE__.link); \ - list_init(&seat_##__LINE__.devices); \ - list_init(&seat_##__LINE__.devices_pending); \ - struct ei_seat *_seat = &seat_ ## __LINE__; - -MUNIT_TEST(test_device_new) -{ - FAKE_SEAT(seat); - struct ei_device *d = ei_device_new(seat); - - munit_assert_int(d->id, >, 0); - munit_assert_int(d->capabilities, ==, 0); - munit_assert_int(d->state, ==, EI_DEVICE_STATE_NEW); - - struct ei_device *unrefd = ei_device_unref(d); - munit_assert_ptr_null(unrefd); - - ei_device_remove(d); - - return MUNIT_OK; -} - -MUNIT_TEST(test_device_ids) -{ - FAKE_SEAT(seat); - _unref_(ei_device) *d1 = ei_device_new(seat); - _unref_(ei_device) *d2 = ei_device_new(seat); - _unref_(ei_device) *d3 = ei_device_new(seat); - - munit_assert_int(d1->id, <, d2->id); - munit_assert_int(d1->id, <, d3->id); - munit_assert_int(d2->id, <, d3->id); - - ei_device_remove(d1); - ei_device_remove(d2); - ei_device_remove(d3); - - return MUNIT_OK; -} - -MUNIT_TEST(test_device_ref_unref) -{ - FAKE_SEAT(seat); - struct ei_device *d = ei_device_new(seat); - - munit_assert_int(d->object.refcount, ==, 2); - - struct ei_device *refd = ei_device_ref(d); - munit_assert_ptr_equal(d, refd); - munit_assert_int(d->object.refcount, ==, 3); - - struct ei_device *unrefd = ei_device_unref(d); - munit_assert_ptr_null(unrefd); - munit_assert_int(d->object.refcount, ==, 2); - - ei_device_remove(d); - munit_assert_int(d->object.refcount, ==, 1); - - unrefd = ei_device_unref(d); - munit_assert_ptr_null(unrefd); - - return MUNIT_OK; -} - -MUNIT_TEST(test_device_cap) -{ - FAKE_SEAT(seat); - _unref_(ei_device) *d = ei_device_new(seat); - - munit_assert(ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER)); - /* twice is fine */ - munit_assert(ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER)); - munit_assert(ei_device_has_capability(d, EI_DEVICE_CAP_POINTER)); - - munit_assert(ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER_ABSOLUTE)); - munit_assert(ei_device_has_capability(d, EI_DEVICE_CAP_POINTER_ABSOLUTE)); - - munit_assert(ei_device_configure_capability(d, EI_DEVICE_CAP_KEYBOARD)); - munit_assert(ei_device_has_capability(d, EI_DEVICE_CAP_KEYBOARD)); - - munit_assert(ei_device_configure_capability(d, EI_DEVICE_CAP_TOUCH)); - munit_assert(ei_device_has_capability(d, EI_DEVICE_CAP_TOUCH)); - - /* Invalid caps */ - munit_assert(!ei_device_configure_capability(d, 0)); - munit_assert(!ei_device_has_capability(d, 0)); - munit_assert(!ei_device_configure_capability(d, EI_DEVICE_CAP_TOUCH + 1)); - munit_assert(!ei_device_has_capability(d, EI_DEVICE_CAP_TOUCH + 1)); - - ei_device_remove(d); - - return MUNIT_OK; -} - -MUNIT_TEST(test_device_get_seat) -{ - FAKE_SEAT(seat); - _unref_(ei_device) *d = ei_device_new(seat); - - munit_assert_ptr_equal(d->object.parent, seat); - munit_assert_ptr_equal(ei_device_get_seat(d), seat); - - ei_device_remove(d); - - return MUNIT_OK; -} - -MUNIT_TEST(test_device_pointer_ranges) -{ - FAKE_SEAT(seat); - _unref_(ei_device) *d = ei_device_new(seat); - - /* Missing the cap */ - ei_device_pointer_configure_range(d, 1920, 1200); - munit_assert_int(ei_device_pointer_get_width(d), ==, 0); - munit_assert_int(ei_device_pointer_get_height(d), ==, 0); - - munit_assert(ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER_ABSOLUTE)); - - ei_device_pointer_configure_range(d, 1024, 768); - munit_assert_int(ei_device_pointer_get_width(d), ==, 1024); - munit_assert_int(ei_device_pointer_get_height(d), ==, 768); - - /* Twice is fine before adding the device */ - ei_device_pointer_configure_range(d, 640, 480); - munit_assert_int(ei_device_pointer_get_width(d), ==, 640); - munit_assert_int(ei_device_pointer_get_height(d), ==, 480); - - /* But zero is silently rejected */ - ei_device_pointer_configure_range(d, 0, 480); - munit_assert_int(ei_device_pointer_get_width(d), ==, 640); - munit_assert_int(ei_device_pointer_get_height(d), ==, 480); - ei_device_pointer_configure_range(d, 640, 0); - munit_assert_int(ei_device_pointer_get_width(d), ==, 640); - munit_assert_int(ei_device_pointer_get_height(d), ==, 480); - - ei_device_remove(d); - - return MUNIT_OK; -} - -MUNIT_TEST(test_device_touch_ranges) -{ - FAKE_SEAT(seat); - _unref_(ei_device) *d = ei_device_new(seat); - - /* Missing the cap */ - ei_device_touch_configure_range(d, 1920, 1200); - munit_assert_int(ei_device_touch_get_width(d), ==, 0); - munit_assert_int(ei_device_touch_get_height(d), ==, 0); - - munit_assert(ei_device_configure_capability(d, EI_DEVICE_CAP_TOUCH)); - - ei_device_touch_configure_range(d, 1024, 768); - munit_assert_int(ei_device_touch_get_width(d), ==, 1024); - munit_assert_int(ei_device_touch_get_height(d), ==, 768); - - /* Twice is fine before adding the device */ - ei_device_touch_configure_range(d, 640, 480); - munit_assert_int(ei_device_touch_get_width(d), ==, 640); - munit_assert_int(ei_device_touch_get_height(d), ==, 480); - - /* But zero is silently rejected */ - ei_device_touch_configure_range(d, 0, 480); - munit_assert_int(ei_device_touch_get_width(d), ==, 640); - munit_assert_int(ei_device_touch_get_height(d), ==, 480); - ei_device_touch_configure_range(d, 640, 0); - munit_assert_int(ei_device_touch_get_width(d), ==, 640); - munit_assert_int(ei_device_touch_get_height(d), ==, 480); - - ei_device_remove(d); - - return MUNIT_OK; -} - -#endif diff --git a/src/libei-private.h b/src/libei-private.h index 1b7f57f..3fdf3f4 100644 --- a/src/libei-private.h +++ b/src/libei-private.h @@ -65,7 +65,9 @@ struct ei { }; enum ei_seat_state { - EI_SEAT_STATE_PRESENT, + EI_SEAT_STATE_NEW, + EI_SEAT_STATE_BOUND, + EI_SEAT_STATE_UNBOUND, EI_SEAT_STATE_REMOVED, }; @@ -74,17 +76,14 @@ struct ei_seat { void *user_data; struct list link; enum ei_seat_state state; - /* devices created by client but not yet added */ - struct list devices_pending; struct list devices; uint32_t id; uint32_t capabilities; + uint32_t capabilities_mask; char *name; }; enum ei_device_state { - EI_DEVICE_STATE_NEW, - EI_DEVICE_STATE_CONNECTING, EI_DEVICE_STATE_SUSPENDED, EI_DEVICE_STATE_RESUMED, /** @@ -175,10 +174,13 @@ void ei_seat_drop(struct ei_seat *seat); int -ei_send_add_device(struct ei_device *device); +ei_send_seat_bind(struct ei_seat *seat, uint32_t capabilities); int -ei_send_remove_device(struct ei_device *device); +ei_send_seat_unbind(struct ei_seat *seat); + +int +ei_send_close_device(struct ei_device *device); void ei_queue_device_removed_event(struct ei_device *device); @@ -189,6 +191,9 @@ ei_insert_device_removed_event(struct ei_device *device); void ei_queue_seat_removed_event(struct ei_seat *seat); +struct ei_device * +ei_device_new(struct ei_seat *seat, uint32_t deviceid); + void ei_device_removed_by_server(struct ei_device *device); @@ -243,6 +248,10 @@ ei_device_set_seat(struct ei_device *device, const char *seat); void ei_device_set_capabilities(struct ei_device *device, uint32_t capabilities); +void +ei_device_set_pointer_range(struct ei_device *device, uint32_t w, uint32_t h); +void +ei_device_set_touch_range(struct ei_device *device, uint32_t w, uint32_t h); void ei_device_set_keymap(struct ei_device *device, diff --git a/src/libei-proto.c b/src/libei-proto.c index 061538a..ff42694 100644 --- a/src/libei-proto.c +++ b/src/libei-proto.c @@ -113,6 +113,10 @@ ei_proto_parse_message(struct brei_message *bmsg, size_t *consumed) .device_added.keymap_from_server = a->keymap_from_server, .device_added.keymap_size = a->keymap_size, .device_added.seatid = a->seatid, + .device_added.pointer_width = a->pointer_width, + .device_added.pointer_height = a->pointer_height, + .device_added.touch_width = a->touch_width, + .device_added.touch_height = a->touch_height, }; if (a->keymap_type && a->keymap_from_server) msg->device_added.keymap_fd = brei_message_take_fd(bmsg); @@ -166,8 +170,9 @@ log_wire_message(struct ei *ei, const ClientMessage *msg, int error) abort(); MSG_STRING_CASE(CONNECT); MSG_STRING_CASE(DISCONNECT); - MSG_STRING_CASE(ADD_DEVICE); - MSG_STRING_CASE(REMOVE_DEVICE); + MSG_STRING_CASE(BIND_SEAT); + MSG_STRING_CASE(UNBIND_SEAT); + MSG_STRING_CASE(CLOSE_DEVICE); MSG_STRING_CASE(REL); MSG_STRING_CASE(ABS); MSG_STRING_CASE(BUTTON); @@ -206,7 +211,7 @@ ei_proto_send_msg(struct ei *ei, const ClientMessage *msg) return rc; } -static int +_unused_ static int ei_proto_send_msg_with_fds(struct ei *ei, const ClientMessage *msg, int *fds) { size_t msglen = client_message__get_packed_size(msg); @@ -250,47 +255,44 @@ ei_proto_send_disconnect(struct ei *ei) } int -ei_proto_send_add(struct ei *ei, struct ei_device *device) +ei_proto_send_bind_seat(struct ei *ei, struct ei_seat *seat, uint32_t capabilities) { ClientMessage msg = CLIENT_MESSAGE__INIT; - AddDevice add = ADD_DEVICE__INIT; - struct ei_seat *seat = ei_device_get_seat(device); + BindSeat bind = BIND_SEAT__INIT; - add.deviceid = device->id; - add.name = device->name; - add.capabilities = device->capabilities; - add.pointer_width = device->abs.dim.width; - add.pointer_height = device->abs.dim.height; - add.touch_width = device->touch.dim.width; - add.touch_height = device->touch.dim.height; - add.keymap_type = 0; + bind.seatid = seat->id; + bind.capabilities = capabilities; - int fd[2] = {-1, -1}; + msg.bind_seat = &bind; + msg.msg_case = CLIENT_MESSAGE__MSG_BIND_SEAT; - struct ei_keymap *keymap = device->keymap; - if (keymap) { - add.keymap_type = ei_keymap_get_type(keymap); - add.keymap_size = ei_keymap_get_size(keymap); - fd[0] = ei_keymap_get_fd(keymap); - } - add.seat = seat->id; - - msg.add_device = &add; - msg.msg_case = CLIENT_MESSAGE__MSG_ADD_DEVICE; - - return ei_proto_send_msg_with_fds(ei, &msg, fd); + return ei_proto_send_msg(ei, &msg); } int -ei_proto_send_remove(struct ei *ei, struct ei_device *device) +ei_proto_send_unbind_seat(struct ei *ei, struct ei_seat *seat) { ClientMessage msg = CLIENT_MESSAGE__INIT; - RemoveDevice remove = REMOVE_DEVICE__INIT; + UnbindSeat unbind = UNBIND_SEAT__INIT; - remove.deviceid = device->id; + unbind.seatid = seat->id; - msg.remove_device = &remove; - msg.msg_case = CLIENT_MESSAGE__MSG_REMOVE_DEVICE; + msg.unbind_seat = &unbind; + msg.msg_case = CLIENT_MESSAGE__MSG_UNBIND_SEAT; + + return ei_proto_send_msg(ei, &msg); +} + +int +ei_proto_send_close_device(struct ei *ei, struct ei_device *device) +{ + ClientMessage msg = CLIENT_MESSAGE__INIT; + CloseDevice close = CLOSE_DEVICE__INIT; + + close.deviceid = device->id; + + msg.close_device = &close; + msg.msg_case = CLIENT_MESSAGE__MSG_CLOSE_DEVICE; return ei_proto_send_msg(ei, &msg); } diff --git a/src/libei-proto.h b/src/libei-proto.h index 56e4119..935d6ba 100644 --- a/src/libei-proto.h +++ b/src/libei-proto.h @@ -85,6 +85,10 @@ struct message { int keymap_fd; size_t keymap_size; uint32_t seatid; + uint32_t pointer_width; + uint32_t pointer_height; + uint32_t touch_width; + uint32_t touch_height; } device_added; struct message_device_removed { uint32_t deviceid; @@ -116,7 +120,13 @@ int ei_proto_send_add(struct ei *ei, struct ei_device *device); int -ei_proto_send_remove(struct ei *ei, struct ei_device *device); +ei_proto_send_bind_seat(struct ei *ei, struct ei_seat *seat, uint32_t capabilities); + +int +ei_proto_send_unbind_seat(struct ei *ei, struct ei_seat *seat); + +int +ei_proto_send_close_device(struct ei *ei, struct ei_device *device); int ei_proto_send_rel(struct ei *ei, struct ei_device *device, diff --git a/src/libei-seat.c b/src/libei-seat.c index 1b17d1f..ad48f36 100644 --- a/src/libei-seat.c +++ b/src/libei-seat.c @@ -65,10 +65,11 @@ ei_seat_new(struct ei *ei, uint32_t id, const char *name, uint32_t capabilities) { struct ei_seat *seat = ei_seat_create(&ei->object); - seat->state = EI_SEAT_STATE_PRESENT; + seat->state = EI_SEAT_STATE_NEW; seat->name = xstrdup(name); seat->id = id; seat->capabilities = capabilities; + seat->capabilities_mask = ~0; /* Masked out by client */ list_init(&seat->devices); list_init(&seat->link); @@ -92,7 +93,7 @@ ei_seat_remove(struct ei_seat *seat) * need to clean this up in the library */ list_for_each_safe(d, tmp, &seat->devices, link) { /* remove the device */ - ei_device_remove(d); + ei_device_close(d); /* And pretend to process the removed message from * the server */ ei_device_removed_by_server(d); @@ -121,3 +122,41 @@ ei_seat_find_device(struct ei_seat *seat, uint32_t deviceid) return NULL; } + +_public_ void +ei_seat_drop_capability(struct ei_seat *seat, + enum ei_device_capability cap) +{ + if (seat->state == EI_SEAT_STATE_NEW) + flag_clear(seat->capabilities_mask, cap); +} + +_public_ void +ei_seat_bind(struct ei_seat *seat) +{ + if (seat->state != EI_SEAT_STATE_NEW) + return; + + ei_send_seat_bind(seat, seat->capabilities & seat->capabilities_mask); + seat->state = EI_SEAT_STATE_BOUND; +} + +_public_ void +ei_seat_unbind(struct ei_seat *seat) +{ + switch (seat->state) { + case EI_SEAT_STATE_NEW: + case EI_SEAT_STATE_BOUND: + break; + case EI_SEAT_STATE_UNBOUND: + case EI_SEAT_STATE_REMOVED: + return; + } + + struct ei_device *device; + list_for_each(device, &seat->devices, link) { + ei_device_close(device); + } + ei_send_seat_unbind(seat); + seat->state = EI_SEAT_STATE_UNBOUND; +} diff --git a/src/libei.c b/src/libei.c index 9874a97..e9a4061 100644 --- a/src/libei.c +++ b/src/libei.c @@ -90,7 +90,7 @@ OBJECT_IMPLEMENT_GETTER(ei_event, device, struct ei_device*); _public_ struct ei_seat * ei_event_get_seat(struct ei_event *event) { - return event->device ? ei_device_get_seat(event->device) : event->seat; + return event->seat; } static struct ei_seat * @@ -254,6 +254,7 @@ queue_device_added_event(struct ei_device *device) struct ei_event *e = ei_event_create(&ei->object); e->type = EI_EVENT_DEVICE_ADDED; + e->seat = ei_seat_ref(ei_device_get_seat(device)); e->device = ei_device_ref(device); queue_event(ei, e); @@ -266,6 +267,7 @@ queue_device_removed_event(struct ei_device *device) struct ei_event *e = ei_event_create(&ei->object); e->type = EI_EVENT_DEVICE_REMOVED; + e->seat = ei_seat_ref(ei_device_get_seat(device)); e->device = ei_device_ref(device); queue_event(ei, e); @@ -278,6 +280,7 @@ insert_device_removed_event(struct ei_device *device) struct ei_event *e = ei_event_create(&ei->object); e->type = EI_EVENT_DEVICE_REMOVED; + e->seat = ei_seat_ref(ei_device_get_seat(device)); e->device = ei_device_ref(device); insert_event(ei, e); @@ -290,6 +293,7 @@ queue_suspended_event(struct ei_device *device) struct ei_event *e = ei_event_create(&ei->object); e->type = EI_EVENT_DEVICE_SUSPENDED; + e->seat = ei_seat_ref(ei_device_get_seat(device)); e->device = ei_device_ref(device); queue_event(ei, e); @@ -302,6 +306,7 @@ queue_resumed_event(struct ei_device *device) struct ei_event *e = ei_event_create(&ei->object); e->type = EI_EVENT_DEVICE_RESUMED; + e->seat = ei_seat_ref(ei_device_get_seat(device)); e->device = ei_device_ref(device); queue_event(ei, e); @@ -328,23 +333,33 @@ connection_send_disconnect(struct ei *ei) } static int -connection_send_add(struct ei *ei, struct ei_device *device) +connection_send_bind_seat(struct ei *ei, struct ei_seat *seat, uint32_t capabilities) { if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; - return ei_proto_send_add(ei, device); + return ei_proto_send_bind_seat(ei, seat, capabilities); } static int -connection_send_remove(struct ei *ei, struct ei_device *device) +connection_send_unbind_seat(struct ei *ei, struct ei_seat *seat) { if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; - return ei_proto_send_remove(ei, device); + return ei_proto_send_unbind_seat(ei, seat); +} + +static int +connection_send_close_device(struct ei *ei, struct ei_device *device) +{ + if (ei->state == EI_STATE_NEW || + ei->state == EI_STATE_DISCONNECTED) + return 0; + + return ei_proto_send_close_device(ei, device); } static int @@ -473,28 +488,6 @@ ei_disconnect(struct ei *ei) ei->source = source_unref(ei->source); } -int -ei_send_add_device(struct ei_device *device) -{ - struct ei *ei = ei_device_get_context(device); - int rc = connection_send_add(ei, device); - if (rc) - ei_disconnect(ei); - - return rc; -} - -int -ei_send_remove_device(struct ei_device *device) -{ - struct ei *ei = ei_device_get_context(device); - int rc = connection_send_remove(ei, device); - if (rc) - ei_disconnect(ei); - - return rc; -} - static int handle_msg_seat_added(struct ei *ei, uint32_t seatid, const char *name, uint32_t capabilities) @@ -504,6 +497,7 @@ handle_msg_seat_added(struct ei *ei, uint32_t seatid, struct ei_seat *seat = ei_seat_new(ei, seatid, name, capabilities); + /* seats list owns the ref */ list_append(&ei->seats, &seat->link); queue_seat_added_event(seat); @@ -529,7 +523,9 @@ handle_msg_device_added(struct ei *ei, uint32_t deviceid, const char *name, uint32_t capabilities, bool keymap_from_server, enum ei_keymap_type keymap_type, int keymap_fd, size_t keymap_sz, - uint32_t seatid) + uint32_t seatid, + uint32_t pointer_width, uint32_t pointer_height, + uint32_t touch_width, uint32_t touch_height) { struct ei_seat *seat = ei_find_seat(ei, seatid); @@ -540,15 +536,20 @@ handle_msg_device_added(struct ei *ei, uint32_t deviceid, } struct ei_device *device = ei_seat_find_device(seat, deviceid); - /* Wrong device id or a device already removed by the client but we * won't know which unless we keep some device ID table. Not worth * it, so just silently ignore */ - if (!device) - return 0; + if (device) { + log_error(ei, "Device sent duplicate device id %d\n", deviceid); + return -EINVAL; + } + + device = ei_device_new(seat, deviceid); ei_device_set_name(device, name); ei_device_set_capabilities(device, capabilities); + ei_device_set_pointer_range(device, pointer_width, pointer_height); + ei_device_set_touch_range(device, touch_width, touch_height); if (keymap_from_server) ei_device_set_keymap(device, keymap_type, keymap_fd, keymap_sz); @@ -621,6 +622,37 @@ handle_msg_suspended(struct ei *ei, uint32_t deviceid) return 0; } +int +ei_send_close_device(struct ei_device *device) +{ + struct ei *ei = ei_device_get_context(device); + int rc = connection_send_close_device(ei, device); + if (rc) + ei_disconnect(ei); + return rc; +} + +int +ei_send_seat_bind(struct ei_seat *seat, uint32_t capabilities) +{ + struct ei *ei = ei_seat_get_context(seat); + int rc = connection_send_bind_seat(ei, seat, capabilities); + if (rc) + ei_disconnect(ei); + return rc; +} + +int +ei_send_seat_unbind(struct ei_seat *seat) +{ + struct ei *ei = ei_seat_get_context(seat); + int rc = connection_send_unbind_seat(ei, seat); + if (rc) + ei_disconnect(ei); + return rc; +} + + int ei_send_pointer_rel(struct ei_device *device, double x, double y) { @@ -810,7 +842,12 @@ connection_connected_handle_msg(struct ei *ei, struct message *msg) msg->device_added.keymap_type, msg->device_added.keymap_fd, msg->device_added.keymap_size, - msg->device_added.seatid); + msg->device_added.seatid, + msg->device_added.pointer_width, + msg->device_added.pointer_height, + msg->device_added.touch_width, + msg->device_added.touch_height + ); break; case MESSAGE_DEVICE_REMOVED: rc = handle_msg_device_removed(ei, msg->device_removed.deviceid); diff --git a/src/libei.h b/src/libei.h index 32b559b..1546f29 100644 --- a/src/libei.h +++ b/src/libei.h @@ -191,8 +191,8 @@ enum ei_event_type { /** * The server has removed a seat previously available to this * client. The caller should release the struct @ref ei_seat and - * all its associated resources. No devices can be created through - * this seat anymore. + * all its associated resources. No devices will be added to this seat + * anymore. * * libei guarantees that any device in this seat generates a @ref * EI_EVENT_DEVICE_REMOVED event before the @ref @@ -202,14 +202,10 @@ enum ei_event_type { /** * The server has added a device for this client. The capabilities - * of the device may not match the requested capabilities - it is up + * of the device may be a subset of the seat capabilities - it is up * to the client to verify the minimum required capabilities are * indeed set. * - * Where the server refuses to add a specific device or the - * intersection of requested capabilities and allowed capabilities - * is zero, the server sends @ref EI_EVENT_DEVICE_REMOVED instead. - * * libei guarantees that any device added has a corresponding @ref * EI_EVENT_DEVICE_REMOVED event before @ref EI_EVENT_DISCONNECT. */ @@ -469,6 +465,42 @@ bool ei_seat_has_capability(struct ei_seat *seat, enum ei_device_capability cap); +/** + * Remove a capability from this seat before calling ei_seat_bind(). + * Devices with only the dropped capability will never be added to this + * client, devices with multiple capabilities will not show the dropped + * capabilities. + * + * This function has no effect if called after ei_seat_bind(). + */ +void +ei_seat_drop_capability(struct ei_seat *seat, + enum ei_device_capability cap); + +/** + * Bind this client to the given seat for the seat's capabilities. + * This function can only be called once per seat. Once bound, the server will + * create devices for the seat's capabillities and send the respective @ref + * EI_EVENT_DEVICE_ADDED events. + * + * Devices may be added and removed at any time. + */ +void +ei_seat_bind(struct ei_seat *seat); + +/** + * Unbind a seat and remove it from the server. + * + * If called on a seat immediately after @ref EI_EVENT_SEAT_ADDED, this + * function indicates that the client is not interested in this seat. + * If called on a seat after ei_seat_bind(), this function implicitly calls + * ei_device_close() on all devices for this seat. + * + * The server responds with an @ref EI_EVENT_SEAT_REMOVED event. + */ +void +ei_seat_unbind(struct ei_seat *seat); + struct ei_seat * ei_seat_ref(struct ei_seat *seat); @@ -524,25 +556,6 @@ ei_device_ref(struct ei_device *device); struct ei_device * ei_device_unref(struct ei_device *device); -/** - * Create a new device in the given seat. This device is a proxy - * representing the server's device and should be used for initial device - * configuration. It does not represent the server-created device until the - * @ref EI_EVENT_DEVICE_ADDED for this device has been received. - * - * Use the configure API (e.g. ei_device_configure_capability()) to set up - * the device, then call ei_device_add() to request creation of the device - * by the server. - * - * @note A caller that does not want to add a created device to a seat - * **must** call ei_device_remove() for this device to ensure the - * resources are released. - * - * The returned object must be released by the caller with ei_event_unref() - */ -struct ei_device * -ei_device_new(struct ei_seat *ei_seat); - struct ei_seat * ei_device_get_seat(struct ei_device *device); @@ -576,84 +589,6 @@ ei_device_set_user_data(struct ei_device *device, void *user_data); void * ei_device_get_user_data(struct ei_device *device); -/** - * Set the name for this device. This is a suggestion only, the server may - * ignore the name and assign a different one (or none). Use - * ei_device_get_name() upon receiving @ref EI_EVENT_DEVICE_ADDED to get the - * server-assigned - * name. - * - * This function has no effect if called after ei_device_add() - * - * libei may quietly ignore names of unreasonable length. This is not - * something a normal caller ever needs to worry about. - * - * @param device The EI device - * @param name A name suggestion for the device - */ -void -ei_device_configure_name(struct ei_device *device, const char *name); - -/** - * Enable the given capability on this device. This is a suggestion only, - * the server may ignore this capability. - * Use ei_device_has_capability() upon receiving @ref EI_EVENT_DEVICE_ADDED - * to check for the actual capabilities of the device. - * - * This function has no effect if called after ei_device_add() - * - * @param device The EI device - * @param cap The capability to enable - */ -bool -ei_device_configure_capability(struct ei_device *device, - enum ei_device_capability cap); - -/** - * Set the range of the absolute pointer device in logical - * pixels. The allowable range for absolute pointer motion is - * [0, max) for each axis, i.e. zero inclusive, max exclusive. Coordinates - * outside this range may be discarded or clipped silently by the library. - * - * The pointer range is constant. Where the pointer range is no longer - * applicable, the client needs to remove the device and create and add a - * new device with the updated pointer range. - * - * The server may use this in mapping heuristics. For example, a pointer - * device with a pixel range of 1920x1200 **may** be automatically mapped by - * the server to the monitor with this range, or a pointer device with a - * ratio of R **may** be mapped to the monitor with the same ratio. This is - * not a guarantee, the mapping policy is a private implementation detail - * in the server. It is assumed that the client has other communication - * channels (e.g. Wayland) to obtain the pointer range it needs to emulate - * input on a device and channels to notify the server of desired mappings - * (e.g. gsettings). - * - * It is a client bug to send pointer values outside this range. - * It is a client bug to call this function on a device without the @ref - * EI_DEVICE_CAP_POINTER_ABSOLUTE capability. - * - * This function has no effect if called after ei_device_add() - * - * @param device The EI device - * @param width The maximum (exclusive) x value in logical pixels - * @param height The maximum (exclusive) y value in logical pixels - */ -void -ei_device_pointer_configure_range(struct ei_device *device, - uint32_t width, - uint32_t height); - -/** - * Set the range of the touch device in logical pixels. This - * function is identical to ei_device_pointer_configure_range() but - * configures the touch range instead. - */ -void -ei_device_touch_configure_range(struct ei_device *device, - uint32_t width, - uint32_t height); - /** * Create a new keymap of the given @p type. This keymap does not immediately @@ -779,27 +714,8 @@ ei_device_keyboard_configure_keymap(struct ei_device *device, struct ei_keymap *keymap); /** - * Request that the device be added to the server. - * The server will respond with an @ref EI_EVENT_DEVICE_ADDED or @ref - * EI_EVENT_DEVICE_REMOVED event once the request has been processed. - * - * A client can assume that an @ref EI_EVENT_DEVICE_REMOVED event is sent - * for any device for which ei_device_add() was called before the @ref - * EI_EVENT_DISCONNECT. Where a client gets - * disconnected libei will emulate that event. - * - * A client may not send events through this device until it has been added - * by the server. - * - * Devices should only be added once all events from ei_get_event() have - * been processed. It is considered a client bug to add a device to a seat - * after the SEAT_REMOVED has been received by libei. - */ -void -ei_device_add(struct ei_device *device); - -/** - * Notify the server that the device should be removed. + * Notify the server that the client is no longer listening to events + * from this device. * * Due to the asynchronous nature of the client-server interaction, * events for this device may still be in transit. The server will send an @@ -807,7 +723,7 @@ ei_device_add(struct ei_device *device); * device is considered removed by the server. * * A client can assume that an @ref EI_EVENT_DEVICE_REMOVED event is sent - * for any device for which ei_device_remove() was called before the @ref + * for any device for which ei_device_close() was called before the @ref * EI_EVENT_DISCONNECT. Where a client gets * disconnected libei will emulate that event. * @@ -815,7 +731,7 @@ ei_device_add(struct ei_device *device); * ei_device_unref() for any references held by the client. */ void -ei_device_remove(struct ei_device *device); +ei_device_close(struct ei_device *device); /** * Return the name of this device. diff --git a/src/libeis-client.c b/src/libeis-client.c index c6c960d..fe246be 100644 --- a/src/libeis-client.c +++ b/src/libeis-client.c @@ -171,69 +171,7 @@ eis_client_disconnect(struct eis_client *client) } static int -client_new_device(struct eis_client *client, - uint32_t id, const char *name, uint32_t capabilities, - const struct dimensions *dim_pointer, - const struct dimensions *dim_touch, - enum eis_keymap_type keymap_type, - int keymap_fd, size_t keymap_sz, - uint32_t seatid) -{ - struct eis_seat *s, *seat = NULL; - - list_for_each(s, &client->seats, link) { - if (s->id == seatid) { - seat = s; - break; - } - } - - if (seat == NULL) - return -EINVAL; - - /* Check for duplicate IDs */ - struct eis_device *d; - list_for_each(d, &seat->devices, link) { - if (d->id == id) - return -EINVAL; - } - - if (capabilities == 0 || - capabilities & ~(bit(EIS_DEVICE_CAP_POINTER) | - bit(EIS_DEVICE_CAP_POINTER_ABSOLUTE) | - bit(EIS_DEVICE_CAP_KEYBOARD) | - bit(EIS_DEVICE_CAP_TOUCH))) - return -EINVAL; - - struct eis_device *device = eis_device_new(seat, id, name, capabilities); - list_append(&seat->devices, &device->link); - - if (flag_is_set(capabilities, EIS_DEVICE_CAP_POINTER_ABSOLUTE)) - eis_device_set_pointer_range(device, dim_pointer->width, - dim_pointer->height); - - if (flag_is_set(capabilities, EIS_DEVICE_CAP_TOUCH)) - eis_device_set_touch_range(device, dim_touch->width, - dim_touch->height); - - eis_device_set_client_keymap(device, keymap_type, keymap_fd, keymap_sz); - - log_debug(eis_client_parent(client), - "New device %#x '%s' caps: %s%s%s%s seat: %s\n", - id, name, - eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER) ? "p" : "", - eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE) ? "a" : "", - eis_device_has_capability(device, EIS_DEVICE_CAP_KEYBOARD) ? "k" : "", - eis_device_has_capability(device, EIS_DEVICE_CAP_TOUCH) ? "t" : "", - eis_seat_get_name(seat)); - - eis_queue_added_event(device); - - return 0; -} - -static int -client_remove_device(struct eis_client *client, uint32_t deviceid) +client_close_device(struct eis_client *client, uint32_t deviceid) { struct eis_seat *seat; @@ -242,7 +180,7 @@ client_remove_device(struct eis_client *client, uint32_t deviceid) list_for_each(device, &seat->devices, link) { if (device->id == deviceid) { - eis_device_removed_by_client(device); + eis_device_closed_by_client(device); break; } } @@ -250,6 +188,36 @@ client_remove_device(struct eis_client *client, uint32_t deviceid) return 0; } +static int +client_seat_bind(struct eis_client *client, uint32_t seatid, uint32_t caps) +{ + struct eis_seat *seat; + + list_for_each(seat, &client->seats, link) { + if (seat->id == seatid) { + eis_queue_seat_bind_event(seat, caps); + return 0; + } + } + + return -EINVAL; +} + +static int +client_seat_unbind(struct eis_client *client, uint32_t seatid) +{ + struct eis_seat *seat; + + list_for_each(seat, &client->seats, link) { + if (seat->id == seatid) { + /* FIXME */ + return 0; + } + } + + return -EINVAL; +} + static int client_pointer_rel(struct eis_client *client, uint32_t deviceid, double x, double y) @@ -431,8 +399,9 @@ client_new_handle_msg(struct eis_client *client, struct message *msg) case MESSAGE_DISCONNECT: rc = -ECANCELED; break; - case MESSAGE_ADD_DEVICE: - case MESSAGE_REMOVE_DEVICE: + case MESSAGE_BIND_SEAT: + case MESSAGE_UNBIND_SEAT: + case MESSAGE_CLOSE_DEVICE: case MESSAGE_POINTER_REL: case MESSAGE_POINTER_ABS: case MESSAGE_POINTER_BUTTON: @@ -467,8 +436,9 @@ client_connecting_handle_msg(struct eis_client *client, const struct message *ms case MESSAGE_DISCONNECT: rc = -ECANCELED; break; - case MESSAGE_ADD_DEVICE: - case MESSAGE_REMOVE_DEVICE: + case MESSAGE_BIND_SEAT: + case MESSAGE_UNBIND_SEAT: + case MESSAGE_CLOSE_DEVICE: case MESSAGE_POINTER_REL: case MESSAGE_POINTER_ABS: case MESSAGE_POINTER_BUTTON: @@ -504,19 +474,14 @@ client_connected_handle_msg(struct eis_client *client, case MESSAGE_DISCONNECT: rc = -ECANCELED; break; - case MESSAGE_ADD_DEVICE: - rc = client_new_device(client, msg->add_device.deviceid, - msg->add_device.name, - msg->add_device.capabilities, - &msg->add_device.dim_pointer, - &msg->add_device.dim_touch, - msg->add_device.keymap_type, - msg->add_device.keymap_fd, - msg->add_device.keymap_size, - msg->add_device.seat); + case MESSAGE_BIND_SEAT: + client_seat_bind(client, msg->bind_seat.seatid, msg->bind_seat.capabilities); break; - case MESSAGE_REMOVE_DEVICE: - rc = client_remove_device(client, msg->remove_device.deviceid); + case MESSAGE_UNBIND_SEAT: + client_seat_unbind(client, msg->unbind_seat.seatid); + break; + case MESSAGE_CLOSE_DEVICE: + rc = client_close_device(client, msg->close_device.deviceid); break; case MESSAGE_POINTER_REL: rc = client_pointer_rel(client, msg->pointer_rel.deviceid, @@ -678,13 +643,13 @@ eis_client_remove_seat(struct eis_client *client, struct eis_seat *seat) } void -eis_client_connect_device(struct eis_client *client, struct eis_device *device) +eis_client_add_device(struct eis_client *client, struct eis_device *device) { client_send_device_added(client, device); } void -eis_client_disconnect_device(struct eis_client *client, struct eis_device *device) +eis_client_remove_device(struct eis_client *client, struct eis_device *device) { client_send_device_removed(client, device); } diff --git a/src/libeis-device.c b/src/libeis-device.c index ed6e061..05dc59b 100644 --- a/src/libeis-device.c +++ b/src/libeis-device.c @@ -165,39 +165,85 @@ eis_device_get_client(struct eis_device *device) return eis_seat_get_client(eis_device_get_seat(device)); } -struct eis_device * -eis_device_new(struct eis_seat *seat, - uint32_t id, - const char *name, - uint32_t capabilities) +_public_ struct eis_device * +eis_device_new(struct eis_seat *seat) { + static uint32_t deviceid; struct eis_device *device = eis_device_create(&seat->object); - device->name = xstrdup(name); - device->capabilities_mask = 0; - device->capabilities = capabilities; - device->id = id; + device->id = seat->id | deviceid++; + device->name = xstrdup("unnamed device"); + device->capabilities = 0; device->state = EIS_DEVICE_STATE_NEW; - return device; + list_append(&seat->devices, &device->link); + + return eis_device_ref(device); } -void -eis_device_set_pointer_range(struct eis_device *device, - uint32_t w, uint32_t h) +_public_ void +eis_device_configure_name(struct eis_device *device, const char *name) { + if (device->state != EIS_DEVICE_STATE_NEW) + return; + + free(device->name); + device->name = xstrdup(name); +} + +_public_ void +eis_device_configure_capability(struct eis_device *device, enum eis_device_capability cap) +{ + if (device->state != EIS_DEVICE_STATE_NEW) + return; + + if (!eis_seat_has_capability(eis_device_get_seat(device), cap)) + return; + + flag_set(device->capabilities, cap); +} + +_public_ void +eis_device_configure_pointer_range(struct eis_device *device, + uint32_t w, uint32_t h) +{ + if (device->state != EIS_DEVICE_STATE_NEW) + return; + device->abs.dim.width = w; device->abs.dim.height = h; } -void -eis_device_set_touch_range(struct eis_device *device, - uint32_t w, uint32_t h) +_public_ void +eis_device_configure_touch_range(struct eis_device *device, + uint32_t w, uint32_t h) { + if (device->state != EIS_DEVICE_STATE_NEW) + return; + device->touch.dim.width = w; device->touch.dim.height = h; } +_public_ void +eis_device_add(struct eis_device *device) +{ + if (device->state != EIS_DEVICE_STATE_NEW) + return; + + device->state = EIS_DEVICE_STATE_SUSPENDED; + eis_client_add_device(eis_device_get_client(device), device); +} + +_public_ void +eis_device_remove(struct eis_device *device) +{ + device->state = EIS_DEVICE_STATE_REMOVED_BY_SERVER ; + eis_client_remove_device(eis_device_get_client(device), device); + list_remove(&device->link); + eis_device_unref(device); +} + void eis_device_set_client_keymap(struct eis_device *device, enum eis_keymap_type type, @@ -239,19 +285,6 @@ eis_device_has_capability(struct eis_device *device, return false; } -_public_ void -eis_device_allow_capability(struct eis_device *device, - enum eis_device_capability cap) -{ - switch(cap) { - case EIS_DEVICE_CAP_POINTER: - case EIS_DEVICE_CAP_POINTER_ABSOLUTE: - case EIS_DEVICE_CAP_KEYBOARD: - case EIS_DEVICE_CAP_TOUCH: - flag_set(device->capabilities_mask, cap); - break; - } -} _public_ uint32_t eis_device_pointer_get_width(struct eis_device *device) @@ -415,24 +448,7 @@ eis_device_touch(struct eis_device *device, uint32_t touchid, return 0; } -_public_ void -eis_device_connect(struct eis_device *device) -{ - if (device->state != EIS_DEVICE_STATE_NEW) - return; - - if (device->capabilities_mask == 0) { - log_bug(eis_device_get_context(device), - "Connecting a device without capabilities\n"); - eis_device_disconnect(device); - return; - } - - device->capabilities &= device->capabilities_mask; - device->state = EIS_DEVICE_STATE_SUSPENDED; - eis_client_connect_device(eis_device_get_client(device), device); -} - +#if 0 /* FIXME: needs to move to eis_device_remove */ _public_ void eis_device_disconnect(struct eis_device *device) { @@ -450,36 +466,32 @@ eis_device_disconnect(struct eis_device *device) break; /* device was already removed by the client, so it's properly gone * now */ - case EIS_DEVICE_STATE_REMOVED_BY_CLIENT: + case EIS_DEVICE_STATE_CLOSED_BY_CLIENT: device->state = EIS_DEVICE_STATE_DEAD; list_remove(&device->link); eis_device_unref(device); break; } } +#endif void -eis_device_removed_by_client(struct eis_device *device) +eis_device_closed_by_client(struct eis_device *device) { switch (device->state) { case EIS_DEVICE_STATE_DEAD: - case EIS_DEVICE_STATE_REMOVED_BY_CLIENT: + case EIS_DEVICE_STATE_CLOSED_BY_CLIENT: /* libei bug, ignore */ break; - /* Confirmation from the client. Queue our local event but otherwise - * this device is done */ case EIS_DEVICE_STATE_REMOVED_BY_SERVER: - eis_queue_removed_event(device); - device->state = EIS_DEVICE_STATE_DEAD; - list_remove(&device->link); - eis_device_unref(device); + /* FIXME: Late arrival after eis_device_removed? */ break; case EIS_DEVICE_STATE_NEW: case EIS_DEVICE_STATE_SUSPENDED: case EIS_DEVICE_STATE_RESUMED: - eis_queue_removed_event(device); - device->state = EIS_DEVICE_STATE_REMOVED_BY_CLIENT; - eis_client_disconnect_device(eis_device_get_client(device), device); + eis_queue_device_closed_event(device); + device->state = EIS_DEVICE_STATE_CLOSED_BY_CLIENT; + eis_client_remove_device(eis_device_get_client(device), device); break; } } diff --git a/src/libeis-event.c b/src/libeis-event.c index 7e727e9..c588ec5 100644 --- a/src/libeis-event.c +++ b/src/libeis-event.c @@ -25,6 +25,7 @@ #include +#include "util-bits.h" #include "util-object.h" #include "util-macros.h" @@ -36,7 +37,9 @@ eis_event_destroy(struct eis_event *event) switch (event->type) { case EIS_EVENT_CLIENT_CONNECT: case EIS_EVENT_CLIENT_DISCONNECT: - case EIS_EVENT_DEVICE_ADDED: + case EIS_EVENT_SEAT_BIND: + case EIS_EVENT_SEAT_UNBIND: + case EIS_EVENT_DEVICE_CLOSED: case EIS_EVENT_POINTER_BUTTON: case EIS_EVENT_POINTER_MOTION: case EIS_EVENT_POINTER_MOTION_ABSOLUTE: @@ -47,13 +50,11 @@ eis_event_destroy(struct eis_event *event) case EIS_EVENT_TOUCH_MOTION: case EIS_EVENT_TOUCH_UP: break; - case EIS_EVENT_DEVICE_REMOVED: - eis_device_disconnect(event->device); - break; default: abort(); /* not yet implemented */ } event->device = eis_device_unref(event->device); + event->seat = eis_seat_unref(event->seat); event->client = eis_client_unref(event->client); } @@ -71,6 +72,19 @@ eis_event_new_for_client(struct eis_client *client) return e; } +struct eis_event * +eis_event_new_for_seat(struct eis_seat *seat) +{ + struct eis_client *client = eis_seat_get_client(seat); + struct eis *eis = eis_client_get_context(client); + + struct eis_event *e = eis_event_create(&eis->object); + e->client = eis_client_ref(client); + e->seat = eis_seat_ref(seat); + + return e; +} + struct eis_event * eis_event_new_for_device(struct eis_device *device) { @@ -79,6 +93,7 @@ eis_event_new_for_device(struct eis_device *device) struct eis_event *e = eis_event_create(&eis->object); e->client = eis_client_ref(client); + e->seat = eis_seat_ref(eis_device_get_seat(device)); e->device = eis_device_ref(device); return e; @@ -94,6 +109,8 @@ OBJECT_IMPLEMENT_GETTER(eis_event, type, enum eis_event_type); _public_ OBJECT_IMPLEMENT_GETTER(eis_event, client, struct eis_client*); _public_ +OBJECT_IMPLEMENT_GETTER(eis_event, seat, struct eis_seat*); +_public_ OBJECT_IMPLEMENT_GETTER(eis_event, device, struct eis_device*); static @@ -140,6 +157,14 @@ check_event_type(struct eis_event *event, if (!check_event_type(event_, __func__, __VA_ARGS__, -1)) \ return retval_; \ +_public_ bool +eis_event_seat_has_capability(struct eis_event *event, enum eis_device_capability cap) +{ + require_event_type(event, false, EIS_EVENT_SEAT_BIND); + + return flag_is_set(event->bind.capabilities, cap); +} + _public_ double eis_event_pointer_get_dx(struct eis_event *event) { diff --git a/src/libeis-private.h b/src/libeis-private.h index bad107b..640bfae 100644 --- a/src/libeis-private.h +++ b/src/libeis-private.h @@ -105,7 +105,7 @@ enum eis_device_state { EIS_DEVICE_STATE_NEW, EIS_DEVICE_STATE_SUSPENDED, EIS_DEVICE_STATE_RESUMED, - EIS_DEVICE_STATE_REMOVED_BY_CLIENT, + EIS_DEVICE_STATE_CLOSED_BY_CLIENT, EIS_DEVICE_STATE_REMOVED_BY_SERVER, EIS_DEVICE_STATE_DEAD, }; @@ -118,7 +118,6 @@ struct eis_device { char *name; enum eis_device_state state; uint32_t capabilities; - uint32_t capabilities_mask; void *user_data; struct { @@ -136,9 +135,13 @@ struct eis_event { enum eis_event_type type; struct list link; struct eis_client *client; + struct eis_seat *seat; struct eis_device *device; union { + struct { + uint32_t capabilities; + } bind; struct { double dx, dy; /* relative motion */ double absx, absy; /* absolute motion */ @@ -189,11 +192,9 @@ void eis_client_remove_seat(struct eis_client *client, struct eis_seat *seat); void -eis_client_connect_device(struct eis_client *client, - struct eis_device *device); +eis_client_add_device(struct eis_client *client, struct eis_device *device); void -eis_client_disconnect_device(struct eis_client *client, - struct eis_device *device); +eis_client_remove_device(struct eis_client *client, struct eis_device *device); void eis_client_resume_device(struct eis_client *client, @@ -203,13 +204,10 @@ eis_client_suspend_device(struct eis_client *client, struct eis_device *device); void -eis_seat_disconnect(struct eis_seat *seat); +eis_seat_bind(struct eis_seat *seat, uint32_t cap); -struct eis_device * -eis_device_new(struct eis_seat *seat, - uint32_t id, - const char *name, - uint32_t capabilities); +void +eis_seat_disconnect(struct eis_seat *seat); void eis_device_set_pointer_range(struct eis_device *device, @@ -251,11 +249,14 @@ eis_device_touch(struct eis_device *device, uint32_t touchid, bool is_down, bool is_up, double x, double y); void -eis_device_removed_by_client(struct eis_device *device); +eis_device_closed_by_client(struct eis_device *device); struct eis_event * eis_event_new_for_client(struct eis_client *client); +struct eis_event * +eis_event_new_for_seat(struct eis_seat *seat); + struct eis_event * eis_event_new_for_device(struct eis_device *device); @@ -272,10 +273,13 @@ void eis_queue_disconnect_event(struct eis_client *client); void -eis_queue_added_event(struct eis_device *device); +eis_queue_seat_bind_event(struct eis_seat *seat, uint32_t capabilities); void -eis_queue_removed_event(struct eis_device *device); +eis_queue_seat_unbind_event(struct eis_seat *seat); + +void +eis_queue_device_closed_event(struct eis_device *device); void eis_queue_pointer_rel_event(struct eis_device *device, double x, double y); diff --git a/src/libeis-proto.c b/src/libeis-proto.c index cd8f691..2b2ccd0 100644 --- a/src/libeis-proto.c +++ b/src/libeis-proto.c @@ -38,9 +38,6 @@ void message_free(struct message *msg) { switch (msg->type) { - case MESSAGE_ADD_DEVICE: - free(msg->add_device.name); - break; case MESSAGE_CONNECT: free(msg->connect.name); break; @@ -196,6 +193,11 @@ eis_proto_send_device_added(struct eis_client *client, struct eis_device *device } added.seatid = seat->id; + added.pointer_width = device->abs.dim.width; + added.pointer_height = device->abs.dim.height; + added.touch_width = device->touch.dim.width; + added.touch_height = device->touch.dim.height; + msg.device_added = &added; msg.msg_case = SERVER_MESSAGE__MSG_DEVICE_ADDED; @@ -272,34 +274,31 @@ eis_proto_parse_message(struct brei_message *bmsg, size_t *consumed) .type = MESSAGE_DISCONNECT, }; break; - case CLIENT_MESSAGE__MSG_ADD_DEVICE: + case CLIENT_MESSAGE__MSG_BIND_SEAT: { - AddDevice *a = proto->add_device; + BindSeat *b = proto->bind_seat; *msg = (struct message) { - .type = MESSAGE_ADD_DEVICE, - .add_device.deviceid = a->deviceid, - .add_device.name = a->name[0] ? xstrdup(a->name) : NULL, - .add_device.capabilities = a->capabilities, - .add_device.dim_pointer.width = a->pointer_width, - .add_device.dim_pointer.height = a->pointer_height, - .add_device.dim_touch.width = a->touch_width, - .add_device.dim_touch.height = a->touch_height, - .add_device.keymap_fd = -1, - .add_device.keymap_type = a->keymap_type, - .add_device.keymap_size = a->keymap_size, - .add_device.seat = a->seat, + .type = MESSAGE_BIND_SEAT, + .bind_seat.seatid = b->seatid, + .bind_seat.capabilities = b->capabilities, }; - - if (a->keymap_type) - msg->add_device.keymap_fd = brei_message_take_fd(bmsg); } break; - case CLIENT_MESSAGE__MSG_REMOVE_DEVICE: + case CLIENT_MESSAGE__MSG_UNBIND_SEAT: { - RemoveDevice *r = proto->remove_device; + UnbindSeat *u = proto->unbind_seat; *msg = (struct message) { - .type = MESSAGE_REMOVE_DEVICE, - .remove_device.deviceid = r->deviceid, + .type = MESSAGE_UNBIND_SEAT, + .unbind_seat.seatid = u->seatid, + }; + } + break; + case CLIENT_MESSAGE__MSG_CLOSE_DEVICE: + { + CloseDevice *r = proto->close_device; + *msg = (struct message) { + .type = MESSAGE_CLOSE_DEVICE, + .close_device.deviceid = r->deviceid, }; } break; diff --git a/src/libeis-proto.h b/src/libeis-proto.h index 8680e3c..1e4e86a 100644 --- a/src/libeis-proto.h +++ b/src/libeis-proto.h @@ -37,8 +37,9 @@ enum message_type { MESSAGE_CONNECT, MESSAGE_DISCONNECT, - MESSAGE_ADD_DEVICE, - MESSAGE_REMOVE_DEVICE, + MESSAGE_BIND_SEAT, + MESSAGE_UNBIND_SEAT, + MESSAGE_CLOSE_DEVICE, MESSAGE_POINTER_REL, MESSAGE_POINTER_ABS, MESSAGE_POINTER_BUTTON, @@ -57,8 +58,9 @@ message_type_to_string(enum message_type type) switch(type) { CASE_RETURN_STRING(MESSAGE_CONNECT); CASE_RETURN_STRING(MESSAGE_DISCONNECT); - CASE_RETURN_STRING(MESSAGE_ADD_DEVICE); - CASE_RETURN_STRING(MESSAGE_REMOVE_DEVICE); + CASE_RETURN_STRING(MESSAGE_BIND_SEAT); + CASE_RETURN_STRING(MESSAGE_UNBIND_SEAT); + CASE_RETURN_STRING(MESSAGE_CLOSE_DEVICE); CASE_RETURN_STRING(MESSAGE_POINTER_REL); CASE_RETURN_STRING(MESSAGE_POINTER_ABS); CASE_RETURN_STRING(MESSAGE_POINTER_BUTTON); @@ -81,6 +83,17 @@ struct message { struct message_disconnect { uint8_t pad; /* no data */ } disconnect; + struct message_bind_seat { + uint32_t seatid; + uint32_t capabilities; + } bind_seat; + struct message_unbind_seat { + uint32_t seatid; + } unbind_seat; + struct message_close_device { + uint32_t deviceid; + } close_device; +#if 0 struct message_add_device { uint32_t deviceid; char *name; @@ -96,6 +109,7 @@ struct message { struct message_remove_device { uint32_t deviceid; } remove_device; +#endif struct message_pointer_rel { uint32_t deviceid; double x; diff --git a/src/libeis-seat.c b/src/libeis-seat.c index de3facb..cae3d74 100644 --- a/src/libeis-seat.c +++ b/src/libeis-seat.c @@ -124,7 +124,7 @@ eis_seat_remove(struct eis_seat *seat) */ struct eis_device *d, *tmp; list_for_each_safe(d, tmp, &seat->devices, link) { - eis_device_disconnect(d); + eis_device_remove(d); } eis_client_remove_seat(eis_seat_get_client(seat), seat); @@ -141,7 +141,7 @@ eis_seat_disconnect(struct eis_seat *seat) * device removed event. */ struct eis_device *d, *tmp; list_for_each_safe(d, tmp, &seat->devices, link) { - eis_device_removed_by_client(d); + eis_device_closed_by_client(d); } seat->state = EIS_SEAT_STATE_DEAD; @@ -150,15 +150,22 @@ eis_seat_disconnect(struct eis_seat *seat) } _public_ void -eis_seat_allow_capability(struct eis_seat *seat, - enum eis_device_capability cap) +eis_seat_configure_capability(struct eis_seat *seat, + enum eis_device_capability cap) { switch (cap) { case EIS_DEVICE_CAP_POINTER: case EIS_DEVICE_CAP_POINTER_ABSOLUTE: case EIS_DEVICE_CAP_KEYBOARD: case EIS_DEVICE_CAP_TOUCH: - seat->capabilities_mask |= bit(cap); + flag_set(seat->capabilities_mask, cap); break; } } + +_public_ bool +eis_seat_has_capability(struct eis_seat *seat, + enum eis_device_capability cap) +{ + return flag_is_set(seat->capabilities_mask, cap); +} diff --git a/src/libeis.c b/src/libeis.c index 1d79091..6d4e5b7 100644 --- a/src/libeis.c +++ b/src/libeis.c @@ -102,8 +102,9 @@ eis_event_type_to_string(enum eis_event_type type) switch(type) { CASE_RETURN_STRING(EIS_EVENT_CLIENT_CONNECT); CASE_RETURN_STRING(EIS_EVENT_CLIENT_DISCONNECT); - CASE_RETURN_STRING(EIS_EVENT_DEVICE_ADDED); - CASE_RETURN_STRING(EIS_EVENT_DEVICE_REMOVED); + CASE_RETURN_STRING(EIS_EVENT_SEAT_BIND); + CASE_RETURN_STRING(EIS_EVENT_SEAT_UNBIND); + CASE_RETURN_STRING(EIS_EVENT_DEVICE_CLOSED); CASE_RETURN_STRING(EIS_EVENT_POINTER_MOTION); CASE_RETURN_STRING(EIS_EVENT_POINTER_MOTION_ABSOLUTE); CASE_RETURN_STRING(EIS_EVENT_POINTER_BUTTON); @@ -146,18 +147,27 @@ eis_queue_disconnect_event(struct eis_client *client) } void -eis_queue_added_event(struct eis_device *device) +eis_queue_seat_bind_event(struct eis_seat *seat, uint32_t capabilities) { - struct eis_event *e = eis_event_new_for_device(device); - e->type = EIS_EVENT_DEVICE_ADDED; + struct eis_event *e = eis_event_new_for_seat(seat); + e->type = EIS_EVENT_SEAT_BIND; + e->bind.capabilities = capabilities; eis_queue_event(e); } void -eis_queue_removed_event(struct eis_device *device) +eis_queue_seat_unbind_event(struct eis_seat *seat) +{ + struct eis_event *e = eis_event_new_for_seat(seat); + e->type = EIS_EVENT_SEAT_UNBIND; + eis_queue_event(e); +} + +void +eis_queue_device_closed_event(struct eis_device *device) { struct eis_event *e = eis_event_new_for_device(device); - e->type = EIS_EVENT_DEVICE_REMOVED; + e->type = EIS_EVENT_DEVICE_CLOSED; eis_queue_event(e); } diff --git a/src/libeis.h b/src/libeis.h index fbe4341..33d014c 100644 --- a/src/libeis.h +++ b/src/libeis.h @@ -74,21 +74,21 @@ enum eis_event_type { EIS_EVENT_CLIENT_DISCONNECT, /** - * The client requests creation of a device with a given set of - * capabilities. A client may create more than one device and more - * than one device with the same capabilities. The server may filter - * the capabilities or deny them altogether. - * + * The client wants to bind to a seat. Devices associated with this + * seat should be sent to the client. */ - EIS_EVENT_DEVICE_ADDED, + EIS_EVENT_SEAT_BIND, + /** - * The device created by the client was removed. The server must - * call eis_device_disconnect() in response to this device. - * - * libeis guarantees this event is generated before - * @ref EIS_EVENT_CLIENT_DISCONNECT. + * The client wants to unbind from this seat. */ - EIS_EVENT_DEVICE_REMOVED, + EIS_EVENT_SEAT_UNBIND, + + /** + * The client no longer listens to events from this device. The caller + * should released resources associated with this device. + */ + EIS_EVENT_DEVICE_CLOSED, EIS_EVENT_POINTER_MOTION = 300, EIS_EVENT_POINTER_MOTION_ABSOLUTE, @@ -287,9 +287,10 @@ void eis_client_disconnect(struct eis_client *client); /** - * Create a new logical seat with a given name. Devices created by the - * client must bind to a seat, or in other words: a client cannot create - * devices until at least one seat is bound. + * Create a new logical seat with a given name. Devices available to a + * client belong to a bound seat, or in other words: a client cannot receive + * events from a device until it binds to a seat and receives all devices from + * that seat. * * This seat is not immediately active, use eis_seat_add() to bind this * seat on the client and notify the client of it's availability. @@ -315,6 +316,10 @@ eis_seat_get_name(struct eis_seat *eis_seat); void * eis_seat_get_user_data(struct eis_seat *eis_seat); +bool +eis_seat_has_capability(struct eis_seat *seat, + enum eis_device_capability cap); + void eis_seat_set_user_data(struct eis_seat *eis_seat, void *user_data); @@ -329,7 +334,7 @@ eis_seat_set_user_data(struct eis_seat *eis_seat, void *user_data); * This function has no effect if called after eis_seat_add() */ void -eis_seat_allow_capability(struct eis_seat *seat, +eis_seat_configure_capability(struct eis_seat *seat, enum eis_device_capability cap); /** @@ -351,6 +356,9 @@ eis_event_get_type(struct eis_event *event); struct eis_client * eis_event_get_client(struct eis_event *event); +struct eis_seat * +eis_event_get_seat(struct eis_event *event); + struct eis_client * eis_device_get_client(struct eis_device *device); @@ -389,47 +397,47 @@ eis_device_has_capability(struct eis_device *device, enum eis_device_capability cap); /** - * Allow a capability on the device. This function must be called in - * response to an @ref EIS_EVENT_DEVICE_ADDED and before - * eis_device_connect(). + * Create a new device with the given name and capabilities on the seat. * - * This function has no effect if called for a capability the device does - * not support. This function has no effect if called for a capability not - * allowed on the seat this device belongs to. + * This device is not immediately active, use eis_device_add() to + * notify the client of it's availability. * - * This function has no effect if called after eis_device_connect() + * The returned device is refcounted, use eis_device_unref() to drop the + * reference. */ +struct eis_device * +eis_device_new(struct eis_seat *seat); + void -eis_device_allow_capability(struct eis_device *device, - enum eis_device_capability cap); +eis_device_configure_name(struct eis_device *device, const char *name); + +void +eis_device_configure_capability(struct eis_device *device, enum eis_device_capability cap); + +void +eis_device_configure_pointer_range(struct eis_device *device, + uint32_t w, uint32_t h); +void +eis_device_configure_touch_range(struct eis_device *device, + uint32_t w, uint32_t h); /** - * Connects the device. - * - * This function should be called in response to an @ref - * EIS_EVENT_DEVICE_ADDED if the server accepts the device creation. - * Any changes to the device, e.g. eis_device_set_name() and - * eis_device_disable_capability() must be performed before connecting the - * device. - * - * Calling eis_device_connect() on a device with all capabilities set to - * zero is a bug. - * - * If the device is rejected, call eis_device_disconnect() instead. + * Add this device to its seat and notify the client of the device's + * availability. * * The device is suspended, use eis_device_resume() to enable events from * the client. */ void -eis_device_connect(struct eis_device *device); +eis_device_add(struct eis_device *device); /** - * Disconnect the device. + * Remove the device. * This does not release any resources associated with this device, use * eis_device_unref() for any references held by the caller. */ void -eis_device_disconnect(struct eis_device *device); +eis_device_remove(struct eis_device *device); /** * Notify the client that the device is suspended and that no events @@ -592,6 +600,13 @@ void eis_device_keyboard_set_keymap(struct eis_device *device, struct eis_keymap *keymap); +/** + * For an event of type @ref EIS_EVENT_SEAT_BIND, return the capabilities + * requested by the client. + */ +bool +eis_event_seat_has_capability(struct eis_event *event, enum eis_device_capability cap); + /** * Return the device from this event. * @@ -610,7 +625,7 @@ eis_event_pointer_get_dx(struct eis_event *event); /** * For an event of type @ref EIS_EVENT_POINTER_MOTION return the relative y - * movement in logical pixels. +uint32_* movement in logical pixels. */ double eis_event_pointer_get_dy(struct eis_event *event); diff --git a/test/eierpecken.c b/test/eierpecken.c index f1227f1..4a88699 100644 --- a/test/eierpecken.c +++ b/test/eierpecken.c @@ -49,8 +49,18 @@ struct peck { uint32_t ei_behavior; struct logger *logger; + /* The default seat/devices */ struct eis_seat *eis_seat; + struct eis_device *eis_pointer; + struct eis_device *eis_keyboard; + struct eis_device *eis_abs; + struct eis_device *eis_touch; + struct ei_seat *ei_seat; + struct ei_device *ei_pointer; + struct ei_device *ei_keyboard; + struct ei_device *ei_abs; + struct ei_device *ei_touch; struct eis_client *eis_client; @@ -88,9 +98,19 @@ peck_destroy(struct peck *peck) eis_client_unref(peck->eis_client); - ei_seat_unref(peck->ei_seat); + + eis_device_unref(peck->eis_pointer); + eis_device_unref(peck->eis_abs); + eis_device_unref(peck->eis_keyboard); + eis_device_unref(peck->eis_touch); eis_seat_unref(peck->eis_seat); + ei_device_unref(peck->ei_pointer); + ei_device_unref(peck->ei_abs); + ei_device_unref(peck->ei_keyboard); + ei_device_unref(peck->ei_touch); + ei_seat_unref(peck->ei_seat); + ei_unref(peck->ei); eis_unref(peck->eis); logger_unref(peck->logger); @@ -105,6 +125,10 @@ OBJECT_IMPLEMENT_GETTER(peck, eis, struct eis*); void peck_drop_ei(struct peck *peck) { + peck->ei_pointer = ei_device_unref(peck->ei_pointer); + peck->ei_keyboard = ei_device_unref(peck->ei_keyboard); + peck->ei_abs = ei_device_unref(peck->ei_abs); + peck->ei_touch = ei_device_unref(peck->ei_touch); peck->ei_seat = ei_seat_unref(peck->ei_seat); peck->ei = NULL; } @@ -123,6 +147,34 @@ peck_eis_get_default_seat(struct peck *peck) return peck->eis_seat; }; +struct eis_device * +peck_eis_get_default_pointer(struct peck *peck) +{ + munit_assert_ptr_not_null(peck->eis_pointer); + return peck->eis_pointer; +}; + +struct eis_device * +peck_eis_get_default_pointer_absolute(struct peck *peck) +{ + munit_assert_ptr_not_null(peck->eis_abs); + return peck->eis_abs; +}; + +struct eis_device * +peck_eis_get_default_keyboard(struct peck *peck) +{ + munit_assert_ptr_not_null(peck->eis_keyboard); + return peck->eis_keyboard; +}; + +struct eis_device * +peck_eis_get_default_touch(struct peck *peck) +{ + munit_assert_ptr_not_null(peck->eis_touch); + return peck->eis_touch; +}; + struct ei_seat * peck_ei_get_default_seat(struct peck *peck) { @@ -130,6 +182,34 @@ peck_ei_get_default_seat(struct peck *peck) return peck->ei_seat; } +struct ei_device * +peck_ei_get_default_pointer(struct peck *peck) +{ + munit_assert_ptr_not_null(peck->ei_pointer); + return peck->ei_pointer; +}; + +struct ei_device * +peck_ei_get_default_pointer_absolute(struct peck *peck) +{ + munit_assert_ptr_not_null(peck->ei_abs); + return peck->ei_abs; +}; + +struct ei_device * +peck_ei_get_default_keyboard(struct peck *peck) +{ + munit_assert_ptr_not_null(peck->ei_keyboard); + return peck->ei_keyboard; +}; + +struct ei_device * +peck_ei_get_default_touch(struct peck *peck) +{ + munit_assert_ptr_not_null(peck->ei_touch); + return peck->ei_touch; +}; + static void peck_ei_log_handler(struct ei *ei, enum ei_log_priority priority, @@ -220,7 +300,7 @@ peck_new(void) rc = ei_setup_backend_fd(ei, sv[0]); munit_assert_int(rc, ==, 0); peck->ei = ei; - flag_set(peck->ei_behavior, PECK_EI_BEHAVIOR_AUTOCONNNECT); + flag_set(peck->ei_behavior, PECK_EI_BEHAVIOR_AUTOCONNECT); flag_set(peck->ei_behavior, PECK_EI_BEHAVIOR_AUTOSEAT); struct eis *eis = eis_new(peck); @@ -254,46 +334,37 @@ peck_enable_eis_behavior(struct peck *peck, enum peck_eis_behavior behavior) case PECK_EIS_BEHAVIOR_ACCEPT_ALL: peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_DEVICE); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_BIND_SEAT); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_RESUME_DEVICE); break; - case PECK_EIS_BEHAVIOR_REJECT_ALL: - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_REJECT_CLIENT); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_REJECT_DEVICE); + case PECK_EIS_BEHAVIOR_ADD_DEVICES: + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER_ABSOLUTE); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_TOUCH); break; - case PECK_EIS_BEHAVIOR_ACCEPT_DEVICE: - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_POINTER); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_POINTER_ABSOLUTE); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_KEYBOARD); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_TOUCH); - break; - case PECK_EIS_BEHAVIOR_REJECT_DEVICE: - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DROP_POINTER); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DROP_POINTER_ABSOLUTE); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DROP_KEYBOARD); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DROP_TOUCH); - break; - case PECK_EIS_BEHAVIOR_DROP_POINTER: - case PECK_EIS_BEHAVIOR_DROP_POINTER_ABSOLUTE: - case PECK_EIS_BEHAVIOR_DROP_KEYBOARD: - case PECK_EIS_BEHAVIOR_DROP_TOUCH: - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_DEVICE); - _fallthrough_; case PECK_EIS_BEHAVIOR_REJECT_CLIENT: flag_clear(peck->eis_behavior, behavior - 1); flag_set(peck->eis_behavior, behavior); break; - case PECK_EIS_BEHAVIOR_ACCEPT_POINTER: - case PECK_EIS_BEHAVIOR_ACCEPT_POINTER_ABSOLUTE: - case PECK_EIS_BEHAVIOR_ACCEPT_KEYBOARD: - case PECK_EIS_BEHAVIOR_ACCEPT_TOUCH: - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_DEVICE); - _fallthrough_; - case PECK_EIS_BEHAVIOR_ACCEPT_CLIENT: + case PECK_EIS_BEHAVIOR_ACCEPT_UNBIND_SEAT: + case PECK_EIS_BEHAVIOR_ACCEPT_BIND_SEAT: flag_clear(peck->eis_behavior, behavior + 1); flag_set(peck->eis_behavior, behavior); break; - case PECK_EIS_BEHAVIOR_HANDLE_DEVICE: + case PECK_EIS_BEHAVIOR_REJECT_UNBIND_SEAT: + case PECK_EIS_BEHAVIOR_REJECT_BIND_SEAT: + flag_clear(peck->eis_behavior, behavior - 1); + flag_set(peck->eis_behavior, behavior); + break; + case PECK_EIS_BEHAVIOR_ADD_POINTER: + case PECK_EIS_BEHAVIOR_ADD_POINTER_ABSOLUTE: + case PECK_EIS_BEHAVIOR_ADD_KEYBOARD: + case PECK_EIS_BEHAVIOR_ADD_TOUCH: + flag_set(peck->eis_behavior, behavior); + break; + case PECK_EIS_BEHAVIOR_ACCEPT_CLIENT: + flag_clear(peck->eis_behavior, behavior + 1); flag_set(peck->eis_behavior, behavior); break; case PECK_EIS_BEHAVIOR_RESUME_DEVICE: @@ -314,12 +385,12 @@ peck_enable_ei_behavior(struct peck *peck, enum peck_ei_behavior behavior) case PECK_EI_BEHAVIOR_NONE: peck->ei_behavior = 0; break; - case PECK_EI_BEHAVIOR_AUTOCONNNECT: + case PECK_EI_BEHAVIOR_AUTOCONNECT: case PECK_EI_BEHAVIOR_AUTOSEAT: flag_set(peck->ei_behavior, behavior); break; case PECK_EI_BEHAVIOR_AUTODEVICES: - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNNECT); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNECT); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOSEAT); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_RESUMED); @@ -346,12 +417,12 @@ peck_enable_ei_behavior(struct peck *peck, enum peck_ei_behavior behavior) static inline void peck_create_eis_seat(struct peck *peck, struct eis_client *client) { - _unref_(eis_seat) *seat = eis_client_new_seat(client, "default"); + _unref_(eis_seat) *seat = eis_client_new_seat(client, "peck default seat"); - eis_seat_allow_capability(seat, EIS_DEVICE_CAP_POINTER); - eis_seat_allow_capability(seat, EIS_DEVICE_CAP_POINTER_ABSOLUTE); - eis_seat_allow_capability(seat, EIS_DEVICE_CAP_KEYBOARD); - eis_seat_allow_capability(seat, EIS_DEVICE_CAP_TOUCH); + eis_seat_configure_capability(seat, EIS_DEVICE_CAP_POINTER); + eis_seat_configure_capability(seat, EIS_DEVICE_CAP_POINTER_ABSOLUTE); + eis_seat_configure_capability(seat, EIS_DEVICE_CAP_KEYBOARD); + eis_seat_configure_capability(seat, EIS_DEVICE_CAP_TOUCH); log_debug(peck, "EIS adding seat: '%s'\n", eis_seat_get_name(seat)); eis_seat_add(seat); @@ -376,46 +447,119 @@ peck_handle_eis_connect(struct peck *peck, struct eis_event *e) } } -static inline bool -peck_handle_eis_added(struct peck *peck, struct eis_event *e) +static inline struct eis_device * +peck_eis_create_pointer(struct peck *peck, struct eis_seat *seat, const char *name) { - struct eis_device *device = eis_event_get_device(e); - uint32_t mask = 0; - struct map { - enum eis_device_capability cap; - enum peck_eis_behavior behavior; - } map[] = { - { EIS_DEVICE_CAP_POINTER, PECK_EIS_BEHAVIOR_ACCEPT_POINTER }, - { EIS_DEVICE_CAP_POINTER_ABSOLUTE, PECK_EIS_BEHAVIOR_ACCEPT_POINTER_ABSOLUTE }, - { EIS_DEVICE_CAP_KEYBOARD, PECK_EIS_BEHAVIOR_ACCEPT_KEYBOARD }, - { EIS_DEVICE_CAP_TOUCH, PECK_EIS_BEHAVIOR_ACCEPT_TOUCH }, - }; - struct map *m; + struct eis_device *device = eis_device_new(seat); - ARRAY_FOR_EACH(map, m) { - if (eis_device_has_capability(device, m->cap)) { - if (flag_is_set(peck->eis_behavior, m->behavior)) { - mask |= bit(m->cap); - eis_device_allow_capability(device, m->cap); - } else { - log_debug(peck, "Dropping cap %d\n", m->cap); - } - } + eis_device_configure_name(device, name); + eis_device_configure_capability(device, EIS_DEVICE_CAP_POINTER); + eis_device_add(device); + + if (!peck->eis_pointer) + peck->eis_pointer = eis_device_ref(device); + + return device; +} + +static inline struct eis_device * +peck_eis_create_pointer_absolute(struct peck *peck, struct eis_seat *seat, const char *name) +{ + struct eis_device *device = eis_device_new(seat); + + eis_device_configure_name(device, name); + eis_device_configure_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE); + eis_device_configure_pointer_range(device, 1920, 1080); /* FIXME */ + eis_device_add(device); + + if (!peck->eis_abs) + peck->eis_abs = eis_device_ref(device); + + return device; +} + +static inline struct eis_device * +peck_eis_create_keyboard(struct peck *peck, struct eis_seat *seat, const char *name) +{ + struct eis_device *device = eis_device_new(seat); + + eis_device_configure_name(device, name); + eis_device_configure_capability(device, EIS_DEVICE_CAP_KEYBOARD); + eis_device_add(device); + + if (!peck->eis_keyboard) + peck->eis_keyboard = eis_device_ref(device); + + return device; +} + +static inline struct eis_device * +peck_eis_create_touch(struct peck *peck, struct eis_seat *seat, const char *name) +{ + struct eis_device *device = eis_device_new(seat); + + eis_device_configure_name(device, name); + eis_device_configure_capability(device, EIS_DEVICE_CAP_TOUCH); + eis_device_configure_touch_range(device, 1920, 1080); /* FIXME */ + eis_device_add(device); + + if (!peck->eis_touch) + peck->eis_touch = eis_device_ref(device); + + return device; +} + +static inline void +peck_handle_eis_seat_bind(struct peck *peck, struct eis_event *e) +{ + struct eis_seat *seat = eis_event_get_seat(e); + + log_debug(peck, "EIS binding seat: '%s'\n", eis_seat_get_name(seat)); + + if (eis_event_seat_has_capability(e, EIS_DEVICE_CAP_POINTER) && + flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_ADD_POINTER)) { + log_debug(peck, "EIS creating default pointer\n"); + _unref_(eis_device) *ptr = peck_eis_create_pointer(peck, seat, "default pointer"); + + if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_RESUME_DEVICE)) + eis_device_resume(ptr); } - if (!mask) { - log_debug(peck, "EIS refusing device: '%s'\n", - eis_device_get_name(device)); - eis_device_disconnect(device); - return false; - } else { - log_debug(peck, "EIS adding device: '%s'\n", - eis_device_get_name(device)); - eis_device_connect(device); - return true; + if (eis_event_seat_has_capability(e, EIS_DEVICE_CAP_POINTER_ABSOLUTE) && + flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_ADD_POINTER_ABSOLUTE)) { + log_debug(peck, "EIS creating default abs pointer\n"); + _unref_(eis_device) *abs = peck_eis_create_pointer_absolute(peck, seat, "default abs"); + + if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_RESUME_DEVICE)) + eis_device_resume(abs); + } + + if (eis_event_seat_has_capability(e, EIS_DEVICE_CAP_KEYBOARD) && + flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_ADD_KEYBOARD)) { + log_debug(peck, "EIS creating default keyboard\n"); + _unref_(eis_device) *kbd = peck_eis_create_keyboard(peck, seat, "default keyboard"); + + if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_RESUME_DEVICE)) + eis_device_resume(kbd); + } + + if (eis_event_seat_has_capability(e, EIS_DEVICE_CAP_TOUCH) && + flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_ADD_TOUCH)) { + log_debug(peck, "EIS creating default touch\n"); + _unref_(eis_device) *touch = peck_eis_create_touch(peck, seat, "default touch"); + + if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_RESUME_DEVICE)) + eis_device_resume(touch); } } +static inline void +peck_handle_eis_seat_unbind(struct peck *peck, struct eis_seat *seat) +{ + /* FIXME */ +} + + bool _peck_dispatch_eis(struct peck *peck, int lineno) { @@ -440,9 +584,16 @@ _peck_dispatch_eis(struct peck *peck, int lineno) flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_REJECT_CLIENT)) process_event = tristate_yes; break; - case EIS_EVENT_DEVICE_ADDED: - case EIS_EVENT_DEVICE_REMOVED: - if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_HANDLE_DEVICE)) + case EIS_EVENT_SEAT_BIND: + if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_ACCEPT_BIND_SEAT) || + flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_REJECT_BIND_SEAT)) + process_event = tristate_yes; + else + process_event = tristate_no; + break; + case EIS_EVENT_SEAT_UNBIND: + if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_ACCEPT_UNBIND_SEAT) || + flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_REJECT_UNBIND_SEAT)) process_event = tristate_yes; else process_event = tristate_no; @@ -474,14 +625,11 @@ _peck_dispatch_eis(struct peck *peck, int lineno) eis_client_get_name(eis_event_get_client(e))); eis_client_disconnect(eis_event_get_client(e)); break; - case EIS_EVENT_DEVICE_ADDED: - if (peck_handle_eis_added(peck, e) && - flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_RESUME_DEVICE)) - eis_device_resume(eis_event_get_device(e)); + case EIS_EVENT_SEAT_BIND: + peck_handle_eis_seat_bind(peck, e); break; - case EIS_EVENT_DEVICE_REMOVED: - log_debug(peck, "EIS removing device\n"); - eis_device_disconnect(eis_event_get_device(e)); + case EIS_EVENT_SEAT_UNBIND: + peck_handle_eis_seat_unbind(peck, eis_event_get_seat(e)); break; default: break; @@ -537,7 +685,7 @@ _peck_dispatch_ei(struct peck *peck, int lineno) switch (ei_event_get_type(e)) { case EI_EVENT_CONNECT: if (flag_is_set(peck->ei_behavior, - PECK_EI_BEHAVIOR_AUTOCONNNECT)) + PECK_EI_BEHAVIOR_AUTOCONNECT)) process_event = tristate_yes; break; case EI_EVENT_SEAT_ADDED: @@ -585,10 +733,23 @@ _peck_dispatch_ei(struct peck *peck, int lineno) struct ei_seat *seat = ei_event_get_seat(e); munit_assert_ptr_null(peck->ei_seat); peck->ei_seat = ei_seat_ref(seat); - log_debug(peck, "default seat: %s\n"); + log_debug(peck, "default seat: %s\n", ei_seat_get_name(peck->ei_seat)); + ei_seat_bind(seat); break; } case EI_EVENT_DEVICE_ADDED: + { + struct ei_device *device = ei_event_get_device(e); + if (ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)) + peck->ei_pointer = ei_device_ref(device); + if (ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)) + peck->ei_abs = ei_device_ref(device); + if (ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD)) + peck->ei_keyboard = ei_device_ref(device); + if (ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH)) + peck->ei_touch = ei_device_ref(device); + break; + } case EI_EVENT_DEVICE_RESUMED: case EI_EVENT_DEVICE_SUSPENDED: /* Nothing to do here */ @@ -765,8 +926,9 @@ peck_eis_event_type_name(enum eis_event_type type) switch (type) { CASE_STRING(CLIENT_CONNECT); CASE_STRING(CLIENT_DISCONNECT); - CASE_STRING(DEVICE_ADDED); - CASE_STRING(DEVICE_REMOVED); + CASE_STRING(SEAT_BIND); + CASE_STRING(SEAT_UNBIND); + CASE_STRING(DEVICE_CLOSED); CASE_STRING(POINTER_MOTION); CASE_STRING(POINTER_MOTION_ABSOLUTE); CASE_STRING(POINTER_BUTTON); diff --git a/test/eierpecken.h b/test/eierpecken.h index f053681..06b8c16 100644 --- a/test/eierpecken.h +++ b/test/eierpecken.h @@ -43,24 +43,10 @@ enum peck_eis_behavior { */ PECK_EIS_BEHAVIOR_NONE, /** - * Create a "default" seat. This behavior is enabled as part of - * PECK_EIS_BEHAVIOR_ACCEPT_ALL. - */ - PECK_EIS_BEHAVIOR_DEFAULT_SEAT, - /** - * Do not create a "default" seat. - */ - PECK_EIS_BEHAVIOR_NO_DEFAULT_SEAT, - /** - * Accept all client connection requests and device additions + * Accept all client connection requests, create default seats * **and** resume any device immediately after add. - * This also enables @ref PECK_EIS_BEHAVIOR_DEFAULT_SEAT. */ PECK_EIS_BEHAVIOR_ACCEPT_ALL, - /** - * Reject any client connection requests or device additions. - */ - PECK_EIS_BEHAVIOR_REJECT_ALL, /** * Process connect/disconnect requests from the client. @@ -69,23 +55,31 @@ enum peck_eis_behavior { PECK_EIS_BEHAVIOR_REJECT_CLIENT, /** - * Process add/remove requests from the client. + * Create a "default" seat. This behavior is enabled as part of + * PECK_EIS_BEHAVIOR_ACCEPT_ALL. */ - PECK_EIS_BEHAVIOR_HANDLE_DEVICE, /* Implied by the various ones below */ - PECK_EIS_BEHAVIOR_ACCEPT_DEVICE, - PECK_EIS_BEHAVIOR_REJECT_DEVICE, + PECK_EIS_BEHAVIOR_DEFAULT_SEAT, + /** + * Do not create a "default" seat. + */ + PECK_EIS_BEHAVIOR_NO_DEFAULT_SEAT, - PECK_EIS_BEHAVIOR_ACCEPT_POINTER, - PECK_EIS_BEHAVIOR_DROP_POINTER, + /** + * Accept or reject bind/unbind seat requests + */ + PECK_EIS_BEHAVIOR_ACCEPT_BIND_SEAT, + PECK_EIS_BEHAVIOR_REJECT_BIND_SEAT, + PECK_EIS_BEHAVIOR_ACCEPT_UNBIND_SEAT, + PECK_EIS_BEHAVIOR_REJECT_UNBIND_SEAT, - PECK_EIS_BEHAVIOR_ACCEPT_POINTER_ABSOLUTE, - PECK_EIS_BEHAVIOR_DROP_POINTER_ABSOLUTE, - - PECK_EIS_BEHAVIOR_ACCEPT_KEYBOARD, - PECK_EIS_BEHAVIOR_DROP_KEYBOARD, - - PECK_EIS_BEHAVIOR_ACCEPT_TOUCH, - PECK_EIS_BEHAVIOR_DROP_TOUCH, + /** + * Create default devices + */ + PECK_EIS_BEHAVIOR_ADD_DEVICES, /**< add all of the below */ + PECK_EIS_BEHAVIOR_ADD_POINTER, + PECK_EIS_BEHAVIOR_ADD_POINTER_ABSOLUTE, + PECK_EIS_BEHAVIOR_ADD_KEYBOARD, + PECK_EIS_BEHAVIOR_ADD_TOUCH, PECK_EIS_BEHAVIOR_RESUME_DEVICE, PECK_EIS_BEHAVIOR_SUSPEND_DEVICE, @@ -94,9 +88,9 @@ enum peck_eis_behavior { enum peck_ei_behavior { PECK_EI_BEHAVIOR_NONE, /* enabled by default - handle the Connect event */ - PECK_EI_BEHAVIOR_AUTOCONNNECT, + PECK_EI_BEHAVIOR_AUTOCONNECT, /* enabled by default - handle the first seat added event, setting - * the default seat to the first seat */ + * the default seat to the first seat and bind to it */ PECK_EI_BEHAVIOR_AUTOSEAT, /* handle Connect/Seat/Added/Resumed events, i.e. anything until the * first real device event */ @@ -137,9 +131,33 @@ peck_eis_get_default_client(struct peck *peck); struct eis_seat * peck_eis_get_default_seat(struct peck *peck); +struct eis_device * +peck_eis_get_default_pointer(struct peck *peck); + +struct eis_device * +peck_eis_get_default_keyboard(struct peck *peck); + +struct eis_device * +peck_eis_get_default_pointer_absolute(struct peck *peck); + +struct eis_device * +peck_eis_get_default_touch(struct peck *peck); + struct ei_seat * peck_ei_get_default_seat(struct peck *peck); +struct ei_device * +peck_ei_get_default_pointer(struct peck *peck); + +struct ei_device * +peck_ei_get_default_keyboard(struct peck *peck); + +struct ei_device * +peck_ei_get_default_pointer_absolute(struct peck *peck); + +struct ei_device * +peck_ei_get_default_touch(struct peck *peck); + /** * Dispatch all events according to the currently defined behavior. * When this function returns false, the connection is in a "stable" state @@ -241,6 +259,7 @@ DEFINE_UNREF_CLEANUP_FUNC(ei_event); DEFINE_UNREF_CLEANUP_FUNC(ei_device); DEFINE_UNREF_CLEANUP_FUNC(ei_touch); DEFINE_UNREF_CLEANUP_FUNC(ei_keymap); +DEFINE_UNREF_CLEANUP_FUNC(ei_seat); DEFINE_UNREF_CLEANUP_FUNC(eis); DEFINE_UNREF_CLEANUP_FUNC(eis_client); diff --git a/test/test-ei.c b/test/test-ei.c index e0212d7..e909d7c 100644 --- a/test/test-ei.c +++ b/test/test-ei.c @@ -206,23 +206,25 @@ MUNIT_TEST(test_ei_disconnect_self_after_seat) return MUNIT_OK; } -MUNIT_TEST(test_ei_disconnect_after_add_before_received) + +MUNIT_TEST(test_ei_disconnect_after_bind_before_received) { _unref_(peck) *peck = peck_new(); _unref_(eis_client) *client = NULL; - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); + 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_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNECT); 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_POINTER); - ei_device_add(device); + _unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED); + struct ei_seat *seat = ei_event_get_seat(event); + ei_seat_bind(seat); } - /* We have *not* called eis_dispatch, so the device add hasn't been + /* We have *not* called eis_dispatch, so the seat bind hasn't been * processed by the server yet */ with_server(peck) { struct eis_client *client = peck_eis_get_default_client(peck); @@ -231,8 +233,6 @@ MUNIT_TEST(test_ei_disconnect_after_add_before_received) with_client(peck) { ei_dispatch(ei); - _unref_(ei_event) *device_removed = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); _unref_(ei_event) *seat_removed = peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED); _unref_(ei_event) *disconnect = @@ -242,21 +242,22 @@ MUNIT_TEST(test_ei_disconnect_after_add_before_received) return MUNIT_OK; } -MUNIT_TEST(test_ei_disconnect_self_after_add_before_received) +MUNIT_TEST(test_ei_disconnect_self_after_bind_before_received) { _unref_(peck) *peck = peck_new(); _unref_(eis_client) *client = 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_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNECT); 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_POINTER); - ei_device_add(device); + _unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED); + struct ei_seat *seat = ei_event_get_seat(event); + ei_seat_bind(seat); + /* Disconnect before the server can process the bind event */ peck_drop_ei(peck); ei_unref(ei); } @@ -264,15 +265,14 @@ MUNIT_TEST(test_ei_disconnect_self_after_add_before_received) peck_dispatch_eis(peck); with_server(peck) { - _unref_(eis_event) *added = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); - - /* Device is already gone, but let's say we add it anyway */ - struct eis_device *device = eis_event_get_device(added); - eis_device_connect(device); - - _unref_(eis_event) *removed = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED); + /* Server got the bind event but client disconnected + * immediately after */ + _unref_(eis_event) *bind = + peck_eis_next_event(eis, EIS_EVENT_SEAT_BIND); + /* FIXME: libeis should insert unbind here? + _unref_(eis_event) *unbind = + peck_eis_next_event(eis, EIS_EVENT_SEAT_UNBIND); + */ _unref_(eis_event) *disconnect = peck_eis_next_event(eis, EIS_EVENT_CLIENT_DISCONNECT); } @@ -280,24 +280,25 @@ MUNIT_TEST(test_ei_disconnect_self_after_add_before_received) return MUNIT_OK; } -MUNIT_TEST(test_ei_disconnect_after_add_after_received) +MUNIT_TEST(test_ei_disconnect_after_bind_after_received) { _unref_(peck) *peck = peck_new(); _unref_(eis_client) *client = 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_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNECT); 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_POINTER); - ei_device_add(device); + _unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED); + struct ei_seat *seat = ei_event_get_seat(event); + ei_seat_bind(seat); } - /* Receive the Added event but don't actually add the device */ + /* Receive the Bind event but don't actually add any devices, + * disconnect the client instead */ peck_dispatch_eis(peck); with_server(peck) { @@ -307,8 +308,6 @@ MUNIT_TEST(test_ei_disconnect_after_add_after_received) with_client(peck) { ei_dispatch(ei); - _unref_(ei_event) *device_removed = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); _unref_(ei_event) *seat_removed = peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED); _unref_(ei_event) *disconnect = @@ -318,23 +317,24 @@ MUNIT_TEST(test_ei_disconnect_after_add_after_received) return MUNIT_OK; } -MUNIT_TEST(test_ei_disconnect_self_after_add_after_received) +MUNIT_TEST(test_ei_disconnect_self_after_bind_after_received) { _unref_(peck) *peck = peck_new(); _unref_(eis_client) *client = 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_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNECT); 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_POINTER); - ei_device_add(device); + _unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED); + struct ei_seat *seat = ei_event_get_seat(event); + ei_seat_bind(seat); } + /* Make sure server sees Bind, then disconnect from server */ peck_dispatch_eis(peck); with_client(peck) { @@ -345,15 +345,12 @@ MUNIT_TEST(test_ei_disconnect_self_after_add_after_received) peck_dispatch_eis(peck); with_server(peck) { - _unref_(eis_event) *added = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); - - /* Device is already gone, but let's say we add it anyway */ - struct eis_device *device = eis_event_get_device(added); - eis_device_connect(device); - - _unref_(eis_event) *removed = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED); + _unref_(eis_event) *bind = + peck_eis_next_event(eis, EIS_EVENT_SEAT_BIND); + /* FIXME: libeis should insert unbind here? + _unref_(eis_event) *unbind = + peck_eis_next_event(eis, EIS_EVENT_SEAT_UNBIND); + */ _unref_(eis_event) *disconnect = peck_eis_next_event(eis, EIS_EVENT_CLIENT_DISCONNECT); } @@ -361,39 +358,35 @@ MUNIT_TEST(test_ei_disconnect_self_after_add_after_received) return MUNIT_OK; } -MUNIT_TEST(test_ei_disconnect_after_remove_before_received) +MUNIT_TEST(test_ei_disconnect_after_unbind_before_received) { _unref_(peck) *peck = peck_new(); _unref_(ei_device) *device = NULL; + _unref_(ei_seat) *seat = NULL; - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); + 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) { - 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_POINTER); - ei_device_add(device); + _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); } peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); - /* server has the device now */ + /* server has the Bind event now */ peck_dispatch_until_stable(peck); with_client(peck) { - _unref_(ei_event) *added = - peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - _unref_(ei_event) *resumed = - peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); - ei_device_remove(device); + ei_seat_unbind(seat); } /* No server dispatch here so the server isn't aware of the - * ei_device_remove() call. Disconnect the client, this - * automatically removes all devices */ + * ei_seat_unbind() call. Disconnect the client + */ with_server(peck) { struct eis_client *client = peck_eis_get_default_client(peck); eis_client_disconnect(client); @@ -401,8 +394,6 @@ MUNIT_TEST(test_ei_disconnect_after_remove_before_received) with_client(peck) { ei_dispatch(ei); - _unref_(ei_event) *device_removed = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); _unref_(ei_event) *seat_removed = peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED); _unref_(ei_event) *disconnect = @@ -412,34 +403,31 @@ MUNIT_TEST(test_ei_disconnect_after_remove_before_received) return MUNIT_OK; } -MUNIT_TEST(test_ei_disconnect_after_remove_after_received) +MUNIT_TEST(test_ei_disconnect_after_unbind_after_received) { _unref_(peck) *peck = peck_new(); _unref_(ei_device) *device = NULL; + _unref_(ei_seat) *seat = NULL; peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); + 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) { - 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_POINTER); - ei_device_add(device); + _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 device now */ + /* server has the Bind event now */ peck_dispatch_until_stable(peck); with_client(peck) { - _unref_(ei_event) *added = - peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - _unref_(ei_event) *resumed = - peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); - ei_device_remove(device); + ei_seat_unbind(seat); } - /* Dispatch, server is aware of the ei_device_remove() */ + /* Dispatch, server is aware of the ei_seat_unbind() */ peck_dispatch_eis(peck); with_server(peck) { struct eis_client *client = peck_eis_get_default_client(peck); @@ -448,9 +436,6 @@ MUNIT_TEST(test_ei_disconnect_after_remove_after_received) peck_dispatch_ei(peck); with_client(peck) { - _unref_(ei_event) *device_removed = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - _unref_(ei_event) *seat_removed = peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED); @@ -464,132 +449,98 @@ MUNIT_TEST(test_ei_disconnect_after_remove_after_received) MUNIT_TEST(test_ei_device_basics) { _unref_(peck) *peck = peck_new(); - _unref_(ei_device) *device = NULL; 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) { - struct ei_seat *seat = peck_ei_get_default_seat(peck); - device = ei_device_new(seat); + _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); - 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)); + 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) +MUNIT_TEST(test_ei_device_set_name_multiple_devices) { _unref_(peck) *peck = peck_new(); - _unref_(ei_device) *d1 = NULL; - _unref_(ei_device) *d2 = NULL; - _unref_(ei_device) *d3 = NULL; 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_client(peck) { - struct ei_seat *seat = peck_ei_get_default_seat(peck); - d1 = ei_device_new(seat); - ei_device_configure_name(d1, "first device"); - ei_device_configure_capability(d1, EI_DEVICE_CAP_POINTER); - ei_device_add(d1); - - d2 = ei_device_new(seat); - 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(seat); - 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) { - _unref_(eis_event) *e1 = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); + 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); - 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); + _unref_(eis_device) *d2 = eis_device_new(seat); + /* Unnamed */ + eis_device_add(d2); - _unref_(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); - - _unref_(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); + _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); - munit_assert_ptr_equal(d1, ei_event_get_device(e1)); - munit_assert_string_equal(ei_device_get_name(d1), "other name"); + _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); - munit_assert_ptr_equal(d2, ei_event_get_device(e2)); - munit_assert_ptr_null(ei_device_get_name(d2)); + _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); - munit_assert_ptr_equal(d3, ei_event_get_device(e3)); + _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"); } @@ -603,32 +554,38 @@ MUNIT_TEST(test_ei_device_never_added) peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_dispatch_until_stable(peck); - /* unref after remove */ - with_client(peck) { - struct ei_seat *seat = peck_ei_get_default_seat(peck); - _unref_(ei_device) *device = ei_device_new(seat); - ei_device_remove(device); + /* 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_client(peck) { - struct ei_seat *seat = peck_ei_get_default_seat(peck); - struct ei_device *device = ei_device_new(seat); - ei_device_unref(device); - ei_device_remove(device); + 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_server(peck) { - peck_assert_no_eis_events(eis); + with_client(peck) { + peck_assert_no_ei_events(ei); } return MUNIT_OK; @@ -643,345 +600,52 @@ MUNIT_TEST(test_ei_device_add_remove) peck_dispatch_until_stable(peck); _unref_(ei_device) *device = NULL; - - with_client(peck) { - 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_POINTER); - ei_device_add(device); - } - - peck_dispatch_until_stable(peck); - _unref_(eis_device) *eis_device = NULL; - with_server(peck) { - _unref_(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); - - _unref_(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); - _unref_(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); - - _unref_(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) -{ - _unref_(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); - - _unref_(ei_device) *d1 = NULL; - _unref_(ei_device) *d2 = NULL; - - with_client(peck) { - struct ei_seat *seat = peck_ei_get_default_seat(peck); - d1 = ei_device_new(seat); - ei_device_configure_name(d1, "first"); - ei_device_configure_capability(d1, EI_DEVICE_CAP_POINTER); - ei_device_add(d1); - - d2 = ei_device_new(seat); - 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); - - with_server(peck) { - _unref_(eis_event) *e1 = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED); - _unref_(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 don't eis_device_disconnect(d1). It doesn't matter - * because libeis will do this for us when receiving the - * event. */ - } - - peck_dispatch_ei(peck); - with_client(peck) { - _unref_(ei_event) *e1 = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - - struct ei_device *r1 = ei_event_get_device(e1); - munit_assert_ptr_equal(d1, r1); - - _unref_(ei_event) *e2 = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - - struct ei_device *r2 = ei_event_get_device(e2); - munit_assert_ptr_equal(d2, r2); - peck_assert_no_ei_events(ei); - } - - return MUNIT_OK; -} - - -MUNIT_TEST(test_ei_device_add_drop_caps) -{ - _unref_(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); - - _unref_(ei_device) *device = NULL; - - with_client(peck) { - 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_POINTER); - ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD); - ei_device_add(device); - } - - peck_dispatch_eis(peck); - - with_client(peck) { - ei_dispatch(ei); - - _unref_(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) -{ - _unref_(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); - - _unref_(ei_device) *device = NULL; - - with_client(peck) { - 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_POINTER); - ei_device_add(device); - } - - peck_dispatch_eis(peck); - - with_client(peck) { - ei_dispatch(ei); - - _unref_(ei_event) *event = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - } - - return MUNIT_OK; -} - -MUNIT_TEST(test_ei_device_add_after_seat_remove) -{ - _unref_(peck) *peck = peck_new(); - - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED); - peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_RESUMED); - 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_POINTER); - ei_device_add(device); - } - - peck_dispatch_until_stable(peck); - with_server(peck) { struct eis_seat *seat = peck_eis_get_default_seat(peck); - eis_seat_remove(seat); - } - - /* Seat was removed by server but we don't know this yet, let's add - * a device */ - 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_POINTER); - ei_device_add(device); + 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); - /* Now add a device while the SEAT_REMOVED event is pending */ with_client(peck) { - /* The original device */ - _unref_(ei_event) *removed1 = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - - /* The device added before we knew about seat removal */ - _unref_(ei_event) *removed2 = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - - 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_POINTER); - ei_device_add(device); - - /* The device added just above */ - _unref_(ei_event) *removed3 = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - - _unref_(ei_event) *seat_removed = - peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED); + _unref_(ei_event) *event = + peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); + device = ei_device_ref(ei_event_get_device(event)); } - /* Now add a device when the seat had already been removed */ - 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_POINTER); - ei_device_add(device); - - _unref_(ei_event) *removed = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - } - - return MUNIT_OK; -} - -MUNIT_TEST(test_ei_device_add_after_disconnect) -{ - _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_client *client = peck_eis_get_default_client(peck); - eis_client_disconnect(client); + eis_device_remove(eis_device); } peck_dispatch_until_stable(peck); with_client(peck) { - struct ei_seat *seat = peck_ei_get_default_seat(peck); - _unref_(ei_device) *d1 = ei_device_new(seat); - - ei_device_configure_name(d1, __func__); - ei_device_configure_capability(d1, EI_DEVICE_CAP_POINTER); - ei_device_add(d1); - - _unref_(ei_event) *removed1 = + _unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - _unref_(ei_event) *seat_removed = - peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED); - - _unref_(ei_device) *d2 = ei_device_new(seat); - - ei_device_configure_name(d2, __func__); - ei_device_configure_capability(d2, EI_DEVICE_CAP_POINTER); - ei_device_add(d2); - - _unref_(ei_event) *removed2 = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - - _unref_(ei_event) *disconnect = - peck_ei_next_event(ei, EI_EVENT_DISCONNECT); + 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(); - _unref_(ei_device) *device = NULL; 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_seat *seat = peck_ei_get_default_seat(peck); - device = ei_device_new(seat); - 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) { + 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); @@ -1012,27 +676,17 @@ MUNIT_TEST(test_ei_device_pointer_rel) MUNIT_TEST(test_ei_device_pointer_abs) { _unref_(peck) *peck = peck_new(); - _unref_(ei_device) *device = NULL; + struct ei_device *device = NULL; peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); - peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT); + 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); - with_client(peck) { - struct ei_seat *seat = peck_ei_get_default_seat(peck); - device = ei_device_new(seat); - 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); + /* 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); } @@ -1058,21 +712,22 @@ MUNIT_TEST(test_ei_device_pointer_abs) 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_remove(device); + ei_device_close(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); + peck_dispatch_until_stable(peck); + with_server(peck) { _unref_(eis_event) *e = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED); + peck_eis_next_event(eis, EIS_EVENT_DEVICE_CLOSED); peck_assert_no_eis_events(eis); } @@ -1082,26 +737,17 @@ MUNIT_TEST(test_ei_device_pointer_abs) MUNIT_TEST(test_ei_device_touch) { _unref_(peck) *peck = peck_new(); - _unref_(ei_device) *device = NULL; + 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); - with_client(peck) { - struct ei_seat *seat = peck_ei_get_default_seat(peck); - device = ei_device_new(seat); - 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); + /* 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); @@ -1124,8 +770,8 @@ MUNIT_TEST(test_ei_device_touch) with_client(peck) { _unref_(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_down(t, 1920, 1200); + ei_touch_motion(t, 1920, 1000); ei_touch_up(t); } @@ -1139,7 +785,7 @@ MUNIT_TEST(test_ei_device_touch) _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, 1200, 200); + ei_touch_motion(t, 1950, 200); ei_touch_up(t); } @@ -1225,26 +871,17 @@ MUNIT_TEST(test_ei_device_touch) MUNIT_TEST(test_ei_device_multitouch) { _unref_(peck) *peck = peck_new(); - _unref_(ei_device) *device = NULL; + 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); - with_client(peck) { - struct ei_seat *seat = peck_ei_get_default_seat(peck); - device = ei_device_new(seat); - 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) { + 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); @@ -1285,6 +922,9 @@ MUNIT_TEST(test_ei_device_multitouch) 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)); @@ -1303,10 +943,14 @@ MUNIT_TEST(test_ei_keymap_invalid) 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; @@ -1376,10 +1020,14 @@ MUNIT_TEST(test_ei_keymap_set) } 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)); @@ -1425,10 +1073,14 @@ MUNIT_TEST(test_ei_keymap_null) } 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)); @@ -1490,6 +1142,7 @@ MUNIT_TEST(test_ei_keymap_changed) } return MUNIT_OK; +#endif } /* Emulates the XWayland behavior for calling @@ -1498,26 +1151,16 @@ MUNIT_TEST(test_ei_keymap_changed) MUNIT_TEST(test_xdotool_rel_motion) { _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); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); peck_dispatch_until_stable(peck); with_client(peck) { - 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_POINTER); - ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD); - ei_device_add(device); - } - - peck_dispatch_until_stable(peck); - - with_client(peck) { + struct ei_device *device = peck_ei_get_default_pointer(peck); ei_device_pointer_motion(device, -1, 10); - ei_device_remove(device); - ei_device_unref(device); + ei_device_close(device); ei_unref(ei); peck_drop_ei(peck); } @@ -1527,8 +1170,8 @@ MUNIT_TEST(test_xdotool_rel_motion) with_server(peck) { _unref_(eis_event) *motion = peck_eis_next_event(eis, EIS_EVENT_POINTER_MOTION); - _unref_(eis_event) *removed = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED); + _unref_(eis_event) *close = + peck_eis_next_event(eis, EIS_EVENT_DEVICE_CLOSED); _unref_(eis_event) *disconnect = peck_eis_next_event(eis, EIS_EVENT_CLIENT_DISCONNECT); @@ -1537,9 +1180,3 @@ MUNIT_TEST(test_xdotool_rel_motion) return MUNIT_OK; } - -int -main(int argc, char **argv) -{ - return munit_tests_run(argc, argv); -} diff --git a/test/test-eis.c b/test/test-eis.c index 41302d5..3dfee94 100644 --- a/test/test-eis.c +++ b/test/test-eis.c @@ -76,6 +76,73 @@ MUNIT_TEST(eistest_name) return MUNIT_OK; } +MUNIT_TEST(eistest_cliend_bind_all_caps) +{ + _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_client(peck) { + struct ei_seat *seat = peck_ei_get_default_seat(peck); + ei_seat_bind(seat); + } + + peck_dispatch_until_stable(peck); + + with_server(peck) { + _unref_(eis_event) *event = + peck_eis_next_event(eis, EIS_EVENT_SEAT_BIND); + + /* Our default seat has all caps */ + munit_assert_true(eis_event_seat_has_capability(event, EIS_DEVICE_CAP_KEYBOARD)); + munit_assert_true(eis_event_seat_has_capability(event, EIS_DEVICE_CAP_POINTER)); + munit_assert_true(eis_event_seat_has_capability(event, EIS_DEVICE_CAP_POINTER_ABSOLUTE)); + munit_assert_true(eis_event_seat_has_capability(event, EIS_DEVICE_CAP_TOUCH)); + } + + return MUNIT_OK; +} + +MUNIT_TEST(eistest_cliend_bind_some_caps) +{ + _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_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); + struct ei_seat *seat = ei_event_get_seat(event); + ei_seat_drop_capability(seat, EI_DEVICE_CAP_KEYBOARD); + ei_seat_drop_capability(seat, EI_DEVICE_CAP_TOUCH); + ei_seat_bind(seat); + } + + peck_dispatch_until_stable(peck); + + with_server(peck) { + _unref_(eis_event) *event = + peck_eis_next_event(eis, EIS_EVENT_SEAT_BIND); + + /* Our default seat has all caps */ + munit_assert_false(eis_event_seat_has_capability(event, EIS_DEVICE_CAP_KEYBOARD)); + munit_assert_true(eis_event_seat_has_capability(event, EIS_DEVICE_CAP_POINTER)); + munit_assert_true(eis_event_seat_has_capability(event, EIS_DEVICE_CAP_POINTER_ABSOLUTE)); + munit_assert_false(eis_event_seat_has_capability(event, EIS_DEVICE_CAP_TOUCH)); + } + + return MUNIT_OK; +} + +#if 0 MUNIT_TEST(eistest_ranges) { _unref_(peck) *peck = peck_new(); @@ -112,33 +179,22 @@ MUNIT_TEST(eistest_ranges) return MUNIT_OK; } +#endif MUNIT_TEST(eistest_device_resume_suspend_twice) { _unref_(peck) *peck = peck_new(); - _unref_(eis_device) *device = NULL; 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_client(peck) { - struct ei_seat *seat = peck_ei_get_default_seat(peck); - _unref_(ei_device) *d = ei_device_new(seat); - ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER); - ei_device_add(d); - } - + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_BIND_SEAT); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED); peck_dispatch_until_stable(peck); with_server(peck) { - _unref_(eis_event) *added = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); + struct eis_device *device = peck_eis_get_default_pointer(peck); - device = eis_device_ref(eis_event_get_device(added)); - - eis_device_allow_capability(device, EIS_DEVICE_CAP_POINTER); - eis_device_connect(device); /* Resuming multiple times should only trigger one event */ eis_device_resume(device); eis_device_resume(device); /* noop */ @@ -148,14 +204,6 @@ MUNIT_TEST(eistest_device_resume_suspend_twice) peck_dispatch_until_stable(peck); with_client(peck) { - _unref_(ei_event) *added = - peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); - - /* _until_stable() may stop after DEVICE_ADDED since it's - * punting to the caller, so we need another dispatch to - * make sure the RESUMED is really waiting for us here */ - ei_dispatch(ei); - _unref_(ei_event) *resumed = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); @@ -164,6 +212,8 @@ MUNIT_TEST(eistest_device_resume_suspend_twice) /* Suspending multiple times should only trigger one event */ with_server(peck) { + struct eis_device *device = peck_eis_get_default_pointer(peck); + eis_device_suspend(device); eis_device_suspend(device); /* noop */ eis_device_suspend(device); /* noop */ @@ -181,34 +231,14 @@ MUNIT_TEST(eistest_device_resume_suspend_twice) return MUNIT_OK; } -MUNIT_TEST(eistest_device_ignore_suspended) +MUNIT_TEST(eistest_device_ignore_suspended_device) { _unref_(peck) *peck = peck_new(); - _unref_(eis_device) *device = NULL; 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_client(peck) { - struct ei_seat *seat = peck_ei_get_default_seat(peck); - _unref_(ei_device) *d = ei_device_new(seat); - ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER); - ei_device_add(d); - } - - peck_dispatch_until_stable(peck); - - with_server(peck) { - _unref_(eis_event) *added = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); - - device = eis_device_ref(eis_event_get_device(added)); - - eis_device_allow_capability(device, EIS_DEVICE_CAP_POINTER); - eis_device_connect(device); - } - + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_BIND_SEAT); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER); peck_dispatch_until_stable(peck); with_client(peck) { @@ -220,7 +250,10 @@ MUNIT_TEST(eistest_device_ignore_suspended) ei_device_pointer_motion(device, 1, 1); } + for (size_t i = 0; i < 3; i++) { + struct eis_device *device = peck_eis_get_default_pointer(peck); + /* Device is suspended */ with_server(peck) { peck_assert_no_eis_events(eis); @@ -264,72 +297,3 @@ MUNIT_TEST(eistest_device_ignore_suspended) return MUNIT_OK; } - -MUNIT_TEST(eistest_device_late_connect) -{ - _unref_(peck) *peck = peck_new(); - _unref_(eis_device) *eis_device = NULL; - _unref_(ei_device) *ei_device = NULL; - - 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_client(peck) { - struct ei_seat *seat = peck_ei_get_default_seat(peck); - ei_device = ei_device_new(seat); - ei_device_configure_capability(ei_device, EI_DEVICE_CAP_POINTER); - ei_device_add(ei_device); - } - - peck_dispatch_until_stable(peck); - - with_server(peck) { - _unref_(eis_event) *added = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED); - eis_device = eis_device_ref(eis_event_get_device(added)); - /* Do not connect here */ - } - - peck_dispatch_until_stable(peck); - - with_client(peck) { - /* remove before server accepted */ - ei_device_remove(ei_device); - } - - peck_dispatch_until_stable(peck); - - with_server(peck) { - /* libeis will confirm removal automatically, so this is a - * noop - the device is already removed */ - eis_device_allow_capability(eis_device, EIS_DEVICE_CAP_POINTER); - eis_device_connect(eis_device); - } - - peck_dispatch_until_stable(peck); - - with_server(peck) { - _unref_(eis_event) *removed = - peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED); - peck_assert_no_eis_events(eis); - } - - peck_dispatch_until_stable(peck); - - with_client(peck) { - /* We never get an added event, the removed event is already - * handled before we get to it */ - _unref_(ei_event) *removed = - peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); - peck_assert_no_ei_events(ei); - } - - return MUNIT_OK; -} - -int -main(int argc, char **argv) -{ - return munit_tests_run(argc, argv); -} diff --git a/test/test-main.c b/test/test-main.c new file mode 100644 index 0000000..66a24e1 --- /dev/null +++ b/test/test-main.c @@ -0,0 +1,8 @@ +#include "util-munit.h" + +int +main(int argc, char **argv) +{ + return munit_tests_run(argc, argv); +} + diff --git a/tools/ei-demo-client.c b/tools/ei-demo-client.c index 434ee5c..761b7ef 100644 --- a/tools/ei-demo-client.c +++ b/tools/ei-demo-client.c @@ -71,6 +71,7 @@ DEFINE_UNREF_CLEANUP_FUNC(xkb_keymap); DEFINE_UNREF_CLEANUP_FUNC(xkb_state); #endif +#if 0 /* FIXME: needs keymap revamp */ static void setup_keymap(struct ei_device *kbd, const char *layout) { @@ -104,6 +105,7 @@ setup_keymap(struct ei_device *kbd, const char *layout) memfile_unref(f); #endif } +#endif static void handle_keymap(struct ei_event *event) @@ -158,7 +160,7 @@ int main(int argc, char **argv) PORTAL, } backend = SOCKET; bool verbose = false; - const char *layout = NULL; + _unused_ const char *layout = NULL; _cleanup_free_ char *busname = xstrdup("org.freedesktop.portal.Desktop"); @@ -276,39 +278,50 @@ int main(int argc, char **argv) } default_seat = ei_seat_ref(ei_event_get_seat(e)); colorprint("seat added: %s\n", ei_seat_get_name(default_seat)); - ptr = ei_device_new(default_seat); - ei_device_configure_capability(ptr, EI_DEVICE_CAP_POINTER); - - kbd = ei_device_new(default_seat); - ei_device_configure_capability(kbd, EI_DEVICE_CAP_KEYBOARD); - if (layout) - setup_keymap(kbd, layout); - - ei_device_add(ptr); - ei_device_add(kbd); + ei_seat_bind(default_seat); break; } case EI_EVENT_SEAT_REMOVED: + /* Don't need to close the devices, libei will + * give us the right events */ if (ei_event_get_seat(e) == default_seat) default_seat = ei_seat_unref(default_seat); break; case EI_EVENT_DEVICE_ADDED: - colorprint("our device was accepted, waiting for resume\n"); - handle_keymap(e); + { + struct ei_device *device = ei_event_get_device(e); + + if (ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)) { + colorprint("New pointer device: %s\n", ei_device_get_name(device)); + ptr = device; + } + if (ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD)) { + colorprint("New keyboard device: %s\n", ei_device_get_name(device)); + kbd = device; + /* FIXME */ + handle_keymap(e); + } + } break; case EI_EVENT_DEVICE_RESUMED: - colorprint("our device was resumed\n"); - if (ei_event_get_device(e) == ptr) + if (ei_event_get_device(e) == ptr) { + colorprint("Pointer device was resumed\n"); have_ptr = true; - if (ei_event_get_device(e) == kbd) + } + if (ei_event_get_device(e) == kbd) { + colorprint("Keybaord device was resumed\n"); have_kbd = true; + } break; case EI_EVENT_DEVICE_SUSPENDED: - colorprint("our device was suspended\n"); - if (ei_event_get_device(e) == ptr) + if (ei_event_get_device(e) == ptr) { + colorprint("Pointer device was resumed\n"); have_ptr = false; - if (ei_event_get_device(e) == kbd) + } + if (ei_event_get_device(e) == kbd) { + colorprint("Keyboard device was resumed\n"); have_kbd = false; + } break; case EI_EVENT_DEVICE_REMOVED: { diff --git a/tools/eis-demo-server-uinput.c b/tools/eis-demo-server-uinput.c index ea49c0c..42c51c3 100644 --- a/tools/eis-demo-server-uinput.c +++ b/tools/eis-demo-server-uinput.c @@ -37,6 +37,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct libevdev_uinput *, libevdev_uinput_destroy); #define _cleanup_libevdev_ _cleanup_(libevdev_freep) #define _cleanup_libevdev_uinput_ _cleanup_(libevdev_uinput_destroyp) DEFINE_UNREF_CLEANUP_FUNC(eis_seat); +DEFINE_UNREF_CLEANUP_FUNC(eis_device); static inline void _printf_(1, 2) @@ -61,10 +62,15 @@ struct uinput_context { }; static int -create_mouse(struct eis_demo_server *server, struct eis_device *device) +create_mouse(struct eis_demo_server *server, struct eis_seat *seat, + struct eis_device **device_return) { - struct eis_client *client = eis_device_get_client(device); + struct eis_client *client = eis_seat_get_client(seat); _cleanup_free_ char *devicename = xaprintf("%s pointer", eis_client_get_name(client)); + _unref_(eis_device) *device = eis_device_new(seat); + + eis_device_configure_name(device, devicename); + eis_device_configure_capability(device, EIS_DEVICE_CAP_POINTER); _cleanup_libevdev_ struct libevdev *dev = libevdev_new(); libevdev_set_name(dev, devicename); @@ -83,15 +89,21 @@ create_mouse(struct eis_demo_server *server, struct eis_device *device) if (err == 0) { colorprint("Pointer device is %s\n", libevdev_uinput_get_devnode(uinput)); eis_device_set_user_data(device, steal(&uinput)); + *device_return = steal(&device); } return err; } static int -create_keyboard(struct eis_demo_server *server, struct eis_device *device) +create_keyboard(struct eis_demo_server *server, struct eis_seat *seat, + struct eis_device **device_return) { - struct eis_client *client = eis_device_get_client(device); + struct eis_client *client = eis_seat_get_client(seat); _cleanup_free_ char *devicename = xaprintf("%s keyboard", eis_client_get_name(client)); + _unref_(eis_device) *device = eis_device_new(seat); + + eis_device_configure_name(device, devicename); + eis_device_configure_capability(device, EIS_DEVICE_CAP_KEYBOARD); _cleanup_libevdev_ struct libevdev *dev = libevdev_new(); libevdev_set_name(dev, devicename); @@ -103,11 +115,11 @@ create_keyboard(struct eis_demo_server *server, struct eis_device *device) if (err == 0) { colorprint("Keyboard device is %s\n", libevdev_uinput_get_devnode(uinput)); eis_device_set_user_data(device, steal(&uinput)); + *device_return = steal(&device); } return err; } - static int eis_demo_server_uinput_handle_event(struct eis_demo_server *server, struct eis_event *e) @@ -120,10 +132,10 @@ eis_demo_server_uinput_handle_event(struct eis_demo_server *server, colorprint("new client: %s, accepting. creating new seat 'default'\n", eis_client_get_name(client)); _unref_(eis_seat) *seat = eis_client_new_seat(client, "default"); - eis_seat_allow_capability(seat, EIS_DEVICE_CAP_POINTER); - eis_seat_allow_capability(seat, EIS_DEVICE_CAP_POINTER_ABSOLUTE); - eis_seat_allow_capability(seat, EIS_DEVICE_CAP_KEYBOARD); - eis_seat_allow_capability(seat, EIS_DEVICE_CAP_TOUCH); + eis_seat_configure_capability(seat, EIS_DEVICE_CAP_POINTER); + eis_seat_configure_capability(seat, EIS_DEVICE_CAP_POINTER_ABSOLUTE); + eis_seat_configure_capability(seat, EIS_DEVICE_CAP_KEYBOARD); + eis_seat_configure_capability(seat, EIS_DEVICE_CAP_TOUCH); eis_seat_add(seat); break; } @@ -134,46 +146,46 @@ eis_demo_server_uinput_handle_event(struct eis_demo_server *server, eis_client_disconnect(client); break; } - case EIS_EVENT_DEVICE_ADDED: + case EIS_EVENT_SEAT_BIND: { - struct eis_device *device = eis_event_get_device(e); - colorprint("new device, caps:%s%s%s%s\n", - eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER) ? " ptr" : "", - eis_device_has_capability(device, EIS_DEVICE_CAP_KEYBOARD) ? " kbd" : "", - eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE) ? " abs" : "", - eis_device_has_capability(device, EIS_DEVICE_CAP_TOUCH) ? " touch" : ""); + struct eis_seat *seat = eis_event_get_seat(e); - if (eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER)) { - eis_device_allow_capability(device, EIS_DEVICE_CAP_POINTER); - int rc = create_mouse(server, device); + if (eis_event_seat_has_capability(e, EIS_DEVICE_CAP_POINTER)) { + struct eis_device *device = NULL; + int rc = create_mouse(server, seat, &device); if (rc != 0) { colorprint("Failed to create device: %s\n", strerror(-rc)); return rc; } - eis_device_connect(device); + eis_device_add(device); eis_device_resume(device); - } else if (eis_device_has_capability(device, EIS_DEVICE_CAP_KEYBOARD)) { - eis_device_allow_capability(device, EIS_DEVICE_CAP_KEYBOARD); - int rc = create_keyboard(server, device); + } + if (eis_event_seat_has_capability(e, EIS_DEVICE_CAP_KEYBOARD)) { + struct eis_device *device = NULL; + int rc = create_keyboard(server, seat, &device); if (rc != 0) { colorprint("Failed to create device: %s\n", strerror(-rc)); return rc; } - eis_device_connect(device); + eis_device_add(device); eis_device_resume(device); - } else { - colorprint("No supported capabilities found\n"); - eis_device_disconnect(device); + } + /* Note: our device has a dangling ref here. It's a + * demo-server so we can just ignore that */ } break; - } - case EIS_EVENT_DEVICE_REMOVED: + case EIS_EVENT_SEAT_UNBIND: + /* FIXME */ + break; + case EIS_EVENT_DEVICE_CLOSED: { struct eis_device *device = eis_event_get_device(e); - colorprint("device removed\n"); + colorprint("device closed\n"); struct libevdev_uinput *uinput = eis_device_get_user_data(device); if (uinput) libevdev_uinput_destroy(uinput); + eis_device_remove(device); + eis_device_unref(device); /* because we know we have a dangling ref */ break; } case EIS_EVENT_POINTER_MOTION: diff --git a/tools/eis-demo-server.c b/tools/eis-demo-server.c index c399bb3..8987051 100644 --- a/tools/eis-demo-server.c +++ b/tools/eis-demo-server.c @@ -203,10 +203,10 @@ eis_demo_server_printf_handle_event(struct eis_demo_server *server, eis_client_connect(client); colorprint("accepting client, creating new seat 'default'\n"); _unref_(eis_seat) *seat = eis_client_new_seat(client, "default"); - eis_seat_allow_capability(seat, EIS_DEVICE_CAP_POINTER); - eis_seat_allow_capability(seat, EIS_DEVICE_CAP_POINTER_ABSOLUTE); - eis_seat_allow_capability(seat, EIS_DEVICE_CAP_KEYBOARD); - eis_seat_allow_capability(seat, EIS_DEVICE_CAP_TOUCH); + eis_seat_configure_capability(seat, EIS_DEVICE_CAP_POINTER); + eis_seat_configure_capability(seat, EIS_DEVICE_CAP_POINTER_ABSOLUTE); + eis_seat_configure_capability(seat, EIS_DEVICE_CAP_KEYBOARD); + eis_seat_configure_capability(seat, EIS_DEVICE_CAP_TOUCH); eis_seat_add(seat); break; } @@ -217,31 +217,48 @@ eis_demo_server_printf_handle_event(struct eis_demo_server *server, eis_client_disconnect(client); break; } - case EIS_EVENT_DEVICE_ADDED: + case EIS_EVENT_SEAT_BIND: { - struct eis_device *device = eis_event_get_device(e); - colorprint("new device, caps:%s%s%s%s\n", - eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER) ? " ptr" : "", - eis_device_has_capability(device, EIS_DEVICE_CAP_KEYBOARD) ? " kbd" : "", - eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE) ? " abs" : "", - eis_device_has_capability(device, EIS_DEVICE_CAP_TOUCH) ? " touch" : ""); + struct eis_client *client = eis_event_get_client(e); + struct eis_seat *seat = eis_event_get_seat(e); + struct eis_device *ptr = eis_device_new(seat); - eis_device_allow_capability(device, EIS_DEVICE_CAP_POINTER); - eis_device_allow_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE); - eis_device_allow_capability(device, EIS_DEVICE_CAP_KEYBOARD); - eis_device_allow_capability(device, EIS_DEVICE_CAP_TOUCH); + eis_device_configure_name(ptr, "test pointer"); + eis_device_configure_capability(ptr, EIS_DEVICE_CAP_POINTER); + colorprint("Creating pointer device %s for %s\n", eis_device_get_name(ptr), + eis_client_get_name(client)); + eis_device_add(ptr); + eis_device_resume(ptr); + /* ptr ref is dangling */ - setup_keymap(server, device); - /* insert sophisticated device checks here */ - eis_device_connect(device); - eis_device_resume(device); - break; + + struct eis_device *kbd = eis_device_new(seat); + eis_device_configure_name(kbd, "test keyboard"); + /* FIXME: review keymaps */ + setup_keymap(server, kbd); + eis_device_configure_capability(ptr, EIS_DEVICE_CAP_KEYBOARD); + colorprint("Creating keyboard device %s for %s\n", eis_device_get_name(kbd), + eis_client_get_name(client)); + eis_device_add(kbd); + eis_device_resume(kbd); + /* kbd ref is dangling */ } - case EIS_EVENT_DEVICE_REMOVED: + break; + case EIS_EVENT_SEAT_UNBIND: { - colorprint("device removed\n"); - break; + struct eis_seat *seat = eis_event_get_seat(e); + /* FIXME: remove all devices? we need a devices_foreach + * function on the eis seat */ + eis_seat_remove(seat); } + break; + case EIS_EVENT_DEVICE_CLOSED: + { + struct eis_device *device = eis_event_get_device(e); + eis_device_remove(device); + eis_device_unref(device); /* because our devices have a dangling */ + } + break; case EIS_EVENT_POINTER_MOTION: { colorprint("motion by %.2f/%.2f\n",