diff --git a/src/libei-event.c b/src/libei-event.c index 2919987..9de45de 100644 --- a/src/libei-event.c +++ b/src/libei-event.c @@ -50,6 +50,7 @@ ei_event_type_to_string(enum ei_event_type type) CASE_RETURN_STRING(EI_EVENT_DEVICE_RESUMED); CASE_RETURN_STRING(EI_EVENT_KEYBOARD_MODIFIERS); CASE_RETURN_STRING(EI_EVENT_PONG); + CASE_RETURN_STRING(EI_EVENT_SYNC); CASE_RETURN_STRING(EI_EVENT_FRAME); CASE_RETURN_STRING(EI_EVENT_DEVICE_START_EMULATING); CASE_RETURN_STRING(EI_EVENT_DEVICE_STOP_EMULATING); @@ -100,6 +101,9 @@ ei_event_destroy(struct ei_event *event) case EI_EVENT_PONG: ei_ping_unref(event->pong.ping); break; + case EI_EVENT_SYNC: + ei_pingpong_unref(event->sync.pingpong); + break; } ei_device_unref(event->device); ei_seat_unref(event->seat); diff --git a/src/libei-event.h b/src/libei-event.h index cc2db03..bd6f8f4 100644 --- a/src/libei-event.h +++ b/src/libei-event.h @@ -72,6 +72,9 @@ struct ei_event { struct { struct ei_ping *ping; } pong; + struct { + struct ei_pingpong *pingpong; + } sync; }; }; diff --git a/src/libei-private.h b/src/libei-private.h index b11ed0f..af83a93 100644 --- a/src/libei-private.h +++ b/src/libei-private.h @@ -171,6 +171,9 @@ ei_queue_disconnect_event(struct ei *ei); void ei_queue_pong_event(struct ei *ei, struct ei_ping *ping); +void +ei_queue_sync_event(struct ei *ei, struct ei_pingpong *ping); + void ei_queue_device_removed_event(struct ei_device *device); diff --git a/src/libei.c b/src/libei.c index 7a7f438..00ce208 100644 --- a/src/libei.c +++ b/src/libei.c @@ -336,6 +336,16 @@ ei_queue_pong_event(struct ei *ei, struct ei_ping *ping) queue_event(ei, e); } +void +ei_queue_sync_event(struct ei *ei, struct ei_pingpong *ping) +{ + struct ei_event *e = ei_event_new(ei); + e->type = EI_EVENT_SYNC; + e->sync.pingpong = ei_pingpong_ref(ping); + + queue_event(ei, e); +} + void ei_queue_seat_added_event(struct ei_seat *seat) { @@ -683,6 +693,16 @@ ei_get_event(struct ei *ei) struct ei_event *e = list_first_entry(&ei->event_queue, e, link); list_remove(&e->link); + if (e->type == EI_EVENT_SYNC) { + _unref_(ei_pingpong) *pp = steal(&e->sync.pingpong); + log_debug(ei_event_get_context(e), + "object %#" PRIx64 ": ping pong done", + ei_pingpong_get_id(pp)); + + if (ei->state < EI_STATE_DISCONNECTED) + ei_pingpong_request_done(pp, 0); + } + return e; } @@ -764,8 +784,7 @@ handle_msg_ping(struct ei_connection *connection, object_id_t id, uint32_t vers DISCONNECT_IF_INVALID_VERSION(ei, ei_pingpong, id, version); _unref_(ei_pingpong) *pingpong = ei_pingpong_new_for_id(ei, id, version); - - ei_pingpong_request_done(pingpong, 0); + ei_queue_sync_event(ei_connection_get_context(connection), pingpong); return NULL; } diff --git a/src/libei.h b/src/libei.h index 447a709..a532143 100644 --- a/src/libei.h +++ b/src/libei.h @@ -431,6 +431,17 @@ enum ei_event_type { */ EI_EVENT_PONG = 90, + /** + * This event represents a synchronization request (ping) from the EIS + * implementation. The corresponding reply (pong) will be sent when + * it is unref'd. It has no other API. + * + * The caller must ensure that any state changes triggered by messages + * received prior to this event have been resolved and communicated to the + * EIS implementation prior to calling ei_event_unref(). + */ + EI_EVENT_SYNC, + /** * "Hardware" frame event. This event **must** be sent by the server * and notifies the client that the previous set of events belong to diff --git a/test/eierpecken.c b/test/eierpecken.c index 40b36b3..f82accc 100644 --- a/test/eierpecken.c +++ b/test/eierpecken.c @@ -502,6 +502,7 @@ new_context(enum peck_ei_mode ei_mode) peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOSEAT); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOSTART); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_FRAME); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_SYNC); peck_ei_enable_fatal_bug(peck); peck_eis_enable_fatal_bug(peck); @@ -655,6 +656,7 @@ peck_enable_ei_behavior(struct peck *peck, enum peck_ei_behavior behavior) case PECK_EI_BEHAVIOR_HANDLE_ADDED_BUTTON: case PECK_EI_BEHAVIOR_HANDLE_ADDED_SCROLL: case PECK_EI_BEHAVIOR_HANDLE_FRAME: + case PECK_EI_BEHAVIOR_HANDLE_SYNC: flag_set(peck->ei_behavior, behavior); break; case PECK_EI_BEHAVIOR_HANDLE_RESUMED: @@ -1076,6 +1078,10 @@ _peck_dispatch_ei(struct peck *peck, int lineno) break; case EI_EVENT_PONG: break; + case EI_EVENT_SYNC: + if (flag_is_set(peck->ei_behavior, PECK_EI_BEHAVIOR_HANDLE_SYNC)) + process_event = tristate_yes; + break; case EI_EVENT_FRAME: /* Ensure we only expect frames when we expect them */ munit_assert_true(need_frame); @@ -1247,6 +1253,12 @@ _peck_assert_no_ei_events(struct ei *ei, int lineno) continue; } + if (peck && flag_is_set(peck->ei_behavior, PECK_EI_BEHAVIOR_HANDLE_SYNC) && + ei_event_get_type(e) == EI_EVENT_SYNC) { + log_debug(peck, "Skipping over sync event\n"); + continue; + } + munit_errorf("Expected empty event queue, have: %s, line %d\n", peck_ei_event_name(e), lineno); } @@ -1295,6 +1307,14 @@ _peck_ei_next_event(struct ei *ei, enum ei_event_type type, int lineno) } } + if (flag_is_set(peck->ei_behavior, PECK_EI_BEHAVIOR_HANDLE_SYNC)) { + while (event && ei_event_get_type(event) == EI_EVENT_SYNC) { + ei_event_unref(event); + log_debug(peck, "Skipping over sync event\n"); + event = ei_get_event(ei); + } + } + if (!event) munit_errorf("Expected ei event type %s, got none, line %d\n", peck_ei_event_type_name(type), @@ -1406,6 +1426,7 @@ peck_ei_event_type_name(enum ei_event_type type) CASE_STRING(DEVICE_RESUMED); CASE_STRING(KEYBOARD_MODIFIERS); CASE_STRING(PONG); + CASE_STRING(SYNC); CASE_STRING(FRAME); CASE_STRING(DEVICE_START_EMULATING); CASE_STRING(DEVICE_STOP_EMULATING); diff --git a/test/eierpecken.h b/test/eierpecken.h index 9eaa89c..a629b01 100644 --- a/test/eierpecken.h +++ b/test/eierpecken.h @@ -139,6 +139,10 @@ enum peck_ei_behavior { * Handle frame events. This behavior is enabled by default. */ PECK_EI_BEHAVIOR_HANDLE_FRAME, + /** + * Handle sync events. This behavior is enabled by default. + */ + PECK_EI_BEHAVIOR_HANDLE_SYNC, }; struct peck; diff --git a/test/test-ei-device.c b/test/test-ei-device.c index 6fad482..84cc5d6 100644 --- a/test/test-ei-device.c +++ b/test/test-ei-device.c @@ -295,6 +295,7 @@ MUNIT_TEST(test_ei_device_close) peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_DEVICES); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); peck_dispatch_until_stable(peck); @@ -1873,6 +1874,7 @@ MUNIT_TEST(test_passive_ei_device_start_stop_emulating) peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_RESUME_DEVICE); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOSEAT); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED_POINTER); @@ -1914,6 +1916,7 @@ MUNIT_TEST(test_passive_ei_device_stop_emulating_when_removing) peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_RESUME_DEVICE); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOSEAT); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED_POINTER); @@ -2901,6 +2904,7 @@ MUNIT_TEST(test_passive_ei_frame_timestamp) peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_RESUME_DEVICE); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); peck_dispatch_until_stable(peck); @@ -2960,6 +2964,7 @@ MUNIT_TEST(test_passive_ei_flush_frame) peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_RESUME_DEVICE); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); peck_dispatch_until_stable(peck); diff --git a/test/test-ei-seat.c b/test/test-ei-seat.c index 402d891..7eeba56 100644 --- a/test/test-ei-seat.c +++ b/test/test-ei-seat.c @@ -38,6 +38,7 @@ MUNIT_TEST(test_ei_seat_bind_unbind) peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_dispatch_until_stable(peck); @@ -95,6 +96,7 @@ MUNIT_TEST(test_ei_seat_bind_unbind_noref) peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_dispatch_until_stable(peck); @@ -144,6 +146,7 @@ MUNIT_TEST(test_ei_seat_bind_unbind_immediately) peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_dispatch_until_stable(peck); diff --git a/test/test-ei.c b/test/test-ei.c index 2534b02..93270f0 100644 --- a/test/test-ei.c +++ b/test/test-ei.c @@ -126,6 +126,7 @@ MUNIT_TEST(test_ei_disconnect_after_connect) _unref_(eis_client) *client = NULL; peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_SYNC); peck_dispatch_until_stable(peck); @@ -212,6 +213,7 @@ MUNIT_TEST(test_ei_disconnect_after_seat) 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_HANDLE_SYNC); peck_dispatch_until_stable(peck); @@ -246,6 +248,7 @@ MUNIT_TEST(test_ei_disconnect_self_after_seat) 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_HANDLE_SYNC); peck_dispatch_until_stable(peck); @@ -283,6 +286,7 @@ MUNIT_TEST(test_ei_disconnect_after_bind_before_received) 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_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_dispatch_until_stable(peck); @@ -317,6 +321,7 @@ MUNIT_TEST(test_ei_disconnect_self_after_bind_before_received) 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_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_dispatch_until_stable(peck); @@ -355,6 +360,7 @@ MUNIT_TEST(test_ei_disconnect_after_bind_after_received) 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_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_dispatch_until_stable(peck); @@ -391,6 +397,7 @@ MUNIT_TEST(test_ei_disconnect_self_after_bind_after_received) 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_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_dispatch_until_stable(peck); @@ -432,6 +439,7 @@ MUNIT_TEST(test_ei_disconnect_after_unbind_before_received) 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_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_dispatch_until_stable(peck); @@ -477,6 +485,7 @@ MUNIT_TEST(test_ei_disconnect_after_unbind_after_received) 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_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_dispatch_until_stable(peck); @@ -520,6 +529,7 @@ MUNIT_TEST(test_client_is_sender) peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_dispatch_until_stable(peck); @@ -539,6 +549,7 @@ MUNIT_TEST(test_client_is_receiver) peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_dispatch_until_stable(peck); @@ -922,6 +933,7 @@ MUNIT_TEST(test_ei_ping_within_frame) peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_RESUME_DEVICE); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOSTART); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED); diff --git a/test/test-eis.c b/test/test-eis.c index f6ea868..69dd7f3 100644 --- a/test/test-eis.c +++ b/test/test-eis.c @@ -53,6 +53,7 @@ MUNIT_TEST(eistest_name) peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE); peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_SYNC); /* The name is set by peck_new() and immutable after the * backend was set, which peck_new() does for us as well. @@ -85,6 +86,7 @@ MUNIT_TEST(eistest_cliend_bind_all_caps) 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_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_dispatch_until_stable(peck); @@ -122,6 +124,7 @@ MUNIT_TEST(eistest_cliend_bind_some_caps) 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_HANDLE_SYNC); peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT); peck_dispatch_until_stable(peck); diff --git a/tools/ei-debug-events.c b/tools/ei-debug-events.c index a8b67c9..02bfeb8 100644 --- a/tools/ei-debug-events.c +++ b/tools/ei-debug-events.c @@ -455,6 +455,8 @@ int main(int argc, char **argv) case EI_EVENT_PONG: print_pong_event(e); break; + case EI_EVENT_SYNC: + break; } } }