libeis: flatten the event hierarchy

Same as already done for libei. There's relatively little benefit here since
we won't have a lot of different events and any caller will do the switch
based on the event type anyway. So let's just export a single event type and
have everything contained in that.

Since this required rewriting all getters, let's move the lot to a new file
and streamline things a bit that way.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2020-08-18 15:45:01 +10:00
parent 4565fb6851
commit d4e274ee6f
7 changed files with 277 additions and 221 deletions

View file

@ -65,6 +65,7 @@ lib_libeis = shared_library('eis',
'src/libeis.c',
'src/libeis-client.c',
'src/libeis-device.c',
'src/libeis-event.c',
'src/libeis-socket.c',
'src/libeis-fd.c',
proto_headers,

203
src/libeis-event.c Normal file
View file

@ -0,0 +1,203 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <stdarg.h>
#include "util-object.h"
#include "util-macros.h"
#include "util-logger.h"
#include "libeis-private.h"
static void
eis_event_destroy(struct eis_event *event)
{
switch (event->type) {
case EIS_EVENT_CLIENT_CONNECT:
case EIS_EVENT_CLIENT_DISCONNECT:
case EIS_EVENT_DEVICE_ADDED:
case EIS_EVENT_DEVICE_REMOVED:
case EIS_EVENT_POINTER_BUTTON:
case EIS_EVENT_POINTER_MOTION:
case EIS_EVENT_KEYBOARD_KEY:
break;
default:
abort(); /* not yet implemented */
}
event->device = eis_device_unref(event->device);
event->client = eis_client_unref(event->client);
}
OBJECT_IMPLEMENT_CREATE(eis_event);
struct eis_event *
eis_event_new_for_client(struct eis_client *client)
{
struct eis *eis = eis_client_get_context(client);
struct eis_event *e = eis_event_create(&eis->object);
e->client = eis_client_ref(client);
return e;
}
struct eis_event *
eis_event_new_for_device(struct eis_device *device)
{
struct eis_client *client = eis_device_get_client(device);
struct eis *eis = eis_client_get_context(client);
struct eis_event *e = eis_event_create(&eis->object);
e->client = eis_client_ref(client);
e->device = eis_device_ref(device);
return e;
}
/* this one is not public */
OBJECT_IMPLEMENT_REF(eis_event);
_public_
OBJECT_IMPLEMENT_UNREF(eis_event);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event, type, enum eis_event_type);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event, client, struct eis_client*);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event, device, struct eis_device*);
static
OBJECT_IMPLEMENT_PARENT(eis_event, eis);
struct eis *
eis_event_get_context(struct eis_event *event)
{
return eis_event_parent(event);
}
static inline bool
check_event_type(struct eis_event *event,
const char *function_name,
...)
{
bool rc = false;
va_list args;
unsigned int type_permitted;
enum eis_event_type type = eis_event_get_type(event);
va_start(args, function_name);
type_permitted = va_arg(args, unsigned int);
while (type_permitted != (unsigned int)-1) {
if (type_permitted == type) {
rc = true;
break;
}
type_permitted = va_arg(args, unsigned int);
}
va_end(args);
if (!rc)
log_bug(eis_event_get_context(event),
"Invalid event type %d passed to %s()\n",
type, function_name);
return rc;
}
#define require_event_type(event_, retval_, ...) \
if (!check_event_type(event_, __func__, __VA_ARGS__, -1)) \
return retval_; \
_public_ double
eis_event_pointer_get_x(struct eis_event *event)
{
require_event_type(event, 0.0,
EIS_EVENT_POINTER_MOTION,
EIS_EVENT_POINTER_MOTION_ABSOLUTE,
EIS_EVENT_POINTER_BUTTON,
EIS_EVENT_POINTER_SCROLL,
EIS_EVENT_POINTER_SCROLL_DISCRETE);
return event->pointer.x;
}
_public_ double
eis_event_pointer_get_y(struct eis_event *event)
{
require_event_type(event, 0.0,
EIS_EVENT_POINTER_MOTION,
EIS_EVENT_POINTER_MOTION_ABSOLUTE,
EIS_EVENT_POINTER_BUTTON,
EIS_EVENT_POINTER_SCROLL,
EIS_EVENT_POINTER_SCROLL_DISCRETE);
return event->pointer.y;
}
_public_ uint32_t
eis_event_pointer_get_button(struct eis_event *event)
{
require_event_type(event, 0,
EIS_EVENT_POINTER_MOTION,
EIS_EVENT_POINTER_MOTION_ABSOLUTE,
EIS_EVENT_POINTER_BUTTON,
EIS_EVENT_POINTER_SCROLL,
EIS_EVENT_POINTER_SCROLL_DISCRETE);
return event->pointer.button;
}
_public_ bool
eis_event_pointer_get_button_is_press(struct eis_event *event)
{
require_event_type(event, false,
EIS_EVENT_POINTER_MOTION,
EIS_EVENT_POINTER_MOTION_ABSOLUTE,
EIS_EVENT_POINTER_BUTTON,
EIS_EVENT_POINTER_SCROLL,
EIS_EVENT_POINTER_SCROLL_DISCRETE);
return event->pointer.button_is_press;
}
_public_ uint32_t
eis_event_keyboard_get_key(struct eis_event *event)
{
require_event_type(event, 0,
EIS_EVENT_KEYBOARD_KEY);
return event->keyboard.key;
}
_public_ bool
eis_event_keyboard_get_key_is_press(struct eis_event *event)
{
require_event_type(event, false,
EIS_EVENT_KEYBOARD_KEY);
return event->keyboard.key_is_press;
}

