diff --git a/src/libei-device.c b/src/libei-device.c index c92e3f6..226cacf 100644 --- a/src/libei-device.c +++ b/src/libei-device.c @@ -348,6 +348,17 @@ ei_device_has_capability(struct ei_device *device, return false; } +static void +_flush_frame(struct ei_device *device, const char *func) +{ + if (device->send_frame_event) { + log_bug_client(ei_device_get_context(device), + "%s: missing call to ei_device_frame()\n", func); + ei_device_frame(device); + } +} +#define ei_device_flush_frame(d_) _flush_frame(d_, __func__) + _public_ void ei_device_start_emulating(struct ei_device *device) { @@ -364,6 +375,7 @@ ei_device_stop_emulating(struct ei_device *device) if (device->state != EI_DEVICE_STATE_EMULATING) return; + ei_device_flush_frame(device); device->state = EI_DEVICE_STATE_RESUMED; ei_send_stop_emulating(device); } diff --git a/src/libeis-device.c b/src/libeis-device.c index 6558c40..3e9be58 100644 --- a/src/libeis-device.c +++ b/src/libeis-device.c @@ -308,6 +308,17 @@ eis_device_has_capability(struct eis_device *device, eis->requests->func_(device_, device->id, __VA_ARGS__); \ } +static void +_flush_frame(struct eis_device *device, const char *func) +{ + if (device->send_frame_event) { + log_bug_client(eis_device_get_context(device), + "%s: missing call to eis_device_frame()\n", func); + eis_device_frame(device); + } +} +#define eis_device_flush_frame(d_) _flush_frame(d_, __func__) + _public_ void eis_device_start_emulating(struct eis_device *device) { @@ -325,6 +336,8 @@ eis_device_stop_emulating(struct eis_device *device) if (device->state != EIS_DEVICE_STATE_EMULATING) return; + eis_device_flush_frame(device); + device->state = EIS_DEVICE_STATE_RESUMED; handle_request_noargs(device, stop_emulating); diff --git a/test/test-ei-device.c b/test/test-ei-device.c index c83fcd2..6b4acf3 100644 --- a/test/test-ei-device.c +++ b/test/test-ei-device.c @@ -1185,6 +1185,39 @@ MUNIT_TEST(test_ei_no_empty_frames) return MUNIT_OK; } +MUNIT_TEST(test_ei_flush_frame) +{ + _unref_(peck) *peck = peck_new(); + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); + 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_AUTODEVICES); + peck_dispatch_until_stable(peck); + + with_client(peck) { + struct ei_device *device = peck_ei_get_default_keyboard(peck); + ei_device_keyboard_key(device, KEY_Q, true); + /* Missing call to ei_device_frame() */ + ei_device_stop_emulating(device); + } + + peck_dispatch_until_stable(peck); + + with_server(peck) { + _unref_(eis_event) *kbd = + peck_eis_next_event(eis, EIS_EVENT_KEYBOARD_KEY); + _unref_(eis_event) *frame = + peck_eis_next_event(eis, EIS_EVENT_FRAME); + _unref_(eis_event) *stop = + peck_eis_next_event(eis, EIS_EVENT_DEVICE_STOP_EMULATING); + peck_assert_no_eis_events(eis); + } + + return MUNIT_OK; +} + MUNIT_TEST(test_passive_ei_device_start_stop_emulating) { _unref_(peck) *peck = peck_new_context(PECK_EI_RECEIVER); @@ -1977,3 +2010,41 @@ MUNIT_TEST(test_passive_ei_device_multitouch) return MUNIT_OK; } + +MUNIT_TEST(test_passive_ei_flush_frame) +{ + _unref_(peck) *peck = peck_new_context(PECK_EI_RECEIVER); + + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE); + peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); + 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_AUTOCONNECT); + peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES); + peck_dispatch_until_stable(peck); + + with_server(peck) { + struct eis_device *device = peck_eis_get_default_keyboard(peck); + eis_device_start_emulating(device); + eis_device_keyboard_key(device, KEY_Q, true); + /* Missing call to ei_device_frame() */ + eis_device_stop_emulating(device); + } + + peck_dispatch_until_stable(peck); + + with_client(peck) { + _unref_(ei_event) *start = + peck_ei_next_event(ei, EI_EVENT_DEVICE_START_EMULATING); + _unref_(ei_event) *kbd = + peck_ei_next_event(ei, EI_EVENT_KEYBOARD_KEY); + _unref_(ei_event) *frame = + peck_ei_next_event(ei, EI_EVENT_FRAME); + _unref_(ei_event) *stop = + peck_ei_next_event(ei, EI_EVENT_DEVICE_STOP_EMULATING); + peck_assert_no_ei_events(ei); + } + + return MUNIT_OK; +}