/* 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. */ #pragma once #ifdef __cplusplus extern "C" { #endif #include <stdbool.h> #include <stdint.h> #include <stddef.h> /** * @addtogroup libei EI - The client API * * libei is the client-side module. This API should be used by processes * that need to emulate devices. * * libei clients come in "sender" and "receiver" modes, depending on whether * the client sends or receives events. A libeis context however may accept * both sender and receiver clients, the EIS implementation works as * corresponding receiver or sender for this client. It is up to the * implementation to disconnect clients that it does not want to allow. See * eis_client_is_sender() for details. * * @{ */ /** * @struct ei * * The main context to interact with libei. A libei context is a single * connection to an EIS implementation and may contain multiple devices, see * @ref ei_device. * * An @ref ei context is refcounted, see ei_unref(). */ struct ei; /** * @struct ei_device * * A single device to generate input events from. A device may have multiple * capabilities. For example, a single device may be a pointer and a keyboard * and a touch device. It is up to the EIS implementation on how to handle * this case, some implementations may split a single device up into * multiple virtual devices, others may not. * * An @ref ei_device is refcounted, see ei_device_unref(). */ struct ei_device; /** * @struct ei_seat * * A logical seat for a group of devices. Seats are provided by the EIS * implementation, devices may be added to a seat. The hierarchy of objects * looks like this: * <pre> * ei ---- ei_seat one ---- ei_device 1 * \ \ * \ --- ei device 2 * --- ei_seat two --- ei device 3 * </pre> */ struct ei_seat; /** * @struct ei_event * * An event received from the EIS implementation. See @ref ei_event_type * for the list of possible event types. * * An @ref ei_event is refcounted, see ei_event_unref(). */ struct ei_event; /** * @struct ei_keymap * * An keymap for a device with the @ref EI_DEVICE_CAP_KEYBOARD capability. * * An @ref ei_keymap is refcounted, see ei_keymap_unref(). */ struct ei_keymap; /** * @struct ei_region * * A rectangular region, defined by an x/y offset and a width and a height. * A region defines the area on an EIS desktop layout that is accessible by * this device - this region may not be the full area of the desktop. * Input events may only be sent for points within the regions. * * The use of regions is private to the EIS compositor and coordinates may not * match the size of the actual desktop. For example, a compositor may set a * 1920x1080 region to represent a 4K monitor and transparently map input * events into the respective true pixels. * * Absolute devices may have different regions, it is up to the libei client * to send events through the correct device to target the right pixel. For * example, a dual-head setup my have two absolute devices, the first with a * zero offset region spanning the first screen, the second with a nonzero * offset spanning the second screen. */ struct ei_region; /** * @enum ei_device_type * * The device type determines what the device represents. * * If the device type is @ref EI_DEVICE_TYPE_VIRTUAL, the device is a * virtual device representing input as applied on the EIS implementation's * screen. A relative virtual device generates input events in logical pixels, * an absolute virtual device generates input events in logical pixels on one * of the device's regions. Virtual devices do not have a size. * * If the device type is @ref EI_DEVICE_TYPE_PHYSICAL, the device is a * representation of a physical device as if connected to the EIS * implementation's host computer. A relative physical device generates input * events in mm, an absolute physical device generates input events in mm * within the device's specified physical size. Physical devices do not have * regions. * * @see ei_device_get_width * @see ei_device_get_height */ enum ei_device_type { … }; /** * @enum ei_device_capability * * The set of supported capabilities. A device may have zero or more * capabilities, a device with perceived zero capabilities is typically a * device with capabilities unsupported by the client. * * Capabilities are initialized by the EIS implementation but the client may * further reduce the requested capabilities, see ei_seat_confirm_capability(). * For example, a client may bind to a seat with the pointer and keyboard * capability but only the former is permitted by the EIS implementation. * Keyboard events sent through such a device will be treated as client bug * and discarded. * * See ei_device_has_capability(). * */ enum ei_device_capability { … }; /** * @enum ei_keymap_type * * The set of supported keymap types for a struct @ref ei_keymap. */ enum ei_keymap_type { … }; enum ei_event_type { … }; /** * This is an alias for @ref ei_new_sender. */ struct ei * ei_new(void *user_data); /** * Create a new sender ei context. The context is refcounted and must be * released with ei_unref(). * * A sender ei context sends events to the EIS implementation but cannot * receive events. * * A context supports exactly one backend, set up with one of * ei_setup_backend_socket() or ei_setup_backend_fd(). * * @param user_data An opaque pointer to be returned with ei_get_user_data() * * @see ei_set_user_data * @see ei_get_user_data * @see ei_setup_backend_fd * @see ei_setup_backend_socket */ struct ei * ei_new_sender(void *user_data); /** * Create a new receiver ei context. The context is refcounted and must be * released with ei_unref(). * * A receiver ei context receives events from the EIS implementation but cannot * send events. * * A context supports exactly one backend, set up with one of * ei_setup_backend_socket() or ei_setup_backend_fd(). * * @param user_data An opaque pointer to be returned with ei_get_user_data() * * @see ei_set_user_data * @see ei_get_user_data * @see ei_setup_backend_fd * @see ei_setup_backend_socket */ struct ei * ei_new_receiver(void *user_data); bool ei_is_sender(struct ei *ei); enum ei_log_priority { … }; struct ei_log_context; /** * @return the line number (``__LINE__``) for a given log message context. */ unsigned int ei_log_context_get_line(struct ei_log_context *ctx); /** * @return the file name (``__FILE__``) for a given log message context. */ const char * ei_log_context_get_file(struct ei_log_context *ctx); /** * @return the function name (``__func__``) for a given log message context. */ const char * ei_log_context_get_func(struct ei_log_context *ctx); /** * The log handler for library logging. This handler is only called for * messages with a log level equal or greater than than the one set in * ei_log_set_priority(). * * The context passed to this function contains auxilary information about * this log message such as the line number, file name and function name * this message occured in. The log context is valid only within the current * invocation of the log handler. * * @param ei The EI context * @param priority The log priority * @param message The log message as a null-terminated string * @param context A log message context for this message */ ei_log_handler; /** * Change the log handler for this context. If the log handler is NULL, the * built-in default log function is used. * * @param ei The EI context * @param log_handler The log handler or NULL to use the default log * handler. */ void ei_log_set_handler(struct ei *ei, ei_log_handler log_handler); void ei_log_set_priority(struct ei *ei, enum ei_log_priority priority); enum ei_log_priority ei_log_get_priority(const struct ei *ei); /** * Set the name for this client. This is a suggestion to the * server only and may not be honored. * * The client name may be used for display to the user, for example in * an authorization dialog that requires the user to approve a connection to * the EIS implementation. * * This function must be called immediately after ei_new() and before * setting up a backend with ei_setup_backend_socket() or * ei_setup_backend_fd(). */ void ei_configure_name(struct ei * ei, const char *name); /** * Set this ei context to use the socket backend. The ei context will * connect to the socket at the given path and initiate the conversation * with the EIS server listening on that socket. * * If @a socketpath is `NULL`, the value of the environment variable * `LIBEI_SOCKET` is used. If @a socketpath does not start with '/', it is * relative to `$XDG_RUNTIME_DIR`. If `XDG_RUNTIME_DIR` is not set, this * function fails. * * If the connection was successful, an event of type @ref EI_EVENT_CONNECT * or @ref EI_EVENT_DISCONNECT will become available after a future call to * ei_dispatch(). * * If the connection failed, use ei_unref() to release the data allocated * for this context. * * @return zero on success or a negative errno on failure */ int ei_setup_backend_socket(struct ei *ei, const char *socketpath); /** * Initialize the ei context on the given socket. The ei context will * initiate the conversation with the EIS server listening on the other end * of this socket. * * If the connection was successful, an event of type @ref EI_EVENT_CONNECT * or @ref EI_EVENT_DISCONNECT will become available after a future call to * ei_dispatch(). * * If the connection failed, use ei_unref() to release the data allocated * for this context. * * This function takes ownership of the file descriptor, and will close it * when tearing down. * * @return zero on success or a negative errno on failure */ int ei_setup_backend_fd(struct ei *ei, int fd); /** * Increase the refcount of this struct by one. Use ei_unref() to decrease * the refcount. * * @return the argument passed into the function */ struct ei * ei_ref(struct ei *ei); /** * Decrease the refcount of this struct by one. When the refcount reaches * zero, the context disconnects from the server and all allocated resources * are released. * * @return always NULL */ struct ei * ei_unref(struct ei *ei); /** * Set a custom data pointer for this context. libei will not look at or * modify the pointer. Use ei_get_user_data() to retrieve a previously set * user data. */ void ei_set_user_data(struct ei *ei, void *user_data); /** * Return the custom data pointer for this context. libei will not look at or * modify the pointer. Use ei_set_user_data() to change the user data. */ void * ei_get_user_data(struct ei *ei); /** * libei keeps a single file descriptor for all events. This fd should be * monitored for events by the caller's mainloop, e.g. using select(). When * events are available on this fd, call ei_dispatch() immediately to * process. */ int ei_get_fd(struct ei *ei); /** * Main event dispatching function. Reads events of the file descriptors * and processes them internally. Use ei_get_event() to retrieve the * events. * * Dispatching does not necessarily queue events. This function * should be called immediately once data is available on the file * descriptor returned by libei_get_fd(). */ void ei_dispatch(struct ei *ei); /** * Return the next event from the event queue, removing it from the queue. * * The returned object must be released by the caller with ei_event_unref() */ struct ei_event * ei_get_event(struct ei *ei); /** * Returns the next event in the internal event queue (or `NULL`) without * removing that event from the queue; the next call to ei_get_event() * will return that same event. * * This call is useful for checking whether there is an event and/or what * type of event it is. * * Repeated calls to ei_peek_event() return the same event. * * The returned event is refcounted, use ei_event_unref() to drop the * reference. * * A caller must not call ei_get_event() while holding a ref to an event * returned by ei_peek_event(). Doing so is undefined behavior. */ struct ei_event * ei_peek_event(struct ei *ei); /** * Release resources associated with this event. This function always * returns NULL. * * The caller cannot increase the refcount of an event. Events should be * considered transient data and not be held longer than required. * ei_event_unref() is provided for consistency (as opposed to, say, * ei_event_free()). */ struct ei_event * ei_event_unref(struct ei_event *event); const char * ei_seat_get_name(struct ei_seat *seat); /** * Return true if the capabilitiy is available on this seat or false * otherwise. The return value of this function is not affected by * ei_seat_confirm_capability(). */ bool ei_seat_has_capability(struct ei_seat *seat, enum ei_device_capability cap); /** * Bind this client to the given seat capability. Once bound, the server may * create devices for the requested capability and send the respective @ref * EI_EVENT_DEVICE_ADDED events. To undo, call ei_seat_unbind_capability(). * * Note that binding to a capability does not guarantee a device for that * capability becomes available. Devices may be added and removed at any time. * * It is an application bug to call this function for a capability already * bound - call ei_seat_unbind_capability() first. * * Calling this function for a capability that does not exist on the seat is * permitted (but obviously a noop) */ void ei_seat_bind_capability(struct ei_seat *seat, enum ei_device_capability cap); /** * Same as ei_seat_bind_capability() but takes multiple capabilities, * terminated by NULL. */ __attribute__((sentinel)) void ei_seat_bind_capabilities(struct ei_seat *seat, ...); /** * Unbind a seat's capability. This function indicates the the application is * no longer interested in devices with the given capability. * * If any devices with the given capability are present, libei automatically * calls ei_device_close() on those devices (and thus the server will send * @ref EI_EVENT_DEVICE_REMOVED for those devices). */ void ei_seat_unbind_capability(struct ei_seat *seat, enum ei_device_capability cap); /** * Same as ei_seat_unbind_capability() but takes multiple capabilities, terminated * by NULL. */ __attribute__((sentinel)) void ei_seat_unbind_capabilities(struct ei_seat *seat, ...); struct ei_seat * ei_seat_ref(struct ei_seat *seat); struct ei_seat * ei_seat_unref(struct ei_seat *seat); /** * Return the struct @ref ei context this seat is associated with. */ struct ei * ei_seat_get_context(struct ei_seat *seat); /** * @return the type of this event */ enum ei_event_type ei_event_get_type(struct ei_event *event); /** * Return the device from this event. * * For events of type @ref EI_EVENT_CONNECT and @ref EI_EVENT_DISCONNECT, * this function returns NULL. * * This does not increase the refcount of the device. Use eis_device_ref() * to keep a reference beyond the immediate scope. */ struct ei_device * ei_event_get_device(struct ei_event *event); /** * Return the time for the event of type @ref EI_EVENT_FRAME in microseconds. * * @note: Only events of type @ref EI_EVENT_FRAME carry a timestamp. For * convenience, the timestamp for other device events is retrofitted by this * library. * * @return the event time in microseconds */ uint64_t ei_event_get_time(struct ei_event *event); /** * For an event of type @ref EI_EVENT_KEYBOARD_MODIFIERS, get the * mask of currently logically pressed-down modifiers. * See ei_device_get_keymap() for the corresponding keymap. */ uint32_t ei_event_keyboard_get_xkb_mods_depressed(struct ei_event *event); /** * For an event of type @ref EI_EVENT_KEYBOARD_MODIFIERS, get the * mask of currently logically latched modifiers. * See ei_device_get_keymap() for the corresponding keymap. */ uint32_t ei_event_keyboard_get_xkb_mods_latched(struct ei_event *event); /** * For an event of type @ref EI_EVENT_KEYBOARD_MODIFIERS, get the * mask of currently logically locked modifiers. * See ei_device_get_keymap() for the corresponding keymap. */ uint32_t ei_event_keyboard_get_xkb_mods_locked(struct ei_event *event); /** * For an event of type @ref EI_EVENT_KEYBOARD_MODIFIERS, get the * logical group state. * See ei_device_get_keymap() for the corresponding keymap. */ uint32_t ei_event_keyboard_get_xkb_group(struct ei_event *event); /** * Increase the refcount of this struct by one. Use ei_device_unref() to * decrease the refcount. * * @return the argument passed into the function */ struct ei_device * ei_device_ref(struct ei_device *device); /** * Decrease the refcount of this struct by one. When the refcount reaches * zero, the context disconnects from the server and all allocated resources * are released. * * @return always NULL */ struct ei_device * ei_device_unref(struct ei_device *device); struct ei_seat * ei_device_get_seat(struct ei_device *device); /** * Set a custom data pointer for this context. libei will not look at or * modify the pointer. Use ei_seat_get_user_data() to retrieve a * previously set user data. */ void ei_seat_set_user_data(struct ei_seat *seat, void *user_data); /** * Return the custom data pointer for this context. libei will not look at or * modify the pointer. Use ei_seat_get_user_data() to change the user data. */ void * ei_seat_get_user_data(struct ei_seat *seat); /** * Set a custom data pointer for this context. libei will not look at or * modify the pointer. Use ei_device_get_user_data() to retrieve a * previously set user data. */ void ei_device_set_user_data(struct ei_device *device, void *user_data); /** * Return the custom data pointer for this context. libei will not look at or * modify the pointer. Use ei_device_get_user_data() to change the user data. */ void * ei_device_get_user_data(struct ei_device *device); /** * Return the width of the device in mm if the device is of type @ref * EI_DEVICE_TYPE_PHYSICAL, otherwise zero. */ uint32_t ei_device_get_width(struct ei_device *device); /** * Return the height of the device in mm if the device is of type @ref * EI_DEVICE_TYPE_PHYSICAL, otherwise zero. */ uint32_t ei_device_get_height(struct ei_device *device); struct ei_keymap * ei_device_get_keymap(struct ei_device *device); /** * @return the size of the keymap in bytes */ size_t ei_keymap_get_size(struct ei_keymap *keymap); /** * Returns the type for this keymap. The type specifies how to interpret the * data at the file descriptor returned by ei_keymap_get_fd(). */ enum ei_keymap_type ei_keymap_get_type(struct ei_keymap *keymap); /** * Return a memmap-able file descriptor pointing to the keymap used by the * device. The keymap is constant for the lifetime of the device and * assigned to this device individually. */ int ei_keymap_get_fd(struct ei_keymap *keymap); /** * Return the device this keymap belongs to, or `NULL` if it has not yet * been assigned to a device. * * After processing and if the server changed the keymap or set the keymap * to NULL, this keymap may no longer be in use by the device and future * calls to this function return `NULL`. */ struct ei_device * ei_keymap_get_device(struct ei_keymap *keymap); /** * Increase the refcount of this struct by one. Use ei_keymap_unref() to * decrease the refcount. * * @return the argument passed into the function */ struct ei_keymap * ei_keymap_ref(struct ei_keymap *keymap); /** * Decrease the refcount of this struct by one. When the refcount reaches * zero, the context disconnects from the server and all allocated resources * are released. * * @return always NULL */ struct ei_keymap * ei_keymap_unref(struct ei_keymap *keymap); void ei_keymap_set_user_data(struct ei_keymap *keymap, void *user_data); void * ei_keymap_get_user_data(struct ei_keymap *keymap); /** * Notify the server that the client is no longer interested in * this device. * * Due to the asynchronous nature of the client-server interaction, * events for this device may still be in transit. The server will send an * @ref EI_EVENT_DEVICE_REMOVED event for this device. After that event, * device is considered removed by the server. * * A client can assume that an @ref EI_EVENT_DEVICE_REMOVED event is sent * for any device for which ei_device_close() was called before the @ref * EI_EVENT_DISCONNECT event. Where a client gets * disconnected libei will emulate that event. * * This does not release any resources associated with this device, use * ei_device_unref() for any references held by the client. */ void ei_device_close(struct ei_device *device); /** * @return the name of the device (if any) or NULL */ const char * ei_device_get_name(struct ei_device *device); /** * The device type of the device is determined by the type of the ei * context. If the client context was created with ei_new_sender(), the device * type defaults to @ref EI_DEVICE_TYPE_VIRTUAL. If the client context was * created with ei_new_receiver(), the device type defaults to @ref * EI_DEVICE_TYPE_PHYSICAL. */ enum ei_device_type ei_device_get_type(struct ei_device *device); /** * Return true if the device has the requested capability. Device * capabilities are constant. */ bool ei_device_has_capability(struct ei_device *device, enum ei_device_capability cap); /** * Obtain a region from a device of type @ref EI_DEVICE_TYPE_VIRTUAL. The * number of regions is constant for a device and the indices of any region * remains the same for the lifetime of the device. * * Regions are shared between all capabilities. Where two capabilities need * different regions, the EIS implementation must create multiple devices with * individual capabilities and regions. For example, two touchscreens that are * mapped to two screens would typically show up as two separate devices with * one region each. * * This function returns the given region or NULL if the index is larger than * the number of regions available. * * This does not increase the refcount of the region. Use ei_region_ref() to * keep a reference beyond the immediate scope. * * Devices of type @ref EI_DEVICE_TYPE_PHYSICAL do not have regions. */ struct ei_region * ei_device_get_region(struct ei_device *device, size_t index); struct ei_region * ei_region_ref(struct ei_region *region); struct ei_region * ei_region_unref(struct ei_region *region); void ei_region_set_user_data(struct ei_region *region, void *user_data); void * ei_region_get_user_data(struct ei_region *region); uint32_t ei_region_get_x(struct ei_region *region); uint32_t ei_region_get_y(struct ei_region *region); uint32_t ei_region_get_width(struct ei_region *region); uint32_t ei_region_get_height(struct ei_region *region); /** * Return true if the point x/y (in desktop-wide coordinates) is within @a * region. */ bool ei_region_contains(struct ei_region *region, double x, double y); /** * Convert the point x/y in a desktop-wide coordinate system into the * corresponding point relative to the offset of the given region. * If the point is inside the region, this function returns true and @a x and @a * y are set to the points with the region offset subtracted. * If the point is outside the region, this function returns false and @a x * and @a y are left unmodified. */ bool ei_region_convert_point(struct ei_region *region, double *x, double *y); /** * Return the physical scale for this region. The default scale is 1.0. * * The regions' coordinate space is in logical pixels in the EIS range. The * logical pixels may or may not match the physical pixels on the output * range but the mapping from logical pixels to physical pixels is performed * by the EIS implementation. * * In some use-cases though, relative data from a remote input source needs * to be converted by the libei client into an absolute movement on an EIS * region. In that case, the physical scale provides the factor to multiply * the relative logical input to provide the expected physical relative * movement. * * For example consider the following dual-monitor setup comprising a 2k and * a 4k monitor **of the same physical size**: * The physical layout of the monitors appears like this: * @code * 2k 4k * +-------------++-------------+ * | || | * | a b || c d | * | || | * +-------------++-------------+ * @endcode * * The physical distance `ab` is the same as the physical distance `cd`. * Where the EIS implementation supports high-dpi screens, the logical * distance (in pixels) are identical too. * * Where the EIS implementation does not support high-dpi screens, the * logical layout of these two monitors appears like this: * * @code * 2k 4k * +-------------++--------------------------+ * | || | * | a b || | * | || | * +-------------+| c d | * | | * | | * | | * +--------------------------+ * @endcode * * While the two physical distances `ab` and `cd` are still identical, the * logical distance `cd` (in pixels) is twice that of `ab`. * Where a libei client receives relative deltas from an input source and * converts that relative input into an absolute position on the screen, it * needs to take this into account. * * For example, if a remote input source moves by relative 100 logical * pixels, the libei client would convert this as `a + 100 = b` on the * region for the 2k screen and send the absolute events to logically change * the position from `a` to `b`. If the same remote input source moves by * relative 100 logical pixels, the libei client would convert this as * `c + 100 * scale = d` on the region for the 4k screen to logically * change the position from `c` to `d`. While the pixel movement differs, * the physical movement as seen by the user is thus identical. * * A second possible use-case for the physical scale is to match pixels from * one region to their respective counterpart on a different region. * For example, if the bottom-right corner of the 2k screen in the * illustration above has a coordinate of ``(x, y)``, the neighbouring pixel on * the **physical** 4k screen is ``(0, y * scale)``. */ double ei_region_get_physical_scale(struct ei_region *region); /** * Return the keymap for this device or `NULL`. The keymap is constant for * the lifetime of the device and applies to this device individually. * * If this function returns `NULL`, this device does not have * an individual keymap assigned. What keymap applies to the device in this * case is a server implementation detail. * * This does not increase the refcount of the keymap. Use ei_keymap_ref() to * keep a reference beyond the immediate scope. * */ /* FIXME: the current API makes it impossible to know when the keymap has * been consumed so the file stays open forever. */ struct ei_keymap * ei_device_keyboard_get_keymap(struct ei_device *device); /** * Return the struct @ref ei_device this keymap is associated with. */ struct ei_device * ei_keymap_get_context(struct ei_keymap *keymap); /** * Return the struct @ref ei context this device is associated with. */ struct ei * ei_device_get_context(struct ei_device *device); /** * Notify the EIS implementation that the given device is about to start * sending events. This should be seen more as a transactional boundary than a * time-based boundary. The primary use-cases for this are to allow for setup on * the EIS implementation side and/or UI updates to indicate that a device is * sending events now and for out-of-band information to sync with a given event * sequence. * * There is no actual requirement that events start immediately once emulation * starts and there is no requirement that a client calls * ei_device_stop_emulating() after the most recent events. * * For example, in a synergy-like use-case the client would call * ei_device_start_emulating() once the pointer moves into the the screen and * ei_device_stop_emulating() once the pointer moves out of the screen. * * Sending events before ei_device_start_emulating() or after * ei_device_stop_emulating() is a client bug. * * The sequence number identifies this transaction between start/stop emulating. * It must go up by at least 1 on each call to * ei_device_start_emulating(). Wraparound must be handled by the EIS * implementation but Callers must ensure that detection of wraparound is * reasonably. */ void ei_device_start_emulating(struct ei_device *device, uint32_t sequence); /** * Notify the EIS implementation that the given device is no longer sending * events. See ei_device_start_emulating() for details. */ void ei_device_stop_emulating(struct ei_device *device); /** * Generate a frame event to group the current set of events * into a logical hardware event. This function **must** be called after any * other event has been generated. * * The given timestamp applies to all events in the current frame. * The timestamp must be in microseconds of CLOCK_MONOTONIC, use the return * value of ei_now() to get a compatible timestamp. * * @note libei does not prevent a caller from passing in a future time but it * is strongly recommended that this is avoided by the caller. */ void ei_device_frame(struct ei_device *device, uint64_t time); /** * Generate a relative motion event on a device with * the @ref EI_DEVICE_CAP_POINTER capability. * * @param device The EI device * @param x The x movement in logical pixels * @param y The y movement in logical pixels */ void ei_device_pointer_motion(struct ei_device *device, double x, double y); /** * Generate an absolute motion event on a device with * the @ref EI_DEVICE_CAP_POINTER_ABSOLUTE capability. * * The x/y coordinate must be within the device's regions or the event is * silently discarded. * * @param device The EI device * @param x The x position in logical pixels * @param y The y position in logical pixels */ void ei_device_pointer_motion_absolute(struct ei_device *device, double x, double y); /** * Generate a button event on a device with * the @ref EI_DEVICE_CAP_POINTER_ABSOLUTE or * @ref EI_DEVICE_CAP_POINTER capability. * * Button codes must match the defines in ``linux/input-event-codes.h`` * * @param device The EI device * @param button The button code * @param is_press true for button press, false for button release */ void ei_device_pointer_button(struct ei_device *device, uint32_t button, bool is_press); /** * Generate a smooth (pixel-precise) scroll event on a device with * the @ref EI_DEVICE_CAP_POINTER_ABSOLUTE or * @ref EI_DEVICE_CAP_POINTER capability. * * @note The server is responsible for emulating discrete scrolling based * on the pixel value, do not call ei_device_pointer_scroll_discrete() for * the same input event. * * @param device The EI device * @param x The x scroll distance in logical pixels * @param y The y scroll distance in logical pixels * * @see ei_device_pointer_scroll_discrete */ void ei_device_pointer_scroll(struct ei_device *device, double x, double y); /** * Generate a discrete scroll event on a device with * the @ref EI_DEVICE_CAP_POINTER_ABSOLUTE or * @ref EI_DEVICE_CAP_POINTER capability. * * A discrete scroll event is based logical scroll units (equivalent to one * mouse wheel click). The value for one scroll unit is 120, a fraction or * multiple thereof represents a fraction or multiple of a wheel click. * * @note The server is responsible for emulating pixel-based scrolling based * on the discrete value, do not call ei_device_pointer_scroll() for the * same input event. * * @param device The EI device * @param x The x scroll distance in fractions or multiples of 120 * @param y The y scroll distance in fractions or multiples of 120 * * @see ei_device_pointer_scroll */ void ei_device_pointer_scroll_discrete(struct ei_device *device, int32_t x, int32_t y); /** * Generate a scroll stop event on a device with the @ref * EI_DEVICE_CAP_POINTER_ABSOLUTE or @ref EI_DEVICE_CAP_POINTER capability. * * A scroll stop event notifies the server that the interaction causing a * scroll motion previously triggered with ei_device_pointer_scroll() or * ei_device_pointer_scroll_discrete() has stopped. For example, if all * fingers are lifted off a touchpad, two-finger scrolling has logically * stopped. * * The server may use this information to e.g. start kinetic scrolling * previously based on the previous finger speed. * * Use ei_device_pointer_scroll_cancel() to signal that the scroll motion has * completely stopped. * * Calling ei_device_pointer_scroll_stop() after * ei_device_pointer_scroll_cancel() without any of ei_device_pointer_scroll() * or ei_device_pointer_scroll_discrete() in between indicates a client logic bug. * * libei keeps track of the scroll axis and filters duplicate calls to * ei_device_pointer_scroll_stop() for the same axis. A nonzero scroll or * scroll-discrete value is required for the given axis to re-start scrolling * for that axis. */ void ei_device_pointer_scroll_stop(struct ei_device *device, bool stop_x, bool stop_y); /** * Generate a scroll cancel event on a device with the @ref * EI_DEVICE_CAP_POINTER_ABSOLUTE or @ref EI_DEVICE_CAP_POINTER capability. * * A scroll cancel event notifies the server that a scroll motion previously * triggered with ei_device_pointer_scroll() or * ei_device_pointer_scroll_discrete() has ceased and no further events should * be sent. * * This event indicates that the interaction has stopped to the point where * further (server-emulated) scroll events from this device are wrong. * * Use ei_device_pointer_scroll_stop() to signal that the interaction has * stopped but a server may emulate further scroll events. * * Calling ei_device_pointer_scroll_cancel() after * ei_device_pointer_scroll_stop() without any of ei_device_pointer_scroll() * or ei_device_pointer_scroll_discrete() in between iis permitted. * * libei keeps track of the scroll axis and filters duplicate calls to * ei_device_pointer_scroll_cancel() for the same axis. A nonzero scroll or * scroll-discrete value is required for the given axis to re-start scrolling * for that axis. */ void ei_device_pointer_scroll_cancel(struct ei_device *device, bool cancel_x, bool cancel_y); /** * Generate a key event on a device with * the @ref EI_DEVICE_CAP_KEYBOARD capability. * * Keys use the evdev scan codes as defined in * ``linux/input-event-codes.h``. * * Note that this is a keymap-independent key code, equivalent to the scancode * a physical keyboard would produce. To generate a specific key symbol, a * client must look at the keymap returned by ei_device_get_keymap() and * generate the appropriate keycodes. * * @param device The EI device * @param keycode The key code * @param is_press true for key down, false for key up */ void ei_device_keyboard_key(struct ei_device *device, uint32_t keycode, bool is_press); /** * Initiate a new touch on a device with the @ref EI_DEVICE_CAP_TOUCH * capability. This touch does not immediately send events, use * ei_touch_down(), ei_touch_motion(), and ei_touch_up(). * * The returned touch has a refcount of at least 1, use ei_touch_unref() to * release resources associated with this touch */ struct ei_touch * ei_device_touch_new(struct ei_device *device); /** * This function can only be called once on an ei_touch object. Further * calls to ei_touch_down() on the same object are silently ignored. * * The x/y coordinate must be within the device's regions or the event is * silently discarded. * * @param touch A newly created touch * @param x The x position in logical pixels * @param y The y position in logical pixels */ void ei_touch_down(struct ei_touch *touch, double x, double y); /** * Move this touch to the new coordinates. */ void ei_touch_motion(struct ei_touch *touch, double x, double y); /** * Release this touch. After this call, the touch event becomes inert and * no longer responds to either ei_touch_down(), ei_touch_motion() or * ei_touch_up() and the caller should call ei_touch_unref(). */ void ei_touch_up(struct ei_touch *touch); /** * Increase the refcount of this struct by one. Use ei_touch_unref() to * decrease the refcount. * * @return the argument passed into the function */ struct ei_touch * ei_touch_ref(struct ei_touch *touch); /** * Decrease the refcount of this struct by one. When the refcount reaches * zero, the context disconnects from the server and all allocated resources * are released. * * @return always NULL */ struct ei_touch * ei_touch_unref(struct ei_touch *touch); /** * Return the custom data pointer for this context. libei will not look at or * modify the pointer. Use ei_touch_set_user_data() to change the user data. */ void ei_touch_set_user_data(struct ei_touch *touch, void *user_data); /** * Set a custom data pointer for this context. libei will not look at or * modify the pointer. Use ei_touch_get_user_data() to retrieve a previously * set user data. */ void * ei_touch_get_user_data(struct ei_touch *touch); /** * @return the device this touch originates on */ struct ei_device * ei_touch_get_device(struct ei_touch *touch); /** * Return the seat from this event. * * For events of type @ref EI_EVENT_CONNECT and @ref EI_EVENT_DISCONNECT, * this function returns NULL. * * This does not increase the refcount of the seat. Use eis_seat_ref() * to keep a reference beyond the immediate scope. */ struct ei_seat * ei_event_get_seat(struct ei_event *event); /** * For an event of type @ref EI_EVENT_DEVICE_START_EMULATING, return the * sequence number set by the EIS implementation. * * See eis_device_start_emulating() for details. */ uint32_t ei_event_emulating_get_sequence(struct ei_event *event); /** * For an event of type @ref EI_EVENT_POINTER_MOTION return the relative x * movement in logical pixels or mm, depending on the device type. */ double ei_event_pointer_get_dx(struct ei_event *event); /** * For an event of type @ref EI_EVENT_POINTER_MOTION return the relative y * movement in logical pixels or mm, depending on the device type. */ double ei_event_pointer_get_dy(struct ei_event *event); /** * For an event of type @ref EI_EVENT_POINTER_MOTION_ABSOLUTE return the x * position in logical pixels or mm, depending on the device type. */ double ei_event_pointer_get_absolute_x(struct ei_event *event); /** * For an event of type @ref EI_EVENT_POINTER_MOTION_ABSOLUTE return the y * position in logical pixels or mm, depending on the device type. */ double ei_event_pointer_get_absolute_y(struct ei_event *event); /** * For an event of type @ref EI_EVENT_POINTER_BUTTON return the button * code as defined in linux/input-event-codes.h */ uint32_t ei_event_pointer_get_button(struct ei_event *event); /** * For an event of type @ref EI_EVENT_POINTER_BUTTON return true if the * event is a button press, false for a release. */ bool ei_event_pointer_get_button_is_press(struct ei_event *event); /** * For an event of type @ref EI_EVENT_POINTER_SCROLL return the x scroll * distance in logical pixels or mm, depending on the device type. */ double ei_event_pointer_get_scroll_x(struct ei_event *event); /** * For an event of type @ref EI_EVENT_POINTER_SCROLL return the y scroll * distance in logical pixels or mm, depending on the device type. */ double ei_event_pointer_get_scroll_y(struct ei_event *event); /** * For an event of type @ref EI_EVENT_POINTER_SCROLL_CANCEL return whether the * x axis has cancelled scrolling. */ bool ei_event_pointer_get_scroll_stop_x(struct ei_event *event); /** * For an event of type @ref EI_EVENT_POINTER_SCROLL_STOP return whether the * y axis has stopped scrolling. */ bool ei_event_pointer_get_scroll_stop_y(struct ei_event *event); /** * For an event of type @ref EI_EVENT_POINTER_SCROLL_DISCRETE return the x * scroll distance in fractions or multiples of 120. */ int32_t ei_event_pointer_get_scroll_discrete_x(struct ei_event *event); /** * For an event of type @ref EI_EVENT_POINTER_SCROLL_DISCRETE return the y * scroll distance in fractions or multiples of 120. */ int32_t ei_event_pointer_get_scroll_discrete_y(struct ei_event *event); /** * For an event of type @ref EI_EVENT_KEYBOARD_KEY return the key code (as * defined in include/linux/input-event-codes.h). */ uint32_t ei_event_keyboard_get_key(struct ei_event *event); /** * For an event of type @ref EI_EVENT_KEYBOARD_KEY return true if the * event is a key down, false for a release. */ bool ei_event_keyboard_get_key_is_press(struct ei_event *event); /** * For an event of type @ref EI_EVENT_TOUCH_DOWN, @ref * EI_EVENT_TOUCH_MOTION, or @ref EI_EVENT_TOUCH_UP, return the tracking * ID of the touch. * * The tracking ID is a unique identifier for a touch and is valid from * touch down through to touch up but may be re-used in the future. * The tracking ID is randomly assigned to a touch, a client * must not expect any specific value. */ uint32_t ei_event_touch_get_id(struct ei_event *event); /** * For an event of type @ref EI_EVENT_TOUCH_DOWN, or @ref * EI_EVENT_TOUCH_MOTION, return the x coordinate of the touch * in logical pixels or mm, depending on the device type. */ double ei_event_touch_get_x(struct ei_event *event); /** * For an event of type @ref EI_EVENT_TOUCH_DOWN, or @ref * EI_EVENT_TOUCH_MOTION, return the y coordinate of the touch * in logical pixels or mm, depending on the device type. */ double ei_event_touch_get_y(struct ei_event *event); /** * @returns a timestamp in microseconds for the current time to pass into * ei_device_frame(). * * In the current implementation, the returned timestamp is CLOCK_MONOTONIC * for compatibility with evdev and libinput. */ uint64_t ei_now(struct ei *ei); /** * @} */ #ifdef __cplusplus } #endif