View file

@ -100,23 +100,18 @@ struct eis_event {
struct list link;
struct eis_client *client;
struct eis_device *device;
};
struct eis_event_client {
struct eis_event base;
};
struct eis_event_pointer {
struct eis_event base;
int x, y; /* relative motion */
uint32_t button;
bool button_is_press;
};
struct eis_event_keyboard {
struct eis_event base;
uint32_t key;
bool key_is_press;
union {
struct {
int x, y; /* relative motion */
uint32_t button;
bool button_is_press;
} pointer;
struct {
uint32_t key;
bool key_is_press;
} keyboard;
};
};
void
@ -164,6 +159,18 @@ int
eis_device_keyboard_key(struct eis_device *device,
uint32_t key, bool state);
struct eis_event *
eis_event_new_for_client(struct eis_client *client);
struct eis_event *
eis_event_new_for_device(struct eis_device *device);
struct eis *
eis_event_get_context(struct eis_event *event);
struct eis_event*
eis_event_ref(struct eis_event *event);
void
eis_queue_connect_event(struct eis_client *client);

View file

@ -37,108 +37,6 @@
#include "libeis.h"
#include "libeis-private.h"
static struct eis_event* eis_event_ref(struct eis_event *event);
static void
eis_event_destroy(struct eis_event *event)
{
switch (event->type) {
case EIS_EVENT_CLIENT_CONNECT:
case EIS_EVENT_CLIENT_DISCONNECT:
case EIS_EVENT_DEVICE_ADDED:
case EIS_EVENT_DEVICE_REMOVED:
case EIS_EVENT_POINTER_BUTTON:
case EIS_EVENT_POINTER_MOTION:
case EIS_EVENT_KEYBOARD_KEY:
break;
default:
abort(); /* not yet implemented */
}
event->device = eis_device_unref(event->device);
event->client = eis_client_unref(event->client);
}
static
OBJECT_IMPLEMENT_INIT(eis_event);
/* this one is not public */
OBJECT_IMPLEMENT_REF(eis_event);
_public_
OBJECT_IMPLEMENT_UNREF(eis_event);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event, type, enum eis_event_type);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event, client, struct eis_client*);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event, device, struct eis_device*);
/* FIXME: these should contain error checks but for now this will do */
_public_
OBJECT_IMPLEMENT_GETTER(eis_event_pointer, x, double);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event_pointer, y, double);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event_pointer, button, uint32_t);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event_pointer, button_is_press, bool);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event_keyboard, key, uint32_t);
_public_
OBJECT_IMPLEMENT_GETTER(eis_event_keyboard, key_is_press, bool);
_public_ struct eis_event_pointer *
eis_event_get_pointer_event(struct eis_event *e)
{
switch (e->type) {
case EIS_EVENT_CLIENT_CONNECT:
case EIS_EVENT_CLIENT_DISCONNECT:
case EIS_EVENT_DEVICE_ADDED:
case EIS_EVENT_DEVICE_REMOVED:
case EIS_EVENT_REQUEST_CAPABILITY:
case EIS_EVENT_CANCEL_CAPABILITY:
break;
case EIS_EVENT_POINTER_MOTION:
case EIS_EVENT_POINTER_MOTION_ABSOLUTE:
case EIS_EVENT_POINTER_BUTTON:
case EIS_EVENT_POINTER_SCROLL:
case EIS_EVENT_POINTER_SCROLL_DISCRETE:
return container_of(e, struct eis_event_pointer, base);
case EIS_EVENT_KEYBOARD_KEY:
case EIS_EVENT_TOUCH_DOWN:
case EIS_EVENT_TOUCH_UP:
case EIS_EVENT_TOUCH_MOTION:
break;
}
return NULL;
}
_public_ struct eis_event_keyboard *
eis_event_get_keyboard_event(struct eis_event *e)
{
switch (e->type) {
case EIS_EVENT_CLIENT_CONNECT:
case EIS_EVENT_CLIENT_DISCONNECT:
case EIS_EVENT_DEVICE_ADDED:
case EIS_EVENT_DEVICE_REMOVED:
case EIS_EVENT_REQUEST_CAPABILITY:
case EIS_EVENT_CANCEL_CAPABILITY:
case EIS_EVENT_POINTER_MOTION:
case EIS_EVENT_POINTER_MOTION_ABSOLUTE:
case EIS_EVENT_POINTER_BUTTON:
case EIS_EVENT_POINTER_SCROLL:
case EIS_EVENT_POINTER_SCROLL_DISCRETE:
break;
case EIS_EVENT_KEYBOARD_KEY:
return container_of(e, struct eis_event_keyboard, base);
case EIS_EVENT_TOUCH_DOWN:
case EIS_EVENT_TOUCH_UP:
case EIS_EVENT_TOUCH_MOTION:
break;
}
return NULL;
}
static void
eis_destroy(struct eis *eis)
{
@ -198,8 +96,10 @@ eis_dispatch(struct eis *eis)
}
static void
eis_queue_event(struct eis *eis, struct eis_event *event)
eis_queue_event(struct eis_event *event)
{
struct eis *eis = eis_event_get_context(event);
log_debug(eis, "queuing event type %d\n", event->type);
list_append(&eis->event_queue, &event->link);
@ -208,111 +108,67 @@ eis_queue_event(struct eis *eis, struct eis_event *event)
void
eis_queue_connect_event(struct eis_client *client)
{
struct eis *eis = eis_client_get_context(client);
struct eis_event_client *e = xalloc(sizeof(*e));
eis_event_init_object(&e->base, &eis->object);
e->base.client = eis_client_ref(client);
e->base.type = EIS_EVENT_CLIENT_CONNECT;
eis_queue_event(eis, &e->base);
struct eis_event *e = eis_event_new_for_client(client);
e->type = EIS_EVENT_CLIENT_CONNECT;
eis_queue_event(e);
}
void
eis_queue_disconnect_event(struct eis_client *client)
{
struct eis *eis = eis_client_get_context(client);
struct eis_event_client *e = xalloc(sizeof(*e));
eis_event_init_object(&e->base, &eis->object);
e->base.type = EIS_EVENT_CLIENT_DISCONNECT;
e->base.client = eis_client_ref(client);
eis_queue_event(eis, &e->base);
struct eis_event *e = eis_event_new_for_client(client);
e->type = EIS_EVENT_CLIENT_DISCONNECT;
eis_queue_event(e);
}
void
eis_queue_added_event(struct eis_device *device)
{
struct eis_client *client = eis_device_get_client(device);
struct eis *eis = eis_client_get_context(client);
struct eis_event_client *e = xalloc(sizeof(*e));
eis_event_init_object(&e->base, &eis->object);
e->base.type = EIS_EVENT_DEVICE_ADDED;
e->base.client = eis_client_ref(client);
e->base.device = eis_device_ref(device);
eis_queue_event(eis, &e->base);
struct eis_event *e = eis_event_new_for_device(device);
e->type = EIS_EVENT_DEVICE_ADDED;
eis_queue_event(e);
}
void
eis_queue_removed_event(struct eis_device *device)
{
struct eis_client *client = eis_device_get_client(device);
struct eis *eis = eis_client_get_context(client);
struct eis_event_client *e = xalloc(sizeof(*e));
eis_event_init_object(&e->base, &eis->object);
e->base.type = EIS_EVENT_DEVICE_REMOVED;
e->base.client = eis_client_ref(client);
e->base.device = eis_device_ref(device);
eis_queue_event(eis, &e->base);
struct eis_event *e = eis_event_new_for_device(device);
e->type = EIS_EVENT_DEVICE_REMOVED;
eis_queue_event(e);
}
void
eis_queue_pointer_rel_event(struct eis_device *device,
double x, double y)
{
struct eis_client *client = eis_device_get_client(device);
struct eis *eis = eis_client_get_context(client);
struct eis_event_pointer *e = xalloc(sizeof(*e));
eis_event_init_object(&e->base, &eis->object);
e->base.type = EIS_EVENT_POINTER_MOTION;
e->base.client = eis_client_ref(client);
e->base.device = eis_device_ref(device);
e->x = x;
e->y = y;
eis_queue_event(eis, &e->base);
struct eis_event *e = eis_event_new_for_device(device);
e->type = EIS_EVENT_POINTER_MOTION;
e->pointer.x = x;
e->pointer.y = y;
eis_queue_event(e);
}
void
eis_queue_pointer_button_event(struct eis_device *device, uint32_t button,
bool is_press)
{
struct eis_client *client = eis_device_get_client(device);
struct eis *eis = eis_client_get_context(client);
struct eis_event *e = eis_event_new_for_device(device);
e->type = EIS_EVENT_POINTER_BUTTON;
e->pointer.button = button;
e->pointer.button_is_press = is_press;
struct eis_event_pointer *e = xalloc(sizeof(*e));
eis_event_init_object(&e->base, &eis->object);
e->base.type = EIS_EVENT_POINTER_BUTTON;
e->base.client = eis_client_ref(client);
e->base.device = eis_device_ref(device);
e->button = button;
e->button_is_press = is_press;
eis_queue_event(eis, &e->base);
eis_queue_event(e);
}
void
eis_queue_keyboard_key_event(struct eis_device *device, uint32_t key,
bool is_press)
{
struct eis_client *client = eis_device_get_client(device);
struct eis *eis = eis_client_get_context(client);
struct eis_event_keyboard *e = xalloc(sizeof(*e));
eis_event_init_object(&e->base, &eis->object);
e->base.type = EIS_EVENT_KEYBOARD_KEY;
e->base.client = eis_client_ref(client);
e->base.device = eis_device_ref(device);
e->key = key;
e->key_is_press = is_press;
eis_queue_event(eis, &e->base);
struct eis_event *e = eis_event_new_for_device(device);
e->type = EIS_EVENT_KEYBOARD_KEY;
e->keyboard.key = key;
e->keyboard.key_is_press = is_press;
eis_queue_event(e);
}
_public_ struct eis_event*

View file

@ -31,10 +31,6 @@ struct eis;
struct eis_client;
struct eis_device;
struct eis_event;
struct eis_event_client;
struct eis_event_pointer;
struct eis_event_keyboard;
struct eis_event_touch;
enum eis_device_capability {
EIS_DEVICE_CAP_POINTER = 1,
@ -412,92 +408,86 @@ eis_device_keyboard_set_keymap(struct eis_device *device,
struct eis_device *
eis_event_get_device(struct eis_event *event);
struct eis_event_pointer *
eis_event_get_pointer_event(struct eis_event *event);
struct eis_event_keyboard *
eis_event_get_keyboard_event(struct eis_event *event);
/**
* For an event of type @ref EIS_EVENT_POINTER_MOTION return the x movement
* in logical pixels.
*/
double
eis_event_pointer_get_x(struct eis_event_pointer *ptrev);
eis_event_pointer_get_x(struct eis_event *event);
/**
* For an event of type @ref EIS_EVENT_POINTER_MOTION return the y movement
* in logical pixels.
*/
double
eis_event_pointer_get_y(struct eis_event_pointer *ptrev);
eis_event_pointer_get_y(struct eis_event *event);
/**
* For an event of type @ref EIS_EVENT_POINTER_MOTION_ABSOLUTE return the x
* position in logical pixels.
*/
double
eis_event_pointer_get_absolute_x(struct eis_event_pointer *ptrev);
eis_event_pointer_get_absolute_x(struct eis_event *event);
/**
* For an event of type @ref EIS_EVENT_POINTER_MOTION_ABSOLUTE return the y
* position in logical pixels.
*/
double
eis_event_pointer_get_absolute_y(struct eis_event_pointer *ptrev);
eis_event_pointer_get_absolute_y(struct eis_event *event);
/**
* For an event of type @ref EIS_EVENT_POINTER_BUTTON return the button
* code as defined in linux/input-event-codes.h
*/
uint32_t
eis_event_pointer_get_button(struct eis_event_pointer *ptrev);
eis_event_pointer_get_button(struct eis_event *event);
/**
* For an event of type @ref EIS_EVENT_POINTER_BUTTON return true if the
* event is a button press, false for a release.
*/
bool
eis_event_pointer_get_button_is_press(struct eis_event_pointer *ptrev);
eis_event_pointer_get_button_is_press(struct eis_event *event);
/**
* For an event of type @ref EIS_EVENT_POINTER_SCROLL return the x scroll
* distance in logical pixels.
*/
double
eis_event_pointer_get_scroll_x(struct eis_event_pointer *ptrev);
eis_event_pointer_get_scroll_x(struct eis_event *event);
/**
* For an event of type @ref EIS_EVENT_POINTER_SCROLL return the y scroll
* distance in logical pixels.
*/
double
eis_event_pointer_get_scroll_y(struct eis_event_pointer *ptrev);
eis_event_pointer_get_scroll_y(struct eis_event *event);
/**
* For an event of type @ref EIS_EVENT_POINTER_SCROLL_DISCRETE return the x
* scroll distance in fractions or multiples of 120.
*/
int32_t
eis_event_pointer_get_scroll_discrete_x(struct eis_event_pointer *ptrev);
eis_event_pointer_get_scroll_discrete_x(struct eis_event *event);
/**
* For an event of type @ref EIS_EVENT_POINTER_SCROLL_DISCRETE return the y
* scroll distance in fractions or multiples of 120.
*/
int32_t
eis_event_pointer_get_scroll_discrete_y(struct eis_event_pointer *ptrev);
eis_event_pointer_get_scroll_discrete_y(struct eis_event *event);
/**
* For an event of type @ref EIS_EVENT_KEYBOARD_KEY return the key code (as
* defined in include/linux/input-event-codes.h).
*/
uint32_t
eis_event_keyboard_get_key(struct eis_event_keyboard *kbdev);
eis_event_keyboard_get_key(struct eis_event *event);
/**
* For an event of type @ref EIS_EVENT_KEYBOARD_KEY return true if the
* event is a key down, false for a release.
*/
bool
eis_event_keyboard_get_key_is_press(struct eis_event_keyboard *kbdev);
eis_event_keyboard_get_key_is_press(struct eis_event *event);

View file

@ -63,6 +63,8 @@ log_msg_va(struct logger *logger,
log_msg((T_)->logger, LOGGER_WARN, __VA_ARGS__)
#define log_error(T_, ...) \
log_msg((T_)->logger, LOGGER_ERROR, __VA_ARGS__)
#define log_bug(T_, ...) \
log_msg((T_)->logger, LOGGER_ERROR, "bug: " __VA_ARGS__)
struct logger *
logger_new(const char *prefix, void *user_data);

View file

@ -126,26 +126,23 @@ int main(int argc, char **argv)
}
case EIS_EVENT_POINTER_MOTION:
{
struct eis_event_pointer *p = eis_event_get_pointer_event(e);
printf("server: motion by %.2f/%.2f\n",
eis_event_pointer_get_x(p),
eis_event_pointer_get_y(p));
eis_event_pointer_get_x(e),
eis_event_pointer_get_y(e));
}
break;
case EIS_EVENT_POINTER_BUTTON:
{
struct eis_event_pointer *p = eis_event_get_pointer_event(e);
printf("server: button %d (%s)\n",
eis_event_pointer_get_button(p),
eis_event_pointer_get_button_is_press(p) ? "press" : "release");
eis_event_pointer_get_button(e),
eis_event_pointer_get_button_is_press(e) ? "press" : "release");
}
break;
case EIS_EVENT_KEYBOARD_KEY:
{
struct eis_event_keyboard *k = eis_event_get_keyboard_event(e);
printf("server: key %d (%s)\n",
eis_event_keyboard_get_key(k),
eis_event_keyboard_get_key_is_press(k) ? "press" : "release");
eis_event_keyboard_get_key(e),
eis_event_keyboard_get_key_is_press(e) ? "press" : "release");
}
break;
default: