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.
This commit is contained in:
Peter Hutterer 2022-04-29 09:30:28 +10:00
parent 35aca1a387
commit a4dde7c35f
5 changed files with 91 additions and 2 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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);
}

View file

@ -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;

View file

@ -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);