ei: make ei_disconnect() public

Previously the only way to disconnect from the EIS implementation was
to call ei_unref() and release all resources. This makes it more
difficult for shared cleanup code - clients already have code in place
to deal with DEVICE_REMOVED, SEAT_REMOVED, etc. but that code has to
be triggered manually before ei_unref() is called.

OTOH where the server disconnects us, libei already unwound the state
so we would artificially generate these removed events, allowing the
client to clean up.

Make life easier for client by allowing them to ei_disconnect() and
get the benefits of our state unwinding. ei_disconnect() was already
used internally to disconnect on any error so this merely makes this
function public.

Closes #67

Part-of: <https://gitlab.freedesktop.org/libinput/libei/-/merge_requests/311>
This commit is contained in:
Peter Hutterer 2024-11-28 15:38:06 +10:00 committed by Marge Bot
parent b33317cda0
commit 62ae6f5edf
4 changed files with 71 additions and 12 deletions

View file

@ -131,9 +131,6 @@ ei_get_interface(struct ei *ei);
int
ei_set_socket(struct ei *ei, int fd);
void
ei_disconnect(struct ei *ei);
struct ei *
ei_get_context(struct ei *ei);

View file

@ -580,7 +580,7 @@ ei_queue_touch_up_event(struct ei_device *device, uint32_t touchid)
queue_event(ei_device_get_context(device), e);
}
void
_public_ void
ei_disconnect(struct ei *ei)
{
if (ei->state == EI_STATE_DISCONNECTED ||

View file

@ -849,6 +849,24 @@ ei_peek_event(struct ei *ei);
uint64_t
ei_now(struct ei *ei);
/**
* Disconnect the current ei context from the EIS implementation.
*
* After a call to ei_disconnect(), ei_get_event() will return
* events to remove resources (e.g. seats and devices) as if they
* had been removed by the EIS implementation. The last event
* returned by ei_get_event() is @ref EI_EVENT_DISCONNECT after
* which the context should be considered inert and any
* remaining resources released with ei_unref().
*
* This does not free the resources associated with the ei context, use
* ei_unref().
*
* @since 1.4
*/
void
ei_disconnect(struct ei *ei);
/**
* @ingroup libei-seat
*

View file

@ -67,7 +67,7 @@ MUNIT_TEST(test_ei_disconnect_immediately)
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_self_immediately)
MUNIT_TEST(test_ei_unref_self_immediately)
{
_unref_(peck) *peck = peck_new();
@ -93,6 +93,30 @@ MUNIT_TEST(test_ei_disconnect_self_immediately)
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_self_immediately)
{
_unref_(peck) *peck = peck_new();
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
peck_dispatch_until_stable(peck);
/* Disconnect before server processed CONNECT */
with_client(peck) {
ei_disconnect(ei);
}
peck_dispatch_until_stable(peck);
/* Expect the client to get a disconnect event */
with_server(peck) {
_unref_(eis_event) *connect =
peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT);
_unref_(eis_event) *disconnect =
peck_eis_next_event(eis, EIS_EVENT_CLIENT_DISCONNECT);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_after_connect)
{
@ -130,7 +154,7 @@ MUNIT_TEST(test_ei_disconnect_after_connect)
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_self_after_connect)
MUNIT_TEST(test_ei_unref_self_after_connect)
{
_unref_(peck) *peck = peck_new();
@ -154,6 +178,29 @@ MUNIT_TEST(test_ei_disconnect_self_after_connect)
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_self_after_connect)
{
_unref_(peck) *peck = peck_new();
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
peck_dispatch_until_stable(peck);
with_client(peck) {
ei_disconnect(ei);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *connect =
peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT);
_unref_(eis_event) *disconnect =
peck_eis_next_event(eis, EIS_EVENT_CLIENT_DISCONNECT);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_after_seat)
{
_unref_(peck) *peck = peck_new();
@ -203,9 +250,8 @@ MUNIT_TEST(test_ei_disconnect_self_after_seat)
peck_ei_next_event(ei, EI_EVENT_CONNECT);
_unref_(ei_event) *seat =
peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED);
peck_drop_ei(peck);
/* Disconnect from client */
ei_unref(ei);
ei_disconnect(ei);
/* There is no way to disconnect from the server without
* destroying the context, so we don't care about the actual
@ -274,8 +320,7 @@ MUNIT_TEST(test_ei_disconnect_self_after_bind_before_received)
struct ei_seat *seat = ei_event_get_seat(event);
ei_seat_bind_capabilities(seat, EI_DEVICE_CAP_POINTER, NULL);
/* Disconnect before the server can process the bind event */
peck_drop_ei(peck);
ei_unref(ei);
ei_disconnect(ei);
}
peck_dispatch_eis(peck);
@ -354,8 +399,7 @@ MUNIT_TEST(test_ei_disconnect_self_after_bind_after_received)
peck_dispatch_eis(peck);
with_client(peck) {
peck_drop_ei(peck);
ei_unref(ei);
ei_disconnect(ei);
}
peck_dispatch_eis(peck);