ei: remove some indirection from device events

Now that we only have one nice hook as entry point for those events,
let's move (and harden) the code there.
This commit is contained in:
Peter Hutterer 2023-02-20 17:10:26 +10:00
parent 1846223991
commit d698ed2f75
2 changed files with 162 additions and 285 deletions

View file

@ -125,6 +125,19 @@ ei_device_get_context(struct ei_device *device)
return ei_seat_get_context(ei_device_get_seat(device));
}
static inline bool
ei_device_in_region(struct ei_device *device, double x, double y)
{
struct ei_region *r;
list_for_each(r, &device->regions, link) {
if (ei_region_contains(r, x, y))
return true;
}
return false;
}
static struct brei_result *
handle_msg_destroy(struct ei_device *device)
{
@ -261,7 +274,6 @@ handle_msg_paused(struct ei_device *device)
} \
} while(0)
static struct brei_result *
handle_msg_start_emulating(struct ei_device *device, uint32_t sequence)
{
@ -308,14 +320,39 @@ handle_msg_stop_emulating(struct ei_device *device)
return NULL;
}
static struct brei_result *
maybe_error_on_device_state(struct ei_device *device, const char *event_type)
{
switch (device->state) {
case EI_DEVICE_STATE_EMULATING:
return NULL;
case EI_DEVICE_STATE_REMOVED_FROM_CLIENT:
/* we removed the device but server sent us an event - most
* likely a race condition, so let's ignore it */
return NULL;
case EI_DEVICE_STATE_NEW:
case EI_DEVICE_STATE_PAUSED:
case EI_DEVICE_STATE_RESUMED:
case EI_DEVICE_STATE_REMOVED_FROM_SERVER:
case EI_DEVICE_STATE_DEAD:
break;
}
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
"Invalid device state %ud for a %s event", device->state, event_type);
}
static struct brei_result *
handle_msg_frame(struct ei_device *device, uint32_t time, uint32_t micros)
{
DISCONNECT_IF_SENDER_CONTEXT(device);
ei_queue_frame_event(device, ms2us(time) + micros);
if (device->state == EI_DEVICE_STATE_EMULATING) {
ei_queue_frame_event(device, ms2us(time) + micros);
return NULL;
}
return NULL;
return maybe_error_on_device_state(device, "frame");
}
static struct brei_result *
@ -385,7 +422,17 @@ handle_msg_pointer_rel(struct ei_pointer *pointer, float x, float y)
DISCONNECT_IF_SENDER_CONTEXT(device);
return brei_result_new_from_neg_errno(ei_device_event_pointer_rel(device, x, y));
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)) {
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
"Pointer rel event for non-pointer device");
}
if (device->state == EI_DEVICE_STATE_EMULATING) {
ei_queue_pointer_rel_event(device, x, y);
return NULL;
}
return maybe_error_on_device_state(device, "pointer rel");
}
static struct brei_result *
@ -395,7 +442,21 @@ handle_msg_pointer_abs(struct ei_pointer *pointer, float x, float y)
DISCONNECT_IF_SENDER_CONTEXT(device);
return brei_result_new_from_neg_errno(ei_device_event_pointer_abs(device, x, y));
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)) {
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
"Pointer abs event for non-pointer device");
}
if (device->state == EI_DEVICE_STATE_EMULATING) {
if (!ei_device_in_region(device, x, y))
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_VALUE,
"abs position outside regions");
ei_queue_pointer_abs_event(device, x, y);
return NULL;
}
return maybe_error_on_device_state(device, "pointer abs");
}
static struct brei_result *
@ -406,7 +467,19 @@ handle_msg_pointer_button(struct ei_pointer *pointer,
DISCONNECT_IF_SENDER_CONTEXT(device);
return brei_result_new_from_neg_errno(ei_device_event_pointer_button(device, button, !!state));
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE) &&
!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)) {
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
"Pointer button event for non-pointer device");
}
if (device->state == EI_DEVICE_STATE_EMULATING) {
ei_queue_pointer_button_event(device, button, !!state);
return NULL;
}
return maybe_error_on_device_state(device, "pointer button");
}
static struct brei_result *
@ -416,7 +489,18 @@ handle_msg_pointer_scroll(struct ei_pointer *pointer, float x, float y)
DISCONNECT_IF_SENDER_CONTEXT(device);
return brei_result_new_from_neg_errno(ei_device_event_pointer_scroll(device, x, y));
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE) &&
!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)) {
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
"Pointer scroll event for non-pointer device");
}
if (device->state == EI_DEVICE_STATE_EMULATING) {
ei_queue_pointer_scroll_event(device, x, y);
return NULL;
}
return maybe_error_on_device_state(device, "pointer scroll");
}
static struct brei_result *
@ -427,7 +511,18 @@ handle_msg_pointer_scroll_discrete(struct ei_pointer *pointer,
DISCONNECT_IF_SENDER_CONTEXT(device);
return brei_result_new_from_neg_errno(ei_device_event_pointer_scroll_discrete(device, x, y));
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE) &&
!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)) {
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
"Pointer scroll discrete event for non-pointer device");
}
if (device->state == EI_DEVICE_STATE_EMULATING) {
ei_queue_pointer_scroll_discrete_event(device, x, y);
return NULL;
}
return maybe_error_on_device_state(device, "pointer scroll discrete");
}
static struct brei_result *
@ -438,12 +533,21 @@ handle_msg_pointer_scroll_stop(struct ei_pointer *pointer,
DISCONNECT_IF_SENDER_CONTEXT(device);
if (is_cancel)
return brei_result_new_from_neg_errno(ei_device_event_pointer_scroll_cancel(device, !!x, !!y));
else
return brei_result_new_from_neg_errno(ei_device_event_pointer_scroll_stop(device, !!x, !!y));
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE) &&
!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)) {
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
"Pointer scroll stop event for non-pointer device");
}
return brei_result_new_from_neg_errno(-EINVAL);
if (device->state == EI_DEVICE_STATE_EMULATING) {
if (is_cancel)
ei_queue_pointer_scroll_cancel_event(device, !!x, !!y);
else
ei_queue_pointer_scroll_stop_event(device, !!x, !!y);
return NULL;
}
return maybe_error_on_device_state(device, "pointer scroll discrete");
}
static struct brei_result *
@ -488,19 +592,28 @@ handle_msg_keyboard_key(struct ei_keyboard *keyboard, uint32_t key, uint32_t sta
DISCONNECT_IF_SENDER_CONTEXT(device);
return brei_result_new_from_neg_errno(ei_device_event_keyboard_key(device, key, !!state));
if (!ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD)) {
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
"Key event for non-keyboard device");
}
if (device->state == EI_DEVICE_STATE_EMULATING) {
ei_queue_keyboard_key_event(device, key, !!state);
return NULL;
}
return maybe_error_on_device_state(device, "key");
}
static struct brei_result *
handle_msg_keyboard_modifiers(struct ei_keyboard *keyboard, uint32_t depressed,
uint32_t locked, uint32_t latched, uint32_t group)
{
struct ei *ei = ei_keyboard_get_context(keyboard);
struct ei_device *device = ei_keyboard_get_device(keyboard);
if (!ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD)) {
log_bug(ei,"Modifier event for non-keyboard");
return brei_result_new_from_neg_errno(-EPROTO);
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
"Modifier event for non-keyboard device");
}
struct ei_xkb_modifiers mods = {
@ -546,7 +659,17 @@ handle_msg_touch_down(struct ei_touchscreen *touchscreen,
DISCONNECT_IF_SENDER_CONTEXT(device);
return brei_result_new_from_neg_errno(ei_device_event_touch_down(device, touchid, x, y));
if (!ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH)) {
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
"Touch down event for non-touch device");
}
if (device->state == EI_DEVICE_STATE_EMULATING) {
ei_queue_touch_down_event(device, touchid, x, y);
return NULL;
}
return maybe_error_on_device_state(device, "touch down");
}
static struct brei_result *
@ -557,7 +680,17 @@ handle_msg_touch_motion(struct ei_touchscreen *touchscreen,
DISCONNECT_IF_SENDER_CONTEXT(device);
return brei_result_new_from_neg_errno(ei_device_event_touch_motion(device, touchid, x, y));
if (!ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH)) {
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
"Touch motion event for non-touch device");
}
if (device->state == EI_DEVICE_STATE_EMULATING) {
ei_queue_touch_motion_event(device, touchid, x, y);
return NULL;
}
return maybe_error_on_device_state(device, "touch motion");
}
static struct brei_result *
@ -567,7 +700,16 @@ handle_msg_touch_up(struct ei_touchscreen *touchscreen, uint32_t touchid)
DISCONNECT_IF_SENDER_CONTEXT(device);
return brei_result_new_from_neg_errno(ei_device_event_touch_up(device, touchid));
if (!ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH)) {
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
"Touch up event for non-touch device");
}
if (device->state == EI_DEVICE_STATE_EMULATING) {
ei_queue_touch_up_event(device, touchid);
return NULL;
}
return maybe_error_on_device_state(device, "touch up");
}
static struct brei_result *
@ -1065,19 +1207,6 @@ ei_device_pointer_motion(struct ei_device *device,
ei_send_pointer_rel(device, x, y);
}
static inline bool
ei_device_in_region(struct ei_device *device, double x, double y)
{
struct ei_region *r;
list_for_each(r, &device->regions, link) {
if (ei_region_contains(r, x, y))
return true;
}
return false;
}
_public_ void
ei_device_pointer_motion_absolute(struct ei_device *device,
double x, double y)
@ -1461,214 +1590,3 @@ ei_device_frame(struct ei_device *device, uint64_t time)
ei_disconnect(ei_device_get_context(device));
return;
}
int
ei_device_event_frame(struct ei_device *device, uint64_t time)
{
if (device->state != EI_DEVICE_STATE_EMULATING)
return -EINVAL;
ei_queue_frame_event(device, time);
return 0;
}
int
ei_device_event_pointer_rel(struct ei_device *device, double x, double y)
{
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)) {
log_bug_client(ei_device_get_context(device),
"%s: device is not a pointer", __func__);
return -EINVAL;
}
if (device->state != EI_DEVICE_STATE_EMULATING)
return -EINVAL;
ei_queue_pointer_rel_event(device, x, y);
return 0;
}
int
ei_device_event_pointer_abs(struct ei_device *device,
double x, double y)
{
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)) {
log_bug_client(ei_device_get_context(device),
"%s: device is not an absolute pointer", __func__);
return -EINVAL;
}
if (device->state != EI_DEVICE_STATE_EMULATING)
return -EINVAL;
if (!ei_device_in_region(device, x, y))
return -EINVAL;
ei_queue_pointer_abs_event(device, x, y);
return 0;
}
int
ei_device_event_pointer_button(struct ei_device *device,
uint32_t button, bool is_press)
{
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)) {
log_bug_client(ei_device_get_context(device),
"%s: device is not a pointer", __func__);
return -EINVAL;
}
if (device->state != EI_DEVICE_STATE_EMULATING)
return -EINVAL;
ei_queue_pointer_button_event(device, button, is_press);
return 0;
}
int
ei_device_event_pointer_scroll(struct ei_device *device,
double x, double y)
{
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER) &&
!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)) {
log_bug_client(ei_device_get_context(device),
"%s: device is not a (absolute) pointer", __func__);
return -EINVAL;
}
if (device->state != EI_DEVICE_STATE_EMULATING)
return -EINVAL;
ei_queue_pointer_scroll_event(device, x, y);
return 0;
}
int
ei_device_event_pointer_scroll_discrete(struct ei_device *device,
int32_t x, int32_t y)
{
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER) &&
!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)) {
log_bug_client(ei_device_get_context(device),
"%s: device is not a (absolute) pointer", __func__);
return -EINVAL;
}
if (device->state != EI_DEVICE_STATE_EMULATING)
return -EINVAL;
ei_queue_pointer_scroll_discrete_event(device, x, y);
return 0;
}
int
ei_device_event_pointer_scroll_stop(struct ei_device *device, bool x, bool y)
{
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER) &&
!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)) {
log_bug_client(ei_device_get_context(device),
"%s: device is not a (absolute) pointer", __func__);
return -EINVAL;
}
if (device->state != EI_DEVICE_STATE_EMULATING)
return -EINVAL;
ei_queue_pointer_scroll_stop_event(device, x, y);
return 0;
}
int
ei_device_event_pointer_scroll_cancel(struct ei_device *device, bool x, bool y)
{
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER) &&
!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)) {
log_bug_client(ei_device_get_context(device),
"%s: device is not a (absolute) pointer", __func__);
return -EINVAL;
}
if (device->state != EI_DEVICE_STATE_EMULATING)
return -EINVAL;
ei_queue_pointer_scroll_cancel_event(device, x, y);
return 0;
}
int
ei_device_event_keyboard_key(struct ei_device *device,
uint32_t key, bool is_press)
{
if (!ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD)) {
log_bug_client(ei_device_get_context(device),
"%s: device is not a keyboard", __func__);
return -EINVAL;
}
if (device->state != EI_DEVICE_STATE_EMULATING)
return -EINVAL;
ei_queue_keyboard_key_event(device, key, is_press);
return 0;
}
int
ei_device_event_touch_down(struct ei_device *device, uint32_t touchid, double x, double y)
{
if (!ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH)) {
log_bug_client(ei_device_get_context(device),
"%s: device is not a touch device", __func__);
return -EINVAL;
}
if (device->state != EI_DEVICE_STATE_EMULATING)
return -EINVAL;
ei_queue_touch_down_event(device, touchid, x, y);
return 0;
}
int
ei_device_event_touch_motion(struct ei_device *device, uint32_t touchid, double x, double y)
{
if (!ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH)) {
log_bug_client(ei_device_get_context(device),
"%s: device is not a touch device", __func__);
return -EINVAL;
}
if (device->state != EI_DEVICE_STATE_EMULATING)
return -EINVAL;
ei_queue_touch_motion_event(device, touchid, x, y);
return 0;
}
int
ei_device_event_touch_up(struct ei_device *device, uint32_t touchid)
{
if (!ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH)) {
log_bug_client(ei_device_get_context(device),
"%s: device is not a touch device", __func__);
return -EINVAL;
}
if (device->state != EI_DEVICE_STATE_EMULATING)
return -EINVAL;
ei_queue_touch_up_event(device, touchid);
return 0;
}

