diff --git a/meson.build b/meson.build index 11cc511..d4fcab4 100644 --- a/meson.build +++ b/meson.build @@ -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, diff --git a/src/libeis-event.c b/src/libeis-event.c new file mode 100644 index 0000000..aeae6a2 --- /dev/null +++ b/src/libeis-event.c @@ -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 + +#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; +} diff --git a/src/libeis-private.h b/src/libeis-private.h index db58e97..0825bda 100644 --- a/src/libeis-private.h +++ b/src/libeis-private.h @@ -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); diff --git a/src/libeis.c b/src/libeis.c index e8f1592..906dc23 100644 --- a/src/libeis.c +++ b/src/libeis.c @@ -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* diff --git a/src/libeis.h b/src/libeis.h index 97897cd..da2f29a 100644 --- a/src/libeis.h +++ b/src/libeis.h @@ -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); diff --git a/src/util-logger.h b/src/util-logger.h index 0cfa87a..30b8b3d 100644 --- a/src/util-logger.h +++ b/src/util-logger.h @@ -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); diff --git a/tools/eis-socket-server.c b/tools/eis-socket-server.c index e8361f4..f519091 100644 --- a/tools/eis-socket-server.c +++ b/tools/eis-socket-server.c @@ -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: