From 4d9ca1796d972f4ceb81fc2f916e22a01ae75f57 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 6 Feb 2023 09:24:36 +1000 Subject: [PATCH] protocol: move pointer/keyboard/touch into separate interfaces This allows us to have a device support multiple interfaces and evolve those interfaces individually, e.g. add things to the keyboard interface without having to bump the touchscreen interface. Note that due to a name clash with the existing struct ei_touch public API the protocol interface is named touchscreen. --- meson.build | 6 + proto/protocol.xml | 330 ++++++++++++++---------- src/libei-device.c | 466 +++++++++++++++++++++++++++++++++- src/libei-device.h | 10 + src/libei-keyboard.c | 87 +++++++ src/libei-keyboard.h | 49 ++++ src/libei-pointer.c | 87 +++++++ src/libei-pointer.h | 49 ++++ src/libei-private.h | 44 +--- src/libei-touchscreen.c | 87 +++++++ src/libei-touchscreen.h | 49 ++++ src/libei.c | 400 +---------------------------- src/libeis-client.c | 218 +--------------- src/libeis-client.h | 3 + src/libeis-connection-setup.c | 3 + src/libeis-device.c | 262 ++++++++++++++++--- src/libeis-device.h | 7 + src/libeis-keyboard.c | 107 ++++++++ src/libeis-keyboard.h | 51 ++++ src/libeis-pointer.c | 107 ++++++++ src/libeis-pointer.h | 51 ++++ src/libeis-private.h | 3 + src/libeis-touchscreen.c | 107 ++++++++ src/libeis-touchscreen.h | 51 ++++ 24 files changed, 1811 insertions(+), 823 deletions(-) create mode 100644 src/libei-keyboard.c create mode 100644 src/libei-keyboard.h create mode 100644 src/libei-pointer.c create mode 100644 src/libei-pointer.h create mode 100644 src/libei-touchscreen.c create mode 100644 src/libei-touchscreen.h create mode 100644 src/libeis-keyboard.c create mode 100644 src/libeis-keyboard.h create mode 100644 src/libeis-pointer.c create mode 100644 src/libeis-pointer.h create mode 100644 src/libeis-touchscreen.c create mode 100644 src/libeis-touchscreen.h diff --git a/meson.build b/meson.build index 028be39..b73bca8 100644 --- a/meson.build +++ b/meson.build @@ -81,11 +81,14 @@ src_libei = files( 'src/libei-device.c', 'src/libei-event.c', 'src/libei-fd.c', + 'src/libei-keyboard.c', 'src/libei-log.c', + 'src/libei-pointer.c', 'src/libei-region.c', 'src/libei-region.c', 'src/libei-seat.c', 'src/libei-socket.c', + 'src/libei-touchscreen.c', ) + [ei_proto_headers, ei_proto_sources] deps_libei = [ @@ -127,10 +130,13 @@ src_libeis = files( 'src/libeis-device.c', 'src/libeis-event.c', 'src/libeis-fd.c', + 'src/libeis-keyboard.c', 'src/libeis-log.c', + 'src/libeis-pointer.c', 'src/libeis-region.c', 'src/libeis-seat.c', 'src/libeis-socket.c', + 'src/libeis-touchscreen.c', ) + [eis_proto_headers, eis_proto_sources] lib_libeis = shared_library('eis', diff --git a/proto/protocol.xml b/proto/protocol.xml index d4153b3..0f051f0 100644 --- a/proto/protocol.xml +++ b/proto/protocol.xml @@ -86,68 +86,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Provides the client with an object to initialize and setup the connection. @@ -208,77 +146,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -507,6 +374,21 @@ + + + + + + + + + + + + + + + Notification that the initial burst of events is complete and @@ -532,5 +414,187 @@ + + + + + + + + Notification that the client is no longer interested in this pointer. + The EIS implementation will release any resources related to this pointer and + send the ei_pointer.destroyed event once complete. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This pointer has been removed and a client should release all + associated resources. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Notification that the client is no longer interested in this keyboard. + The EIS implementation will release any resources related to this keyboard and + send the ei_keyboard.destroyed event once complete. + + + + + + + + + + + + + + + + This keyboard has been removed and a client should release all + associated resources. + + + + + + + + + + + + + + + + + + + + + + + Notification that the client is no longer interested in this touch. + The EIS implementation will release any resources related to this touch and + send the ei_touch.destroyed event once complete. + + + + + + + + + + + + + + + + + + + + + + This touch has been removed and a client should release all + associated resources. + + + + + + + + + + + + + + + + + + + diff --git a/src/libei-device.c b/src/libei-device.c index c429cd5..70bc616 100644 --- a/src/libei-device.c +++ b/src/libei-device.c @@ -83,6 +83,9 @@ ei_device_destroy(struct ei_device *device) list_remove(&device->link); ei_keymap_unref(device->keymap); + ei_pointer_unref(device->pointer); + ei_touchscreen_unref(device->touchscreen); + ei_keyboard_unref(device->keyboard); ei_seat_unref(seat); free(device->name); } @@ -179,7 +182,6 @@ handle_msg_keymap(struct ei_device *device, uint32_t keymap_type, uint32_t keyma return 0; } - static int handle_msg_done(struct ei_device *device) { @@ -282,6 +284,39 @@ handle_msg_frame(struct ei_device *device, uint32_t time, uint32_t micros) return 0; } +static int +handle_msg_pointer(struct ei_device *device, uint32_t id, uint32_t version) +{ + if (device->pointer) + return -EPROTO; + + device->pointer = ei_pointer_new(device, id, version); + + return 0; +} + +static int +handle_msg_keyboard(struct ei_device *device, uint32_t id, uint32_t version) +{ + if (device->keyboard) + return -EPROTO; + + device->keyboard = ei_keyboard_new(device, id, version); + + return 0; +} + +static int +handle_msg_touchscreen(struct ei_device *device, uint32_t id, uint32_t version) +{ + if (device->touchscreen) + return -EPROTO; + + device->touchscreen = ei_touchscreen_new(device, id, version); + + return 0; +} + static const struct ei_device_interface interface = { .destroyed = handle_msg_destroy, .name = handle_msg_name, @@ -296,6 +331,9 @@ static const struct ei_device_interface interface = { .start_emulating = handle_msg_start_emulating, .stop_emulating = handle_msg_stop_emulating, .frame = handle_msg_frame, + .pointer = handle_msg_pointer, + .keyboard = handle_msg_keyboard, + .touchscreen = handle_msg_touchscreen, }; const struct ei_device_interface * @@ -304,6 +342,210 @@ ei_device_get_interface(struct ei_device *device) return &interface; } +static int +handle_msg_pointer_rel(struct ei_pointer *pointer, float x, float y) +{ + struct ei_device *device = ei_pointer_get_device(pointer); + + DISCONNECT_IF_SENDER_CONTEXT(device); + + return ei_device_event_pointer_rel(device, x, y); +} + +static int +handle_msg_pointer_abs(struct ei_pointer *pointer, float x, float y) +{ + struct ei_device *device = ei_pointer_get_device(pointer); + + DISCONNECT_IF_SENDER_CONTEXT(device); + + return ei_device_event_pointer_abs(device, x, y); +} + +static int +handle_msg_pointer_button(struct ei_pointer *pointer, + uint32_t button, uint32_t state) +{ + struct ei_device *device = ei_pointer_get_device(pointer); + + DISCONNECT_IF_SENDER_CONTEXT(device); + + return ei_device_event_pointer_button(device, button, !!state); +} + +static int +handle_msg_pointer_scroll(struct ei_pointer *pointer, float x, float y) +{ + struct ei_device *device = ei_pointer_get_device(pointer); + + DISCONNECT_IF_SENDER_CONTEXT(device); + + return ei_device_event_pointer_scroll(device, x, y); +} + +static int +handle_msg_pointer_scroll_discrete(struct ei_pointer *pointer, + int32_t x, int32_t y) +{ + struct ei_device *device = ei_pointer_get_device(pointer); + + DISCONNECT_IF_SENDER_CONTEXT(device); + + return ei_device_event_pointer_scroll_discrete(device, x, y); +} + +static int +handle_msg_pointer_scroll_stop(struct ei_pointer *pointer, + uint32_t x, uint32_t y, uint32_t is_cancel) +{ + struct ei_device *device = ei_pointer_get_device(pointer); + + DISCONNECT_IF_SENDER_CONTEXT(device); + + if (is_cancel) + return ei_device_event_pointer_scroll_cancel(device, !!x, !!y); + else + return ei_device_event_pointer_scroll_stop(device, !!x, !!y); + + return -EINVAL; +} + +static int +handle_msg_pointer_destroy(struct ei_pointer *pointer) +{ + struct ei_device *device = ei_pointer_get_device(pointer); + ei_pointer_unref(steal(&device->pointer)); + + return 0; +} + +static const struct ei_pointer_interface pointer_interface = { + .destroyed = handle_msg_pointer_destroy, + .motion_relative = handle_msg_pointer_rel, + .motion_absolute = handle_msg_pointer_abs, + .button = handle_msg_pointer_button, + .scroll = handle_msg_pointer_scroll, + .scroll_stop = handle_msg_pointer_scroll_stop, + .scroll_discrete = handle_msg_pointer_scroll_discrete, +}; + +const struct ei_pointer_interface * +ei_device_get_pointer_interface(struct ei_device *device) +{ + return &pointer_interface; +} + +static int +handle_msg_keyboard_key(struct ei_keyboard *keyboard, uint32_t key, uint32_t state) +{ + struct ei_device *device = ei_keyboard_get_device(keyboard); + + DISCONNECT_IF_SENDER_CONTEXT(device); + + return ei_device_event_keyboard_key(device, key, !!state); +} + +static int +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 -EPROTO; + } + + struct ei_xkb_modifiers mods = { + .depressed = depressed, + .latched = latched, + .locked = locked, + .group = group, + }; + + ei_queue_keyboard_modifiers_event(device, &mods); + + return 0; +} + +static int +handle_msg_keyboard_destroy(struct ei_keyboard *keyboard) +{ + + struct ei_device *device = ei_keyboard_get_device(keyboard); + ei_keyboard_unref(steal(&device->keyboard)); + + return 0; +} + +static const struct ei_keyboard_interface keyboard_interface = { + .destroyed = handle_msg_keyboard_destroy, + .key = handle_msg_keyboard_key, + .modifiers = handle_msg_keyboard_modifiers, +}; + +const struct ei_keyboard_interface * +ei_device_get_keyboard_interface(struct ei_device *device) +{ + return &keyboard_interface; +} + +static int +handle_msg_touch_down(struct ei_touchscreen *touchscreen, + uint32_t touchid, float x, float y) +{ + struct ei_device *device = ei_touchscreen_get_device(touchscreen); + + DISCONNECT_IF_SENDER_CONTEXT(device); + + return ei_device_event_touch_down(device, touchid, x, y); +} + +static int +handle_msg_touch_motion(struct ei_touchscreen *touchscreen, + uint32_t touchid, float x, float y) +{ + struct ei_device *device = ei_touchscreen_get_device(touchscreen); + + DISCONNECT_IF_SENDER_CONTEXT(device); + + return ei_device_event_touch_motion(device, touchid, x, y); +} + +static int +handle_msg_touch_up(struct ei_touchscreen *touchscreen, uint32_t touchid) +{ + struct ei_device *device = ei_touchscreen_get_device(touchscreen); + + DISCONNECT_IF_SENDER_CONTEXT(device); + + return ei_device_event_touch_up(device, touchid); +} + +static int +handle_msg_touchscreen_destroy(struct ei_touchscreen *touchscreen) +{ + + struct ei_device *device = ei_touchscreen_get_device(touchscreen); + ei_touchscreen_unref(steal(&device->touchscreen)); + + return 0; +} + +static const struct ei_touchscreen_interface touchscreen_interface = { + .destroyed = handle_msg_touchscreen_destroy, + .down = handle_msg_touch_down, + .motion = handle_msg_touch_motion, + .up = handle_msg_touch_up, +}; + +const struct ei_touchscreen_interface * +ei_device_get_touchscreen_interface(struct ei_device *device) +{ + return &touchscreen_interface; +} + struct ei_device * ei_device_new(struct ei_seat *seat, uint32_t deviceid, uint32_t version) { @@ -437,6 +679,13 @@ ei_device_send_release(struct ei_device *device) if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) return 0; + if (device->pointer) + ei_pointer_request_release(device->pointer); + if (device->keyboard) + ei_keyboard_request_release(device->keyboard); + if (device->touchscreen) + ei_touchscreen_request_release(device->touchscreen); + int rc = ei_device_request_release(device); if (rc) ei_disconnect(ei); @@ -480,6 +729,14 @@ ei_device_removed_by_server(struct ei_device *device) case EI_DEVICE_STATE_PAUSED: case EI_DEVICE_STATE_RESUMED: case EI_DEVICE_STATE_EMULATING: + /* in the case of ei_disconnect() we may fake the + * removal by the server, so we need to also remove the + * pointer/keyboard/touch interfaces + */ + ei_pointer_unref(steal(&device->pointer)); + ei_keyboard_unref(steal(&device->keyboard)); + ei_touchscreen_unref(steal(&device->touchscreen)); + ei_unregister_object(ei, &device->proto_object); ei_queue_device_removed_event(device); ei_device_set_state(device, EI_DEVICE_STATE_DEAD); @@ -617,6 +874,131 @@ ei_device_get_region(struct ei_device *device, size_t index) return list_nth_entry(struct ei_region, &device->regions, link, index); } +static inline void +ei_device_resume_scrolling(struct ei_device *device, double x, double y) +{ + if (x) { + device->scroll.x_is_stopped = false; + device->scroll.x_is_cancelled = false; + } + if (y) { + device->scroll.y_is_stopped = false; + device->scroll.y_is_cancelled = false; + } +} + +static int +ei_send_pointer_rel(struct ei_device *device, double x, double y) +{ + struct ei *ei = ei_device_get_context(device); + + if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) + return 0; + + device->send_frame_event = true; + + int rc = ei_pointer_request_motion_relative(device->pointer, x, y); + if (rc) + ei_disconnect(ei); + return rc; +} + +static int +ei_send_pointer_abs(struct ei_device *device, double x, double y) +{ + struct ei *ei = ei_device_get_context(device); + + if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) + return 0; + + device->send_frame_event = true; + + int rc = ei_pointer_request_motion_absolute(device->pointer, x, y); + if (rc) + ei_disconnect(ei); + return rc; +} + +static int +ei_send_pointer_button(struct ei_device *device, uint32_t button, bool is_press) +{ + struct ei *ei = ei_device_get_context(device); + + if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) + return 0; + + device->send_frame_event = true; + + int rc = ei_pointer_request_button(device->pointer, button, is_press); + if (rc) + ei_disconnect(ei); + return rc; +} + +static int +ei_send_pointer_scroll(struct ei_device *device, double x, double y) +{ + struct ei *ei = ei_device_get_context(device); + + if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) + return 0; + + device->send_frame_event = true; + + int rc = ei_pointer_request_scroll(device->pointer, x, y); + if (rc) + ei_disconnect(ei); + return rc; +} + +static int +ei_send_pointer_scroll_stop(struct ei_device *device, double x, double y) +{ + struct ei *ei = ei_device_get_context(device); + + if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) + return 0; + + device->send_frame_event = true; + + int rc = ei_pointer_request_scroll_stop(device->pointer, x, y, false); + if (rc) + ei_disconnect(ei); + return rc; +} + +static int +ei_send_pointer_scroll_cancel(struct ei_device *device, double x, double y) +{ + struct ei *ei = ei_device_get_context(device); + + if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) + return 0; + + device->send_frame_event = true; + + int rc = ei_pointer_request_scroll_stop(device->pointer, x, y, true); + if (rc) + ei_disconnect(ei); + return rc; +} + +static int +ei_send_pointer_scroll_discrete(struct ei_device *device, int32_t x, int32_t y) +{ + struct ei *ei = ei_device_get_context(device); + + if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) + return 0; + + device->send_frame_event = true; + + int rc = ei_pointer_request_scroll_discrete(device->pointer, x, y); + if (rc) + ei_disconnect(ei); + return rc; +} + _public_ void ei_device_pointer_motion(struct ei_device *device, double x, double y) @@ -698,19 +1080,6 @@ ei_device_pointer_button(struct ei_device *device, ei_send_pointer_button(device, button, is_press); } -static inline void -ei_device_resume_scrolling(struct ei_device *device, double x, double y) -{ - if (x) { - device->scroll.x_is_stopped = false; - device->scroll.x_is_cancelled = false; - } - if (y) { - device->scroll.y_is_stopped = false; - device->scroll.y_is_cancelled = false; - } -} - _public_ void ei_device_pointer_scroll(struct ei_device *device, double x, double y) @@ -732,6 +1101,7 @@ ei_device_pointer_scroll(struct ei_device *device, ei_send_pointer_scroll(device, x, y); } + _public_ void ei_device_pointer_scroll_stop(struct ei_device *device, bool x, bool y) { @@ -817,6 +1187,23 @@ ei_device_pointer_scroll_discrete(struct ei_device *device, ei_send_pointer_scroll_discrete(device, x, y); } +static int +ei_send_keyboard_key(struct ei_device *device, uint32_t key, bool is_press) +{ + struct ei *ei = ei_device_get_context(device); + + if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) + return 0; + + device->send_frame_event = true; + + int rc = ei_keyboard_request_key(device->keyboard, key, is_press); + if (rc) + ei_disconnect(ei); + return rc; +} + + _public_ void ei_device_keyboard_key(struct ei_device *device, uint32_t key, bool is_press) @@ -862,6 +1249,57 @@ ei_touch_destroy(struct ei_touch *touch) static OBJECT_IMPLEMENT_CREATE(ei_touch); +static int +ei_send_touch_down(struct ei_device *device, uint32_t tid, + double x, double y) +{ + struct ei *ei = ei_device_get_context(device); + + if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) + return 0; + + device->send_frame_event = true; + + int rc = ei_touchscreen_request_down(device->touchscreen, tid, x, y); + if (rc) + ei_disconnect(ei); + return rc; +} + +static int +ei_send_touch_motion(struct ei_device *device, uint32_t tid, + double x, double y) +{ + struct ei *ei = ei_device_get_context(device); + + if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) + return 0; + + device->send_frame_event = true; + + int rc = ei_touchscreen_request_motion(device->touchscreen, tid, x, y); + if (rc) + ei_disconnect(ei); + return rc; +} + +static int +ei_send_touch_up(struct ei_device *device, uint32_t tid) +{ + struct ei *ei = ei_device_get_context(device); + + if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) + return 0; + + device->send_frame_event = true; + + int rc = ei_touchscreen_request_up(device->touchscreen, tid); + if (rc) + ei_disconnect(ei); + return rc; +} + + _public_ struct ei_touch * ei_device_touch_new(struct ei_device *device) { diff --git a/src/libei-device.h b/src/libei-device.h index 82ca242..a9a684c 100644 --- a/src/libei-device.h +++ b/src/libei-device.h @@ -29,6 +29,9 @@ #include "util-object.h" #include "util-list.h" #include "brei-shared.h" +#include "libei-pointer.h" +#include "libei-keyboard.h" +#include "libei-touchscreen.h" enum ei_device_state { /* Before the DeviceAddedDone was received */ @@ -56,6 +59,10 @@ struct ei_device { void *user_data; struct brei_object proto_object; + struct ei_pointer *pointer; + struct ei_keyboard *keyboard; + struct ei_touchscreen *touchscreen; + struct list link; uint32_t id; /* FIXME: remove this one */ enum ei_device_state state; @@ -106,6 +113,9 @@ struct ei_touch { OBJECT_DECLARE_GETTER(ei_device, id, uint32_t); OBJECT_DECLARE_GETTER(ei_device, proto_object, const struct brei_object *); OBJECT_DECLARE_GETTER(ei_device, interface, const struct ei_device_interface *); +OBJECT_DECLARE_GETTER(ei_device, pointer_interface, const struct ei_pointer_interface *); +OBJECT_DECLARE_GETTER(ei_device, keyboard_interface, const struct ei_keyboard_interface *); +OBJECT_DECLARE_GETTER(ei_device, touchscreen_interface, const struct ei_touchscreen_interface *); OBJECT_DECLARE_SETTER(ei_device, type, enum ei_device_type); OBJECT_DECLARE_SETTER(ei_device, name, const char*); OBJECT_DECLARE_SETTER(ei_device, seat, const char*); diff --git a/src/libei-keyboard.c b/src/libei-keyboard.c new file mode 100644 index 0000000..073f4a3 --- /dev/null +++ b/src/libei-keyboard.c @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 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 keyboard WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include +#include + +#include "util-bits.h" +#include "util-macros.h" +#include "util-mem.h" +#include "util-io.h" +#include "util-strings.h" +#include "util-version.h" + +#include "libei-private.h" +#include "ei-proto.h" + +static void +ei_keyboard_destroy(struct ei_keyboard *keyboard) +{ + struct ei *ei = ei_keyboard_get_context(keyboard); + ei_unregister_object(ei, &keyboard->proto_object); +} + +OBJECT_IMPLEMENT_REF(ei_keyboard); +OBJECT_IMPLEMENT_UNREF_CLEANUP(ei_keyboard); + +static +OBJECT_IMPLEMENT_CREATE(ei_keyboard); +static +OBJECT_IMPLEMENT_PARENT(ei_keyboard, ei_device); +OBJECT_IMPLEMENT_GETTER_AS_REF(ei_keyboard, proto_object, const struct brei_object*); + +struct ei_device * +ei_keyboard_get_device(struct ei_keyboard *keyboard) +{ + return ei_keyboard_parent(keyboard); +} + +struct ei* +ei_keyboard_get_context(struct ei_keyboard *keyboard) +{ + return ei_device_get_context(ei_keyboard_get_device(keyboard)); +} + +const struct ei_keyboard_interface * +ei_keyboard_get_interface(struct ei_keyboard *keyboard) { + struct ei_device *device = ei_keyboard_get_device(keyboard); + return ei_device_get_keyboard_interface(device); +} + +struct ei_keyboard * +ei_keyboard_new(struct ei_device *device, uint32_t id, uint32_t version) +{ + struct ei_keyboard *keyboard = ei_keyboard_create(&device->object); + struct ei *ei = ei_device_get_context(device); + + keyboard->proto_object.id = id; + keyboard->proto_object.implementation = keyboard; + keyboard->proto_object.interface = &ei_keyboard_proto_interface; + keyboard->proto_object.version = version; + ei_register_object(ei, &keyboard->proto_object); + + return keyboard; /* ref owned by caller */ +} diff --git a/src/libei-keyboard.h b/src/libei-keyboard.h new file mode 100644 index 0000000..fda0996 --- /dev/null +++ b/src/libei-keyboard.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 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 keyboard WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include "util-object.h" +#include "util-list.h" +#include "brei-shared.h" + +struct ei; +struct ei_device; +struct ei_keyboard; + +/* This is a protocol-only object, not exposed in the API */ +struct ei_keyboard { + struct object object; + struct brei_object proto_object; +}; + +OBJECT_DECLARE_GETTER(ei_keyboard, context, struct ei*); +OBJECT_DECLARE_GETTER(ei_keyboard, device, struct ei_device*); +OBJECT_DECLARE_GETTER(ei_keyboard, proto_object, const struct brei_object*); +OBJECT_DECLARE_GETTER(ei_keyboard, interface, const struct ei_keyboard_interface *); +OBJECT_DECLARE_REF(ei_keyboard); +OBJECT_DECLARE_UNREF(ei_keyboard); + +struct ei_keyboard * +ei_keyboard_new(struct ei_device *device, uint32_t id, uint32_t version); diff --git a/src/libei-pointer.c b/src/libei-pointer.c new file mode 100644 index 0000000..5080a25 --- /dev/null +++ b/src/libei-pointer.c @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 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 pointer WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include +#include + +#include "util-bits.h" +#include "util-macros.h" +#include "util-mem.h" +#include "util-io.h" +#include "util-strings.h" +#include "util-version.h" + +#include "libei-private.h" +#include "ei-proto.h" + +static void +ei_pointer_destroy(struct ei_pointer *pointer) +{ + struct ei *ei = ei_pointer_get_context(pointer); + ei_unregister_object(ei, &pointer->proto_object); +} + +OBJECT_IMPLEMENT_REF(ei_pointer); +OBJECT_IMPLEMENT_UNREF_CLEANUP(ei_pointer); + +static +OBJECT_IMPLEMENT_CREATE(ei_pointer); +static +OBJECT_IMPLEMENT_PARENT(ei_pointer, ei_device); +OBJECT_IMPLEMENT_GETTER_AS_REF(ei_pointer, proto_object, const struct brei_object*); + +struct ei_device * +ei_pointer_get_device(struct ei_pointer *pointer) +{ + return ei_pointer_parent(pointer); +} + +struct ei* +ei_pointer_get_context(struct ei_pointer *pointer) +{ + return ei_device_get_context(ei_pointer_get_device(pointer)); +} + +const struct ei_pointer_interface * +ei_pointer_get_interface(struct ei_pointer *pointer) { + struct ei_device *device = ei_pointer_get_device(pointer); + return ei_device_get_pointer_interface(device); +} + +struct ei_pointer * +ei_pointer_new(struct ei_device *device, uint32_t id, uint32_t version) +{ + struct ei_pointer *pointer = ei_pointer_create(&device->object); + struct ei *ei = ei_device_get_context(device); + + pointer->proto_object.id = id; + pointer->proto_object.implementation = pointer; + pointer->proto_object.interface = &ei_pointer_proto_interface; + pointer->proto_object.version = version; + ei_register_object(ei, &pointer->proto_object); + + return pointer; /* ref owned by caller */ +} diff --git a/src/libei-pointer.h b/src/libei-pointer.h new file mode 100644 index 0000000..4ea0fe0 --- /dev/null +++ b/src/libei-pointer.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 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 pointer WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include "util-object.h" +#include "util-list.h" +#include "brei-shared.h" + +struct ei; +struct ei_device; +struct ei_pointer; + +/* This is a protocol-only object, not exposed in the API */ +struct ei_pointer { + struct object object; + struct brei_object proto_object; +}; + +OBJECT_DECLARE_GETTER(ei_pointer, context, struct ei*); +OBJECT_DECLARE_GETTER(ei_pointer, device, struct ei_device*); +OBJECT_DECLARE_GETTER(ei_pointer, proto_object, const struct brei_object*); +OBJECT_DECLARE_GETTER(ei_pointer, interface, const struct ei_pointer_interface *); +OBJECT_DECLARE_REF(ei_pointer); +OBJECT_DECLARE_UNREF(ei_pointer); + +struct ei_pointer * +ei_pointer_new(struct ei_device *device, uint32_t id, uint32_t version); diff --git a/src/libei-private.h b/src/libei-private.h index 8fe604c..5810e7e 100644 --- a/src/libei-private.h +++ b/src/libei-private.h @@ -40,8 +40,11 @@ #include "libei-connection-setup.h" #include "libei-seat.h" #include "libei-device.h" +#include "libei-keyboard.h" #include "libei-event.h" +#include "libei-pointer.h" #include "libei-region.h" +#include "libei-touchscreen.h" struct ei_backend_interface { void (*destroy)(struct ei *ei, void *backend); @@ -153,6 +156,10 @@ ei_queue_pointer_button_event(struct ei_device *device, uint32_t button, bool is void ei_queue_keyboard_key_event(struct ei_device *device, uint32_t key, bool is_press); +void +ei_queue_keyboard_modifiers_event(struct ei_device *device, + const struct ei_xkb_modifiers *mods); + void ei_queue_pointer_scroll_event(struct ei_device *device, double x, double y); @@ -176,43 +183,6 @@ ei_queue_touch_motion_event(struct ei_device *device, uint32_t touchid, void ei_queue_touch_up_event(struct ei_device *device, uint32_t touchid); -int -ei_send_pointer_rel(struct ei_device *device, - double x, double y); - -int -ei_send_pointer_abs(struct ei_device *device, - double x, double y); - -int -ei_send_pointer_button(struct ei_device *device, - uint32_t button, bool is_press); - -int -ei_send_pointer_scroll(struct ei_device *device, - double x, double y); -int -ei_send_pointer_scroll_stop(struct ei_device *device, double x, double y); - -int -ei_send_pointer_scroll_cancel(struct ei_device *device, double x, double y); - -int -ei_send_pointer_scroll_discrete(struct ei_device *device, - int32_t x, int32_t y); - -int -ei_send_keyboard_key(struct ei_device *device, - uint32_t key, bool is_press); - -int -ei_send_touch_down(struct ei_device *device, uint32_t tid, - double x, double y); -int -ei_send_touch_motion(struct ei_device *device, uint32_t tid, - double x, double y); -int -ei_send_touch_up(struct ei_device *device, uint32_t tid); _printf_(6, 7) void ei_log_msg(struct ei *ei, diff --git a/src/libei-touchscreen.c b/src/libei-touchscreen.c new file mode 100644 index 0000000..ffbd047 --- /dev/null +++ b/src/libei-touchscreen.c @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 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 touchscreen WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include +#include + +#include "util-bits.h" +#include "util-macros.h" +#include "util-mem.h" +#include "util-io.h" +#include "util-strings.h" +#include "util-version.h" + +#include "libei-private.h" +#include "ei-proto.h" + +static void +ei_touchscreen_destroy(struct ei_touchscreen *touchscreen) +{ + struct ei *ei = ei_touchscreen_get_context(touchscreen); + ei_unregister_object(ei, &touchscreen->proto_object); +} + +OBJECT_IMPLEMENT_REF(ei_touchscreen); +OBJECT_IMPLEMENT_UNREF_CLEANUP(ei_touchscreen); + +static +OBJECT_IMPLEMENT_CREATE(ei_touchscreen); +static +OBJECT_IMPLEMENT_PARENT(ei_touchscreen, ei_device); +OBJECT_IMPLEMENT_GETTER_AS_REF(ei_touchscreen, proto_object, const struct brei_object*); + +struct ei_device * +ei_touchscreen_get_device(struct ei_touchscreen *touchscreen) +{ + return ei_touchscreen_parent(touchscreen); +} + +struct ei* +ei_touchscreen_get_context(struct ei_touchscreen *touchscreen) +{ + return ei_device_get_context(ei_touchscreen_get_device(touchscreen)); +} + +const struct ei_touchscreen_interface * +ei_touchscreen_get_interface(struct ei_touchscreen *touchscreen) { + struct ei_device *device = ei_touchscreen_get_device(touchscreen); + return ei_device_get_touchscreen_interface(device); +} + +struct ei_touchscreen * +ei_touchscreen_new(struct ei_device *device, uint32_t id, uint32_t version) +{ + struct ei_touchscreen *touchscreen = ei_touchscreen_create(&device->object); + struct ei *ei = ei_device_get_context(device); + + touchscreen->proto_object.id = id; + touchscreen->proto_object.implementation = touchscreen; + touchscreen->proto_object.interface = &ei_touchscreen_proto_interface; + touchscreen->proto_object.version = version; + ei_register_object(ei, &touchscreen->proto_object); + + return touchscreen; /* ref owned by caller */ +} diff --git a/src/libei-touchscreen.h b/src/libei-touchscreen.h new file mode 100644 index 0000000..5fdc56c --- /dev/null +++ b/src/libei-touchscreen.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 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 touch WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include "util-object.h" +#include "util-list.h" +#include "brei-shared.h" + +struct ei; +struct ei_device; +struct ei_touchscreen; + +/* This is a protocol-only object, not exposed in the API */ +struct ei_touchscreen { + struct object object; + struct brei_object proto_object; +}; + +OBJECT_DECLARE_GETTER(ei_touchscreen, context, struct ei*); +OBJECT_DECLARE_GETTER(ei_touchscreen, device, struct ei_device*); +OBJECT_DECLARE_GETTER(ei_touchscreen, proto_object, const struct brei_object*); +OBJECT_DECLARE_GETTER(ei_touchscreen, interface, const struct ei_touchscreen_interface *); +OBJECT_DECLARE_REF(ei_touchscreen); +OBJECT_DECLARE_UNREF(ei_touchscreen); + +struct ei_touchscreen * +ei_touchscreen_new(struct ei_device *device, uint32_t id, uint32_t version); diff --git a/src/libei.c b/src/libei.c index 9b9ec4b..4d99c65 100644 --- a/src/libei.c +++ b/src/libei.c @@ -50,20 +50,6 @@ _Static_assert(sizeof(enum ei_keymap_type) == sizeof(int), "Invalid enum size"); _Static_assert(sizeof(enum ei_event_type) == sizeof(int), "Invalid enum size"); _Static_assert(sizeof(enum ei_log_priority) == sizeof(int), "Invalid enum size"); -static struct ei_device * -ei_find_device(struct ei *ei, uint32_t deviceid) -{ - struct ei_seat *seat; - - list_for_each(seat, &ei->seats, link) { - struct ei_device *device = ei_seat_find_device(seat, deviceid); - if (device) - return device; - } - - return NULL; -} - static void ei_destroy(struct ei *ei) { @@ -376,9 +362,9 @@ ei_queue_device_resumed_event(struct ei_device *device) queue_event(ei, e); } -static void -queue_keyboard_modifiers_event(struct ei_device *device, - const struct ei_xkb_modifiers *mods) +void +ei_queue_keyboard_modifiers_event(struct ei_device *device, + const struct ei_xkb_modifiers *mods) { struct ei *ei= ei_device_get_context(device); struct ei_event *e = ei_event_new_for_device(device); @@ -621,210 +607,6 @@ ei_insert_device_removed_event(struct ei_device *device) insert_device_removed_event(device); } -static int -handle_msg_keyboard_modifiers(struct ei_connection *connection, uint32_t deviceid, - uint32_t depressed, uint32_t locked, - uint32_t latched, uint32_t group) -{ - struct ei *ei = ei_connection_get_context(connection); - - log_debug(ei, "Setting modifiers for %#x", deviceid); - - struct ei_device *device = ei_find_device(ei, deviceid); - if (!device) - return 0; - - if (!ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD)) { - log_bug(ei,"Modifier event for non-keyboard"); - return -EPROTO; - } - - struct ei_xkb_modifiers mods = { - .depressed = depressed, - .latched = latched, - .locked = locked, - .group = group, - }; - queue_keyboard_modifiers_event(device, &mods); - - return 0; -} - -int -ei_send_pointer_rel(struct ei_device *device, double x, double y) -{ - struct ei *ei = ei_device_get_context(device); - - if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) - return 0; - - device->send_frame_event = true; - - int rc = ei_connection_request_pointer_relative(ei->connection, device->id, x, y); - if (rc) - ei_disconnect(ei); - return rc; -} - -int -ei_send_pointer_abs(struct ei_device *device, double x, double y) -{ - struct ei *ei = ei_device_get_context(device); - - if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) - return 0; - - device->send_frame_event = true; - - int rc = ei_connection_request_pointer_absolute(ei->connection, device->id, x, y); - if (rc) - ei_disconnect(ei); - return rc; -} - -int -ei_send_pointer_button(struct ei_device *device, uint32_t button, bool is_press) -{ - struct ei *ei = ei_device_get_context(device); - - if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) - return 0; - - device->send_frame_event = true; - - int rc = ei_connection_request_pointer_button(ei->connection, device->id, button, is_press); - if (rc) - ei_disconnect(ei); - return rc; -} - -int ei_send_pointer_scroll(struct ei_device *device, double x, double y) -{ - struct ei *ei = ei_device_get_context(device); - - if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) - return 0; - - device->send_frame_event = true; - - int rc = ei_connection_request_pointer_scroll(ei->connection, device->id, x, y); - if (rc) - ei_disconnect(ei); - return rc; -} - -int ei_send_pointer_scroll_stop(struct ei_device *device, double x, double y) -{ - struct ei *ei = ei_device_get_context(device); - - if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) - return 0; - - device->send_frame_event = true; - - int rc = ei_connection_request_pointer_scroll_stop(ei->connection, device->id, x, y, false); - if (rc) - ei_disconnect(ei); - return rc; -} - -int ei_send_pointer_scroll_cancel(struct ei_device *device, double x, double y) -{ - struct ei *ei = ei_device_get_context(device); - - if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) - return 0; - - device->send_frame_event = true; - - int rc = ei_connection_request_pointer_scroll_stop(ei->connection, device->id, x, y, true); - if (rc) - ei_disconnect(ei); - return rc; -} - - -int ei_send_pointer_scroll_discrete(struct ei_device *device, int32_t x, int32_t y) -{ - struct ei *ei = ei_device_get_context(device); - - if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) - return 0; - - device->send_frame_event = true; - - int rc = ei_connection_request_pointer_scroll_discrete(ei->connection, device->id, x, y); - if (rc) - ei_disconnect(ei); - return rc; -} - -int -ei_send_keyboard_key(struct ei_device *device, uint32_t key, bool is_press) -{ - struct ei *ei = ei_device_get_context(device); - - if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) - return 0; - - device->send_frame_event = true; - - int rc = ei_connection_request_keyboard_key(ei->connection, device->id, key, is_press); - if (rc) - ei_disconnect(ei); - return rc; -} - -int -ei_send_touch_down(struct ei_device *device, uint32_t tid, - double x, double y) -{ - struct ei *ei = ei_device_get_context(device); - - if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) - return 0; - - device->send_frame_event = true; - - int rc = ei_connection_request_touch_down(ei->connection, device->id, tid, x, y); - if (rc) - ei_disconnect(ei); - return rc; -} - -int -ei_send_touch_motion(struct ei_device *device, uint32_t tid, - double x, double y) -{ - struct ei *ei = ei_device_get_context(device); - - if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) - return 0; - - device->send_frame_event = true; - - int rc = ei_connection_request_touch_motion(ei->connection, device->id, tid, x, y); - if (rc) - ei_disconnect(ei); - return rc; -} - -int -ei_send_touch_up(struct ei_device *device, uint32_t tid) -{ - struct ei *ei = ei_device_get_context(device); - - if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED) - return 0; - - device->send_frame_event = true; - - int rc = ei_connection_request_touch_up(ei->connection, device->id, tid); - if (rc) - ei_disconnect(ei); - return rc; -} - _public_ struct ei_event* ei_get_event(struct ei *ei) { @@ -866,166 +648,6 @@ static int handle_msg_disconnected(struct ei_connection *connection, uint32_t re } \ } while(0) -static int -handle_msg_pointer_rel(struct ei_connection *connection, uint32_t deviceid, float x, float y) -{ - struct ei *ei = ei_connection_get_context(connection); - - DISCONNECT_IF_SENDER_CONTEXT(ei); - - struct ei_device *device = ei_find_device(ei, deviceid); - - if (device) - return ei_device_event_pointer_rel(device, x, y); - - return -EINVAL; -} - -static int -handle_msg_pointer_abs(struct ei_connection *connection, uint32_t deviceid, float x, float y) -{ - struct ei *ei = ei_connection_get_context(connection); - - DISCONNECT_IF_SENDER_CONTEXT(ei); - - struct ei_device *device = ei_find_device(ei, deviceid); - - if (device) - return ei_device_event_pointer_abs(device, x, y); - - return -EINVAL; -} - -static int -handle_msg_pointer_button(struct ei_connection *connection, uint32_t deviceid, - uint32_t button, uint32_t state) -{ - struct ei *ei = ei_connection_get_context(connection); - - DISCONNECT_IF_SENDER_CONTEXT(ei); - - struct ei_device *device = ei_find_device(ei, deviceid); - - if (device) - return ei_device_event_pointer_button(device, button, !!state); - - return -EINVAL; -} - -static int -handle_msg_pointer_scroll(struct ei_connection *connection, uint32_t deviceid, float x, float y) -{ - struct ei *ei = ei_connection_get_context(connection); - - DISCONNECT_IF_SENDER_CONTEXT(ei); - - struct ei_device *device = ei_find_device(ei, deviceid); - - if (device) - return ei_device_event_pointer_scroll(device, x, y); - - return -EINVAL; -} - -static int -handle_msg_pointer_scroll_discrete(struct ei_connection *connection, uint32_t deviceid, - int32_t x, int32_t y) -{ - struct ei *ei = ei_connection_get_context(connection); - - DISCONNECT_IF_SENDER_CONTEXT(ei); - - struct ei_device *device = ei_find_device(ei, deviceid); - - if (device) - return ei_device_event_pointer_scroll_discrete(device, x, y); - - return -EINVAL; -} - -static int -handle_msg_pointer_scroll_stop(struct ei_connection *connection, uint32_t deviceid, - uint32_t x, uint32_t y, uint32_t is_cancel) -{ - struct ei *ei = ei_connection_get_context(connection); - - DISCONNECT_IF_SENDER_CONTEXT(ei); - - struct ei_device *device = ei_find_device(ei, deviceid); - - if (device) { - if (is_cancel) - return ei_device_event_pointer_scroll_cancel(device, !!x, !!y); - else - return ei_device_event_pointer_scroll_stop(device, !!x, !!y); - } - - return -EINVAL; -} - -static int -handle_msg_keyboard_key(struct ei_connection *connection, uint32_t deviceid, - uint32_t key, uint32_t state) -{ - struct ei *ei = ei_connection_get_context(connection); - - DISCONNECT_IF_SENDER_CONTEXT(ei); - - struct ei_device *device = ei_find_device(ei, deviceid); - - if (device) - return ei_device_event_keyboard_key(device, key, !!state); - - return -EINVAL; -} - -static int -handle_msg_touch_down(struct ei_connection *connection, uint32_t deviceid, - uint32_t touchid, float x, float y) -{ - struct ei *ei = ei_connection_get_context(connection); - - DISCONNECT_IF_SENDER_CONTEXT(ei); - - struct ei_device *device = ei_find_device(ei, deviceid); - - if (device) - return ei_device_event_touch_down(device, touchid, x, y); - - return -EINVAL; -} - -static int -handle_msg_touch_motion(struct ei_connection *connection, uint32_t deviceid, - uint32_t touchid, float x, float y) -{ - struct ei *ei = ei_connection_get_context(connection); - - DISCONNECT_IF_SENDER_CONTEXT(ei); - - struct ei_device *device = ei_find_device(ei, deviceid); - - if (device) - return ei_device_event_touch_motion(device, touchid, x, y); - - return -EINVAL; -} - -static int -handle_msg_touch_up(struct ei_connection *connection, uint32_t deviceid, uint32_t touchid) -{ - struct ei *ei = ei_connection_get_context(connection); - - DISCONNECT_IF_SENDER_CONTEXT(ei); - - struct ei_device *device = ei_find_device(ei, deviceid); - - if (device) - return ei_device_event_touch_up(device, touchid); - - return -EINVAL; -} - static void connected(struct ei_connection *connection, void *user_data) { @@ -1055,6 +677,9 @@ handle_msg_connection_setup(struct ei_connection *connection, uint32_t new_id, u ei_connection_setup_request_interface(setup, "ei_callback", VERSION_V(1)); ei_connection_setup_request_interface(setup, "ei_seat", VERSION_V(1)); ei_connection_setup_request_interface(setup, "ei_device", VERSION_V(1)); + ei_connection_setup_request_interface(setup, "ei_pointer", VERSION_V(1)); + ei_connection_setup_request_interface(setup, "ei_keyboard", VERSION_V(1)); + ei_connection_setup_request_interface(setup, "ei_touchscreen", VERSION_V(1)); } ei_connection_setup_request_done(setup); ei_connection_setup_unref(setup); @@ -1080,19 +705,6 @@ static const struct ei_connection_interface intf_state_connected = { .connection_setup = NULL, /* EPROTO */ .disconnected = handle_msg_disconnected, .seat = handle_msg_seat, - .keyboard_modifiers = handle_msg_keyboard_modifiers, - - /* events */ - .pointer_relative = handle_msg_pointer_rel, - .pointer_absolute = handle_msg_pointer_abs, - .pointer_button = handle_msg_pointer_button, - .pointer_scroll = handle_msg_pointer_scroll, - .pointer_scroll_stop = handle_msg_pointer_scroll_stop, - .pointer_scroll_discrete = handle_msg_pointer_scroll_discrete, - .keyboard_key = handle_msg_keyboard_key, - .touch_down = handle_msg_touch_down, - .touch_motion = handle_msg_touch_motion, - .touch_up = handle_msg_touch_up, }; static const struct ei_connection_interface *interfaces[] = { diff --git a/src/libeis-client.c b/src/libeis-client.c index a6f4baa..a221a65 100644 --- a/src/libeis-client.c +++ b/src/libeis-client.c @@ -141,22 +141,6 @@ eis_client_has_capability(struct eis_client *client, return false; } -static struct eis_device * -eis_client_find_device(struct eis_client *client, uint32_t deviceid) -{ - struct eis_seat *seat; - - list_for_each(seat, &client->seats, link) { - struct eis_device *device; - - list_for_each(device, &seat->devices, link) { - if (device->id == deviceid) - return device; - } - } - return NULL; -} - int eis_client_send_message(struct eis_client *client, const struct brei_object *object, uint32_t opcode, const char *signature, size_t nargs, ...) @@ -202,15 +186,6 @@ client_send_seat_added(struct eis_client *client, struct eis_seat *seat) eis_seat_get_version(seat)); } -static int -client_send_keyboard_modifiers(struct eis_client *client, struct eis_device *device, - const struct eis_xkb_modifiers *mods) -{ - return eis_connection_event_keyboard_modifiers(client->connection, device->id, - mods->depressed, mods->locked, - mods->latched, mods->group); -} - _public_ void eis_client_connect(struct eis_client *client) { @@ -282,169 +257,6 @@ eis_client_setup_done(struct eis_client *client, const char *name, bool is_sende } \ } while(0) -static int -client_msg_pointer_rel(struct eis_connection *connection, uint32_t deviceid, - float x, float y) -{ - struct eis_client *client = eis_connection_get_client(connection); - - DISCONNECT_IF_RECEIVER_CONTEXT(client); - - struct eis_device *device = eis_client_find_device(client, deviceid); - - if (device) - return eis_device_event_pointer_rel(device, x, y); - - return -EINVAL; -} - -static int -client_msg_pointer_abs(struct eis_connection *connection, uint32_t deviceid, - float x, float y) -{ - struct eis_client *client = eis_connection_get_client(connection); - - DISCONNECT_IF_RECEIVER_CONTEXT(client); - - struct eis_device *device = eis_client_find_device(client, deviceid); - - if (device) - return eis_device_event_pointer_abs(device, x, y); - - return -EINVAL; -} - -static int -client_msg_pointer_button(struct eis_connection *connection, uint32_t deviceid, - uint32_t button, uint32_t state) -{ - struct eis_client *client = eis_connection_get_client(connection); - - DISCONNECT_IF_RECEIVER_CONTEXT(client); - - struct eis_device *device = eis_client_find_device(client, deviceid); - - if (device) - return eis_device_event_pointer_button(device, button, !!state); - - return -EINVAL; -} - -static int -client_msg_pointer_scroll(struct eis_connection *connection, uint32_t deviceid, - float x, float y) -{ - struct eis_client *client = eis_connection_get_client(connection); - - DISCONNECT_IF_RECEIVER_CONTEXT(client); - - struct eis_device *device = eis_client_find_device(client, deviceid); - - if (device) - return eis_device_event_pointer_scroll(device, x, y); - - return -EINVAL; -} - -static int -client_msg_pointer_scroll_discrete(struct eis_connection *connection, uint32_t deviceid, - int32_t x, int32_t y) -{ - struct eis_client *client = eis_connection_get_client(connection); - - DISCONNECT_IF_RECEIVER_CONTEXT(client); - - struct eis_device *device = eis_client_find_device(client, deviceid); - - if (device) - return eis_device_event_pointer_scroll_discrete(device, x, y); - - return -EINVAL; -} - -static int -client_msg_pointer_scroll_stop(struct eis_connection *connection, uint32_t deviceid, - uint32_t x, uint32_t y, uint32_t is_cancel) -{ - struct eis_client *client = eis_connection_get_client(connection); - - DISCONNECT_IF_RECEIVER_CONTEXT(client); - - struct eis_device *device = eis_client_find_device(client, deviceid); - - if (device) { - if (is_cancel) - return eis_device_event_pointer_scroll_cancel(device, !!x, !!y); - else - return eis_device_event_pointer_scroll_stop(device, !!x, !!y); - } - - return -EINVAL; -} - -static int -client_msg_keyboard_key(struct eis_connection *connection, uint32_t deviceid, - uint32_t key, uint32_t state) -{ - struct eis_client *client = eis_connection_get_client(connection); - - DISCONNECT_IF_RECEIVER_CONTEXT(client); - - struct eis_device *device = eis_client_find_device(client, deviceid); - - if (device) - return eis_device_event_keyboard_key(device, key, !!state); - - return -EINVAL; -} - -static int -client_msg_touch_down(struct eis_connection *connection, uint32_t deviceid, - uint32_t touchid, float x, float y) -{ - struct eis_client *client = eis_connection_get_client(connection); - - DISCONNECT_IF_RECEIVER_CONTEXT(client); - - struct eis_device *device = eis_client_find_device(client, deviceid); - - if (device) - return eis_device_event_touch_down(device, touchid, x, y); - - return -EINVAL; -} - -static int -client_msg_touch_motion(struct eis_connection *connection, uint32_t deviceid, - uint32_t touchid, float x, float y) -{ - struct eis_client *client = eis_connection_get_client(connection); - - DISCONNECT_IF_RECEIVER_CONTEXT(client); - - struct eis_device *device = eis_client_find_device(client, deviceid); - - if (device) - return eis_device_event_touch_motion(device, touchid, x, y); - - return -EINVAL; -} - -static int -client_msg_touch_up(struct eis_connection *connection, uint32_t deviceid, uint32_t touchid) -{ - struct eis_client *client = eis_connection_get_client(connection); - - DISCONNECT_IF_RECEIVER_CONTEXT(client); - - struct eis_device *device = eis_client_find_device(client, deviceid); - - if (device) - return eis_device_event_touch_up(device, touchid); - - return -EINVAL; -} - static int client_msg_disconnect(struct eis_connection *connection) { @@ -481,18 +293,6 @@ static const struct eis_connection_interface intf_state_connecting = { static const struct eis_connection_interface intf_state_connected = { .sync = client_msg_sync, .disconnect = client_msg_disconnect, - - /* events */ - .pointer_relative = client_msg_pointer_rel, - .pointer_absolute = client_msg_pointer_abs, - .pointer_button = client_msg_pointer_button, - .pointer_scroll = client_msg_pointer_scroll, - .pointer_scroll_stop = client_msg_pointer_scroll_stop, - .pointer_scroll_discrete = client_msg_pointer_scroll_discrete, - .keyboard_key = client_msg_keyboard_key, - .touch_down = client_msg_touch_down, - .touch_motion = client_msg_touch_motion, - .touch_up = client_msg_touch_up, }; static const struct eis_connection_interface *interfaces[] = { @@ -578,6 +378,9 @@ eis_client_new(struct eis *eis, int fd) .ei_callback = VERSION_V(1), .ei_seat = VERSION_V(1), .ei_device = VERSION_V(1), + .ei_pointer = VERSION_V(1), + .ei_keyboard = VERSION_V(1), + .ei_touchscreen = VERSION_V(1), }; client->connection = eis_connection_new(client); @@ -621,18 +424,3 @@ eis_client_add_seat(struct eis_client *client, struct eis_seat *seat) list_append(&client->seats, &seat->link); client_send_seat_added(client, seat); } - -void -eis_client_keyboard_modifiers(struct eis_client *client, struct eis_device *device, - uint32_t depressed, uint32_t latched, uint32_t locked, - uint32_t group) -{ - struct eis_xkb_modifiers mods = { - .depressed = depressed, - .locked = locked, - .latched = latched, - .group = group, - }; - client_send_keyboard_modifiers(client, device, &mods); -} - diff --git a/src/libeis-client.h b/src/libeis-client.h index 1d92426..62df1d3 100644 --- a/src/libeis-client.h +++ b/src/libeis-client.h @@ -43,6 +43,9 @@ struct eis_client_interface_versions { uint32_t ei_callback; uint32_t ei_seat; uint32_t ei_device; + uint32_t ei_pointer; + uint32_t ei_keyboard; + uint32_t ei_touchscreen; }; struct eis_client { diff --git a/src/libeis-connection-setup.c b/src/libeis-connection-setup.c index 900c6c8..b2dabcb 100644 --- a/src/libeis-connection-setup.c +++ b/src/libeis-connection-setup.c @@ -135,6 +135,9 @@ client_msg_interface(struct eis_connection_setup *setup, const char *name, uint3 VERSION_ENTRY(ei_connection_setup), VERSION_ENTRY(ei_seat), VERSION_ENTRY(ei_device), + VERSION_ENTRY(ei_pointer), + VERSION_ENTRY(ei_keyboard), + VERSION_ENTRY(ei_touchscreen), #undef VERSION_ENTRY }; diff --git a/src/libeis-device.c b/src/libeis-device.c index 9a46c61..fa2e9e0 100644 --- a/src/libeis-device.c +++ b/src/libeis-device.c @@ -150,6 +150,10 @@ eis_device_destroy(struct eis_device *device) eis_event_unref(event); } + eis_pointer_unref(device->pointer); + eis_touchscreen_unref(device->touchscreen); + eis_keyboard_unref(device->keyboard); + free(device->name); } @@ -281,6 +285,179 @@ eis_device_get_interface(struct eis_device *device) return &interface; } +static int +client_msg_pointer_rel(struct eis_pointer *pointer, float x, float y) +{ + struct eis_device *device = eis_pointer_get_device(pointer); + + DISCONNECT_IF_RECEIVER_CONTEXT(device); + + return eis_device_event_pointer_rel(device, x, y); +} + +static int +client_msg_pointer_abs(struct eis_pointer *pointer, float x, float y) +{ + struct eis_device *device = eis_pointer_get_device(pointer); + + DISCONNECT_IF_RECEIVER_CONTEXT(device); + + return eis_device_event_pointer_abs(device, x, y); +} + +static int +client_msg_pointer_button(struct eis_pointer *pointer, uint32_t button, uint32_t state) +{ + struct eis_device *device = eis_pointer_get_device(pointer); + + DISCONNECT_IF_RECEIVER_CONTEXT(device); + + return eis_device_event_pointer_button(device, button, !!state); +} + +static int +client_msg_pointer_scroll(struct eis_pointer *pointer, float x, float y) +{ + struct eis_device *device = eis_pointer_get_device(pointer); + + DISCONNECT_IF_RECEIVER_CONTEXT(device); + + return eis_device_event_pointer_scroll(device, x, y); +} + +static int +client_msg_pointer_scroll_discrete(struct eis_pointer *pointer, int32_t x, int32_t y) +{ + struct eis_device *device = eis_pointer_get_device(pointer); + + DISCONNECT_IF_RECEIVER_CONTEXT(device); + + return eis_device_event_pointer_scroll_discrete(device, x, y); +} + +static int +client_msg_pointer_scroll_stop(struct eis_pointer *pointer, + uint32_t x, uint32_t y, uint32_t is_cancel) +{ + struct eis_device *device = eis_pointer_get_device(pointer); + + DISCONNECT_IF_RECEIVER_CONTEXT(device); + + if (is_cancel) + return eis_device_event_pointer_scroll_cancel(device, !!x, !!y); + else + return eis_device_event_pointer_scroll_stop(device, !!x, !!y); +} + +static int +client_msg_pointer_release(struct eis_pointer *pointer) +{ + struct eis_device *device = eis_pointer_get_device(pointer); + eis_pointer_event_destroyed(device->pointer); + eis_pointer_unref(steal(&device->pointer)); + return 0; +} + +static const struct eis_pointer_interface pointer_interface = { + .release = client_msg_pointer_release, + .motion_relative = client_msg_pointer_rel, + .motion_absolute = client_msg_pointer_abs, + .button = client_msg_pointer_button, + .scroll = client_msg_pointer_scroll, + .scroll_discrete = client_msg_pointer_scroll_discrete, + .scroll_stop = client_msg_pointer_scroll_stop, +}; + +const struct eis_pointer_interface * +eis_device_get_pointer_interface(struct eis_device *device) +{ + return &pointer_interface; +} + +static int +client_msg_keyboard_key(struct eis_keyboard *keyboard, uint32_t key, uint32_t state) +{ + struct eis_device *device = eis_keyboard_get_device(keyboard); + + DISCONNECT_IF_RECEIVER_CONTEXT(device); + + return eis_device_event_keyboard_key(device, key, !!state); +} + +static int +client_msg_keyboard_release(struct eis_keyboard *keyboard) +{ + struct eis_device *device = eis_keyboard_get_device(keyboard); + eis_keyboard_event_destroyed(device->keyboard); + eis_keyboard_unref(steal(&device->keyboard)); + return 0; +} + +static const struct eis_keyboard_interface keyboard_interface = { + .release = client_msg_keyboard_release, + .key = client_msg_keyboard_key, +}; + +const struct eis_keyboard_interface * +eis_device_get_keyboard_interface(struct eis_device *device) +{ + return &keyboard_interface; +} + +static int +client_msg_touch_down(struct eis_touchscreen *touchscreen, + uint32_t touchid, float x, float y) +{ + struct eis_device *device = eis_touchscreen_get_device(touchscreen); + + DISCONNECT_IF_RECEIVER_CONTEXT(device); + + return eis_device_event_touch_down(device, touchid, x, y); +} + +static int +client_msg_touch_motion(struct eis_touchscreen *touchscreen, + uint32_t touchid, float x, float y) +{ + struct eis_device *device = eis_touchscreen_get_device(touchscreen); + + DISCONNECT_IF_RECEIVER_CONTEXT(device); + + return eis_device_event_touch_motion(device, touchid, x, y); +} + +static int +client_msg_touch_up(struct eis_touchscreen *touchscreen, uint32_t touchid) +{ + struct eis_device *device = eis_touchscreen_get_device(touchscreen); + + DISCONNECT_IF_RECEIVER_CONTEXT(device); + + return eis_device_event_touch_up(device, touchid); +} + +static int +client_msg_touchscreen_release(struct eis_touchscreen *touchscreen) +{ + struct eis_device *device = eis_touchscreen_get_device(touchscreen); + eis_touchscreen_event_destroyed(device->touchscreen); + eis_touchscreen_unref(steal(&device->touchscreen)); + return 0; +} + +static const struct eis_touchscreen_interface touchscreen_interface = { + .release = client_msg_touchscreen_release, + .down = client_msg_touch_down, + .motion = client_msg_touch_motion, + .up = client_msg_touch_up, +}; + +const struct eis_touchscreen_interface * +eis_device_get_touchscreen_interface(struct eis_device *device) +{ + return &touchscreen_interface; +} + _public_ struct eis_device * eis_seat_new_device(struct eis_seat *seat) { @@ -408,17 +585,40 @@ eis_device_add(struct eis_device *device) goto out; } } - - if (device->keymap) { - rc = eis_device_event_keymap(device, device->keymap->type, device->keymap->size, device->keymap->fd); + if (eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER) || + eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE)) { + device->pointer = eis_pointer_new(device); + rc = eis_device_event_pointer(device, eis_pointer_get_id(device->pointer), + eis_pointer_get_version(device->pointer)); if (rc < 0) goto out; } + if (eis_device_has_capability(device, EIS_DEVICE_CAP_KEYBOARD)) { + device->keyboard = eis_keyboard_new(device); + rc = eis_device_event_keyboard(device, eis_keyboard_get_id(device->keyboard), + eis_keyboard_get_version(device->keyboard)); + if (rc < 0) + goto out; + + if (device->keymap) + rc = eis_device_event_keymap(device, device->keymap->type, device->keymap->size, device->keymap->fd); + if (rc < 0) + goto out; + } + if (eis_device_has_capability(device, EIS_DEVICE_CAP_TOUCH)) { + device->touchscreen = eis_touchscreen_new(device); + rc = eis_device_event_touchscreen(device, eis_touchscreen_get_id(device->touchscreen), + eis_touchscreen_get_version(device->touchscreen)); + if (rc < 0) + goto out; + } + rc = eis_device_event_done(device); - if (rc < 0) - goto out; out: - /* FIXME: check rc */ + if (rc < 0) { + log_error(eis_client_get_context(client), "Failed to add device, disconnecting client\n"); + eis_client_disconnect(client); + } return; } @@ -434,8 +634,22 @@ eis_device_remove(struct eis_device *device) !eis_client_is_sender(eis_device_get_client(device))) eis_device_stop_emulating(device); + if (device->pointer) { + eis_pointer_event_destroyed(device->pointer); + eis_pointer_unref(steal(&device->pointer)); + } + if (device->touchscreen) { + eis_touchscreen_event_destroyed(device->touchscreen); + eis_touchscreen_unref(steal(&device->touchscreen)); + } + if (device->keyboard) { + eis_keyboard_event_destroyed(device->keyboard); + eis_keyboard_unref(steal(&device->keyboard)); + } + if (device->state != EIS_DEVICE_STATE_NEW) eis_device_event_destroyed(device); + device->state = EIS_DEVICE_STATE_DEAD; eis_client_unregister_object(client, &device->proto_object); list_remove(&device->link); @@ -456,16 +670,6 @@ eis_device_has_capability(struct eis_device *device, return false; } -#define handle_request_noargs(device_, func_) { \ - struct eis_client *client = eis_device_get_client(device); \ - eis_connection_event_##func_(client->connection, device->id); \ -} - -#define handle_request(device_, func_, ...) { \ - struct eis_client *client = eis_device_get_client(device); \ - eis_connection_event_##func_(client->connection, device->id, __VA_ARGS__); \ -} - static void eis_device_frame_now(struct eis_device *device) { @@ -526,7 +730,7 @@ eis_device_pointer_motion(struct eis_device *device, device->send_frame_event = true; - handle_request(device, pointer_relative, x, y); + eis_pointer_event_motion_relative(device->pointer, x, y); } _public_ void @@ -551,7 +755,7 @@ eis_device_pointer_motion_absolute(struct eis_device *device, device->send_frame_event = true; - handle_request(device, pointer_absolute, x, y); + eis_pointer_event_motion_absolute(device->pointer, x, y); } _public_ void @@ -577,7 +781,7 @@ eis_device_pointer_button(struct eis_device *device, device->send_frame_event = true; - handle_request(device, pointer_button, button, is_press); + eis_pointer_event_button(device->pointer, button, is_press); } static inline void @@ -610,7 +814,7 @@ eis_device_pointer_scroll(struct eis_device *device, device->send_frame_event = true; - handle_request(device, pointer_scroll, x, y); + eis_pointer_event_scroll(device->pointer, x, y); } _public_ void @@ -637,7 +841,7 @@ eis_device_pointer_scroll_stop(struct eis_device *device, bool x, bool y) if (x || y) { device->send_frame_event = true; - handle_request(device, pointer_scroll_stop, x, y, false); + eis_pointer_event_scroll_stop(device->pointer, x, y, false); } } @@ -669,7 +873,7 @@ eis_device_pointer_scroll_cancel(struct eis_device *device, bool x, bool y) if (x || y) { device->send_frame_event = true; - handle_request(device, pointer_scroll_stop, x, y, true); + eis_pointer_event_scroll_stop(device->pointer, x, y, true); } } @@ -690,7 +894,7 @@ eis_device_pointer_scroll_discrete(struct eis_device *device, device->send_frame_event = true; - handle_request(device, pointer_scroll_discrete, x, y); + eis_pointer_event_scroll_discrete(device->pointer, x, y); } _public_ void @@ -708,10 +912,9 @@ eis_device_keyboard_key(struct eis_device *device, device->send_frame_event = true; - handle_request(device, keyboard_key, key, is_press); + eis_keyboard_event_key(device->keyboard, key, is_press); } - _public_ OBJECT_IMPLEMENT_REF(eis_touch); _public_ @@ -777,7 +980,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); + eis_touchscreen_event_down(device->touchscreen, touch->tracking_id, x, y); } _public_ void @@ -799,7 +1002,7 @@ 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); + eis_touchscreen_event_motion(device->touchscreen, touch->tracking_id, x, y); } _public_ void @@ -816,7 +1019,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); + eis_touchscreen_event_up(device->touchscreen, touch->tracking_id); } _public_ void @@ -1095,6 +1298,5 @@ eis_device_keyboard_send_xkb_modifiers(struct eis_device *device, uint32_t depre return; } - eis_client_keyboard_modifiers(eis_device_get_client(device), - device, depressed, latched, locked, group); + eis_keyboard_event_modifiers(device->keyboard, depressed, locked, latched, group); } diff --git a/src/libeis-device.h b/src/libeis-device.h index f722af2..b08d16c 100644 --- a/src/libeis-device.h +++ b/src/libeis-device.h @@ -45,6 +45,10 @@ struct eis_device { struct brei_object proto_object; + struct eis_pointer *pointer; + struct eis_keyboard *keyboard; + struct eis_touchscreen *touchscreen; + uint32_t id; char *name; enum eis_device_state state; @@ -105,6 +109,9 @@ OBJECT_DECLARE_GETTER(eis_device, id, uint32_t); OBJECT_DECLARE_GETTER(eis_device, context, struct eis *); OBJECT_DECLARE_GETTER(eis_device, proto_object, const struct brei_object *); OBJECT_DECLARE_GETTER(eis_device, interface, const struct eis_device_interface *); +OBJECT_DECLARE_GETTER(eis_device, pointer_interface, const struct eis_pointer_interface *); +OBJECT_DECLARE_GETTER(eis_device, keyboard_interface, const struct eis_keyboard_interface *); +OBJECT_DECLARE_GETTER(eis_device, touchscreen_interface, const struct eis_touchscreen_interface *); void eis_device_set_client_keymap(struct eis_device *device, diff --git a/src/libeis-keyboard.c b/src/libeis-keyboard.c new file mode 100644 index 0000000..45ddcae --- /dev/null +++ b/src/libeis-keyboard.c @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 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 keyboard WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include +#include + +#include "util-bits.h" +#include "util-macros.h" +#include "util-mem.h" +#include "util-io.h" +#include "util-strings.h" +#include "util-version.h" + +#include "libeis-private.h" +#include "eis-proto.h" + +static void +eis_keyboard_destroy(struct eis_keyboard *keyboard) +{ + struct eis_client * client = eis_keyboard_get_client(keyboard); + eis_client_unregister_object(client, &keyboard->proto_object); +} + +OBJECT_IMPLEMENT_REF(eis_keyboard); +OBJECT_IMPLEMENT_UNREF_CLEANUP(eis_keyboard); +OBJECT_IMPLEMENT_GETTER_AS_REF(eis_keyboard, proto_object, const struct brei_object *); + +static +OBJECT_IMPLEMENT_CREATE(eis_keyboard); +static +OBJECT_IMPLEMENT_PARENT(eis_keyboard, eis_device); + +uint32_t +eis_keyboard_get_version(struct eis_keyboard *keyboard) +{ + return keyboard->proto_object.version; +} + +uint32_t +eis_keyboard_get_id(struct eis_keyboard *keyboard) +{ + return keyboard->proto_object.id; +} + +struct eis_device * +eis_keyboard_get_device(struct eis_keyboard *keyboard) +{ + return eis_keyboard_parent(keyboard); +} + +struct eis_client* +eis_keyboard_get_client(struct eis_keyboard *keyboard) +{ + return eis_device_get_client(eis_keyboard_get_device(keyboard)); +} + +struct eis* +eis_keyboard_get_context(struct eis_keyboard *keyboard) +{ + struct eis_client *client = eis_keyboard_get_client(keyboard); + return eis_client_get_context(client); +} + +const struct eis_keyboard_interface * +eis_keyboard_get_interface(struct eis_keyboard *keyboard) { + return eis_device_get_keyboard_interface(eis_keyboard_get_device(keyboard)); +} + +struct eis_keyboard * +eis_keyboard_new(struct eis_device *device) +{ + struct eis_keyboard *keyboard = eis_keyboard_create(&device->object); + struct eis_client *client = eis_device_get_client(device); + + keyboard->proto_object.id = eis_client_get_new_id(client); + keyboard->proto_object.implementation = keyboard; + keyboard->proto_object.interface = &eis_keyboard_proto_interface; + keyboard->proto_object.version = client->interface_versions.ei_keyboard; + list_init(&keyboard->proto_object.link); + + eis_client_register_object(client, &keyboard->proto_object); + + return keyboard; /* ref owned by caller */ +} diff --git a/src/libeis-keyboard.h b/src/libeis-keyboard.h new file mode 100644 index 0000000..43bbfa3 --- /dev/null +++ b/src/libeis-keyboard.h @@ -0,0 +1,51 @@ +/* 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 keyboard WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include "util-object.h" +#include "brei-shared.h" +#include "libeis-client.h" + +struct eis; +struct eis_client; + +/* This is a protocol-only object, not exposed in the API */ +struct eis_keyboard { + struct object object; + struct brei_object proto_object; +}; + +OBJECT_DECLARE_GETTER(eis_keyboard, context, struct eis *); +OBJECT_DECLARE_GETTER(eis_keyboard, device, struct eis_device *); +OBJECT_DECLARE_GETTER(eis_keyboard, client, struct eis_client *); +OBJECT_DECLARE_GETTER(eis_keyboard, id, uint32_t); +OBJECT_DECLARE_GETTER(eis_keyboard, version, uint32_t); +OBJECT_DECLARE_GETTER(eis_keyboard, proto_object, const struct brei_object *); +OBJECT_DECLARE_GETTER(eis_keyboard, interface, const struct eis_keyboard_interface *); +OBJECT_DECLARE_REF(eis_keyboard); +OBJECT_DECLARE_UNREF(eis_keyboard); + +struct eis_keyboard * +eis_keyboard_new(struct eis_device *device); diff --git a/src/libeis-pointer.c b/src/libeis-pointer.c new file mode 100644 index 0000000..71c5432 --- /dev/null +++ b/src/libeis-pointer.c @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 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 pointer WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include +#include + +#include "util-bits.h" +#include "util-macros.h" +#include "util-mem.h" +#include "util-io.h" +#include "util-strings.h" +#include "util-version.h" + +#include "libeis-private.h" +#include "eis-proto.h" + +static void +eis_pointer_destroy(struct eis_pointer *pointer) +{ + struct eis_client * client = eis_pointer_get_client(pointer); + eis_client_unregister_object(client, &pointer->proto_object); +} + +OBJECT_IMPLEMENT_REF(eis_pointer); +OBJECT_IMPLEMENT_UNREF_CLEANUP(eis_pointer); +OBJECT_IMPLEMENT_GETTER_AS_REF(eis_pointer, proto_object, const struct brei_object *); + +static +OBJECT_IMPLEMENT_CREATE(eis_pointer); +static +OBJECT_IMPLEMENT_PARENT(eis_pointer, eis_device); + +uint32_t +eis_pointer_get_version(struct eis_pointer *pointer) +{ + return pointer->proto_object.version; +} + +uint32_t +eis_pointer_get_id(struct eis_pointer *pointer) +{ + return pointer->proto_object.id; +} + +struct eis_device * +eis_pointer_get_device(struct eis_pointer *pointer) +{ + return eis_pointer_parent(pointer); +} + +struct eis_client* +eis_pointer_get_client(struct eis_pointer *pointer) +{ + return eis_device_get_client(eis_pointer_get_device(pointer)); +} + +struct eis* +eis_pointer_get_context(struct eis_pointer *pointer) +{ + struct eis_client *client = eis_pointer_get_client(pointer); + return eis_client_get_context(client); +} + +const struct eis_pointer_interface * +eis_pointer_get_interface(struct eis_pointer *pointer) { + return eis_device_get_pointer_interface(eis_pointer_get_device(pointer)); +} + +struct eis_pointer * +eis_pointer_new(struct eis_device *device) +{ + struct eis_pointer *pointer = eis_pointer_create(&device->object); + struct eis_client *client = eis_device_get_client(device); + + pointer->proto_object.id = eis_client_get_new_id(client); + pointer->proto_object.implementation = pointer; + pointer->proto_object.interface = &eis_pointer_proto_interface; + pointer->proto_object.version = client->interface_versions.ei_pointer; + list_init(&pointer->proto_object.link); + + eis_client_register_object(client, &pointer->proto_object); + + return pointer; /* ref owned by caller */ +} diff --git a/src/libeis-pointer.h b/src/libeis-pointer.h new file mode 100644 index 0000000..f57b3b4 --- /dev/null +++ b/src/libeis-pointer.h @@ -0,0 +1,51 @@ +/* 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 pointer WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include "util-object.h" +#include "brei-shared.h" +#include "libeis-client.h" + +struct eis; +struct eis_client; + +/* This is a protocol-only object, not exposed in the API */ +struct eis_pointer { + struct object object; + struct brei_object proto_object; +}; + +OBJECT_DECLARE_GETTER(eis_pointer, context, struct eis *); +OBJECT_DECLARE_GETTER(eis_pointer, device, struct eis_device *); +OBJECT_DECLARE_GETTER(eis_pointer, client, struct eis_client *); +OBJECT_DECLARE_GETTER(eis_pointer, id, uint32_t); +OBJECT_DECLARE_GETTER(eis_pointer, version, uint32_t); +OBJECT_DECLARE_GETTER(eis_pointer, proto_object, const struct brei_object *); +OBJECT_DECLARE_GETTER(eis_pointer, interface, const struct eis_pointer_interface *); +OBJECT_DECLARE_REF(eis_pointer); +OBJECT_DECLARE_UNREF(eis_pointer); + +struct eis_pointer * +eis_pointer_new(struct eis_device *device); diff --git a/src/libeis-private.h b/src/libeis-private.h index ed92e7e..9d4f251 100644 --- a/src/libeis-private.h +++ b/src/libeis-private.h @@ -41,8 +41,11 @@ #include "libeis-connection-setup.h" #include "libeis-device.h" #include "libeis-event.h" +#include "libeis-keyboard.h" +#include "libeis-pointer.h" #include "libeis-region.h" #include "libeis-seat.h" +#include "libeis-touchscreen.h" struct eis_backend_interface { void (*destroy)(struct eis *eis, void *backend); diff --git a/src/libeis-touchscreen.c b/src/libeis-touchscreen.c new file mode 100644 index 0000000..e1feb72 --- /dev/null +++ b/src/libeis-touchscreen.c @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 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 touchscreen WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include +#include + +#include "util-bits.h" +#include "util-macros.h" +#include "util-mem.h" +#include "util-io.h" +#include "util-strings.h" +#include "util-version.h" + +#include "libeis-private.h" +#include "eis-proto.h" + +static void +eis_touchscreen_destroy(struct eis_touchscreen *touchscreen) +{ + struct eis_client * client = eis_touchscreen_get_client(touchscreen); + eis_client_unregister_object(client, &touchscreen->proto_object); +} + +OBJECT_IMPLEMENT_REF(eis_touchscreen); +OBJECT_IMPLEMENT_UNREF_CLEANUP(eis_touchscreen); +OBJECT_IMPLEMENT_GETTER_AS_REF(eis_touchscreen, proto_object, const struct brei_object *); + +static +OBJECT_IMPLEMENT_CREATE(eis_touchscreen); +static +OBJECT_IMPLEMENT_PARENT(eis_touchscreen, eis_device); + +uint32_t +eis_touchscreen_get_version(struct eis_touchscreen *touchscreen) +{ + return touchscreen->proto_object.version; +} + +uint32_t +eis_touchscreen_get_id(struct eis_touchscreen *touchscreen) +{ + return touchscreen->proto_object.id; +} + +struct eis_device * +eis_touchscreen_get_device(struct eis_touchscreen *touchscreen) +{ + return eis_touchscreen_parent(touchscreen); +} + +struct eis_client* +eis_touchscreen_get_client(struct eis_touchscreen *touchscreen) +{ + return eis_device_get_client(eis_touchscreen_get_device(touchscreen)); +} + +struct eis* +eis_touchscreen_get_context(struct eis_touchscreen *touchscreen) +{ + struct eis_client *client = eis_touchscreen_get_client(touchscreen); + return eis_client_get_context(client); +} + +const struct eis_touchscreen_interface * +eis_touchscreen_get_interface(struct eis_touchscreen *touchscreen) { + return eis_device_get_touchscreen_interface(eis_touchscreen_get_device(touchscreen)); +} + +struct eis_touchscreen * +eis_touchscreen_new(struct eis_device *device) +{ + struct eis_touchscreen *touchscreen = eis_touchscreen_create(&device->object); + struct eis_client *client = eis_device_get_client(device); + + touchscreen->proto_object.id = eis_client_get_new_id(client); + touchscreen->proto_object.implementation = touchscreen; + touchscreen->proto_object.interface = &eis_touchscreen_proto_interface; + touchscreen->proto_object.version = client->interface_versions.ei_touchscreen; + list_init(&touchscreen->proto_object.link); + + eis_client_register_object(client, &touchscreen->proto_object); + + return touchscreen; /* ref owned by caller */ +} diff --git a/src/libeis-touchscreen.h b/src/libeis-touchscreen.h new file mode 100644 index 0000000..8e33dbb --- /dev/null +++ b/src/libeis-touchscreen.h @@ -0,0 +1,51 @@ +/* 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 touchscreen WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include "util-object.h" +#include "brei-shared.h" +#include "libeis-client.h" + +struct eis; +struct eis_client; + +/* This is a protocol-only object, not exposed in the API */ +struct eis_touchscreen { + struct object object; + struct brei_object proto_object; +}; + +OBJECT_DECLARE_GETTER(eis_touchscreen, context, struct eis *); +OBJECT_DECLARE_GETTER(eis_touchscreen, device, struct eis_device *); +OBJECT_DECLARE_GETTER(eis_touchscreen, client, struct eis_client *); +OBJECT_DECLARE_GETTER(eis_touchscreen, id, uint32_t); +OBJECT_DECLARE_GETTER(eis_touchscreen, version, uint32_t); +OBJECT_DECLARE_GETTER(eis_touchscreen, proto_object, const struct brei_object *); +OBJECT_DECLARE_GETTER(eis_touchscreen, interface, const struct eis_touchscreen_interface *); +OBJECT_DECLARE_REF(eis_touchscreen); +OBJECT_DECLARE_UNREF(eis_touchscreen); + +struct eis_touchscreen * +eis_touchscreen_new(struct eis_device *device);