/* SPDX-License-Identifier: MIT */ /* * 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-bits.h" #include "util-macros.h" #include "util-object.h" #include "libeis-private.h" static void eis_event_destroy(struct eis_event *event) { bool handled = false; switch (event->type) { case EIS_EVENT_CLIENT_CONNECT: case EIS_EVENT_CLIENT_DISCONNECT: case EIS_EVENT_SEAT_BIND: case EIS_EVENT_SEAT_DEVICE_REQUESTED: case EIS_EVENT_DEVICE_CLOSED: case EIS_EVENT_DEVICE_START_EMULATING: case EIS_EVENT_DEVICE_STOP_EMULATING: case EIS_EVENT_DEVICE_READY: case EIS_EVENT_BUTTON_BUTTON: case EIS_EVENT_POINTER_MOTION: case EIS_EVENT_POINTER_MOTION_ABSOLUTE: case EIS_EVENT_SCROLL_DELTA: case EIS_EVENT_SCROLL_STOP: case EIS_EVENT_SCROLL_CANCEL: case EIS_EVENT_SCROLL_DISCRETE: case EIS_EVENT_KEYBOARD_KEY: case EIS_EVENT_TOUCH_DOWN: case EIS_EVENT_TOUCH_MOTION: case EIS_EVENT_TOUCH_UP: case EIS_EVENT_FRAME: case EIS_EVENT_TEXT_KEYSYM: handled = true; break; case EIS_EVENT_TEXT_UTF8: free(steal(&event->text.utf8)); handled = true; break; case EIS_EVENT_PONG: eis_ping_unref(event->pong.ping); handled = true; break; case EIS_EVENT_SYNC: eis_sync_event_send_done(event); eis_callback_unref(event->sync.callback); handled = true; break; } if (!handled) abort(); /* not yet implemented */ event->device = eis_device_unref(event->device); event->seat = eis_seat_unref(event->seat); event->client = eis_client_unref(event->client); } static 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_seat(struct eis_seat *seat) { struct eis_client *client = eis_seat_get_client(seat); struct eis *eis = eis_client_get_context(client); struct eis_event *e = eis_event_create(&eis->object); e->client = eis_client_ref(client); e->seat = eis_seat_ref(seat); 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->seat = eis_seat_ref(eis_device_get_seat(device)); e->device = eis_device_ref(device); return e; } _public_ OBJECT_IMPLEMENT_REF(eis_event); _public_ OBJECT_IMPLEMENT_UNREF_CLEANUP(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, seat, struct eis_seat *); _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_client(eis_event_get_context(event), "Invalid event type %s (%u) passed to %s()", eis_event_type_to_string(type), type, function_name); return rc; } #define require_event_type(event_, retval_, ...) \ if (!check_event_type(event_, __func__, __VA_ARGS__, -1)) \ return retval_; _public_ uint64_t eis_event_get_time(struct eis_event *event) { require_event_type(event, 0, EIS_EVENT_POINTER_MOTION, EIS_EVENT_POINTER_MOTION_ABSOLUTE, EIS_EVENT_BUTTON_BUTTON, EIS_EVENT_SCROLL_DELTA, EIS_EVENT_SCROLL_STOP, EIS_EVENT_SCROLL_CANCEL, EIS_EVENT_SCROLL_DISCRETE, EIS_EVENT_KEYBOARD_KEY, EIS_EVENT_TOUCH_DOWN, EIS_EVENT_TOUCH_UP, EIS_EVENT_TOUCH_MOTION, EIS_EVENT_TEXT_KEYSYM, EIS_EVENT_TEXT_UTF8, EIS_EVENT_FRAME); return event->timestamp; } _public_ struct eis_ping * eis_event_pong_get_ping(struct eis_event *event) { require_event_type(event, NULL, EIS_EVENT_PONG); return event->pong.ping; } _public_ bool eis_event_seat_has_capability(struct eis_event *event, enum eis_device_capability cap) { require_event_type(event, false, EIS_EVENT_SEAT_BIND, EIS_EVENT_SEAT_DEVICE_REQUESTED); switch (cap) { case EIS_DEVICE_CAP_POINTER: case EIS_DEVICE_CAP_POINTER_ABSOLUTE: case EIS_DEVICE_CAP_KEYBOARD: case EIS_DEVICE_CAP_TOUCH: case EIS_DEVICE_CAP_BUTTON: case EIS_DEVICE_CAP_SCROLL: case EIS_DEVICE_CAP_TEXT: return mask_all(event->bind.capabilities, cap); } return false; } _public_ uint32_t eis_event_emulating_get_sequence(struct eis_event *event) { require_event_type(event, 0, EIS_EVENT_DEVICE_START_EMULATING); return event->start_emulating.sequence; } _public_ double eis_event_pointer_get_dx(struct eis_event *event) { require_event_type(event, 0.0, EIS_EVENT_POINTER_MOTION, EIS_EVENT_POINTER_MOTION_ABSOLUTE, EIS_EVENT_BUTTON_BUTTON, EIS_EVENT_SCROLL_DELTA, EIS_EVENT_SCROLL_DISCRETE); return event->pointer.dx; } _public_ double eis_event_pointer_get_dy(struct eis_event *event) { require_event_type(event, 0.0, EIS_EVENT_POINTER_MOTION, EIS_EVENT_POINTER_MOTION_ABSOLUTE, EIS_EVENT_BUTTON_BUTTON, EIS_EVENT_SCROLL_DELTA, EIS_EVENT_SCROLL_DISCRETE); return event->pointer.dy; } _public_ double eis_event_pointer_get_absolute_x(struct eis_event *event) { require_event_type(event, 0.0, EIS_EVENT_POINTER_MOTION, EIS_EVENT_POINTER_MOTION_ABSOLUTE, EIS_EVENT_BUTTON_BUTTON, EIS_EVENT_SCROLL_DELTA, EIS_EVENT_SCROLL_DISCRETE); return event->pointer.absx; } _public_ double eis_event_pointer_get_absolute_y(struct eis_event *event) { require_event_type(event, 0.0, EIS_EVENT_POINTER_MOTION, EIS_EVENT_POINTER_MOTION_ABSOLUTE, EIS_EVENT_BUTTON_BUTTON, EIS_EVENT_SCROLL_DELTA, EIS_EVENT_SCROLL_DISCRETE); return event->pointer.absy; } _public_ uint32_t eis_event_button_get_button(struct eis_event *event) { require_event_type(event, 0, EIS_EVENT_POINTER_MOTION, EIS_EVENT_POINTER_MOTION_ABSOLUTE, EIS_EVENT_BUTTON_BUTTON, EIS_EVENT_SCROLL_DELTA, EIS_EVENT_SCROLL_DISCRETE); return event->pointer.button; } _public_ bool eis_event_button_get_is_press(struct eis_event *event) { require_event_type(event, false, EIS_EVENT_POINTER_MOTION, EIS_EVENT_POINTER_MOTION_ABSOLUTE, EIS_EVENT_BUTTON_BUTTON, EIS_EVENT_SCROLL_DELTA, EIS_EVENT_SCROLL_DISCRETE); return event->pointer.button_is_press; } _public_ double eis_event_scroll_get_dx(struct eis_event *event) { require_event_type(event, 0, EIS_EVENT_POINTER_MOTION, EIS_EVENT_POINTER_MOTION_ABSOLUTE, EIS_EVENT_BUTTON_BUTTON, EIS_EVENT_SCROLL_DELTA, EIS_EVENT_SCROLL_DISCRETE); return event->pointer.sx; } _public_ double eis_event_scroll_get_dy(struct eis_event *event) { require_event_type(event, 0, EIS_EVENT_POINTER_MOTION, EIS_EVENT_POINTER_MOTION_ABSOLUTE, EIS_EVENT_BUTTON_BUTTON, EIS_EVENT_SCROLL_DELTA, EIS_EVENT_SCROLL_DISCRETE); return event->pointer.sy; } _public_ int32_t eis_event_scroll_get_discrete_dx(struct eis_event *event) { require_event_type(event, 0, EIS_EVENT_POINTER_MOTION, EIS_EVENT_POINTER_MOTION_ABSOLUTE, EIS_EVENT_BUTTON_BUTTON, EIS_EVENT_SCROLL_DELTA, EIS_EVENT_SCROLL_DISCRETE); return event->pointer.sdx; } _public_ int32_t eis_event_scroll_get_discrete_dy(struct eis_event *event) { require_event_type(event, 0, EIS_EVENT_POINTER_MOTION, EIS_EVENT_POINTER_MOTION_ABSOLUTE, EIS_EVENT_BUTTON_BUTTON, EIS_EVENT_SCROLL_DELTA, EIS_EVENT_SCROLL_DISCRETE); return event->pointer.sdy; } _public_ bool eis_event_scroll_get_stop_x(struct eis_event *event) { require_event_type(event, 0, EIS_EVENT_SCROLL_STOP, EIS_EVENT_SCROLL_CANCEL); return event->pointer.stop_x; } _public_ bool eis_event_scroll_get_stop_y(struct eis_event *event) { require_event_type(event, 0, EIS_EVENT_SCROLL_STOP, EIS_EVENT_SCROLL_CANCEL); return event->pointer.stop_y; } _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; } _public_ uint32_t eis_event_touch_get_id(struct eis_event *event) { require_event_type(event, 0, EIS_EVENT_TOUCH_DOWN, EIS_EVENT_TOUCH_UP, EIS_EVENT_TOUCH_MOTION); return event->touch.touchid; } _public_ double eis_event_touch_get_x(struct eis_event *event) { require_event_type(event, 0.0, EIS_EVENT_TOUCH_DOWN, EIS_EVENT_TOUCH_MOTION); return event->touch.x; } _public_ double eis_event_touch_get_y(struct eis_event *event) { require_event_type(event, 0.0, EIS_EVENT_TOUCH_DOWN, EIS_EVENT_TOUCH_MOTION); return event->touch.y; } _public_ bool eis_event_touch_get_is_cancel(struct eis_event *event) { require_event_type(event, false, EIS_EVENT_TOUCH_UP); return event->touch.is_cancel; } _public_ uint32_t eis_event_text_get_keysym(struct eis_event *event) { require_event_type(event, 0, EIS_EVENT_TEXT_KEYSYM); return event->text.keysym; } _public_ bool eis_event_text_get_keysym_is_press(struct eis_event *event) { require_event_type(event, false, EIS_EVENT_TEXT_KEYSYM); return event->text.is_press; } _public_ const char * eis_event_text_get_utf8(struct eis_event *event) { require_event_type(event, NULL, EIS_EVENT_TEXT_UTF8); return event->text.utf8; }