View file

@ -133,53 +133,12 @@ ei_device_done(struct ei_device *device);
void
ei_device_removed_by_server(struct ei_device *device);
int
ei_device_event_frame(struct ei_device *device, uint64_t time);
void
ei_device_event_start_emulating(struct ei_device *device, uint32_t sequence);
void
ei_device_event_stop_emulating(struct ei_device *device);
int
ei_device_event_pointer_rel(struct ei_device *device,
double x, double y);
int
ei_device_event_pointer_abs(struct ei_device *device,
double x, double y);
int
ei_device_event_pointer_button(struct ei_device *device,
uint32_t button, bool is_press);
int
ei_device_event_pointer_scroll(struct ei_device *device,
double x, double y);
int
ei_device_event_pointer_scroll_stop(struct ei_device *device, bool x, bool y);
int
ei_device_event_pointer_scroll_cancel(struct ei_device *device, bool x, bool y);
int
ei_device_event_pointer_scroll_discrete(struct ei_device *device,
int32_t x, int32_t y);
int
ei_device_event_keyboard_key(struct ei_device *device,
uint32_t key, bool is_press);
int
ei_device_event_touch_down(struct ei_device *device, uint32_t tid,
double x, double y);
int
ei_device_event_touch_motion(struct ei_device *device, uint32_t tid,
double x, double y);
int
ei_device_event_touch_up(struct ei_device *device, uint32_t tid);
void
ei_device_added(struct ei_device *device);