From a4dde7c35f1ae64577f5d2547f4668dac61475a4 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 29 Apr 2022 09:30:28 +1000 Subject: [PATCH] Filter empty frame events We only need frame events after device events (pointer, touch, keyboard). In some cases, the library prevents an event from being written to the wire, e.g. if the coordinates are out of region, but the client will still call ei_device_frame() for that now-filtered event. Keep a boolean to remember if we have sent something that requires a frame event and filter accordingly. Note that this currently filters the *sender* side only, not the receiver side. A sender that gets an empty frame event onto the wire will still get that into the other side. This also doesn't handle the flushing of frame events before other events, ideally we should enforce a frame event before e.g. stop emulating. --- src/libei-private.h | 2 ++ src/libei.c | 27 +++++++++++++++++++++++++++ src/libeis-device.c | 30 ++++++++++++++++++++++++++++-- src/libeis-private.h | 2 ++ test/test-ei-device.c | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 2 deletions(-) diff --git a/src/libei-private.h b/src/libei-private.h index 4ad4aa1..bc404b0 100644 --- a/src/libei-private.h +++ b/src/libei-private.h @@ -129,6 +129,8 @@ struct ei_device { char *name; enum ei_device_type type; + bool send_frame_event; + uint32_t width, height; struct list regions; diff --git a/src/libei.c b/src/libei.c index 7892c78..a1a11b8 100644 --- a/src/libei.c +++ b/src/libei.c @@ -847,6 +847,11 @@ ei_send_frame(struct ei_device *device) if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; + if (!device->send_frame_event) + return 0; + + device->send_frame_event = false; + int rc = ei->requests->frame(device); if (rc) ei_disconnect(ei); @@ -861,6 +866,8 @@ ei_send_pointer_rel(struct ei_device *device, double x, double y) if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; + device->send_frame_event = true; + int rc = ei->requests->rel(device, x, y); if (rc) ei_disconnect(ei); @@ -875,6 +882,8 @@ ei_send_pointer_abs(struct ei_device *device, double x, double y) if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; + device->send_frame_event = true; + int rc = ei->requests->abs(device, x, y); if (rc) ei_disconnect(ei); @@ -889,6 +898,8 @@ ei_send_pointer_button(struct ei_device *device, uint32_t button, bool is_press) if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; + device->send_frame_event = true; + int rc = ei->requests->button(device, button, is_press); if (rc) ei_disconnect(ei); @@ -902,6 +913,8 @@ int ei_send_pointer_scroll(struct ei_device *device, double x, double y) if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; + device->send_frame_event = true; + int rc = ei->requests->scroll(device, x, y); if (rc) ei_disconnect(ei); @@ -915,6 +928,8 @@ int ei_send_pointer_scroll_stop(struct ei_device *device, double x, double y) if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; + device->send_frame_event = true; + int rc = ei->requests->scroll_stop(device, x, y); if (rc) ei_disconnect(ei); @@ -928,6 +943,8 @@ int ei_send_pointer_scroll_cancel(struct ei_device *device, double x, double y) if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; + device->send_frame_event = true; + int rc = ei->requests->scroll_cancel(device, x, y); if (rc) ei_disconnect(ei); @@ -942,6 +959,8 @@ int ei_send_pointer_scroll_discrete(struct ei_device *device, int32_t x, int32_t if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; + device->send_frame_event = true; + int rc = ei->requests->scroll_discrete(device, x, y); if (rc) ei_disconnect(ei); @@ -956,6 +975,8 @@ ei_send_keyboard_key(struct ei_device *device, uint32_t key, bool is_press) if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; + device->send_frame_event = true; + int rc = ei->requests->key(device, key, is_press); if (rc) ei_disconnect(ei); @@ -971,6 +992,8 @@ ei_send_touch_down(struct ei_device *device, uint32_t tid, if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; + device->send_frame_event = true; + int rc = ei->requests->touch_down(device, tid, x, y); if (rc) ei_disconnect(ei); @@ -986,6 +1009,8 @@ ei_send_touch_motion(struct ei_device *device, uint32_t tid, if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; + device->send_frame_event = true; + int rc = ei->requests->touch_motion(device, tid, x, y); if (rc) ei_disconnect(ei); @@ -1000,6 +1025,8 @@ ei_send_touch_up(struct ei_device *device, uint32_t tid) if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; + device->send_frame_event = true; + int rc = ei->requests->touch_up(device, tid); if (rc) ei_disconnect(ei); diff --git a/src/libeis-device.c b/src/libeis-device.c index cf10ba5..2960946 100644 --- a/src/libeis-device.c +++ b/src/libeis-device.c @@ -343,6 +343,8 @@ eis_device_pointer_motion(struct eis_device *device, if (device->state != EIS_DEVICE_STATE_EMULATING) return; + device->send_frame_event = true; + handle_request(device, rel, x, y); } @@ -366,6 +368,8 @@ eis_device_pointer_motion_absolute(struct eis_device *device, } } + device->send_frame_event = true; + handle_request(device, abs, x, y); } @@ -390,6 +394,8 @@ eis_device_pointer_button(struct eis_device *device, return; } + device->send_frame_event = true; + handle_request(device, button, button, is_press); } @@ -421,6 +427,8 @@ eis_device_pointer_scroll(struct eis_device *device, eis_device_resume_scrolling(device, x, y); + device->send_frame_event = true; + handle_request(device, scroll, x, y); } @@ -446,8 +454,10 @@ eis_device_pointer_scroll_stop(struct eis_device *device, bool x, bool y) else y = false; - if (x || y) + if (x || y) { + device->send_frame_event = true; handle_request(device, scroll_stop, x, y, false); + } } _public_ void @@ -476,8 +486,10 @@ eis_device_pointer_scroll_cancel(struct eis_device *device, bool x, bool y) y = false; } - if (x || y) + if (x || y) { + device->send_frame_event = true; handle_request(device, scroll_stop, x, y, true); + } } _public_ void @@ -495,6 +507,8 @@ eis_device_pointer_scroll_discrete(struct eis_device *device, eis_device_resume_scrolling(device, x, y); + device->send_frame_event = true; + handle_request(device, scroll_discrete, x, y); } @@ -511,6 +525,8 @@ eis_device_keyboard_key(struct eis_device *device, if (device->state != EIS_DEVICE_STATE_EMULATING) return; + device->send_frame_event = true; + handle_request(device, key, key, is_press); } @@ -578,6 +594,7 @@ eis_touch_down(struct eis_touch *touch, double x, double y) } touch->state = TOUCH_IS_DOWN; + device->send_frame_event = true; handle_request(device, touch_down, touch->tracking_id, x, y); } @@ -599,6 +616,8 @@ eis_touch_motion(struct eis_touch *touch, double x, double y) } } + device->send_frame_event = true; + handle_request(device, touch_motion, touch->tracking_id, x, y); } @@ -614,6 +633,7 @@ eis_touch_up(struct eis_touch *touch) } touch->state = TOUCH_IS_UP; + device->send_frame_event = true; handle_request(device, touch_up, touch->tracking_id); } @@ -624,6 +644,12 @@ eis_device_frame(struct eis_device *device) if (device->state != EIS_DEVICE_STATE_EMULATING) return; + if (!device->send_frame_event) + return; + + device->send_frame_event = false; + + handle_request_noargs(device, frame); } diff --git a/src/libeis-private.h b/src/libeis-private.h index 5e38cb9..94ec6ed 100644 --- a/src/libeis-private.h +++ b/src/libeis-private.h @@ -142,6 +142,8 @@ struct eis_device { struct eis_keymap *keymap; + bool send_frame_event; + struct { bool x_is_stopped, y_is_stopped; bool x_is_cancelled, y_is_cancelled; diff --git a/test/test-ei-device.c b/test/test-ei-device.c index 4c47d9d..46ef8fc 100644 --- a/test/test-ei-device.c +++ b/test/test-ei-device.c @@ -1148,6 +1148,38 @@ MUNIT_TEST(test_ei_keyboard_modifiers) return MUNIT_OK; } +MUNIT_TEST(test_ei_no_empty_frames) +{ + _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_frame(device); /* Expect to be filtered */ + ei_device_keyboard_key(device, KEY_Q, true); + ei_device_frame(device); + ei_device_frame(device); /* Expect to be filtered */ + } + + 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); + 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);